|
|
1.1 root 1: /* dz.c 6.1 83/07/29 */
2:
3: #include "dz.h"
4: #if NDZ > 0
5: /*
6: * DZ-11/DZ-32 Driver
7: *
8: * This driver mimics dh.c; see it for explanation of common code.
9: */
10: #include "bk.h"
11:
12: #include "../machine/pte.h"
13:
14: #include "../h/param.h"
15: #include "../h/systm.h"
16: #include "../h/ioctl.h"
17: #include "../h/tty.h"
18: #include "../h/dir.h"
19: #include "../h/user.h"
20: #include "../h/proc.h"
21: #include "../h/map.h"
22: #include "../h/buf.h"
23: #include "../h/vm.h"
24: #include "../h/conf.h"
25: #include "../h/bk.h"
26: #include "../h/file.h"
27: #include "../h/uio.h"
28: #include "../h/kernel.h"
29:
30: #include "../vaxuba/pdma.h"
31: #include "../vaxuba/ubavar.h"
32: #include "../vaxuba/dzreg.h"
33:
34: /*
35: * Driver information for auto-configuration stuff.
36: */
37: int dzprobe(), dzattach(), dzrint();
38: struct uba_device *dzinfo[NDZ];
39: u_short dzstd[] = { 0 };
40: struct uba_driver dzdriver =
41: { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
42:
43: #define NDZLINE (NDZ*8)
44:
45: int dzstart(), dzxint(), dzdma();
46: int ttrstrt();
47: struct tty dz_tty[NDZLINE];
48: int dz_cnt = { NDZLINE };
49: int dzact;
50:
51: #define dzwait(x) while (((x)->dzlcs & DZ_ACK) == 0)
52:
53: /*
54: * Software copy of dzbrk since it isn't readable
55: */
56: char dz_brk[NDZ];
57: char dzsoftCAR[NDZ];
58: char dz_lnen[NDZ]; /* saved line enable bits for DZ32 */
59:
60: /*
61: * The dz11 doesn't interrupt on carrier transitions, so
62: * we have to use a timer to watch it.
63: */
64: char dz_timer; /* timer started? */
65:
66: /*
67: * Pdma structures for fast output code
68: */
69: struct pdma dzpdma[NDZLINE];
70:
71: char dz_speeds[] =
72: { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 };
73:
74: #ifndef PORTSELECTOR
75: #define ISPEED B300
76: #define IFLAGS (EVENP|ODDP|ECHO)
77: #else
78: #define ISPEED B4800
79: #define IFLAGS (EVENP|ODDP)
80: #endif
81:
82: dzprobe(reg)
83: caddr_t reg;
84: {
85: register int br, cvec;
86: register struct dzdevice *dzaddr = (struct dzdevice *)reg;
87:
88: #ifdef lint
89: br = 0; cvec = br; br = cvec;
90: dzrint(0); dzxint((struct tty *)0);
91: #endif
92: dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
93: if (dzaddr->dzcsr & DZ_32)
94: dzaddr->dzlnen = 1;
95: else
96: dzaddr->dztcr = 1; /* enable any line */
97: DELAY(100000);
98: dzaddr->dzcsr = DZ_CLR|DZ_32; /* reset everything */
99: if (cvec && cvec != 0x200)
100: cvec -= 4;
101: return (sizeof (struct dzdevice));
102: }
103:
104: dzattach(ui)
105: register struct uba_device *ui;
106: {
107: register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
108: register struct tty *tp = &dz_tty[ui->ui_unit*8];
109: register int cntr;
110: extern dzscan();
111:
112: for (cntr = 0; cntr < 8; cntr++) {
113: pdp->p_addr = (struct dzdevice *)ui->ui_addr;
114: pdp->p_arg = (int)tp;
115: pdp->p_fcn = dzxint;
116: pdp++, tp++;
117: }
118: dzsoftCAR[ui->ui_unit] = ui->ui_flags;
119: if (dz_timer == 0) {
120: dz_timer++;
121: timeout(dzscan, (caddr_t)0, hz);
122: }
123: }
124:
125: /*ARGSUSED*/
126: dzopen(dev, flag)
127: dev_t dev;
128: {
129: register struct tty *tp;
130: register int unit;
131:
132: unit = minor(dev);
133: if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
134: return (ENXIO);
135: tp = &dz_tty[unit];
136: tp->t_addr = (caddr_t)&dzpdma[unit];
137: tp->t_oproc = dzstart;
138: tp->t_state |= TS_WOPEN;
139: if ((tp->t_state & TS_ISOPEN) == 0) {
140: ttychars(tp);
141: tp->t_ospeed = tp->t_ispeed = ISPEED;
142: tp->t_flags = IFLAGS;
143: /* tp->t_state |= TS_HUPCLS; */
144: dzparam(unit);
145: } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
146: return (EBUSY);
147: (void) dzmctl(dev, DZ_ON, DMSET);
148: (void) spl5();
149: while ((tp->t_state & TS_CARR_ON) == 0) {
150: tp->t_state |= TS_WOPEN;
151: sleep((caddr_t)&tp->t_rawq, TTIPRI);
152: }
153: (void) spl0();
154: return ((*linesw[tp->t_line].l_open)(dev, tp));
155: }
156:
157: /*ARGSUSED*/
158: dzclose(dev, flag)
159: dev_t dev;
160: {
161: register struct tty *tp;
162: register int unit;
163: register struct dzdevice *dzaddr;
164: int dz;
165:
166: unit = minor(dev);
167: dz = unit >> 3;
168: tp = &dz_tty[unit];
169: (*linesw[tp->t_line].l_close)(tp);
170: dzaddr = dzpdma[unit].p_addr;
171: if (dzaddr->dzcsr&DZ_32)
172: (void) dzmctl(dev, DZ_BRK, DMBIC);
173: else
174: dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
175: if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0)
176: (void) dzmctl(dev, DZ_OFF, DMSET);
177: ttyclose(tp);
178: }
179:
180: dzread(dev, uio)
181: dev_t dev;
182: struct uio *uio;
183: {
184: register struct tty *tp;
185:
186: tp = &dz_tty[minor(dev)];
187: return ((*linesw[tp->t_line].l_read)(tp, uio));
188: }
189:
190: dzwrite(dev, uio)
191: dev_t dev;
192: struct uio *uio;
193: {
194: register struct tty *tp;
195:
196: tp = &dz_tty[minor(dev)];
197: return ((*linesw[tp->t_line].l_write)(tp, uio));
198: }
199:
200: /*ARGSUSED*/
201: dzrint(dz)
202: int dz;
203: {
204: register struct tty *tp;
205: register int c;
206: register struct dzdevice *dzaddr;
207: register struct tty *tp0;
208: register int unit;
209: int overrun = 0;
210:
211: if ((dzact & (1<<dz)) == 0)
212: return;
213: unit = dz * 8;
214: dzaddr = dzpdma[unit].p_addr;
215: tp0 = &dz_tty[unit];
216: dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE); /* the manual says this song */
217: dzaddr->dzcsr |= DZ_RIE|DZ_MIE; /* and dance is necessary */
218: while (dzaddr->dzcsr & DZ_MSC) { /* DZ32 modem change interrupt */
219: c = dzaddr->dzmtsr;
220: tp = tp0 + (c&7);
221: if (tp >= &dz_tty[dz_cnt])
222: break;
223: dzaddr->dzlcs = c&7; /* get status of modem lines */
224: dzwait(dzaddr); /* wait for them */
225: if (c & DZ_CD) /* carrier status change? */
226: if (dzaddr->dzlcs & DZ_CD) { /* carrier up? */
227: if ((tp->t_state&TS_CARR_ON) == 0) {
228: wakeup((caddr_t)&tp->t_rawq);
229: tp->t_state |= TS_CARR_ON;
230: }
231: } else { /* no carrier */
232: if (tp->t_state&TS_CARR_ON) {
233: gsignal(tp->t_pgrp, SIGHUP);
234: gsignal(tp->t_pgrp, SIGCONT);
235: dzaddr->dzlcs = DZ_ACK|(c&7);
236: ttyflush(tp, FREAD|FWRITE);
237: }
238: tp->t_state &= ~TS_CARR_ON;
239: }
240: }
241: while ((c = dzaddr->dzrbuf) < 0) { /* char present */
242: tp = tp0 + ((c>>8)&07);
243: if (tp >= &dz_tty[dz_cnt])
244: continue;
245: if ((tp->t_state & TS_ISOPEN) == 0) {
246: wakeup((caddr_t)&tp->t_rawq);
247: #ifdef PORTSELECTOR
248: if ((tp->t_state&TS_WOPEN) == 0)
249: #endif
250: continue;
251: }
252: if (c&DZ_FE)
253: if (tp->t_flags & RAW)
254: c = 0;
255: else
256: c = tp->t_intrc;
257: if (c&DZ_DO && overrun == 0) {
258: /* printf("dz%d,%d: silo overflow\n", dz, (c>>8)&7); */
259: overrun = 1;
260: }
261: if (c&DZ_PE)
262: if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
263: || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
264: continue;
265: #if NBK > 0
266: if (tp->t_line == NETLDISC) {
267: c &= 0177;
268: BKINPUT(c, tp);
269: } else
270: #endif
271: (*linesw[tp->t_line].l_rint)(c, tp);
272: }
273: }
274:
275: /*ARGSUSED*/
276: dzioctl(dev, cmd, data, flag)
277: dev_t dev;
278: caddr_t data;
279: {
280: register struct tty *tp;
281: register int unit = minor(dev);
282: register int dz = unit >> 3;
283: register struct dzdevice *dzaddr;
284: int error;
285:
286: tp = &dz_tty[unit];
287: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
288: if (error >= 0)
289: return (error);
290: error = ttioctl(tp, cmd, data, flag);
291: if (error >= 0) {
292: if (cmd == TIOCSETP || cmd == TIOCSETN)
293: dzparam(unit);
294: return (error);
295: }
296: switch (cmd) {
297:
298: case TIOCSBRK:
299: dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
300: if (dzaddr->dzcsr&DZ_32)
301: (void) dzmctl(dev, DZ_BRK, DMBIS);
302: else
303: dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
304: break;
305:
306: case TIOCCBRK:
307: dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
308: if (dzaddr->dzcsr&DZ_32)
309: (void) dzmctl(dev, DZ_BRK, DMBIC);
310: else
311: dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
312: break;
313:
314: case TIOCSDTR:
315: (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
316: break;
317:
318: case TIOCCDTR:
319: (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
320: break;
321:
322: case TIOCMSET:
323: (void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
324: break;
325:
326: case TIOCMBIS:
327: (void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
328: break;
329:
330: case TIOCMBIC:
331: (void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
332: break;
333:
334: case TIOCMGET:
335: *(int *)data = dztodm(dzmctl(dev, 0, DMGET));
336: break;
337:
338: default:
339: return (ENOTTY);
340: }
341: return (0);
342: }
343:
344: dmtodz(bits)
345: register int bits;
346: {
347: register int b;
348:
349: b = (bits >>1) & 0370;
350: if (bits & DML_ST) b |= DZ_ST;
351: if (bits & DML_RTS) b |= DZ_RTS;
352: if (bits & DML_DTR) b |= DZ_DTR;
353: if (bits & DML_LE) b |= DZ_LE;
354: return(b);
355: }
356:
357: dztodm(bits)
358: register int bits;
359: {
360: register int b;
361:
362: b = (bits << 1) & 0360;
363: if (bits & DZ_DSR) b |= DML_DSR;
364: if (bits & DZ_DTR) b |= DML_DTR;
365: if (bits & DZ_ST) b |= DML_ST;
366: if (bits & DZ_RTS) b |= DML_RTS;
367: return(b);
368: }
369:
370: dzparam(unit)
371: register int unit;
372: {
373: register struct tty *tp;
374: register struct dzdevice *dzaddr;
375: register int lpr;
376:
377: tp = &dz_tty[unit];
378: dzaddr = dzpdma[unit].p_addr;
379: dzaddr->dzcsr = DZ_IEN;
380: dzact |= (1<<(unit>>3));
381: if (tp->t_ispeed == 0) {
382: (void) dzmctl(unit, DZ_OFF, DMSET); /* hang up line */
383: return;
384: }
385: lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
386: if (tp->t_flags & (RAW|LITOUT))
387: lpr |= BITS8;
388: else
389: lpr |= (BITS7|PENABLE);
390: if ((tp->t_flags & EVENP) == 0)
391: lpr |= OPAR;
392: if (tp->t_ispeed == B110)
393: lpr |= TWOSB;
394: dzaddr->dzlpr = lpr;
395: }
396:
397: dzxint(tp)
398: register struct tty *tp;
399: {
400: register struct pdma *dp;
401: register s, dz, unit;
402:
403: s = spl5(); /* block pdma interrupts */
404: dp = (struct pdma *)tp->t_addr;
405: tp->t_state &= ~TS_BUSY;
406: if (tp->t_state & TS_FLUSH)
407: tp->t_state &= ~TS_FLUSH;
408: else {
409: ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
410: dp->p_end = dp->p_mem = tp->t_outq.c_cf;
411: }
412: if (tp->t_line)
413: (*linesw[tp->t_line].l_start)(tp);
414: else
415: dzstart(tp);
416: dz = minor(tp->t_dev) >> 3;
417: unit = minor(tp->t_dev) & 7;
418: if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
419: if (dp->p_addr->dzcsr & DZ_32)
420: dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
421: else
422: dp->p_addr->dztcr &= ~(1<<unit);
423: splx(s);
424: }
425:
426: dzstart(tp)
427: register struct tty *tp;
428: {
429: register struct pdma *dp;
430: register struct dzdevice *dzaddr;
431: register int cc;
432: int s, dz, unit;
433:
434: dp = (struct pdma *)tp->t_addr;
435: dzaddr = dp->p_addr;
436: s = spl5();
437: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
438: goto out;
439: if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
440: if (tp->t_state&TS_ASLEEP) {
441: tp->t_state &= ~TS_ASLEEP;
442: wakeup((caddr_t)&tp->t_outq);
443: }
444: if (tp->t_wsel) {
445: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
446: tp->t_wsel = 0;
447: tp->t_state &= ~TS_WCOLL;
448: }
449: }
450: if (tp->t_outq.c_cc == 0)
451: goto out;
452: if (tp->t_flags & (RAW|LITOUT))
453: cc = ndqb(&tp->t_outq, 0);
454: else {
455: cc = ndqb(&tp->t_outq, 0200);
456: if (cc == 0) {
457: cc = getc(&tp->t_outq);
458: timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
459: tp->t_state |= TS_TIMEOUT;
460: goto out;
461: }
462: }
463: tp->t_state |= TS_BUSY;
464: dp->p_end = dp->p_mem = tp->t_outq.c_cf;
465: dp->p_end += cc;
466: dz = minor(tp->t_dev) >> 3;
467: unit = minor(tp->t_dev) & 7;
468: if (dzaddr->dzcsr & DZ_32)
469: dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
470: else
471: dzaddr->dztcr |= (1<<unit);
472: out:
473: splx(s);
474: }
475:
476: /*
477: * Stop output on a line.
478: */
479: /*ARGSUSED*/
480: dzstop(tp, flag)
481: register struct tty *tp;
482: {
483: register struct pdma *dp;
484: register int s;
485:
486: dp = (struct pdma *)tp->t_addr;
487: s = spl5();
488: if (tp->t_state & TS_BUSY) {
489: dp->p_end = dp->p_mem;
490: if ((tp->t_state&TS_TTSTOP)==0)
491: tp->t_state |= TS_FLUSH;
492: }
493: splx(s);
494: }
495:
496: dzmctl(dev, bits, how)
497: dev_t dev;
498: int bits, how;
499: {
500: register struct dzdevice *dzaddr;
501: register int unit, mbits;
502: int b, s;
503:
504: unit = minor(dev);
505: b = 1<<(unit&7);
506: dzaddr = dzpdma[unit].p_addr;
507: s = spl5();
508: if (dzaddr->dzcsr & DZ_32) {
509: dzwait(dzaddr)
510: DELAY(100); /* IS 100 TOO MUCH? */
511: dzaddr->dzlcs = unit&7;
512: DELAY(100);
513: dzwait(dzaddr)
514: DELAY(100);
515: mbits = dzaddr->dzlcs;
516: mbits &= 0177770;
517: } else {
518: mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
519: mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
520: mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
521: }
522: switch (how) {
523: case DMSET:
524: mbits = bits;
525: break;
526:
527: case DMBIS:
528: mbits |= bits;
529: break;
530:
531: case DMBIC:
532: mbits &= ~bits;
533: break;
534:
535: case DMGET:
536: (void) splx(s);
537: return(mbits);
538: }
539: if (dzaddr->dzcsr & DZ_32) {
540: mbits |= DZ_ACK|(unit&7);
541: dzaddr->dzlcs = mbits;
542: } else {
543: if (mbits & DZ_DTR)
544: dzaddr->dzdtr |= b;
545: else
546: dzaddr->dzdtr &= ~b;
547: }
548: (void) splx(s);
549: return(mbits);
550: }
551:
552: dzscan()
553: {
554: register i;
555: register struct dzdevice *dzaddr;
556: register bit;
557: register struct tty *tp;
558: register car;
559:
560: for (i = 0; i < dz_cnt ; i++) {
561: dzaddr = dzpdma[i].p_addr;
562: if (dzaddr == 0)
563: continue;
564: tp = &dz_tty[i];
565: bit = 1<<(i&07);
566: car = 0;
567: if (dzsoftCAR[i>>3]&bit)
568: car = 1;
569: else if (dzaddr->dzcsr & DZ_32) {
570: dzaddr->dzlcs = i&07;
571: dzwait(dzaddr);
572: car = dzaddr->dzlcs & DZ_CD;
573: } else
574: car = dzaddr->dzmsr&bit;
575: if (car) {
576: /* carrier present */
577: if ((tp->t_state & TS_CARR_ON) == 0) {
578: wakeup((caddr_t)&tp->t_rawq);
579: tp->t_state |= TS_CARR_ON;
580: }
581: } else {
582: if ((tp->t_state&TS_CARR_ON) &&
583: (tp->t_flags&NOHANG) == 0) {
584: /* carrier lost */
585: if (tp->t_state&TS_ISOPEN) {
586: gsignal(tp->t_pgrp, SIGHUP);
587: gsignal(tp->t_pgrp, SIGCONT);
588: dzaddr->dzdtr &= ~bit;
589: ttyflush(tp, FREAD|FWRITE);
590: }
591: tp->t_state &= ~TS_CARR_ON;
592: }
593: }
594: }
595: timeout(dzscan, (caddr_t)0, 2*hz);
596: }
597:
598: dztimer()
599: {
600: register int dz;
601: register int s = spl5();
602:
603: for (dz = 0; dz < NDZ; dz++)
604: dzrint(dz);
605: splx(s);
606: }
607:
608: /*
609: * Reset state of driver if UBA reset was necessary.
610: * Reset parameters and restart transmission on open lines.
611: */
612: dzreset(uban)
613: int uban;
614: {
615: register int unit;
616: register struct tty *tp;
617: register struct uba_device *ui;
618:
619: for (unit = 0; unit < NDZLINE; unit++) {
620: ui = dzinfo[unit >> 3];
621: if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
622: continue;
623: if (unit%8 == 0)
624: printf(" dz%d", unit>>3);
625: tp = &dz_tty[unit];
626: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
627: dzparam(unit);
628: (void) dzmctl(unit, DZ_ON, DMSET);
629: tp->t_state &= ~TS_BUSY;
630: dzstart(tp);
631: }
632: }
633: dztimer();
634: }
635: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.