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