xref: /csrg-svn/sys/vax/uba/dmf.c (revision 30537)
123324Smckusick /*
229213Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323324Smckusick  * All rights reserved.  The Berkeley software License Agreement
423324Smckusick  * specifies the terms and conditions for redistribution.
523324Smckusick  *
6*30537Skarels  *	@(#)dmf.c	7.4 (Berkeley) 02/19/87
723324Smckusick  */
86940Ssam 
96940Ssam /*
106940Ssam  * DMF32 driver
116940Ssam  *
1221955Sbloom  *
136940Ssam  * TODO:
146940Ssam  *	test with modem
156940Ssam  *	load as much as possible into silo
166940Ssam  *	use auto XON/XOFF
176940Ssam  *	test reset code
186940Ssam  */
19*30537Skarels #include "dmf.h"
20*30537Skarels #if NDMF > 0
21*30537Skarels 
22*30537Skarels #ifndef NDMF_LP
23*30537Skarels #define	NDMF_LP	NDMF
24*30537Skarels #endif	NDMF_LP
259772Ssam #include "../machine/pte.h"
269772Ssam 
276940Ssam #include "bk.h"
2816063Skarels #include "uba.h"
2917124Sbloom #include "param.h"
3017124Sbloom #include "conf.h"
3117124Sbloom #include "dir.h"
3217124Sbloom #include "user.h"
3326836Skarels #include "proc.h"
3417124Sbloom #include "ioctl.h"
3517124Sbloom #include "tty.h"
3617124Sbloom #include "map.h"
3717124Sbloom #include "buf.h"
3817124Sbloom #include "vm.h"
3917124Sbloom #include "bkmac.h"
4017124Sbloom #include "clist.h"
4117124Sbloom #include "file.h"
4217124Sbloom #include "uio.h"
4321955Sbloom #include "kernel.h"
4418312Sralph #include "syslog.h"
456940Ssam 
46*30537Skarels #include "dmx.h"
4717124Sbloom #include "ubareg.h"
4817124Sbloom #include "ubavar.h"
49*30537Skarels #include "dmxreg.h"
5017124Sbloom #include "dmfreg.h"
51*30537Skarels #include "dmreg.h"
528473Sroot 
53*30537Skarels extern	int dmx_timeout;		/* silo timeout, in ms */
54*30537Skarels extern	char dmx_speeds[];
55*30537Skarels int	dmfstart();
56*30537Skarels 
576940Ssam /*
58*30537Skarels  * The clist space is mapped by one terminal driver onto each UNIBUS.
59*30537Skarels  * The identity of the board which allocated resources is recorded,
60*30537Skarels  * so the process may be repeated after UNIBUS resets.
61*30537Skarels  * The UBACVT macro converts a clist space address for unibus uban
62*30537Skarels  * into an i/o space address for the DMA routine.
636940Ssam  */
64*30537Skarels int	dmf_uballoc[NUBA];	/* which dmf (if any) allocated unibus map */
65*30537Skarels int	cbase[NUBA];		/* base address of clists in unibus map */
66*30537Skarels 
67*30537Skarels /*
68*30537Skarels  * Autoconfiguration and variables for DMF32
69*30537Skarels  */
706940Ssam int	dmfprobe(), dmfattach(), dmfrint(), dmfxint();
7121955Sbloom int	dmflint();
726940Ssam struct	uba_device *dmfinfo[NDMF];
736940Ssam u_short	dmfstd[] = { 0 };
746940Ssam struct	uba_driver dmfdriver =
756940Ssam 	{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
766940Ssam 
776940Ssam struct	tty dmf_tty[NDMF*8];
78*30537Skarels struct	dmx_softc dmf_softc[NDMF];
798778Sroot #ifndef lint
808778Sroot int	ndmf = NDMF*8;			/* used by iostat */
818778Sroot #endif
826940Ssam 
836940Ssam /*
846940Ssam  * Routine for configuration to set dmf interrupt.
856940Ssam  */
866940Ssam /*ARGSUSED*/
876940Ssam dmfprobe(reg, ctlr)
886940Ssam 	caddr_t reg;
8921955Sbloom 	struct uba_device *ctlr;
906940Ssam {
916940Ssam 	register int br, cvec;		/* these are ``value-result'' */
926940Ssam 	register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
9321955Sbloom 	register int i;
9421955Sbloom 	register unsigned int a;
9521955Sbloom 	static char *dmfdevs[]=
9621955Sbloom 		{"parallel","printer","synch","asynch"};
9721955Sbloom 	unsigned int dmfoptions;
9825449Skarels 	static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
996940Ssam 
1006940Ssam #ifdef lint
1016940Ssam 	br = 0; cvec = br; br = cvec;
1028808Sroot 	dmfxint(0); dmfrint(0);
10326366Skarels 	dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
1046940Ssam #endif
10521955Sbloom 	/*
10621955Sbloom 	 * Pick the usual size DMF vector here (don't decrement it here).
10721955Sbloom 	 * grab configuration; note that the DMF32
10821955Sbloom 	 * doesn't seem to put the right bits in this
10921955Sbloom 	 * register until AFTER the interrupt vector is set.
11021955Sbloom 	 */
1116940Ssam 	br = 0x15;
11221955Sbloom 	cvec = (uba_hd[numuba].uh_lastiv - 4*8);
11325449Skarels 	dmfaddr->dmfccsr0 = (cvec >> 2);
11421955Sbloom 	dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
11521955Sbloom 
11621955Sbloom 	/* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
11721955Sbloom 	if (dmfoptions == DMFC_ASYNC) {
11825449Skarels 		/* Async portion only */
11925449Skarels 
12025449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
12125449Skarels 		dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
12225449Skarels 		intrv[0] = ctlr->ui_intr[4];
12325449Skarels 		intrv[1] = ctlr->ui_intr[5];
12425449Skarels 		ctlr->ui_intr = intrv;
12526312Skarels 	} else if (dmfoptions == DMFC_LP) {
12625449Skarels 		/* LP portion only */
12721955Sbloom 
12825449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
12925449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[6];
13026312Skarels 	} else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
131*30537Skarels 		/* LP and Async portions only */
13225449Skarels 
13325449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
13425449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[4];
13526312Skarels 	} else {
13625449Skarels 		/* All other configurations get everything */
13721955Sbloom 
13821955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
13921955Sbloom 	}
14025449Skarels 	a = (dmfoptions >> 12) & 0xf;
14125449Skarels 	printf("dmf%d:", ctlr->ui_unit);
14226312Skarels 	for (i = 0; a != 0; ++i, a >>= 1) {
14326312Skarels 		if (a & 1)
14425449Skarels 			printf(" %s",dmfdevs[i]);
14525449Skarels 	}
14625449Skarels 	printf(".\n");
14721955Sbloom 
14821955Sbloom 	if (dmfoptions & DMFC_LP)
14927057Skarels 		dmfaddr->dmfl_ctrl = DMFL_RESET;
1507412Skre 	return (sizeof (struct dmfdevice));
1516940Ssam }
1526940Ssam 
1536940Ssam /*
1546940Ssam  * Routine called to attach a dmf.
1556940Ssam  */
1566940Ssam dmfattach(ui)
157*30537Skarels 	register struct uba_device *ui;
1586940Ssam {
159*30537Skarels 	register struct dmx_softc *sc;
1606940Ssam 
161*30537Skarels 	sc = &dmf_softc[ui->ui_unit];
162*30537Skarels 	sc->dmx_type = 'f';
163*30537Skarels 	sc->dmx_unit = ui->ui_unit;
164*30537Skarels 	sc->dmx_unit0 = 0;
165*30537Skarels 	sc->dmx_ubanum = ui->ui_ubanum;
166*30537Skarels 	sc->dmx_softCAR = ui->ui_flags & 0xff;
167*30537Skarels 	sc->dmx_tty = &dmf_tty[ui->ui_unit * 8];
168*30537Skarels 	sc->dmx_octet =
169*30537Skarels 	    (struct dmx_octet *)&((struct dmfdevice *)ui->ui_addr)->dmfa;
170*30537Skarels 
17126221Skarels 	cbase[ui->ui_ubanum] = -1;
17230322Skarels 	dmf_uballoc[ui->ui_unit] = -1;
173*30537Skarels #if NDMF_LP > 0
174*30537Skarels 	dmflattach(ui);
175*30537Skarels #endif NDMF_LP
1766940Ssam }
1776940Ssam 
1786940Ssam /*
1796940Ssam  * Open a DMF32 line, mapping the clist onto the uba if this
1806940Ssam  * is the first dmf on this uba.  Turn on this dmf if this is
1816940Ssam  * the first use of it.
1826940Ssam  */
1836940Ssam /*ARGSUSED*/
1846940Ssam dmfopen(dev, flag)
1856940Ssam 	dev_t dev;
1866940Ssam {
1876940Ssam 	register struct tty *tp;
188*30537Skarels 	register struct dmx_softc *sc;
189*30537Skarels 	int unit, dmf;
1906940Ssam 	register struct dmfdevice *addr;
1916940Ssam 	register struct uba_device *ui;
1926940Ssam 	int s;
1936940Ssam 
1946940Ssam 	unit = minor(dev);
19526312Skarels 	if (unit & 0200)
19626312Skarels 		return (dmflopen(dev,flag));
1976940Ssam 	dmf = unit >> 3;
1988567Sroot 	if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
1998567Sroot 		return (ENXIO);
200*30537Skarels 
2016940Ssam 	tp = &dmf_tty[unit];
202*30537Skarels 	sc = &dmf_softc[dmf];
2036940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
204*30537Skarels 	tp->t_addr = (caddr_t)(&addr->dmfa);
2056940Ssam 	tp->t_oproc = dmfstart;
206*30537Skarels 	tp->t_dev = dev;			/* needed before dmxopen */
207*30537Skarels 
2086940Ssam 	/*
209*30537Skarels 	 * While setting up state for this uba,
2106940Ssam 	 * block uba resets which can clear the state.
2116940Ssam 	 */
212*30537Skarels 	s = spl6();
21326221Skarels 	if (cbase[ui->ui_ubanum] == -1) {
21430322Skarels 		dmf_uballoc[ui->ui_ubanum] = dmf;
21530322Skarels 		cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
21630322Skarels 		    (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
2176940Ssam 	}
2186940Ssam 	splx(s);
219*30537Skarels 
220*30537Skarels 	return (dmxopen(tp, sc));
2216940Ssam }
2226940Ssam 
2236940Ssam /*
2246940Ssam  * Close a DMF32 line.
2256940Ssam  */
2266940Ssam /*ARGSUSED*/
2276940Ssam dmfclose(dev, flag)
2286940Ssam 	dev_t dev;
2296940Ssam 	int flag;
2306940Ssam {
2316940Ssam 	register unit;
2326940Ssam 
2336940Ssam 	unit = minor(dev);
23426312Skarels 	if (unit & 0200) {
235*30537Skarels 		dmflclose(dev, flag);
23626312Skarels 		return;
23726312Skarels 	}
238*30537Skarels 	dmxclose(&dmf_tty[unit]);
2396940Ssam }
2406940Ssam 
2417726Sroot dmfread(dev, uio)
2426940Ssam 	dev_t dev;
2437726Sroot 	struct uio *uio;
2446940Ssam {
2456940Ssam 	register struct tty *tp;
2466940Ssam 
24726312Skarels 	if (minor(dev) & 0200)
24821955Sbloom 		return(ENXIO);
2496940Ssam 	tp = &dmf_tty[minor(dev)];
2507726Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
2516940Ssam }
2526940Ssam 
2537832Sroot dmfwrite(dev, uio)
2546940Ssam 	dev_t dev;
2557832Sroot 	struct uio *uio;
2566940Ssam {
2576940Ssam 	register struct tty *tp;
2586940Ssam 
25926312Skarels 	if (minor(dev) & 0200)
26026312Skarels 		return (dmflwrite(dev,uio));
2616940Ssam 	tp = &dmf_tty[minor(dev)];
2628530Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
2636940Ssam }
2646940Ssam 
2656940Ssam /*
2666940Ssam  * DMF32 receiver interrupt.
2676940Ssam  */
2686940Ssam dmfrint(dmf)
2696940Ssam 	int dmf;
2706940Ssam {
271*30537Skarels 	struct uba_device *ui;
2726940Ssam 
27326312Skarels 	ui = dmfinfo[dmf];
27426312Skarels 	if (ui == 0 || ui->ui_alive == 0)
27526312Skarels 		return;
276*30537Skarels 	dmxrint(&dmf_softc[dmf]);
2776940Ssam }
2786940Ssam 
2796940Ssam /*
2806940Ssam  * Ioctl for DMF32.
2816940Ssam  */
2827630Ssam dmfioctl(dev, cmd, data, flag)
2836940Ssam 	dev_t dev;
2847630Ssam 	caddr_t data;
2856940Ssam {
286*30537Skarels 	int unit = minor(dev);
2876940Ssam 
28826312Skarels 	if (unit & 0200)
28921955Sbloom 		return (ENOTTY);
290*30537Skarels 	return (dmxioctl(&dmf_tty[unit], cmd, data, flag));
2916940Ssam }
2926940Ssam 
2936940Ssam /*
2946940Ssam  * DMF32 transmitter interrupt.
2956940Ssam  * Restart the idle line.
2966940Ssam  */
2976940Ssam dmfxint(dmf)
2986940Ssam 	int dmf;
2996940Ssam {
3006940Ssam 
301*30537Skarels 	dmxxint(&dmf_softc[dmf]);
3026940Ssam }
3036940Ssam 
3046940Ssam /*
305*30537Skarels  * Start (restart) transmission on the given line.
3066940Ssam  */
3076940Ssam dmfstart(tp)
308*30537Skarels 	struct tty *tp;
3096940Ssam {
3106940Ssam 
311*30537Skarels 	dmxstart(tp, &dmf_softc[minor(tp->t_dev) >> 3]);
3126940Ssam }
3136940Ssam 
3146940Ssam /*
3156940Ssam  * Stop output on a line, e.g. for ^S/^Q or output flush.
3166940Ssam  */
3176940Ssam dmfstop(tp, flag)
318*30537Skarels 	struct tty *tp;
3196940Ssam {
3206940Ssam 
321*30537Skarels 	dmxstop(tp, &dmf_softc[minor(tp->t_dev) >> 3], flag);
3226940Ssam }
3236940Ssam 
3246940Ssam /*
3256940Ssam  * Reset state of driver if UBA reset was necessary.
3266940Ssam  * Reset the csr, lpr, and lcr registers on open lines, and
3276940Ssam  * restart transmitters.
3286940Ssam  */
3296940Ssam dmfreset(uban)
3306940Ssam 	int uban;
3316940Ssam {
332*30537Skarels 	register int dmf;
3336940Ssam 	register struct tty *tp;
3346940Ssam 	register struct uba_device *ui;
3356940Ssam 	register struct dmfdevice *addr;
3366940Ssam 	int i;
3376940Ssam 
3386940Ssam 	for (dmf = 0; dmf < NDMF; dmf++) {
3396940Ssam 		ui = dmfinfo[dmf];
3406940Ssam 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
3416940Ssam 			continue;
3426940Ssam 		printf(" dmf%d", dmf);
34330322Skarels 		if (dmf_uballoc[uban] == dmf) {
34430322Skarels 			int info;
34530322Skarels 
34630322Skarels 			info = uballoc(uban, (caddr_t)cfree,
34730322Skarels 			    nclist * sizeof(struct cblock), UBA_CANTWAIT);
34830322Skarels 			if (info)
34930322Skarels 				cbase[uban] = UBAI_ADDR(info);
35030322Skarels 			else {
35130322Skarels 				printf(" [can't get uba map]");
35230322Skarels 				cbase[uban] = -1;
35330322Skarels 			}
35425449Skarels 		}
3556940Ssam 		addr = (struct dmfdevice *)ui->ui_addr;
356*30537Skarels 		addr->dmfa.csr = DMF_IE;
357*30537Skarels 		addr->dmfa.rsp = dmx_timeout;
358*30537Skarels 		tp = &dmf_tty[dmf * 8];
359*30537Skarels 		for (i = 0; i < 8; i++, tp++) {
3606971Ssam 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
361*30537Skarels 				dmxparam(tp);
362*30537Skarels 				(void) dmxmctl(tp, DMF_ON, DMSET);
3636971Ssam 				tp->t_state &= ~TS_BUSY;
3646940Ssam 				dmfstart(tp);
3656940Ssam 			}
3666940Ssam 		}
367*30537Skarels #if NDMF_LP > 0
368*30537Skarels 		dmflint(dmf);
369*30537Skarels #endif
3706940Ssam 	}
3716940Ssam }
3726940Ssam 
373*30537Skarels #if NDMF_LP > 0
37426312Skarels /*
375*30537Skarels  * DMF32 line printer driver
376*30537Skarels  *
377*30537Skarels  * the line printer on dmfx is indicated by a minor device code of 128+x
378*30537Skarels  *
379*30537Skarels  * the flags field of the config file is interpreted like so:
380*30537Skarels  * bits		meaning
381*30537Skarels  * ----		-------
382*30537Skarels  * 0-7		soft carrier bits for ttys part of dmf32
383*30537Skarels  * 8-15		number of cols/line on the line printer
384*30537Skarels  *			if 0, 132 will be used.
385*30537Skarels  * 16-23	number of lines/page on the line printer
386*30537Skarels  *			if 0, 66 will be used.
387*30537Skarels  * 24		if 1 DO NOT use the auto format mode of the
388*30537Skarels  *			line printer parallel port
389*30537Skarels  */
390*30537Skarels 
391*30537Skarels struct dmfl_softc {
392*30537Skarels 	u_int	dmfl_state; 		/* soft state bits */
393*30537Skarels 	int	dmfl_info;		/* uba info */
394*30537Skarels 	u_short	dmfl_lines;		/* lines per page (66 def.) */
395*30537Skarels 	u_short	dmfl_cols; 		/* cols per line (132 def.) */
396*30537Skarels 	u_short	dmfl_format;		/* fflag for auto form feed */
397*30537Skarels 	char	dmfl_buf[DMFL_BUFSIZ];
398*30537Skarels } dmfl_softc[NDMF];
399*30537Skarels 
400*30537Skarels /*
401*30537Skarels  * convert device number into DMF line printer unit number
402*30537Skarels  */
403*30537Skarels #define	DMFL_UNIT(d)	(minor(d) & 0xf)	/* up to 16 DMFs */
404*30537Skarels 
405*30537Skarels #define ASLP 1		/* waiting for interrupt from dmf */
406*30537Skarels #define OPEN 2		/* line printer is open */
407*30537Skarels #define ERROR 4		/* error while printing, driver
408*30537Skarels 			 refuses to do anything till closed */
409*30537Skarels #define MOREIO 8	/* more data for printer */
410*30537Skarels 
411*30537Skarels /*
412*30537Skarels  * Attach printer portion of dmf.
413*30537Skarels  */
414*30537Skarels dmflattach(ui)
415*30537Skarels 	register struct uba_device *ui;
416*30537Skarels {
417*30537Skarels 	register int unit = ui->ui_unit;
418*30537Skarels 	register int cols = (ui->ui_flags>>8) & 0xff;
419*30537Skarels 	register int lines = (ui->ui_flags>>16) & 0xff;
420*30537Skarels 	register struct dmfl_softc *sc;
421*30537Skarels 
422*30537Skarels 	sc = &dmfl_softc[unit];
423*30537Skarels 	sc->dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
424*30537Skarels 	sc->dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
425*30537Skarels  	if ((ui->ui_flags >> 24) & 0x1)
426*30537Skarels  		sc->dmfl_format = (2 << 8);
427*30537Skarels  	else
428*30537Skarels  		sc->dmfl_format = (2 << 8) | DMFL_FORMAT;
429*30537Skarels }
430*30537Skarels 
431*30537Skarels /*
43226312Skarels  * dmflopen -- open the line printer port on a dmf32
43321955Sbloom  */
43426312Skarels /* ARGSUSED */
43526312Skarels dmflopen(dev, flag)
43626312Skarels 	dev_t dev;
43726312Skarels 	int flag;
43821955Sbloom {
43921955Sbloom 	register int dmf;
44021955Sbloom 	register struct dmfl_softc *sc;
44121955Sbloom 	register struct uba_device *ui;
44221955Sbloom 	register struct dmfdevice *addr;
44321955Sbloom 
44426312Skarels 	dmf = DMFL_UNIT(dev);
44526910Skarels 	if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
44626910Skarels 		return (ENXIO);
44726910Skarels 	sc = &dmfl_softc[dmf];
44826910Skarels 	if (sc->dmfl_state & OPEN)
44926910Skarels 		return (EBUSY);
45021955Sbloom 	addr = (struct dmfdevice *)ui->ui_addr;
45126910Skarels 	if (addr->dmfl_ctrl & DMFL_OFFLINE) {
45226910Skarels #ifdef notdef
45326910Skarels 		log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
45426910Skarels 			dmf);
45526910Skarels #endif
45626312Skarels 		return (EIO);
45721955Sbloom 	}
45826910Skarels 	if ((addr->dmfl_ctrl & DMFL_CONV)) {
45926910Skarels 		log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
46026312Skarels 		return (EIO);
46121955Sbloom 	}
46221955Sbloom 
46326910Skarels 	addr->dmfl_ctrl = 0;
46421955Sbloom 	sc->dmfl_state |= OPEN;
46526312Skarels 	return (0);
46621955Sbloom }
46721955Sbloom 
46826312Skarels /* ARGSUSED */
46926312Skarels dmflclose(dev, flag)
47026312Skarels 	dev_t dev;
47126312Skarels 	int flag;
47221955Sbloom {
47326910Skarels 	register int dmf = DMFL_UNIT(dev);
47421955Sbloom 	register struct dmfl_softc *sc = &dmfl_softc[dmf];
47526910Skarels 	register struct uba_device *ui = dmfinfo[dmf];
47621955Sbloom 
47721955Sbloom 	sc->dmfl_state = 0;
47826312Skarels 	if (sc->dmfl_info != 0)
47926910Skarels 		ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
48021955Sbloom 
48126910Skarels 	((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
48221955Sbloom }
48321955Sbloom 
48426312Skarels dmflwrite(dev, uio)
48526312Skarels 	dev_t dev;
48626312Skarels 	struct uio *uio;
48721955Sbloom {
48826366Skarels 	register int n;
48921955Sbloom 	register int error;
49021955Sbloom 	register struct dmfl_softc *sc;
49121955Sbloom 
49221955Sbloom 	sc = &dmfl_softc[DMFL_UNIT(dev)];
49326910Skarels 	if (sc->dmfl_state & ERROR)
49426910Skarels 		return (EIO);
49526910Skarels 	while (n = (unsigned)uio->uio_resid) {
49626910Skarels 		if (n > DMFL_BUFSIZ) {
49726910Skarels 			n = DMFL_BUFSIZ;
49826910Skarels 			sc->dmfl_state |= MOREIO;
49926910Skarels 		} else
50026910Skarels 			sc->dmfl_state &= ~MOREIO;
50126910Skarels 		if (error = uiomove(sc->dmfl_buf, (int)n, UIO_WRITE, uio))
50226312Skarels 			return (error);
50326910Skarels 		if (error = dmflout(dev, sc->dmfl_buf, n))
50426312Skarels 			return (error);
50521955Sbloom 	}
50626312Skarels 	return (0);
50721955Sbloom }
50821955Sbloom 
50921955Sbloom 
51026312Skarels /*
51126312Skarels  * dmflout -- start io operation to dmf line printer
51221955Sbloom  *		cp is addr of buf of n chars to be sent.
51321955Sbloom  *
51421955Sbloom  *	-- dmf will be put in formatted output mode, this will
51521955Sbloom  *		be selectable from an ioctl if the
51621955Sbloom  *		need ever arises.
51721955Sbloom  */
51826312Skarels dmflout(dev, cp, n)
51926312Skarels 	dev_t dev;
52026312Skarels 	char *cp;
52126312Skarels 	int n;
52221955Sbloom {
52321955Sbloom 	register struct dmfl_softc *sc;
52421955Sbloom 	register int dmf;
52521955Sbloom 	register struct uba_device *ui;
52621955Sbloom 	register struct dmfdevice *d;
52726910Skarels 	int s;
52821955Sbloom 
52926312Skarels 	dmf = DMFL_UNIT(dev);
53026312Skarels 	sc = &dmfl_softc[dmf];
53126312Skarels 	if (sc->dmfl_state & ERROR)
53226312Skarels 		return (EIO);
53326312Skarels 	ui = dmfinfo[dmf];
53426312Skarels 	/*
53526312Skarels 	 * allocate unibus resources, will be released when io
53626312Skarels 	 * operation is done.
53721955Sbloom 	 */
53826910Skarels 	if (sc->dmfl_info == 0)
53926910Skarels 		sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
54026312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
54126910Skarels 	d->dmfl_ctrl = sc->dmfl_format;		/* indir reg 2 */
54221955Sbloom 	/* indir reg auto increments on r/w */
54321955Sbloom 	/* SO DON'T CHANGE THE ORDER OF THIS CODE */
54426910Skarels 	d->dmfl_indrct = 0;			/* prefix chars & num */
54526910Skarels 	d->dmfl_indrct = 0;			/* suffix chars & num */
54626910Skarels 	d->dmfl_indrct = sc->dmfl_info; 	/* dma lo 16 bits addr */
54726910Skarels 	d->dmfl_indrct = -n;			/* number of chars */
54821955Sbloom 
54926910Skarels 	d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
55026910Skarels 						/* dma hi 2 bits addr */
55126910Skarels 	d->dmfl_indrct = sc->dmfl_lines 	/* lines per page */
55226910Skarels 		| (sc->dmfl_cols<<8);		/* carriage width */
55321955Sbloom 	sc->dmfl_state |= ASLP;
55426910Skarels 	s = spltty();
55526910Skarels 	d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
55626312Skarels 	while (sc->dmfl_state & ASLP) {
55726910Skarels 		sleep(sc->dmfl_buf, PZERO + 8);
55826312Skarels 		while (sc->dmfl_state & ERROR) {
55926910Skarels 			timeout(dmflint, (caddr_t)dmf, 10 * hz);
56026910Skarels 			sleep((caddr_t)&sc->dmfl_state, PZERO + 8);
56121955Sbloom 		}
56221955Sbloom 	}
56326910Skarels 	splx(s);
56426312Skarels 	return (0);
56521955Sbloom }
56626312Skarels 
56726312Skarels /*
56826312Skarels  * dmflint -- handle an interrupt from the line printer part of the dmf32
56921955Sbloom  */
57021955Sbloom dmflint(dmf)
57126312Skarels 	int dmf;
57221955Sbloom {
57321955Sbloom 	register struct uba_device *ui;
57421955Sbloom 	register struct dmfl_softc *sc;
57521955Sbloom 	register struct dmfdevice *d;
57626910Skarels 	short dmfl_stats;
57721955Sbloom 
57826312Skarels 	ui = dmfinfo[dmf];
57926312Skarels 	sc = &dmfl_softc[dmf];
58026312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
58121955Sbloom 
58226910Skarels 	d->dmfl_ctrl &= ~DMFL_IE;
58327057Skarels 	dmfl_stats = d->dmfl_ctrl;
58426312Skarels 	if (sc->dmfl_state & ERROR) {
58526910Skarels 		if ((dmfl_stats & DMFL_OFFLINE) == 0)
58621955Sbloom 			sc->dmfl_state &= ~ERROR;
58726366Skarels 		wakeup((caddr_t)&sc->dmfl_state);
58821955Sbloom 		return;
58921955Sbloom 	}
59026910Skarels 	if (dmfl_stats & DMFL_DMAERR)
59126910Skarels 		log(LOG_WARNING, "dmf%d: NXM\n", dmf);
59226910Skarels 	if (dmfl_stats & DMFL_OFFLINE) {
59326910Skarels 		log(LOG_WARNING, "dmf%d: printer error\n", dmf);
59421955Sbloom 		sc->dmfl_state |= ERROR;
59521955Sbloom 	}
59621955Sbloom #ifdef notdef
59726910Skarels 	if (dmfl_stats & DMFL_PDONE) {
59826910Skarels 		printf("bytes= %d\n", d->dmfl_indrct);
59926910Skarels 		printf("lines= %d\n", d->dmfl_indrct);
60026910Skarels 	}
60121955Sbloom #endif
60221955Sbloom 	sc->dmfl_state &= ~ASLP;
60326910Skarels 	wakeup((caddr_t)sc->dmfl_buf);
60426910Skarels 	if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
60526312Skarels 		ubarelse(ui->ui_ubanum, &sc->dmfl_info);
60621955Sbloom }
607*30537Skarels #endif NDMF_LP
60821955Sbloom 
6096940Ssam /* stubs for interrupt routines for devices not yet supported */
6106940Ssam 
61126312Skarels dmfsrint()
61226312Skarels {
61326312Skarels 	printf("dmfsrint\n");
61426312Skarels }
6156940Ssam 
61626312Skarels dmfsxint()
61726312Skarels {
61826312Skarels 	printf("dmfsxint\n");
61926312Skarels }
6206940Ssam 
62126312Skarels dmfdaint()
62226312Skarels {
62326312Skarels 	printf("dmfdaint\n");
62426312Skarels }
6256940Ssam 
62626312Skarels dmfdbint()
62726312Skarels {
62826312Skarels 	printf("dmfdbint\n");
62926312Skarels }
63026910Skarels #endif NDMF
631