|
|
1.1 root 1: /* dz.c 4.29 81/08/31 */
2:
3: #include "dz.h"
4: #if NDZ > 0
5: /*
6: * DZ-11 Driver
7: *
8: * This driver mimics dh.c; see it for explanation of common code.
9: */
10: #include "bk.h"
11: #include "../h/param.h"
12: #include "../h/systm.h"
13: #include "../h/tty.h"
14: #include "../h/dir.h"
15: #include "../h/user.h"
16: #include "../h/map.h"
17: #include "../h/pte.h"
18: #include "../h/buf.h"
19: #include "../h/vm.h"
20: #include "../h/ubavar.h"
21: #include "../h/conf.h"
22: #include "../h/pdma.h"
23: #include "../h/bk.h"
24: #include "../h/file.h"
25: #include "../h/mx.h"
26:
27: /*
28: * Driver information for auto-configuration stuff.
29: */
30: int dzprobe(), dzattach(), dzrint();
31: struct uba_device *dzinfo[NDZ];
32: u_short dzstd[] = { 0 };
33: struct uba_driver dzdriver =
34: { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
35:
36: #define NDZLINE (NDZ*8)
37:
38: /*
39: * Registers and bits
40: */
41:
42: /* Bits in dzlpr */
43: #define BITS7 020
44: #define BITS8 030
45: #define TWOSB 040
46: #define PENABLE 0100
47: #define OPAR 0200
48:
49: /* Bits in dzrbuf */
50: #define DZ_PE 010000
51: #define DZ_FE 020000
52: #define DZ_DO 040000
53:
54: /* Bits in dzcsr */
55: #define DZ_CLR 020 /* Reset dz */
56: #define DZ_MSE 040 /* Master Scan Enable */
57: #define DZ_RIE 0100 /* Receiver Interrupt Enable */
58: #define DZ_SAE 010000 /* Silo Alarm Enable */
59: #define DZ_TIE 040000 /* Transmit Interrupt Enable */
60: #define DZ_IEN (DZ_MSE|DZ_RIE|DZ_TIE|DZ_SAE)
61:
62: /* Flags for modem-control */
63: #define DZ_ON 1
64: #define DZ_OFF 0
65:
66: int dzstart(), dzxint(), dzdma();
67: int ttrstrt();
68: struct tty dz_tty[NDZLINE];
69: int dz_cnt = { NDZLINE };
70: int dzact;
71:
72: struct device {
73: short dzcsr; /* control-status register */
74: short dzrbuf; /* receiver buffer */
75: #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */
76: char dztcr; /* transmit control register */
77: char dzdtr; /* data terminal ready */
78: char dztbuf; /* transmit buffer */
79: char dzbrk; /* break control */
80: #define dzmsr dzbrk /* modem status register */
81: };
82: /*
83: * Software copy of dzbrk since it isn't readable
84: */
85: char dz_brk[NDZ];
86: char dzsoftCAR[NDZ];
87:
88: /*
89: * The dz doesn't interrupt on carrier transitions, so
90: * we have to use a timer to watch it.
91: */
92: char dz_timer; /* timer started? */
93:
94: /*
95: * Pdma structures for fast output code
96: */
97: struct pdma dzpdma[NDZLINE];
98:
99: char dz_speeds[] =
100: { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
101:
102: dzprobe(reg)
103: caddr_t reg;
104: {
105: register int br, cvec;
106: register struct device *dzaddr = (struct device *)reg;
107:
108: #ifdef lint
109: br = 0; cvec = br; br = cvec;
110: #endif
111: dzaddr->dzcsr = DZ_TIE|DZ_MSE;
112: dzaddr->dztcr = 1; /* enable any line */
113: DELAY(100000);
114: dzaddr->dzcsr = DZ_CLR; /* reset everything */
115: if (cvec && cvec != 0x200)
116: cvec -= 4;
117: return (1);
118: }
119:
120: dzattach(ui)
121: register struct uba_device *ui;
122: {
123: register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
124: register struct tty *tp = &dz_tty[ui->ui_unit*8];
125: register int cntr;
126: extern dzscan();
127:
128: for (cntr = 0; cntr < 8; cntr++) {
129: pdp->p_addr = (struct device *)ui->ui_addr;
130: pdp->p_arg = (int)tp;
131: pdp->p_fcn = dzxint;
132: pdp++, tp++;
133: }
134: dzsoftCAR[ui->ui_unit] = ui->ui_flags;
135: if (dz_timer == 0) {
136: dz_timer++;
137: timeout(dzscan, (caddr_t)0, hz);
138: }
139: }
140:
141: /*ARGSUSED*/
142: dzopen(dev, flag)
143: dev_t dev;
144: {
145: register struct tty *tp;
146: register int unit;
147:
148: unit = minor(dev);
149: if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
150: u.u_error = ENXIO;
151: return;
152: }
153: tp = &dz_tty[unit];
154: tp->t_addr = (caddr_t)&dzpdma[unit];
155: tp->t_oproc = dzstart;
156: tp->t_iproc = NULL;
157: tp->t_state |= WOPEN;
158: if ((tp->t_state & ISOPEN) == 0) {
159: ttychars(tp);
160: tp->t_ospeed = tp->t_ispeed = B300;
161: tp->t_flags = ODDP|EVENP|ECHO;
162: /* tp->t_state |= HUPCLS; */
163: dzparam(unit);
164: } else if (tp->t_state&XCLUDE && u.u_uid != 0) {
165: u.u_error = EBUSY;
166: return;
167: }
168: dzmodem(unit, DZ_ON);
169: (void) spl5();
170: while ((tp->t_state & CARR_ON) == 0) {
171: tp->t_state |= WOPEN;
172: sleep((caddr_t)&tp->t_rawq, TTIPRI);
173: }
174: (void) spl0();
175: (*linesw[tp->t_line].l_open)(dev, tp);
176: }
177:
178: /*ARGSUSED*/
179: dzclose(dev, flag)
180: dev_t dev;
181: {
182: register struct tty *tp;
183: register int unit;
184: int dz;
185:
186: unit = minor(dev);
187: dz = unit >> 3;
188: tp = &dz_tty[unit];
189: (*linesw[tp->t_line].l_close)(tp);
190: ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
191: (dz_brk[dz] &= ~(1 << (unit&07)));
192: if (tp->t_state & HUPCLS)
193: dzmodem(unit, DZ_OFF);
194: ttyclose(tp);
195: }
196:
197: dzread(dev)
198: dev_t dev;
199: {
200: register struct tty *tp;
201:
202: tp = &dz_tty[minor(dev)];
203: (*linesw[tp->t_line].l_read)(tp);
204: }
205:
206: dzwrite(dev)
207: dev_t dev;
208: {
209: register struct tty *tp;
210:
211: tp = &dz_tty[minor(dev)];
212: (*linesw[tp->t_line].l_write)(tp);
213: }
214:
215: /*ARGSUSED*/
216: dzrint(dz)
217: int dz;
218: {
219: register struct tty *tp;
220: register int c;
221: register struct device *dzaddr;
222: register struct tty *tp0;
223: register int unit;
224: int overrun = 0;
225:
226: if ((dzact & (1<<dz)) == 0)
227: return;
228: unit = dz * 8;
229: dzaddr = dzpdma[unit].p_addr;
230: tp0 = &dz_tty[unit];
231: while ((c = dzaddr->dzrbuf) < 0) { /* char present */
232: tp = tp0 + ((c>>8)&07);
233: if (tp >= &dz_tty[dz_cnt])
234: continue;
235: if ((tp->t_state & ISOPEN) == 0) {
236: wakeup((caddr_t)&tp->t_rawq);
237: continue;
238: }
239: if (c&DZ_FE)
240: if (tp->t_flags & RAW)
241: c = 0;
242: else
243: c = tun.t_intrc;
244: if (c&DZ_DO && overrun == 0) {
245: printf("dz%d: silo overflow\n", dz);
246: overrun = 1;
247: }
248: if (c&DZ_PE)
249: if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
250: || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
251: continue;
252: #if NBK > 0
253: if (tp->t_line == NETLDISC) {
254: c &= 0177;
255: BKINPUT(c, tp);
256: } else
257: #endif
258: (*linesw[tp->t_line].l_rint)(c, tp);
259: }
260: }
261:
262: /*ARGSUSED*/
263: dzioctl(dev, cmd, addr, flag)
264: dev_t dev;
265: caddr_t addr;
266: {
267: register struct tty *tp;
268: register int unit = minor(dev);
269: register int dz = unit >> 3;
270:
271: tp = &dz_tty[unit];
272: cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
273: if (cmd == 0)
274: return;
275: if (ttioctl(tp, cmd, addr, flag)) {
276: if (cmd==TIOCSETP || cmd==TIOCSETN)
277: dzparam(unit);
278: } else switch(cmd) {
279:
280: case TIOCSBRK:
281: ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
282: (dz_brk[dz] |= 1 << (unit&07));
283: break;
284: case TIOCCBRK:
285: ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
286: (dz_brk[dz] &= ~(1 << (unit&07)));
287: break;
288: case TIOCSDTR:
289: dzmodem(unit, DZ_ON);
290: break;
291: case TIOCCDTR:
292: dzmodem(unit, DZ_OFF);
293: break;
294: default:
295: u.u_error = ENOTTY;
296: }
297: }
298:
299: dzparam(unit)
300: register int unit;
301: {
302: register struct tty *tp;
303: register struct device *dzaddr;
304: register int lpr;
305:
306: tp = &dz_tty[unit];
307: dzaddr = dzpdma[unit].p_addr;
308: dzaddr->dzcsr = DZ_IEN;
309: dzact |= (1<<(unit>>3));
310: if (tp->t_ispeed == 0) {
311: dzmodem(unit, DZ_OFF); /* hang up line */
312: return;
313: }
314: lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
315: if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
316: lpr |= BITS8;
317: else
318: lpr |= (BITS7|PENABLE);
319: if ((tp->t_flags & EVENP) == 0)
320: lpr |= OPAR;
321: if (tp->t_ispeed == B110)
322: lpr |= TWOSB;
323: dzaddr->dzlpr = lpr;
324: }
325:
326: dzxint(tp)
327: register struct tty *tp;
328: {
329: register struct pdma *dp;
330: register s;
331:
332: s = spl5(); /* block pdma interrupts */
333: dp = (struct pdma *)tp->t_addr;
334: tp->t_state &= ~BUSY;
335: if (tp->t_state & FLUSH)
336: tp->t_state &= ~FLUSH;
337: else
338: ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
339: if (tp->t_line)
340: (*linesw[tp->t_line].l_start)(tp);
341: else
342: dzstart(tp);
343: if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
344: dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
345: splx(s);
346: }
347:
348: dzstart(tp)
349: register struct tty *tp;
350: {
351: register struct pdma *dp;
352: register struct device *dzaddr;
353: register int cc;
354: int s;
355:
356: dp = (struct pdma *)tp->t_addr;
357: dzaddr = dp->p_addr;
358: s = spl5();
359: if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
360: goto out;
361: if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
362: tp->t_state &= ~ASLEEP;
363: if (tp->t_chan)
364: mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
365: else
366: wakeup((caddr_t)&tp->t_outq);
367: }
368: if (tp->t_outq.c_cc == 0)
369: goto out;
370: if (tp->t_flags&RAW || tp->t_local&LLITOUT)
371: cc = ndqb(&tp->t_outq, 0);
372: else {
373: cc = ndqb(&tp->t_outq, 0200);
374: if (cc == 0) {
375: cc = getc(&tp->t_outq);
376: timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
377: tp->t_state |= TIMEOUT;
378: goto out;
379: }
380: }
381: tp->t_state |= BUSY;
382: dp->p_end = dp->p_mem = tp->t_outq.c_cf;
383: dp->p_end += cc;
384: dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */
385: out:
386: splx(s);
387: }
388:
389: /*
390: * Stop output on a line.
391: */
392: /*ARGSUSED*/
393: dzstop(tp, flag)
394: register struct tty *tp;
395: {
396: register struct pdma *dp;
397: register int s;
398:
399: dp = (struct pdma *)tp->t_addr;
400: s = spl5();
401: if (tp->t_state & BUSY) {
402: dp->p_end = dp->p_mem;
403: if ((tp->t_state&TTSTOP)==0)
404: tp->t_state |= FLUSH;
405: }
406: splx(s);
407: }
408:
409: dzmodem(unit, flag)
410: register int unit;
411: {
412: register struct device *dzaddr;
413: register char bit;
414:
415: dzaddr = dzpdma[unit].p_addr;
416: bit = 1<<(unit&07);
417: if (flag == DZ_OFF)
418: dzaddr->dzdtr &= ~bit;
419: else
420: dzaddr->dzdtr |= bit;
421: }
422:
423: dzscan()
424: {
425: register i;
426: register struct device *dzaddr;
427: register bit;
428: register struct tty *tp;
429:
430: for (i = 0; i < dz_cnt ; i++) {
431: dzaddr = dzpdma[i].p_addr;
432: if (dzaddr == 0)
433: continue;
434: tp = &dz_tty[i];
435: bit = 1<<(i&07);
436: if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) {
437: /* carrier present */
438: if ((tp->t_state & CARR_ON) == 0) {
439: wakeup((caddr_t)&tp->t_rawq);
440: tp->t_state |= CARR_ON;
441: }
442: } else {
443: if ((tp->t_state&CARR_ON) &&
444: (tp->t_local&LNOHANG)==0) {
445: /* carrier lost */
446: if (tp->t_state&ISOPEN) {
447: gsignal(tp->t_pgrp, SIGHUP);
448: gsignal(tp->t_pgrp, SIGCONT);
449: dzaddr->dzdtr &= ~bit;
450: flushtty(tp, FREAD|FWRITE);
451: }
452: tp->t_state &= ~CARR_ON;
453: }
454: }
455: }
456: timeout(dzscan, (caddr_t)0, 2*hz);
457: }
458:
459: dztimer()
460: {
461: int dz;
462:
463: for (dz = 0; dz < NDZ; dz++)
464: dzrint(dz);
465: }
466:
467: /*
468: * Reset state of driver if UBA reset was necessary.
469: * Reset parameters and restart transmission on open lines.
470: */
471: dzreset(uban)
472: int uban;
473: {
474: register int unit;
475: register struct tty *tp;
476: register struct uba_device *ui;
477:
478: for (unit = 0; unit < NDZLINE; unit++) {
479: ui = dzinfo[unit >> 3];
480: if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
481: continue;
482: if (unit%8 == 0)
483: printf(" dz%d", unit>>3);
484: tp = &dz_tty[unit];
485: if (tp->t_state & (ISOPEN|WOPEN)) {
486: dzparam(unit);
487: dzmodem(unit, DZ_ON);
488: tp->t_state &= ~BUSY;
489: dzstart(tp);
490: }
491: }
492: dztimer();
493: }
494: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.