xref: /csrg-svn/sys/vax/uba/dmf.c (revision 30322)
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*30322Skarels  *	@(#)dmf.c	7.3 (Berkeley) 12/19/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.
3326910Skarels  * 24		if 1 DO NOT use the auto format mode of the
3426910Skarels  *			line printer parallel port
356940Ssam  */
369772Ssam #include "../machine/pte.h"
379772Ssam 
386940Ssam #include "bk.h"
3916063Skarels #include "uba.h"
4017124Sbloom #include "param.h"
4117124Sbloom #include "conf.h"
4217124Sbloom #include "dir.h"
4317124Sbloom #include "user.h"
4426836Skarels #include "proc.h"
4517124Sbloom #include "ioctl.h"
4617124Sbloom #include "tty.h"
4717124Sbloom #include "map.h"
4817124Sbloom #include "buf.h"
4917124Sbloom #include "vm.h"
5017124Sbloom #include "bkmac.h"
5117124Sbloom #include "clist.h"
5217124Sbloom #include "file.h"
5317124Sbloom #include "uio.h"
5421955Sbloom #include "kernel.h"
5518312Sralph #include "syslog.h"
566940Ssam 
5717124Sbloom #include "ubareg.h"
5817124Sbloom #include "ubavar.h"
5917124Sbloom #include "dmfreg.h"
608473Sroot 
616940Ssam /*
626940Ssam  * Definition of the driver for the auto-configuration program.
636940Ssam  */
646940Ssam int	dmfprobe(), dmfattach(), dmfrint(), dmfxint();
6521955Sbloom int	dmflint();
666940Ssam struct	uba_device *dmfinfo[NDMF];
676940Ssam u_short	dmfstd[] = { 0 };
686940Ssam struct	uba_driver dmfdriver =
696940Ssam 	{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
706940Ssam 
7125449Skarels int	dmf_timeout = 10;		/* silo timeout, in ms */
7221955Sbloom int	dmf_mindma = 4;			/* don't dma below this point */
7321955Sbloom 
746940Ssam /*
756940Ssam  * Local variables for the driver
766940Ssam  */
776940Ssam char	dmf_speeds[] =
786940Ssam 	{ 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
796940Ssam 
8025449Skarels #ifndef	PORTSELECTOR
8125449Skarels #define	ISPEED	B9600
8225449Skarels #define	IFLAGS	(EVENP|ODDP|ECHO)
8325449Skarels #else
8425449Skarels #define	ISPEED	B4800
8525449Skarels #define	IFLAGS	(EVENP|ODDP)
8625449Skarels #endif
8725449Skarels 
886940Ssam struct	tty dmf_tty[NDMF*8];
896940Ssam char	dmfsoftCAR[NDMF];
9021955Sbloom 
9126366Skarels struct dmfl_softc {
9226366Skarels 	u_int	dmfl_state; 		/* soft state bits */
9326366Skarels 	int	dmfl_info;		/* uba info */
9426366Skarels 	u_short	dmfl_lines;		/* lines per page (66 def.) */
9526366Skarels 	u_short	dmfl_cols; 		/* cols per line (132 def.) */
9626910Skarels 	u_short	dmfl_format;		/* fflag for auto form feed */
9726366Skarels 	char	dmfl_buf[DMFL_BUFSIZ];
9821955Sbloom } dmfl_softc[NDMF];
9921955Sbloom 
10021955Sbloom /*
10121955Sbloom  * convert device number into DMF line printer unit number
10221955Sbloom  */
10321955Sbloom #define	DMFL_UNIT(d)	(minor(d)&0xF)	/* up to 16 DMFs */
10421955Sbloom 
10521955Sbloom #define ASLP 1		/* waiting for interrupt from dmf */
10621955Sbloom #define OPEN 2		/* line printer is open */
10721955Sbloom #define ERROR 4		/* error while printing, driver
10821955Sbloom 			 refuses to do anything till closed */
10926910Skarels #define MOREIO 8	/* more data for printer */
11021955Sbloom 
1118778Sroot #ifndef lint
1128778Sroot int	ndmf = NDMF*8;			/* used by iostat */
1138778Sroot #endif
1146940Ssam int	dmfact;				/* mask of active dmf's */
1156940Ssam int	dmfstart(), ttrstrt();
1166940Ssam 
1176940Ssam /*
118*30322Skarels  * The clist space is mapped by one terminal driver onto each UNIBUS.
119*30322Skarels  * The identity of the board which allocated resources is recorded,
120*30322Skarels  * so the process may be repeated after UNIBUS resets.
1216940Ssam  * The UBACVT macro converts a clist space address for unibus uban
1226940Ssam  * into an i/o space address for the DMA routine.
1236940Ssam  */
124*30322Skarels int	dmf_uballoc[NUBA];	/* which dmf (if any) allocated unibus map */
125*30322Skarels int	cbase[NUBA];		/* base address of clists in unibus map */
1266940Ssam #define	UBACVT(x, uban)		(cbase[uban] + ((x)-(char *)cfree))
12721955Sbloom char	dmf_dma[NDMF*8];
1286940Ssam 
1296940Ssam /*
1306940Ssam  * Routine for configuration to set dmf interrupt.
1316940Ssam  */
1326940Ssam /*ARGSUSED*/
1336940Ssam dmfprobe(reg, ctlr)
1346940Ssam 	caddr_t reg;
13521955Sbloom 	struct uba_device *ctlr;
1366940Ssam {
1376940Ssam 	register int br, cvec;		/* these are ``value-result'' */
1386940Ssam 	register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
13921955Sbloom 	register int i;
14021955Sbloom 	register unsigned int a;
14121955Sbloom 	static char *dmfdevs[]=
14221955Sbloom 		{"parallel","printer","synch","asynch"};
14321955Sbloom 	unsigned int dmfoptions;
14425449Skarels 	static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
1456940Ssam 
1466940Ssam #ifdef lint
1476940Ssam 	br = 0; cvec = br; br = cvec;
1488808Sroot 	dmfxint(0); dmfrint(0);
14926366Skarels 	dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
1506940Ssam #endif
15121955Sbloom 	/*
15221955Sbloom 	 * Pick the usual size DMF vector here (don't decrement it here).
15321955Sbloom 	 * grab configuration; note that the DMF32
15421955Sbloom 	 * doesn't seem to put the right bits in this
15521955Sbloom 	 * register until AFTER the interrupt vector is set.
15621955Sbloom 	 */
1576940Ssam 	br = 0x15;
15821955Sbloom 	cvec = (uba_hd[numuba].uh_lastiv - 4*8);
15925449Skarels 	dmfaddr->dmfccsr0 = (cvec >> 2);
16021955Sbloom 	dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
16121955Sbloom 
16221955Sbloom 	/* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
16321955Sbloom 	if (dmfoptions == DMFC_ASYNC) {
16425449Skarels 		/* Async portion only */
16525449Skarels 
16625449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
16725449Skarels 		dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
16825449Skarels 		intrv[0] = ctlr->ui_intr[4];
16925449Skarels 		intrv[1] = ctlr->ui_intr[5];
17025449Skarels 		ctlr->ui_intr = intrv;
17126312Skarels 	} else if (dmfoptions == DMFC_LP) {
17225449Skarels 		/* LP portion only */
17321955Sbloom 
17425449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 8);
17525449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[6];
17626312Skarels 	} else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
17725449Skarels 		/* LP ans Async portions only */
17825449Skarels 
17925449Skarels 		cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
18025449Skarels 		ctlr->ui_intr = &ctlr->ui_intr[4];
18126312Skarels 	} else {
18225449Skarels 		/* All other configurations get everything */
18321955Sbloom 
18421955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
18521955Sbloom 	}
18625449Skarels 	a = (dmfoptions >> 12) & 0xf;
18725449Skarels 	printf("dmf%d:", ctlr->ui_unit);
18826312Skarels 	for (i = 0; a != 0; ++i, a >>= 1) {
18926312Skarels 		if (a & 1)
19025449Skarels 			printf(" %s",dmfdevs[i]);
19125449Skarels 	}
19225449Skarels 	printf(".\n");
19321955Sbloom 
19421955Sbloom 	if (dmfoptions & DMFC_LP)
19527057Skarels 		dmfaddr->dmfl_ctrl = DMFL_RESET;
1967412Skre 	return (sizeof (struct dmfdevice));
1976940Ssam }
1986940Ssam 
1996940Ssam /*
2006940Ssam  * Routine called to attach a dmf.
2016940Ssam  */
2026940Ssam dmfattach(ui)
2036940Ssam 	struct uba_device *ui;
2046940Ssam {
20521955Sbloom 	register int cols = (ui->ui_flags>>8) & 0xff;
20621955Sbloom 	register int lines = (ui->ui_flags>>16) & 0xff;
2076940Ssam 
20821955Sbloom 	dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff;
20927052Skarels 	dmfl_softc[ui->ui_unit].dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
21027052Skarels 	dmfl_softc[ui->ui_unit].dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
21126910Skarels  	if ((ui->ui_flags >> 24) & 0x1)
21226910Skarels  		dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8);
21326910Skarels  	else
21426910Skarels  		dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8) | DMFL_FORMAT;
21526221Skarels 	cbase[ui->ui_ubanum] = -1;
216*30322Skarels 	dmf_uballoc[ui->ui_unit] = -1;
2176940Ssam }
2186940Ssam 
2196940Ssam 
2206940Ssam /*
2216940Ssam  * Open a DMF32 line, mapping the clist onto the uba if this
2226940Ssam  * is the first dmf on this uba.  Turn on this dmf if this is
2236940Ssam  * the first use of it.
2246940Ssam  */
2256940Ssam /*ARGSUSED*/
2266940Ssam dmfopen(dev, flag)
2276940Ssam 	dev_t dev;
2286940Ssam {
2296940Ssam 	register struct tty *tp;
2306940Ssam 	register int unit, dmf;
2316940Ssam 	register struct dmfdevice *addr;
2326940Ssam 	register struct uba_device *ui;
2336940Ssam 	int s;
2346940Ssam 
2356940Ssam 	unit = minor(dev);
23626312Skarels 	if (unit & 0200)
23726312Skarels 		return (dmflopen(dev,flag));
2386940Ssam 	dmf = unit >> 3;
2398567Sroot 	if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
2408567Sroot 		return (ENXIO);
2416940Ssam 	tp = &dmf_tty[unit];
2428567Sroot 	if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
2438567Sroot 		return (EBUSY);
2446940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
2456940Ssam 	tp->t_addr = (caddr_t)addr;
2466940Ssam 	tp->t_oproc = dmfstart;
2476971Ssam 	tp->t_state |= TS_WOPEN;
2486940Ssam 	/*
2496940Ssam 	 * While setting up state for this uba and this dmf,
2506940Ssam 	 * block uba resets which can clear the state.
2516940Ssam 	 */
25221955Sbloom 	s = spltty();
25326221Skarels 	if (cbase[ui->ui_ubanum] == -1) {
254*30322Skarels 		dmf_uballoc[ui->ui_ubanum] = dmf;
255*30322Skarels 		cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum,
256*30322Skarels 		    (caddr_t)cfree, nclist*sizeof(struct cblock), 0));
2576940Ssam 	}
2586940Ssam 	if ((dmfact&(1<<dmf)) == 0) {
2596940Ssam 		addr->dmfcsr |= DMF_IE;
2606940Ssam 		dmfact |= (1<<dmf);
26121955Sbloom 		addr->dmfrsp = dmf_timeout;
2626940Ssam 	}
2636940Ssam 	splx(s);
2646940Ssam 	/*
26526910Skarels 	 * If this is first open, initialize tty state to default.
2666940Ssam 	 */
2676971Ssam 	if ((tp->t_state&TS_ISOPEN) == 0) {
2686940Ssam 		ttychars(tp);
26927052Skarels #ifndef PORTSELECTOR
27026910Skarels 		if (tp->t_ispeed == 0) {
27127052Skarels #else
27227052Skarels 			tp->t_state |= TS_HUPCLS;
27327052Skarels #endif PORTSELECTOR
27426910Skarels 			tp->t_ispeed = ISPEED;
27526910Skarels 			tp->t_ospeed = ISPEED;
27626910Skarels 			tp->t_flags = IFLAGS;
27727052Skarels #ifndef PORTSELECTOR
27826910Skarels 		}
27927052Skarels #endif PORTSELECTOR
2806940Ssam 		dmfparam(unit);
2816940Ssam 	}
2826940Ssam 	/*
2836940Ssam 	 * Wait for carrier, then process line discipline specific open.
2846940Ssam 	 */
28521955Sbloom 	s = spltty();
28626910Skarels 	for (;;) {
28726910Skarels 		if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
28826910Skarels 		    (dmfsoftCAR[dmf] & (1<<(unit&07))))
28926910Skarels 			tp->t_state |= TS_CARR_ON;
29026910Skarels 		if (tp->t_state & TS_CARR_ON)
29126910Skarels 			break;
2926971Ssam 		tp->t_state |= TS_WOPEN;
2936940Ssam 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
2946940Ssam 	}
2956940Ssam 	splx(s);
2968567Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
2976940Ssam }
2986940Ssam 
2996940Ssam /*
3006940Ssam  * Close a DMF32 line.
3016940Ssam  */
3026940Ssam /*ARGSUSED*/
3036940Ssam dmfclose(dev, flag)
3046940Ssam 	dev_t dev;
3056940Ssam 	int flag;
3066940Ssam {
3076940Ssam 	register struct tty *tp;
3086940Ssam 	register unit;
3096940Ssam 
3106940Ssam 	unit = minor(dev);
31126312Skarels 	if (unit & 0200) {
31226312Skarels 		dmflclose(dev,flag);
31326312Skarels 		return;
31426312Skarels 	}
31521955Sbloom 
3166940Ssam 	tp = &dmf_tty[unit];
3176940Ssam 	(*linesw[tp->t_line].l_close)(tp);
3188702Sroot 	(void) dmfmctl(unit, DMF_BRK, DMBIC);
3196971Ssam 	if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
3208702Sroot 		(void) dmfmctl(unit, DMF_OFF, DMSET);
3216940Ssam 	ttyclose(tp);
3226940Ssam }
3236940Ssam 
3247726Sroot dmfread(dev, uio)
3256940Ssam 	dev_t dev;
3267726Sroot 	struct uio *uio;
3276940Ssam {
3286940Ssam 	register struct tty *tp;
3296940Ssam 
33026312Skarels 	if (minor(dev) & 0200)
33121955Sbloom 		return(ENXIO);
3326940Ssam 	tp = &dmf_tty[minor(dev)];
3337726Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
3346940Ssam }
3356940Ssam 
3367832Sroot dmfwrite(dev, uio)
3376940Ssam 	dev_t dev;
3387832Sroot 	struct uio *uio;
3396940Ssam {
3406940Ssam 	register struct tty *tp;
3416940Ssam 
34226312Skarels 	if (minor(dev) & 0200)
34326312Skarels 		return (dmflwrite(dev,uio));
3446940Ssam 	tp = &dmf_tty[minor(dev)];
3458530Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
3466940Ssam }
3476940Ssam 
3486940Ssam /*
3496940Ssam  * DMF32 receiver interrupt.
3506940Ssam  */
3516940Ssam dmfrint(dmf)
3526940Ssam 	int dmf;
3536940Ssam {
3546940Ssam 	register c;
35526312Skarels 	register struct tty *tp;
3566940Ssam 	register struct dmfdevice *addr;
3576940Ssam 	register struct tty *tp0;
35821955Sbloom 	int unit;
35925449Skarels 	int overrun = 0;
36026312Skarels 	register struct uba_device *ui;
3616940Ssam 
36226312Skarels 	ui = dmfinfo[dmf];
36326312Skarels 	if (ui == 0 || ui->ui_alive == 0)
36426312Skarels 		return;
36526312Skarels 	addr = (struct dmfdevice *)ui->ui_addr;
36621955Sbloom 	tp0 = &dmf_tty[dmf * 8];
3676940Ssam 	/*
3686940Ssam 	 * Loop fetching characters from the silo for this
3696940Ssam 	 * dmf until there are no more in the silo.
3706940Ssam 	 */
3716940Ssam 	while ((c = addr->dmfrbuf) < 0) {
37221955Sbloom 
37321955Sbloom 		unit = (c >> 8) & 07;
37421955Sbloom 		tp = tp0 + unit;
3756940Ssam 		if (c & DMF_DSC) {
37621955Sbloom 			addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
37725449Skarels 			if (addr->dmfrms & DMF_CAR)
37825449Skarels 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
37926312Skarels 			else if ((dmfsoftCAR[dmf] & (1 << unit)) == 0 &&
38025449Skarels 			    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
38125449Skarels 				addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
38225449Skarels 				addr->dmflctms = DMFLCR_ENA;
3836940Ssam 			}
3846940Ssam 			continue;
3856940Ssam 		}
38626312Skarels 		if ((tp->t_state&TS_ISOPEN) == 0) {
38725449Skarels 			wakeup((caddr_t)&tp->t_rawq);
38825449Skarels #ifdef PORTSELECTOR
38926312Skarels 			if ((tp->t_state & TS_WOPEN) == 0)
39025449Skarels #endif
39125449Skarels 				continue;
3926940Ssam 		}
39321956Sbloom 		if (c & (DMF_PE|DMF_DO|DMF_FE)) {
39421955Sbloom 			if (c & DMF_PE)
39526312Skarels 				if ((tp->t_flags & (EVENP|ODDP)) == EVENP
39626312Skarels 			 	|| (tp->t_flags & (EVENP|ODDP)) == ODDP)
39721955Sbloom 					continue;
39821955Sbloom 			if ((c & DMF_DO) && overrun == 0) {
39924842Seric 				log(LOG_WARNING, "dmf%d: silo overflow\n", dmf);
40021955Sbloom 				overrun = 1;
40121955Sbloom 			}
40221955Sbloom 			if (c & DMF_FE)
40321955Sbloom 				/*
40421955Sbloom 			 	* At framing error (break) generate
40521955Sbloom 			 	* a null (in raw mode, for getty), or a
40621955Sbloom 			 	* interrupt (in cooked/cbreak mode).
40721955Sbloom 			 	*/
40826312Skarels 				if (tp->t_flags & RAW)
40921955Sbloom 					c = 0;
41021955Sbloom 				else
41121955Sbloom 					c = tp->t_intrc;
4126940Ssam 		}
4136940Ssam #if NBK > 0
4146940Ssam 		if (tp->t_line == NETLDISC) {
4156940Ssam 			c &= 0177;
4166940Ssam 			BKINPUT(c, tp);
4176940Ssam 		} else
4186940Ssam #endif
4196940Ssam 			(*linesw[tp->t_line].l_rint)(c, tp);
4206940Ssam 	}
4216940Ssam }
4226940Ssam 
4236940Ssam /*
4246940Ssam  * Ioctl for DMF32.
4256940Ssam  */
4266940Ssam /*ARGSUSED*/
4277630Ssam dmfioctl(dev, cmd, data, flag)
4286940Ssam 	dev_t dev;
4297630Ssam 	caddr_t data;
4306940Ssam {
4316940Ssam 	register struct tty *tp;
4326940Ssam 	register int unit = minor(dev);
4338567Sroot 	int error;
4346940Ssam 
43526312Skarels 	if (unit & 0200)
43621955Sbloom 		return (ENOTTY);
4376940Ssam 	tp = &dmf_tty[unit];
4388567Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
4398567Sroot 	if (error >= 0)
4408567Sroot 		return (error);
4418567Sroot 	error = ttioctl(tp, cmd, data, flag);
4428567Sroot 	if (error >= 0) {
44317562Sbloom 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
44417562Sbloom 		    cmd == TIOCLBIC || cmd == TIOCLSET)
4456940Ssam 			dmfparam(unit);
4468567Sroot 		return (error);
4478567Sroot 	}
4488567Sroot 	switch (cmd) {
4496940Ssam 
4506940Ssam 	case TIOCSBRK:
4518702Sroot 		(void) dmfmctl(dev, DMF_BRK, DMBIS);
4526940Ssam 		break;
4537630Ssam 
4546940Ssam 	case TIOCCBRK:
4558702Sroot 		(void) dmfmctl(dev, DMF_BRK, DMBIC);
4566940Ssam 		break;
4577630Ssam 
4586940Ssam 	case TIOCSDTR:
4598702Sroot 		(void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
4606940Ssam 		break;
4617630Ssam 
4626940Ssam 	case TIOCCDTR:
4638702Sroot 		(void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
4646940Ssam 		break;
4657630Ssam 
4666940Ssam 	case TIOCMSET:
4678702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
4686940Ssam 		break;
4697630Ssam 
4706940Ssam 	case TIOCMBIS:
4718702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
4726940Ssam 		break;
4737630Ssam 
4746940Ssam 	case TIOCMBIC:
4758702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
4766940Ssam 		break;
4777630Ssam 
4786940Ssam 	case TIOCMGET:
4797630Ssam 		*(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
4806940Ssam 		break;
4817630Ssam 
4826940Ssam 	default:
4838567Sroot 		return (ENOTTY);
4846940Ssam 	}
4858567Sroot 	return (0);
4866940Ssam }
4876940Ssam 
4886940Ssam dmtodmf(bits)
4896940Ssam 	register int bits;
4906940Ssam {
4916940Ssam 	register int b;
4926940Ssam 
4936940Ssam 	b = bits & 012;
4946940Ssam 	if (bits & DML_ST) b |= DMF_RATE;
4956940Ssam 	if (bits & DML_RTS) b |= DMF_RTS;
4966940Ssam 	if (bits & DML_USR) b |= DMF_USRW;
4976940Ssam 	return(b);
4986940Ssam }
4996940Ssam 
5006940Ssam dmftodm(bits)
5016940Ssam 	register int bits;
5026940Ssam {
5036940Ssam 	register int b;
5046940Ssam 
5056940Ssam 	b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
5066940Ssam 	if (bits & DMF_USRR) b |= DML_USR;
5076940Ssam 	if (bits & DMF_RTS) b |= DML_RTS;
5086940Ssam 	return(b);
5096940Ssam }
5106940Ssam 
5116940Ssam 
5126940Ssam /*
5136940Ssam  * Set parameters from open or stty into the DMF hardware
5146940Ssam  * registers.
5156940Ssam  */
5166940Ssam dmfparam(unit)
5176940Ssam 	register int unit;
5186940Ssam {
5196940Ssam 	register struct tty *tp;
5206940Ssam 	register struct dmfdevice *addr;
5216940Ssam 	register int lpar, lcr;
5226940Ssam 	int s;
5236940Ssam 
5246940Ssam 	tp = &dmf_tty[unit];
5256940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
5266940Ssam 	/*
5276940Ssam 	 * Block interrupts so parameters will be set
5286940Ssam 	 * before the line interrupts.
5296940Ssam 	 */
53021955Sbloom 	s = spltty();
5316940Ssam 	addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
5326940Ssam 	if ((tp->t_ispeed)==0) {
5336971Ssam 		tp->t_state |= TS_HUPCLS;
5348702Sroot 		(void) dmfmctl(unit, DMF_OFF, DMSET);
53525449Skarels 		splx(s);
5366940Ssam 		return;
5376940Ssam 	}
5386940Ssam 	lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
5396940Ssam 	lcr = DMFLCR_ENA;
5406940Ssam 	if ((tp->t_ispeed) == B134)
5416940Ssam 		lpar |= BITS6|PENABLE;
54224270Slepreau 	else if (tp->t_flags & (RAW|LITOUT|PASS8))
5436940Ssam 		lpar |= BITS8;
5446940Ssam 	else {
5456940Ssam 		lpar |= BITS7|PENABLE;
5466940Ssam 		/* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
5476940Ssam 	}
54812450Ssam 	if (tp->t_flags&EVENP)
54912450Ssam 		lpar |= EPAR;
5506940Ssam 	if ((tp->t_ospeed) == B110)
5516940Ssam 		lpar |= TWOSB;
5526940Ssam 	lpar |= (unit&07);
5536940Ssam 	addr->dmflpr = lpar;
55425654Skarels 	addr->dmflctms = (addr->dmflctms &~ 0xff) | lcr;
5556940Ssam 	splx(s);
5566940Ssam }
5576940Ssam 
5586940Ssam /*
5596940Ssam  * DMF32 transmitter interrupt.
5606940Ssam  * Restart the idle line.
5616940Ssam  */
5626940Ssam dmfxint(dmf)
5636940Ssam 	int dmf;
5646940Ssam {
56526312Skarels 	int unit0 = dmf * 8;
56626312Skarels 	struct tty *tp0 = &dmf_tty[unit0];
5676940Ssam 	register struct tty *tp;
5686940Ssam 	register struct dmfdevice *addr;
5696940Ssam 	register struct uba_device *ui;
57021955Sbloom 	register int t;
5716940Ssam 	short cntr;
5726940Ssam 
5736940Ssam 	ui = dmfinfo[dmf];
5746940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
5756940Ssam 	while ((t = addr->dmfcsr) & DMF_TI) {
57621955Sbloom 		if (t & DMF_NXM)
57721955Sbloom 			/* SHOULD RESTART OR SOMETHING... */
57821955Sbloom 			printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
57921955Sbloom 		t = t >> 8 & 7;
58021955Sbloom 		tp = tp0 + t;
5816971Ssam 		tp->t_state &= ~TS_BUSY;
5826971Ssam 		if (tp->t_state&TS_FLUSH)
5836971Ssam 			tp->t_state &= ~TS_FLUSH;
58429549Skarels 		else if (dmf_dma[unit0 + t])
58529549Skarels 			ndflush(&tp->t_outq, (int)dmf_dma[unit0 + t]);
58629549Skarels 		dmf_dma[unit0 + t] = 0;
5876940Ssam 		if (tp->t_line)
5886940Ssam 			(*linesw[tp->t_line].l_start)(tp);
5896940Ssam 		else
5906940Ssam 			dmfstart(tp);
5916940Ssam 	}
5926940Ssam }
5936940Ssam 
5946940Ssam /*
5956940Ssam  * Start (restart) transmission on the given DMF32 line.
5966940Ssam  */
5976940Ssam dmfstart(tp)
5986940Ssam 	register struct tty *tp;
5996940Ssam {
6006940Ssam 	register struct dmfdevice *addr;
6018607Sroot 	register int unit, nch;
6026940Ssam 	int s;
60321955Sbloom 	register int dmf;
6046940Ssam 
6056940Ssam 	unit = minor(tp->t_dev);
60621955Sbloom 	dmf = unit >> 3;
6076940Ssam 	unit &= 07;
6086940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
6096940Ssam 
6106940Ssam 	/*
6116940Ssam 	 * Must hold interrupts in following code to prevent
6126940Ssam 	 * state of the tp from changing.
6136940Ssam 	 */
61421955Sbloom 	s = spltty();
6156940Ssam 	/*
6166940Ssam 	 * If it's currently active, or delaying, no need to do anything.
6176940Ssam 	 */
6186971Ssam 	if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
6196940Ssam 		goto out;
6206940Ssam 	/*
6216940Ssam 	 * If there are still characters in the silo,
6226940Ssam 	 * just reenable the transmitter.
6236940Ssam 	 */
6246940Ssam 	addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
6256940Ssam 	if (addr->dmftsc) {
6266940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
62725449Skarels 		addr->dmflctms = addr->dmflctms | DMF_TE;
6286971Ssam 		tp->t_state |= TS_BUSY;
6296940Ssam 		goto out;
6306940Ssam 	}
6316940Ssam 	/*
6326940Ssam 	 * If there are sleepers, and output has drained below low
6336940Ssam 	 * water mark, wake up the sleepers.
6346940Ssam 	 */
63521955Sbloom 	if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
63621955Sbloom 		if (tp->t_state&TS_ASLEEP) {
63721955Sbloom 			tp->t_state &= ~TS_ASLEEP;
63821955Sbloom 			wakeup((caddr_t)&tp->t_outq);
63921955Sbloom 		}
64021955Sbloom 		if (tp->t_wsel) {
64121955Sbloom 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
64221955Sbloom 			tp->t_wsel = 0;
64321955Sbloom 			tp->t_state &= ~TS_WCOLL;
64421955Sbloom 		}
6456940Ssam 	}
6466940Ssam 	/*
6476940Ssam 	 * Now restart transmission unless the output queue is
6486940Ssam 	 * empty.
6496940Ssam 	 */
6506940Ssam 	if (tp->t_outq.c_cc == 0)
6516940Ssam 		goto out;
6529550Ssam 	if (tp->t_flags & (RAW|LITOUT))
6536940Ssam 		nch = ndqb(&tp->t_outq, 0);
6546940Ssam 	else {
65521955Sbloom 		if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
65621955Sbloom 			/*
65721955Sbloom 		 	* If first thing on queue is a delay process it.
65821955Sbloom 		 	*/
6596940Ssam 			nch = getc(&tp->t_outq);
6606940Ssam 			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
6616971Ssam 			tp->t_state |= TS_TIMEOUT;
6626940Ssam 			goto out;
6636940Ssam 		}
6646940Ssam 	}
6656940Ssam 	/*
6666940Ssam 	 * If characters to transmit, restart transmission.
6676940Ssam 	 */
66821955Sbloom 	if (nch >= dmf_mindma) {
66921955Sbloom 		register car;
67021955Sbloom 
67129549Skarels 		dmf_dma[minor(tp->t_dev)] = nch;
6726940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
67325449Skarels 		addr->dmflctms = addr->dmflctms | DMF_TE;
6746940Ssam 		car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
6756940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
6766940Ssam 		addr->dmftba = car;
67721955Sbloom 		addr->dmftcc = ((car >> 2) & 0xc000) | nch;
67821955Sbloom 		tp->t_state |= TS_BUSY;
67921955Sbloom 	} else if (nch) {
6806940Ssam 		register char *cp = tp->t_outq.c_cf;
6816940Ssam 		register int i;
6826940Ssam 
68321955Sbloom 		dmf_dma[minor(tp->t_dev)] = 0;
6846940Ssam 		nch = MIN(nch, DMF_SILOCNT);
6856940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
68625449Skarels 		addr->dmflctms = addr->dmflctms | DMF_TE;
6876940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
6886940Ssam 		for (i = 0; i < nch; i++)
6896940Ssam 			addr->dmftbuf = *cp++;
6906940Ssam 		ndflush(&tp->t_outq, nch);
6916971Ssam 		tp->t_state |= TS_BUSY;
6926940Ssam 	}
6936940Ssam out:
6946940Ssam 	splx(s);
6956940Ssam }
6966940Ssam 
6976940Ssam /*
6986940Ssam  * Stop output on a line, e.g. for ^S/^Q or output flush.
6996940Ssam  */
7006940Ssam /*ARGSUSED*/
7016940Ssam dmfstop(tp, flag)
7026940Ssam 	register struct tty *tp;
7036940Ssam {
7046940Ssam 	register struct dmfdevice *addr;
70521955Sbloom 	register unit = minor(tp->t_dev) & 7;
70621955Sbloom 	int s;
7076940Ssam 
7086940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
7096940Ssam 	/*
7106940Ssam 	 * Block input/output interrupts while messing with state.
7116940Ssam 	 */
71221955Sbloom 	s = spltty();
71321955Sbloom 	if (flag) {
71421955Sbloom 		addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
71521955Sbloom 		if (addr->dmftsc) {
71621955Sbloom 			/*
71721955Sbloom 			 * Flush regardless of whether we're transmitting
71821955Sbloom 			 * (TS_BUSY), if the silo contains untransmitted
71921955Sbloom 			 * characters.
72021955Sbloom 			 */
72121955Sbloom 			addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
72225449Skarels 			addr->dmflctms = addr->dmflctms | DMF_TE | DMF_FLUSH;
72321955Sbloom 			/* this will interrupt so let dmfxint handle the rest */
72421955Sbloom 			tp->t_state |= TS_FLUSH|TS_BUSY;
72521955Sbloom 		}
72621955Sbloom 	} else {
72721955Sbloom 		if (tp->t_state & TS_BUSY) {
72821955Sbloom 			/*
72921955Sbloom 			 * Stop transmission by disabling
73021955Sbloom 			 * the transmitter.  We'll pick up where we
73121955Sbloom 			 * left off by reenabling in dmfstart.
73221955Sbloom 			 */
73321955Sbloom 			addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
73425449Skarels 			addr->dmflctms = addr->dmflctms &~ DMF_TE;
73521955Sbloom 			/* no interrupt here */
7366971Ssam 			tp->t_state &= ~TS_BUSY;
73721955Sbloom 		}
7386940Ssam 	}
7396940Ssam 	splx(s);
7406940Ssam }
7416940Ssam 
7426940Ssam /*
7436940Ssam  * DMF32 modem control
7446940Ssam  */
7456940Ssam dmfmctl(dev, bits, how)
7466940Ssam 	dev_t dev;
7476940Ssam 	int bits, how;
7486940Ssam {
7496940Ssam 	register struct dmfdevice *dmfaddr;
7506940Ssam 	register int unit, mbits, lcr;
7516940Ssam 	int s;
7526940Ssam 
7536940Ssam 	unit = minor(dev);
7546940Ssam 	dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
7556940Ssam 	unit &= 07;
75621955Sbloom 	s = spltty();
7576940Ssam 	dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
7586940Ssam 	mbits = dmfaddr->dmfrms << 8;
7596940Ssam 	dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
76025654Skarels 	lcr = dmfaddr->dmflctms;
76125449Skarels 	mbits |= (lcr & 0xff00) >> 8;
7626940Ssam 	switch (how) {
7636940Ssam 	case DMSET:
76412449Ssam 		mbits = (mbits &0xff00) | bits;
7656940Ssam 		break;
7666940Ssam 
7676940Ssam 	case DMBIS:
7686940Ssam 		mbits |= bits;
7696940Ssam 		break;
7706940Ssam 
7716940Ssam 	case DMBIC:
7726940Ssam 		mbits &= ~bits;
7736940Ssam 		break;
7746940Ssam 
7756940Ssam 	case DMGET:
7766940Ssam 		(void) splx(s);
7776940Ssam 		return(mbits);
7786940Ssam 	}
7796940Ssam 	if (mbits & DMF_BRK)
7806940Ssam 		lcr |= DMF_RBRK;
7816940Ssam 	else
7826940Ssam 		lcr &= ~DMF_RBRK;
78325449Skarels 	dmfaddr->dmflctms = ((mbits & 037) << 8) | (lcr & 0xff);
7846940Ssam 	(void) splx(s);
7856940Ssam 	return(mbits);
7866940Ssam }
7876940Ssam 
7886940Ssam /*
7896940Ssam  * Reset state of driver if UBA reset was necessary.
7906940Ssam  * Reset the csr, lpr, and lcr registers on open lines, and
7916940Ssam  * restart transmitters.
7926940Ssam  */
7936940Ssam dmfreset(uban)
7946940Ssam 	int uban;
7956940Ssam {
7966940Ssam 	register int dmf, unit;
7976940Ssam 	register struct tty *tp;
7986940Ssam 	register struct uba_device *ui;
7996940Ssam 	register struct dmfdevice *addr;
8006940Ssam 	int i;
8016940Ssam 
8026940Ssam 	for (dmf = 0; dmf < NDMF; dmf++) {
8036940Ssam 		ui = dmfinfo[dmf];
8046940Ssam 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
8056940Ssam 			continue;
8066940Ssam 		printf(" dmf%d", dmf);
807*30322Skarels 		if (dmf_uballoc[uban] == dmf) {
808*30322Skarels 			int info;
809*30322Skarels 
810*30322Skarels 			info = uballoc(uban, (caddr_t)cfree,
811*30322Skarels 			    nclist * sizeof(struct cblock), UBA_CANTWAIT);
812*30322Skarels 			if (info)
813*30322Skarels 				cbase[uban] = UBAI_ADDR(info);
814*30322Skarels 			else {
815*30322Skarels 				printf(" [can't get uba map]");
816*30322Skarels 				cbase[uban] = -1;
817*30322Skarels 			}
81825449Skarels 		}
8196940Ssam 		addr = (struct dmfdevice *)ui->ui_addr;
8206940Ssam 		addr->dmfcsr = DMF_IE;
82121955Sbloom 		addr->dmfrsp = dmf_timeout;
8226940Ssam 		unit = dmf * 8;
8236940Ssam 		for (i = 0; i < 8; i++) {
8246940Ssam 			tp = &dmf_tty[unit];
8256971Ssam 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
8266940Ssam 				dmfparam(unit);
8278702Sroot 				(void) dmfmctl(unit, DMF_ON, DMSET);
8286971Ssam 				tp->t_state &= ~TS_BUSY;
8296940Ssam 				dmfstart(tp);
8306940Ssam 			}
8316940Ssam 			unit++;
8326940Ssam 		}
8336940Ssam 	}
8346940Ssam }
8356940Ssam 
83626312Skarels /*
83726312Skarels  * dmflopen -- open the line printer port on a dmf32
83821955Sbloom  */
83926312Skarels /* ARGSUSED */
84026312Skarels dmflopen(dev, flag)
84126312Skarels 	dev_t dev;
84226312Skarels 	int flag;
84321955Sbloom {
84421955Sbloom 	register int dmf;
84521955Sbloom 	register struct dmfl_softc *sc;
84621955Sbloom 	register struct uba_device *ui;
84721955Sbloom 	register struct dmfdevice *addr;
84821955Sbloom 
84926312Skarels 	dmf = DMFL_UNIT(dev);
85026910Skarels 	if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
85126910Skarels 		return (ENXIO);
85226910Skarels 	sc = &dmfl_softc[dmf];
85326910Skarels 	if (sc->dmfl_state & OPEN)
85426910Skarels 		return (EBUSY);
85521955Sbloom 	addr = (struct dmfdevice *)ui->ui_addr;
85626910Skarels 	if (addr->dmfl_ctrl & DMFL_OFFLINE) {
85726910Skarels #ifdef notdef
85826910Skarels 		log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
85926910Skarels 			dmf);
86026910Skarels #endif
86126312Skarels 		return (EIO);
86221955Sbloom 	}
86326910Skarels 	if ((addr->dmfl_ctrl & DMFL_CONV)) {
86426910Skarels 		log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
86526312Skarels 		return (EIO);
86621955Sbloom 	}
86721955Sbloom 
86826910Skarels 	addr->dmfl_ctrl = 0;
86921955Sbloom 	sc->dmfl_state |= OPEN;
87026312Skarels 	return (0);
87121955Sbloom }
87221955Sbloom 
87326312Skarels /* ARGSUSED */
87426312Skarels dmflclose(dev, flag)
87526312Skarels 	dev_t dev;
87626312Skarels 	int flag;
87721955Sbloom {
87826910Skarels 	register int dmf = DMFL_UNIT(dev);
87921955Sbloom 	register struct dmfl_softc *sc = &dmfl_softc[dmf];
88026910Skarels 	register struct uba_device *ui = dmfinfo[dmf];
88121955Sbloom 
88221955Sbloom 	sc->dmfl_state = 0;
88326312Skarels 	if (sc->dmfl_info != 0)
88426910Skarels 		ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
88521955Sbloom 
88626910Skarels 	((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
88721955Sbloom }
88821955Sbloom 
88926312Skarels dmflwrite(dev, uio)
89026312Skarels 	dev_t dev;
89126312Skarels 	struct uio *uio;
89221955Sbloom {
89326366Skarels 	register int n;
89421955Sbloom 	register int error;
89521955Sbloom 	register struct dmfl_softc *sc;
89621955Sbloom 
89721955Sbloom 	sc = &dmfl_softc[DMFL_UNIT(dev)];
89826910Skarels 	if (sc->dmfl_state & ERROR)
89926910Skarels 		return (EIO);
90026910Skarels 	while (n = (unsigned)uio->uio_resid) {
90126910Skarels 		if (n > DMFL_BUFSIZ) {
90226910Skarels 			n = DMFL_BUFSIZ;
90326910Skarels 			sc->dmfl_state |= MOREIO;
90426910Skarels 		} else
90526910Skarels 			sc->dmfl_state &= ~MOREIO;
90626910Skarels 		if (error = uiomove(sc->dmfl_buf, (int)n, UIO_WRITE, uio))
90726312Skarels 			return (error);
90826910Skarels 		if (error = dmflout(dev, sc->dmfl_buf, n))
90926312Skarels 			return (error);
91021955Sbloom 	}
91126312Skarels 	return (0);
91221955Sbloom }
91321955Sbloom 
91421955Sbloom 
91526312Skarels /*
91626312Skarels  * dmflout -- start io operation to dmf line printer
91721955Sbloom  *		cp is addr of buf of n chars to be sent.
91821955Sbloom  *
91921955Sbloom  *	-- dmf will be put in formatted output mode, this will
92021955Sbloom  *		be selectable from an ioctl if the
92121955Sbloom  *		need ever arises.
92221955Sbloom  */
92326312Skarels dmflout(dev, cp, n)
92426312Skarels 	dev_t dev;
92526312Skarels 	char *cp;
92626312Skarels 	int n;
92721955Sbloom {
92821955Sbloom 	register struct dmfl_softc *sc;
92921955Sbloom 	register int dmf;
93021955Sbloom 	register struct uba_device *ui;
93121955Sbloom 	register struct dmfdevice *d;
93226910Skarels 	int s;
93321955Sbloom 
93426312Skarels 	dmf = DMFL_UNIT(dev);
93526312Skarels 	sc = &dmfl_softc[dmf];
93626312Skarels 	if (sc->dmfl_state & ERROR)
93726312Skarels 		return (EIO);
93826312Skarels 	ui = dmfinfo[dmf];
93926312Skarels 	/*
94026312Skarels 	 * allocate unibus resources, will be released when io
94126312Skarels 	 * operation is done.
94221955Sbloom 	 */
94326910Skarels 	if (sc->dmfl_info == 0)
94426910Skarels 		sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
94526312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
94626910Skarels 	d->dmfl_ctrl = sc->dmfl_format;		/* indir reg 2 */
94721955Sbloom 	/* indir reg auto increments on r/w */
94821955Sbloom 	/* SO DON'T CHANGE THE ORDER OF THIS CODE */
94926910Skarels 	d->dmfl_indrct = 0;			/* prefix chars & num */
95026910Skarels 	d->dmfl_indrct = 0;			/* suffix chars & num */
95126910Skarels 	d->dmfl_indrct = sc->dmfl_info; 	/* dma lo 16 bits addr */
95226910Skarels 	d->dmfl_indrct = -n;			/* number of chars */
95321955Sbloom 
95426910Skarels 	d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
95526910Skarels 						/* dma hi 2 bits addr */
95626910Skarels 	d->dmfl_indrct = sc->dmfl_lines 	/* lines per page */
95726910Skarels 		| (sc->dmfl_cols<<8);		/* carriage width */
95821955Sbloom 	sc->dmfl_state |= ASLP;
95926910Skarels 	s = spltty();
96026910Skarels 	d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
96126312Skarels 	while (sc->dmfl_state & ASLP) {
96226910Skarels 		sleep(sc->dmfl_buf, PZERO + 8);
96326312Skarels 		while (sc->dmfl_state & ERROR) {
96426910Skarels 			timeout(dmflint, (caddr_t)dmf, 10 * hz);
96526910Skarels 			sleep((caddr_t)&sc->dmfl_state, PZERO + 8);
96621955Sbloom 		}
96721955Sbloom 	}
96826910Skarels 	splx(s);
96926312Skarels 	return (0);
97021955Sbloom }
97126312Skarels 
97226312Skarels /*
97326312Skarels  * dmflint -- handle an interrupt from the line printer part of the dmf32
97421955Sbloom  */
97521955Sbloom dmflint(dmf)
97626312Skarels 	int dmf;
97721955Sbloom {
97821955Sbloom 	register struct uba_device *ui;
97921955Sbloom 	register struct dmfl_softc *sc;
98021955Sbloom 	register struct dmfdevice *d;
98126910Skarels 	short dmfl_stats;
98221955Sbloom 
98326312Skarels 	ui = dmfinfo[dmf];
98426312Skarels 	sc = &dmfl_softc[dmf];
98526312Skarels 	d = (struct dmfdevice *)ui->ui_addr;
98621955Sbloom 
98726910Skarels 	d->dmfl_ctrl &= ~DMFL_IE;
98827057Skarels 	dmfl_stats = d->dmfl_ctrl;
98926312Skarels 	if (sc->dmfl_state & ERROR) {
99026910Skarels 		if ((dmfl_stats & DMFL_OFFLINE) == 0)
99121955Sbloom 			sc->dmfl_state &= ~ERROR;
99226366Skarels 		wakeup((caddr_t)&sc->dmfl_state);
99321955Sbloom 		return;
99421955Sbloom 	}
99526910Skarels 	if (dmfl_stats & DMFL_DMAERR)
99626910Skarels 		log(LOG_WARNING, "dmf%d: NXM\n", dmf);
99726910Skarels 	if (dmfl_stats & DMFL_OFFLINE) {
99826910Skarels 		log(LOG_WARNING, "dmf%d: printer error\n", dmf);
99921955Sbloom 		sc->dmfl_state |= ERROR;
100021955Sbloom 	}
100121955Sbloom #ifdef notdef
100226910Skarels 	if (dmfl_stats & DMFL_PDONE) {
100326910Skarels 		printf("bytes= %d\n", d->dmfl_indrct);
100426910Skarels 		printf("lines= %d\n", d->dmfl_indrct);
100526910Skarels 	}
100621955Sbloom #endif
100721955Sbloom 	sc->dmfl_state &= ~ASLP;
100826910Skarels 	wakeup((caddr_t)sc->dmfl_buf);
100926910Skarels 	if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
101026312Skarels 		ubarelse(ui->ui_ubanum, &sc->dmfl_info);
101121955Sbloom }
101221955Sbloom 
10136940Ssam /* stubs for interrupt routines for devices not yet supported */
10146940Ssam 
101526312Skarels dmfsrint()
101626312Skarels {
101726312Skarels 	printf("dmfsrint\n");
101826312Skarels }
10196940Ssam 
102026312Skarels dmfsxint()
102126312Skarels {
102226312Skarels 	printf("dmfsxint\n");
102326312Skarels }
10246940Ssam 
102526312Skarels dmfdaint()
102626312Skarels {
102726312Skarels 	printf("dmfdaint\n");
102826312Skarels }
10296940Ssam 
103026312Skarels dmfdbint()
103126312Skarels {
103226312Skarels 	printf("dmfdbint\n");
103326312Skarels }
103426910Skarels #endif NDMF
1035