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