|
|
1.1 root 1: /* dh.c 4.3 11/13/80 */
2:
3: #include "../conf/dh.h"
4: #if NDH11 > 0
5: /*
6: * DH-11 driver
7: *
8: * Loaded with dhdm if there are DM-11's otherwise with dhfdm.
9: *
10: * NB: WE HAVEN'T TESTED dhdm CODE ON VAX.
11: */
12:
13: #include "../h/param.h"
14: #include "../h/conf.h"
15: #include "../h/dir.h"
16: #include "../h/user.h"
17: #include "../h/tty.h"
18: #include "../h/map.h"
19: #include "../h/pte.h"
20: #include "../h/uba.h"
21: #include "../h/bk.h"
22: #include "../h/clist.h"
23: #include "../h/mx.h"
24:
25: /*
26: * When running dz's using only SAE (silo alarm) on input
27: * it is necessary to call dzrint() at clock interrupt time.
28: * This is unsafe unless spl5()s in tty code are changed to
29: * spl6()s to block clock interrupts. Note that the dh driver
30: * currently in use works the same way as the dz, even though
31: * we could try to more intelligently manage its silo.
32: * Thus don't take this out if you have no dz's unless you
33: * change clock.c and dhtimer().
34: */
35: #define spl5 spl6
36:
37: #define UBACVT(x) (cbase + (short)((x)-(char *)cfree))
38:
39: struct tty dh11[NDH11];
40: int dhact;
41: int dhisilo;
42: int ndh11 = NDH11;
43: int dhstart();
44: int ttrstrt();
45: int dh_ubinfo;
46: int cbase;
47: int getcbase;
48:
49: /*
50: * Hardware control bits
51: */
52: #define BITS6 01
53: #define BITS7 02
54: #define BITS8 03
55: #define TWOSB 04
56: #define PENABLE 020
57: /* DEC manuals incorrectly say this bit causes generation of even parity. */
58: #define OPAR 040
59: #define HDUPLX 040000
60:
61: #define IENAB 030100
62: #define NXM 02000
63: #define CLRNXM 0400
64: #define PERROR 010000
65: #define FRERROR 020000
66: #define OVERRUN 040000
67: #define XINT 0100000
68: #define SSPEED 7 /* standard speed: 300 baud */
69:
70: /*
71: * DM control bits
72: */
73: #define TURNON 03 /* CD lead + line enable */
74: #define TURNOFF 01 /* line enable */
75: #define DTR 02 /* data terminal ready */
76: #define RQS 04 /* request to send */
77:
78: /*
79: * Software copy of last dhbar
80: */
81: short dhsar[(NDH11+15)/16];
82:
83: struct device
84: {
85: union {
86: short dhcsr;
87: char dhcsrl;
88: } un;
89: short dhnxch;
90: short dhlpr;
91: unsigned short dhcar;
92: short dhbcr;
93: unsigned short dhbar;
94: short dhbreak;
95: short dhsilo;
96: };
97:
98: /*
99: * Open a DH11 line.
100: */
101: /*ARGSUSED*/
102: dhopen(dev, flag)
103: {
104: register struct tty *tp;
105: register d;
106: register struct device *addr;
107: int s;
108:
109: d = minor(dev) & 0177;
110: if (d >= NDH11) {
111: u.u_error = ENXIO;
112: return;
113: }
114: tp = &dh11[d];
115: addr = DHADDR;
116: addr += d>>4;
117: tp->t_addr = (caddr_t)addr;
118: tp->t_oproc = dhstart;
119: tp->t_iproc = NULL;
120: tp->t_state |= WOPEN;
121: s = spl6();
122: if (!getcbase) {
123: getcbase++;
124: /* 512+ is a kludge to try to get around a hardware problem */
125: dh_ubinfo = uballoc((caddr_t)cfree, 512+NCLIST*sizeof(struct cblock), 0);
126: cbase = (short)dh_ubinfo;
127: }
128: splx(s);
129: addr->un.dhcsr |= IENAB;
130: dhact |= (1<<(d>>4));
131: if ((tp->t_state&ISOPEN) == 0) {
132: ttychars(tp);
133: if (tp->t_ispeed == 0) {
134: tp->t_ispeed = SSPEED;
135: tp->t_ospeed = SSPEED;
136: tp->t_flags = ODDP|EVENP|ECHO;
137: }
138: dhparam(d);
139: }
140: if (tp->t_state&XCLUDE && u.u_uid!=0) {
141: u.u_error = EBUSY;
142: return;
143: }
144: dmopen(dev);
145: (*linesw[tp->t_line].l_open)(dev,tp);
146: }
147:
148: /*
149: * Close a DH11 line.
150: */
151: /*ARGSUSED*/
152: dhclose(dev, flag)
153: dev_t dev;
154: int flag;
155: {
156: register struct tty *tp;
157: register d;
158:
159: d = minor(dev) & 0177;
160: tp = &dh11[d];
161: (*linesw[tp->t_line].l_close)(tp);
162: if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0)
163: dmctl(d, TURNOFF, DMSET);
164: ttyclose(tp);
165: }
166:
167: /*
168: * Read from a DH11 line.
169: */
170: dhread(dev)
171: {
172: register struct tty *tp;
173:
174: tp = &dh11[minor(dev) & 0177];
175: (*linesw[tp->t_line].l_read)(tp);
176: }
177:
178: /*
179: * write on a DH11 line
180: */
181: dhwrite(dev)
182: {
183: register struct tty *tp;
184:
185: tp = &dh11[minor(dev) & 0177];
186: (*linesw[tp->t_line].l_write)(tp);
187: }
188:
189: /*
190: * DH11 receiver interrupt.
191: */
192: dhrint(dev)
193: {
194: register struct tty *tp;
195: register short c;
196: register struct device *addr;
197: register struct tty *tp0;
198: int s;
199:
200: s = spl6(); /* see comment in clock.c */
201: addr = DHADDR;
202: addr += minor(dev) & 0177;
203: tp0 = &dh11[((minor(dev)&0177)<<4)];
204: while ((c = addr->dhnxch) < 0) { /* char. present */
205: tp = tp0 + ((c>>8)&017);
206: if (tp >= &dh11[NDH11])
207: continue;
208: if((tp->t_state&ISOPEN)==0) {
209: wakeup((caddr_t)tp);
210: continue;
211: }
212: if (c&PERROR)
213: if ((tp->t_flags&(EVENP|ODDP))==EVENP
214: || (tp->t_flags&(EVENP|ODDP))==ODDP )
215: continue;
216: if (c&OVERRUN)
217: printf("O");
218: if (c&FRERROR) /* break */
219: if (tp->t_flags&RAW)
220: c = 0; /* null (for getty) */
221: else
222: #ifdef IIASA
223: continue;
224: #else
225: c = tun.t_intrc;
226: #endif
227: if (tp->t_line == NETLDISC) {
228: c &= 0177;
229: BKINPUT(c, tp);
230: } else
231: (*linesw[tp->t_line].l_rint)(c,tp);
232: }
233: splx(s);
234: }
235:
236: /*
237: * stty/gtty for DH11
238: */
239: /*ARGSUSED*/
240: dhioctl(dev, cmd, addr, flag)
241: caddr_t addr;
242: {
243: register struct tty *tp;
244:
245: tp = &dh11[minor(dev) & 0177];
246: cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
247: if (cmd==0)
248: return;
249: if (ttioctl(cmd, tp, addr, dev, flag)) {
250: if (cmd==TIOCSETP||cmd==TIOCSETN)
251: dhparam(dev);
252: } else switch(cmd) {
253: case TIOCSBRK:
254: ((struct device *)(tp->t_addr))->dhbreak |= 1<<(minor(dev)&017);
255: break;
256: case TIOCCBRK:
257: ((struct device *)(tp->t_addr))->dhbreak &= ~(1<<(minor(dev)&017));
258: break;
259: case TIOCSDTR:
260: dmctl(minor(dev), DTR|RQS, DMBIS);
261: break;
262: case TIOCCDTR:
263: dmctl(minor(dev), DTR|RQS, DMBIC);
264: break;
265: default:
266: u.u_error = ENOTTY;
267: }
268: }
269:
270: /*
271: * Set parameters from open or stty into the DH hardware
272: * registers.
273: */
274: dhparam(dev)
275: {
276: register struct tty *tp;
277: register struct device *addr;
278: register d;
279: int s;
280:
281: d = minor(dev) & 0177;
282: tp = &dh11[d];
283: addr = (struct device *)tp->t_addr;
284: s = spl5();
285: addr->un.dhcsrl = (d&017) | IENAB;
286: /*
287: * Hang up line?
288: */
289: if ((tp->t_ispeed)==0) {
290: tp->t_state |= HUPCLS;
291: dmctl(d, TURNOFF, DMSET);
292: return;
293: }
294: d = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
295: if ((tp->t_ispeed) == 4) /* 134.5 baud */
296: d |= BITS6|PENABLE|HDUPLX;
297: else if (tp->t_flags&RAW)
298: d |= BITS8;
299: else
300: d |= BITS7|PENABLE;
301: if ((tp->t_flags&EVENP) == 0)
302: d |= OPAR;
303: if ((tp->t_ospeed) == 3) /* 110 baud */
304: d |= TWOSB;
305: addr->dhlpr = d;
306: splx(s);
307: }
308:
309: /*
310: * DH11 transmitter interrupt.
311: * Restart each line which used to be active but has
312: * terminated transmission since the last interrupt.
313: */
314: dhxint(dev)
315: {
316: register struct tty *tp;
317: register struct device *addr;
318: register d;
319: short ttybit, bar, *sbar;
320: int s;
321:
322: s = spl6(); /* block the clock */
323: d = minor(dev) & 0177;
324: addr = DHADDR + d;
325: addr->un.dhcsr &= (short)~XINT;
326: if (addr->un.dhcsr & NXM) {
327: addr->un.dhcsr |= CLRNXM;
328: printf("dh clr NXM\n");
329: }
330: sbar = &dhsar[d];
331: bar = *sbar & ~addr->dhbar;
332: d <<= 4; ttybit = 1;
333:
334: for(; bar; d++, ttybit <<= 1) {
335: if(bar&ttybit) {
336: *sbar &= ~ttybit;
337: bar &= ~ttybit;
338: tp = &dh11[d];
339: tp->t_state &= ~BUSY;
340: if (tp->t_state&FLUSH)
341: tp->t_state &= ~FLUSH;
342: else {
343: addr->un.dhcsrl = (d&017)|IENAB;
344: ndflush(&tp->t_outq,
345: (int)(short)addr->dhcar-UBACVT(tp->t_outq.c_cf));
346: }
347: if (tp->t_line)
348: (*linesw[tp->t_line].l_start)(tp);
349: else
350: dhstart(tp);
351: }
352: }
353: splx(s);
354: }
355:
356: /*
357: * Start (restart) transmission on the given DH11 line.
358: */
359: dhstart(tp)
360: register struct tty *tp;
361: {
362: register struct device *addr;
363: register short nch;
364: int s, d;
365:
366: /*
367: * If it's currently active, or delaying,
368: * no need to do anything.
369: */
370: s = spl5();
371: d = tp-dh11;
372: addr = (struct device *)tp->t_addr;
373: if (tp->t_state&(TIMEOUT|BUSY|TTSTOP))
374: goto out;
375:
376: /*
377: * If the writer was sleeping on output overflow,
378: * wake him when low tide is reached.
379: */
380: if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT(tp)) {
381: tp->t_state &= ~ASLEEP;
382: if (tp->t_chan)
383: mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
384: else
385: wakeup((caddr_t)&tp->t_outq);
386: }
387:
388: if (tp->t_outq.c_cc == 0)
389: goto out;
390:
391: /*
392: * Find number of characters to transfer.
393: */
394: if (tp->t_flags & RAW) {
395: nch = ndqb(&tp->t_outq, 0);
396: } else {
397: nch = ndqb(&tp->t_outq, 0200);
398: if (nch == 0) {
399: nch = getc(&tp->t_outq);
400: timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6);
401: tp->t_state |= TIMEOUT;
402: goto out;
403: }
404: }
405: /*
406: * If any characters were set up, start transmission;
407: */
408: if (nch) {
409: addr->un.dhcsrl = (d&017)|IENAB;
410: addr->dhcar = UBACVT(tp->t_outq.c_cf);
411: addr->dhbcr = -nch;
412: nch = 1<<(d&017);
413: addr->dhbar |= nch;
414: dhsar[d>>4] |= nch;
415: tp->t_state |= BUSY;
416: }
417: out:
418: splx(s);
419: }
420:
421: /*
422: * Stop output on a line.
423: * Assume call is made at spl6.
424: */
425: /*ARGSUSED*/
426: dhstop(tp, flag)
427: register struct tty *tp;
428: {
429: register struct device *addr;
430: register d, s;
431:
432: addr = (struct device *)tp->t_addr;
433: s = spl6();
434: if (tp->t_state & BUSY) {
435: d = minor(tp->t_dev);
436: addr->un.dhcsrl = (d&017) | IENAB;
437: if ((tp->t_state&TTSTOP)==0)
438: tp->t_state |= FLUSH;
439: addr->dhbcr = -1;
440: }
441: splx(s);
442: }
443:
444: int dhsilo = 16;
445: /*
446: * Silo control is fixed strategy
447: * here, paralleling only option available
448: * on DZ-11.
449: */
450: /*ARGSUSED*/
451: dhtimer()
452: {
453: register d;
454: register struct device *addr;
455:
456: addr = DHADDR; d = 0;
457: do {
458: if (dhact & (1<<d)) {
459: if ((dhisilo & (1<<d)) == 0) {
460: addr->dhsilo = dhsilo;
461: dhisilo |= 1<<d;
462: }
463: dhrint(d);
464: }
465: d++;
466: addr++;
467: } while (d < (NDH11+15)/16);
468: }
469:
470: /*
471: * Reset state of driver if UBA reset was necessary.
472: * Reset the csrl and lpr registers on open lines, and
473: * restart transmitters.
474: */
475: dhreset()
476: {
477: int d;
478: register struct tty *tp;
479: register struct device *addr;
480:
481: if (getcbase == 0)
482: return;
483: printf(" dh");
484: dhisilo = 0;
485: ubafree(dh_ubinfo);
486: dh_ubinfo = uballoc((caddr_t)cfree, NCLIST*sizeof (struct cblock), 0);
487: cbase = (short)dh_ubinfo;
488: d = 0;
489: do {
490: addr = DHADDR + d;
491: if (dhact & (1<<d))
492: addr->un.dhcsr |= IENAB;
493: d++;
494: } while (d < (NDH11+15)/16);
495: for (d = 0; d < NDH11; d++) {
496: tp = &dh11[d];
497: if (tp->t_state & (ISOPEN|WOPEN)) {
498: dhparam(d);
499: dmctl(d, TURNON, DMSET);
500: tp->t_state &= ~BUSY;
501: dhstart(tp);
502: }
503: }
504: dhtimer();
505: }
506: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.