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