posix has HUPCL
[unix-history] / usr / src / sys / vax / uba / dhu.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1985, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
764619a6 6 * @(#)dhu.c 7.12 (Berkeley) %G%
da7c5cc6 7 */
48952cf5
KM
8
9/*
10 * based on dh.c 6.3 84/03/15
11 * and on dmf.c 6.2 84/02/16
12 *
13 * Dave Johnson, Brown University Computer Science
14 * ddj%brown@csnet-relay
15 */
16
17#include "dhu.h"
18#if NDHU > 0
19/*
20 * DHU-11 driver
21 */
a5e5eff7 22#include "machine/pte.h"
48952cf5 23
48952cf5
KM
24#include "param.h"
25#include "conf.h"
48952cf5
KM
26#include "user.h"
27#include "proc.h"
28#include "ioctl.h"
29#include "tty.h"
f5f63131 30#include "ttydefaults.h"
48952cf5
KM
31#include "map.h"
32#include "buf.h"
33#include "vm.h"
34#include "kernel.h"
35#include "syslog.h"
36
37#include "uba.h"
38#include "ubareg.h"
39#include "ubavar.h"
40#include "dhureg.h"
41
42#include "bkmac.h"
43#include "clist.h"
44#include "file.h"
45#include "uio.h"
46
47/*
48 * Definition of the driver for the auto-configuration program.
49 */
50int dhuprobe(), dhuattach(), dhurint(), dhuxint();
51struct uba_device *dhuinfo[NDHU];
24db64ff 52u_short dhustd[] = { 160440, 160500, 0 }; /* some common addresses */
48952cf5
KM
53struct uba_driver dhudriver =
54 { dhuprobe, 0, dhuattach, 0, dhustd, "dhu", dhuinfo };
55
56#define NDHULINE (NDHU*16)
57
58#define UNIT(x) (minor(x))
59
60#ifndef PORTSELECTOR
f5f63131
MT
61#define SPEED TTYDEF_SPEED
62#define LFLAG TTYDEF_LFLAG
48952cf5 63#else
f5f63131
MT
64#define SPEED B4800
65#define LFLAG (TTYDEF_LFLAG & ~ECHO)
48952cf5
KM
66#endif
67
68/*
69 * default receive silo timeout value -- valid values are 2..255
70 * number of ms. to delay between first char received and receive interrupt
71 *
72 * A value of 20 gives same response as ABLE dh/dm with silo alarm = 0
73 */
74#define DHU_DEF_TIMO 20
75
76/*
77 * Other values for silo timeout register defined here but not used:
78 * receive interrupt only on modem control or silo alarm (3/4 full)
79 */
80#define DHU_POLL_TIMO 0
81/*
82 * receive interrupt immediately on receive character
83 */
84#define DHU_NO_TIMO 1
85
86/*
87 * Local variables for the driver
88 */
89/*
90 * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B".
91 * EXTA => 19200 baud
92 * EXTB => 2000 baud
93 */
f5f63131
MT
94struct speedtab dhuspeedtab[] = {
95 19200, 14,
96 9600, 13,
97 4800, 11,
98 2400, 10,
99 2000, 9,
100 1800, 8,
101 1200, 7,
102 600, 6,
103 300, 5,
104 150, 4,
105 134, 3,
106 110, 2,
107 75, 1,
108 0, 0,
54766b65
MT
109 EXTA, 14,
110 EXTB, 9,
f5f63131
MT
111 -1, -1,
112};
48952cf5
KM
113
114short dhusoftCAR[NDHU];
115
116struct tty dhu_tty[NDHULINE];
117int ndhu = NDHULINE;
118int dhuact; /* mask of active dhu's */
119int dhustart(), ttrstrt();
120
121/*
e965c38b
MK
122 * The clist space is mapped by one terminal driver onto each UNIBUS.
123 * The identity of the board which allocated resources is recorded,
124 * so the process may be repeated after UNIBUS resets.
48952cf5
KM
125 * The UBACVT macro converts a clist space address for unibus uban
126 * into an i/o space address for the DMA routine.
127 */
e965c38b
MK
128int dhu_uballoc[NUBA]; /* which dhu (if any) allocated unibus map */
129int cbase[NUBA]; /* base address of clists in unibus map */
48952cf5
KM
130#define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
131
132/*
133 * Routine for configuration to force a dhu to interrupt.
134 */
135/*ARGSUSED*/
136dhuprobe(reg)
137 caddr_t reg;
138{
139 register int br, cvec; /* these are ``value-result'' */
140 register struct dhudevice *dhuaddr = (struct dhudevice *)reg;
141 int i;
142
143#ifdef lint
144 br = 0; cvec = br; br = cvec;
145 if (ndhu == 0) ndhu = 1;
146 dhurint(0); dhuxint(0);
147#endif
148 /*
149 * The basic idea here is:
150 * do a self-test by setting the Master-Reset bit
151 * if this fails, then return
152 * if successful, there will be 8 diagnostic codes in RX FIFO
153 * therefore ask for a Received-Data-Available interrupt
154 * wait for it...
155 * reset the interrupt-enable bit and flush out the diag. codes
156 */
157 dhuaddr->dhucsr = DHU_CS_MCLR;
158 for (i = 0; i < 1000; i++) {
159 DELAY(10000);
160 if ((dhuaddr->dhucsr&DHU_CS_MCLR) == 0)
161 break;
162 }
163 if (dhuaddr->dhucsr&DHU_CS_MCLR)
164 return(0);
165 if (dhuaddr->dhucsr&DHU_CS_DFAIL)
166 return(0);
167 dhuaddr->dhucsr = DHU_CS_RIE;
168 DELAY(1000);
169 dhuaddr->dhucsr = 0;
170 while (dhuaddr->dhurbuf < 0)
171 /* void */;
172 return (sizeof(struct dhudevice));
173}
174
175/*
176 * Routine called to attach a dhu.
177 */
178dhuattach(ui)
179 struct uba_device *ui;
180{
181
182 dhusoftCAR[ui->ui_unit] = ui->ui_flags;
27f8c1d5 183 cbase[ui->ui_ubanum] = -1;
367868f3 184 dhu_uballoc[ui->ui_ubanum] = -1;
48952cf5
KM
185}
186
187/*
188 * Open a DHU11 line, mapping the clist onto the uba if this
189 * is the first dhu on this uba. Turn on this dhu if this is
190 * the first use of it.
191 */
192/*ARGSUSED*/
193dhuopen(dev, flag)
194 dev_t dev;
195{
196 register struct tty *tp;
197 register int unit, dhu;
198 register struct dhudevice *addr;
199 register struct uba_device *ui;
c376c8e7 200 int s, error = 0;
f5f63131 201 extern dhuparam();
48952cf5
KM
202
203 unit = UNIT(dev);
204 dhu = unit >> 4;
205 if (unit >= NDHULINE || (ui = dhuinfo[dhu])== 0 || ui->ui_alive == 0)
206 return (ENXIO);
207 tp = &dhu_tty[unit];
208 if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
209 return (EBUSY);
210 addr = (struct dhudevice *)ui->ui_addr;
211 tp->t_addr = (caddr_t)addr;
212 tp->t_oproc = dhustart;
f5f63131 213 tp->t_param = dhuparam;
48952cf5
KM
214 /*
215 * While setting up state for this uba and this dhu,
216 * block uba resets which can clear the state.
217 */
218 s = spl5();
27f8c1d5 219 if (cbase[ui->ui_ubanum] == -1) {
e965c38b
MK
220 dhu_uballoc[ui->ui_ubanum] = dhu;
221 cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
222 (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
48952cf5
KM
223 }
224 if ((dhuact&(1<<dhu)) == 0) {
225 addr->dhucsr = DHU_SELECT(0) | DHU_IE;
226 addr->dhutimo = DHU_DEF_TIMO;
227 dhuact |= (1<<dhu);
228 /* anything else to configure whole board */
229 }
230 (void) splx(s);
231 /*
232 * If this is first open, initialize tty state to default.
233 */
234 if ((tp->t_state&TS_ISOPEN) == 0) {
764619a6 235 tp->t_state |= TS_WOPEN;
48952cf5
KM
236 ttychars(tp);
237#ifndef PORTSELECTOR
f5f63131
MT
238 if (tp->t_ospeed == 0) {
239#endif
240 tp->t_ispeed = SPEED;
241 tp->t_ospeed = SPEED;
242 ttsetwater(tp);
243 tp->t_iflag = TTYDEF_IFLAG;
244 tp->t_oflag = TTYDEF_OFLAG;
245 tp->t_lflag = LFLAG;
246 tp->t_cflag = TTYDEF_CFLAG;
247#ifdef PORTSELECTOR
248 tp->t_cflag |= HUPCL;
249#else
48952cf5 250 }
f5f63131 251#endif
48952cf5 252 tp->t_dev = dev;
f5f63131 253 dhuparam(tp, &tp->t_termios);
48952cf5
KM
254 }
255 /*
256 * Wait for carrier, then process line discipline specific open.
257 */
f5f63131 258 s = spltty();
48952cf5
KM
259 if ((dhumctl(dev, DHU_ON, DMSET) & DHU_CAR) ||
260 (dhusoftCAR[dhu] & (1<<(unit&0xf))))
261 tp->t_state |= TS_CARR_ON;
c376c8e7
MK
262 while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
263 (tp->t_state & TS_CARR_ON) == 0) {
48952cf5 264 tp->t_state |= TS_WOPEN;
764619a6
MT
265 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
266 ttopen, 0))
c376c8e7 267 break;
48952cf5
KM
268 }
269 (void) splx(s);
c376c8e7
MK
270 if (error)
271 return (error);
48952cf5
KM
272 return ((*linesw[tp->t_line].l_open)(dev, tp));
273}
274
275/*
276 * Close a DHU11 line, turning off the modem control.
277 */
278/*ARGSUSED*/
279dhuclose(dev, flag)
280 dev_t dev;
281 int flag;
282{
283 register struct tty *tp;
284 register unit;
285
286 unit = UNIT(dev);
287 tp = &dhu_tty[unit];
288 (*linesw[tp->t_line].l_close)(tp);
289 (void) dhumctl(unit, DHU_BRK, DMBIC);
f5f63131 290 if ((tp->t_state&TS_WOPEN) || (tp->t_cflag&HUPCL) ||
c376c8e7 291 (tp->t_state&TS_ISOPEN) == 0) {
48952cf5 292#ifdef PORTSELECTOR
48952cf5
KM
293 (void) dhumctl(unit, DHU_OFF, DMSET);
294 /* Hold DTR low for 0.5 seconds */
c376c8e7 295 (void) tsleep((caddr_t) &tp->t_dev, PZERO, ttclos, hz/2);
48952cf5
KM
296#else
297 (void) dhumctl(unit, DHU_OFF, DMSET);
298#endif PORTSELECTOR
c376c8e7
MK
299 }
300 return (ttyclose(tp));
48952cf5
KM
301}
302
54766b65 303dhuread(dev, uio, flag)
48952cf5
KM
304 dev_t dev;
305 struct uio *uio;
306{
307 register struct tty *tp = &dhu_tty[UNIT(dev)];
308
54766b65 309 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
48952cf5
KM
310}
311
54766b65 312dhuwrite(dev, uio, flag)
48952cf5
KM
313 dev_t dev;
314 struct uio *uio;
315{
316 register struct tty *tp = &dhu_tty[UNIT(dev)];
317
54766b65 318 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
48952cf5
KM
319}
320
321/*
322 * DHU11 receiver interrupt.
323 */
324dhurint(dhu)
325 int dhu;
326{
327 register struct tty *tp;
f5f63131 328 register creg, c;
48952cf5
KM
329 register struct dhudevice *addr;
330 register struct tty *tp0;
331 register struct uba_device *ui;
332 register line;
333 int overrun = 0;
334
f6322301 335#ifdef QBA
f5f63131 336 (void) spltty();
9d2503c6 337#endif
48952cf5
KM
338 ui = dhuinfo[dhu];
339 if (ui == 0 || ui->ui_alive == 0)
340 return;
341 addr = (struct dhudevice *)ui->ui_addr;
342 tp0 = &dhu_tty[dhu<<4];
343 /*
344 * Loop fetching characters from the silo for this
345 * dhu until there are no more in the silo.
346 */
f5f63131
MT
347 while ((creg = addr->dhurbuf) < 0) { /* (c & DHU_RB_VALID) == on */
348 line = DHU_RX_LINE(creg);
48952cf5 349 tp = tp0 + line;
f5f63131
MT
350 c = creg & 0xff;
351 if ((creg & DHU_RB_STAT) == DHU_RB_STAT) {
48952cf5
KM
352 /*
353 * modem changed or diag info
354 */
f5f63131 355 if (creg & DHU_RB_DIAG) {
48952cf5
KM
356 /* decode diagnostic messages */
357 continue;
358 }
f5f63131 359 if (creg & DHU_ST_DCD)
74bfa0d5
MK
360 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
361 else if ((dhusoftCAR[dhu] & (1<<line)) == 0 &&
362 (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
363 (void) dhumctl((dhu<<4)|line, DHU_OFF, DMSET);
48952cf5
KM
364 continue;
365 }
366 if ((tp->t_state&TS_ISOPEN) == 0) {
367 wakeup((caddr_t)&tp->t_rawq);
368#ifdef PORTSELECTOR
369 if ((tp->t_state&TS_WOPEN) == 0)
370#endif
74bfa0d5 371 continue;
48952cf5 372 }
54766b65
MT
373 if (creg & DHU_RB_PE)
374 c |= TTY_PE;
375 if (creg & DHU_RB_DO && overrun == 0) {
376 log(LOG_WARNING, "dhu%d: silo overflow\n", dhu);
377 overrun = 1;
48952cf5 378 }
54766b65
MT
379 if (creg & DHU_RB_FE)
380 c |= TTY_FE;
f5f63131 381
54766b65 382 (*linesw[tp->t_line].l_rint)(c, tp);
48952cf5
KM
383 }
384}
385
386/*
387 * Ioctl for DHU11.
388 */
389/*ARGSUSED*/
390dhuioctl(dev, cmd, data, flag)
391 caddr_t data;
392{
393 register struct tty *tp;
394 register int unit = UNIT(dev);
48952cf5
KM
395 int error;
396
397 tp = &dhu_tty[unit];
398 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
399 if (error >= 0)
400 return (error);
401 error = ttioctl(tp, cmd, data, flag);
f5f63131 402 if (error >= 0)
48952cf5 403 return (error);
48952cf5
KM
404
405 switch (cmd) {
406 case TIOCSBRK:
407 (void) dhumctl(unit, DHU_BRK, DMBIS);
408 break;
409
410 case TIOCCBRK:
411 (void) dhumctl(unit, DHU_BRK, DMBIC);
412 break;
413
414 case TIOCSDTR:
415 (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIS);
416 break;
417
418 case TIOCCDTR:
419 (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIC);
420 break;
421
422 case TIOCMSET:
423 (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET);
424 break;
425
426 case TIOCMBIS:
427 (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS);
428 break;
429
430 case TIOCMBIC:
431 (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC);
432 break;
433
434 case TIOCMGET:
435 *(int *)data = dhutodm(dhumctl(dev, 0, DMGET));
436 break;
437 default:
438 return (ENOTTY);
439 }
440 return (0);
441}
442
443dmtodhu(bits)
444 register int bits;
445{
446 register int b = 0;
447
448 if (bits & DML_RTS) b |= DHU_RTS;
449 if (bits & DML_DTR) b |= DHU_DTR;
450 if (bits & DML_LE) b |= DHU_LE;
451 return(b);
452}
453
454dhutodm(bits)
455 register int bits;
456{
457 register int b = 0;
458
459 if (bits & DHU_DSR) b |= DML_DSR;
460 if (bits & DHU_RNG) b |= DML_RNG;
461 if (bits & DHU_CAR) b |= DML_CAR;
462 if (bits & DHU_CTS) b |= DML_CTS;
463 if (bits & DHU_RTS) b |= DML_RTS;
464 if (bits & DHU_DTR) b |= DML_DTR;
465 if (bits & DHU_LE) b |= DML_LE;
466 return(b);
467}
468
469
470/*
471 * Set parameters from open or stty into the DHU hardware
f5f63131
MT
472 * registers. Impossible values for speed or character
473 * size are ignored and not copied back into tp.
48952cf5 474 */
f5f63131 475dhuparam(tp, want)
48952cf5 476 register struct tty *tp;
f5f63131
MT
477 register struct termios *want;
478{
479 register int unit = UNIT(tp->t_dev);
480 register struct dhudevice *addr = (struct dhudevice *)tp->t_addr;
48952cf5 481 register int lpar;
f5f63131
MT
482 register long cflag;
483 register int incode, outcode;
48952cf5 484 int s;
f5f63131 485
48952cf5
KM
486 /*
487 * Block interrupts so parameters will be set
488 * before the line interrupts.
489 */
f5f63131
MT
490 s = spltty();
491
492 if (want->c_ospeed == 0) {
493 tp->t_ospeed = 0;
494 tp->t_cflag |= HUPCL;
48952cf5
KM
495 (void)dhumctl(unit, DHU_OFF, DMSET);
496 splx(s);
497 return;
498 }
f5f63131
MT
499
500 if ((outcode = ttspeedtab(want->c_ospeed, dhuspeedtab)) >= 0)
501 tp->t_ospeed = want->c_ospeed;
48952cf5 502 else
f5f63131
MT
503 outcode = ttspeedtab(tp->t_ospeed, dhuspeedtab);
504
505 if (want->c_ispeed == 0) {
506 tp->t_ispeed = 0;
507 incode = outcode;
508 } else if ((incode = ttspeedtab(want->c_ispeed, dhuspeedtab)) >= 0)
509 tp->t_ispeed = want->c_ispeed;
510 else
511 incode = ttspeedtab(tp->t_ispeed, dhuspeedtab);
512
513 lpar = ((char)outcode<<12) | ((char)incode<<8);
514
515 switch (want->c_cflag&CSIZE) {
516 case CS6: case CS7: case CS8:
517 tp->t_cflag = want->c_cflag;
518 break;
519 default:
520 tp->t_cflag = (tp->t_cflag&CSIZE) | (want->c_cflag & ~CSIZE);
521 }
522 cflag = tp->t_cflag;
523
524 switch(cflag&CSIZE) {
525 case CS6:
526 lpar |= DHU_LP_BITS6;
527 break;
528 case CS7:
529 lpar |= DHU_LP_BITS7;
530 break;
531 case CS8:
532 lpar |= DHU_LP_BITS8;
533 break;
534 }
535 if (cflag&PARENB) {
536 lpar |= DHU_LP_PENABLE;
537 if ((cflag&PARODD) == 0)
538 lpar |= DHU_LP_EPAR;
539 }
540 if (cflag&CSTOPB)
48952cf5 541 lpar |= DHU_LP_TWOSB;
f5f63131 542
54766b65 543 addr->dhucsr = DHU_SELECT(unit) | DHU_IE;
48952cf5
KM
544 addr->dhulpr = lpar;
545 splx(s);
546}
547
548/*
549 * DHU11 transmitter interrupt.
550 * Restart each line which used to be active but has
551 * terminated transmission since the last interrupt.
552 */
553dhuxint(dhu)
554 int dhu;
555{
556 register struct tty *tp;
557 register struct dhudevice *addr;
558 register struct tty *tp0;
559 register struct uba_device *ui;
560 register int line, t;
561 u_short cntr;
562
f6322301 563#ifdef QBA
9d2503c6
BK
564 (void) spl5();
565#endif
48952cf5
KM
566 ui = dhuinfo[dhu];
567 tp0 = &dhu_tty[dhu<<4];
568 addr = (struct dhudevice *)ui->ui_addr;
569 while ((t = addr->dhucsrh) & DHU_CSH_TI) {
570 line = DHU_TX_LINE(t);
571 tp = tp0 + line;
572 tp->t_state &= ~TS_BUSY;
573 if (t & DHU_CSH_NXM) {
574 printf("dhu(%d,%d): NXM fault\n", dhu, line);
575 /* SHOULD RESTART OR SOMETHING... */
576 }
577 if (tp->t_state&TS_FLUSH)
578 tp->t_state &= ~TS_FLUSH;
579 else {
580 addr->dhucsrl = DHU_SELECT(line) | DHU_IE;
581 /*
582 * Do arithmetic in a short to make up
583 * for lost 16&17 bits.
584 */
585 cntr = addr->dhubar1 -
586 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
587 ndflush(&tp->t_outq, (int)cntr);
588 }
589 if (tp->t_line)
590 (*linesw[tp->t_line].l_start)(tp);
591 else
592 dhustart(tp);
593 }
594}
595
596/*
597 * Start (restart) transmission on the given DHU11 line.
598 */
599dhustart(tp)
600 register struct tty *tp;
601{
602 register struct dhudevice *addr;
603 register int car, dhu, unit, nch;
604 int s;
605
606 unit = minor(tp->t_dev);
607 dhu = unit >> 4;
608 unit &= 0xf;
609 addr = (struct dhudevice *)tp->t_addr;
610
611 /*
612 * Must hold interrupts in following code to prevent
613 * state of the tp from changing.
614 */
615 s = spl5();
616 /*
617 * If it's currently active, or delaying, no need to do anything.
618 */
619 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
620 goto out;
621 /*
622 * If there are sleepers, and output has drained below low
623 * water mark, wake up the sleepers..
624 */
f5f63131 625 if (tp->t_outq.c_cc <= tp->t_lowat) {
48952cf5
KM
626 if (tp->t_state&TS_ASLEEP) {
627 tp->t_state &= ~TS_ASLEEP;
628 wakeup((caddr_t)&tp->t_outq);
629 }
630 if (tp->t_wsel) {
631 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
632 tp->t_wsel = 0;
633 tp->t_state &= ~TS_WCOLL;
634 }
635 }
636 /*
637 * Now restart transmission unless the output queue is
638 * empty.
639 */
640 if (tp->t_outq.c_cc == 0)
641 goto out;
54766b65 642 if (1 || !(tp->t_oflag & OPOST)) /*XXX*/
48952cf5
KM
643 nch = ndqb(&tp->t_outq, 0);
644 else {
645 nch = ndqb(&tp->t_outq, 0200);
646 /*
647 * If first thing on queue is a delay process it.
648 */
649 if (nch == 0) {
650 nch = getc(&tp->t_outq);
651 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
652 tp->t_state |= TS_TIMEOUT;
653 goto out;
654 }
655 }
656 /*
657 * If characters to transmit, restart transmission.
658 */
659 if (nch) {
660 car = UBACVT(tp->t_outq.c_cf, dhuinfo[dhu]->ui_ubanum);
661 addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
662 addr->dhulcr &= ~DHU_LC_TXABORT;
663 addr->dhubcr = nch;
664 addr->dhubar1 = car;
665 addr->dhubar2 = ((car >> DHU_XBA_SHIFT) & DHU_BA2_XBA) |
666 DHU_BA2_DMAGO;
667 tp->t_state |= TS_BUSY;
668 }
669out:
670 splx(s);
671}
672
673/*
674 * Stop output on a line, e.g. for ^S/^Q or output flush.
675 */
676/*ARGSUSED*/
677dhustop(tp, flag)
678 register struct tty *tp;
679{
680 register struct dhudevice *addr;
681 register int unit, s;
682
683 addr = (struct dhudevice *)tp->t_addr;
684 /*
685 * Block input/output interrupts while messing with state.
686 */
687 s = spl5();
688 if (tp->t_state & TS_BUSY) {
689 /*
690 * Device is transmitting; stop output
691 * by selecting the line and setting the
692 * abort xmit bit. We will get an xmit interrupt,
693 * where we will figure out where to continue the
694 * next time the transmitter is enabled. If
695 * TS_FLUSH is set, the outq will be flushed.
696 * In either case, dhustart will clear the TXABORT bit.
697 */
698 unit = minor(tp->t_dev);
699 addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
700 addr->dhulcr |= DHU_LC_TXABORT;
701 if ((tp->t_state&TS_TTSTOP)==0)
702 tp->t_state |= TS_FLUSH;
703 }
704 (void) splx(s);
705}
706
707/*
708 * DHU11 modem control
709 */
710dhumctl(dev, bits, how)
711 dev_t dev;
712 int bits, how;
713{
714 register struct dhudevice *dhuaddr;
9418508d 715 register int unit, mbits;
48952cf5
KM
716 int s;
717
718 unit = UNIT(dev);
719 dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr);
720 unit &= 0xf;
721 s = spl5();
722 dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE;
723 /*
724 * combine byte from stat register (read only, bits 16..23)
725 * with lcr register (read write, bits 0..15).
726 */
727 mbits = dhuaddr->dhulcr | (dhuaddr->dhustat << 16);
728 switch (how) {
729 case DMSET:
730 mbits = (mbits & 0xff0000) | bits;
731 break;
732
733 case DMBIS:
734 mbits |= bits;
735 break;
736
737 case DMBIC:
738 mbits &= ~bits;
739 break;
740
741 case DMGET:
742 (void) splx(s);
743 return(mbits);
744 }
745 dhuaddr->dhulcr = (mbits & 0xffff) | DHU_LC_RXEN;
746 dhuaddr->dhulcr2 = DHU_LC2_TXEN;
747 (void) splx(s);
748 return(mbits);
749}
750
751/*
752 * Reset state of driver if UBA reset was necessary.
753 * Reset the line and modem control registers.
754 * restart transmitters.
755 */
756dhureset(uban)
757 int uban;
758{
759 register int dhu, unit;
760 register struct tty *tp;
761 register struct uba_device *ui;
762 register struct dhudevice *addr;
763 int i;
48952cf5 764
48952cf5
KM
765 for (dhu = 0; dhu < NDHU; dhu++) {
766 ui = dhuinfo[dhu];
767 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
768 continue;
769 printf(" dhu%d", dhu);
e965c38b
MK
770 if (dhu_uballoc[uban] == dhu) {
771 int info;
772
773 info = uballoc(uban, (caddr_t)cfree,
774 nclist * sizeof(struct cblock), UBA_CANTWAIT);
775 if (info)
776 cbase[uban] = UBAI_ADDR(info);
777 else {
778 printf(" [can't get uba map]");
779 cbase[uban] = -1;
780 }
c18c7ccc 781 }
48952cf5
KM
782 addr = (struct dhudevice *)ui->ui_addr;
783 addr->dhucsr = DHU_SELECT(0) | DHU_IE;
784 addr->dhutimo = DHU_DEF_TIMO;
785 unit = dhu * 16;
786 for (i = 0; i < 16; i++) {
787 tp = &dhu_tty[unit];
788 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
f5f63131 789 dhuparam(tp, &tp->t_termios);
48952cf5
KM
790 (void)dhumctl(unit, DHU_ON, DMSET);
791 tp->t_state &= ~TS_BUSY;
792 dhustart(tp);
793 }
794 unit++;
795 }
796 }
797}
798#endif