|
|
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.12 (Berkeley) 4/12/90
7: */
8:
9: /*
10: * DMF32 driver
11: *
12: *
13: * TODO:
14: * test with modem
15: * load as much as possible into silo
16: * use auto XON/XOFF
17: * test reset code
18: */
19: #include "dmf.h"
20: #if NDMF > 0
21:
22: #ifndef NDMF_LP
23: #define NDMF_LP NDMF
24: #endif NDMF_LP
25: #include "machine/pte.h"
26:
27: #include "uba.h"
28: #include "param.h"
29: #include "conf.h"
30: #include "user.h"
31: #include "proc.h"
32: #include "ioctl.h"
33: #include "tty.h"
34: #include "map.h"
35: #include "buf.h"
36: #include "vm.h"
37: #include "bkmac.h"
38: #include "clist.h"
39: #include "file.h"
40: #include "uio.h"
41: #include "kernel.h"
42: #include "syslog.h"
43:
44: #include "dmx.h"
45: #include "ubareg.h"
46: #include "ubavar.h"
47: #include "dmxreg.h"
48: #include "dmfreg.h"
49: #include "dmreg.h"
50:
51: extern int dmx_timeout; /* silo timeout, in ms */
52: int dmfstart();
53:
54: /*
55: * The clist space is mapped by one terminal driver onto each UNIBUS.
56: * The identity of the board which allocated resources is recorded,
57: * so the process may be repeated after UNIBUS resets.
58: * The UBACVT macro converts a clist space address for unibus uban
59: * into an i/o space address for the DMA routine.
60: */
61: int dmf_uballoc[NUBA]; /* which dmf (if any) allocated unibus map */
62: int cbase[NUBA]; /* base address of clists in unibus map */
63:
64: /*
65: * Autoconfiguration and variables for DMF32
66: */
67: int dmfprobe(), dmfattach(), dmfrint(), dmfxint();
68: int dmflint();
69: struct uba_device *dmfinfo[NDMF];
70: u_short dmfstd[] = { 0 };
71: struct uba_driver dmfdriver =
72: { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
73:
74: struct tty dmf_tty[NDMF*8];
75: struct dmx_softc dmf_softc[NDMF];
76: #ifndef lint
77: int ndmf = NDMF*8; /* used by iostat */
78: #endif
79:
80: /*
81: * Routine for configuration to set dmf interrupt.
82: */
83: /*ARGSUSED*/
84: dmfprobe(reg, ctlr)
85: caddr_t reg;
86: struct uba_device *ctlr;
87: {
88: register int br, cvec; /* these are ``value-result'' */
89: register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
90: register int i;
91: register unsigned int a;
92: static char *dmfdevs[]=
93: {"parallel","printer","synch","asynch"};
94: unsigned int dmfoptions;
95: static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
96:
97: #ifdef lint
98: br = 0; cvec = br; br = cvec;
99: dmfxint(0); dmfrint(0);
100: dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
101: #endif
102: /*
103: * Pick the usual size DMF vector here (don't decrement it here).
104: * grab configuration; note that the DMF32
105: * doesn't seem to put the right bits in this
106: * register until AFTER the interrupt vector is set.
107: */
108: br = 0x15;
109: cvec = (uba_hd[numuba].uh_lastiv - 4*8);
110: dmfaddr->dmfccsr0 = (cvec >> 2);
111: dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
112:
113: /* catch a couple of special cases: Able vmz/32n and vmz/lp */
114: if (dmfoptions == DMFC_ASYNC) {
115: /* Async portion only */
116:
117: cvec = (uba_hd[numuba].uh_lastiv -= 8);
118: dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
119: intrv[0] = ctlr->ui_intr[4];
120: intrv[1] = ctlr->ui_intr[5];
121: ctlr->ui_intr = intrv;
122: } else if (dmfoptions == DMFC_LP) {
123: /* LP portion only */
124:
125: cvec = (uba_hd[numuba].uh_lastiv -= 8);
126: ctlr->ui_intr = &ctlr->ui_intr[6];
127: } else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
128: /* LP and Async portions only */
129:
130: cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
131: ctlr->ui_intr = &ctlr->ui_intr[4];
132: } else {
133: /* All other configurations get everything */
134:
135: cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
136: }
137: a = (dmfoptions >> 12) & 0xf;
138: printf("dmf%d:", ctlr->ui_unit);
139: for (i = 0; a != 0; ++i, a >>= 1) {
140: if (a & 1)
141: printf(" %s",dmfdevs[i]);
142: }
143: printf(".\n");
144:
145: if (dmfoptions & DMFC_LP)
146: dmfaddr->dmfl_ctrl = DMFL_RESET;
147: return (sizeof (struct dmfdevice));
148: }
149:
150: /*
151: * Routine called to attach a dmf.
152: */
153: dmfattach(ui)
154: register struct uba_device *ui;
155: {
156: register struct dmx_softc *sc;
157:
158: sc = &dmf_softc[ui->ui_unit];
159: sc->dmx_type = 'f';
160: sc->dmx_unit = ui->ui_unit;
161: sc->dmx_unit0 = 0;
162: sc->dmx_ubanum = ui->ui_ubanum;
163: sc->dmx_softCAR = ui->ui_flags & 0xff;
164: sc->dmx_tty = &dmf_tty[ui->ui_unit * 8];
165: sc->dmx_octet =
166: (struct dmx_octet *)&((struct dmfdevice *)ui->ui_addr)->dmfa;
167:
168: cbase[ui->ui_ubanum] = -1;
169: dmf_uballoc[ui->ui_ubanum] = -1;
170: #if NDMF_LP > 0
171: dmflattach(ui);
172: #endif NDMF_LP
173: }
174:
175: /*
176: * Open a DMF32 line, mapping the clist onto the uba if this
177: * is the first dmf on this uba. Turn on this dmf if this is
178: * the first use of it.
179: */
180: /*ARGSUSED*/
181: dmfopen(dev, flag)
182: dev_t dev;
183: {
184: register struct tty *tp;
185: register struct dmx_softc *sc;
186: int unit, dmf;
187: register struct dmfdevice *addr;
188: register struct uba_device *ui;
189: int s;
190: int dmxparam();
191:
192: unit = minor(dev);
193: if (unit & 0200)
194: return (dmflopen(dev,flag));
195: dmf = unit >> 3;
196: if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
197: return (ENXIO);
198:
199: tp = &dmf_tty[unit];
200: sc = &dmf_softc[dmf];
201: addr = (struct dmfdevice *)ui->ui_addr;
202: tp->t_addr = (caddr_t)(&addr->dmfa);
203: tp->t_oproc = dmfstart;
204: tp->t_dev = dev; /* needed before dmxopen */
205: tp->t_param = dmxparam;
206:
207: /*
208: * While setting up state for this uba,
209: * block uba resets which can clear the state.
210: */
211: s = spl6();
212: if (cbase[ui->ui_ubanum] == -1) {
213: dmf_uballoc[ui->ui_ubanum] = dmf;
214: cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
215: (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
216: }
217: splx(s);
218:
219: return (dmxopen(tp, sc, flag));
220: }
221:
222: /*
223: * Close a DMF32 line.
224: */
225: /*ARGSUSED*/
226: dmfclose(dev, flag)
227: dev_t dev;
228: int flag;
229: {
230: register unit;
231:
232: unit = minor(dev);
233: if (unit & 0200) {
234: dmflclose(dev, flag);
235: return;
236: }
237: return (dmxclose(&dmf_tty[unit]));
238: }
239:
240: dmfread(dev, uio, flag)
241: dev_t dev;
242: struct uio *uio;
243: {
244: register struct tty *tp;
245:
246: if (minor(dev) & 0200)
247: return(ENXIO);
248: tp = &dmf_tty[minor(dev)];
249: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
250: }
251:
252: dmfwrite(dev, uio)
253: dev_t dev;
254: struct uio *uio;
255: {
256: register struct tty *tp;
257:
258: if (minor(dev) & 0200)
259: return (dmflwrite(dev,uio));
260: tp = &dmf_tty[minor(dev)];
261: return ((*linesw[tp->t_line].l_write)(tp, uio));
262: }
263:
264: /*
265: * DMF32 receiver interrupt.
266: */
267: dmfrint(dmf)
268: int dmf;
269: {
270: struct uba_device *ui;
271:
272: ui = dmfinfo[dmf];
273: if (ui == 0 || ui->ui_alive == 0)
274: return;
275: dmxrint(&dmf_softc[dmf]);
276: }
277:
278: /*
279: * Ioctl for DMF32.
280: */
281: dmfioctl(dev, cmd, data, flag)
282: dev_t dev;
283: caddr_t data;
284: {
285: int unit = minor(dev);
286:
287: if (unit & 0200)
288: return (ENOTTY);
289: return (dmxioctl(&dmf_tty[unit], cmd, data, flag));
290: }
291:
292: /*
293: * DMF32 transmitter interrupt.
294: * Restart the idle line.
295: */
296: dmfxint(dmf)
297: int dmf;
298: {
299:
300: dmxxint(&dmf_softc[dmf]);
301: }
302:
303: /*
304: * Start (restart) transmission on the given line.
305: */
306: dmfstart(tp)
307: struct tty *tp;
308: {
309:
310: dmxstart(tp, &dmf_softc[minor(tp->t_dev) >> 3]);
311: }
312:
313: /*
314: * Stop output on a line, e.g. for ^S/^Q or output flush.
315: */
316: dmfstop(tp, flag)
317: struct tty *tp;
318: {
319:
320: dmxstop(tp, &dmf_softc[minor(tp->t_dev) >> 3], flag);
321: }
322:
323: /*
324: * Reset state of driver if UBA reset was necessary.
325: * Reset the csr, lpr, and lcr registers on open lines, and
326: * restart transmitters.
327: */
328: dmfreset(uban)
329: int uban;
330: {
331: register int dmf;
332: register struct tty *tp;
333: register struct uba_device *ui;
334: register struct dmfdevice *addr;
335: int i;
336:
337: for (dmf = 0; dmf < NDMF; dmf++) {
338: ui = dmfinfo[dmf];
339: if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
340: continue;
341: printf(" dmf%d", dmf);
342: if (dmf_uballoc[uban] == dmf) {
343: int info;
344:
345: info = uballoc(uban, (caddr_t)cfree,
346: nclist * sizeof(struct cblock), UBA_CANTWAIT);
347: if (info)
348: cbase[uban] = UBAI_ADDR(info);
349: else {
350: printf(" [can't get uba map]");
351: cbase[uban] = -1;
352: }
353: }
354: addr = (struct dmfdevice *)ui->ui_addr;
355: addr->dmfa.csr = DMF_IE;
356: addr->dmfa.rsp = dmx_timeout;
357: tp = &dmf_tty[dmf * 8];
358: for (i = 0; i < 8; i++, tp++) {
359: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
360: dmxparam(tp, &tp->t_termios);
361: (void) dmxmctl(tp, DMF_ON, DMSET);
362: tp->t_state &= ~TS_BUSY;
363: dmfstart(tp);
364: }
365: }
366: #if NDMF_LP > 0
367: dmflint(dmf);
368: #endif
369: }
370: }
371:
372: #if NDMF_LP > 0
373: /*
374: * DMF32 line printer driver
375: *
376: * the line printer on dmfx is indicated by a minor device code of 128+x
377: *
378: * the flags field of the config file is interpreted like so:
379: * bits meaning
380: * ---- -------
381: * 0-7 soft carrier bits for ttys part of dmf32
382: * 8-15 number of cols/line on the line printer
383: * if 0, 132 will be used.
384: * 16-23 number of lines/page on the line printer
385: * if 0, 66 will be used.
386: * 24 if 1 DO NOT use the auto format mode of the
387: * line printer parallel port
388: */
389:
390: struct dmfl_softc {
391: u_int dmfl_state; /* soft state bits */
392: int dmfl_info; /* uba info */
393: u_short dmfl_lines; /* lines per page (66 def.) */
394: u_short dmfl_cols; /* cols per line (132 def.) */
395: u_short dmfl_format; /* fflag for auto form feed */
396: char dmfl_buf[DMFL_BUFSIZ];
397: } dmfl_softc[NDMF];
398:
399: /*
400: * convert device number into DMF line printer unit number
401: */
402: #define DMFL_UNIT(d) (minor(d) & 0xf) /* up to 16 DMFs */
403:
404: #define ASLP 1 /* waiting for interrupt from dmf */
405: #define OPEN 2 /* line printer is open */
406: #define ERROR 4 /* error while printing, driver
407: refuses to do anything till closed */
408: #define MOREIO 8 /* more data for printer */
409:
410: /*
411: * Attach printer portion of dmf.
412: */
413: dmflattach(ui)
414: register struct uba_device *ui;
415: {
416: register int unit = ui->ui_unit;
417: register int cols = (ui->ui_flags>>8) & 0xff;
418: register int lines = (ui->ui_flags>>16) & 0xff;
419: register struct dmfl_softc *sc;
420:
421: sc = &dmfl_softc[unit];
422: sc->dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
423: sc->dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
424: if ((ui->ui_flags >> 24) & 0x1)
425: sc->dmfl_format = (2 << 8);
426: else
427: sc->dmfl_format = (2 << 8) | DMFL_FORMAT;
428: }
429:
430: /*
431: * dmflopen -- open the line printer port on a dmf32
432: */
433: /* ARGSUSED */
434: dmflopen(dev, flag)
435: dev_t dev;
436: int flag;
437: {
438: register int dmf;
439: register struct dmfl_softc *sc;
440: register struct uba_device *ui;
441: register struct dmfdevice *addr;
442:
443: dmf = DMFL_UNIT(dev);
444: if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
445: return (ENXIO);
446: sc = &dmfl_softc[dmf];
447: if (sc->dmfl_state & OPEN)
448: return (EBUSY);
449: addr = (struct dmfdevice *)ui->ui_addr;
450: if (addr->dmfl_ctrl & DMFL_OFFLINE) {
451: #ifdef notdef
452: log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
453: dmf);
454: #endif
455: return (EIO);
456: }
457: if ((addr->dmfl_ctrl & DMFL_CONV)) {
458: log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
459: return (EIO);
460: }
461:
462: addr->dmfl_ctrl = 0;
463: sc->dmfl_state |= OPEN;
464: return (0);
465: }
466:
467: /* ARGSUSED */
468: dmflclose(dev, flag)
469: dev_t dev;
470: int flag;
471: {
472: register int dmf = DMFL_UNIT(dev);
473: register struct dmfl_softc *sc = &dmfl_softc[dmf];
474: register struct uba_device *ui = dmfinfo[dmf];
475:
476: sc->dmfl_state = 0;
477: if (sc->dmfl_info != 0)
478: ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
479:
480: ((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
481: }
482:
483: dmflwrite(dev, uio)
484: dev_t dev;
485: struct uio *uio;
486: {
487: register int n;
488: register int error;
489: register struct dmfl_softc *sc;
490:
491: sc = &dmfl_softc[DMFL_UNIT(dev)];
492: if (sc->dmfl_state & ERROR)
493: return (EIO);
494: while (n = (unsigned)uio->uio_resid) {
495: if (n > DMFL_BUFSIZ) {
496: n = DMFL_BUFSIZ;
497: sc->dmfl_state |= MOREIO;
498: } else
499: sc->dmfl_state &= ~MOREIO;
500: if (error = uiomove(sc->dmfl_buf, (int)n, uio))
501: return (error);
502: if (error = dmflout(dev, sc->dmfl_buf, n))
503: return (error);
504: }
505: return (0);
506: }
507:
508:
509: /*
510: * dmflout -- start io operation to dmf line printer
511: * cp is addr of buf of n chars to be sent.
512: *
513: * -- dmf will be put in formatted output mode, this will
514: * be selectable from an ioctl if the
515: * need ever arises.
516: */
517: dmflout(dev, cp, n)
518: dev_t dev;
519: char *cp;
520: int n;
521: {
522: register struct dmfl_softc *sc;
523: register int dmf;
524: register struct uba_device *ui;
525: register struct dmfdevice *d;
526: int s, error;
527:
528: dmf = DMFL_UNIT(dev);
529: sc = &dmfl_softc[dmf];
530: if (sc->dmfl_state & ERROR)
531: return (EIO);
532: ui = dmfinfo[dmf];
533: /*
534: * allocate unibus resources, will be released when io
535: * operation is done.
536: */
537: if (sc->dmfl_info == 0)
538: sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
539: d = (struct dmfdevice *)ui->ui_addr;
540: d->dmfl_ctrl = sc->dmfl_format; /* indir reg 2 */
541: /* indir reg auto increments on r/w */
542: /* SO DON'T CHANGE THE ORDER OF THIS CODE */
543: d->dmfl_indrct = 0; /* prefix chars & num */
544: d->dmfl_indrct = 0; /* suffix chars & num */
545: d->dmfl_indrct = sc->dmfl_info; /* dma lo 16 bits addr */
546: d->dmfl_indrct = -n; /* number of chars */
547:
548: d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
549: /* dma hi 2 bits addr */
550: d->dmfl_indrct = sc->dmfl_lines /* lines per page */
551: | (sc->dmfl_cols<<8); /* carriage width */
552: sc->dmfl_state |= ASLP;
553: error = 0;
554: s = spltty();
555: d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
556: while (sc->dmfl_state & ASLP) {
557: if (error = tsleep(sc->dmfl_buf, (PZERO + 8) | PCATCH,
558: ttyout, 0))
559: break;
560: while (sc->dmfl_state & ERROR) {
561: timeout(dmflint, (caddr_t)dmf, 10 * hz);
562: if (error = tsleep((caddr_t)&sc->dmfl_state,
563: (PZERO + 8) | PCATCH, ttyout, 0))
564: goto out;
565: }
566: }
567: out:
568: splx(s);
569: return (0);
570: }
571:
572: /*
573: * dmflint -- handle an interrupt from the line printer part of the dmf32
574: */
575: dmflint(dmf)
576: int dmf;
577: {
578: register struct uba_device *ui;
579: register struct dmfl_softc *sc;
580: register struct dmfdevice *d;
581: short dmfl_stats;
582:
583: ui = dmfinfo[dmf];
584: sc = &dmfl_softc[dmf];
585: d = (struct dmfdevice *)ui->ui_addr;
586:
587: d->dmfl_ctrl &= ~DMFL_IE;
588: dmfl_stats = d->dmfl_ctrl;
589: if (sc->dmfl_state & ERROR) {
590: if ((dmfl_stats & DMFL_OFFLINE) == 0)
591: sc->dmfl_state &= ~ERROR;
592: wakeup((caddr_t)&sc->dmfl_state);
593: return;
594: }
595: if (dmfl_stats & DMFL_DMAERR)
596: log(LOG_WARNING, "dmf%d: NXM\n", dmf);
597: if (dmfl_stats & DMFL_OFFLINE) {
598: log(LOG_WARNING, "dmf%d: printer error\n", dmf);
599: sc->dmfl_state |= ERROR;
600: }
601: #ifdef notdef
602: if (dmfl_stats & DMFL_PDONE) {
603: printf("bytes= %d\n", d->dmfl_indrct);
604: printf("lines= %d\n", d->dmfl_indrct);
605: }
606: #endif
607: sc->dmfl_state &= ~ASLP;
608: wakeup((caddr_t)sc->dmfl_buf);
609: if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
610: ubarelse(ui->ui_ubanum, &sc->dmfl_info);
611: }
612: #endif NDMF_LP
613:
614: /* stubs for interrupt routines for devices not yet supported */
615:
616: dmfsrint()
617: {
618: printf("dmfsrint\n");
619: }
620:
621: dmfsxint()
622: {
623: printf("dmfsxint\n");
624: }
625:
626: dmfdaint()
627: {
628: printf("dmfdaint\n");
629: }
630:
631: dmfdbint()
632: {
633: printf("dmfdbint\n");
634: }
635: #endif NDMF
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.