1 /*
2 * Copyright (c) 1982, 1986 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)dh.c 7.17 (Berkeley) 05/16/91
7 */
8
9 #include "dh.h"
10 #if NDH > 0
11 /*
12 * DH-11/DM-11 driver
13 */
14 #include "../include/pte.h"
15
16 #include "sys/param.h"
17 #include "uba.h"
18 #include "sys/conf.h"
19 #include "sys/user.h"
20 #include "sys/proc.h"
21 #include "sys/ioctl.h"
22 #include "sys/tty.h"
23 #include "sys/map.h"
24 #include "sys/buf.h"
25 #include "sys/vm.h"
26 #include "sys/kernel.h"
27 #include "sys/syslog.h"
28
29 #include "ubareg.h"
30 #include "ubavar.h"
31 #include "dhreg.h"
32 #include "dmreg.h"
33
34 #include "sys/clist.h"
35 #include "sys/file.h"
36 #include "sys/uio.h"
37
38 /*
39 * Definition of the driver for the auto-configuration program.
40 * There is one definition for the dh and one for the dm.
41 */
42 int dhprobe(), dhattach(), dhrint(), dhxint(), dhtimer();
43 struct uba_device *dhinfo[NDH];
44 u_short dhstd[] = { 0 };
45 struct uba_driver dhdriver =
46 { dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo };
47
48 int dmprobe(), dmattach(), dmintr();
49 struct uba_device *dminfo[NDH];
50 u_short dmstd[] = { 0 };
51 struct uba_driver dmdriver =
52 { dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo };
53
54 #ifndef PORTSELECTOR
55 #define ISPEED TTYDEF_SPEED
56 #define LFLAG TTYDEF_LFLAG
57 #else
58 #define ISPEED B4800
59 #define LFLAG (TTYDEF_LFLAG&~ECHO)
60 #endif
61
62 #define FASTTIMER (hz/30) /* scan rate with silos on */
63
64 /*
65 * Local variables for the driver
66 */
67 short dhsar[NDH]; /* software copy of last bar */
68 short dhsoftCAR[NDH];
69
70 struct tty dh11[NDH*16];
71 int ndh11 = NDH*16;
72 int dhact; /* mask of active dh's */
73 int dhsilos; /* mask of dh's with silo in use */
74 int dhchars[NDH]; /* recent input count */
75 int dhrate[NDH]; /* smoothed input count */
76 int dhhighrate = 100; /* silo on if dhchars > dhhighrate */
77 int dhlowrate = 75; /* silo off if dhrate < dhlowrate */
78 static short timerstarted;
79 int dhstart(), ttrstrt();
80
81 struct speedtab dhspeedtab[] = {
82 19200, 14,
83 9600, 13,
84 4800, 12,
85 2400, 11,
86 1800, 10,
87 1200, 9,
88 600, 8,
89 300, 7,
90 200, 6,
91 150, 5,
92 134, 4,
93 110, 3,
94 75, 2,
95 50, 1,
96 0, 0,
97 EXTA, 14,
98 EXTB, 15,
99 -1, -1
100 };
101
102 /*
103 * The clist space is mapped by one terminal driver onto each UNIBUS.
104 * The identity of the board which allocated resources is recorded,
105 * so the process may be repeated after UNIBUS resets.
106 * The UBACVT macro converts a clist space address for unibus uban
107 * into an i/o space address for the DMA routine.
108 */
109 int dh_uballoc[NUBA]; /* which dh (if any) allocated unibus map */
110 int cbase[NUBA]; /* base address of clists in unibus map */
111 #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
112
113 /*
114 * Routine for configuration to force a dh to interrupt.
115 * Set to transmit at 9600 baud, and cause a transmitter interrupt.
116 */
117 /*ARGSUSED*/
dhprobe(reg)118 dhprobe(reg)
119 caddr_t reg;
120 {
121 register int br, cvec; /* these are ``value-result'' */
122 register struct dhdevice *dhaddr = (struct dhdevice *)reg;
123
124 #ifdef lint
125 br = 0; cvec = br; br = cvec;
126 if (ndh11 == 0) ndh11 = 1;
127 dhrint(0); dhxint(0);
128 #endif
129 #ifndef notdef
130 dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI;
131 DELAY(1000);
132 dhaddr->un.dhcsr &= ~DH_RI;
133 dhaddr->un.dhcsr = 0;
134 #else
135 dhaddr->un.dhcsr = DH_TIE;
136 DELAY(5);
137 dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE;
138 dhaddr->dhbcr = -1;
139 dhaddr->dhcar = 0;
140 dhaddr->dhbar = 1;
141 DELAY(100000); /* wait 1/10'th of a sec for interrupt */
142 dhaddr->un.dhcsr = 0;
143 if (cvec && cvec != 0x200)
144 cvec -= 4; /* transmit -> receive */
145 #endif
146 return (sizeof (struct dhdevice));
147 }
148
149 /*
150 * Routine called to attach a dh.
151 */
152 dhattach(ui)
153 struct uba_device *ui;
154 {
155
156 dhsoftCAR[ui->ui_unit] = ui->ui_flags;
157 cbase[ui->ui_ubanum] = -1;
158 dh_uballoc[ui->ui_ubanum] = -1;
159 }
160
161 /*
162 * Configuration routine to cause a dm to interrupt.
163 */
dmprobe(reg)164 dmprobe(reg)
165 caddr_t reg;
166 {
167 register int br, vec; /* value-result */
168 register struct dmdevice *dmaddr = (struct dmdevice *)reg;
169
170 #ifdef lint
171 br = 0; vec = br; br = vec;
172 dmintr(0);
173 #endif
174 dmaddr->dmcsr = DM_DONE|DM_IE;
175 DELAY(20);
176 dmaddr->dmcsr = 0;
177 return (1);
178 }
179
180 /*ARGSUSED*/
181 dmattach(ui)
182 struct uba_device *ui;
183 {
184
185 /* no local state to set up */
186 }
187
188 /*
189 * Open a DH11 line, mapping the clist onto the uba if this
190 * is the first dh on this uba. Turn on this dh if this is
191 * the first use of it. Also do a dmopen to wait for carrier.
192 */
193 /*ARGSUSED*/
dhopen(dev,flag)194 dhopen(dev, flag)
195 dev_t dev;
196 {
197 register struct tty *tp;
198 register int unit, dh;
199 register struct dhdevice *addr;
200 register struct uba_device *ui;
201 int s, error;
202 int dhparam();
203
204 unit = minor(dev);
205 dh = unit >> 4;
206 if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0)
207 return (ENXIO);
208 tp = &dh11[unit];
209 if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
210 return (EBUSY);
211 addr = (struct dhdevice *)ui->ui_addr;
212 tp->t_addr = (caddr_t)addr;
213 tp->t_oproc = dhstart;
214 tp->t_param = dhparam;
215 tp->t_dev = dev;
216 /*
217 * While setting up state for this uba and this dh,
218 * block uba resets which can clear the state.
219 */
220 s = spl5();
221 if (cbase[ui->ui_ubanum] == -1) {
222 dh_uballoc[ui->ui_ubanum] = dh;
223 cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
224 (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
225 }
226 if (timerstarted == 0) {
227 timerstarted++;
228 timeout(dhtimer, (caddr_t) 0, hz);
229 }
230 if ((dhact&(1<<dh)) == 0) {
231 addr->un.dhcsr |= DH_IE;
232 dhact |= (1<<dh);
233 addr->dhsilo = 0;
234 }
235 splx(s);
236 /*
237 * If this is first open, initialize tty state to default.
238 */
239 if ((tp->t_state&TS_ISOPEN) == 0) {
240 tp->t_state |= TS_WOPEN;
241 ttychars(tp);
242 #ifndef PORTSELECTOR
243 if (tp->t_ispeed == 0) {
244 #endif
245 tp->t_iflag = TTYDEF_IFLAG;
246 tp->t_oflag = TTYDEF_OFLAG;
247 tp->t_cflag = TTYDEF_CFLAG;
248 tp->t_lflag = LFLAG;
249 tp->t_ispeed = tp->t_ospeed = ISPEED;
250 #ifdef PORTSELECTOR
251 tp->t_cflag |= HUPCL;
252 #else
253 }
254 #endif
255 dhparam(tp, &tp->t_termios);
256 ttsetwater(tp);
257 }
258 /*
259 * Wait for carrier, then process line discipline specific open.
260 */
261 if (error = dmopen(dev, flag))
262 return (error);
263 return ((*linesw[tp->t_line].l_open)(dev, tp));
264 }
265
266 /*
267 * Close a DH11 line, turning off the DM11.
268 */
269 /*ARGSUSED*/
dhclose(dev,flag,mode,p)270 dhclose(dev, flag, mode, p)
271 dev_t dev;
272 int flag, mode;
273 struct proc *p;
274 {
275 register struct tty *tp;
276 register unit;
277
278 unit = minor(dev);
279 tp = &dh11[unit];
280 (*linesw[tp->t_line].l_close)(tp, flag);
281 ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
282 if (tp->t_cflag&HUPCL || (tp->t_state&TS_ISOPEN)==0)
283 dmctl(unit, DML_OFF, DMSET);
284 return (ttyclose(tp));
285 }
286
dhread(dev,uio,flag)287 dhread(dev, uio, flag)
288 dev_t dev;
289 struct uio *uio;
290 {
291 register struct tty *tp = &dh11[minor(dev)];
292
293 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
294 }
295
dhwrite(dev,uio,flag)296 dhwrite(dev, uio, flag)
297 dev_t dev;
298 struct uio *uio;
299 {
300 register struct tty *tp = &dh11[minor(dev)];
301
302 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
303 }
304
305 /*
306 * DH11 receiver interrupt.
307 */
dhrint(dh)308 dhrint(dh)
309 int dh;
310 {
311 register struct tty *tp;
312 register c, cc;
313 register struct dhdevice *addr;
314 register struct tty *tp0;
315 register struct uba_device *ui;
316 int overrun = 0;
317
318 ui = dhinfo[dh];
319 if (ui == 0 || ui->ui_alive == 0)
320 return;
321 addr = (struct dhdevice *)ui->ui_addr;
322 tp0 = &dh11[dh<<4];
323 /*
324 * Loop fetching characters from the silo for this
325 * dh until there are no more in the silo.
326 */
327 while ((c = addr->dhrcr) < 0) {
328 tp = tp0 + ((c>>8)&0xf);
329 dhchars[dh]++;
330 if ((tp->t_state&TS_ISOPEN)==0) {
331 wakeup((caddr_t)&tp->t_rawq);
332 #ifdef PORTSELECTOR
333 if ((tp->t_state&TS_WOPEN) == 0)
334 #endif
335 continue;
336 }
337 cc = c&0xff;
338 if (c&DH_PE)
339 cc |= TTY_PE;
340 if ((c&DH_DO) && overrun == 0) {
341 log(LOG_WARNING, "dh%d: silo overflow\n", dh);
342 overrun = 1;
343 }
344 if (c&DH_FE)
345 cc |= TTY_FE;
346 (*linesw[tp->t_line].l_rint)(cc, tp);
347 }
348 }
349
350 /*
351 * Ioctl for DH11.
352 */
353 /*ARGSUSED*/
dhioctl(dev,cmd,data,flag)354 dhioctl(dev, cmd, data, flag)
355 caddr_t data;
356 {
357 register struct tty *tp;
358 register int unit = minor(dev);
359 int error;
360
361 tp = &dh11[unit];
362 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
363 if (error >= 0)
364 return (error);
365 error = ttioctl(tp, cmd, data, flag);
366 if (error >= 0)
367 return (error);
368 switch (cmd) {
369
370 case TIOCSBRK:
371 ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017);
372 break;
373
374 case TIOCCBRK:
375 ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
376 break;
377
378 case TIOCSDTR:
379 dmctl(unit, DML_DTR|DML_RTS, DMBIS);
380 break;
381
382 case TIOCCDTR:
383 dmctl(unit, DML_DTR|DML_RTS, DMBIC);
384 break;
385
386 default:
387 return (ENOTTY);
388 }
389 return (0);
390 }
391
392 /*
393 * Set parameters from open or stty into the DH hardware
394 * registers.
395 */
dhparam(tp,t)396 dhparam(tp, t)
397 register struct tty *tp;
398 register struct termios *t;
399 {
400 register struct dhdevice *addr;
401 register int lpar;
402 register int cflag = t->c_cflag;
403 int unit = minor(tp->t_dev);
404 int s;
405 int ispeed = ttspeedtab(t->c_ispeed, dhspeedtab);
406 int ospeed = ttspeedtab(t->c_ospeed, dhspeedtab);
407
408 /* check requested parameters */
409 if (ospeed < 0 || ispeed < 0 || (cflag&CSIZE) == CS5)
410 return(EINVAL);
411 if (ispeed == 0)
412 ispeed = ospeed;
413 /* and copy to tty */
414 tp->t_ispeed = t->c_ispeed;
415 tp->t_ospeed = t->c_ospeed;
416 tp->t_cflag = cflag;
417 /*
418 * Block interrupts so parameters will be set
419 * before the line interrupts.
420 */
421 addr = (struct dhdevice *)tp->t_addr;
422 s = spl5();
423 addr->un.dhcsrl = (unit&0xf) | DH_IE;
424 if (ospeed == 0) {
425 tp->t_cflag |= HUPCL;
426 dmctl(unit, DML_OFF, DMSET);
427 splx(s);
428 return 0;
429 }
430 lpar = (ospeed<<10) | (ispeed<<6);
431 switch (cflag&CSIZE) {
432 case CS6: lpar |= BITS6; break;
433 case CS7: lpar |= BITS7; break;
434 case CS8: lpar |= BITS8; break;
435 }
436 if (cflag&PARENB)
437 lpar |= PENABLE;
438 if (cflag&PARODD)
439 lpar |= OPAR;
440 if (cflag&CSTOPB)
441 lpar |= TWOSB;
442 addr->dhlpr = lpar;
443 splx(s);
444 return 0;
445 }
446
447 /*
448 * DH11 transmitter interrupt.
449 * Restart each line which used to be active but has
450 * terminated transmission since the last interrupt.
451 */
dhxint(dh)452 dhxint(dh)
453 int dh;
454 {
455 register struct tty *tp;
456 register struct dhdevice *addr;
457 short ttybit, bar, *sbar;
458 register struct uba_device *ui;
459 register int unit;
460 u_short cntr;
461
462 ui = dhinfo[dh];
463 addr = (struct dhdevice *)ui->ui_addr;
464 if (addr->un.dhcsr & DH_NXM) {
465 addr->un.dhcsr |= DH_CNI;
466 printf("dh%d: NXM\n", dh);
467 }
468 sbar = &dhsar[dh];
469 bar = *sbar & ~addr->dhbar;
470 unit = dh * 16; ttybit = 1;
471 addr->un.dhcsr &= (short)~DH_TI;
472 for (; bar; unit++, ttybit <<= 1) {
473 if (bar & ttybit) {
474 *sbar &= ~ttybit;
475 bar &= ~ttybit;
476 tp = &dh11[unit];
477 tp->t_state &= ~TS_BUSY;
478 if (tp->t_state&TS_FLUSH)
479 tp->t_state &= ~TS_FLUSH;
480 else {
481 addr->un.dhcsrl = (unit&017)|DH_IE;
482 /*
483 * Do arithmetic in a short to make up
484 * for lost 16&17 bits.
485 */
486 cntr = addr->dhcar -
487 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
488 ndflush(&tp->t_outq, (int)cntr);
489 }
490 if (tp->t_line)
491 (*linesw[tp->t_line].l_start)(tp);
492 else
493 dhstart(tp);
494 }
495 }
496 }
497
498 /*
499 * Start (restart) transmission on the given DH11 line.
500 */
dhstart(tp)501 dhstart(tp)
502 register struct tty *tp;
503 {
504 register struct dhdevice *addr;
505 register int car, dh, unit, nch;
506 int s;
507
508 unit = minor(tp->t_dev);
509 dh = unit >> 4;
510 unit &= 0xf;
511 addr = (struct dhdevice *)tp->t_addr;
512
513 /*
514 * Must hold interrupts in following code to prevent
515 * state of the tp from changing.
516 */
517 s = spl5();
518 /*
519 * If it's currently active, or delaying, no need to do anything.
520 */
521 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
522 goto out;
523 /*
524 * If there are sleepers, and output has drained below low
525 * water mark, wake up the sleepers.
526 */
527 if (tp->t_outq.c_cc<=tp->t_lowat) {
528 if (tp->t_state&TS_ASLEEP) {
529 tp->t_state &= ~TS_ASLEEP;
530 wakeup((caddr_t)&tp->t_outq);
531 }
532 if (tp->t_wsel) {
533 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
534 tp->t_wsel = 0;
535 tp->t_state &= ~TS_WCOLL;
536 }
537 }
538 /*
539 * Now restart transmission unless the output queue is
540 * empty.
541 */
542 if (tp->t_outq.c_cc == 0)
543 goto out;
544 if (1 || !(tp->t_oflag&OPOST)) /*XXX*/
545 nch = ndqb(&tp->t_outq, 0);
546 else {
547 nch = ndqb(&tp->t_outq, 0200);
548 /*
549 * If first thing on queue is a delay process it.
550 */
551 if (nch == 0) {
552 nch = getc(&tp->t_outq);
553 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
554 tp->t_state |= TS_TIMEOUT;
555 goto out;
556 }
557 }
558 /*
559 * If characters to transmit, restart transmission.
560 */
561 if (nch) {
562 car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum);
563 addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE;
564 /*
565 * The following nonsense with short word
566 * is to make sure the dhbar |= word below
567 * is done with an interlocking bisw2 instruction.
568 */
569 { short word = 1 << unit;
570 dhsar[dh] |= word;
571 addr->dhcar = car;
572 addr->dhbcr = -nch;
573 addr->dhbar |= word;
574 }
575 tp->t_state |= TS_BUSY;
576 }
577 out:
578 splx(s);
579 }
580
581 /*
582 * Stop output on a line, e.g. for ^S/^Q or output flush.
583 */
584 /*ARGSUSED*/
dhstop(tp,flag)585 dhstop(tp, flag)
586 register struct tty *tp;
587 {
588 register struct dhdevice *addr;
589 register int unit, s;
590
591 addr = (struct dhdevice *)tp->t_addr;
592 /*
593 * Block input/output interrupts while messing with state.
594 */
595 s = spl5();
596 if (tp->t_state & TS_BUSY) {
597 /*
598 * Device is transmitting; stop output
599 * by selecting the line and setting the byte
600 * count to -1. We will clean up later
601 * by examining the address where the dh stopped.
602 */
603 unit = minor(tp->t_dev);
604 addr->un.dhcsrl = (unit&017) | DH_IE;
605 if ((tp->t_state&TS_TTSTOP)==0)
606 tp->t_state |= TS_FLUSH;
607 addr->dhbcr = -1;
608 }
609 splx(s);
610 }
611
612 /*
613 * Reset state of driver if UBA reset was necessary.
614 * Reset the csrl and lpr registers on open lines, and
615 * restart transmitters.
616 */
dhreset(uban)617 dhreset(uban)
618 int uban;
619 {
620 register int dh, unit;
621 register struct tty *tp;
622 register struct uba_device *ui;
623 int i;
624
625 dh = 0;
626 for (dh = 0; dh < NDH; dh++) {
627 ui = dhinfo[dh];
628 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
629 continue;
630 printf(" dh%d", dh);
631 if (dh_uballoc[uban] == dh) {
632 int info;
633
634 info = uballoc(uban, (caddr_t)cfree,
635 nclist * sizeof(struct cblock), UBA_CANTWAIT);
636 if (info)
637 cbase[uban] = UBAI_ADDR(info);
638 else {
639 printf(" [can't get uba map]");
640 cbase[uban] = -1;
641 }
642 }
643 ((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE;
644 ((struct dhdevice *)ui->ui_addr)->dhsilo = 0;
645 unit = dh * 16;
646 for (i = 0; i < 16; i++) {
647 tp = &dh11[unit];
648 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
649 dhparam(unit);
650 dmctl(unit, DML_ON, DMSET);
651 tp->t_state &= ~TS_BUSY;
652 dhstart(tp);
653 }
654 unit++;
655 }
656 }
657 dhsilos = 0;
658 }
659
660 int dhtransitions, dhslowtimers, dhfasttimers; /*DEBUG*/
661 /*
662 * At software clock interrupt time, check status.
663 * Empty all the dh silos that are in use, and decide whether
664 * to turn any silos off or on.
665 */
dhtimer()666 dhtimer()
667 {
668 register int dh, s;
669 static int timercalls;
670
671 if (dhsilos) {
672 dhfasttimers++; /*DEBUG*/
673 timercalls++;
674 s = spl5();
675 for (dh = 0; dh < NDH; dh++)
676 if (dhsilos & (1 << dh))
677 dhrint(dh);
678 splx(s);
679 }
680 if ((dhsilos == 0) || ((timercalls += FASTTIMER) >= hz)) {
681 dhslowtimers++; /*DEBUG*/
682 timercalls = 0;
683 for (dh = 0; dh < NDH; dh++) {
684 ave(dhrate[dh], dhchars[dh], 8);
685 if ((dhchars[dh] > dhhighrate) &&
686 ((dhsilos & (1 << dh)) == 0)) {
687 ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo =
688 (dhchars[dh] > 500? 32 : 16);
689 dhsilos |= (1 << dh);
690 dhtransitions++; /*DEBUG*/
691 } else if ((dhsilos & (1 << dh)) &&
692 (dhrate[dh] < dhlowrate)) {
693 ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo = 0;
694 dhsilos &= ~(1 << dh);
695 }
696 dhchars[dh] = 0;
697 }
698 }
699 timeout(dhtimer, (caddr_t) 0, dhsilos? FASTTIMER: hz);
700 }
701
702 /*
703 * Turn on the line associated with dh dev.
704 */
dmopen(dev,flag)705 dmopen(dev, flag)
706 dev_t dev;
707 {
708 register struct tty *tp;
709 register struct dmdevice *addr;
710 register struct uba_device *ui;
711 register int unit;
712 register int dm;
713 int s, error = 0;
714
715 unit = minor(dev);
716 dm = unit >> 4;
717 tp = &dh11[unit];
718 unit &= 0xf;
719 if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) {
720 tp->t_state |= TS_CARR_ON;
721 return (0);
722 }
723 addr = (struct dmdevice *)ui->ui_addr;
724 s = spl5();
725 for (;;) {
726 tp->t_state |= TS_WOPEN;
727 addr->dmcsr &= ~DM_SE;
728 while (addr->dmcsr & DM_BUSY)
729 ;
730 addr->dmcsr = unit;
731 addr->dmlstat = DML_ON;
732 if ((addr->dmlstat & DML_CAR) || (dhsoftCAR[dm] & (1 << unit)))
733 tp->t_state |= TS_CARR_ON;
734 addr->dmcsr = DM_IE|DM_SE;
735 if (tp->t_state&TS_CARR_ON || flag&O_NONBLOCK ||
736 tp->t_cflag&CLOCAL)
737 break;
738 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
739 ttopen, 0))
740 break;
741 }
742 splx(s);
743 return (error);
744 }
745
746 /*
747 * Dump control bits into the DM registers.
748 */
dmctl(dev,bits,how)749 dmctl(dev, bits, how)
750 dev_t dev;
751 int bits, how;
752 {
753 register struct uba_device *ui;
754 register struct dmdevice *addr;
755 register int unit, s;
756 int dm;
757
758 unit = minor(dev);
759 dm = unit >> 4;
760 if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0)
761 return;
762 addr = (struct dmdevice *)ui->ui_addr;
763 s = spl5();
764 addr->dmcsr &= ~DM_SE;
765 while (addr->dmcsr & DM_BUSY)
766 ;
767 addr->dmcsr = unit & 0xf;
768 switch(how) {
769 case DMSET:
770 addr->dmlstat = bits;
771 break;
772 case DMBIS:
773 addr->dmlstat |= bits;
774 break;
775 case DMBIC:
776 addr->dmlstat &= ~bits;
777 break;
778 }
779 addr->dmcsr = DM_IE|DM_SE;
780 splx(s);
781 }
782
783 /*
784 * DM11 interrupt; deal with carrier transitions.
785 */
dmintr(dm)786 dmintr(dm)
787 register int dm;
788 {
789 register struct uba_device *ui;
790 register struct tty *tp;
791 register struct dmdevice *addr;
792 int unit;
793
794 ui = dminfo[dm];
795 if (ui == 0)
796 return;
797 addr = (struct dmdevice *)ui->ui_addr;
798 if (addr->dmcsr&DM_DONE) {
799 if (addr->dmcsr&DM_CF) {
800 unit = addr->dmcsr & 0xf;
801 tp = &dh11[(dm << 4) + unit];
802 if (addr->dmlstat & DML_CAR)
803 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
804 else if ((dhsoftCAR[dm] & (1<<unit)) == 0 &&
805 (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
806 addr->dmlstat = 0;
807 }
808 addr->dmcsr = DM_IE|DM_SE;
809 }
810 }
811 #endif
812