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