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