|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)dmf.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "dmf.h"
10: #if NDMF > 0
11: /*
12: * DMF32 driver
13: *
14: *
15: * TODO:
16: * test with modem
17: * load as much as possible into silo
18: * use auto XON/XOFF
19: * test reset code
20: ****************************
21: * DMF32 line printer driver
22: *
23: * the line printer on dmfx is indicated by a minor device code of 128+x
24: *
25: * the flags field of the config file is interpreted like so:
26: * bits meaning
27: * ---- -------
28: * 0-7 soft carrier bits for ttys part of dmf32
29: * 8-15 number of cols/line on the line printer
30: * if 0, 132 will be used.
31: * 16-23 number of lines/page on the line printer
32: * if 0, 66 will be used.
33: * 24 if 1 DO NOT use the auto format mode of the
34: * line printer parallel port
35: */
36: #include "../machine/pte.h"
37:
38: #include "bk.h"
39: #include "uba.h"
40: #include "param.h"
41: #include "conf.h"
42: #include "dir.h"
43: #include "user.h"
44: #include "proc.h"
45: #include "ioctl.h"
46: #include "tty.h"
47: #include "map.h"
48: #include "buf.h"
49: #include "vm.h"
50: #include "bkmac.h"
51: #include "clist.h"
52: #include "file.h"
53: #include "uio.h"
54: #include "kernel.h"
55: #include "syslog.h"
56:
57: #include "ubareg.h"
58: #include "ubavar.h"
59: #include "dmfreg.h"
60:
61: /*
62: * Definition of the driver for the auto-configuration program.
63: */
64: int dmfprobe(), dmfattach(), dmfrint(), dmfxint();
65: int dmflint();
66: struct uba_device *dmfinfo[NDMF];
67: u_short dmfstd[] = { 0 };
68: struct uba_driver dmfdriver =
69: { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
70:
71: int dmf_timeout = 10; /* silo timeout, in ms */
72: int dmf_mindma = 4; /* don't dma below this point */
73:
74: /*
75: * Local variables for the driver
76: */
77: char dmf_speeds[] =
78: { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
79:
80: #ifndef PORTSELECTOR
81: #define ISPEED B9600
82: #define IFLAGS (EVENP|ODDP|ECHO)
83: #else
84: #define ISPEED B4800
85: #define IFLAGS (EVENP|ODDP)
86: #endif
87:
88: struct tty dmf_tty[NDMF*8];
89: char dmfsoftCAR[NDMF];
90:
91: struct dmfl_softc {
92: u_int dmfl_state; /* soft state bits */
93: int dmfl_info; /* uba info */
94: u_short dmfl_lines; /* lines per page (66 def.) */
95: u_short dmfl_cols; /* cols per line (132 def.) */
96: u_short dmfl_format; /* fflag for auto form feed */
97: char dmfl_buf[DMFL_BUFSIZ];
98: } dmfl_softc[NDMF];
99:
100: /*
101: * convert device number into DMF line printer unit number
102: */
103: #define DMFL_UNIT(d) (minor(d)&0xF) /* up to 16 DMFs */
104:
105: #define ASLP 1 /* waiting for interrupt from dmf */
106: #define OPEN 2 /* line printer is open */
107: #define ERROR 4 /* error while printing, driver
108: refuses to do anything till closed */
109: #define MOREIO 8 /* more data for printer */
110:
111: #ifndef lint
112: int ndmf = NDMF*8; /* used by iostat */
113: #endif
114: int dmfact; /* mask of active dmf's */
115: int dmfstart(), ttrstrt();
116:
117: /*
118: * The clist space is mapped by the driver onto each UNIBUS.
119: * The UBACVT macro converts a clist space address for unibus uban
120: * into an i/o space address for the DMA routine.
121: */
122: int dmf_ubinfo[NUBA]; /* info about allocated unibus map */
123: int cbase[NUBA]; /* base address in unibus map */
124: #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
125: char dmf_dma[NDMF*8];
126:
127: /*
128: * Routine for configuration to set dmf interrupt.
129: */
130: /*ARGSUSED*/
131: dmfprobe(reg, ctlr)
132: caddr_t reg;
133: struct uba_device *ctlr;
134: {
135: register int br, cvec; /* these are ``value-result'' */
136: register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
137: register int i;
138: register unsigned int a;
139: static char *dmfdevs[]=
140: {"parallel","printer","synch","asynch"};
141: unsigned int dmfoptions;
142: static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
143:
144: #ifdef lint
145: br = 0; cvec = br; br = cvec;
146: dmfxint(0); dmfrint(0);
147: dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
148: #endif
149: /*
150: * Pick the usual size DMF vector here (don't decrement it here).
151: * grab configuration; note that the DMF32
152: * doesn't seem to put the right bits in this
153: * register until AFTER the interrupt vector is set.
154: */
155: br = 0x15;
156: cvec = (uba_hd[numuba].uh_lastiv - 4*8);
157: dmfaddr->dmfccsr0 = (cvec >> 2);
158: dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
159:
160: /* catch a couple of special cases: Able vmz/32n and vmz/lp */
161: if (dmfoptions == DMFC_ASYNC) {
162: /* Async portion only */
163:
164: cvec = (uba_hd[numuba].uh_lastiv -= 8);
165: dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
166: intrv[0] = ctlr->ui_intr[4];
167: intrv[1] = ctlr->ui_intr[5];
168: ctlr->ui_intr = intrv;
169: } else if (dmfoptions == DMFC_LP) {
170: /* LP portion only */
171:
172: cvec = (uba_hd[numuba].uh_lastiv -= 8);
173: ctlr->ui_intr = &ctlr->ui_intr[6];
174: } else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
175: /* LP ans Async portions only */
176:
177: cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
178: ctlr->ui_intr = &ctlr->ui_intr[4];
179: } else {
180: /* All other configurations get everything */
181:
182: cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
183: }
184: a = (dmfoptions >> 12) & 0xf;
185: printf("dmf%d:", ctlr->ui_unit);
186: for (i = 0; a != 0; ++i, a >>= 1) {
187: if (a & 1)
188: printf(" %s",dmfdevs[i]);
189: }
190: printf(".\n");
191:
192: if (dmfoptions & DMFC_LP)
193: dmfaddr->dmfl_ctrl = DMFL_RESET;
194: return (sizeof (struct dmfdevice));
195: }
196:
197: /*
198: * Routine called to attach a dmf.
199: */
200: dmfattach(ui)
201: struct uba_device *ui;
202: {
203: register int cols = (ui->ui_flags>>8) & 0xff;
204: register int lines = (ui->ui_flags>>16) & 0xff;
205:
206: dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff;
207: dmfl_softc[ui->ui_unit].dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
208: dmfl_softc[ui->ui_unit].dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
209: if ((ui->ui_flags >> 24) & 0x1)
210: dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8);
211: else
212: dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8) | DMFL_FORMAT;
213: cbase[ui->ui_ubanum] = -1;
214: }
215:
216:
217: /*
218: * Open a DMF32 line, mapping the clist onto the uba if this
219: * is the first dmf on this uba. Turn on this dmf if this is
220: * the first use of it.
221: */
222: /*ARGSUSED*/
223: dmfopen(dev, flag)
224: dev_t dev;
225: {
226: register struct tty *tp;
227: register int unit, dmf;
228: register struct dmfdevice *addr;
229: register struct uba_device *ui;
230: int s;
231:
232: unit = minor(dev);
233: if (unit & 0200)
234: return (dmflopen(dev,flag));
235: dmf = unit >> 3;
236: if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
237: return (ENXIO);
238: tp = &dmf_tty[unit];
239: if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
240: return (EBUSY);
241: addr = (struct dmfdevice *)ui->ui_addr;
242: tp->t_addr = (caddr_t)addr;
243: tp->t_oproc = dmfstart;
244: tp->t_state |= TS_WOPEN;
245: /*
246: * While setting up state for this uba and this dmf,
247: * block uba resets which can clear the state.
248: */
249: s = spltty();
250: if (cbase[ui->ui_ubanum] == -1) {
251: dmf_ubinfo[ui->ui_ubanum] =
252: uballoc(ui->ui_ubanum, (caddr_t)cfree,
253: nclist*sizeof(struct cblock), 0);
254: cbase[ui->ui_ubanum] = UBAI_ADDR(dmf_ubinfo[ui->ui_ubanum]);
255: }
256: if ((dmfact&(1<<dmf)) == 0) {
257: addr->dmfcsr |= DMF_IE;
258: dmfact |= (1<<dmf);
259: addr->dmfrsp = dmf_timeout;
260: }
261: splx(s);
262: /*
263: * If this is first open, initialize tty state to default.
264: */
265: if ((tp->t_state&TS_ISOPEN) == 0) {
266: ttychars(tp);
267: #ifndef PORTSELECTOR
268: if (tp->t_ispeed == 0) {
269: #else
270: tp->t_state |= TS_HUPCLS;
271: #endif PORTSELECTOR
272: tp->t_ispeed = ISPEED;
273: tp->t_ospeed = ISPEED;
274: tp->t_flags = IFLAGS;
275: #ifndef PORTSELECTOR
276: }
277: #endif PORTSELECTOR
278: dmfparam(unit);
279: }
280: /*
281: * Wait for carrier, then process line discipline specific open.
282: */
283: s = spltty();
284: for (;;) {
285: if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
286: (dmfsoftCAR[dmf] & (1<<(unit&07))))
287: tp->t_state |= TS_CARR_ON;
288: if (tp->t_state & TS_CARR_ON)
289: break;
290: tp->t_state |= TS_WOPEN;
291: sleep((caddr_t)&tp->t_rawq, TTIPRI);
292: }
293: splx(s);
294: return ((*linesw[tp->t_line].l_open)(dev, tp));
295: }
296:
297: /*
298: * Close a DMF32 line.
299: */
300: /*ARGSUSED*/
301: dmfclose(dev, flag)
302: dev_t dev;
303: int flag;
304: {
305: register struct tty *tp;
306: register unit;
307:
308: unit = minor(dev);
309: if (unit & 0200) {
310: dmflclose(dev,flag);
311: return;
312: }
313:
314: tp = &dmf_tty[unit];
315: (*linesw[tp->t_line].l_close)(tp);
316: (void) dmfmctl(unit, DMF_BRK, DMBIC);
317: if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
318: (void) dmfmctl(unit, DMF_OFF, DMSET);
319: ttyclose(tp);
320: }
321:
322: dmfread(dev, uio)
323: dev_t dev;
324: struct uio *uio;
325: {
326: register struct tty *tp;
327:
328: if (minor(dev) & 0200)
329: return(ENXIO);
330: tp = &dmf_tty[minor(dev)];
331: return ((*linesw[tp->t_line].l_read)(tp, uio));
332: }
333:
334: dmfwrite(dev, uio)
335: dev_t dev;
336: struct uio *uio;
337: {
338: register struct tty *tp;
339:
340: if (minor(dev) & 0200)
341: return (dmflwrite(dev,uio));
342: tp = &dmf_tty[minor(dev)];
343: return ((*linesw[tp->t_line].l_write)(tp, uio));
344: }
345:
346: /*
347: * DMF32 receiver interrupt.
348: */
349: dmfrint(dmf)
350: int dmf;
351: {
352: register c;
353: register struct tty *tp;
354: register struct dmfdevice *addr;
355: register struct tty *tp0;
356: int unit;
357: int overrun = 0;
358: register struct uba_device *ui;
359:
360: ui = dmfinfo[dmf];
361: if (ui == 0 || ui->ui_alive == 0)
362: return;
363: addr = (struct dmfdevice *)ui->ui_addr;
364: tp0 = &dmf_tty[dmf * 8];
365: /*
366: * Loop fetching characters from the silo for this
367: * dmf until there are no more in the silo.
368: */
369: while ((c = addr->dmfrbuf) < 0) {
370:
371: unit = (c >> 8) & 07;
372: tp = tp0 + unit;
373: if (c & DMF_DSC) {
374: addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
375: if (addr->dmfrms & DMF_CAR)
376: (void)(*linesw[tp->t_line].l_modem)(tp, 1);
377: else if ((dmfsoftCAR[dmf] & (1 << unit)) == 0 &&
378: (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
379: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
380: addr->dmflctms = DMFLCR_ENA;
381: }
382: continue;
383: }
384: if ((tp->t_state&TS_ISOPEN) == 0) {
385: wakeup((caddr_t)&tp->t_rawq);
386: #ifdef PORTSELECTOR
387: if ((tp->t_state & TS_WOPEN) == 0)
388: #endif
389: continue;
390: }
391: if (c & (DMF_PE|DMF_DO|DMF_FE)) {
392: if (c & DMF_PE)
393: if ((tp->t_flags & (EVENP|ODDP)) == EVENP
394: || (tp->t_flags & (EVENP|ODDP)) == ODDP)
395: continue;
396: if ((c & DMF_DO) && overrun == 0) {
397: log(LOG_WARNING, "dmf%d: silo overflow\n", dmf);
398: overrun = 1;
399: }
400: if (c & DMF_FE)
401: /*
402: * At framing error (break) generate
403: * a null (in raw mode, for getty), or a
404: * interrupt (in cooked/cbreak mode).
405: */
406: if (tp->t_flags & RAW)
407: c = 0;
408: else
409: c = tp->t_intrc;
410: }
411: #if NBK > 0
412: if (tp->t_line == NETLDISC) {
413: c &= 0177;
414: BKINPUT(c, tp);
415: } else
416: #endif
417: (*linesw[tp->t_line].l_rint)(c, tp);
418: }
419: }
420:
421: /*
422: * Ioctl for DMF32.
423: */
424: /*ARGSUSED*/
425: dmfioctl(dev, cmd, data, flag)
426: dev_t dev;
427: caddr_t data;
428: {
429: register struct tty *tp;
430: register int unit = minor(dev);
431: int error;
432:
433: if (unit & 0200)
434: return (ENOTTY);
435: tp = &dmf_tty[unit];
436: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
437: if (error >= 0)
438: return (error);
439: error = ttioctl(tp, cmd, data, flag);
440: if (error >= 0) {
441: if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
442: cmd == TIOCLBIC || cmd == TIOCLSET)
443: dmfparam(unit);
444: return (error);
445: }
446: switch (cmd) {
447:
448: case TIOCSBRK:
449: (void) dmfmctl(dev, DMF_BRK, DMBIS);
450: break;
451:
452: case TIOCCBRK:
453: (void) dmfmctl(dev, DMF_BRK, DMBIC);
454: break;
455:
456: case TIOCSDTR:
457: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
458: break;
459:
460: case TIOCCDTR:
461: (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
462: break;
463:
464: case TIOCMSET:
465: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
466: break;
467:
468: case TIOCMBIS:
469: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
470: break;
471:
472: case TIOCMBIC:
473: (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
474: break;
475:
476: case TIOCMGET:
477: *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
478: break;
479:
480: default:
481: return (ENOTTY);
482: }
483: return (0);
484: }
485:
486: dmtodmf(bits)
487: register int bits;
488: {
489: register int b;
490:
491: b = bits & 012;
492: if (bits & DML_ST) b |= DMF_RATE;
493: if (bits & DML_RTS) b |= DMF_RTS;
494: if (bits & DML_USR) b |= DMF_USRW;
495: return(b);
496: }
497:
498: dmftodm(bits)
499: register int bits;
500: {
501: register int b;
502:
503: b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
504: if (bits & DMF_USRR) b |= DML_USR;
505: if (bits & DMF_RTS) b |= DML_RTS;
506: return(b);
507: }
508:
509:
510: /*
511: * Set parameters from open or stty into the DMF hardware
512: * registers.
513: */
514: dmfparam(unit)
515: register int unit;
516: {
517: register struct tty *tp;
518: register struct dmfdevice *addr;
519: register int lpar, lcr;
520: int s;
521:
522: tp = &dmf_tty[unit];
523: addr = (struct dmfdevice *)tp->t_addr;
524: /*
525: * Block interrupts so parameters will be set
526: * before the line interrupts.
527: */
528: s = spltty();
529: addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
530: if ((tp->t_ispeed)==0) {
531: tp->t_state |= TS_HUPCLS;
532: (void) dmfmctl(unit, DMF_OFF, DMSET);
533: splx(s);
534: return;
535: }
536: lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
537: lcr = DMFLCR_ENA;
538: if ((tp->t_ispeed) == B134)
539: lpar |= BITS6|PENABLE;
540: else if (tp->t_flags & (RAW|LITOUT|PASS8))
541: lpar |= BITS8;
542: else {
543: lpar |= BITS7|PENABLE;
544: /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
545: }
546: if (tp->t_flags&EVENP)
547: lpar |= EPAR;
548: if ((tp->t_ospeed) == B110)
549: lpar |= TWOSB;
550: lpar |= (unit&07);
551: addr->dmflpr = lpar;
552: addr->dmflctms = (addr->dmflctms &~ 0xff) | lcr;
553: splx(s);
554: }
555:
556: /*
557: * DMF32 transmitter interrupt.
558: * Restart the idle line.
559: */
560: dmfxint(dmf)
561: int dmf;
562: {
563: int unit0 = dmf * 8;
564: struct tty *tp0 = &dmf_tty[unit0];
565: register struct tty *tp;
566: register struct dmfdevice *addr;
567: register struct uba_device *ui;
568: register int t;
569: short cntr;
570:
571: ui = dmfinfo[dmf];
572: addr = (struct dmfdevice *)ui->ui_addr;
573: while ((t = addr->dmfcsr) & DMF_TI) {
574: if (t & DMF_NXM)
575: /* SHOULD RESTART OR SOMETHING... */
576: printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
577: t = t >> 8 & 7;
578: tp = tp0 + t;
579: tp->t_state &= ~TS_BUSY;
580: if (tp->t_state&TS_FLUSH)
581: tp->t_state &= ~TS_FLUSH;
582: else if (dmf_dma[unit0 + t]) {
583: /*
584: * Do arithmetic in a short to make up
585: * for lost 16&17 bits.
586: */
587: addr->dmfcsr = DMFIR_TBA | DMF_IE | t;
588: cntr = addr->dmftba -
589: UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
590: ndflush(&tp->t_outq, (int)cntr);
591: }
592: if (tp->t_line)
593: (*linesw[tp->t_line].l_start)(tp);
594: else
595: dmfstart(tp);
596: }
597: }
598:
599: /*
600: * Start (restart) transmission on the given DMF32 line.
601: */
602: dmfstart(tp)
603: register struct tty *tp;
604: {
605: register struct dmfdevice *addr;
606: register int unit, nch;
607: int s;
608: register int dmf;
609:
610: unit = minor(tp->t_dev);
611: dmf = unit >> 3;
612: unit &= 07;
613: addr = (struct dmfdevice *)tp->t_addr;
614:
615: /*
616: * Must hold interrupts in following code to prevent
617: * state of the tp from changing.
618: */
619: s = spltty();
620: /*
621: * If it's currently active, or delaying, no need to do anything.
622: */
623: if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
624: goto out;
625: /*
626: * If there are still characters in the silo,
627: * just reenable the transmitter.
628: */
629: addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
630: if (addr->dmftsc) {
631: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
632: addr->dmflctms = addr->dmflctms | DMF_TE;
633: tp->t_state |= TS_BUSY;
634: goto out;
635: }
636: /*
637: * If there are sleepers, and output has drained below low
638: * water mark, wake up the sleepers.
639: */
640: if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
641: if (tp->t_state&TS_ASLEEP) {
642: tp->t_state &= ~TS_ASLEEP;
643: wakeup((caddr_t)&tp->t_outq);
644: }
645: if (tp->t_wsel) {
646: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
647: tp->t_wsel = 0;
648: tp->t_state &= ~TS_WCOLL;
649: }
650: }
651: /*
652: * Now restart transmission unless the output queue is
653: * empty.
654: */
655: if (tp->t_outq.c_cc == 0)
656: goto out;
657: if (tp->t_flags & (RAW|LITOUT))
658: nch = ndqb(&tp->t_outq, 0);
659: else {
660: if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
661: /*
662: * If first thing on queue is a delay process it.
663: */
664: nch = getc(&tp->t_outq);
665: timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
666: tp->t_state |= TS_TIMEOUT;
667: goto out;
668: }
669: }
670: /*
671: * If characters to transmit, restart transmission.
672: */
673: if (nch >= dmf_mindma) {
674: register car;
675:
676: dmf_dma[minor(tp->t_dev)] = 1;
677: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
678: addr->dmflctms = addr->dmflctms | DMF_TE;
679: car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
680: addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
681: addr->dmftba = car;
682: addr->dmftcc = ((car >> 2) & 0xc000) | nch;
683: tp->t_state |= TS_BUSY;
684: } else if (nch) {
685: register char *cp = tp->t_outq.c_cf;
686: register int i;
687:
688: dmf_dma[minor(tp->t_dev)] = 0;
689: nch = MIN(nch, DMF_SILOCNT);
690: addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
691: addr->dmflctms = addr->dmflctms | DMF_TE;
692: addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
693: for (i = 0; i < nch; i++)
694: addr->dmftbuf = *cp++;
695: ndflush(&tp->t_outq, nch);
696: tp->t_state |= TS_BUSY;
697: }
698: out:
699: splx(s);
700: }
701:
702: /*
703: * Stop output on a line, e.g. for ^S/^Q or output flush.
704: */
705: /*ARGSUSED*/
706: dmfstop(tp, flag)
707: register struct tty *tp;
708: {
709: register struct dmfdevice *addr;
710: register unit = minor(tp->t_dev) & 7;
711: int s;
712:
713: addr = (struct dmfdevice *)tp->t_addr;
714: /*
715: * Block input/output interrupts while messing with state.
716: */
717: s = spltty();
718: if (flag) {
719: addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
720: if (addr->dmftsc) {
721: /*
722: * Flush regardless of whether we're transmitting
723: * (TS_BUSY), if the silo contains untransmitted
724: * characters.
725: */
726: addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
727: addr->dmflctms = addr->dmflctms | DMF_TE | DMF_FLUSH;
728: /* this will interrupt so let dmfxint handle the rest */
729: tp->t_state |= TS_FLUSH|TS_BUSY;
730: }
731: } else {
732: if (tp->t_state & TS_BUSY) {
733: /*
734: * Stop transmission by disabling
735: * the transmitter. We'll pick up where we
736: * left off by reenabling in dmfstart.
737: */
738: addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
739: addr->dmflctms = addr->dmflctms &~ DMF_TE;
740: /* no interrupt here */
741: tp->t_state &= ~TS_BUSY;
742: }
743: }
744: splx(s);
745: }
746:
747: /*
748: * DMF32 modem control
749: */
750: dmfmctl(dev, bits, how)
751: dev_t dev;
752: int bits, how;
753: {
754: register struct dmfdevice *dmfaddr;
755: register int unit, mbits, lcr;
756: int s;
757:
758: unit = minor(dev);
759: dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
760: unit &= 07;
761: s = spltty();
762: dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
763: mbits = dmfaddr->dmfrms << 8;
764: dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
765: lcr = dmfaddr->dmflctms;
766: mbits |= (lcr & 0xff00) >> 8;
767: switch (how) {
768: case DMSET:
769: mbits = (mbits &0xff00) | bits;
770: break;
771:
772: case DMBIS:
773: mbits |= bits;
774: break;
775:
776: case DMBIC:
777: mbits &= ~bits;
778: break;
779:
780: case DMGET:
781: (void) splx(s);
782: return(mbits);
783: }
784: if (mbits & DMF_BRK)
785: lcr |= DMF_RBRK;
786: else
787: lcr &= ~DMF_RBRK;
788: dmfaddr->dmflctms = ((mbits & 037) << 8) | (lcr & 0xff);
789: (void) splx(s);
790: return(mbits);
791: }
792:
793: /*
794: * Reset state of driver if UBA reset was necessary.
795: * Reset the csr, lpr, and lcr registers on open lines, and
796: * restart transmitters.
797: */
798: dmfreset(uban)
799: int uban;
800: {
801: register int dmf, unit;
802: register struct tty *tp;
803: register struct uba_device *ui;
804: register struct dmfdevice *addr;
805: int i;
806:
807: for (dmf = 0; dmf < NDMF; dmf++) {
808: ui = dmfinfo[dmf];
809: if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
810: continue;
811: printf(" dmf%d", dmf);
812: if (dmf_ubinfo[uban]) {
813: dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
814: nclist*sizeof (struct cblock), 0);
815: cbase[uban] = UBAI_ADDR(dmf_ubinfo[uban]);
816: }
817: addr = (struct dmfdevice *)ui->ui_addr;
818: addr->dmfcsr = DMF_IE;
819: addr->dmfrsp = dmf_timeout;
820: unit = dmf * 8;
821: for (i = 0; i < 8; i++) {
822: tp = &dmf_tty[unit];
823: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
824: dmfparam(unit);
825: (void) dmfmctl(unit, DMF_ON, DMSET);
826: tp->t_state &= ~TS_BUSY;
827: dmfstart(tp);
828: }
829: unit++;
830: }
831: }
832: }
833:
834: /*
835: * dmflopen -- open the line printer port on a dmf32
836: */
837: /* ARGSUSED */
838: dmflopen(dev, flag)
839: dev_t dev;
840: int flag;
841: {
842: register int dmf;
843: register struct dmfl_softc *sc;
844: register struct uba_device *ui;
845: register struct dmfdevice *addr;
846:
847: dmf = DMFL_UNIT(dev);
848: if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
849: return (ENXIO);
850: sc = &dmfl_softc[dmf];
851: if (sc->dmfl_state & OPEN)
852: return (EBUSY);
853: addr = (struct dmfdevice *)ui->ui_addr;
854: if (addr->dmfl_ctrl & DMFL_OFFLINE) {
855: #ifdef notdef
856: log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
857: dmf);
858: #endif
859: return (EIO);
860: }
861: if ((addr->dmfl_ctrl & DMFL_CONV)) {
862: log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
863: return (EIO);
864: }
865:
866: addr->dmfl_ctrl = 0;
867: sc->dmfl_state |= OPEN;
868: return (0);
869: }
870:
871: /* ARGSUSED */
872: dmflclose(dev, flag)
873: dev_t dev;
874: int flag;
875: {
876: register int dmf = DMFL_UNIT(dev);
877: register struct dmfl_softc *sc = &dmfl_softc[dmf];
878: register struct uba_device *ui = dmfinfo[dmf];
879:
880: sc->dmfl_state = 0;
881: if (sc->dmfl_info != 0)
882: ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
883:
884: ((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
885: }
886:
887: dmflwrite(dev, uio)
888: dev_t dev;
889: struct uio *uio;
890: {
891: register int n;
892: register int error;
893: register struct dmfl_softc *sc;
894:
895: sc = &dmfl_softc[DMFL_UNIT(dev)];
896: if (sc->dmfl_state & ERROR)
897: return (EIO);
898: while (n = (unsigned)uio->uio_resid) {
899: if (n > DMFL_BUFSIZ) {
900: n = DMFL_BUFSIZ;
901: sc->dmfl_state |= MOREIO;
902: } else
903: sc->dmfl_state &= ~MOREIO;
904: if (error = uiomove(sc->dmfl_buf, (int)n, UIO_WRITE, uio))
905: return (error);
906: if (error = dmflout(dev, sc->dmfl_buf, n))
907: return (error);
908: }
909: return (0);
910: }
911:
912:
913: /*
914: * dmflout -- start io operation to dmf line printer
915: * cp is addr of buf of n chars to be sent.
916: *
917: * -- dmf will be put in formatted output mode, this will
918: * be selectable from an ioctl if the
919: * need ever arises.
920: */
921: dmflout(dev, cp, n)
922: dev_t dev;
923: char *cp;
924: int n;
925: {
926: register struct dmfl_softc *sc;
927: register int dmf;
928: register struct uba_device *ui;
929: register struct dmfdevice *d;
930: int s;
931:
932: dmf = DMFL_UNIT(dev);
933: sc = &dmfl_softc[dmf];
934: if (sc->dmfl_state & ERROR)
935: return (EIO);
936: ui = dmfinfo[dmf];
937: /*
938: * allocate unibus resources, will be released when io
939: * operation is done.
940: */
941: if (sc->dmfl_info == 0)
942: sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
943: d = (struct dmfdevice *)ui->ui_addr;
944: d->dmfl_ctrl = sc->dmfl_format; /* indir reg 2 */
945: /* indir reg auto increments on r/w */
946: /* SO DON'T CHANGE THE ORDER OF THIS CODE */
947: d->dmfl_indrct = 0; /* prefix chars & num */
948: d->dmfl_indrct = 0; /* suffix chars & num */
949: d->dmfl_indrct = sc->dmfl_info; /* dma lo 16 bits addr */
950: d->dmfl_indrct = -n; /* number of chars */
951:
952: d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
953: /* dma hi 2 bits addr */
954: d->dmfl_indrct = sc->dmfl_lines /* lines per page */
955: | (sc->dmfl_cols<<8); /* carriage width */
956: sc->dmfl_state |= ASLP;
957: s = spltty();
958: d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
959: while (sc->dmfl_state & ASLP) {
960: sleep(sc->dmfl_buf, PZERO + 8);
961: while (sc->dmfl_state & ERROR) {
962: timeout(dmflint, (caddr_t)dmf, 10 * hz);
963: sleep((caddr_t)&sc->dmfl_state, PZERO + 8);
964: }
965: }
966: splx(s);
967: return (0);
968: }
969:
970: /*
971: * dmflint -- handle an interrupt from the line printer part of the dmf32
972: */
973: dmflint(dmf)
974: int dmf;
975: {
976: register struct uba_device *ui;
977: register struct dmfl_softc *sc;
978: register struct dmfdevice *d;
979: short dmfl_stats;
980:
981: ui = dmfinfo[dmf];
982: sc = &dmfl_softc[dmf];
983: d = (struct dmfdevice *)ui->ui_addr;
984:
985: d->dmfl_ctrl &= ~DMFL_IE;
986: dmfl_stats = d->dmfl_ctrl;
987: if (sc->dmfl_state & ERROR) {
988: if ((dmfl_stats & DMFL_OFFLINE) == 0)
989: sc->dmfl_state &= ~ERROR;
990: wakeup((caddr_t)&sc->dmfl_state);
991: return;
992: }
993: if (dmfl_stats & DMFL_DMAERR)
994: log(LOG_WARNING, "dmf%d: NXM\n", dmf);
995: if (dmfl_stats & DMFL_OFFLINE) {
996: log(LOG_WARNING, "dmf%d: printer error\n", dmf);
997: sc->dmfl_state |= ERROR;
998: }
999: #ifdef notdef
1000: if (dmfl_stats & DMFL_PDONE) {
1001: printf("bytes= %d\n", d->dmfl_indrct);
1002: printf("lines= %d\n", d->dmfl_indrct);
1003: }
1004: #endif
1005: sc->dmfl_state &= ~ASLP;
1006: wakeup((caddr_t)sc->dmfl_buf);
1007: if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
1008: ubarelse(ui->ui_ubanum, &sc->dmfl_info);
1009: }
1010:
1011: /* stubs for interrupt routines for devices not yet supported */
1012:
1013: dmfsrint()
1014: {
1015: printf("dmfsrint\n");
1016: }
1017:
1018: dmfsxint()
1019: {
1020: printf("dmfsxint\n");
1021: }
1022:
1023: dmfdaint()
1024: {
1025: printf("dmfdaint\n");
1026: }
1027:
1028: dmfdbint()
1029: {
1030: printf("dmfdbint\n");
1031: }
1032: #endif NDMF
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.