|
|
1.1 root 1: /* dh.c 2.2 2/18/80 */
2:
3: /*
4: * DH-11 driver
5: * This driver calls on the DHDM driver.
6: * If the DH has no DM11-BB, then the latter will
7: * be fake. To insure loading of the correct DM code,
8: * lib2 should have dhdm.o, dh.o and dhfdm.o in that order.
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"
18: #include "../h/uba.h"
19:
20: #define q3 tp->t_outq
21: #define DHADDR ((struct device *)(UBA0_DEV + 0160020))
22: #define NDH11 16 /* number of lines */
23: #define UBACVT(x) (cbase + (short)((x)-(char *)cfree))
24:
25: struct cblock {
26: struct cblock *c_next;
27: char c_info[CBSIZE];
28: };
29:
30: struct tty dh11[NDH11];
31: short dhcc[NDH11];
32: int dhchars[(NDH11+15)/16];
33: int ndh11 = NDH11;
34: int dhstart();
35: int ttrstrt();
36: int cbase;
37: extern struct cblock cfree[];
38:
39: /*
40: * Hardware control bits
41: */
42: #define BITS6 01
43: #define BITS7 02
44: #define BITS8 03
45: #define TWOSB 04
46: #define PENABLE 020
47: /* DEC manuals incorrectly say this bit causes generation of even parity. */
48: #define OPAR 040
49: #define HDUPLX 040000
50:
51: #define IENAB 030100
52: #define PERROR 010000
53: #define FRERROR 020000
54: #define OVERRUN 040000
55: #define XINT 0100000
56: #define SSPEED 7 /* standard speed: 300 baud */
57: #define NSILO 16
58: #define DHTIME 6
59: extern int dhtimer();
60:
61: /*
62: * DM control bits
63: */
64: #define TURNON 03 /* CD lead + line enable */
65: #define TURNOFF 01 /* line enable */
66: #define RQS 04 /* request to send */
67:
68: /*
69: * Software copy of last dhbar
70: */
71: short dhsar[(NDH11+15)/16];
72:
73: struct device
74: {
75: union {
76: short dhcsr;
77: char dhcsrl;
78: } un;
79: short dhnxch;
80: short dhlpr;
81: unsigned short dhcar;
82: short dhbcr;
83: unsigned short dhbar;
84: short dhbreak;
85: short dhsilo;
86: };
87:
88: /*
89: * Open a DH11 line.
90: */
91: dhopen(dev, flag)
92: {
93: register struct tty *tp;
94: register d;
95: register struct device *addr;
96: static timer_on;
97: int s;
98:
99: d = minor(dev) & 0177;
100: if (d >= NDH11) {
101: u.u_error = ENXIO;
102: return;
103: }
104: tp = &dh11[d];
105: addr = DHADDR;
106: addr += d>>4;
107: tp->t_addr = (caddr_t)addr;
108: tp->t_oproc = dhstart;
109: tp->t_iproc = NULL;
110: tp->t_state |= WOPEN;
111: s = spl6();
112: if (!timer_on) {
113: timer_on++;
114: timeout(dhtimer, (caddr_t)0, DHTIME);
115: cbase = (short)uballoc(cfree, NCLIST*sizeof(struct cblock), 0);
116: }
117: splx(s);
118: addr->un.dhcsr |= IENAB;
119: if ((tp->t_state&ISOPEN) == 0) {
120: ttychars(tp);
121: tp->t_ispeed = SSPEED;
122: tp->t_ospeed = SSPEED;
123: tp->t_flags = ODDP|EVENP|ECHO;
124: dhparam(d);
125: }
126: if (tp->t_state&XCLUDE && u.u_uid!=0) {
127: u.u_error = EBUSY;
128: return;
129: }
130: dmopen(dev);
131: (*linesw[tp->t_line].l_open)(dev,tp);
132: }
133:
134: /*
135: * Close a DH11 line.
136: */
137: dhclose(dev, flag)
138: dev_t dev;
139: int flag;
140: {
141: register struct tty *tp;
142: register d;
143:
144: d = minor(dev) & 0177;
145: tp = &dh11[d];
146: (*linesw[tp->t_line].l_close)(tp);
147: if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0)
148: dmctl(d, TURNOFF);
149: ttyclose(tp);
150: }
151:
152: /*
153: * Read from a DH11 line.
154: */
155: dhread(dev)
156: {
157: register struct tty *tp;
158:
159: tp = &dh11[minor(dev) & 0177];
160: (*linesw[tp->t_line].l_read)(tp);
161: }
162:
163: /*
164: * write on a DH11 line
165: */
166: dhwrite(dev)
167: {
168: register struct tty *tp;
169:
170: tp = &dh11[minor(dev) & 0177];
171: (*linesw[tp->t_line].l_write)(tp);
172: }
173:
174: /*
175: * DH11 receiver interrupt.
176: */
177: dhrint(dev)
178: {
179: register struct tty *tp;
180: register short c;
181: register struct device *addr;
182:
183: addr = DHADDR;
184: addr += minor(dev) & 0177;
185: while ((c = addr->dhnxch) < 0) { /* char. present */
186: tp = &dh11[((minor(dev)&0177)<<4) + ((c>>8)&017)];
187: dhchars[minor(dev)&0177]++;
188: if (tp >= &dh11[NDH11])
189: continue;
190: if((tp->t_state&ISOPEN)==0) {
191: wakeup((caddr_t)tp);
192: continue;
193: }
194: if (c&PERROR)
195: if ((tp->t_flags&(EVENP|ODDP))==EVENP
196: || (tp->t_flags&(EVENP|ODDP))==ODDP )
197: continue;
198: if (c&OVERRUN)
199: printf("O");
200: if (c&FRERROR) /* break */
201: if (tp->t_flags&RAW)
202: c = 0; /* null (for getty) */
203: else
204: c = 0177; /* DEL (intr) */
205: (*linesw[tp->t_line].l_rint)(c,tp);
206: }
207: }
208:
209: /*
210: * stty/gtty for DH11
211: */
212: dhioctl(dev, cmd, addr, flag)
213: caddr_t addr;
214: {
215: register struct tty *tp;
216:
217: tp = &dh11[minor(dev) & 0177];
218: if (ttioccomm(cmd, tp, addr, dev)) {
219: if (cmd==TIOCSETP||cmd==TIOCSETN)
220: dhparam(dev);
221: } else if (cmd==TIOCSBRK) {
222: /* send a break */
223: register int linebit = 1 << (dev&017);
224: extern dhunbrk();
225:
226: wflushtty(tp);
227: spl5();
228: ((struct device *)tp->t_addr)->dhbreak |= linebit;
229: tp->t_state |= TIMEOUT;
230: timeout(dhunbrk, (caddr_t)tp, 25); /* 300-500 ms */
231: while (((struct device *)tp->t_addr)->dhbreak & linebit)
232: sleep((caddr_t)&tp->t_rawq, TTIPRI);
233: tp->t_state &= ~TIMEOUT;
234: spl0();
235: flushtty(tp);
236: return;
237: } else
238: u.u_error = ENOTTY;
239: }
240:
241: dhunbrk(tp)
242: register struct tty *tp;
243: {
244:
245: ((struct device *)tp->t_addr)->dhbreak &= ~ (1 << (minor(tp->t_dev)&017));
246: wakeup((caddr_t)&tp->t_rawq);
247: }
248:
249: /*
250: * Set parameters from open or stty into the DH hardware
251: * registers.
252: */
253: dhparam(dev)
254: {
255: register struct tty *tp;
256: register struct device *addr;
257: register d;
258:
259: d = minor(dev) & 0177;
260: tp = &dh11[d];
261: addr = (struct device *)tp->t_addr;
262: spl5();
263: addr->un.dhcsrl = (d&017) | IENAB;
264: /*
265: * Hang up line?
266: */
267: if ((tp->t_ispeed)==0) {
268: tp->t_state |= HUPCLS;
269: dmctl(d, TURNOFF);
270: return;
271: }
272: d = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
273: if ((tp->t_ispeed) == 4) /* 134.5 baud */
274: d |= BITS6|PENABLE|HDUPLX;
275: else if (tp->t_flags&RAW)
276: d |= BITS8;
277: else
278: d |= BITS7|PENABLE;
279: if ((tp->t_flags&EVENP) == 0)
280: d |= OPAR;
281: if ((tp->t_ospeed) == 3) /* 110 baud */
282: d |= TWOSB;
283: addr->dhlpr = d;
284: spl0();
285: }
286:
287: /*
288: * DH11 transmitter interrupt.
289: * Restart each line which used to be active but has
290: * terminated transmission since the last interrupt.
291: */
292: dhxint(dev)
293: {
294: register struct tty *tp;
295: register struct device *addr;
296: register d;
297: short ttybit, bar, *sbar;
298:
299: d = minor(dev) & 0177;
300: addr = DHADDR + d;
301: addr->un.dhcsr &= (short)~XINT;
302: sbar = &dhsar[d];
303: bar = *sbar & ~addr->dhbar;
304: d <<= 4; ttybit = 1;
305:
306: for(; bar; d++, ttybit <<= 1) {
307: if(bar&ttybit) {
308: *sbar &= ~ttybit;
309: bar &= ~ttybit;
310: tp = &dh11[d];
311: if (tp->t_line) {
312: (*linesw[tp->t_line].l_start)(tp);
313: } else {
314: addr->un.dhcsrl = (d&017)|IENAB;
315: if (tp->t_state&FLUSH)
316: tp->t_state &= ~FLUSH;
317: else {
318: ndflush(&q3, dhcc[d]);
319: }
320: tp->t_state &= ~BUSY;
321: dhstart(tp);
322: }
323: }
324: }
325: }
326:
327: /*
328: * Start (restart) transmission on the given DH11 line.
329: */
330: dhstart(tp)
331: register struct tty *tp;
332: {
333: register struct device *addr;
334: register short nch;
335: int s, d;
336:
337: /*
338: * If it's currently active, or delaying,
339: * no need to do anything.
340: */
341: s = spl5();
342: d = tp-dh11;
343: addr = (struct device *)tp->t_addr;
344: if (tp->t_state&(TIMEOUT|BUSY|TTSTOP))
345: goto out;
346:
347:
348: /*
349: * If the writer was sleeping on output overflow,
350: * wake him when low tide is reached.
351: */
352: if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT) {
353: tp->t_state &= ~ASLEEP;
354: if (tp->t_chan)
355: mcstart(tp->t_chan, (caddr_t)&tp->t_outq); else
356: wakeup((caddr_t)&tp->t_outq);
357: }
358:
359: if (tp->t_outq.c_cc == 0)
360: goto out;
361:
362:
363:
364: /*
365: * Find number of characters to transfer.
366: */
367: if (tp->t_flags & RAW) {
368: nch = ndqb(&tp->t_outq, 0);
369: } else {
370: nch = ndqb(&tp->t_outq, 0200);
371: if (nch == 0) {
372: nch = getc(&tp->t_outq);
373: timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6);
374: tp->t_state |= TIMEOUT;
375: goto out;
376: }
377: }
378: /*
379: * If any characters were set up, start transmission;
380: */
381: if (nch) {
382: addr->un.dhcsrl = (d&017)|IENAB;
383: addr->dhcar = UBACVT(tp->t_outq.c_cf);
384: addr->dhbcr = -nch;
385: dhcc[d] = nch;
386: nch = 1<<(d&017);
387: addr->dhbar |= nch;
388: dhsar[d>>4] |= nch;
389: tp->t_state |= BUSY;
390: }
391: out:
392: splx(s);
393: }
394:
395:
396: /*
397: * Stop output on a line.
398: * Assume call is made at spl6.
399: */
400: dhstop(tp, flag)
401: register struct tty *tp;
402: {
403: register struct device *addr;
404: register d, s;
405:
406: addr = (struct device *)tp->t_addr;
407: s = spl6();
408: if (tp->t_state & BUSY) {
409: /*
410: d = minor(tp->t_dev);
411: addr->un.dhcsrl = (d&017) | IENAB;
412: */
413: if ((tp->t_state&TTSTOP)==0) {
414: tp->t_state |= FLUSH;
415: }
416: /*
417: addr->dhbcr = -1;
418: */
419: }
420: splx(s);
421: }
422:
423: dhtimer(dev)
424: {
425: register d,cc;
426: register struct device *addr;
427:
428: addr = DHADDR; d = 0;
429: do {
430: cc = dhchars[d];
431: dhchars[d] = 0;
432: if (cc > 50)
433: cc = 32; else
434: if (cc > 16)
435: cc = 16; else
436: cc = 0;
437: addr->dhsilo = cc;
438: addr += 1;
439: dhrint(d++);
440: } while (d < (NDH11+15)/16);
441: timeout(dhtimer, (caddr_t)0, DHTIME);
442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.