xref: /csrg-svn/sys/vax/uba/dmf.c (revision 39061)
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*39061Smarc  *	@(#)dmf.c	7.8 (Berkeley) 09/06/89
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 "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 
4630537Skarels #include "dmx.h"
4717124Sbloom #include "ubareg.h"
4817124Sbloom #include "ubavar.h"
4930537Skarels #include "dmxreg.h"
5017124Sbloom #include "dmfreg.h"
5130537Skarels #include "dmreg.h"
528473Sroot 
5330537Skarels extern	int dmx_timeout;		/* silo timeout, in ms */
5430537Skarels int	dmfstart();
5530537Skarels 
566940Ssam /*
5730537Skarels  * The clist space is mapped by one terminal driver onto each UNIBUS.
5830537Skarels  * The identity of the board which allocated resources is recorded,
5930537Skarels  * so the process may be repeated after UNIBUS resets.
6030537Skarels  * The UBACVT macro converts a clist space address for unibus uban
6130537Skarels  * into an i/o space address for the DMA routine.
626940Ssam  */
6330537Skarels int	dmf_uballoc[NUBA];	/* which dmf (if any) allocated unibus map */
6430537Skarels int	cbase[NUBA];		/* base address of clists in unibus map */
6530537Skarels 
6630537Skarels /*
6730537Skarels  * Autoconfiguration and variables for DMF32
6830537Skarels  */
696940Ssam int	dmfprobe(), dmfattach(), dmfrint(), dmfxint();
7021955Sbloom int	dmflint();
716940Ssam struct	uba_device *dmfinfo[NDMF];
726940Ssam u_short	dmfstd[] = { 0 };
736940Ssam struct	uba_driver dmfdriver =
746940Ssam 	{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
756940Ssam 
766940Ssam struct	tty dmf_tty[NDMF*8];
7730537Skarels struct	dmx_softc dmf_softc[NDMF];
788778Sroot #ifndef lint
798778Sroot int	ndmf = NDMF*8;			/* used by iostat */
808778Sroot #endif
816940Ssam 
826940Ssam /*
836940Ssam  * Routine for configuration to set dmf interrupt.
846940Ssam  */
856940Ssam /*ARGSUSED*/
866940Ssam dmfprobe(reg, ctlr)
876940Ssam 	caddr_t reg;
8821955Sbloom 	struct uba_device *ctlr;
896940Ssam {
906940Ssam 	register int br, cvec;		/* these are ``value-result'' */
916940Ssam 	register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
9221955Sbloom 	register int i;
9321955Sbloom 	register unsigned int a;
9421955Sbloom 	static char *dmfdevs[]=
9521955Sbloom 		{"parallel","printer","synch","asynch"};
9621955Sbloom 	unsigned int dmfoptions;
9725449Skarels 	static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
986940Ssam 
996940Ssam #ifdef lint
1006940Ssam 	br = 0; cvec = br; br = cvec;
1018808Sroot 	dmfxint(0); dmfrint(0);
10226366Skarels 	dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
1036940Ssam #endif
10421955Sbloom 	/*
10521955Sbloom 	 * Pick the usual size DMF vector here (don't decrement it here).
10621955Sbloom 	 * grab configuration; note that the DMF32
10721955Sbloom 	 * doesn't seem to put the right bits in this
10821955Sbloom 	 * register until AFTER the interrupt vector is set.
10921955Sbloom 	 */
1106940Ssam 	br = 0x15;
11121955Sbloom 	cvec = (uba_hd[numuba].uh_lastiv - 4*8);
11225449Skarels 	dmfaddr->dmfccsr0 = (cvec >> 2);
11321955Sbloom 	dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
11421955Sbloom 
11521955Sbloom 	/* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
11621955Sbloom 	if (dmfoptions == DMFC_ASYNC) {
11725449Skarels 		/* Async portion only */
11825449Skarels 
11925449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
12025449Skarels 		dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
12125449Skarels 		intrv[0] = ctlr->ui_intr[4];
12225449Skarels 		intrv[1] = ctlr->ui_intr[5];
12325449Skarels 		ctlr->ui_intr = intrv;
12426312Skarels 	} else if (dmfoptions == DMFC_LP) {
12525449Skarels 		/* LP portion only */
12621955Sbloom 
12725449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
12825449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[6];
12926312Skarels 	} else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
13030537Skarels 		/* LP and Async portions only */
13125449Skarels 
13225449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
13325449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[4];
13426312Skarels 	} else {
13525449Skarels 		/* All other configurations get everything */
13621955Sbloom 
13721955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
13821955Sbloom 	}
13925449Skarels 	a = (dmfoptions >> 12) & 0xf;
14025449Skarels 	printf("dmf%d:", ctlr->ui_unit);
14126312Skarels 	for (i = 0; a != 0; ++i, a >>= 1) {
14226312Skarels 		if (a & 1)
14325449Skarels 			printf(" %s",dmfdevs[i]);
14425449Skarels 	}
14525449Skarels 	printf(".\n");
14621955Sbloom 
14721955Sbloom 	if (dmfoptions & DMFC_LP)
14827057Skarels 		dmfaddr->dmfl_ctrl = DMFL_RESET;
1497412Skre 	return (sizeof (struct dmfdevice));
1506940Ssam }
1516940Ssam 
1526940Ssam /*
1536940Ssam  * Routine called to attach a dmf.
1546940Ssam  */
1556940Ssam dmfattach(ui)
15630537Skarels 	register struct uba_device *ui;
1576940Ssam {
15830537Skarels 	register struct dmx_softc *sc;
1596940Ssam 
16030537Skarels 	sc = &dmf_softc[ui->ui_unit];
16130537Skarels 	sc->dmx_type = 'f';
16230537Skarels 	sc->dmx_unit = ui->ui_unit;
16330537Skarels 	sc->dmx_unit0 = 0;
16430537Skarels 	sc->dmx_ubanum = ui->ui_ubanum;
16530537Skarels 	sc->dmx_softCAR = ui->ui_flags & 0xff;
16630537Skarels 	sc->dmx_tty = &dmf_tty[ui->ui_unit * 8];
16730537Skarels 	sc->dmx_octet =
16830537Skarels 	    (struct dmx_octet *)&((struct dmfdevice *)ui->ui_addr)->dmfa;
16930537Skarels 
17026221Skarels 	cbase[ui->ui_ubanum] = -1;
17136610Sbostic 	dmf_uballoc[ui->ui_ubanum] = -1;
17230537Skarels #if NDMF_LP > 0
17330537Skarels 	dmflattach(ui);
17430537Skarels #endif NDMF_LP
1756940Ssam }
1766940Ssam 
1776940Ssam /*
1786940Ssam  * Open a DMF32 line, mapping the clist onto the uba if this
1796940Ssam  * is the first dmf on this uba.  Turn on this dmf if this is
1806940Ssam  * the first use of it.
1816940Ssam  */
1826940Ssam /*ARGSUSED*/
1836940Ssam dmfopen(dev, flag)
1846940Ssam 	dev_t dev;
1856940Ssam {
1866940Ssam 	register struct tty *tp;
18730537Skarels 	register struct dmx_softc *sc;
18830537Skarels 	int unit, dmf;
1896940Ssam 	register struct dmfdevice *addr;
1906940Ssam 	register struct uba_device *ui;
1916940Ssam 	int s;
192*39061Smarc 	int dmxparam();
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);
20030537Skarels 
2016940Ssam 	tp = &dmf_tty[unit];
20230537Skarels 	sc = &dmf_softc[dmf];
2036940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
20430537Skarels 	tp->t_addr = (caddr_t)(&addr->dmfa);
2056940Ssam 	tp->t_oproc = dmfstart;
20630537Skarels 	tp->t_dev = dev;			/* needed before dmxopen */
207*39061Smarc 	tp->t_param = dmxparam;
20830537Skarels 
2096940Ssam 	/*
21030537Skarels 	 * While setting up state for this uba,
2116940Ssam 	 * block uba resets which can clear the state.
2126940Ssam 	 */
21330537Skarels 	s = spl6();
21426221Skarels 	if (cbase[ui->ui_ubanum] == -1) {
21530322Skarels 		dmf_uballoc[ui->ui_ubanum] = dmf;
21630322Skarels 		cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
21730322Skarels 		    (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
2186940Ssam 	}
2196940Ssam 	splx(s);
22030537Skarels 
221*39061Smarc 	return (dmxopen(tp, sc, flag));
2226940Ssam }
2236940Ssam 
2246940Ssam /*
2256940Ssam  * Close a DMF32 line.
2266940Ssam  */
2276940Ssam /*ARGSUSED*/
2286940Ssam dmfclose(dev, flag)
2296940Ssam 	dev_t dev;
2306940Ssam 	int flag;
2316940Ssam {
2326940Ssam 	register unit;
2336940Ssam 
2346940Ssam 	unit = minor(dev);
23526312Skarels 	if (unit & 0200) {
23630537Skarels 		dmflclose(dev, flag);
23726312Skarels 		return;
23826312Skarels 	}
23930537Skarels 	dmxclose(&dmf_tty[unit]);
2406940Ssam }
2416940Ssam 
242*39061Smarc dmfread(dev, uio, flag)
2436940Ssam 	dev_t dev;
2447726Sroot 	struct uio *uio;
2456940Ssam {
2466940Ssam 	register struct tty *tp;
2476940Ssam 
24826312Skarels 	if (minor(dev) & 0200)
24921955Sbloom 		return(ENXIO);
2506940Ssam 	tp = &dmf_tty[minor(dev)];
251*39061Smarc 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
2526940Ssam }
2536940Ssam 
2547832Sroot dmfwrite(dev, uio)
2556940Ssam 	dev_t dev;
2567832Sroot 	struct uio *uio;
2576940Ssam {
2586940Ssam 	register struct tty *tp;
2596940Ssam 
26026312Skarels 	if (minor(dev) & 0200)
26126312Skarels 		return (dmflwrite(dev,uio));
2626940Ssam 	tp = &dmf_tty[minor(dev)];
2638530Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
2646940Ssam }
2656940Ssam 
2666940Ssam /*
2676940Ssam  * DMF32 receiver interrupt.
2686940Ssam  */
2696940Ssam dmfrint(dmf)
2706940Ssam 	int dmf;
2716940Ssam {
27230537Skarels 	struct uba_device *ui;
2736940Ssam 
27426312Skarels 	ui = dmfinfo[dmf];
27526312Skarels 	if (ui == 0 || ui->ui_alive == 0)
27626312Skarels 		return;
27730537Skarels 	dmxrint(&dmf_softc[dmf]);
2786940Ssam }
2796940Ssam 
2806940Ssam /*
2816940Ssam  * Ioctl for DMF32.
2826940Ssam  */
2837630Ssam dmfioctl(dev, cmd, data, flag)
2846940Ssam 	dev_t dev;
2857630Ssam 	caddr_t data;
2866940Ssam {
28730537Skarels 	int unit = minor(dev);
2886940Ssam 
28926312Skarels 	if (unit & 0200)
29021955Sbloom 		return (ENOTTY);
29130537Skarels 	return (dmxioctl(&dmf_tty[unit], cmd, data, flag));
2926940Ssam }
2936940Ssam 
2946940Ssam /*
2956940Ssam  * DMF32 transmitter interrupt.
2966940Ssam  * Restart the idle line.
2976940Ssam  */
2986940Ssam dmfxint(dmf)
2996940Ssam 	int dmf;
3006940Ssam {
3016940Ssam 
30230537Skarels 	dmxxint(&dmf_softc[dmf]);
3036940Ssam }
3046940Ssam 
3056940Ssam /*
30630537Skarels  * Start (restart) transmission on the given line.
3076940Ssam  */
3086940Ssam dmfstart(tp)
30930537Skarels 	struct tty *tp;
3106940Ssam {
3116940Ssam 
31230537Skarels 	dmxstart(tp, &dmf_softc[minor(tp->t_dev) >> 3]);
3136940Ssam }
3146940Ssam 
3156940Ssam /*
3166940Ssam  * Stop output on a line, e.g. for ^S/^Q or output flush.
3176940Ssam  */
3186940Ssam dmfstop(tp, flag)
31930537Skarels 	struct tty *tp;
3206940Ssam {
3216940Ssam 
32230537Skarels 	dmxstop(tp, &dmf_softc[minor(tp->t_dev) >> 3], flag);
3236940Ssam }
3246940Ssam 
3256940Ssam /*
3266940Ssam  * Reset state of driver if UBA reset was necessary.
3276940Ssam  * Reset the csr, lpr, and lcr registers on open lines, and
3286940Ssam  * restart transmitters.
3296940Ssam  */
3306940Ssam dmfreset(uban)
3316940Ssam 	int uban;
3326940Ssam {
33330537Skarels 	register int dmf;
3346940Ssam 	register struct tty *tp;
3356940Ssam 	register struct uba_device *ui;
3366940Ssam 	register struct dmfdevice *addr;
3376940Ssam 	int i;
3386940Ssam 
3396940Ssam 	for (dmf = 0; dmf < NDMF; dmf++) {
3406940Ssam 		ui = dmfinfo[dmf];
3416940Ssam 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
3426940Ssam 			continue;
3436940Ssam 		printf(" dmf%d", dmf);
34430322Skarels 		if (dmf_uballoc[uban] == dmf) {
34530322Skarels 			int info;
34630322Skarels 
34730322Skarels 			info = uballoc(uban, (caddr_t)cfree,
34830322Skarels 			    nclist * sizeof(struct cblock), UBA_CANTWAIT);
34930322Skarels 			if (info)
35030322Skarels 				cbase[uban] = UBAI_ADDR(info);
35130322Skarels 			else {
35230322Skarels 				printf(" [can't get uba map]");
35330322Skarels 				cbase[uban] = -1;
35430322Skarels 			}
35525449Skarels 		}
3566940Ssam 		addr = (struct dmfdevice *)ui->ui_addr;
35730537Skarels 		addr->dmfa.csr = DMF_IE;
35830537Skarels 		addr->dmfa.rsp = dmx_timeout;
35930537Skarels 		tp = &dmf_tty[dmf * 8];
36030537Skarels 		for (i = 0; i < 8; i++, tp++) {
3616971Ssam 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
362*39061Smarc 				dmxparam(tp, &tp->t_termios);
36330537Skarels 				(void) dmxmctl(tp, DMF_ON, DMSET);
3646971Ssam 				tp->t_state &= ~TS_BUSY;
3656940Ssam 				dmfstart(tp);
3666940Ssam 			}
3676940Ssam 		}
36830537Skarels #if NDMF_LP > 0
36930537Skarels 		dmflint(dmf);
37030537Skarels #endif
3716940Ssam 	}
3726940Ssam }
3736940Ssam 
37430537Skarels #if NDMF_LP > 0
37526312Skarels /*
37630537Skarels  * DMF32 line printer driver
37730537Skarels  *
37830537Skarels  * the line printer on dmfx is indicated by a minor device code of 128+x
37930537Skarels  *
38030537Skarels  * the flags field of the config file is interpreted like so:
38130537Skarels  * bits		meaning
38230537Skarels  * ----		-------
38330537Skarels  * 0-7		soft carrier bits for ttys part of dmf32
38430537Skarels  * 8-15		number of cols/line on the line printer
38530537Skarels  *			if 0, 132 will be used.
38630537Skarels  * 16-23	number of lines/page on the line printer
38730537Skarels  *			if 0, 66 will be used.
38830537Skarels  * 24		if 1 DO NOT use the auto format mode of the
38930537Skarels  *			line printer parallel port
39030537Skarels  */
39130537Skarels 
39230537Skarels struct dmfl_softc {
39330537Skarels 	u_int	dmfl_state; 		/* soft state bits */
39430537Skarels 	int	dmfl_info;		/* uba info */
39530537Skarels 	u_short	dmfl_lines;		/* lines per page (66 def.) */
39630537Skarels 	u_short	dmfl_cols; 		/* cols per line (132 def.) */
39730537Skarels 	u_short	dmfl_format;		/* fflag for auto form feed */
39830537Skarels 	char	dmfl_buf[DMFL_BUFSIZ];
39930537Skarels } dmfl_softc[NDMF];
40030537Skarels 
40130537Skarels /*
40230537Skarels  * convert device number into DMF line printer unit number
40330537Skarels  */
40430537Skarels #define	DMFL_UNIT(d)	(minor(d) & 0xf)	/* up to 16 DMFs */
40530537Skarels 
40630537Skarels #define ASLP 1		/* waiting for interrupt from dmf */
40730537Skarels #define OPEN 2		/* line printer is open */
40830537Skarels #define ERROR 4		/* error while printing, driver
40930537Skarels 			 refuses to do anything till closed */
41030537Skarels #define MOREIO 8	/* more data for printer */
41130537Skarels 
41230537Skarels /*
41330537Skarels  * Attach printer portion of dmf.
41430537Skarels  */
41530537Skarels dmflattach(ui)
41630537Skarels 	register struct uba_device *ui;
41730537Skarels {
41830537Skarels 	register int unit = ui->ui_unit;
41930537Skarels 	register int cols = (ui->ui_flags>>8) & 0xff;
42030537Skarels 	register int lines = (ui->ui_flags>>16) & 0xff;
42130537Skarels 	register struct dmfl_softc *sc;
42230537Skarels 
42330537Skarels 	sc = &dmfl_softc[unit];
42430537Skarels 	sc->dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
42530537Skarels 	sc->dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
42630537Skarels  	if ((ui->ui_flags >> 24) & 0x1)
42730537Skarels  		sc->dmfl_format = (2 << 8);
42830537Skarels  	else
42930537Skarels  		sc->dmfl_format = (2 << 8) | DMFL_FORMAT;
43030537Skarels }
43130537Skarels 
43230537Skarels /*
43326312Skarels  * dmflopen -- open the line printer port on a dmf32
43421955Sbloom  */
43526312Skarels /* ARGSUSED */
43626312Skarels dmflopen(dev, flag)
43726312Skarels 	dev_t dev;
43826312Skarels 	int flag;
43921955Sbloom {
44021955Sbloom 	register int dmf;
44121955Sbloom 	register struct dmfl_softc *sc;
44221955Sbloom 	register struct uba_device *ui;
44321955Sbloom 	register struct dmfdevice *addr;
44421955Sbloom 
44526312Skarels 	dmf = DMFL_UNIT(dev);
44626910Skarels 	if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
44726910Skarels 		return (ENXIO);
44826910Skarels 	sc = &dmfl_softc[dmf];
44926910Skarels 	if (sc->dmfl_state & OPEN)
45026910Skarels 		return (EBUSY);
45121955Sbloom 	addr = (struct dmfdevice *)ui->ui_addr;
45226910Skarels 	if (addr->dmfl_ctrl & DMFL_OFFLINE) {
45326910Skarels #ifdef notdef
45426910Skarels 		log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
45526910Skarels 			dmf);
45626910Skarels #endif
45726312Skarels 		return (EIO);
45821955Sbloom 	}
45926910Skarels 	if ((addr->dmfl_ctrl & DMFL_CONV)) {
46026910Skarels 		log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
46126312Skarels 		return (EIO);
46221955Sbloom 	}
46321955Sbloom 
46426910Skarels 	addr->dmfl_ctrl = 0;
46521955Sbloom 	sc->dmfl_state |= OPEN;
46626312Skarels 	return (0);
46721955Sbloom }
46821955Sbloom 
46926312Skarels /* ARGSUSED */
47026312Skarels dmflclose(dev, flag)
47126312Skarels 	dev_t dev;
47226312Skarels 	int flag;
47321955Sbloom {
47426910Skarels 	register int dmf = DMFL_UNIT(dev);
47521955Sbloom 	register struct dmfl_softc *sc = &dmfl_softc[dmf];
47626910Skarels 	register struct uba_device *ui = dmfinfo[dmf];
47721955Sbloom 
47821955Sbloom 	sc->dmfl_state = 0;
47926312Skarels 	if (sc->dmfl_info != 0)
48026910Skarels 		ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
48121955Sbloom 
48226910Skarels 	((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
48321955Sbloom }
48421955Sbloom 
48526312Skarels dmflwrite(dev, uio)
48626312Skarels 	dev_t dev;
48726312Skarels 	struct uio *uio;
48821955Sbloom {
48926366Skarels 	register int n;
49021955Sbloom 	register int error;
49121955Sbloom 	register struct dmfl_softc *sc;
49221955Sbloom 
49321955Sbloom 	sc = &dmfl_softc[DMFL_UNIT(dev)];
49426910Skarels 	if (sc->dmfl_state & ERROR)
49526910Skarels 		return (EIO);
49626910Skarels 	while (n = (unsigned)uio->uio_resid) {
49726910Skarels 		if (n > DMFL_BUFSIZ) {
49826910Skarels 			n = DMFL_BUFSIZ;
49926910Skarels 			sc->dmfl_state |= MOREIO;
50026910Skarels 		} else
50126910Skarels 			sc->dmfl_state &= ~MOREIO;
50237765Smckusick 		if (error = uiomove(sc->dmfl_buf, (int)n, uio))
50326312Skarels 			return (error);
50426910Skarels 		if (error = dmflout(dev, sc->dmfl_buf, n))
50526312Skarels 			return (error);
50621955Sbloom 	}
50726312Skarels 	return (0);
50821955Sbloom }
50921955Sbloom 
51021955Sbloom 
51126312Skarels /*
51226312Skarels  * dmflout -- start io operation to dmf line printer
51321955Sbloom  *		cp is addr of buf of n chars to be sent.
51421955Sbloom  *
51521955Sbloom  *	-- dmf will be put in formatted output mode, this will
51621955Sbloom  *		be selectable from an ioctl if the
51721955Sbloom  *		need ever arises.
51821955Sbloom  */
51926312Skarels dmflout(dev, cp, n)
52026312Skarels 	dev_t dev;
52126312Skarels 	char *cp;
52226312Skarels 	int n;
52321955Sbloom {
52421955Sbloom 	register struct dmfl_softc *sc;
52521955Sbloom 	register int dmf;
52621955Sbloom 	register struct uba_device *ui;
52721955Sbloom 	register struct dmfdevice *d;
52826910Skarels 	int s;
52921955Sbloom 
53026312Skarels 	dmf = DMFL_UNIT(dev);
53126312Skarels 	sc = &dmfl_softc[dmf];
53226312Skarels 	if (sc->dmfl_state & ERROR)
53326312Skarels 		return (EIO);
53426312Skarels 	ui = dmfinfo[dmf];
53526312Skarels 	/*
53626312Skarels 	 * allocate unibus resources, will be released when io
53726312Skarels 	 * operation is done.
53821955Sbloom 	 */
53926910Skarels 	if (sc->dmfl_info == 0)
54026910Skarels 		sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
54126312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
54226910Skarels 	d->dmfl_ctrl = sc->dmfl_format;		/* indir reg 2 */
54321955Sbloom 	/* indir reg auto increments on r/w */
54421955Sbloom 	/* SO DON'T CHANGE THE ORDER OF THIS CODE */
54526910Skarels 	d->dmfl_indrct = 0;			/* prefix chars & num */
54626910Skarels 	d->dmfl_indrct = 0;			/* suffix chars & num */
54726910Skarels 	d->dmfl_indrct = sc->dmfl_info; 	/* dma lo 16 bits addr */
54826910Skarels 	d->dmfl_indrct = -n;			/* number of chars */
54921955Sbloom 
55026910Skarels 	d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
55126910Skarels 						/* dma hi 2 bits addr */
55226910Skarels 	d->dmfl_indrct = sc->dmfl_lines 	/* lines per page */
55326910Skarels 		| (sc->dmfl_cols<<8);		/* carriage width */
55421955Sbloom 	sc->dmfl_state |= ASLP;
55526910Skarels 	s = spltty();
55626910Skarels 	d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
55726312Skarels 	while (sc->dmfl_state & ASLP) {
55826910Skarels 		sleep(sc->dmfl_buf, PZERO + 8);
55926312Skarels 		while (sc->dmfl_state & ERROR) {
56026910Skarels 			timeout(dmflint, (caddr_t)dmf, 10 * hz);
56126910Skarels 			sleep((caddr_t)&sc->dmfl_state, PZERO + 8);
56221955Sbloom 		}
56321955Sbloom 	}
56426910Skarels 	splx(s);
56526312Skarels 	return (0);
56621955Sbloom }
56726312Skarels 
56826312Skarels /*
56926312Skarels  * dmflint -- handle an interrupt from the line printer part of the dmf32
57021955Sbloom  */
57121955Sbloom dmflint(dmf)
57226312Skarels 	int dmf;
57321955Sbloom {
57421955Sbloom 	register struct uba_device *ui;
57521955Sbloom 	register struct dmfl_softc *sc;
57621955Sbloom 	register struct dmfdevice *d;
57726910Skarels 	short dmfl_stats;
57821955Sbloom 
57926312Skarels 	ui = dmfinfo[dmf];
58026312Skarels 	sc = &dmfl_softc[dmf];
58126312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
58221955Sbloom 
58326910Skarels 	d->dmfl_ctrl &= ~DMFL_IE;
58427057Skarels 	dmfl_stats = d->dmfl_ctrl;
58526312Skarels 	if (sc->dmfl_state & ERROR) {
58626910Skarels 		if ((dmfl_stats & DMFL_OFFLINE) == 0)
58721955Sbloom 			sc->dmfl_state &= ~ERROR;
58826366Skarels 		wakeup((caddr_t)&sc->dmfl_state);
58921955Sbloom 		return;
59021955Sbloom 	}
59126910Skarels 	if (dmfl_stats & DMFL_DMAERR)
59226910Skarels 		log(LOG_WARNING, "dmf%d: NXM\n", dmf);
59326910Skarels 	if (dmfl_stats & DMFL_OFFLINE) {
59426910Skarels 		log(LOG_WARNING, "dmf%d: printer error\n", dmf);
59521955Sbloom 		sc->dmfl_state |= ERROR;
59621955Sbloom 	}
59721955Sbloom #ifdef notdef
59826910Skarels 	if (dmfl_stats & DMFL_PDONE) {
59926910Skarels 		printf("bytes= %d\n", d->dmfl_indrct);
60026910Skarels 		printf("lines= %d\n", d->dmfl_indrct);
60126910Skarels 	}
60221955Sbloom #endif
60321955Sbloom 	sc->dmfl_state &= ~ASLP;
60426910Skarels 	wakeup((caddr_t)sc->dmfl_buf);
60526910Skarels 	if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
60626312Skarels 		ubarelse(ui->ui_ubanum, &sc->dmfl_info);
60721955Sbloom }
60830537Skarels #endif NDMF_LP
60921955Sbloom 
6106940Ssam /* stubs for interrupt routines for devices not yet supported */
6116940Ssam 
61226312Skarels dmfsrint()
61326312Skarels {
61426312Skarels 	printf("dmfsrint\n");
61526312Skarels }
6166940Ssam 
61726312Skarels dmfsxint()
61826312Skarels {
61926312Skarels 	printf("dmfsxint\n");
62026312Skarels }
6216940Ssam 
62226312Skarels dmfdaint()
62326312Skarels {
62426312Skarels 	printf("dmfdaint\n");
62526312Skarels }
6266940Ssam 
62726312Skarels dmfdbint()
62826312Skarels {
62926312Skarels 	printf("dmfdbint\n");
63026312Skarels }
63126910Skarels #endif NDMF
632