|
|
1.1 root 1: /* dh.c 6.1 83/07/29 */
2:
3: #include "dh.h"
4: #if NDH > 0
5: /*
6: * DH-11/DM-11 driver
7: */
8: #include "../machine/pte.h"
9:
10: #include "bk.h"
11: #include "../h/param.h"
12: #include "../h/conf.h"
13: #include "../h/dir.h"
14: #include "../h/user.h"
15: #include "../h/proc.h"
16: #include "../h/ioctl.h"
17: #include "../h/tty.h"
18: #include "../h/map.h"
19: #include "../h/buf.h"
20: #include "../h/vm.h"
21:
22: #include "../vaxuba/ubareg.h"
23: #include "../vaxuba/ubavar.h"
24: #include "../vaxuba/dhreg.h"
25: #include "../vaxuba/dmreg.h"
26:
27: #include "../h/bk.h"
28: #include "../h/clist.h"
29: #include "../h/file.h"
30: #include "../h/uio.h"
31:
32: /*
33: * Definition of the driver for the auto-configuration program.
34: * There is one definition for the dh and one for the dm.
35: */
36: int dhprobe(), dhattach(), dhrint(), dhxint();
37: struct uba_device *dhinfo[NDH];
38: u_short dhstd[] = { 0 };
39: struct uba_driver dhdriver =
40: { dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo };
41:
42: int dmprobe(), dmattach(), dmintr();
43: struct uba_device *dminfo[NDH];
44: u_short dmstd[] = { 0 };
45: struct uba_driver dmdriver =
46: { dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo };
47:
48: #ifndef PORTSELECTOR
49: #define ISPEED B300
50: #define IFLAGS (EVENP|ODDP|ECHO)
51: #else
52: #define ISPEED B4800
53: #define IFLAGS (EVENP|ODDP)
54: #endif
55:
56: /*
57: * Local variables for the driver
58: */
59: short dhsar[NDH]; /* software copy of last bar */
60: short dhsoftCAR[NDH];
61:
62: struct tty dh11[NDH*16];
63: int ndh11 = NDH*16;
64: int dhact; /* mask of active dh's */
65: int dhstart(), ttrstrt();
66:
67: /*
68: * The clist space is mapped by the driver onto each UNIBUS.
69: * The UBACVT macro converts a clist space address for unibus uban
70: * into an i/o space address for the DMA routine.
71: */
72: int dh_ubinfo[MAXNUBA]; /* info about allocated unibus map */
73: int cbase[MAXNUBA]; /* base address in unibus map */
74: #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
75:
76: /*
77: * Routine for configuration to force a dh to interrupt.
78: * Set to transmit at 9600 baud, and cause a transmitter interrupt.
79: */
80: /*ARGSUSED*/
81: dhprobe(reg)
82: caddr_t reg;
83: {
84: register int br, cvec; /* these are ``value-result'' */
85: register struct dhdevice *dhaddr = (struct dhdevice *)reg;
86:
87: #ifdef lint
88: br = 0; cvec = br; br = cvec;
89: if (ndh11 == 0) ndh11 = 1;
90: dhrint(0); dhxint(0);
91: #endif
92: #ifndef notdef
93: dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI;
94: DELAY(1000);
95: dhaddr->un.dhcsr &= ~DH_RI;
96: dhaddr->un.dhcsr = 0;
97: #else
98: dhaddr->un.dhcsr = DH_TIE;
99: DELAY(5);
100: dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE;
101: dhaddr->dhbcr = -1;
102: dhaddr->dhcar = 0;
103: dhaddr->dhbar = 1;
104: DELAY(100000); /* wait 1/10'th of a sec for interrupt */
105: dhaddr->un.dhcsr = 0;
106: if (cvec && cvec != 0x200)
107: cvec -= 4; /* transmit -> receive */
108: #endif
109: return (sizeof (struct dhdevice));
110: }
111:
112: /*
113: * Routine called to attach a dh.
114: */
115: dhattach(ui)
116: struct uba_device *ui;
117: {
118:
119: dhsoftCAR[ui->ui_unit] = ui->ui_flags;
120: }
121:
122: /*
123: * Configuration routine to cause a dm to interrupt.
124: */
125: dmprobe(reg)
126: caddr_t reg;
127: {
128: register int br, vec; /* value-result */
129: register struct dmdevice *dmaddr = (struct dmdevice *)reg;
130:
131: #ifdef lint
132: br = 0; vec = br; br = vec;
133: dmintr(0);
134: #endif
135: dmaddr->dmcsr = DM_DONE|DM_IE;
136: DELAY(20);
137: dmaddr->dmcsr = 0;
138: return (1);
139: }
140:
141: /*ARGSUSED*/
142: dmattach(ui)
143: struct uba_device *ui;
144: {
145:
146: /* no local state to set up */
147: }
148:
149: /*
150: * Open a DH11 line, mapping the clist onto the uba if this
151: * is the first dh on this uba. Turn on this dh if this is
152: * the first use of it. Also do a dmopen to wait for carrier.
153: */
154: /*ARGSUSED*/
155: dhopen(dev, flag)
156: dev_t dev;
157: {
158: register struct tty *tp;
159: register int unit, dh;
160: register struct dhdevice *addr;
161: register struct uba_device *ui;
162: int s;
163:
164: unit = minor(dev);
165: dh = unit >> 4;
166: if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0)
167: return (ENXIO);
168: tp = &dh11[unit];
169: if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
170: return (EBUSY);
171: addr = (struct dhdevice *)ui->ui_addr;
172: tp->t_addr = (caddr_t)addr;
173: tp->t_oproc = dhstart;
174: tp->t_state |= TS_WOPEN;
175: /*
176: * While setting up state for this uba and this dh,
177: * block uba resets which can clear the state.
178: */
179: s = spl5();
180: if (dh_ubinfo[ui->ui_ubanum] == 0) {
181: /* 512+ is a kludge to try to get around a hardware problem */
182: dh_ubinfo[ui->ui_ubanum] =
183: uballoc(ui->ui_ubanum, (caddr_t)cfree,
184: 512+nclist*sizeof(struct cblock), 0);
185: cbase[ui->ui_ubanum] = dh_ubinfo[ui->ui_ubanum]&0x3ffff;
186: }
187: if ((dhact&(1<<dh)) == 0) {
188: addr->un.dhcsr |= DH_IE;
189: dhact |= (1<<dh);
190: addr->dhsilo = 16;
191: }
192: splx(s);
193: /*
194: * If this is first open, initialze tty state to default.
195: */
196: if ((tp->t_state&TS_ISOPEN) == 0) {
197: ttychars(tp);
198: #ifndef PORTSELECTOR
199: if (tp->t_ispeed == 0) {
200: #endif
201: tp->t_ispeed = ISPEED;
202: tp->t_ospeed = ISPEED;
203: tp->t_flags = IFLAGS;
204: #ifndef PORTSELECTOR
205: }
206: #endif
207: dhparam(unit);
208: }
209: /*
210: * Wait for carrier, then process line discipline specific open.
211: */
212: dmopen(dev);
213: return ((*linesw[tp->t_line].l_open)(dev, tp));
214: }
215:
216: /*
217: * Close a DH11 line, turning off the DM11.
218: */
219: /*ARGSUSED*/
220: dhclose(dev, flag)
221: dev_t dev;
222: int flag;
223: {
224: register struct tty *tp;
225: register unit;
226:
227: unit = minor(dev);
228: tp = &dh11[unit];
229: (*linesw[tp->t_line].l_close)(tp);
230: ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
231: if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
232: dmctl(unit, DML_OFF, DMSET);
233: ttyclose(tp);
234: }
235:
236: dhread(dev, uio)
237: dev_t dev;
238: struct uio *uio;
239: {
240: register struct tty *tp = &dh11[minor(dev)];
241:
242: return ((*linesw[tp->t_line].l_read)(tp, uio));
243: }
244:
245: dhwrite(dev, uio)
246: dev_t dev;
247: struct uio *uio;
248: {
249: register struct tty *tp = &dh11[minor(dev)];
250:
251: return ((*linesw[tp->t_line].l_write)(tp, uio));
252: }
253:
254: /*
255: * DH11 receiver interrupt.
256: */
257: dhrint(dh)
258: int dh;
259: {
260: register struct tty *tp;
261: register c;
262: register struct dhdevice *addr;
263: register struct tty *tp0;
264: register struct uba_device *ui;
265: int overrun = 0;
266:
267: ui = dhinfo[dh];
268: if (ui == 0 || ui->ui_alive == 0)
269: return;
270: addr = (struct dhdevice *)ui->ui_addr;
271: tp0 = &dh11[dh<<4];
272: /*
273: * Loop fetching characters from the silo for this
274: * dh until there are no more in the silo.
275: */
276: while ((c = addr->dhrcr) < 0) {
277: tp = tp0 + ((c>>8)&0xf);
278: #ifndef PORTSELECTOR
279: if ((tp->t_state&TS_ISOPEN)==0) {
280: #else
281: if ((tp->t_state&(TS_ISOPEN|TS_WOPEN))==0) {
282: #endif
283: wakeup((caddr_t)tp);
284: continue;
285: }
286: if (c & DH_PE)
287: if ((tp->t_flags&(EVENP|ODDP))==EVENP
288: || (tp->t_flags&(EVENP|ODDP))==ODDP )
289: continue;
290: if ((c & DH_DO) && overrun == 0) {
291: printf("dh%d: silo overflow\n", dh);
292: overrun = 1;
293: }
294: if (c & DH_FE)
295: /*
296: * At framing error (break) generate
297: * a null (in raw mode, for getty), or a
298: * interrupt (in cooked/cbreak mode).
299: */
300: if (tp->t_flags&RAW)
301: c = 0;
302: else
303: c = tp->t_intrc;
304: #if NBK > 0
305: if (tp->t_line == NETLDISC) {
306: c &= 0177;
307: BKINPUT(c, tp);
308: } else
309: #endif
310: (*linesw[tp->t_line].l_rint)(c, tp);
311: }
312: }
313:
314: /*
315: * Ioctl for DH11.
316: */
317: /*ARGSUSED*/
318: dhioctl(dev, cmd, data, flag)
319: caddr_t data;
320: {
321: register struct tty *tp;
322: register int unit = minor(dev);
323: int error;
324:
325: tp = &dh11[unit];
326: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
327: if (error >= 0)
328: return (error);
329: error = ttioctl(tp, cmd, data, flag);
330: if (error >= 0) {
331: if (cmd == TIOCSETP || cmd == TIOCSETN)
332: dhparam(unit);
333: return (error);
334: }
335: switch (cmd) {
336:
337: case TIOCSBRK:
338: ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017);
339: break;
340:
341: case TIOCCBRK:
342: ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
343: break;
344:
345: case TIOCSDTR:
346: dmctl(unit, DML_DTR|DML_RTS, DMBIS);
347: break;
348:
349: case TIOCCDTR:
350: dmctl(unit, DML_DTR|DML_RTS, DMBIC);
351: break;
352:
353: default:
354: return (ENOTTY);
355: }
356: return (0);
357: }
358:
359: /*
360: * Set parameters from open or stty into the DH hardware
361: * registers.
362: */
363: dhparam(unit)
364: register int unit;
365: {
366: register struct tty *tp;
367: register struct dhdevice *addr;
368: register int lpar;
369: int s;
370:
371: tp = &dh11[unit];
372: addr = (struct dhdevice *)tp->t_addr;
373: /*
374: * Block interrupts so parameters will be set
375: * before the line interrupts.
376: */
377: s = spl5();
378: addr->un.dhcsrl = (unit&0xf) | DH_IE;
379: if ((tp->t_ispeed)==0) {
380: tp->t_state |= TS_HUPCLS;
381: dmctl(unit, DML_OFF, DMSET);
382: return;
383: }
384: lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
385: if ((tp->t_ispeed) == B134)
386: lpar |= BITS6|PENABLE|HDUPLX;
387: else if (tp->t_flags & (RAW|LITOUT))
388: lpar |= BITS8;
389: else
390: lpar |= BITS7|PENABLE;
391: if ((tp->t_flags&EVENP) == 0)
392: lpar |= OPAR;
393: if ((tp->t_ospeed) == B110)
394: lpar |= TWOSB;
395: addr->dhlpr = lpar;
396: splx(s);
397: }
398:
399: /*
400: * DH11 transmitter interrupt.
401: * Restart each line which used to be active but has
402: * terminated transmission since the last interrupt.
403: */
404: dhxint(dh)
405: int dh;
406: {
407: register struct tty *tp;
408: register struct dhdevice *addr;
409: short ttybit, bar, *sbar;
410: register struct uba_device *ui;
411: register int unit;
412: u_short cntr;
413:
414: ui = dhinfo[dh];
415: addr = (struct dhdevice *)ui->ui_addr;
416: if (addr->un.dhcsr & DH_NXM) {
417: addr->un.dhcsr |= DH_CNI;
418: printf("dh%d: NXM\n", dh);
419: }
420: sbar = &dhsar[dh];
421: bar = *sbar & ~addr->dhbar;
422: unit = dh * 16; ttybit = 1;
423: addr->un.dhcsr &= (short)~DH_TI;
424: for (; bar; unit++, ttybit <<= 1) {
425: if (bar & ttybit) {
426: *sbar &= ~ttybit;
427: bar &= ~ttybit;
428: tp = &dh11[unit];
429: tp->t_state &= ~TS_BUSY;
430: if (tp->t_state&TS_FLUSH)
431: tp->t_state &= ~TS_FLUSH;
432: else {
433: addr->un.dhcsrl = (unit&017)|DH_IE;
434: /*
435: * Do arithmetic in a short to make up
436: * for lost 16&17 bits.
437: */
438: cntr = addr->dhcar -
439: UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
440: ndflush(&tp->t_outq, (int)cntr);
441: }
442: if (tp->t_line)
443: (*linesw[tp->t_line].l_start)(tp);
444: else
445: dhstart(tp);
446: }
447: }
448: }
449:
450: /*
451: * Start (restart) transmission on the given DH11 line.
452: */
453: dhstart(tp)
454: register struct tty *tp;
455: {
456: register struct dhdevice *addr;
457: register int car, dh, unit, nch;
458: int s;
459:
460: unit = minor(tp->t_dev);
461: dh = unit >> 4;
462: unit &= 0xf;
463: addr = (struct dhdevice *)tp->t_addr;
464:
465: /*
466: * Must hold interrupts in following code to prevent
467: * state of the tp from changing.
468: */
469: s = spl5();
470: /*
471: * If it's currently active, or delaying, no need to do anything.
472: */
473: if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
474: goto out;
475: /*
476: * If there are sleepers, and output has drained below low
477: * water mark, wake up the sleepers.
478: */
479: if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
480: if (tp->t_state&TS_ASLEEP) {
481: tp->t_state &= ~TS_ASLEEP;
482: wakeup((caddr_t)&tp->t_outq);
483: }
484: if (tp->t_wsel) {
485: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
486: tp->t_wsel = 0;
487: tp->t_state &= ~TS_WCOLL;
488: }
489: }
490: /*
491: * Now restart transmission unless the output queue is
492: * empty.
493: */
494: if (tp->t_outq.c_cc == 0)
495: goto out;
496: if (tp->t_flags & (RAW|LITOUT))
497: nch = ndqb(&tp->t_outq, 0);
498: else {
499: nch = ndqb(&tp->t_outq, 0200);
500: /*
501: * If first thing on queue is a delay process it.
502: */
503: if (nch == 0) {
504: nch = getc(&tp->t_outq);
505: timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
506: tp->t_state |= TS_TIMEOUT;
507: goto out;
508: }
509: }
510: /*
511: * If characters to transmit, restart transmission.
512: */
513: if (nch) {
514: car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum);
515: addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE;
516: /*
517: * The following nonsense with short word
518: * is to make sure the dhbar |= word below
519: * is done with an interlocking bisw2 instruction.
520: */
521: { short word = 1 << unit;
522: dhsar[dh] |= word;
523: addr->dhcar = car;
524: addr->dhbcr = -nch;
525: addr->dhbar |= word;
526: }
527: tp->t_state |= TS_BUSY;
528: }
529: out:
530: splx(s);
531: }
532:
533: /*
534: * Stop output on a line, e.g. for ^S/^Q or output flush.
535: */
536: /*ARGSUSED*/
537: dhstop(tp, flag)
538: register struct tty *tp;
539: {
540: register struct dhdevice *addr;
541: register int unit, s;
542:
543: addr = (struct dhdevice *)tp->t_addr;
544: /*
545: * Block input/output interrupts while messing with state.
546: */
547: s = spl5();
548: if (tp->t_state & TS_BUSY) {
549: /*
550: * Device is transmitting; stop output
551: * by selecting the line and setting the byte
552: * count to -1. We will clean up later
553: * by examining the address where the dh stopped.
554: */
555: unit = minor(tp->t_dev);
556: addr->un.dhcsrl = (unit&017) | DH_IE;
557: if ((tp->t_state&TS_TTSTOP)==0)
558: tp->t_state |= TS_FLUSH;
559: addr->dhbcr = -1;
560: }
561: splx(s);
562: }
563:
564: /*
565: * Reset state of driver if UBA reset was necessary.
566: * Reset the csrl and lpr registers on open lines, and
567: * restart transmitters.
568: */
569: dhreset(uban)
570: int uban;
571: {
572: register int dh, unit;
573: register struct tty *tp;
574: register struct uba_device *ui;
575: int i;
576:
577: if (dh_ubinfo[uban] == 0)
578: return;
579: dh_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
580: 512+nclist*sizeof (struct cblock), 0);
581: cbase[uban] = dh_ubinfo[uban]&0x3ffff;
582: dh = 0;
583: for (dh = 0; dh < NDH; dh++) {
584: ui = dhinfo[dh];
585: if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
586: continue;
587: printf(" dh%d", dh);
588: ((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE;
589: ((struct dhdevice *)ui->ui_addr)->dhsilo = 16;
590: unit = dh * 16;
591: for (i = 0; i < 16; i++) {
592: tp = &dh11[unit];
593: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
594: dhparam(unit);
595: dmctl(unit, DML_ON, DMSET);
596: tp->t_state &= ~TS_BUSY;
597: dhstart(tp);
598: }
599: unit++;
600: }
601: }
602: dhtimer();
603: }
604:
605: /*
606: * At software clock interrupt time or after a UNIBUS reset
607: * empty all the dh silos.
608: */
609: dhtimer()
610: {
611: register int dh;
612: register int s = spl5();
613:
614: for (dh = 0; dh < NDH; dh++)
615: dhrint(dh);
616: splx(s);
617: }
618:
619: /*
620: * Turn on the line associated with dh dev.
621: */
622: dmopen(dev)
623: dev_t dev;
624: {
625: register struct tty *tp;
626: register struct dmdevice *addr;
627: register struct uba_device *ui;
628: register int unit;
629: register int dm;
630: int s;
631:
632: unit = minor(dev);
633: dm = unit >> 4;
634: tp = &dh11[unit];
635: unit &= 0xf;
636: if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0 ||
637: (dhsoftCAR[dm]&(1<<unit))) {
638: tp->t_state |= TS_CARR_ON;
639: return;
640: }
641: addr = (struct dmdevice *)ui->ui_addr;
642: s = spl5();
643: addr->dmcsr &= ~DM_SE;
644: while (addr->dmcsr & DM_BUSY)
645: ;
646: addr->dmcsr = unit;
647: addr->dmlstat = DML_ON;
648: if (addr->dmlstat&DML_CAR)
649: tp->t_state |= TS_CARR_ON;
650: addr->dmcsr = DM_IE|DM_SE;
651: while ((tp->t_state&TS_CARR_ON)==0)
652: sleep((caddr_t)&tp->t_rawq, TTIPRI);
653: splx(s);
654: }
655:
656: /*
657: * Dump control bits into the DM registers.
658: */
659: dmctl(dev, bits, how)
660: dev_t dev;
661: int bits, how;
662: {
663: register struct uba_device *ui;
664: register struct dmdevice *addr;
665: register int unit, s;
666: int dm;
667:
668: unit = minor(dev);
669: dm = unit >> 4;
670: if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0)
671: return;
672: addr = (struct dmdevice *)ui->ui_addr;
673: s = spl5();
674: addr->dmcsr &= ~DM_SE;
675: while (addr->dmcsr & DM_BUSY)
676: ;
677: addr->dmcsr = unit & 0xf;
678: switch(how) {
679: case DMSET:
680: addr->dmlstat = bits;
681: break;
682: case DMBIS:
683: addr->dmlstat |= bits;
684: break;
685: case DMBIC:
686: addr->dmlstat &= ~bits;
687: break;
688: }
689: addr->dmcsr = DM_IE|DM_SE;
690: splx(s);
691: }
692:
693: /*
694: * DM11 interrupt; deal with carrier transitions.
695: */
696: dmintr(dm)
697: register int dm;
698: {
699: register struct uba_device *ui;
700: register struct tty *tp;
701: register struct dmdevice *addr;
702:
703: ui = dminfo[dm];
704: if (ui == 0)
705: return;
706: addr = (struct dmdevice *)ui->ui_addr;
707: if (addr->dmcsr&DM_DONE) {
708: if (addr->dmcsr&DM_CF) {
709: tp = &dh11[(dm<<4)+(addr->dmcsr&0xf)];
710: wakeup((caddr_t)&tp->t_rawq);
711: if ((tp->t_state&TS_WOPEN) == 0 &&
712: (tp->t_flags & MDMBUF)) {
713: if (addr->dmlstat & DML_CAR) {
714: tp->t_state &= ~TS_TTSTOP;
715: ttstart(tp);
716: } else if ((tp->t_state&TS_TTSTOP) == 0) {
717: tp->t_state |= TS_TTSTOP;
718: dhstop(tp, 0);
719: }
720: } else if ((addr->dmlstat&DML_CAR)==0) {
721: if ((tp->t_state&TS_WOPEN)==0 &&
722: (tp->t_flags & NOHANG) == 0) {
723: gsignal(tp->t_pgrp, SIGHUP);
724: gsignal(tp->t_pgrp, SIGCONT);
725: addr->dmlstat = 0;
726: ttyflush(tp, FREAD|FWRITE);
727: }
728: tp->t_state &= ~TS_CARR_ON;
729: } else
730: tp->t_state |= TS_CARR_ON;
731: }
732: addr->dmcsr = DM_IE|DM_SE;
733: }
734: }
735: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.