change to 3 isp pages; proc 0 upages in order
[unix-history] / usr / src / sys / vax / uba / dh.c
CommitLineData
88d5b764 1/* dh.c 4.15 81/02/16 */
a18f326f 2
66b4fb09 3#include "dh.h"
a5cc519e 4#if NDH11 > 0
88d5b764 5#define DELAY(i) { register int j = i; while (--j > 0); }
a18f326f 6/*
a5cc519e 7 * DH-11 driver
5aa9d5ea 8 * DOESNT HANDLE EXTENDED ADDRESS BITS.
a18f326f
BJ
9 */
10
11#include "../h/param.h"
12#include "../h/conf.h"
13#include "../h/dir.h"
14#include "../h/user.h"
15#include "../h/tty.h"
16#include "../h/map.h"
17#include "../h/pte.h"
3f3a34c3 18#include "../h/buf.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"
a18f326f 23
88d5b764 24#define UBACVT(x,uban) (cbase[uban] + ((x)-(char *)cfree))
a18f326f 25
3f3a34c3
BJ
26int dhcntrlr(), dhslave(), dhrint(), dhxint();
27struct uba_dinfo *dhinfo[NDH11];
28u_short dhstd[] = { 0 };
3f3a34c3 29struct uba_driver dhdriver =
88d5b764 30 { dhcntrlr, dhslave, 0, 0, dhstd, "dh", dhinfo };
3f3a34c3
BJ
31
32struct tty dh11[NDH11*16];
0e239190 33int dhact;
3f3a34c3 34int ndh11 = NDH11*16;
a18f326f
BJ
35int dhstart();
36int ttrstrt();
5aa9d5ea
RE
37int dh_ubinfo[MAXNUBA];
38int cbase[MAXNUBA];
a18f326f
BJ
39
40/*
41 * Hardware control bits
42 */
43#define BITS6 01
44#define BITS7 02
45#define BITS8 03
46#define TWOSB 04
47#define PENABLE 020
48/* DEC manuals incorrectly say this bit causes generation of even parity. */
49#define OPAR 040
50#define HDUPLX 040000
51
88d5b764
BJ
52/* Bits in dhcsr */
53#define DH_TI 0100000 /* transmit interrupt */
54#define DH_SI 0040000 /* storage interrupt */
55#define DH_TIE 0020000 /* transmit interrupt enable */
56#define DH_SIE 0010000 /* storage interrupt enable */
57#define DH_MC 0004000 /* master clear */
58#define DH_NXM 0002000 /* non-existant memory */
59#define DH_MM 0001000 /* maintenance mode */
60#define DH_CNI 0000400 /* clear non-existant memory interrupt */
61#define DH_RI 0000200 /* receiver interrupt */
62#define DH_RIE 0000100 /* receiver interrupt enable */
63
64#define DH_IE (DH_TIE|DH_SIE|DH_RIE)
65
66/* Bits in dhrcr */
67#define DH_PE 010000 /* parity error */
68#define DH_FE 020000 /* framing error */
69#define DH_DO 040000 /* data overrun */
a18f326f 70
a18f326f
BJ
71/*
72 * DM control bits
73 */
88d5b764
BJ
74#define DM_ON 03 /* CD lead + line enable */
75#define DM_OFF 01 /* line enable */
76#define DM_DTR 02 /* data terminal ready */
77#define DM_RQS 04 /* request to send */
a18f326f
BJ
78
79/*
80 * Software copy of last dhbar
81 */
3f3a34c3 82short dhsar[NDH11];
a18f326f
BJ
83
84struct device
85{
86 union {
88d5b764
BJ
87 short dhcsr; /* control-status register */
88 char dhcsrl; /* low byte for line select */
a18f326f 89 } un;
88d5b764
BJ
90 short dhrcr; /* receive character register */
91 short dhlpr; /* line parameter register */
92 u_short dhcar; /* current address register */
93 short dhbcr; /* byte count register */
94 u_short dhbar; /* buffer active register */
95 short dhbreak; /* break control register */
96 short dhsilo; /* silo status register */
a18f326f
BJ
97};
98
88d5b764
BJ
99/*
100 * Routine for configuration to force a dh to interrupt.
101 * Set to transmit at 9600 baud, and cause a transmitter interrupt.
102 */
3f3a34c3
BJ
103dhcntrlr(ui, reg)
104 struct uba_dinfo *ui;
105 caddr_t reg;
106{
88d5b764
BJ
107 register int br, cvec;
108 register struct device *dhaddr = (struct device *)reg;
5aa9d5ea
RE
109 int i;
110
88d5b764
BJ
111 dhaddr->un.dhcsr = DH_TIE;
112 DELAY(5);
113 dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE;
5aa9d5ea 114 dhaddr->dhbcr = -1;
5aa9d5ea 115 dhaddr->dhcar = 0;
88d5b764
BJ
116 dhaddr->dhbar = 1;
117 DELAY(100000); /* wait 1/10'th of a sec for interrupt */
5aa9d5ea 118 dhaddr->un.dhcsr = 0;
88d5b764
BJ
119 if (cvec && cvec != 0x200)
120 cvec -= 4; /* transmit -> receive */
121 return (1);
3f3a34c3
BJ
122}
123
88d5b764
BJ
124/*
125 * Routine called to init slave tables.
126 */
3f3a34c3
BJ
127dhslave(ui, reg, slaveno)
128 struct uba_dinfo *ui;
129 caddr_t reg;
130{
131
88d5b764 132 /* no tables to set up */
3f3a34c3
BJ
133}
134
a18f326f
BJ
135/*
136 * Open a DH11 line.
137 */
138/*ARGSUSED*/
139dhopen(dev, flag)
3f3a34c3 140 dev_t dev;
a18f326f
BJ
141{
142 register struct tty *tp;
3f3a34c3 143 register int unit, dh;
a18f326f 144 register struct device *addr;
3f3a34c3 145 register struct uba_dinfo *ui;
a18f326f
BJ
146 int s;
147
3f3a34c3
BJ
148 unit = minor(dev);
149 dh = unit >> 4;
150 if (unit >= NDH11*16 || (ui = dhinfo[dh])->ui_alive == 0) {
a18f326f
BJ
151 u.u_error = ENXIO;
152 return;
153 }
3f3a34c3
BJ
154 tp = &dh11[unit];
155 ui = dhinfo[dh];
156 addr = (struct device *)ui->ui_addr;
a18f326f
BJ
157 tp->t_addr = (caddr_t)addr;
158 tp->t_oproc = dhstart;
159 tp->t_iproc = NULL;
160 tp->t_state |= WOPEN;
161 s = spl6();
5aa9d5ea 162 if (dh_ubinfo[ui->ui_ubanum] == 0) {
d319892b 163 /* 512+ is a kludge to try to get around a hardware problem */
3f3a34c3 164 dh_ubinfo[ui->ui_ubanum] =
5aa9d5ea 165 uballoc(ui->ui_ubanum, (caddr_t)cfree,
3f3a34c3 166 512+NCLIST*sizeof(struct cblock), 0);
88d5b764
BJ
167 cbase[ui->ui_ubanum] = dh_ubinfo[ui->ui_ubanum]&0x3ffff;
168 }
169 if ((dhact&(1<<dh)) == 0) {
170 addr->un.dhcsr |= DH_IE;
171 addr->dhsilo = 16;
172 dhact |= (1<<dh);
a18f326f
BJ
173 }
174 splx(s);
a18f326f
BJ
175 if ((tp->t_state&ISOPEN) == 0) {
176 ttychars(tp);
87f51a66 177 if (tp->t_ispeed == 0) {
88d5b764
BJ
178 tp->t_ispeed = B300;
179 tp->t_ospeed = B300;
87f51a66
BJ
180 tp->t_flags = ODDP|EVENP|ECHO;
181 }
3f3a34c3 182 dhparam(unit);
a18f326f
BJ
183 }
184 if (tp->t_state&XCLUDE && u.u_uid!=0) {
185 u.u_error = EBUSY;
186 return;
187 }
188 dmopen(dev);
3f3a34c3 189 (*linesw[tp->t_line].l_open)(dev, tp);
a18f326f
BJ
190}
191
192/*
193 * Close a DH11 line.
194 */
195/*ARGSUSED*/
196dhclose(dev, flag)
3f3a34c3
BJ
197 dev_t dev;
198 int flag;
a18f326f
BJ
199{
200 register struct tty *tp;
3f3a34c3 201 register unit;
a18f326f 202
3f3a34c3
BJ
203 unit = minor(dev);
204 tp = &dh11[unit];
a18f326f 205 (*linesw[tp->t_line].l_close)(tp);
3f3a34c3 206 ((struct device *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
a18f326f 207 if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0)
88d5b764 208 dmctl(unit, DM_OFF, DMSET);
a18f326f
BJ
209 ttyclose(tp);
210}
211
212/*
213 * Read from a DH11 line.
214 */
215dhread(dev)
3f3a34c3 216 dev_t dev;
a18f326f 217{
3f3a34c3 218 register struct tty *tp;
a18f326f 219
3f3a34c3 220 tp = &dh11[minor(dev)];
a18f326f
BJ
221 (*linesw[tp->t_line].l_read)(tp);
222}
223
224/*
225 * write on a DH11 line
226 */
227dhwrite(dev)
3f3a34c3 228 dev_t dev;
a18f326f 229{
3f3a34c3 230 register struct tty *tp;
a18f326f 231
3f3a34c3 232 tp = &dh11[minor(dev)];
a18f326f
BJ
233 (*linesw[tp->t_line].l_write)(tp);
234}
235
236/*
237 * DH11 receiver interrupt.
238 */
3f3a34c3
BJ
239dhrint(dh)
240 int dh;
a18f326f
BJ
241{
242 register struct tty *tp;
3f3a34c3 243 register c;
a18f326f 244 register struct device *addr;
0e239190 245 register struct tty *tp0;
3f3a34c3 246 register struct uba_dinfo *ui;
5c6adb3e 247 int s;
a18f326f 248
3f3a34c3 249 ui = dhinfo[dh];
88d5b764
BJ
250 if (ui == 0) {
251 printf("stray dhrint %d\n", dh);
252 asm("halt");
253 return;
254 }
3f3a34c3
BJ
255 addr = (struct device *)ui->ui_addr;
256 tp0 = &dh11[dh*16];
88d5b764 257 while ((c = addr->dhrcr) < 0) { /* char. present */
0e239190 258 tp = tp0 + ((c>>8)&017);
3f3a34c3 259 if (tp >= &dh11[NDH11*16])
a18f326f
BJ
260 continue;
261 if((tp->t_state&ISOPEN)==0) {
262 wakeup((caddr_t)tp);
263 continue;
264 }
88d5b764 265 if (c&DH_PE)
a18f326f
BJ
266 if ((tp->t_flags&(EVENP|ODDP))==EVENP
267 || (tp->t_flags&(EVENP|ODDP))==ODDP )
268 continue;
88d5b764 269 if (c&DH_DO)
a18f326f 270 printf("O");
88d5b764 271 if (c&DH_FE) /* break */
a18f326f
BJ
272 if (tp->t_flags&RAW)
273 c = 0; /* null (for getty) */
274 else
1c17c385 275 c = tun.t_intrc;
5c6adb3e 276 if (tp->t_line == NETLDISC) {
0e239190 277 c &= 0177;
87f51a66 278 BKINPUT(c, tp);
0e239190 279 } else
0e239190 280 (*linesw[tp->t_line].l_rint)(c,tp);
a18f326f
BJ
281 }
282}
283
284/*
285 * stty/gtty for DH11
286 */
287/*ARGSUSED*/
288dhioctl(dev, cmd, addr, flag)
3f3a34c3 289 caddr_t addr;
a18f326f
BJ
290{
291 register struct tty *tp;
3f3a34c3 292 register unit = minor(dev);
a18f326f 293
3f3a34c3 294 tp = &dh11[unit];
038bbe6b
BJ
295 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
296 if (cmd==0)
297 return;
f4e18828 298 if (ttioctl(tp, cmd, addr, flag)) {
a18f326f 299 if (cmd==TIOCSETP||cmd==TIOCSETN)
3f3a34c3 300 dhparam(unit);
87f51a66
BJ
301 } else switch(cmd) {
302 case TIOCSBRK:
3f3a34c3 303 ((struct device *)(tp->t_addr))->dhbreak |= 1<<(unit&017);
87f51a66
BJ
304 break;
305 case TIOCCBRK:
3f3a34c3 306 ((struct device *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
87f51a66
BJ
307 break;
308 case TIOCSDTR:
88d5b764 309 dmctl(unit, DM_DTR|DM_RQS, DMBIS);
87f51a66
BJ
310 break;
311 case TIOCCDTR:
88d5b764 312 dmctl(unit, DM_DTR|DM_RQS, DMBIC);
87f51a66
BJ
313 break;
314 default:
a18f326f 315 u.u_error = ENOTTY;
87f51a66 316 }
a18f326f
BJ
317}
318
319/*
320 * Set parameters from open or stty into the DH hardware
321 * registers.
322 */
3f3a34c3
BJ
323dhparam(unit)
324 register int unit;
a18f326f
BJ
325{
326 register struct tty *tp;
327 register struct device *addr;
3f3a34c3 328 register int lpar;
0072a3c2 329 int s;
a18f326f 330
3f3a34c3 331 tp = &dh11[unit];
a18f326f 332 addr = (struct device *)tp->t_addr;
0072a3c2 333 s = spl5();
88d5b764 334 addr->un.dhcsrl = (unit&017) | DH_IE;
a18f326f
BJ
335 if ((tp->t_ispeed)==0) {
336 tp->t_state |= HUPCLS;
88d5b764 337 dmctl(unit, DM_OFF, DMSET);
a18f326f
BJ
338 return;
339 }
3f3a34c3 340 lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
a18f326f 341 if ((tp->t_ispeed) == 4) /* 134.5 baud */
3f3a34c3 342 lpar |= BITS6|PENABLE|HDUPLX;
131b2e17 343 else if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT))
3f3a34c3 344 lpar |= BITS8;
a18f326f 345 else
3f3a34c3 346 lpar |= BITS7|PENABLE;
a18f326f 347 if ((tp->t_flags&EVENP) == 0)
3f3a34c3 348 lpar |= OPAR;
a18f326f 349 if ((tp->t_ospeed) == 3) /* 110 baud */
3f3a34c3
BJ
350 lpar |= TWOSB;
351 addr->dhlpr = lpar;
0072a3c2 352 splx(s);
a18f326f
BJ
353}
354
355/*
356 * DH11 transmitter interrupt.
357 * Restart each line which used to be active but has
358 * terminated transmission since the last interrupt.
359 */
3f3a34c3
BJ
360dhxint(dh)
361 int dh;
a18f326f
BJ
362{
363 register struct tty *tp;
364 register struct device *addr;
a18f326f 365 short ttybit, bar, *sbar;
3f3a34c3
BJ
366 register struct uba_dinfo *ui;
367 register unit;
d3ebf5ee 368 int s;
a18f326f 369
3f3a34c3
BJ
370 ui = dhinfo[dh];
371 addr = (struct device *)ui->ui_addr;
88d5b764
BJ
372 if (addr->un.dhcsr & DH_NXM) {
373 addr->un.dhcsr |= DH_CNI;
374 printf("dh%d NXM\n", ui->ui_ctlr);
b4ec79ea 375 }
88d5b764 376 addr->un.dhcsr &= (short)~DH_TI;
3f3a34c3 377 sbar = &dhsar[dh];
a18f326f 378 bar = *sbar & ~addr->dhbar;
3f3a34c3
BJ
379 unit = dh * 16; ttybit = 1;
380 for(; bar; unit++, ttybit <<= 1) {
a18f326f
BJ
381 if(bar&ttybit) {
382 *sbar &= ~ttybit;
383 bar &= ~ttybit;
3f3a34c3 384 tp = &dh11[unit];
038bbe6b
BJ
385 tp->t_state &= ~BUSY;
386 if (tp->t_state&FLUSH)
387 tp->t_state &= ~FLUSH;
388 else {
88d5b764 389 addr->un.dhcsrl = (unit&017)|DH_IE;
293c7069 390 ndflush(&tp->t_outq,
88d5b764
BJ
391 /* SHOULD PASTE ON 16&17 BITS HERE */
392 addr->dhcar-
3f3a34c3 393 UBACVT(tp->t_outq.c_cf,ui->ui_ubanum));
a18f326f 394 }
038bbe6b
BJ
395 if (tp->t_line)
396 (*linesw[tp->t_line].l_start)(tp);
397 else
398 dhstart(tp);
a18f326f
BJ
399 }
400 }
401}
402
403/*
404 * Start (restart) transmission on the given DH11 line.
405 */
406dhstart(tp)
3f3a34c3 407 register struct tty *tp;
a18f326f
BJ
408{
409 register struct device *addr;
3f3a34c3
BJ
410 register int nch, dh, unit;
411 int s;
a18f326f
BJ
412
413 /*
414 * If it's currently active, or delaying,
415 * no need to do anything.
416 */
417 s = spl5();
3f3a34c3
BJ
418 unit = minor(tp->t_dev);
419 dh = unit >> 4;
a18f326f
BJ
420 addr = (struct device *)tp->t_addr;
421 if (tp->t_state&(TIMEOUT|BUSY|TTSTOP))
422 goto out;
3f3a34c3 423 if ((tp->t_state&ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) {
a18f326f
BJ
424 tp->t_state &= ~ASLEEP;
425 if (tp->t_chan)
87f51a66
BJ
426 mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
427 else
a18f326f
BJ
428 wakeup((caddr_t)&tp->t_outq);
429 }
a18f326f
BJ
430 if (tp->t_outq.c_cc == 0)
431 goto out;
3f3a34c3 432 if (tp->t_flags & RAW)
a18f326f 433 nch = ndqb(&tp->t_outq, 0);
3f3a34c3 434 else {
a18f326f
BJ
435 nch = ndqb(&tp->t_outq, 0200);
436 if (nch == 0) {
437 nch = getc(&tp->t_outq);
438 timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6);
439 tp->t_state |= TIMEOUT;
440 goto out;
441 }
442 }
a18f326f 443 if (nch) {
88d5b764
BJ
444 /* SHOULD PASTE ON BITS 16&17 HERE */
445 addr->un.dhcsrl = (unit&017)|DH_IE;
3f3a34c3
BJ
446 addr->dhcar = UBACVT(tp->t_outq.c_cf,
447 dhinfo[dh]->ui_ubanum);
a18f326f 448 addr->dhbcr = -nch;
3f3a34c3 449 nch = 1<<(unit&017);
a18f326f 450 addr->dhbar |= nch;
3f3a34c3 451 dhsar[dh] |= nch;
a18f326f
BJ
452 tp->t_state |= BUSY;
453 }
3f3a34c3 454out:
a18f326f
BJ
455 splx(s);
456}
457
a18f326f
BJ
458/*
459 * Stop output on a line.
a18f326f
BJ
460 */
461/*ARGSUSED*/
462dhstop(tp, flag)
463register struct tty *tp;
464{
038bbe6b 465 register struct device *addr;
3f3a34c3 466 register int unit, s;
a18f326f 467
038bbe6b 468 addr = (struct device *)tp->t_addr;
a18f326f 469 s = spl6();
038bbe6b 470 if (tp->t_state & BUSY) {
3f3a34c3 471 unit = minor(tp->t_dev);
88d5b764 472 addr->un.dhcsrl = (unit&017) | DH_IE;
a18f326f
BJ
473 if ((tp->t_state&TTSTOP)==0)
474 tp->t_state |= FLUSH;
038bbe6b
BJ
475 addr->dhbcr = -1;
476 }
a18f326f
BJ
477 splx(s);
478}
479
5c30d566
BJ
480/*
481 * Reset state of driver if UBA reset was necessary.
482 * Reset the csrl and lpr registers on open lines, and
483 * restart transmitters.
484 */
3f3a34c3 485dhreset(uban)
5c30d566 486{
3f3a34c3 487 register int dh, unit;
5c30d566 488 register struct tty *tp;
3f3a34c3 489 register struct uba_dinfo *ui;
5aa9d5ea 490 int i;
5c30d566 491
5aa9d5ea
RE
492 if (dh_ubinfo[uban] == 0)
493 return;
5c30d566 494 printf(" dh");
5aa9d5ea
RE
495 ubarelse(uban, &dh_ubinfo[uban]);
496 dh_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
497 512+NCLIST*sizeof (struct cblock), 0);
498 cbase[uban] = dh_ubinfo[uban]&0x3ffff;
3f3a34c3 499 dh = 0;
5aa9d5ea
RE
500 for (dh = 0; dh < NDH11; dh++) {
501 ui = dhinfo[dh];
502 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
503 continue;
88d5b764
BJ
504 ((struct device *)ui->ui_addr)->un.dhcsr |= DH_IE;
505 ((struct device *)ui->ui_addr)->dhsilo = 16;
5aa9d5ea
RE
506 unit = dh * 16;
507 for (i = 0; i < 16; i++) {
508 tp = &dh11[unit];
509 if (tp->t_state & (ISOPEN|WOPEN)) {
510 dhparam(unit);
88d5b764 511 dmctl(unit, DM_ON, DMSET);
5aa9d5ea
RE
512 tp->t_state &= ~BUSY;
513 dhstart(tp);
514 }
515 unit++;
0072a3c2
BJ
516 }
517 }
518 dhtimer();
5c30d566 519}
3f3a34c3 520
88d5b764
BJ
521dhtimer()
522{
523 register int dh;
524
525 for (dh = 0; dh < NDH11; dh++)
526 dhrint(dh);
527}
528
3f3a34c3 529#if DHDM
ea99d5bf
BJ
530#include "../dev/dhdm.c"
531#else
532#include "../dev/dhfdm.c"
533#endif
ae7f533a 534#endif