xref: /csrg-svn/sys/vax/uba/dmf.c (revision 49759)
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*49759Smarc  *	@(#)dmf.c	7.15 (Berkeley) 05/16/91
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
2545804Sbostic #include "../include/pte.h"
269772Ssam 
2745804Sbostic #include "sys/param.h"
2816063Skarels #include "uba.h"
2945804Sbostic #include "sys/conf.h"
3045804Sbostic #include "sys/user.h"
3145804Sbostic #include "sys/proc.h"
3245804Sbostic #include "sys/ioctl.h"
3345804Sbostic #include "sys/tty.h"
3445804Sbostic #include "sys/map.h"
3545804Sbostic #include "sys/buf.h"
3645804Sbostic #include "sys/vm.h"
3745804Sbostic #include "sys/clist.h"
3845804Sbostic #include "sys/file.h"
3945804Sbostic #include "sys/uio.h"
4045804Sbostic #include "sys/kernel.h"
4145804Sbostic #include "sys/syslog.h"
426940Ssam 
4330537Skarels #include "dmx.h"
4417124Sbloom #include "ubareg.h"
4517124Sbloom #include "ubavar.h"
4630537Skarels #include "dmxreg.h"
4717124Sbloom #include "dmfreg.h"
4830537Skarels #include "dmreg.h"
498473Sroot 
5030537Skarels extern	int dmx_timeout;		/* silo timeout, in ms */
5130537Skarels int	dmfstart();
5230537Skarels 
536940Ssam /*
5430537Skarels  * The clist space is mapped by one terminal driver onto each UNIBUS.
5530537Skarels  * The identity of the board which allocated resources is recorded,
5630537Skarels  * so the process may be repeated after UNIBUS resets.
5730537Skarels  * The UBACVT macro converts a clist space address for unibus uban
5830537Skarels  * into an i/o space address for the DMA routine.
596940Ssam  */
6030537Skarels int	dmf_uballoc[NUBA];	/* which dmf (if any) allocated unibus map */
6130537Skarels int	cbase[NUBA];		/* base address of clists in unibus map */
6230537Skarels 
6330537Skarels /*
6430537Skarels  * Autoconfiguration and variables for DMF32
6530537Skarels  */
666940Ssam int	dmfprobe(), dmfattach(), dmfrint(), dmfxint();
6721955Sbloom int	dmflint();
686940Ssam struct	uba_device *dmfinfo[NDMF];
696940Ssam u_short	dmfstd[] = { 0 };
706940Ssam struct	uba_driver dmfdriver =
716940Ssam 	{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
726940Ssam 
736940Ssam struct	tty dmf_tty[NDMF*8];
7430537Skarels struct	dmx_softc dmf_softc[NDMF];
758778Sroot #ifndef lint
768778Sroot int	ndmf = NDMF*8;			/* used by iostat */
778778Sroot #endif
786940Ssam 
796940Ssam /*
806940Ssam  * Routine for configuration to set dmf interrupt.
816940Ssam  */
826940Ssam /*ARGSUSED*/
dmfprobe(reg,ctlr)836940Ssam dmfprobe(reg, ctlr)
846940Ssam 	caddr_t reg;
8521955Sbloom 	struct uba_device *ctlr;
866940Ssam {
876940Ssam 	register int br, cvec;		/* these are ``value-result'' */
886940Ssam 	register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
8921955Sbloom 	register int i;
9021955Sbloom 	register unsigned int a;
9121955Sbloom 	static char *dmfdevs[]=
9221955Sbloom 		{"parallel","printer","synch","asynch"};
9321955Sbloom 	unsigned int dmfoptions;
9425449Skarels 	static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
956940Ssam 
966940Ssam #ifdef lint
976940Ssam 	br = 0; cvec = br; br = cvec;
988808Sroot 	dmfxint(0); dmfrint(0);
9926366Skarels 	dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
1006940Ssam #endif
10121955Sbloom 	/*
10221955Sbloom 	 * Pick the usual size DMF vector here (don't decrement it here).
10321955Sbloom 	 * grab configuration; note that the DMF32
10421955Sbloom 	 * doesn't seem to put the right bits in this
10521955Sbloom 	 * register until AFTER the interrupt vector is set.
10621955Sbloom 	 */
1076940Ssam 	br = 0x15;
10821955Sbloom 	cvec = (uba_hd[numuba].uh_lastiv - 4*8);
10925449Skarels 	dmfaddr->dmfccsr0 = (cvec >> 2);
11021955Sbloom 	dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
11121955Sbloom 
11221955Sbloom 	/* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
11321955Sbloom 	if (dmfoptions == DMFC_ASYNC) {
11425449Skarels 		/* Async portion only */
11525449Skarels 
11625449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
11725449Skarels 		dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
11825449Skarels 		intrv[0] = ctlr->ui_intr[4];
11925449Skarels 		intrv[1] = ctlr->ui_intr[5];
12025449Skarels 		ctlr->ui_intr = intrv;
12126312Skarels 	} else if (dmfoptions == DMFC_LP) {
12225449Skarels 		/* LP portion only */
12321955Sbloom 
12425449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
12525449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[6];
12626312Skarels 	} else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
12730537Skarels 		/* LP and Async portions only */
12825449Skarels 
12925449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
13025449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[4];
13126312Skarels 	} else {
13225449Skarels 		/* All other configurations get everything */
13321955Sbloom 
13421955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
13521955Sbloom 	}
13625449Skarels 	a = (dmfoptions >> 12) & 0xf;
13725449Skarels 	printf("dmf%d:", ctlr->ui_unit);
13826312Skarels 	for (i = 0; a != 0; ++i, a >>= 1) {
13926312Skarels 		if (a & 1)
14025449Skarels 			printf(" %s",dmfdevs[i]);
14125449Skarels 	}
14225449Skarels 	printf(".\n");
14321955Sbloom 
14421955Sbloom 	if (dmfoptions & DMFC_LP)
14527057Skarels 		dmfaddr->dmfl_ctrl = DMFL_RESET;
1467412Skre 	return (sizeof (struct dmfdevice));
1476940Ssam }
1486940Ssam 
1496940Ssam /*
1506940Ssam  * Routine called to attach a dmf.
1516940Ssam  */
dmfattach(ui)1526940Ssam dmfattach(ui)
15330537Skarels 	register struct uba_device *ui;
1546940Ssam {
15530537Skarels 	register struct dmx_softc *sc;
1566940Ssam 
15730537Skarels 	sc = &dmf_softc[ui->ui_unit];
15830537Skarels 	sc->dmx_type = 'f';
15930537Skarels 	sc->dmx_unit = ui->ui_unit;
16030537Skarels 	sc->dmx_unit0 = 0;
16130537Skarels 	sc->dmx_ubanum = ui->ui_ubanum;
16230537Skarels 	sc->dmx_softCAR = ui->ui_flags & 0xff;
16330537Skarels 	sc->dmx_tty = &dmf_tty[ui->ui_unit * 8];
16430537Skarels 	sc->dmx_octet =
16530537Skarels 	    (struct dmx_octet *)&((struct dmfdevice *)ui->ui_addr)->dmfa;
16630537Skarels 
16726221Skarels 	cbase[ui->ui_ubanum] = -1;
16836610Sbostic 	dmf_uballoc[ui->ui_ubanum] = -1;
16930537Skarels #if NDMF_LP > 0
17030537Skarels 	dmflattach(ui);
17130537Skarels #endif NDMF_LP
1726940Ssam }
1736940Ssam 
1746940Ssam /*
1756940Ssam  * Open a DMF32 line, mapping the clist onto the uba if this
1766940Ssam  * is the first dmf on this uba.  Turn on this dmf if this is
1776940Ssam  * the first use of it.
1786940Ssam  */
1796940Ssam /*ARGSUSED*/
dmfopen(dev,flag)1806940Ssam dmfopen(dev, flag)
1816940Ssam 	dev_t dev;
1826940Ssam {
1836940Ssam 	register struct tty *tp;
18430537Skarels 	register struct dmx_softc *sc;
18530537Skarels 	int unit, dmf;
1866940Ssam 	register struct dmfdevice *addr;
1876940Ssam 	register struct uba_device *ui;
1886940Ssam 	int s;
18939061Smarc 	int dmxparam();
1906940Ssam 
1916940Ssam 	unit = minor(dev);
19226312Skarels 	if (unit & 0200)
19326312Skarels 		return (dmflopen(dev,flag));
1946940Ssam 	dmf = unit >> 3;
1958567Sroot 	if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
1968567Sroot 		return (ENXIO);
19730537Skarels 
1986940Ssam 	tp = &dmf_tty[unit];
19930537Skarels 	sc = &dmf_softc[dmf];
2006940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
20130537Skarels 	tp->t_addr = (caddr_t)(&addr->dmfa);
2026940Ssam 	tp->t_oproc = dmfstart;
20330537Skarels 	tp->t_dev = dev;			/* needed before dmxopen */
20439061Smarc 	tp->t_param = dmxparam;
20530537Skarels 
2066940Ssam 	/*
20730537Skarels 	 * While setting up state for this uba,
2086940Ssam 	 * block uba resets which can clear the state.
2096940Ssam 	 */
21030537Skarels 	s = spl6();
21126221Skarels 	if (cbase[ui->ui_ubanum] == -1) {
21230322Skarels 		dmf_uballoc[ui->ui_ubanum] = dmf;
21330322Skarels 		cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
21430322Skarels 		    (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
2156940Ssam 	}
2166940Ssam 	splx(s);
21730537Skarels 
21839061Smarc 	return (dmxopen(tp, sc, flag));
2196940Ssam }
2206940Ssam 
2216940Ssam /*
2226940Ssam  * Close a DMF32 line.
2236940Ssam  */
2246940Ssam /*ARGSUSED*/
dmfclose(dev,flag,mode,p)225*49759Smarc dmfclose(dev, flag, mode, p)
2266940Ssam 	dev_t dev;
227*49759Smarc 	int flag, mode;
228*49759Smarc 	struct proc *p;
2296940Ssam {
2306940Ssam 	register unit;
2316940Ssam 
2326940Ssam 	unit = minor(dev);
23326312Skarels 	if (unit & 0200) {
23430537Skarels 		dmflclose(dev, flag);
23526312Skarels 		return;
23626312Skarels 	}
237*49759Smarc 	return (dmxclose(&dmf_tty[unit]), flag);
2386940Ssam }
2396940Ssam 
dmfread(dev,uio,flag)24039061Smarc dmfread(dev, uio, flag)
2416940Ssam 	dev_t dev;
2427726Sroot 	struct uio *uio;
2436940Ssam {
2446940Ssam 	register struct tty *tp;
2456940Ssam 
24626312Skarels 	if (minor(dev) & 0200)
24721955Sbloom 		return(ENXIO);
2486940Ssam 	tp = &dmf_tty[minor(dev)];
24939061Smarc 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
2506940Ssam }
2516940Ssam 
dmfwrite(dev,uio)2527832Sroot dmfwrite(dev, uio)
2536940Ssam 	dev_t dev;
2547832Sroot 	struct uio *uio;
2556940Ssam {
2566940Ssam 	register struct tty *tp;
2576940Ssam 
25826312Skarels 	if (minor(dev) & 0200)
25926312Skarels 		return (dmflwrite(dev,uio));
2606940Ssam 	tp = &dmf_tty[minor(dev)];
2618530Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
2626940Ssam }
2636940Ssam 
2646940Ssam /*
2656940Ssam  * DMF32 receiver interrupt.
2666940Ssam  */
dmfrint(dmf)2676940Ssam dmfrint(dmf)
2686940Ssam 	int dmf;
2696940Ssam {
27030537Skarels 	struct uba_device *ui;
2716940Ssam 
27226312Skarels 	ui = dmfinfo[dmf];
27326312Skarels 	if (ui == 0 || ui->ui_alive == 0)
27426312Skarels 		return;
27530537Skarels 	dmxrint(&dmf_softc[dmf]);
2766940Ssam }
2776940Ssam 
2786940Ssam /*
2796940Ssam  * Ioctl for DMF32.
2806940Ssam  */
dmfioctl(dev,cmd,data,flag)2817630Ssam dmfioctl(dev, cmd, data, flag)
2826940Ssam 	dev_t dev;
2837630Ssam 	caddr_t data;
2846940Ssam {
28530537Skarels 	int unit = minor(dev);
2866940Ssam 
28726312Skarels 	if (unit & 0200)
28821955Sbloom 		return (ENOTTY);
28930537Skarels 	return (dmxioctl(&dmf_tty[unit], cmd, data, flag));
2906940Ssam }
2916940Ssam 
2926940Ssam /*
2936940Ssam  * DMF32 transmitter interrupt.
2946940Ssam  * Restart the idle line.
2956940Ssam  */
dmfxint(dmf)2966940Ssam dmfxint(dmf)
2976940Ssam 	int dmf;
2986940Ssam {
2996940Ssam 
30030537Skarels 	dmxxint(&dmf_softc[dmf]);
3016940Ssam }
3026940Ssam 
3036940Ssam /*
30430537Skarels  * Start (restart) transmission on the given line.
3056940Ssam  */
3066940Ssam dmfstart(tp)
30730537Skarels 	struct tty *tp;
3086940Ssam {
3096940Ssam 
31030537Skarels 	dmxstart(tp, &dmf_softc[minor(tp->t_dev) >> 3]);
3116940Ssam }
3126940Ssam 
3136940Ssam /*
3146940Ssam  * Stop output on a line, e.g. for ^S/^Q or output flush.
3156940Ssam  */
3166940Ssam dmfstop(tp, flag)
31730537Skarels 	struct tty *tp;
3186940Ssam {
3196940Ssam 
32030537Skarels 	dmxstop(tp, &dmf_softc[minor(tp->t_dev) >> 3], flag);
3216940Ssam }
3226940Ssam 
3236940Ssam /*
3246940Ssam  * Reset state of driver if UBA reset was necessary.
3256940Ssam  * Reset the csr, lpr, and lcr registers on open lines, and
3266940Ssam  * restart transmitters.
3276940Ssam  */
dmfreset(uban)3286940Ssam dmfreset(uban)
3296940Ssam 	int uban;
3306940Ssam {
33130537Skarels 	register int dmf;
3326940Ssam 	register struct tty *tp;
3336940Ssam 	register struct uba_device *ui;
3346940Ssam 	register struct dmfdevice *addr;
3356940Ssam 	int i;
3366940Ssam 
3376940Ssam 	for (dmf = 0; dmf < NDMF; dmf++) {
3386940Ssam 		ui = dmfinfo[dmf];
3396940Ssam 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
3406940Ssam 			continue;
3416940Ssam 		printf(" dmf%d", dmf);
34230322Skarels 		if (dmf_uballoc[uban] == dmf) {
34330322Skarels 			int info;
34430322Skarels 
34530322Skarels 			info = uballoc(uban, (caddr_t)cfree,
34630322Skarels 			    nclist * sizeof(struct cblock), UBA_CANTWAIT);
34730322Skarels 			if (info)
34830322Skarels 				cbase[uban] = UBAI_ADDR(info);
34930322Skarels 			else {
35030322Skarels 				printf(" [can't get uba map]");
35130322Skarels 				cbase[uban] = -1;
35230322Skarels 			}
35325449Skarels 		}
3546940Ssam 		addr = (struct dmfdevice *)ui->ui_addr;
35530537Skarels 		addr->dmfa.csr = DMF_IE;
35630537Skarels 		addr->dmfa.rsp = dmx_timeout;
35730537Skarels 		tp = &dmf_tty[dmf * 8];
35830537Skarels 		for (i = 0; i < 8; i++, tp++) {
3596971Ssam 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
36039061Smarc 				dmxparam(tp, &tp->t_termios);
36130537Skarels 				(void) dmxmctl(tp, DMF_ON, DMSET);
3626971Ssam 				tp->t_state &= ~TS_BUSY;
3636940Ssam 				dmfstart(tp);
3646940Ssam 			}
3656940Ssam 		}
36630537Skarels #if NDMF_LP > 0
36730537Skarels 		dmflint(dmf);
36830537Skarels #endif
3696940Ssam 	}
3706940Ssam }
3716940Ssam 
37230537Skarels #if NDMF_LP > 0
37326312Skarels /*
37430537Skarels  * DMF32 line printer driver
37530537Skarels  *
37630537Skarels  * the line printer on dmfx is indicated by a minor device code of 128+x
37730537Skarels  *
37830537Skarels  * the flags field of the config file is interpreted like so:
37930537Skarels  * bits		meaning
38030537Skarels  * ----		-------
38130537Skarels  * 0-7		soft carrier bits for ttys part of dmf32
38230537Skarels  * 8-15		number of cols/line on the line printer
38330537Skarels  *			if 0, 132 will be used.
38430537Skarels  * 16-23	number of lines/page on the line printer
38530537Skarels  *			if 0, 66 will be used.
38630537Skarels  * 24		if 1 DO NOT use the auto format mode of the
38730537Skarels  *			line printer parallel port
38830537Skarels  */
38930537Skarels 
39030537Skarels struct dmfl_softc {
39130537Skarels 	u_int	dmfl_state; 		/* soft state bits */
39230537Skarels 	int	dmfl_info;		/* uba info */
39330537Skarels 	u_short	dmfl_lines;		/* lines per page (66 def.) */
39430537Skarels 	u_short	dmfl_cols; 		/* cols per line (132 def.) */
39530537Skarels 	u_short	dmfl_format;		/* fflag for auto form feed */
39630537Skarels 	char	dmfl_buf[DMFL_BUFSIZ];
39730537Skarels } dmfl_softc[NDMF];
39830537Skarels 
39930537Skarels /*
40030537Skarels  * convert device number into DMF line printer unit number
40130537Skarels  */
40230537Skarels #define	DMFL_UNIT(d)	(minor(d) & 0xf)	/* up to 16 DMFs */
40330537Skarels 
40430537Skarels #define ASLP 1		/* waiting for interrupt from dmf */
40530537Skarels #define OPEN 2		/* line printer is open */
40630537Skarels #define ERROR 4		/* error while printing, driver
40730537Skarels 			 refuses to do anything till closed */
40830537Skarels #define MOREIO 8	/* more data for printer */
40930537Skarels 
41030537Skarels /*
41130537Skarels  * Attach printer portion of dmf.
41230537Skarels  */
dmflattach(ui)41330537Skarels dmflattach(ui)
41430537Skarels 	register struct uba_device *ui;
41530537Skarels {
41630537Skarels 	register int unit = ui->ui_unit;
41730537Skarels 	register int cols = (ui->ui_flags>>8) & 0xff;
41830537Skarels 	register int lines = (ui->ui_flags>>16) & 0xff;
41930537Skarels 	register struct dmfl_softc *sc;
42030537Skarels 
42130537Skarels 	sc = &dmfl_softc[unit];
42230537Skarels 	sc->dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
42330537Skarels 	sc->dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
42430537Skarels  	if ((ui->ui_flags >> 24) & 0x1)
42530537Skarels  		sc->dmfl_format = (2 << 8);
42630537Skarels  	else
42730537Skarels  		sc->dmfl_format = (2 << 8) | DMFL_FORMAT;
42830537Skarels }
42930537Skarels 
43030537Skarels /*
43126312Skarels  * dmflopen -- open the line printer port on a dmf32
43221955Sbloom  */
43326312Skarels /* ARGSUSED */
dmflopen(dev,flag)43426312Skarels dmflopen(dev, flag)
43526312Skarels 	dev_t dev;
43626312Skarels 	int flag;
43721955Sbloom {
43821955Sbloom 	register int dmf;
43921955Sbloom 	register struct dmfl_softc *sc;
44021955Sbloom 	register struct uba_device *ui;
44121955Sbloom 	register struct dmfdevice *addr;
44221955Sbloom 
44326312Skarels 	dmf = DMFL_UNIT(dev);
44426910Skarels 	if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
44526910Skarels 		return (ENXIO);
44626910Skarels 	sc = &dmfl_softc[dmf];
44726910Skarels 	if (sc->dmfl_state & OPEN)
44826910Skarels 		return (EBUSY);
44921955Sbloom 	addr = (struct dmfdevice *)ui->ui_addr;
45026910Skarels 	if (addr->dmfl_ctrl & DMFL_OFFLINE) {
45126910Skarels #ifdef notdef
45226910Skarels 		log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
45326910Skarels 			dmf);
45426910Skarels #endif
45526312Skarels 		return (EIO);
45621955Sbloom 	}
45726910Skarels 	if ((addr->dmfl_ctrl & DMFL_CONV)) {
45826910Skarels 		log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
45926312Skarels 		return (EIO);
46021955Sbloom 	}
46121955Sbloom 
46226910Skarels 	addr->dmfl_ctrl = 0;
46321955Sbloom 	sc->dmfl_state |= OPEN;
46426312Skarels 	return (0);
46521955Sbloom }
46621955Sbloom 
46726312Skarels /* ARGSUSED */
dmflclose(dev,flag)46826312Skarels dmflclose(dev, flag)
46926312Skarels 	dev_t dev;
47026312Skarels 	int flag;
47121955Sbloom {
47226910Skarels 	register int dmf = DMFL_UNIT(dev);
47321955Sbloom 	register struct dmfl_softc *sc = &dmfl_softc[dmf];
47426910Skarels 	register struct uba_device *ui = dmfinfo[dmf];
47521955Sbloom 
47621955Sbloom 	sc->dmfl_state = 0;
47726312Skarels 	if (sc->dmfl_info != 0)
47826910Skarels 		ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
47921955Sbloom 
48026910Skarels 	((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
48121955Sbloom }
48221955Sbloom 
dmflwrite(dev,uio)48326312Skarels dmflwrite(dev, uio)
48426312Skarels 	dev_t dev;
48526312Skarels 	struct uio *uio;
48621955Sbloom {
48726366Skarels 	register int n;
48821955Sbloom 	register int error;
48921955Sbloom 	register struct dmfl_softc *sc;
49021955Sbloom 
49121955Sbloom 	sc = &dmfl_softc[DMFL_UNIT(dev)];
49226910Skarels 	if (sc->dmfl_state & ERROR)
49326910Skarels 		return (EIO);
49426910Skarels 	while (n = (unsigned)uio->uio_resid) {
49526910Skarels 		if (n > DMFL_BUFSIZ) {
49626910Skarels 			n = DMFL_BUFSIZ;
49726910Skarels 			sc->dmfl_state |= MOREIO;
49826910Skarels 		} else
49926910Skarels 			sc->dmfl_state &= ~MOREIO;
50037765Smckusick 		if (error = uiomove(sc->dmfl_buf, (int)n, uio))
50126312Skarels 			return (error);
50226910Skarels 		if (error = dmflout(dev, sc->dmfl_buf, n))
50326312Skarels 			return (error);
50421955Sbloom 	}
50526312Skarels 	return (0);
50621955Sbloom }
50721955Sbloom 
50821955Sbloom 
50926312Skarels /*
51026312Skarels  * dmflout -- start io operation to dmf line printer
51121955Sbloom  *		cp is addr of buf of n chars to be sent.
51221955Sbloom  *
51321955Sbloom  *	-- dmf will be put in formatted output mode, this will
51421955Sbloom  *		be selectable from an ioctl if the
51521955Sbloom  *		need ever arises.
51621955Sbloom  */
dmflout(dev,cp,n)51726312Skarels dmflout(dev, cp, n)
51826312Skarels 	dev_t dev;
51926312Skarels 	char *cp;
52026312Skarels 	int n;
52121955Sbloom {
52221955Sbloom 	register struct dmfl_softc *sc;
52321955Sbloom 	register int dmf;
52421955Sbloom 	register struct uba_device *ui;
52521955Sbloom 	register struct dmfdevice *d;
52640729Skarels 	int s, error;
52721955Sbloom 
52826312Skarels 	dmf = DMFL_UNIT(dev);
52926312Skarels 	sc = &dmfl_softc[dmf];
53026312Skarels 	if (sc->dmfl_state & ERROR)
53126312Skarels 		return (EIO);
53226312Skarels 	ui = dmfinfo[dmf];
53326312Skarels 	/*
53426312Skarels 	 * allocate unibus resources, will be released when io
53526312Skarels 	 * operation is done.
53621955Sbloom 	 */
53726910Skarels 	if (sc->dmfl_info == 0)
53826910Skarels 		sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
53926312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
54026910Skarels 	d->dmfl_ctrl = sc->dmfl_format;		/* indir reg 2 */
54121955Sbloom 	/* indir reg auto increments on r/w */
54221955Sbloom 	/* SO DON'T CHANGE THE ORDER OF THIS CODE */
54326910Skarels 	d->dmfl_indrct = 0;			/* prefix chars & num */
54426910Skarels 	d->dmfl_indrct = 0;			/* suffix chars & num */
54526910Skarels 	d->dmfl_indrct = sc->dmfl_info; 	/* dma lo 16 bits addr */
54626910Skarels 	d->dmfl_indrct = -n;			/* number of chars */
54721955Sbloom 
54826910Skarels 	d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
54926910Skarels 						/* dma hi 2 bits addr */
55026910Skarels 	d->dmfl_indrct = sc->dmfl_lines 	/* lines per page */
55126910Skarels 		| (sc->dmfl_cols<<8);		/* carriage width */
55221955Sbloom 	sc->dmfl_state |= ASLP;
55340729Skarels 	error = 0;
55426910Skarels 	s = spltty();
55526910Skarels 	d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
55626312Skarels 	while (sc->dmfl_state & ASLP) {
55740729Skarels 		if (error = tsleep(sc->dmfl_buf, (PZERO + 8) | PCATCH,
55840729Skarels 		    ttyout, 0))
55940729Skarels 			break;
56026312Skarels 		while (sc->dmfl_state & ERROR) {
56126910Skarels 			timeout(dmflint, (caddr_t)dmf, 10 * hz);
56240729Skarels 			if (error = tsleep((caddr_t)&sc->dmfl_state,
56340729Skarels 			    (PZERO + 8) | PCATCH, ttyout, 0))
56440729Skarels 				goto out;
56521955Sbloom 		}
56621955Sbloom 	}
56740729Skarels out:
56826910Skarels 	splx(s);
56926312Skarels 	return (0);
57021955Sbloom }
57126312Skarels 
57226312Skarels /*
57326312Skarels  * dmflint -- handle an interrupt from the line printer part of the dmf32
57421955Sbloom  */
dmflint(dmf)57521955Sbloom dmflint(dmf)
57626312Skarels 	int dmf;
57721955Sbloom {
57821955Sbloom 	register struct uba_device *ui;
57921955Sbloom 	register struct dmfl_softc *sc;
58021955Sbloom 	register struct dmfdevice *d;
58126910Skarels 	short dmfl_stats;
58221955Sbloom 
58326312Skarels 	ui = dmfinfo[dmf];
58426312Skarels 	sc = &dmfl_softc[dmf];
58526312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
58621955Sbloom 
58726910Skarels 	d->dmfl_ctrl &= ~DMFL_IE;
58827057Skarels 	dmfl_stats = d->dmfl_ctrl;
58926312Skarels 	if (sc->dmfl_state & ERROR) {
59026910Skarels 		if ((dmfl_stats & DMFL_OFFLINE) == 0)
59121955Sbloom 			sc->dmfl_state &= ~ERROR;
59226366Skarels 		wakeup((caddr_t)&sc->dmfl_state);
59321955Sbloom 		return;
59421955Sbloom 	}
59526910Skarels 	if (dmfl_stats & DMFL_DMAERR)
59626910Skarels 		log(LOG_WARNING, "dmf%d: NXM\n", dmf);
59726910Skarels 	if (dmfl_stats & DMFL_OFFLINE) {
59826910Skarels 		log(LOG_WARNING, "dmf%d: printer error\n", dmf);
59921955Sbloom 		sc->dmfl_state |= ERROR;
60021955Sbloom 	}
60121955Sbloom #ifdef notdef
60226910Skarels 	if (dmfl_stats & DMFL_PDONE) {
60326910Skarels 		printf("bytes= %d\n", d->dmfl_indrct);
60426910Skarels 		printf("lines= %d\n", d->dmfl_indrct);
60526910Skarels 	}
60621955Sbloom #endif
60721955Sbloom 	sc->dmfl_state &= ~ASLP;
60826910Skarels 	wakeup((caddr_t)sc->dmfl_buf);
60926910Skarels 	if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
61026312Skarels 		ubarelse(ui->ui_ubanum, &sc->dmfl_info);
61121955Sbloom }
61230537Skarels #endif NDMF_LP
61321955Sbloom 
6146940Ssam /* stubs for interrupt routines for devices not yet supported */
6156940Ssam 
dmfsrint()61626312Skarels dmfsrint()
61726312Skarels {
61826312Skarels 	printf("dmfsrint\n");
61926312Skarels }
6206940Ssam 
dmfsxint()62126312Skarels dmfsxint()
62226312Skarels {
62326312Skarels 	printf("dmfsxint\n");
62426312Skarels }
6256940Ssam 
dmfdaint()62626312Skarels dmfdaint()
62726312Skarels {
62826312Skarels 	printf("dmfdaint\n");
62926312Skarels }
6306940Ssam 
dmfdbint()63126312Skarels dmfdbint()
63226312Skarels {
63326312Skarels 	printf("dmfdbint\n");
63426312Skarels }
63526910Skarels #endif NDMF
636