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