tsleep: unwind after signal interrupts; close routines must return value
[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 *
c376c8e7 6 * @(#)dhu.c 7.10 (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) {
235 ttychars(tp);
236#ifndef PORTSELECTOR
f5f63131
MT
237 if (tp->t_ospeed == 0) {
238#endif
239 tp->t_ispeed = SPEED;
240 tp->t_ospeed = SPEED;
241 ttsetwater(tp);
242 tp->t_iflag = TTYDEF_IFLAG;
243 tp->t_oflag = TTYDEF_OFLAG;
244 tp->t_lflag = LFLAG;
245 tp->t_cflag = TTYDEF_CFLAG;
246#ifdef PORTSELECTOR
247 tp->t_cflag |= HUPCL;
248#else
48952cf5 249 }
f5f63131 250#endif
48952cf5 251 tp->t_dev = dev;
f5f63131 252 dhuparam(tp, &tp->t_termios);
48952cf5
KM
253 }
254 /*
255 * Wait for carrier, then process line discipline specific open.
256 */
f5f63131 257 s = spltty();
48952cf5
KM
258 if ((dhumctl(dev, DHU_ON, DMSET) & DHU_CAR) ||
259 (dhusoftCAR[dhu] & (1<<(unit&0xf))))
260 tp->t_state |= TS_CARR_ON;
c376c8e7
MK
261 while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
262 (tp->t_state & TS_CARR_ON) == 0) {
48952cf5 263 tp->t_state |= TS_WOPEN;
c376c8e7
MK
264 if (error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
265 ttopen, 0))
266 break;
48952cf5
KM
267 }
268 (void) splx(s);
c376c8e7
MK
269 if (error)
270 return (error);
48952cf5
KM
271 return ((*linesw[tp->t_line].l_open)(dev, tp));
272}
273
274/*
275 * Close a DHU11 line, turning off the modem control.
276 */
277/*ARGSUSED*/
278dhuclose(dev, flag)
279 dev_t dev;
280 int flag;
281{
282 register struct tty *tp;
283 register unit;
284
285 unit = UNIT(dev);
286 tp = &dhu_tty[unit];
287 (*linesw[tp->t_line].l_close)(tp);
288 (void) dhumctl(unit, DHU_BRK, DMBIC);
f5f63131 289 if ((tp->t_state&TS_WOPEN) || (tp->t_cflag&HUPCL) ||
c376c8e7 290 (tp->t_state&TS_ISOPEN) == 0) {
48952cf5 291#ifdef PORTSELECTOR
48952cf5
KM
292 (void) dhumctl(unit, DHU_OFF, DMSET);
293 /* Hold DTR low for 0.5 seconds */
c376c8e7 294 (void) tsleep((caddr_t) &tp->t_dev, PZERO, ttclos, hz/2);
48952cf5
KM
295#else
296 (void) dhumctl(unit, DHU_OFF, DMSET);
297#endif PORTSELECTOR
c376c8e7
MK
298 }
299 return (ttyclose(tp));
48952cf5
KM
300}
301
54766b65 302dhuread(dev, uio, flag)
48952cf5
KM
303 dev_t dev;
304 struct uio *uio;
305{
306 register struct tty *tp = &dhu_tty[UNIT(dev)];
307
54766b65 308 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
48952cf5
KM
309}
310
54766b65 311dhuwrite(dev, uio, flag)
48952cf5
KM
312 dev_t dev;
313 struct uio *uio;
314{
315 register struct tty *tp = &dhu_tty[UNIT(dev)];
316
54766b65 317 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
48952cf5
KM
318}
319
320/*
321 * DHU11 receiver interrupt.
322 */
323dhurint(dhu)
324 int dhu;
325{
326 register struct tty *tp;
f5f63131 327 register creg, c;
48952cf5
KM
328 register struct dhudevice *addr;
329 register struct tty *tp0;
330 register struct uba_device *ui;
331 register line;
332 int overrun = 0;
333
f6322301 334#ifdef QBA
f5f63131 335 (void) spltty();
9d2503c6 336#endif
48952cf5
KM
337 ui = dhuinfo[dhu];
338 if (ui == 0 || ui->ui_alive == 0)
339 return;
340 addr = (struct dhudevice *)ui->ui_addr;
341 tp0 = &dhu_tty[dhu<<4];
342 /*
343 * Loop fetching characters from the silo for this
344 * dhu until there are no more in the silo.
345 */
f5f63131
MT
346 while ((creg = addr->dhurbuf) < 0) { /* (c & DHU_RB_VALID) == on */
347 line = DHU_RX_LINE(creg);
48952cf5 348 tp = tp0 + line;
f5f63131
MT
349 c = creg & 0xff;
350 if ((creg & DHU_RB_STAT) == DHU_RB_STAT) {
48952cf5
KM
351 /*
352 * modem changed or diag info
353 */
f5f63131 354 if (creg & DHU_RB_DIAG) {
48952cf5
KM
355 /* decode diagnostic messages */
356 continue;
357 }
f5f63131 358 if (creg & DHU_ST_DCD)
74bfa0d5
MK
359 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
360 else if ((dhusoftCAR[dhu] & (1<<line)) == 0 &&
361 (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
362 (void) dhumctl((dhu<<4)|line, DHU_OFF, DMSET);
48952cf5
KM
363 continue;
364 }
365 if ((tp->t_state&TS_ISOPEN) == 0) {
366 wakeup((caddr_t)&tp->t_rawq);
367#ifdef PORTSELECTOR
368 if ((tp->t_state&TS_WOPEN) == 0)
369#endif
74bfa0d5 370 continue;
48952cf5 371 }
54766b65
MT
372 if (creg & DHU_RB_PE)
373 c |= TTY_PE;
374 if (creg & DHU_RB_DO && overrun == 0) {
375 log(LOG_WARNING, "dhu%d: silo overflow\n", dhu);
376 overrun = 1;
48952cf5 377 }
54766b65
MT
378 if (creg & DHU_RB_FE)
379 c |= TTY_FE;
f5f63131 380
54766b65 381 (*linesw[tp->t_line].l_rint)(c, tp);
48952cf5
KM
382 }
383}
384
385/*
386 * Ioctl for DHU11.
387 */
388/*ARGSUSED*/
389dhuioctl(dev, cmd, data, flag)
390 caddr_t data;
391{
392 register struct tty *tp;
393 register int unit = UNIT(dev);
48952cf5
KM
394 int error;
395
396 tp = &dhu_tty[unit];
397 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
398 if (error >= 0)
399 return (error);
400 error = ttioctl(tp, cmd, data, flag);
f5f63131 401 if (error >= 0)
48952cf5 402 return (error);
48952cf5
KM
403
404 switch (cmd) {
405 case TIOCSBRK:
406 (void) dhumctl(unit, DHU_BRK, DMBIS);
407 break;
408
409 case TIOCCBRK:
410 (void) dhumctl(unit, DHU_BRK, DMBIC);
411 break;
412
413 case TIOCSDTR:
414 (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIS);
415 break;
416
417 case TIOCCDTR:
418 (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIC);
419 break;
420
421 case TIOCMSET:
422 (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET);
423 break;
424
425 case TIOCMBIS:
426 (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS);
427 break;
428
429 case TIOCMBIC:
430 (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC);
431 break;
432
433 case TIOCMGET:
434 *(int *)data = dhutodm(dhumctl(dev, 0, DMGET));
435 break;
436 default:
437 return (ENOTTY);
438 }
439 return (0);
440}
441
442dmtodhu(bits)
443 register int bits;
444{
445 register int b = 0;
446
447 if (bits & DML_RTS) b |= DHU_RTS;
448 if (bits & DML_DTR) b |= DHU_DTR;
449 if (bits & DML_LE) b |= DHU_LE;
450 return(b);
451}
452
453dhutodm(bits)
454 register int bits;
455{
456 register int b = 0;
457
458 if (bits & DHU_DSR) b |= DML_DSR;
459 if (bits & DHU_RNG) b |= DML_RNG;
460 if (bits & DHU_CAR) b |= DML_CAR;
461 if (bits & DHU_CTS) b |= DML_CTS;
462 if (bits & DHU_RTS) b |= DML_RTS;
463 if (bits & DHU_DTR) b |= DML_DTR;
464 if (bits & DHU_LE) b |= DML_LE;
465 return(b);
466}
467
468
469/*
470 * Set parameters from open or stty into the DHU hardware
f5f63131
MT
471 * registers. Impossible values for speed or character
472 * size are ignored and not copied back into tp.
48952cf5 473 */
f5f63131 474dhuparam(tp, want)
48952cf5 475 register struct tty *tp;
f5f63131
MT
476 register struct termios *want;
477{
478 register int unit = UNIT(tp->t_dev);
479 register struct dhudevice *addr = (struct dhudevice *)tp->t_addr;
48952cf5 480 register int lpar;
f5f63131
MT
481 register long cflag;
482 register int incode, outcode;
48952cf5 483 int s;
f5f63131 484
48952cf5
KM
485 /*
486 * Block interrupts so parameters will be set
487 * before the line interrupts.
488 */
f5f63131
MT
489 s = spltty();
490
491 if (want->c_ospeed == 0) {
492 tp->t_ospeed = 0;
493 tp->t_cflag |= HUPCL;
48952cf5
KM
494 (void)dhumctl(unit, DHU_OFF, DMSET);
495 splx(s);
496 return;
497 }
f5f63131
MT
498
499 if ((outcode = ttspeedtab(want->c_ospeed, dhuspeedtab)) >= 0)
500 tp->t_ospeed = want->c_ospeed;
48952cf5 501 else
f5f63131
MT
502 outcode = ttspeedtab(tp->t_ospeed, dhuspeedtab);
503
504 if (want->c_ispeed == 0) {
505 tp->t_ispeed = 0;
506 incode = outcode;
507 } else if ((incode = ttspeedtab(want->c_ispeed, dhuspeedtab)) >= 0)
508 tp->t_ispeed = want->c_ispeed;
509 else
510 incode = ttspeedtab(tp->t_ispeed, dhuspeedtab);
511
512 lpar = ((char)outcode<<12) | ((char)incode<<8);
513
514 switch (want->c_cflag&CSIZE) {
515 case CS6: case CS7: case CS8:
516 tp->t_cflag = want->c_cflag;
517 break;
518 default:
519 tp->t_cflag = (tp->t_cflag&CSIZE) | (want->c_cflag & ~CSIZE);
520 }
521 cflag = tp->t_cflag;
522
523 switch(cflag&CSIZE) {
524 case CS6:
525 lpar |= DHU_LP_BITS6;
526 break;
527 case CS7:
528 lpar |= DHU_LP_BITS7;
529 break;
530 case CS8:
531 lpar |= DHU_LP_BITS8;
532 break;
533 }
534 if (cflag&PARENB) {
535 lpar |= DHU_LP_PENABLE;
536 if ((cflag&PARODD) == 0)
537 lpar |= DHU_LP_EPAR;
538 }
539 if (cflag&CSTOPB)
48952cf5 540 lpar |= DHU_LP_TWOSB;
f5f63131 541
54766b65 542 addr->dhucsr = DHU_SELECT(unit) | DHU_IE;
48952cf5
KM
543 addr->dhulpr = lpar;
544 splx(s);
545}
546
547/*
548 * DHU11 transmitter interrupt.
549 * Restart each line which used to be active but has
550 * terminated transmission since the last interrupt.
551 */
552dhuxint(dhu)
553 int dhu;
554{
555 register struct tty *tp;
556 register struct dhudevice *addr;
557 register struct tty *tp0;
558 register struct uba_device *ui;
559 register int line, t;
560 u_short cntr;
561
f6322301 562#ifdef QBA
9d2503c6
BK
563 (void) spl5();
564#endif
48952cf5
KM
565 ui = dhuinfo[dhu];
566 tp0 = &dhu_tty[dhu<<4];
567 addr = (struct dhudevice *)ui->ui_addr;
568 while ((t = addr->dhucsrh) & DHU_CSH_TI) {
569 line = DHU_TX_LINE(t);
570 tp = tp0 + line;
571 tp->t_state &= ~TS_BUSY;
572 if (t & DHU_CSH_NXM) {
573 printf("dhu(%d,%d): NXM fault\n", dhu, line);
574 /* SHOULD RESTART OR SOMETHING... */
575 }
576 if (tp->t_state&TS_FLUSH)
577 tp->t_state &= ~TS_FLUSH;
578 else {
579 addr->dhucsrl = DHU_SELECT(line) | DHU_IE;
580 /*
581 * Do arithmetic in a short to make up
582 * for lost 16&17 bits.
583 */
584 cntr = addr->dhubar1 -
585 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
586 ndflush(&tp->t_outq, (int)cntr);
587 }
588 if (tp->t_line)
589 (*linesw[tp->t_line].l_start)(tp);
590 else
591 dhustart(tp);
592 }
593}
594
595/*
596 * Start (restart) transmission on the given DHU11 line.
597 */
598dhustart(tp)
599 register struct tty *tp;
600{
601 register struct dhudevice *addr;
602 register int car, dhu, unit, nch;
603 int s;
604
605 unit = minor(tp->t_dev);
606 dhu = unit >> 4;
607 unit &= 0xf;
608 addr = (struct dhudevice *)tp->t_addr;
609
610 /*
611 * Must hold interrupts in following code to prevent
612 * state of the tp from changing.
613 */
614 s = spl5();
615 /*
616 * If it's currently active, or delaying, no need to do anything.
617 */
618 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
619 goto out;
620 /*
621 * If there are sleepers, and output has drained below low
622 * water mark, wake up the sleepers..
623 */
f5f63131 624 if (tp->t_outq.c_cc <= tp->t_lowat) {
48952cf5
KM
625 if (tp->t_state&TS_ASLEEP) {
626 tp->t_state &= ~TS_ASLEEP;
627 wakeup((caddr_t)&tp->t_outq);
628 }
629 if (tp->t_wsel) {
630 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
631 tp->t_wsel = 0;
632 tp->t_state &= ~TS_WCOLL;
633 }
634 }
635 /*
636 * Now restart transmission unless the output queue is
637 * empty.
638 */
639 if (tp->t_outq.c_cc == 0)
640 goto out;
54766b65 641 if (1 || !(tp->t_oflag & OPOST)) /*XXX*/
48952cf5
KM
642 nch = ndqb(&tp->t_outq, 0);
643 else {
644 nch = ndqb(&tp->t_outq, 0200);
645 /*
646 * If first thing on queue is a delay process it.
647 */
648 if (nch == 0) {
649 nch = getc(&tp->t_outq);
650 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
651 tp->t_state |= TS_TIMEOUT;
652 goto out;
653 }
654 }
655 /*
656 * If characters to transmit, restart transmission.
657 */
658 if (nch) {
659 car = UBACVT(tp->t_outq.c_cf, dhuinfo[dhu]->ui_ubanum);
660 addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
661 addr->dhulcr &= ~DHU_LC_TXABORT;
662 addr->dhubcr = nch;
663 addr->dhubar1 = car;
664 addr->dhubar2 = ((car >> DHU_XBA_SHIFT) & DHU_BA2_XBA) |
665 DHU_BA2_DMAGO;
666 tp->t_state |= TS_BUSY;
667 }
668out:
669 splx(s);
670}
671
672/*
673 * Stop output on a line, e.g. for ^S/^Q or output flush.
674 */
675/*ARGSUSED*/
676dhustop(tp, flag)
677 register struct tty *tp;
678{
679 register struct dhudevice *addr;
680 register int unit, s;
681
682 addr = (struct dhudevice *)tp->t_addr;
683 /*
684 * Block input/output interrupts while messing with state.
685 */
686 s = spl5();
687 if (tp->t_state & TS_BUSY) {
688 /*
689 * Device is transmitting; stop output
690 * by selecting the line and setting the
691 * abort xmit bit. We will get an xmit interrupt,
692 * where we will figure out where to continue the
693 * next time the transmitter is enabled. If
694 * TS_FLUSH is set, the outq will be flushed.
695 * In either case, dhustart will clear the TXABORT bit.
696 */
697 unit = minor(tp->t_dev);
698 addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
699 addr->dhulcr |= DHU_LC_TXABORT;
700 if ((tp->t_state&TS_TTSTOP)==0)
701 tp->t_state |= TS_FLUSH;
702 }
703 (void) splx(s);
704}
705
706/*
707 * DHU11 modem control
708 */
709dhumctl(dev, bits, how)
710 dev_t dev;
711 int bits, how;
712{
713 register struct dhudevice *dhuaddr;
9418508d 714 register int unit, mbits;
48952cf5
KM
715 int s;
716
717 unit = UNIT(dev);
718 dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr);
719 unit &= 0xf;
720 s = spl5();
721 dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE;
722 /*
723 * combine byte from stat register (read only, bits 16..23)
724 * with lcr register (read write, bits 0..15).
725 */
726 mbits = dhuaddr->dhulcr | (dhuaddr->dhustat << 16);
727 switch (how) {
728 case DMSET:
729 mbits = (mbits & 0xff0000) | bits;
730 break;
731
732 case DMBIS:
733 mbits |= bits;
734 break;
735
736 case DMBIC:
737 mbits &= ~bits;
738 break;
739
740 case DMGET:
741 (void) splx(s);
742 return(mbits);
743 }
744 dhuaddr->dhulcr = (mbits & 0xffff) | DHU_LC_RXEN;
745 dhuaddr->dhulcr2 = DHU_LC2_TXEN;
746 (void) splx(s);
747 return(mbits);
748}
749
750/*
751 * Reset state of driver if UBA reset was necessary.
752 * Reset the line and modem control registers.
753 * restart transmitters.
754 */
755dhureset(uban)
756 int uban;
757{
758 register int dhu, unit;
759 register struct tty *tp;
760 register struct uba_device *ui;
761 register struct dhudevice *addr;
762 int i;
48952cf5 763
48952cf5
KM
764 for (dhu = 0; dhu < NDHU; dhu++) {
765 ui = dhuinfo[dhu];
766 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
767 continue;
768 printf(" dhu%d", dhu);
e965c38b
MK
769 if (dhu_uballoc[uban] == dhu) {
770 int info;
771
772 info = uballoc(uban, (caddr_t)cfree,
773 nclist * sizeof(struct cblock), UBA_CANTWAIT);
774 if (info)
775 cbase[uban] = UBAI_ADDR(info);
776 else {
777 printf(" [can't get uba map]");
778 cbase[uban] = -1;
779 }
c18c7ccc 780 }
48952cf5
KM
781 addr = (struct dhudevice *)ui->ui_addr;
782 addr->dhucsr = DHU_SELECT(0) | DHU_IE;
783 addr->dhutimo = DHU_DEF_TIMO;
784 unit = dhu * 16;
785 for (i = 0; i < 16; i++) {
786 tp = &dhu_tty[unit];
787 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
f5f63131 788 dhuparam(tp, &tp->t_termios);
48952cf5
KM
789 (void)dhumctl(unit, DHU_ON, DMSET);
790 tp->t_state &= ~TS_BUSY;
791 dhustart(tp);
792 }
793 unit++;
794 }
795 }
796}
797#endif