xref: /csrg-svn/sys/vax/uba/dmf.c (revision 26312)
123324Smckusick /*
223324Smckusick  * Copyright (c) 1982 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*26312Skarels  *	@(#)dmf.c	6.14 (Berkeley) 02/21/86
723324Smckusick  */
86940Ssam 
96940Ssam #include "dmf.h"
106940Ssam #if NDMF > 0
116940Ssam /*
126940Ssam  * DMF32 driver
136940Ssam  *
1421955Sbloom  *
156940Ssam  * TODO:
166940Ssam  *	test with modem
176940Ssam  *	load as much as possible into silo
186940Ssam  *	use auto XON/XOFF
196940Ssam  *	test reset code
2021955Sbloom  ****************************
2121955Sbloom  * DMF32 line printer driver
2221955Sbloom  *
2321955Sbloom  * the line printer on dmfx is indicated by a minor device code of 128+x
2421955Sbloom  *
2521955Sbloom  * the flags field of the config file is interpreted like so:
2621955Sbloom  * bits		meaning
2721955Sbloom  * ----		-------
2821955Sbloom  * 0-7		soft carrier bits for ttys part of dmf32
2921955Sbloom  * 8-15		number of cols/line on the line printer
3021955Sbloom  *			if 0, 132 will be used.
3121955Sbloom  * 16-23	number of lines/page on the line printer
3221955Sbloom  *			if 0, 66 will be used.
3321955Sbloom  *
346940Ssam  */
359772Ssam #include "../machine/pte.h"
369772Ssam 
376940Ssam #include "bk.h"
3816063Skarels #include "uba.h"
3917124Sbloom #include "param.h"
4017124Sbloom #include "conf.h"
4117124Sbloom #include "dir.h"
4217124Sbloom #include "user.h"
4317124Sbloom #include "ioctl.h"
4417124Sbloom #include "tty.h"
4517124Sbloom #include "map.h"
4617124Sbloom #include "buf.h"
4717124Sbloom #include "vm.h"
4817124Sbloom #include "bkmac.h"
4917124Sbloom #include "clist.h"
5017124Sbloom #include "file.h"
5117124Sbloom #include "uio.h"
5221955Sbloom #include "kernel.h"
5318312Sralph #include "syslog.h"
546940Ssam 
5517124Sbloom #include "ubareg.h"
5617124Sbloom #include "ubavar.h"
5717124Sbloom #include "dmfreg.h"
588473Sroot 
596940Ssam /*
606940Ssam  * Definition of the driver for the auto-configuration program.
616940Ssam  */
626940Ssam int	dmfprobe(), dmfattach(), dmfrint(), dmfxint();
6321955Sbloom int	dmflint();
646940Ssam struct	uba_device *dmfinfo[NDMF];
656940Ssam u_short	dmfstd[] = { 0 };
666940Ssam struct	uba_driver dmfdriver =
676940Ssam 	{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
686940Ssam 
6925449Skarels int	dmf_timeout = 10;		/* silo timeout, in ms */
7021955Sbloom int	dmf_mindma = 4;			/* don't dma below this point */
7121955Sbloom 
726940Ssam /*
736940Ssam  * Local variables for the driver
746940Ssam  */
756940Ssam char	dmf_speeds[] =
766940Ssam 	{ 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
776940Ssam 
7825449Skarels #ifndef	PORTSELECTOR
7925449Skarels #define	ISPEED	B9600
8025449Skarels #define	IFLAGS	(EVENP|ODDP|ECHO)
8125449Skarels #else
8225449Skarels #define	ISPEED	B4800
8325449Skarels #define	IFLAGS	(EVENP|ODDP)
8425449Skarels #endif
8525449Skarels 
866940Ssam struct	tty dmf_tty[NDMF*8];
876940Ssam char	dmfsoftCAR[NDMF];
8821955Sbloom 
8921955Sbloom struct dmfl_softc
9021955Sbloom {
9121955Sbloom 	unsigned dmfl_state; 		/* soft state bits */
9221955Sbloom 	unsigned dmfl_info;		/* uba info */
9321955Sbloom 	unsigned short dmfl_lines;	/* lines per page (66 def.) */
9421955Sbloom 	unsigned short dmfl_cols; 	/* cols per line (132 def.) */
9521955Sbloom 	char dmfl_buf[DMFL_BUFSIZ];
9621955Sbloom } dmfl_softc[NDMF];
9721955Sbloom 
9821955Sbloom /*
9921955Sbloom  * convert device number into DMF line printer unit number
10021955Sbloom  */
10121955Sbloom #define	DMFL_UNIT(d)	(minor(d)&0xF)	/* up to 16 DMFs */
10221955Sbloom 
10321955Sbloom #define ASLP 1		/* waiting for interrupt from dmf */
10421955Sbloom #define OPEN 2		/* line printer is open */
10521955Sbloom #define ERROR 4		/* error while printing, driver
10621955Sbloom 			 refuses to do anything till closed */
10721955Sbloom 
1088778Sroot #ifndef lint
1098778Sroot int	ndmf = NDMF*8;			/* used by iostat */
1108778Sroot #endif
1116940Ssam int	dmfact;				/* mask of active dmf's */
1126940Ssam int	dmfstart(), ttrstrt();
1136940Ssam 
1146940Ssam /*
1156940Ssam  * The clist space is mapped by the driver onto each UNIBUS.
1166940Ssam  * The UBACVT macro converts a clist space address for unibus uban
1176940Ssam  * into an i/o space address for the DMA routine.
1186940Ssam  */
11916063Skarels int	dmf_ubinfo[NUBA];		/* info about allocated unibus map */
12025449Skarels int	cbase[NUBA];			/* base address in unibus map */
1216940Ssam #define	UBACVT(x, uban)		(cbase[uban] + ((x)-(char *)cfree))
12221955Sbloom char	dmf_dma[NDMF*8];
1236940Ssam 
1246940Ssam /*
1256940Ssam  * Routine for configuration to set dmf interrupt.
1266940Ssam  */
1276940Ssam /*ARGSUSED*/
1286940Ssam dmfprobe(reg, ctlr)
1296940Ssam 	caddr_t reg;
13021955Sbloom 	struct uba_device *ctlr;
1316940Ssam {
1326940Ssam 	register int br, cvec;		/* these are ``value-result'' */
1336940Ssam 	register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
13421955Sbloom 	register int i;
13521955Sbloom 	register unsigned int a;
13621955Sbloom 	static char *dmfdevs[]=
13721955Sbloom 		{"parallel","printer","synch","asynch"};
13821955Sbloom 	unsigned int dmfoptions;
13925449Skarels 	static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
1406940Ssam 
1416940Ssam #ifdef lint
1426940Ssam 	br = 0; cvec = br; br = cvec;
1438808Sroot 	dmfxint(0); dmfrint(0);
1448808Sroot 	dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint();
1456940Ssam #endif
14621955Sbloom 	/*
14721955Sbloom 	 * Pick the usual size DMF vector here (don't decrement it here).
14821955Sbloom 	 * grab configuration; note that the DMF32
14921955Sbloom 	 * doesn't seem to put the right bits in this
15021955Sbloom 	 * register until AFTER the interrupt vector is set.
15121955Sbloom 	 */
1526940Ssam 	br = 0x15;
15321955Sbloom 	cvec = (uba_hd[numuba].uh_lastiv - 4*8);
15425449Skarels 	dmfaddr->dmfccsr0 = (cvec >> 2);
15521955Sbloom 	dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
15621955Sbloom 
15721955Sbloom 	/* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
15821955Sbloom 	if (dmfoptions == DMFC_ASYNC) {
15925449Skarels 		/* Async portion only */
16025449Skarels 
16125449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
16225449Skarels 		dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
16325449Skarels 		intrv[0] = ctlr->ui_intr[4];
16425449Skarels 		intrv[1] = ctlr->ui_intr[5];
16525449Skarels 		ctlr->ui_intr = intrv;
166*26312Skarels 	} else if (dmfoptions == DMFC_LP) {
16725449Skarels 		/* LP portion only */
16821955Sbloom 
16925449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
17025449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[6];
171*26312Skarels 	} else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
17225449Skarels 		/* LP ans Async portions only */
17325449Skarels 
17425449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
17525449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[4];
176*26312Skarels 	} else {
17725449Skarels 		/* All other configurations get everything */
17821955Sbloom 
17921955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
18021955Sbloom 	}
18125449Skarels 	a = (dmfoptions >> 12) & 0xf;
18225449Skarels 	printf("dmf%d:", ctlr->ui_unit);
183*26312Skarels 	for (i = 0; a != 0; ++i, a >>= 1) {
184*26312Skarels 		if (a & 1)
18525449Skarels 			printf(" %s",dmfdevs[i]);
18625449Skarels 	}
18725449Skarels 	printf(".\n");
18821955Sbloom 
18921955Sbloom 	if (dmfoptions & DMFC_LP)
19021955Sbloom 		dmfaddr->dmfl[0] = DMFL_RESET;
1917412Skre 	return (sizeof (struct dmfdevice));
1926940Ssam }
1936940Ssam 
1946940Ssam /*
1956940Ssam  * Routine called to attach a dmf.
1966940Ssam  */
1976940Ssam dmfattach(ui)
1986940Ssam 	struct uba_device *ui;
1996940Ssam {
20021955Sbloom 	register int cols = (ui->ui_flags>>8) & 0xff;
20121955Sbloom 	register int lines = (ui->ui_flags>>16) & 0xff;
2026940Ssam 
20321955Sbloom 	dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff;
20421955Sbloom 	dmfl_softc[ui->ui_unit].dmfl_cols = cols==0?DMFL_DEFCOLS:cols;
20521955Sbloom 	dmfl_softc[ui->ui_unit].dmfl_lines = lines==0?DMFL_DEFLINES:lines;
20626221Skarels 	cbase[ui->ui_ubanum] = -1;
2076940Ssam }
2086940Ssam 
2096940Ssam 
2106940Ssam /*
2116940Ssam  * Open a DMF32 line, mapping the clist onto the uba if this
2126940Ssam  * is the first dmf on this uba.  Turn on this dmf if this is
2136940Ssam  * the first use of it.
2146940Ssam  */
2156940Ssam /*ARGSUSED*/
2166940Ssam dmfopen(dev, flag)
2176940Ssam 	dev_t dev;
2186940Ssam {
2196940Ssam 	register struct tty *tp;
2206940Ssam 	register int unit, dmf;
2216940Ssam 	register struct dmfdevice *addr;
2226940Ssam 	register struct uba_device *ui;
2236940Ssam 	int s;
2246940Ssam 
2256940Ssam 	unit = minor(dev);
226*26312Skarels 	if (unit & 0200)
227*26312Skarels 		return (dmflopen(dev,flag));
2286940Ssam 	dmf = unit >> 3;
2298567Sroot 	if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
2308567Sroot 		return (ENXIO);
2316940Ssam 	tp = &dmf_tty[unit];
2328567Sroot 	if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
2338567Sroot 		return (EBUSY);
2346940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
2356940Ssam 	tp->t_addr = (caddr_t)addr;
2366940Ssam 	tp->t_oproc = dmfstart;
2376971Ssam 	tp->t_state |= TS_WOPEN;
2386940Ssam 	/*
2396940Ssam 	 * While setting up state for this uba and this dmf,
2406940Ssam 	 * block uba resets which can clear the state.
2416940Ssam 	 */
24221955Sbloom 	s = spltty();
24326221Skarels 	if (cbase[ui->ui_ubanum] == -1) {
2446940Ssam 		dmf_ubinfo[ui->ui_ubanum] =
2456940Ssam 		    uballoc(ui->ui_ubanum, (caddr_t)cfree,
2466940Ssam 			nclist*sizeof(struct cblock), 0);
24726221Skarels 		cbase[ui->ui_ubanum] = UBAI_ADDR(dmf_ubinfo[ui->ui_ubanum]);
2486940Ssam 	}
2496940Ssam 	if ((dmfact&(1<<dmf)) == 0) {
2506940Ssam 		addr->dmfcsr |= DMF_IE;
2516940Ssam 		dmfact |= (1<<dmf);
25221955Sbloom 		addr->dmfrsp = dmf_timeout;
2536940Ssam 	}
2546940Ssam 	splx(s);
2556940Ssam 	/*
2566940Ssam 	 * If this is first open, initialze tty state to default.
2576940Ssam 	 */
2586971Ssam 	if ((tp->t_state&TS_ISOPEN) == 0) {
2596940Ssam 		ttychars(tp);
26025449Skarels 		tp->t_ispeed = ISPEED;
26125449Skarels 		tp->t_ospeed = ISPEED;
26225449Skarels 		tp->t_flags = IFLAGS;
2636940Ssam 		dmfparam(unit);
2646940Ssam 	}
2656940Ssam 	/*
2666940Ssam 	 * Wait for carrier, then process line discipline specific open.
2676940Ssam 	 */
2686940Ssam 	if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
2696940Ssam 	    (dmfsoftCAR[dmf] & (1<<(unit&07))))
2706971Ssam 		tp->t_state |= TS_CARR_ON;
27121955Sbloom 	s = spltty();
2726971Ssam 	while ((tp->t_state & TS_CARR_ON) == 0) {
2736971Ssam 		tp->t_state |= TS_WOPEN;
2746940Ssam 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
2756940Ssam 	}
2766940Ssam 	splx(s);
2778567Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
2786940Ssam }
2796940Ssam 
2806940Ssam /*
2816940Ssam  * Close a DMF32 line.
2826940Ssam  */
2836940Ssam /*ARGSUSED*/
2846940Ssam dmfclose(dev, flag)
2856940Ssam 	dev_t dev;
2866940Ssam 	int flag;
2876940Ssam {
2886940Ssam 	register struct tty *tp;
2896940Ssam 	register unit;
2906940Ssam 
2916940Ssam 	unit = minor(dev);
292*26312Skarels 	if (unit & 0200) {
293*26312Skarels 		dmflclose(dev,flag);
294*26312Skarels 		return;
295*26312Skarels 	}
29621955Sbloom 
2976940Ssam 	tp = &dmf_tty[unit];
2986940Ssam 	(*linesw[tp->t_line].l_close)(tp);
2998702Sroot 	(void) dmfmctl(unit, DMF_BRK, DMBIC);
3006971Ssam 	if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
3018702Sroot 		(void) dmfmctl(unit, DMF_OFF, DMSET);
3026940Ssam 	ttyclose(tp);
3036940Ssam }
3046940Ssam 
3057726Sroot dmfread(dev, uio)
3066940Ssam 	dev_t dev;
3077726Sroot 	struct uio *uio;
3086940Ssam {
3096940Ssam 	register struct tty *tp;
3106940Ssam 
311*26312Skarels 	if (minor(dev) & 0200)
31221955Sbloom 		return(ENXIO);
3136940Ssam 	tp = &dmf_tty[minor(dev)];
3147726Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
3156940Ssam }
3166940Ssam 
3177832Sroot dmfwrite(dev, uio)
3186940Ssam 	dev_t dev;
3197832Sroot 	struct uio *uio;
3206940Ssam {
3216940Ssam 	register struct tty *tp;
3226940Ssam 
323*26312Skarels 	if (minor(dev) & 0200)
324*26312Skarels 		return (dmflwrite(dev,uio));
3256940Ssam 	tp = &dmf_tty[minor(dev)];
3268530Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
3276940Ssam }
3286940Ssam 
3296940Ssam /*
3306940Ssam  * DMF32 receiver interrupt.
3316940Ssam  */
3326940Ssam dmfrint(dmf)
3336940Ssam 	int dmf;
3346940Ssam {
3356940Ssam 	register c;
336*26312Skarels 	register struct tty *tp;
3376940Ssam 	register struct dmfdevice *addr;
3386940Ssam 	register struct tty *tp0;
33921955Sbloom 	int unit;
34025449Skarels 	int overrun = 0;
341*26312Skarels 	register struct uba_device *ui;
3426940Ssam 
343*26312Skarels 	ui = dmfinfo[dmf];
344*26312Skarels 	if (ui == 0 || ui->ui_alive == 0)
345*26312Skarels 		return;
346*26312Skarels 	addr = (struct dmfdevice *)ui->ui_addr;
34721955Sbloom 	tp0 = &dmf_tty[dmf * 8];
3486940Ssam 	/*
3496940Ssam 	 * Loop fetching characters from the silo for this
3506940Ssam 	 * dmf until there are no more in the silo.
3516940Ssam 	 */
3526940Ssam 	while ((c = addr->dmfrbuf) < 0) {
35321955Sbloom 
35421955Sbloom 		unit = (c >> 8) & 07;
35521955Sbloom 		tp = tp0 + unit;
3566940Ssam 		if (c & DMF_DSC) {
35721955Sbloom 			addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
35825449Skarels 			if (addr->dmfrms & DMF_CAR)
35925449Skarels 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
360*26312Skarels 			else if ((dmfsoftCAR[dmf] & (1 << unit)) == 0 &&
36125449Skarels 			    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
36225449Skarels 				addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
36325449Skarels 				addr->dmflctms = DMFLCR_ENA;
3646940Ssam 			}
3656940Ssam 			continue;
3666940Ssam 		}
367*26312Skarels 		if ((tp->t_state&TS_ISOPEN) == 0) {
36825449Skarels 			wakeup((caddr_t)&tp->t_rawq);
36925449Skarels #ifdef PORTSELECTOR
370*26312Skarels 			if ((tp->t_state & TS_WOPEN) == 0)
37125449Skarels #endif
37225449Skarels 				continue;
3736940Ssam 		}
37421956Sbloom 		if (c & (DMF_PE|DMF_DO|DMF_FE)) {
37521955Sbloom 			if (c & DMF_PE)
376*26312Skarels 				if ((tp->t_flags & (EVENP|ODDP)) == EVENP
377*26312Skarels 			 	|| (tp->t_flags & (EVENP|ODDP)) == ODDP)
37821955Sbloom 					continue;
37921955Sbloom 			if ((c & DMF_DO) && overrun == 0) {
38024842Seric 				log(LOG_WARNING, "dmf%d: silo overflow\n", dmf);
38121955Sbloom 				overrun = 1;
38221955Sbloom 			}
38321955Sbloom 			if (c & DMF_FE)
38421955Sbloom 				/*
38521955Sbloom 			 	* At framing error (break) generate
38621955Sbloom 			 	* a null (in raw mode, for getty), or a
38721955Sbloom 			 	* interrupt (in cooked/cbreak mode).
38821955Sbloom 			 	*/
389*26312Skarels 				if (tp->t_flags & RAW)
39021955Sbloom 					c = 0;
39121955Sbloom 				else
39221955Sbloom 					c = tp->t_intrc;
3936940Ssam 		}
3946940Ssam #if NBK > 0
3956940Ssam 		if (tp->t_line == NETLDISC) {
3966940Ssam 			c &= 0177;
3976940Ssam 			BKINPUT(c, tp);
3986940Ssam 		} else
3996940Ssam #endif
4006940Ssam 			(*linesw[tp->t_line].l_rint)(c, tp);
4016940Ssam 	}
4026940Ssam }
4036940Ssam 
4046940Ssam /*
4056940Ssam  * Ioctl for DMF32.
4066940Ssam  */
4076940Ssam /*ARGSUSED*/
4087630Ssam dmfioctl(dev, cmd, data, flag)
4096940Ssam 	dev_t dev;
4107630Ssam 	caddr_t data;
4116940Ssam {
4126940Ssam 	register struct tty *tp;
4136940Ssam 	register int unit = minor(dev);
4148567Sroot 	int error;
4156940Ssam 
416*26312Skarels 	if (unit & 0200)
41721955Sbloom 		return (ENOTTY);
4186940Ssam 	tp = &dmf_tty[unit];
4198567Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
4208567Sroot 	if (error >= 0)
4218567Sroot 		return (error);
4228567Sroot 	error = ttioctl(tp, cmd, data, flag);
4238567Sroot 	if (error >= 0) {
42417562Sbloom 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
42517562Sbloom 		    cmd == TIOCLBIC || cmd == TIOCLSET)
4266940Ssam 			dmfparam(unit);
4278567Sroot 		return (error);
4288567Sroot 	}
4298567Sroot 	switch (cmd) {
4306940Ssam 
4316940Ssam 	case TIOCSBRK:
4328702Sroot 		(void) dmfmctl(dev, DMF_BRK, DMBIS);
4336940Ssam 		break;
4347630Ssam 
4356940Ssam 	case TIOCCBRK:
4368702Sroot 		(void) dmfmctl(dev, DMF_BRK, DMBIC);
4376940Ssam 		break;
4387630Ssam 
4396940Ssam 	case TIOCSDTR:
4408702Sroot 		(void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
4416940Ssam 		break;
4427630Ssam 
4436940Ssam 	case TIOCCDTR:
4448702Sroot 		(void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
4456940Ssam 		break;
4467630Ssam 
4476940Ssam 	case TIOCMSET:
4488702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
4496940Ssam 		break;
4507630Ssam 
4516940Ssam 	case TIOCMBIS:
4528702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
4536940Ssam 		break;
4547630Ssam 
4556940Ssam 	case TIOCMBIC:
4568702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
4576940Ssam 		break;
4587630Ssam 
4596940Ssam 	case TIOCMGET:
4607630Ssam 		*(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
4616940Ssam 		break;
4627630Ssam 
4636940Ssam 	default:
4648567Sroot 		return (ENOTTY);
4656940Ssam 	}
4668567Sroot 	return (0);
4676940Ssam }
4686940Ssam 
4696940Ssam dmtodmf(bits)
4706940Ssam 	register int bits;
4716940Ssam {
4726940Ssam 	register int b;
4736940Ssam 
4746940Ssam 	b = bits & 012;
4756940Ssam 	if (bits & DML_ST) b |= DMF_RATE;
4766940Ssam 	if (bits & DML_RTS) b |= DMF_RTS;
4776940Ssam 	if (bits & DML_USR) b |= DMF_USRW;
4786940Ssam 	return(b);
4796940Ssam }
4806940Ssam 
4816940Ssam dmftodm(bits)
4826940Ssam 	register int bits;
4836940Ssam {
4846940Ssam 	register int b;
4856940Ssam 
4866940Ssam 	b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
4876940Ssam 	if (bits & DMF_USRR) b |= DML_USR;
4886940Ssam 	if (bits & DMF_RTS) b |= DML_RTS;
4896940Ssam 	return(b);
4906940Ssam }
4916940Ssam 
4926940Ssam 
4936940Ssam /*
4946940Ssam  * Set parameters from open or stty into the DMF hardware
4956940Ssam  * registers.
4966940Ssam  */
4976940Ssam dmfparam(unit)
4986940Ssam 	register int unit;
4996940Ssam {
5006940Ssam 	register struct tty *tp;
5016940Ssam 	register struct dmfdevice *addr;
5026940Ssam 	register int lpar, lcr;
5036940Ssam 	int s;
5046940Ssam 
5056940Ssam 	tp = &dmf_tty[unit];
5066940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
5076940Ssam 	/*
5086940Ssam 	 * Block interrupts so parameters will be set
5096940Ssam 	 * before the line interrupts.
5106940Ssam 	 */
51121955Sbloom 	s = spltty();
5126940Ssam 	addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
5136940Ssam 	if ((tp->t_ispeed)==0) {
5146971Ssam 		tp->t_state |= TS_HUPCLS;
5158702Sroot 		(void) dmfmctl(unit, DMF_OFF, DMSET);
51625449Skarels 		splx(s);
5176940Ssam 		return;
5186940Ssam 	}
5196940Ssam 	lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
5206940Ssam 	lcr = DMFLCR_ENA;
5216940Ssam 	if ((tp->t_ispeed) == B134)
5226940Ssam 		lpar |= BITS6|PENABLE;
52324270Slepreau 	else if (tp->t_flags & (RAW|LITOUT|PASS8))
5246940Ssam 		lpar |= BITS8;
5256940Ssam 	else {
5266940Ssam 		lpar |= BITS7|PENABLE;
5276940Ssam 		/* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
5286940Ssam 	}
52912450Ssam 	if (tp->t_flags&EVENP)
53012450Ssam 		lpar |= EPAR;
5316940Ssam 	if ((tp->t_ospeed) == B110)
5326940Ssam 		lpar |= TWOSB;
5336940Ssam 	lpar |= (unit&07);
5346940Ssam 	addr->dmflpr = lpar;
53525654Skarels 	addr->dmflctms = (addr->dmflctms &~ 0xff) | lcr;
5366940Ssam 	splx(s);
5376940Ssam }
5386940Ssam 
5396940Ssam /*
5406940Ssam  * DMF32 transmitter interrupt.
5416940Ssam  * Restart the idle line.
5426940Ssam  */
5436940Ssam dmfxint(dmf)
5446940Ssam 	int dmf;
5456940Ssam {
546*26312Skarels 	int unit0 = dmf * 8;
547*26312Skarels 	struct tty *tp0 = &dmf_tty[unit0];
5486940Ssam 	register struct tty *tp;
5496940Ssam 	register struct dmfdevice *addr;
5506940Ssam 	register struct uba_device *ui;
55121955Sbloom 	register int t;
5526940Ssam 	short cntr;
5536940Ssam 
5546940Ssam 	ui = dmfinfo[dmf];
5556940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
5566940Ssam 	while ((t = addr->dmfcsr) & DMF_TI) {
55721955Sbloom 		if (t & DMF_NXM)
55821955Sbloom 			/* SHOULD RESTART OR SOMETHING... */
55921955Sbloom 			printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
56021955Sbloom 		t = t >> 8 & 7;
56121955Sbloom 		tp = tp0 + t;
5626971Ssam 		tp->t_state &= ~TS_BUSY;
5636971Ssam 		if (tp->t_state&TS_FLUSH)
5646971Ssam 			tp->t_state &= ~TS_FLUSH;
565*26312Skarels 		else if (dmf_dma[unit0 + t]) {
56621955Sbloom 			/*
56721955Sbloom 			 * Do arithmetic in a short to make up
56821955Sbloom 			 * for lost 16&17 bits.
56921955Sbloom 			 */
57021955Sbloom 			addr->dmfcsr = DMFIR_TBA | DMF_IE | t;
57121955Sbloom 			cntr = addr->dmftba -
57221955Sbloom 			    UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
57321955Sbloom 			ndflush(&tp->t_outq, (int)cntr);
5746940Ssam 		}
5756940Ssam 		if (tp->t_line)
5766940Ssam 			(*linesw[tp->t_line].l_start)(tp);
5776940Ssam 		else
5786940Ssam 			dmfstart(tp);
5796940Ssam 	}
5806940Ssam }
5816940Ssam 
5826940Ssam /*
5836940Ssam  * Start (restart) transmission on the given DMF32 line.
5846940Ssam  */
5856940Ssam dmfstart(tp)
5866940Ssam 	register struct tty *tp;
5876940Ssam {
5886940Ssam 	register struct dmfdevice *addr;
5898607Sroot 	register int unit, nch;
5906940Ssam 	int s;
59121955Sbloom 	register int dmf;
5926940Ssam 
5936940Ssam 	unit = minor(tp->t_dev);
59421955Sbloom 	dmf = unit >> 3;
5956940Ssam 	unit &= 07;
5966940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
5976940Ssam 
5986940Ssam 	/*
5996940Ssam 	 * Must hold interrupts in following code to prevent
6006940Ssam 	 * state of the tp from changing.
6016940Ssam 	 */
60221955Sbloom 	s = spltty();
6036940Ssam 	/*
6046940Ssam 	 * If it's currently active, or delaying, no need to do anything.
6056940Ssam 	 */
6066971Ssam 	if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
6076940Ssam 		goto out;
6086940Ssam 	/*
6096940Ssam 	 * If there are still characters in the silo,
6106940Ssam 	 * just reenable the transmitter.
6116940Ssam 	 */
6126940Ssam 	addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
6136940Ssam 	if (addr->dmftsc) {
6146940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
61525449Skarels 		addr->dmflctms = addr->dmflctms | DMF_TE;
6166971Ssam 		tp->t_state |= TS_BUSY;
6176940Ssam 		goto out;
6186940Ssam 	}
6196940Ssam 	/*
6206940Ssam 	 * If there are sleepers, and output has drained below low
6216940Ssam 	 * water mark, wake up the sleepers.
6226940Ssam 	 */
62321955Sbloom 	if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
62421955Sbloom 		if (tp->t_state&TS_ASLEEP) {
62521955Sbloom 			tp->t_state &= ~TS_ASLEEP;
62621955Sbloom 			wakeup((caddr_t)&tp->t_outq);
62721955Sbloom 		}
62821955Sbloom 		if (tp->t_wsel) {
62921955Sbloom 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
63021955Sbloom 			tp->t_wsel = 0;
63121955Sbloom 			tp->t_state &= ~TS_WCOLL;
63221955Sbloom 		}
6336940Ssam 	}
6346940Ssam 	/*
6356940Ssam 	 * Now restart transmission unless the output queue is
6366940Ssam 	 * empty.
6376940Ssam 	 */
6386940Ssam 	if (tp->t_outq.c_cc == 0)
6396940Ssam 		goto out;
6409550Ssam 	if (tp->t_flags & (RAW|LITOUT))
6416940Ssam 		nch = ndqb(&tp->t_outq, 0);
6426940Ssam 	else {
64321955Sbloom 		if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
64421955Sbloom 			/*
64521955Sbloom 		 	* If first thing on queue is a delay process it.
64621955Sbloom 		 	*/
6476940Ssam 			nch = getc(&tp->t_outq);
6486940Ssam 			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
6496971Ssam 			tp->t_state |= TS_TIMEOUT;
6506940Ssam 			goto out;
6516940Ssam 		}
6526940Ssam 	}
6536940Ssam 	/*
6546940Ssam 	 * If characters to transmit, restart transmission.
6556940Ssam 	 */
65621955Sbloom 	if (nch >= dmf_mindma) {
65721955Sbloom 		register car;
65821955Sbloom 
65921955Sbloom 		dmf_dma[minor(tp->t_dev)] = 1;
6606940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
66125449Skarels 		addr->dmflctms = addr->dmflctms | DMF_TE;
6626940Ssam 		car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
6636940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
6646940Ssam 		addr->dmftba = car;
66521955Sbloom 		addr->dmftcc = ((car >> 2) & 0xc000) | nch;
66621955Sbloom 		tp->t_state |= TS_BUSY;
66721955Sbloom 	} else if (nch) {
6686940Ssam 		register char *cp = tp->t_outq.c_cf;
6696940Ssam 		register int i;
6706940Ssam 
67121955Sbloom 		dmf_dma[minor(tp->t_dev)] = 0;
6726940Ssam 		nch = MIN(nch, DMF_SILOCNT);
6736940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
67425449Skarels 		addr->dmflctms = addr->dmflctms | DMF_TE;
6756940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
6766940Ssam 		for (i = 0; i < nch; i++)
6776940Ssam 			addr->dmftbuf = *cp++;
6786940Ssam 		ndflush(&tp->t_outq, nch);
6796971Ssam 		tp->t_state |= TS_BUSY;
6806940Ssam 	}
6816940Ssam out:
6826940Ssam 	splx(s);
6836940Ssam }
6846940Ssam 
6856940Ssam /*
6866940Ssam  * Stop output on a line, e.g. for ^S/^Q or output flush.
6876940Ssam  */
6886940Ssam /*ARGSUSED*/
6896940Ssam dmfstop(tp, flag)
6906940Ssam 	register struct tty *tp;
6916940Ssam {
6926940Ssam 	register struct dmfdevice *addr;
69321955Sbloom 	register unit = minor(tp->t_dev) & 7;
69421955Sbloom 	int s;
6956940Ssam 
6966940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
6976940Ssam 	/*
6986940Ssam 	 * Block input/output interrupts while messing with state.
6996940Ssam 	 */
70021955Sbloom 	s = spltty();
70121955Sbloom 	if (flag) {
70221955Sbloom 		addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
70321955Sbloom 		if (addr->dmftsc) {
70421955Sbloom 			/*
70521955Sbloom 			 * Flush regardless of whether we're transmitting
70621955Sbloom 			 * (TS_BUSY), if the silo contains untransmitted
70721955Sbloom 			 * characters.
70821955Sbloom 			 */
70921955Sbloom 			addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
71025449Skarels 			addr->dmflctms = addr->dmflctms | DMF_TE | DMF_FLUSH;
71121955Sbloom 			/* this will interrupt so let dmfxint handle the rest */
71221955Sbloom 			tp->t_state |= TS_FLUSH|TS_BUSY;
71321955Sbloom 		}
71421955Sbloom 	} else {
71521955Sbloom 		if (tp->t_state & TS_BUSY) {
71621955Sbloom 			/*
71721955Sbloom 			 * Stop transmission by disabling
71821955Sbloom 			 * the transmitter.  We'll pick up where we
71921955Sbloom 			 * left off by reenabling in dmfstart.
72021955Sbloom 			 */
72121955Sbloom 			addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
72225449Skarels 			addr->dmflctms = addr->dmflctms &~ DMF_TE;
72321955Sbloom 			/* no interrupt here */
7246971Ssam 			tp->t_state &= ~TS_BUSY;
72521955Sbloom 		}
7266940Ssam 	}
7276940Ssam 	splx(s);
7286940Ssam }
7296940Ssam 
7306940Ssam /*
7316940Ssam  * DMF32 modem control
7326940Ssam  */
7336940Ssam dmfmctl(dev, bits, how)
7346940Ssam 	dev_t dev;
7356940Ssam 	int bits, how;
7366940Ssam {
7376940Ssam 	register struct dmfdevice *dmfaddr;
7386940Ssam 	register int unit, mbits, lcr;
7396940Ssam 	int s;
7406940Ssam 
7416940Ssam 	unit = minor(dev);
7426940Ssam 	dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
7436940Ssam 	unit &= 07;
74421955Sbloom 	s = spltty();
7456940Ssam 	dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
7466940Ssam 	mbits = dmfaddr->dmfrms << 8;
7476940Ssam 	dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
74825654Skarels 	lcr = dmfaddr->dmflctms;
74925449Skarels 	mbits |= (lcr & 0xff00) >> 8;
7506940Ssam 	switch (how) {
7516940Ssam 	case DMSET:
75212449Ssam 		mbits = (mbits &0xff00) | bits;
7536940Ssam 		break;
7546940Ssam 
7556940Ssam 	case DMBIS:
7566940Ssam 		mbits |= bits;
7576940Ssam 		break;
7586940Ssam 
7596940Ssam 	case DMBIC:
7606940Ssam 		mbits &= ~bits;
7616940Ssam 		break;
7626940Ssam 
7636940Ssam 	case DMGET:
7646940Ssam 		(void) splx(s);
7656940Ssam 		return(mbits);
7666940Ssam 	}
7676940Ssam 	if (mbits & DMF_BRK)
7686940Ssam 		lcr |= DMF_RBRK;
7696940Ssam 	else
7706940Ssam 		lcr &= ~DMF_RBRK;
77125449Skarels 	dmfaddr->dmflctms = ((mbits & 037) << 8) | (lcr & 0xff);
7726940Ssam 	(void) splx(s);
7736940Ssam 	return(mbits);
7746940Ssam }
7756940Ssam 
7766940Ssam /*
7776940Ssam  * Reset state of driver if UBA reset was necessary.
7786940Ssam  * Reset the csr, lpr, and lcr registers on open lines, and
7796940Ssam  * restart transmitters.
7806940Ssam  */
7816940Ssam dmfreset(uban)
7826940Ssam 	int uban;
7836940Ssam {
7846940Ssam 	register int dmf, unit;
7856940Ssam 	register struct tty *tp;
7866940Ssam 	register struct uba_device *ui;
7876940Ssam 	register struct dmfdevice *addr;
7886940Ssam 	int i;
7896940Ssam 
7906940Ssam 	for (dmf = 0; dmf < NDMF; dmf++) {
7916940Ssam 		ui = dmfinfo[dmf];
7926940Ssam 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
7936940Ssam 			continue;
7946940Ssam 		printf(" dmf%d", dmf);
79526221Skarels 		if (dmf_ubinfo[uban]) {
79625449Skarels 			dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
79725449Skarels 			    nclist*sizeof (struct cblock), 0);
79826221Skarels 			cbase[uban] = UBAI_ADDR(dmf_ubinfo[uban]);
79925449Skarels 		}
8006940Ssam 		addr = (struct dmfdevice *)ui->ui_addr;
8016940Ssam 		addr->dmfcsr = DMF_IE;
80221955Sbloom 		addr->dmfrsp = dmf_timeout;
8036940Ssam 		unit = dmf * 8;
8046940Ssam 		for (i = 0; i < 8; i++) {
8056940Ssam 			tp = &dmf_tty[unit];
8066971Ssam 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
8076940Ssam 				dmfparam(unit);
8088702Sroot 				(void) dmfmctl(unit, DMF_ON, DMSET);
8096971Ssam 				tp->t_state &= ~TS_BUSY;
8106940Ssam 				dmfstart(tp);
8116940Ssam 			}
8126940Ssam 			unit++;
8136940Ssam 		}
8146940Ssam 	}
8156940Ssam }
8166940Ssam 
817*26312Skarels /*
818*26312Skarels  * dmflopen -- open the line printer port on a dmf32
81921955Sbloom  */
820*26312Skarels /* ARGSUSED */
821*26312Skarels dmflopen(dev, flag)
822*26312Skarels 	dev_t dev;
823*26312Skarels 	int flag;
82421955Sbloom {
82521955Sbloom 	register int dmf;
82621955Sbloom 	register struct dmfl_softc *sc;
82721955Sbloom 	register struct uba_device *ui;
82821955Sbloom 	register struct dmfdevice *addr;
82921955Sbloom 
830*26312Skarels 	dmf = DMFL_UNIT(dev);
831*26312Skarels 	if (((sc= &dmfl_softc[dmf])->dmfl_state & OPEN) ||
83221955Sbloom 		((ui=dmfinfo[dmf]) == 0) || ui->ui_alive == 0)
83321955Sbloom 			return(ENXIO);
83421955Sbloom 	addr = (struct dmfdevice *)ui->ui_addr;
835*26312Skarels 	if ((addr->dmfl[0] & DMFL_OFFLINE)) {
83621955Sbloom 		/*printf("dmf: line printer offline/jammed\n");*/
837*26312Skarels 		return (EIO);
83821955Sbloom 	}
839*26312Skarels 	if ((addr->dmfl[0] & DMFL_CONV)) {
84021955Sbloom 		printf("dmf:line printer disconnected\n");
841*26312Skarels 		return (EIO);
84221955Sbloom 	}
84321955Sbloom 
84421955Sbloom 	addr->dmfl[0] = 0;
84521955Sbloom 	sc->dmfl_state |= OPEN;
846*26312Skarels 	return (0);
84721955Sbloom }
84821955Sbloom 
849*26312Skarels /* ARGSUSED */
850*26312Skarels dmflclose(dev, flag)
851*26312Skarels 	dev_t dev;
852*26312Skarels 	int flag;
85321955Sbloom {
85421955Sbloom 	register int dmf= DMFL_UNIT(dev);
85521955Sbloom 	register struct dmfl_softc *sc = &dmfl_softc[dmf];
85621955Sbloom 
857*26312Skarels 	dmflout(dev, "\f", 1);
85821955Sbloom 	sc->dmfl_state = 0;
859*26312Skarels 	if (sc->dmfl_info != 0)
86021955Sbloom 		ubarelse((struct dmfdevice *)(dmfinfo[dmf])->ui_ubanum,
86121955Sbloom 			&(sc->dmfl_info));
86221955Sbloom 
863*26312Skarels 	((struct dmfdevice *)(dmfinfo[dmf]->ui_addr))->dmfl[0] = 0;
864*26312Skarels 	return (0);
86521955Sbloom }
86621955Sbloom 
867*26312Skarels dmflwrite(dev, uio)
868*26312Skarels 	dev_t dev;
869*26312Skarels 	struct uio *uio;
87021955Sbloom {
87121955Sbloom 	register unsigned int n;
87221955Sbloom 	register int error;
87321955Sbloom 	register struct dmfl_softc *sc;
87421955Sbloom 
87521955Sbloom 	sc = &dmfl_softc[DMFL_UNIT(dev)];
876*26312Skarels 	if (sc->dmfl_state&ERROR)
877*26312Skarels 		return(EIO);
878*26312Skarels 	while (n = min(DMFL_BUFSIZ, (unsigned)uio->uio_resid)) {
879*26312Skarels 		if (error = uiomove(&sc->dmfl_buf[0], (int)n, UIO_WRITE, uio)) {
88021955Sbloom 			printf("uio move error\n");
881*26312Skarels 			return (error);
88221955Sbloom 		}
883*26312Skarels 		if (error = dmflout(dev, &sc->dmfl_buf[0], n))
884*26312Skarels 			return (error);
88521955Sbloom 	}
886*26312Skarels 	return (0);
88721955Sbloom }
88821955Sbloom 
88921955Sbloom 
890*26312Skarels /*
891*26312Skarels  * dmflout -- start io operation to dmf line printer
89221955Sbloom  *		cp is addr of buf of n chars to be sent.
89321955Sbloom  *
89421955Sbloom  *	-- dmf will be put in formatted output mode, this will
89521955Sbloom  *		be selectable from an ioctl if the
89621955Sbloom  *		need ever arises.
89721955Sbloom  */
898*26312Skarels dmflout(dev, cp, n)
899*26312Skarels 	dev_t dev;
900*26312Skarels 	char *cp;
901*26312Skarels 	int n;
90221955Sbloom {
90321955Sbloom 	register struct dmfl_softc *sc;
90421955Sbloom 	register int dmf;
90521955Sbloom 	register struct uba_device *ui;
90621955Sbloom 	register struct dmfdevice *d;
90721955Sbloom 	register unsigned info;
90821955Sbloom 	register unsigned i;
90921955Sbloom 
910*26312Skarels 	dmf = DMFL_UNIT(dev);
911*26312Skarels 	sc = &dmfl_softc[dmf];
912*26312Skarels 	if (sc->dmfl_state & ERROR)
913*26312Skarels 		return (EIO);
914*26312Skarels 	ui = dmfinfo[dmf];
915*26312Skarels 	/*
916*26312Skarels 	 * allocate unibus resources, will be released when io
917*26312Skarels 	 * operation is done.
91821955Sbloom 	 */
919*26312Skarels 	sc->dmfl_info = info = uballoc(ui->ui_ubanum,cp,n,0);
920*26312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
921*26312Skarels 	d->dmfl[0] = (2<<8) | DMFL_FORMAT;	/* indir reg 2 */
92221955Sbloom 	/* indir reg auto increments on r/w */
92321955Sbloom 	/* SO DON'T CHANGE THE ORDER OF THIS CODE */
924*26312Skarels 	d->dmfl[1] = 0;			/* prefix chars & num */
925*26312Skarels 	d->dmfl[1] = 0;			/* suffix chars & num */
926*26312Skarels 	d->dmfl[1] = info; 		/* dma lo 16 bits addr */
92721955Sbloom 
92821955Sbloom 	/* NOT DOCUMENTED !! */
92921955Sbloom 	d->dmfl[1] = -n;		/* number of chars */
93021955Sbloom 	/* ----------^-------- */
93121955Sbloom 
93221955Sbloom 	d->dmfl[1] = ((info>>16)&3) /* dma hi 2 bits addr */
93321955Sbloom 		| (1<<8) /* auto cr insert */
93421955Sbloom 		| (1<<9) /* use real ff */
93521955Sbloom 		| (1<<15); /* no u/l conversion */
93621955Sbloom 	d->dmfl[1] = sc->dmfl_lines 	/* lines per page */
93721955Sbloom 		| (sc->dmfl_cols<<8);	/* carriage width */
93821955Sbloom 	sc->dmfl_state |= ASLP;
939*26312Skarels 	i = spltty();
94021955Sbloom 	d->dmfl[0] |= DMFL_PEN|DMFL_IE;
941*26312Skarels 	while (sc->dmfl_state & ASLP) {
942*26312Skarels 		sleep(&sc->dmfl_buf[0], (PZERO+8));
943*26312Skarels 		while (sc->dmfl_state & ERROR) {
944*26312Skarels 			timeout(dmflint, dmf, 10*hz);
945*26312Skarels 			sleep(&sc->dmfl_state, (PZERO+8));
94621955Sbloom 		}
947*26312Skarels 		/*if (sc->dmfl_state&ERROR) return (EIO);*/
94821955Sbloom 	}
94921955Sbloom 	splx(i);
950*26312Skarels 	return (0);
95121955Sbloom }
952*26312Skarels 
953*26312Skarels /*
954*26312Skarels  * dmflint -- handle an interrupt from the line printer part of the dmf32
95521955Sbloom  */
95621955Sbloom dmflint(dmf)
957*26312Skarels 	int dmf;
95821955Sbloom {
95921955Sbloom 	register struct uba_device *ui;
96021955Sbloom 	register struct dmfl_softc *sc;
96121955Sbloom 	register struct dmfdevice *d;
96221955Sbloom 
963*26312Skarels 	ui = dmfinfo[dmf];
964*26312Skarels 	sc = &dmfl_softc[dmf];
965*26312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
96621955Sbloom 
96721955Sbloom 	d->dmfl[0] &= ~DMFL_IE;
96821955Sbloom 
969*26312Skarels 	if (sc->dmfl_state & ERROR) {
97021955Sbloom 		printf("dmfl: intr while in error state \n");
971*26312Skarels 		if ((d->dmfl[0]&DMFL_OFFLINE) == 0)
97221955Sbloom 			sc->dmfl_state &= ~ERROR;
97321955Sbloom 		wakeup(&sc->dmfl_state);
97421955Sbloom 		return;
97521955Sbloom 	}
976*26312Skarels 	if (d->dmfl[0] & DMFL_DMAERR)
97721955Sbloom 		printf("dmf:NXM\n");
978*26312Skarels 	if (d->dmfl[0] & DMFL_OFFLINE) {
97921955Sbloom 		printf("dmf:printer error\n");
98021955Sbloom 		sc->dmfl_state |= ERROR;
98121955Sbloom 	}
982*26312Skarels 	if (d->dmfl[0] & DMFL_PDONE) {
98321955Sbloom #ifdef notdef
984*26312Skarels 		printf("bytes= %d\n", d->dmfl[1]);
985*26312Skarels 		printf("lines= %d\n", d->dmfl[1]);
98621955Sbloom #endif
98721955Sbloom 	}
98821955Sbloom 	sc->dmfl_state &= ~ASLP;
98921955Sbloom 	wakeup(&sc->dmfl_buf[0]);
990*26312Skarels 	if (sc->dmfl_info != 0)
991*26312Skarels 		ubarelse(ui->ui_ubanum, &sc->dmfl_info);
99221955Sbloom 	sc->dmfl_info = 0;
99321955Sbloom }
99421955Sbloom 
9956940Ssam /* stubs for interrupt routines for devices not yet supported */
9966940Ssam 
997*26312Skarels dmfsrint()
998*26312Skarels {
999*26312Skarels 	printf("dmfsrint\n");
1000*26312Skarels }
10016940Ssam 
1002*26312Skarels dmfsxint()
1003*26312Skarels {
1004*26312Skarels 	printf("dmfsxint\n");
1005*26312Skarels }
10066940Ssam 
1007*26312Skarels dmfdaint()
1008*26312Skarels {
1009*26312Skarels 	printf("dmfdaint\n");
1010*26312Skarels }
10116940Ssam 
1012*26312Skarels dmfdbint()
1013*26312Skarels {
1014*26312Skarels 	printf("dmfdbint\n");
1015*26312Skarels }
10166940Ssam #endif
1017