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