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