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