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