xref: /csrg-svn/sys/vax/uba/dmf.c (revision 40729)
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*40729Skarels  *	@(#)dmf.c	7.11 (Berkeley) 04/03/90
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  */
1930537Skarels #include "dmf.h"
2030537Skarels #if NDMF > 0
2130537Skarels 
2230537Skarels #ifndef NDMF_LP
2330537Skarels #define	NDMF_LP	NDMF
2430537Skarels #endif	NDMF_LP
2537511Smckusick #include "machine/pte.h"
269772Ssam 
276940Ssam #include "bk.h"
2816063Skarels #include "uba.h"
2917124Sbloom #include "param.h"
3017124Sbloom #include "conf.h"
3117124Sbloom #include "user.h"
3226836Skarels #include "proc.h"
3317124Sbloom #include "ioctl.h"
3417124Sbloom #include "tty.h"
3517124Sbloom #include "map.h"
3617124Sbloom #include "buf.h"
3717124Sbloom #include "vm.h"
3817124Sbloom #include "bkmac.h"
3917124Sbloom #include "clist.h"
4017124Sbloom #include "file.h"
4117124Sbloom #include "uio.h"
4221955Sbloom #include "kernel.h"
4318312Sralph #include "syslog.h"
446940Ssam 
4530537Skarels #include "dmx.h"
4617124Sbloom #include "ubareg.h"
4717124Sbloom #include "ubavar.h"
4830537Skarels #include "dmxreg.h"
4917124Sbloom #include "dmfreg.h"
5030537Skarels #include "dmreg.h"
518473Sroot 
5230537Skarels extern	int dmx_timeout;		/* silo timeout, in ms */
5330537Skarels int	dmfstart();
5430537Skarels 
556940Ssam /*
5630537Skarels  * The clist space is mapped by one terminal driver onto each UNIBUS.
5730537Skarels  * The identity of the board which allocated resources is recorded,
5830537Skarels  * so the process may be repeated after UNIBUS resets.
5930537Skarels  * The UBACVT macro converts a clist space address for unibus uban
6030537Skarels  * into an i/o space address for the DMA routine.
616940Ssam  */
6230537Skarels int	dmf_uballoc[NUBA];	/* which dmf (if any) allocated unibus map */
6330537Skarels int	cbase[NUBA];		/* base address of clists in unibus map */
6430537Skarels 
6530537Skarels /*
6630537Skarels  * Autoconfiguration and variables for DMF32
6730537Skarels  */
686940Ssam int	dmfprobe(), dmfattach(), dmfrint(), dmfxint();
6921955Sbloom int	dmflint();
706940Ssam struct	uba_device *dmfinfo[NDMF];
716940Ssam u_short	dmfstd[] = { 0 };
726940Ssam struct	uba_driver dmfdriver =
736940Ssam 	{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
746940Ssam 
756940Ssam struct	tty dmf_tty[NDMF*8];
7630537Skarels struct	dmx_softc dmf_softc[NDMF];
778778Sroot #ifndef lint
788778Sroot int	ndmf = NDMF*8;			/* used by iostat */
798778Sroot #endif
806940Ssam 
816940Ssam /*
826940Ssam  * Routine for configuration to set dmf interrupt.
836940Ssam  */
846940Ssam /*ARGSUSED*/
856940Ssam dmfprobe(reg, ctlr)
866940Ssam 	caddr_t reg;
8721955Sbloom 	struct uba_device *ctlr;
886940Ssam {
896940Ssam 	register int br, cvec;		/* these are ``value-result'' */
906940Ssam 	register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
9121955Sbloom 	register int i;
9221955Sbloom 	register unsigned int a;
9321955Sbloom 	static char *dmfdevs[]=
9421955Sbloom 		{"parallel","printer","synch","asynch"};
9521955Sbloom 	unsigned int dmfoptions;
9625449Skarels 	static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
976940Ssam 
986940Ssam #ifdef lint
996940Ssam 	br = 0; cvec = br; br = cvec;
1008808Sroot 	dmfxint(0); dmfrint(0);
10126366Skarels 	dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
1026940Ssam #endif
10321955Sbloom 	/*
10421955Sbloom 	 * Pick the usual size DMF vector here (don't decrement it here).
10521955Sbloom 	 * grab configuration; note that the DMF32
10621955Sbloom 	 * doesn't seem to put the right bits in this
10721955Sbloom 	 * register until AFTER the interrupt vector is set.
10821955Sbloom 	 */
1096940Ssam 	br = 0x15;
11021955Sbloom 	cvec = (uba_hd[numuba].uh_lastiv - 4*8);
11125449Skarels 	dmfaddr->dmfccsr0 = (cvec >> 2);
11221955Sbloom 	dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
11321955Sbloom 
11421955Sbloom 	/* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
11521955Sbloom 	if (dmfoptions == DMFC_ASYNC) {
11625449Skarels 		/* Async portion only */
11725449Skarels 
11825449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
11925449Skarels 		dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
12025449Skarels 		intrv[0] = ctlr->ui_intr[4];
12125449Skarels 		intrv[1] = ctlr->ui_intr[5];
12225449Skarels 		ctlr->ui_intr = intrv;
12326312Skarels 	} else if (dmfoptions == DMFC_LP) {
12425449Skarels 		/* LP portion only */
12521955Sbloom 
12625449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
12725449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[6];
12826312Skarels 	} else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
12930537Skarels 		/* LP and Async portions only */
13025449Skarels 
13125449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
13225449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[4];
13326312Skarels 	} else {
13425449Skarels 		/* All other configurations get everything */
13521955Sbloom 
13621955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
13721955Sbloom 	}
13825449Skarels 	a = (dmfoptions >> 12) & 0xf;
13925449Skarels 	printf("dmf%d:", ctlr->ui_unit);
14026312Skarels 	for (i = 0; a != 0; ++i, a >>= 1) {
14126312Skarels 		if (a & 1)
14225449Skarels 			printf(" %s",dmfdevs[i]);
14325449Skarels 	}
14425449Skarels 	printf(".\n");
14521955Sbloom 
14621955Sbloom 	if (dmfoptions & DMFC_LP)
14727057Skarels 		dmfaddr->dmfl_ctrl = DMFL_RESET;
1487412Skre 	return (sizeof (struct dmfdevice));
1496940Ssam }
1506940Ssam 
1516940Ssam /*
1526940Ssam  * Routine called to attach a dmf.
1536940Ssam  */
1546940Ssam dmfattach(ui)
15530537Skarels 	register struct uba_device *ui;
1566940Ssam {
15730537Skarels 	register struct dmx_softc *sc;
1586940Ssam 
15930537Skarels 	sc = &dmf_softc[ui->ui_unit];
16030537Skarels 	sc->dmx_type = 'f';
16130537Skarels 	sc->dmx_unit = ui->ui_unit;
16230537Skarels 	sc->dmx_unit0 = 0;
16330537Skarels 	sc->dmx_ubanum = ui->ui_ubanum;
16430537Skarels 	sc->dmx_softCAR = ui->ui_flags & 0xff;
16530537Skarels 	sc->dmx_tty = &dmf_tty[ui->ui_unit * 8];
16630537Skarels 	sc->dmx_octet =
16730537Skarels 	    (struct dmx_octet *)&((struct dmfdevice *)ui->ui_addr)->dmfa;
16830537Skarels 
16926221Skarels 	cbase[ui->ui_ubanum] = -1;
17036610Sbostic 	dmf_uballoc[ui->ui_ubanum] = -1;
17130537Skarels #if NDMF_LP > 0
17230537Skarels 	dmflattach(ui);
17330537Skarels #endif NDMF_LP
1746940Ssam }
1756940Ssam 
1766940Ssam /*
1776940Ssam  * Open a DMF32 line, mapping the clist onto the uba if this
1786940Ssam  * is the first dmf on this uba.  Turn on this dmf if this is
1796940Ssam  * the first use of it.
1806940Ssam  */
1816940Ssam /*ARGSUSED*/
1826940Ssam dmfopen(dev, flag)
1836940Ssam 	dev_t dev;
1846940Ssam {
1856940Ssam 	register struct tty *tp;
18630537Skarels 	register struct dmx_softc *sc;
18730537Skarels 	int unit, dmf;
1886940Ssam 	register struct dmfdevice *addr;
1896940Ssam 	register struct uba_device *ui;
1906940Ssam 	int s;
19139061Smarc 	int dmxparam();
1926940Ssam 
1936940Ssam 	unit = minor(dev);
19426312Skarels 	if (unit & 0200)
19526312Skarels 		return (dmflopen(dev,flag));
1966940Ssam 	dmf = unit >> 3;
1978567Sroot 	if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
1988567Sroot 		return (ENXIO);
19930537Skarels 
2006940Ssam 	tp = &dmf_tty[unit];
20130537Skarels 	sc = &dmf_softc[dmf];
2026940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
20330537Skarels 	tp->t_addr = (caddr_t)(&addr->dmfa);
2046940Ssam 	tp->t_oproc = dmfstart;
20530537Skarels 	tp->t_dev = dev;			/* needed before dmxopen */
20639061Smarc 	tp->t_param = dmxparam;
20730537Skarels 
2086940Ssam 	/*
20930537Skarels 	 * While setting up state for this uba,
2106940Ssam 	 * block uba resets which can clear the state.
2116940Ssam 	 */
21230537Skarels 	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);
21930537Skarels 
22039061Smarc 	return (dmxopen(tp, sc, flag));
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) {
23530537Skarels 		dmflclose(dev, flag);
23626312Skarels 		return;
23726312Skarels 	}
238*40729Skarels 	return (dmxclose(&dmf_tty[unit]));
2396940Ssam }
2406940Ssam 
24139061Smarc dmfread(dev, uio, flag)
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)];
25039061Smarc 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
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 {
27130537Skarels 	struct uba_device *ui;
2726940Ssam 
27326312Skarels 	ui = dmfinfo[dmf];
27426312Skarels 	if (ui == 0 || ui->ui_alive == 0)
27526312Skarels 		return;
27630537Skarels 	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 {
28630537Skarels 	int unit = minor(dev);
2876940Ssam 
28826312Skarels 	if (unit & 0200)
28921955Sbloom 		return (ENOTTY);
29030537Skarels 	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 
30130537Skarels 	dmxxint(&dmf_softc[dmf]);
3026940Ssam }
3036940Ssam 
3046940Ssam /*
30530537Skarels  * Start (restart) transmission on the given line.
3066940Ssam  */
3076940Ssam dmfstart(tp)
30830537Skarels 	struct tty *tp;
3096940Ssam {
3106940Ssam 
31130537Skarels 	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)
31830537Skarels 	struct tty *tp;
3196940Ssam {
3206940Ssam 
32130537Skarels 	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 {
33230537Skarels 	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;
35630537Skarels 		addr->dmfa.csr = DMF_IE;
35730537Skarels 		addr->dmfa.rsp = dmx_timeout;
35830537Skarels 		tp = &dmf_tty[dmf * 8];
35930537Skarels 		for (i = 0; i < 8; i++, tp++) {
3606971Ssam 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
36139061Smarc 				dmxparam(tp, &tp->t_termios);
36230537Skarels 				(void) dmxmctl(tp, DMF_ON, DMSET);
3636971Ssam 				tp->t_state &= ~TS_BUSY;
3646940Ssam 				dmfstart(tp);
3656940Ssam 			}
3666940Ssam 		}
36730537Skarels #if NDMF_LP > 0
36830537Skarels 		dmflint(dmf);
36930537Skarels #endif
3706940Ssam 	}
3716940Ssam }
3726940Ssam 
37330537Skarels #if NDMF_LP > 0
37426312Skarels /*
37530537Skarels  * DMF32 line printer driver
37630537Skarels  *
37730537Skarels  * the line printer on dmfx is indicated by a minor device code of 128+x
37830537Skarels  *
37930537Skarels  * the flags field of the config file is interpreted like so:
38030537Skarels  * bits		meaning
38130537Skarels  * ----		-------
38230537Skarels  * 0-7		soft carrier bits for ttys part of dmf32
38330537Skarels  * 8-15		number of cols/line on the line printer
38430537Skarels  *			if 0, 132 will be used.
38530537Skarels  * 16-23	number of lines/page on the line printer
38630537Skarels  *			if 0, 66 will be used.
38730537Skarels  * 24		if 1 DO NOT use the auto format mode of the
38830537Skarels  *			line printer parallel port
38930537Skarels  */
39030537Skarels 
39130537Skarels struct dmfl_softc {
39230537Skarels 	u_int	dmfl_state; 		/* soft state bits */
39330537Skarels 	int	dmfl_info;		/* uba info */
39430537Skarels 	u_short	dmfl_lines;		/* lines per page (66 def.) */
39530537Skarels 	u_short	dmfl_cols; 		/* cols per line (132 def.) */
39630537Skarels 	u_short	dmfl_format;		/* fflag for auto form feed */
39730537Skarels 	char	dmfl_buf[DMFL_BUFSIZ];
39830537Skarels } dmfl_softc[NDMF];
39930537Skarels 
40030537Skarels /*
40130537Skarels  * convert device number into DMF line printer unit number
40230537Skarels  */
40330537Skarels #define	DMFL_UNIT(d)	(minor(d) & 0xf)	/* up to 16 DMFs */
40430537Skarels 
40530537Skarels #define ASLP 1		/* waiting for interrupt from dmf */
40630537Skarels #define OPEN 2		/* line printer is open */
40730537Skarels #define ERROR 4		/* error while printing, driver
40830537Skarels 			 refuses to do anything till closed */
40930537Skarels #define MOREIO 8	/* more data for printer */
41030537Skarels 
41130537Skarels /*
41230537Skarels  * Attach printer portion of dmf.
41330537Skarels  */
41430537Skarels dmflattach(ui)
41530537Skarels 	register struct uba_device *ui;
41630537Skarels {
41730537Skarels 	register int unit = ui->ui_unit;
41830537Skarels 	register int cols = (ui->ui_flags>>8) & 0xff;
41930537Skarels 	register int lines = (ui->ui_flags>>16) & 0xff;
42030537Skarels 	register struct dmfl_softc *sc;
42130537Skarels 
42230537Skarels 	sc = &dmfl_softc[unit];
42330537Skarels 	sc->dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
42430537Skarels 	sc->dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
42530537Skarels  	if ((ui->ui_flags >> 24) & 0x1)
42630537Skarels  		sc->dmfl_format = (2 << 8);
42730537Skarels  	else
42830537Skarels  		sc->dmfl_format = (2 << 8) | DMFL_FORMAT;
42930537Skarels }
43030537Skarels 
43130537Skarels /*
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;
50137765Smckusick 		if (error = uiomove(sc->dmfl_buf, (int)n, 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;
527*40729Skarels 	int s, error;
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;
554*40729Skarels 	error = 0;
55526910Skarels 	s = spltty();
55626910Skarels 	d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
55726312Skarels 	while (sc->dmfl_state & ASLP) {
558*40729Skarels 		if (error = tsleep(sc->dmfl_buf, (PZERO + 8) | PCATCH,
559*40729Skarels 		    ttyout, 0))
560*40729Skarels 			break;
56126312Skarels 		while (sc->dmfl_state & ERROR) {
56226910Skarels 			timeout(dmflint, (caddr_t)dmf, 10 * hz);
563*40729Skarels 			if (error = tsleep((caddr_t)&sc->dmfl_state,
564*40729Skarels 			    (PZERO + 8) | PCATCH, ttyout, 0))
565*40729Skarels 				goto out;
56621955Sbloom 		}
56721955Sbloom 	}
568*40729Skarels out:
56926910Skarels 	splx(s);
57026312Skarels 	return (0);
57121955Sbloom }
57226312Skarels 
57326312Skarels /*
57426312Skarels  * dmflint -- handle an interrupt from the line printer part of the dmf32
57521955Sbloom  */
57621955Sbloom dmflint(dmf)
57726312Skarels 	int dmf;
57821955Sbloom {
57921955Sbloom 	register struct uba_device *ui;
58021955Sbloom 	register struct dmfl_softc *sc;
58121955Sbloom 	register struct dmfdevice *d;
58226910Skarels 	short dmfl_stats;
58321955Sbloom 
58426312Skarels 	ui = dmfinfo[dmf];
58526312Skarels 	sc = &dmfl_softc[dmf];
58626312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
58721955Sbloom 
58826910Skarels 	d->dmfl_ctrl &= ~DMFL_IE;
58927057Skarels 	dmfl_stats = d->dmfl_ctrl;
59026312Skarels 	if (sc->dmfl_state & ERROR) {
59126910Skarels 		if ((dmfl_stats & DMFL_OFFLINE) == 0)
59221955Sbloom 			sc->dmfl_state &= ~ERROR;
59326366Skarels 		wakeup((caddr_t)&sc->dmfl_state);
59421955Sbloom 		return;
59521955Sbloom 	}
59626910Skarels 	if (dmfl_stats & DMFL_DMAERR)
59726910Skarels 		log(LOG_WARNING, "dmf%d: NXM\n", dmf);
59826910Skarels 	if (dmfl_stats & DMFL_OFFLINE) {
59926910Skarels 		log(LOG_WARNING, "dmf%d: printer error\n", dmf);
60021955Sbloom 		sc->dmfl_state |= ERROR;
60121955Sbloom 	}
60221955Sbloom #ifdef notdef
60326910Skarels 	if (dmfl_stats & DMFL_PDONE) {
60426910Skarels 		printf("bytes= %d\n", d->dmfl_indrct);
60526910Skarels 		printf("lines= %d\n", d->dmfl_indrct);
60626910Skarels 	}
60721955Sbloom #endif
60821955Sbloom 	sc->dmfl_state &= ~ASLP;
60926910Skarels 	wakeup((caddr_t)sc->dmfl_buf);
61026910Skarels 	if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
61126312Skarels 		ubarelse(ui->ui_ubanum, &sc->dmfl_info);
61221955Sbloom }
61330537Skarels #endif NDMF_LP
61421955Sbloom 
6156940Ssam /* stubs for interrupt routines for devices not yet supported */
6166940Ssam 
61726312Skarels dmfsrint()
61826312Skarels {
61926312Skarels 	printf("dmfsrint\n");
62026312Skarels }
6216940Ssam 
62226312Skarels dmfsxint()
62326312Skarels {
62426312Skarels 	printf("dmfsxint\n");
62526312Skarels }
6266940Ssam 
62726312Skarels dmfdaint()
62826312Skarels {
62926312Skarels 	printf("dmfdaint\n");
63026312Skarels }
6316940Ssam 
63226312Skarels dmfdbint()
63326312Skarels {
63426312Skarels 	printf("dmfdbint\n");
63526312Skarels }
63626910Skarels #endif NDMF
637