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