|
|
1.1 root 1: /* dmf.c 6.1 83/07/29 */
2:
3: #include "dmf.h"
4: #if NDMF > 0
5: /*
6: * DMF32 driver
7: *
8: * TODO:
9: * test with modem
10: * load as much as possible into silo
11: * get correct numbers for receive silo parameter timeout
12: * use auto XON/XOFF
13: * test reset code
14: * test with more than one unit
15: * optimize for efficient DMA and dynamically
16: * decide between silo and DMA mode
17: */
18: #include "../machine/pte.h"
19:
20: #include "bk.h"
21: #include "../h/param.h"
22: #include "../h/conf.h"
23: #include "../h/dir.h"
24: #include "../h/user.h"
25: #include "../h/ioctl.h"
26: #include "../h/tty.h"
27: #include "../h/map.h"
28: #include "../h/buf.h"
29: #include "../h/vm.h"
30: #include "../h/bk.h"
31: #include "../h/clist.h"
32: #include "../h/file.h"
33: #include "../h/uio.h"
34:
35: #include "../vaxuba/ubareg.h"
36: #include "../vaxuba/ubavar.h"
37: #include "../vaxuba/dmfreg.h"
38:
39: /*
40: * Definition of the driver for the auto-configuration program.
41: */
42: int dmfprobe(), dmfattach(), dmfrint(), dmfxint();
43: struct uba_device *dmfinfo[NDMF];
44: u_short dmfstd[] = { 0 };
45: struct uba_driver dmfdriver =
46: { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
47:
48: /*
49: * Local variables for the driver
50: */
51: char dmf_speeds[] =
52: { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
53:
54: struct tty dmf_tty[NDMF*8];
55: char dmfsoftCAR[NDMF];
56: #ifndef lint
57: int ndmf = NDMF*8; /* used by iostat */
58: #endif
59: int dmfact; /* mask of active dmf's */
60: int dmfstart(), ttrstrt();
61:
62: #ifdef DMFDMA
63: /*
64: * The clist space is mapped by the driver onto each UNIBUS.
65: * The UBACVT macro converts a clist space address for unibus uban
66: * into an i/o space address for the DMA routine.
67: */
68: int dmf_ubinfo[MAXNUBA]; /* info about allocated unibus map */
69: static int cbase[MAXNUBA]; /* base address in unibus map */
70: #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
71: #endif
72:
73: /*
74: * Routine for configuration to set dmf interrupt.
75: */
76: /*ARGSUSED*/
77: dmfprobe(reg, ctlr)
78: caddr_t reg;
79: int ctlr;
80: {
81: register int br, cvec; /* these are ``value-result'' */
82: register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
83:
84: #ifdef lint
85: br = 0; cvec = br; br = cvec;
86: dmfxint(0); dmfrint(0);
87: dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint();
88: #endif
89: br = 0x15;
90: cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
91: dmfaddr->dmfccsr0 = cvec >> 2;
92: /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */
93: return (sizeof (struct dmfdevice));
94: }
95:
96: /*
97: * Routine called to attach a dmf.
98: */
99: dmfattach(ui)
100: struct uba_device *ui;
101: {
102:
103: dmfsoftCAR[ui->ui_unit] = ui->ui_flags;
104: }
105:
106:
107: /*
108: * Open a DMF32 line, mapping the clist onto the uba if this
109: * is the first dmf on this uba. Turn on this dmf if this is
110: * the first use of it.
111: */
112: /*ARGSUSED*/
113: dmfopen(dev, flag)
114: dev_t dev;
115: {
116: register struct tty *tp;
117: register int unit, dmf;
118: register struct dmfdevice *addr;
119: register struct uba_device *ui;
120: int s;
121:
122: unit = minor(dev);
123: dmf = unit >> 3;
124: if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
125: return (ENXIO);
126: tp = &dmf_tty[unit];
127: if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
128: return (EBUSY);
129: addr = (struct dmfdevice *)ui->ui_addr;
130: tp->t_addr = (caddr_t)addr;
131: tp->t_oproc = dmfstart;
132: tp->t_state |= TS_WOPEN;
133: /*
134: * While setting up state for this uba and this dmf,
135: * block uba resets which can clear the state.
136: */
137: s = spl5();
138: #ifdef DMFDMA
139: if (dmf_ubinfo[ui->ui_ubanum] == 0) {
140: dmf_ubinfo[ui->ui_ubanum] =
141: uballoc(ui->ui_ubanum, (caddr_t)cfree,
142: nclist*sizeof(struct cblock), 0);
143: cbase[ui->ui_ubanum] = dmf_ubinfo[ui->ui_ubanum]&0x3ffff;
144: }
145: #endif
146: if ((dmfact&(1<<dmf)) == 0) {
147: addr->dmfcsr |= DMF_IE;
148: dmfact |= (1<<dmf);
149: addr->dmfrsp = 1; /* DON'T KNOW WHAT TO SET IT TO YET */
150: }
151: splx(s);
152: /*
153: * If this is first open, initialze tty state to default.
154: */
155: if ((tp->t_state&TS_ISOPEN) == 0) {
156: ttychars(tp);
157: if (tp->t_ispeed == 0) {
158: tp->t_ispeed = B300;
159: tp->t_ospeed = B300;
160: tp->t_flags = ODDP|EVENP|ECHO;
161: }
162: dmfparam(unit);
163: }
164: /*
165: * Wait for carrier, then process line discipline specific open.
166: */
167: if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
168: (dmfsoftCAR[dmf] & (1<<(unit&07))))
169: tp->t_state |= TS_CARR_ON;
170: s = spl5();
171: while ((tp->t_state & TS_CARR_ON) == 0) {
172: tp->t_state |= TS_WOPEN;
173: sleep((caddr_t)&tp->t_rawq, TTIPRI);
174: }
175: splx(s);
176: return ((*linesw[tp->t_line].l_open)(dev, tp));
177: }
178:
179: /*
180: * Close a DMF32 line.
181: */
182: /*ARGSUSED*/
183: dmfclose(dev, flag)
184: dev_t dev;
185: int flag;
186: {
187: register struct tty *tp;
188: register unit;
189:
190: unit = minor(dev);
191: tp = &dmf_tty[unit];
192: (*linesw[tp->t_line].l_close)(tp);
193: (void) dmfmctl(unit, DMF_BRK, DMBIC);
194: if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
195: (void) dmfmctl(unit, DMF_OFF, DMSET);
196: ttyclose(tp);
197: }
198:
199: dmfread(dev, uio)
200: dev_t dev;
201: struct uio *uio;
202: {
203: register struct tty *tp;
204:
205: tp = &dmf_tty[minor(dev)];
206: return ((*linesw[tp->t_line].l_read)(tp, uio));
207: }
208:
209: dmfwrite(dev, uio)
210: dev_t dev;
211: struct uio *uio;
212: {
213: register struct tty *tp;
214:
215: tp = &dmf_tty[minor(dev)];
216: return ((*linesw[tp->t_line].l_write)(tp, uio));
217: }
218:
219: /*
220: * DMF32 receiver interrupt.
221: */
222: dmfrint(dmf)
223: int dmf;
224: {
225: register struct tty *tp;
226: register c;
227: register struct dmfdevice *addr;
228: register struct tty *tp0;
229: register struct uba_device *ui;
230: int overrun = 0, s;
231:
232: ui = dmfinfo[dmf];
233: if (ui == 0 || ui->ui_alive == 0)
234: return;
235: addr = (struct dmfdevice *)ui->ui_addr;
236: tp0 = &dmf_tty[dmf<<3];
237: /*
238: * Loop fetching characters from the silo for this
239: * dmf until there are no more in the silo.
240: */
241: while ((c = addr->dmfrbuf) < 0) {
242: tp = tp0 + ((c>>8)&07);
243: if (c & DMF_DSC) {
244: s = spl5();
245: addr->dmfcsr = DMF_IE | DMFIR_TBUF | ((c>>8)&07);
246: if (addr->dmfrms & DMF_CAR) {
247: if ((tp->t_state & TS_CARR_ON) == 0) {
248: wakeup((caddr_t)&tp->t_rawq);
249: tp->t_state |= TS_CARR_ON;
250: }
251: } else {
252: if (tp->t_state & TS_CARR_ON) {
253: gsignal(tp->t_pgrp, SIGHUP);
254: gsignal(tp->t_pgrp, SIGCONT);
255: addr->dmfcsr = DMF_IE | DMFIR_LCR |
256: ((c>>8)&07);
257: addr->dmftms = 0;
258: ttyflush(tp, FREAD|FWRITE);
259: }
260: tp->t_state &= ~TS_CARR_ON;
261: }
262: splx(s);
263: continue;
264: }
265: if ((tp->t_state&TS_ISOPEN)==0) {
266: wakeup((caddr_t)tp);
267: continue;
268: }
269: if (c & DMF_PE)
270: if ((tp->t_flags&(EVENP|ODDP))==EVENP
271: || (tp->t_flags&(EVENP|ODDP))==ODDP )
272: continue;
273: if ((c & DMF_DO) && overrun == 0) {
274: printf("dmf%d: silo overflow\n", dmf);
275: overrun = 1;
276: }
277: if (c & DMF_FE)
278: /*
279: * At framing error (break) generate
280: * a null (in raw mode, for getty), or a
281: * interrupt (in cooked/cbreak mode).
282: */
283: if (tp->t_flags&RAW)
284: c = 0;
285: else
286: c = tp->t_intrc;
287: #if NBK > 0
288: if (tp->t_line == NETLDISC) {
289: c &= 0177;
290: BKINPUT(c, tp);
291: } else
292: #endif
293: (*linesw[tp->t_line].l_rint)(c, tp);
294: }
295: }
296:
297: /*
298: * Ioctl for DMF32.
299: */
300: /*ARGSUSED*/
301: dmfioctl(dev, cmd, data, flag)
302: dev_t dev;
303: caddr_t data;
304: {
305: register struct tty *tp;
306: register int unit = minor(dev);
307: int error;
308:
309: tp = &dmf_tty[unit];
310: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
311: if (error >= 0)
312: return (error);
313: error = ttioctl(tp, cmd, data, flag);
314: if (error >= 0) {
315: if (cmd == TIOCSETP || cmd == TIOCSETN)
316: dmfparam(unit);
317: return (error);
318: }
319: switch (cmd) {
320:
321: case TIOCSBRK:
322: (void) dmfmctl(dev, DMF_BRK, DMBIS);
323: break;
324:
325: case TIOCCBRK:
326: (void) dmfmctl(dev, DMF_BRK, DMBIC);
327: break;
328:
329: case TIOCSDTR:
330: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
331: break;
332:
333: case TIOCCDTR:
334: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
335: break;
336:
337: case TIOCMSET:
338: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
339: break;
340:
341: case TIOCMBIS:
342: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
343: break;
344:
345: case TIOCMBIC:
346: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
347: break;
348:
349: case TIOCMGET:
350: *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
351: break;
352:
353: default:
354: return (ENOTTY);
355: }
356: return (0);
357: }
358:
359: dmtodmf(bits)
360: register int bits;
361: {
362: register int b;
363:
364: b = bits & 012;
365: if (bits & DML_ST) b |= DMF_RATE;
366: if (bits & DML_RTS) b |= DMF_RTS;
367: if (bits & DML_USR) b |= DMF_USRW;
368: return(b);
369: }
370:
371: dmftodm(bits)
372: register int bits;
373: {
374: register int b;
375:
376: b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
377: if (bits & DMF_USRR) b |= DML_USR;
378: if (bits & DMF_RTS) b |= DML_RTS;
379: return(b);
380: }
381:
382:
383: /*
384: * Set parameters from open or stty into the DMF hardware
385: * registers.
386: */
387: dmfparam(unit)
388: register int unit;
389: {
390: register struct tty *tp;
391: register struct dmfdevice *addr;
392: register int lpar, lcr;
393: int s;
394:
395: tp = &dmf_tty[unit];
396: addr = (struct dmfdevice *)tp->t_addr;
397: /*
398: * Block interrupts so parameters will be set
399: * before the line interrupts.
400: */
401: s = spl5();
402: addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
403: if ((tp->t_ispeed)==0) {
404: tp->t_state |= TS_HUPCLS;
405: (void) dmfmctl(unit, DMF_OFF, DMSET);
406: return;
407: }
408: lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
409: lcr = DMFLCR_ENA;
410: if ((tp->t_ispeed) == B134)
411: lpar |= BITS6|PENABLE;
412: else if (tp->t_flags & (RAW|LITOUT))
413: lpar |= BITS8;
414: else {
415: lpar |= BITS7|PENABLE;
416: /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
417: }
418: if (tp->t_flags&EVENP)
419: lpar |= EPAR;
420: if ((tp->t_ospeed) == B110)
421: lpar |= TWOSB;
422: lpar |= (unit&07);
423: addr->dmflpr = lpar;
424: SETLCR(addr, lcr);
425: splx(s);
426: }
427:
428: /*
429: * DMF32 transmitter interrupt.
430: * Restart the idle line.
431: */
432: dmfxint(dmf)
433: int dmf;
434: {
435: register struct tty *tp;
436: register struct dmfdevice *addr;
437: register struct uba_device *ui;
438: register int unit, t;
439: #ifdef DMFDMA
440: short cntr;
441: int s;
442: #endif
443:
444: ui = dmfinfo[dmf];
445: addr = (struct dmfdevice *)ui->ui_addr;
446: while ((t = addr->dmfcsr) & DMF_TI) {
447: unit = dmf*8 + ((t>>8)&07);
448: tp = &dmf_tty[unit];
449: tp->t_state &= ~TS_BUSY;
450: if (t & DMF_NXM) {
451: printf("dmf%d: NXM line %d\n", dmf, unit&7);
452: /* SHOULD RESTART OR SOMETHING... */
453: }
454: if (tp->t_state&TS_FLUSH)
455: tp->t_state &= ~TS_FLUSH;
456: #ifdef DMFDMA
457: else {
458: s = spl5();
459: addr->dmfcsr = DMFIR_TBUF | DMF_IE | (unit&07);
460: if (addr->dmftsc == 0) {
461: /*
462: * Do arithmetic in a short to make up
463: * for lost 16&17 bits.
464: */
465: addr->dmfcsr = DMFIR_TBA | DMF_IE | (unit&07);
466: cntr = addr->dmftba -
467: UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
468: ndflush(&tp->t_outq, (int)cntr);
469: }
470: splx(s);
471: }
472: #endif
473: if (tp->t_line)
474: (*linesw[tp->t_line].l_start)(tp);
475: else
476: dmfstart(tp);
477: }
478: }
479:
480: /*
481: * Start (restart) transmission on the given DMF32 line.
482: */
483: dmfstart(tp)
484: register struct tty *tp;
485: {
486: register struct dmfdevice *addr;
487: register int unit, nch;
488: int s;
489:
490: unit = minor(tp->t_dev);
491: unit &= 07;
492: addr = (struct dmfdevice *)tp->t_addr;
493:
494: /*
495: * Must hold interrupts in following code to prevent
496: * state of the tp from changing.
497: */
498: s = spl5();
499: /*
500: * If it's currently active, or delaying, no need to do anything.
501: */
502: if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
503: goto out;
504: /*
505: * If there are still characters in the silo,
506: * just reenable the transmitter.
507: */
508: addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
509: if (addr->dmftsc) {
510: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
511: SETLCR(addr, addr->dmflcr|DMF_TE);
512: tp->t_state |= TS_BUSY;
513: goto out;
514: }
515: /*
516: * If there are sleepers, and output has drained below low
517: * water mark, wake up the sleepers.
518: */
519: if ((tp->t_state&TS_ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) {
520: tp->t_state &= ~TS_ASLEEP;
521: wakeup((caddr_t)&tp->t_outq);
522: }
523: /*
524: * Now restart transmission unless the output queue is
525: * empty.
526: */
527: if (tp->t_outq.c_cc == 0)
528: goto out;
529: if (tp->t_flags & (RAW|LITOUT))
530: nch = ndqb(&tp->t_outq, 0);
531: else {
532: nch = ndqb(&tp->t_outq, 0200);
533: /*
534: * If first thing on queue is a delay process it.
535: */
536: if (nch == 0) {
537: nch = getc(&tp->t_outq);
538: timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
539: tp->t_state |= TS_TIMEOUT;
540: goto out;
541: }
542: }
543: /*
544: * If characters to transmit, restart transmission.
545: */
546: if (nch) {
547: #ifdef DMFDMA
548: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
549: SETLCR(addr, addr->dmflcr|DMF_TE);
550: car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
551: addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
552: addr->dmftba = car;
553: addr->dmftcc = ((car>>2)&0xc000) | nch;
554: #else
555: register char *cp = tp->t_outq.c_cf;
556: register int i;
557:
558: nch = MIN(nch, DMF_SILOCNT);
559: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
560: SETLCR(addr, addr->dmflcr|DMF_TE);
561: addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
562: for (i = 0; i < nch; i++)
563: addr->dmftbuf = *cp++;
564: ndflush(&tp->t_outq, nch);
565: #endif
566: tp->t_state |= TS_BUSY;
567: }
568: out:
569: splx(s);
570: }
571:
572: /*
573: * Stop output on a line, e.g. for ^S/^Q or output flush.
574: */
575: /*ARGSUSED*/
576: dmfstop(tp, flag)
577: register struct tty *tp;
578: {
579: register struct dmfdevice *addr;
580: register int unit, s;
581:
582: addr = (struct dmfdevice *)tp->t_addr;
583: /*
584: * Block input/output interrupts while messing with state.
585: */
586: s = spl5();
587: if (tp->t_state & TS_BUSY) {
588: /*
589: * Device is transmitting; stop output
590: * by selecting the line and disabling
591: * the transmitter. If this is a flush
592: * request then flush the output silo,
593: * otherwise we will pick up where we
594: * left off by enabling the transmitter.
595: */
596: unit = minor(tp->t_dev);
597: addr->dmfcsr = DMFIR_LCR | (unit&07) | DMF_IE;
598: SETLCR(addr, addr->dmflcr &~ DMF_TE);
599: if ((tp->t_state&TS_TTSTOP)==0) {
600: tp->t_state |= TS_FLUSH;
601: SETLCR(addr, addr->dmflcr|DMF_FLUSH);
602: } else
603: tp->t_state &= ~TS_BUSY;
604: }
605: splx(s);
606: }
607:
608: /*
609: * DMF32 modem control
610: */
611: dmfmctl(dev, bits, how)
612: dev_t dev;
613: int bits, how;
614: {
615: register struct dmfdevice *dmfaddr;
616: register int unit, mbits, lcr;
617: int s;
618:
619: unit = minor(dev);
620: dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
621: unit &= 07;
622: s = spl5();
623: dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
624: mbits = dmfaddr->dmfrms << 8;
625: dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
626: mbits |= dmfaddr->dmftms;
627: lcr = dmfaddr->dmflcr;
628: switch (how) {
629: case DMSET:
630: mbits = (mbits &0xff00) | bits;
631: break;
632:
633: case DMBIS:
634: mbits |= bits;
635: break;
636:
637: case DMBIC:
638: mbits &= ~bits;
639: break;
640:
641: case DMGET:
642: (void) splx(s);
643: return(mbits);
644: }
645: if (mbits & DMF_BRK)
646: lcr |= DMF_RBRK;
647: else
648: lcr &= ~DMF_RBRK;
649: lcr = ((mbits & 037) << 8) | (lcr & 0xff);
650: dmfaddr->dmfun.dmfirw = lcr;
651: (void) splx(s);
652: return(mbits);
653: }
654:
655: /*
656: * Reset state of driver if UBA reset was necessary.
657: * Reset the csr, lpr, and lcr registers on open lines, and
658: * restart transmitters.
659: */
660: dmfreset(uban)
661: int uban;
662: {
663: register int dmf, unit;
664: register struct tty *tp;
665: register struct uba_device *ui;
666: register struct dmfdevice *addr;
667: int i;
668:
669: #ifdef DMFDMA
670: if (dmf_ubinfo[uban] == 0)
671: return;
672: dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
673: nclist*sizeof (struct cblock), 0);
674: cbase[uban] = dmf_ubinfo[uban]&0x3ffff;
675: #endif
676: for (dmf = 0; dmf < NDMF; dmf++) {
677: ui = dmfinfo[dmf];
678: if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
679: continue;
680: printf(" dmf%d", dmf);
681: addr = (struct dmfdevice *)ui->ui_addr;
682: addr->dmfcsr = DMF_IE;
683: addr->dmfrsp = 1;
684: unit = dmf * 8;
685: for (i = 0; i < 8; i++) {
686: tp = &dmf_tty[unit];
687: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
688: dmfparam(unit);
689: (void) dmfmctl(unit, DMF_ON, DMSET);
690: tp->t_state &= ~TS_BUSY;
691: dmfstart(tp);
692: }
693: unit++;
694: }
695: }
696: }
697:
698: /* stubs for interrupt routines for devices not yet supported */
699:
700: dmfsrint() { printf("dmfsrint\n"); }
701:
702: dmfsxint() { printf("dmfsxint\n"); }
703:
704: dmfdaint() { printf("dmfdaint\n"); }
705:
706: dmfdbint() { printf("dmfdbint\n"); }
707:
708: dmflint() { printf("dmflint\n"); }
709: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.