xref: /csrg-svn/sys/vax/uba/dmf.c (revision 23324)
1*23324Smckusick /*
2*23324Smckusick  * Copyright (c) 1982 Regents of the University of California.
3*23324Smckusick  * All rights reserved.  The Berkeley software License Agreement
4*23324Smckusick  * specifies the terms and conditions for redistribution.
5*23324Smckusick  *
6*23324Smckusick  *	@(#)dmf.c	6.8 (Berkeley) 06/08/85
7*23324Smckusick  */
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 
6921955Sbloom int	dmf_timeout = 50;		/* 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 
786940Ssam struct	tty dmf_tty[NDMF*8];
796940Ssam char	dmfsoftCAR[NDMF];
8021955Sbloom 
8121955Sbloom struct dmfl_softc
8221955Sbloom {
8321955Sbloom 	unsigned dmfl_state; 		/* soft state bits */
8421955Sbloom 	unsigned dmfl_info;		/* uba info */
8521955Sbloom 	unsigned short dmfl_lines;	/* lines per page (66 def.) */
8621955Sbloom 	unsigned short dmfl_cols; 	/* cols per line (132 def.) */
8721955Sbloom 	char dmfl_buf[DMFL_BUFSIZ];
8821955Sbloom } dmfl_softc[NDMF];
8921955Sbloom 
9021955Sbloom /*
9121955Sbloom  * convert device number into DMF line printer unit number
9221955Sbloom  */
9321955Sbloom #define	DMFL_UNIT(d)	(minor(d)&0xF)	/* up to 16 DMFs */
9421955Sbloom 
9521955Sbloom #define ASLP 1		/* waiting for interrupt from dmf */
9621955Sbloom #define OPEN 2		/* line printer is open */
9721955Sbloom #define ERROR 4		/* error while printing, driver
9821955Sbloom 			 refuses to do anything till closed */
9921955Sbloom 
1008778Sroot #ifndef lint
1018778Sroot int	ndmf = NDMF*8;			/* used by iostat */
1028778Sroot #endif
1036940Ssam int	dmfact;				/* mask of active dmf's */
1046940Ssam int	dmfstart(), ttrstrt();
1056940Ssam 
1066940Ssam /*
1076940Ssam  * The clist space is mapped by the driver onto each UNIBUS.
1086940Ssam  * The UBACVT macro converts a clist space address for unibus uban
1096940Ssam  * into an i/o space address for the DMA routine.
1106940Ssam  */
11116063Skarels int	dmf_ubinfo[NUBA];		/* info about allocated unibus map */
11216063Skarels static int cbase[NUBA];			/* base address in unibus map */
1136940Ssam #define	UBACVT(x, uban)		(cbase[uban] + ((x)-(char *)cfree))
11421955Sbloom char	dmf_dma[NDMF*8];
1156940Ssam 
1166940Ssam /*
1176940Ssam  * Routine for configuration to set dmf interrupt.
1186940Ssam  */
1196940Ssam /*ARGSUSED*/
1206940Ssam dmfprobe(reg, ctlr)
1216940Ssam 	caddr_t reg;
12221955Sbloom 	struct uba_device *ctlr;
1236940Ssam {
1246940Ssam 	register int br, cvec;		/* these are ``value-result'' */
1256940Ssam 	register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
12621955Sbloom 	register int i;
12721955Sbloom 	register unsigned int a;
12821955Sbloom 	static char *dmfdevs[]=
12921955Sbloom 		{"parallel","printer","synch","asynch"};
13021955Sbloom 	unsigned int dmfoptions;
1316940Ssam 
1326940Ssam #ifdef lint
1336940Ssam 	br = 0; cvec = br; br = cvec;
1348808Sroot 	dmfxint(0); dmfrint(0);
1358808Sroot 	dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint();
1366940Ssam #endif
13721955Sbloom 	/*
13821955Sbloom 	 * Pick the usual size DMF vector here (don't decrement it here).
13921955Sbloom 	 * grab configuration; note that the DMF32
14021955Sbloom 	 * doesn't seem to put the right bits in this
14121955Sbloom 	 * register until AFTER the interrupt vector is set.
14221955Sbloom 	 */
1436940Ssam 	br = 0x15;
14421955Sbloom 	cvec = (uba_hd[numuba].uh_lastiv - 4*8);
14521955Sbloom 	dmfaddr->dmfccsr0 = (cvec >> 2) ;
14621955Sbloom 	dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
14721955Sbloom 
14821955Sbloom 	/* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
14921955Sbloom 	if (dmfoptions == DMFC_ASYNC) {
15021955Sbloom 		/* Async portion only  -  vmz/32n */
15121955Sbloom 		/* device dmf0 csr 0160400	vector dmfrint dmfxint  */
15221955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 8);	/* only 8 bytes req'd */
15321955Sbloom 		dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;	/* program 020 less   */
15421955Sbloom 		printf("dmf%d: Able vmz32/n\n", ctlr->ui_unit);
15521955Sbloom 	}
15621955Sbloom 	else if (dmfoptions == DMFC_LP) {
15721955Sbloom 		/* LP portion only - vmz/lp */
15821955Sbloom 		/* device dmf0 csr 0160400	vector dmflint */
15921955Sbloom 
16021955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 8);	/* only 8 bytes req'd */
16121955Sbloom 		dmfaddr->dmfccsr0 = (cvec - 3*8) >> 2;	/* program 030 less   */
16221955Sbloom 		printf("dmf%d: Able vmz/lp\n", ctlr->ui_unit);
16321955Sbloom 	}
16421955Sbloom 	else {
16521955Sbloom 		/* anything else we program like a dec dmf32	*/
16621955Sbloom 		/* device dmf0 vector dmfsrint dmfsxint dmfdaint dmfdbint dmfrint dmfxint dmflint */
16721955Sbloom 
16821955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
16921955Sbloom 		dmfaddr->dmfccsr0 = (cvec >> 2) ;
17021955Sbloom 		a = (dmfaddr->dmfccsr0>>12) & 0xf;
17121955Sbloom 		printf("dmf%d:", ctlr->ui_unit);
17221955Sbloom 		for(i=0;a != 0;++i,a >>= 1) {
17321955Sbloom 			if(a&1)
17421955Sbloom 				printf(" %s",dmfdevs[i]);
17521955Sbloom 		}
17621955Sbloom 		printf(".\n");
17721955Sbloom 	}
17821955Sbloom 
17921955Sbloom 	if (dmfoptions & DMFC_LP)
18021955Sbloom 		dmfaddr->dmfl[0] = DMFL_RESET;
1816940Ssam 	/* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */
1827412Skre 	return (sizeof (struct dmfdevice));
1836940Ssam }
1846940Ssam 
1856940Ssam /*
1866940Ssam  * Routine called to attach a dmf.
1876940Ssam  */
1886940Ssam dmfattach(ui)
1896940Ssam 	struct uba_device *ui;
1906940Ssam {
19121955Sbloom 	register int cols = (ui->ui_flags>>8) & 0xff;
19221955Sbloom 	register int lines = (ui->ui_flags>>16) & 0xff;
1936940Ssam 
19421955Sbloom 	dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff;
19521955Sbloom 	dmfl_softc[ui->ui_unit].dmfl_cols = cols==0?DMFL_DEFCOLS:cols;
19621955Sbloom 	dmfl_softc[ui->ui_unit].dmfl_lines = lines==0?DMFL_DEFLINES:lines;
1976940Ssam }
1986940Ssam 
1996940Ssam 
2006940Ssam /*
2016940Ssam  * Open a DMF32 line, mapping the clist onto the uba if this
2026940Ssam  * is the first dmf on this uba.  Turn on this dmf if this is
2036940Ssam  * the first use of it.
2046940Ssam  */
2056940Ssam /*ARGSUSED*/
2066940Ssam dmfopen(dev, flag)
2076940Ssam 	dev_t dev;
2086940Ssam {
2096940Ssam 	register struct tty *tp;
2106940Ssam 	register int unit, dmf;
2116940Ssam 	register struct dmfdevice *addr;
2126940Ssam 	register struct uba_device *ui;
2136940Ssam 	int s;
2146940Ssam 
2156940Ssam 	unit = minor(dev);
21621955Sbloom 	if(unit & 0200)
21721955Sbloom 		return(dmflopen(dev,flag));
2186940Ssam 	dmf = unit >> 3;
2198567Sroot 	if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
2208567Sroot 		return (ENXIO);
2216940Ssam 	tp = &dmf_tty[unit];
2228567Sroot 	if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
2238567Sroot 		return (EBUSY);
2246940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
2256940Ssam 	tp->t_addr = (caddr_t)addr;
2266940Ssam 	tp->t_oproc = dmfstart;
2276971Ssam 	tp->t_state |= TS_WOPEN;
2286940Ssam 	/*
2296940Ssam 	 * While setting up state for this uba and this dmf,
2306940Ssam 	 * block uba resets which can clear the state.
2316940Ssam 	 */
23221955Sbloom 	s = spltty();
2336940Ssam 	if (dmf_ubinfo[ui->ui_ubanum] == 0) {
2346940Ssam 		dmf_ubinfo[ui->ui_ubanum] =
2356940Ssam 		    uballoc(ui->ui_ubanum, (caddr_t)cfree,
2366940Ssam 			nclist*sizeof(struct cblock), 0);
2376940Ssam 		cbase[ui->ui_ubanum] = dmf_ubinfo[ui->ui_ubanum]&0x3ffff;
2386940Ssam 	}
2396940Ssam 	if ((dmfact&(1<<dmf)) == 0) {
2406940Ssam 		addr->dmfcsr |= DMF_IE;
2416940Ssam 		dmfact |= (1<<dmf);
24221955Sbloom 		addr->dmfrsp = dmf_timeout;
2436940Ssam 	}
2446940Ssam 	splx(s);
2456940Ssam 	/*
2466940Ssam 	 * If this is first open, initialze tty state to default.
2476940Ssam 	 */
2486971Ssam 	if ((tp->t_state&TS_ISOPEN) == 0) {
2496940Ssam 		ttychars(tp);
2506940Ssam 		if (tp->t_ispeed == 0) {
2516940Ssam 			tp->t_ispeed = B300;
2526940Ssam 			tp->t_ospeed = B300;
2536940Ssam 			tp->t_flags = ODDP|EVENP|ECHO;
2546940Ssam 		}
2556940Ssam 		dmfparam(unit);
2566940Ssam 	}
2576940Ssam 	/*
2586940Ssam 	 * Wait for carrier, then process line discipline specific open.
2596940Ssam 	 */
2606940Ssam 	if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
2616940Ssam 	    (dmfsoftCAR[dmf] & (1<<(unit&07))))
2626971Ssam 		tp->t_state |= TS_CARR_ON;
26321955Sbloom 	s = spltty();
2646971Ssam 	while ((tp->t_state & TS_CARR_ON) == 0) {
2656971Ssam 		tp->t_state |= TS_WOPEN;
2666940Ssam 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
2676940Ssam 	}
2686940Ssam 	splx(s);
2698567Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
2706940Ssam }
2716940Ssam 
2726940Ssam /*
2736940Ssam  * Close a DMF32 line.
2746940Ssam  */
2756940Ssam /*ARGSUSED*/
2766940Ssam dmfclose(dev, flag)
2776940Ssam 	dev_t dev;
2786940Ssam 	int flag;
2796940Ssam {
2806940Ssam 	register struct tty *tp;
2816940Ssam 	register unit;
2826940Ssam 
2836940Ssam 	unit = minor(dev);
28421955Sbloom 	if(unit & 0200)
28521955Sbloom 		return(dmflclose(dev,flag));
28621955Sbloom 
2876940Ssam 	tp = &dmf_tty[unit];
2886940Ssam 	(*linesw[tp->t_line].l_close)(tp);
2898702Sroot 	(void) dmfmctl(unit, DMF_BRK, DMBIC);
2906971Ssam 	if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
2918702Sroot 		(void) dmfmctl(unit, DMF_OFF, DMSET);
2926940Ssam 	ttyclose(tp);
2936940Ssam }
2946940Ssam 
2957726Sroot dmfread(dev, uio)
2966940Ssam 	dev_t dev;
2977726Sroot 	struct uio *uio;
2986940Ssam {
2996940Ssam 	register struct tty *tp;
3006940Ssam 
30121955Sbloom 	if(minor(dev)&0200)
30221955Sbloom 		return(ENXIO);
3036940Ssam 	tp = &dmf_tty[minor(dev)];
3047726Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
3056940Ssam }
3066940Ssam 
3077832Sroot dmfwrite(dev, uio)
3086940Ssam 	dev_t dev;
3097832Sroot 	struct uio *uio;
3106940Ssam {
3116940Ssam 	register struct tty *tp;
3126940Ssam 
31321955Sbloom 	if(minor(dev)&0200)
31421955Sbloom 		return(dmflwrite(dev,uio));
3156940Ssam 	tp = &dmf_tty[minor(dev)];
3168530Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
3176940Ssam }
3186940Ssam 
3196940Ssam /*
3206940Ssam  * DMF32 receiver interrupt.
3216940Ssam  */
3226940Ssam dmfrint(dmf)
3236940Ssam 	int dmf;
3246940Ssam {
3256940Ssam 	register c;
3266940Ssam 	register struct dmfdevice *addr;
3276940Ssam 	register struct tty *tp0;
32821955Sbloom 	register dev;
32921955Sbloom 	int unit;
33012449Ssam 	int overrun = 0, s;
3316940Ssam 
33221955Sbloom 	{
33321955Sbloom 		register struct uba_device *ui;
33421955Sbloom 
33521955Sbloom 		ui = dmfinfo[dmf];
33621955Sbloom 		if (ui == 0 || ui->ui_alive == 0)
33721955Sbloom 			return;
33821955Sbloom 		addr = (struct dmfdevice *)ui->ui_addr;
33921955Sbloom 	}
34021955Sbloom 	tp0 = &dmf_tty[dmf * 8];
3416940Ssam 	/*
3426940Ssam 	 * Loop fetching characters from the silo for this
3436940Ssam 	 * dmf until there are no more in the silo.
3446940Ssam 	 */
3456940Ssam 	while ((c = addr->dmfrbuf) < 0) {
34621955Sbloom 		register struct tty *tp;
34721955Sbloom 
34821955Sbloom 		unit = (c >> 8) & 07;
34921955Sbloom 		tp = tp0 + unit;
35021955Sbloom 		dev = unit + dmf * 8;
3516940Ssam 		if (c & DMF_DSC) {
35221955Sbloom 			s = spltty();
35321955Sbloom 			addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
3546940Ssam 			if (addr->dmfrms & DMF_CAR) {
3556971Ssam 				if ((tp->t_state & TS_CARR_ON) == 0) {
3566940Ssam 					wakeup((caddr_t)&tp->t_rawq);
3576971Ssam 					tp->t_state |= TS_CARR_ON;
35821956Sbloom 				} else if ((tp->t_flags & MDMBUF) &&
35921956Sbloom 				    (tp->t_state & TS_TTSTOP)) {
36021956Sbloom 					tp->t_state &= ~TS_TTSTOP;
36121956Sbloom 					ttstart(tp);
3626940Ssam 				}
36321956Sbloom 			} else if ((tp->t_state & TS_WOPEN) == 0 &&
36421956Sbloom 			    tp->t_flags & MDMBUF) {
36521956Sbloom 			    	if ((tp->t_state & TS_TTSTOP) == 0) {
36621956Sbloom 					tp->t_state |= TS_TTSTOP;
36721956Sbloom 					dmfstop(tp, 0);
36821956Sbloom 				}
36921956Sbloom 			} else if ((tp->t_state & TS_CARR_ON) &&
37021956Sbloom 			    (tp->t_flags & NOHANG) == 0 &&
37121956Sbloom 			    (dmfsoftCAR[dmf] & (1<<unit)) == 0) {
37221956Sbloom 				if (tp->t_state&TS_ISOPEN) {
3736940Ssam 					gsignal(tp->t_pgrp, SIGHUP);
3746940Ssam 					gsignal(tp->t_pgrp, SIGCONT);
3756940Ssam 					addr->dmfcsr = DMF_IE | DMFIR_LCR |
37621955Sbloom 						unit;
3776940Ssam 					addr->dmftms = 0;
37812776Ssam 					ttyflush(tp, FREAD|FWRITE);
3796940Ssam 				}
3806971Ssam 				tp->t_state &= ~TS_CARR_ON;
3816940Ssam 			}
38212449Ssam 			splx(s);
3836940Ssam 			continue;
3846940Ssam 		}
3856971Ssam 		if ((tp->t_state&TS_ISOPEN)==0) {
3866940Ssam 			wakeup((caddr_t)tp);
3876940Ssam 			continue;
3886940Ssam 		}
38921956Sbloom 		if (c & (DMF_PE|DMF_DO|DMF_FE)) {
39021955Sbloom 			if (c & DMF_PE)
39121955Sbloom 				if ((tp->t_flags&(EVENP|ODDP))==EVENP
39221955Sbloom 			 	|| (tp->t_flags&(EVENP|ODDP))==ODDP )
39321955Sbloom 					continue;
39421955Sbloom 			if ((c & DMF_DO) && overrun == 0) {
39521955Sbloom 				log(KERN_RECOV, "dmf%d: silo overflow\n", dmf);
39621955Sbloom 				overrun = 1;
39721955Sbloom 			}
39821955Sbloom 			if (c & DMF_FE)
39921955Sbloom 				/*
40021955Sbloom 			 	* At framing error (break) generate
40121955Sbloom 			 	* a null (in raw mode, for getty), or a
40221955Sbloom 			 	* interrupt (in cooked/cbreak mode).
40321955Sbloom 			 	*/
40421955Sbloom 				if (tp->t_flags&RAW)
40521955Sbloom 					c = 0;
40621955Sbloom 				else
40721955Sbloom 					c = tp->t_intrc;
4086940Ssam 		}
4096940Ssam #if NBK > 0
4106940Ssam 		if (tp->t_line == NETLDISC) {
4116940Ssam 			c &= 0177;
4126940Ssam 			BKINPUT(c, tp);
4136940Ssam 		} else
4146940Ssam #endif
4156940Ssam 			(*linesw[tp->t_line].l_rint)(c, tp);
4166940Ssam 	}
4176940Ssam }
4186940Ssam 
4196940Ssam /*
4206940Ssam  * Ioctl for DMF32.
4216940Ssam  */
4226940Ssam /*ARGSUSED*/
4237630Ssam dmfioctl(dev, cmd, data, flag)
4246940Ssam 	dev_t dev;
4257630Ssam 	caddr_t data;
4266940Ssam {
4276940Ssam 	register struct tty *tp;
4286940Ssam 	register int unit = minor(dev);
4298567Sroot 	int error;
4306940Ssam 
43121955Sbloom 	if(unit & 0200)
43221955Sbloom 		return (ENOTTY);
4336940Ssam 	tp = &dmf_tty[unit];
4348567Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
4358567Sroot 	if (error >= 0)
4368567Sroot 		return (error);
4378567Sroot 	error = ttioctl(tp, cmd, data, flag);
4388567Sroot 	if (error >= 0) {
43917562Sbloom 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
44017562Sbloom 		    cmd == TIOCLBIC || cmd == TIOCLSET)
4416940Ssam 			dmfparam(unit);
4428567Sroot 		return (error);
4438567Sroot 	}
4448567Sroot 	switch (cmd) {
4456940Ssam 
4466940Ssam 	case TIOCSBRK:
4478702Sroot 		(void) dmfmctl(dev, DMF_BRK, DMBIS);
4486940Ssam 		break;
4497630Ssam 
4506940Ssam 	case TIOCCBRK:
4518702Sroot 		(void) dmfmctl(dev, DMF_BRK, DMBIC);
4526940Ssam 		break;
4537630Ssam 
4546940Ssam 	case TIOCSDTR:
4558702Sroot 		(void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
4566940Ssam 		break;
4577630Ssam 
4586940Ssam 	case TIOCCDTR:
4598702Sroot 		(void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
4606940Ssam 		break;
4617630Ssam 
4626940Ssam 	case TIOCMSET:
4638702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
4646940Ssam 		break;
4657630Ssam 
4666940Ssam 	case TIOCMBIS:
4678702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
4686940Ssam 		break;
4697630Ssam 
4706940Ssam 	case TIOCMBIC:
4718702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
4726940Ssam 		break;
4737630Ssam 
4746940Ssam 	case TIOCMGET:
4757630Ssam 		*(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
4766940Ssam 		break;
4777630Ssam 
4786940Ssam 	default:
4798567Sroot 		return (ENOTTY);
4806940Ssam 	}
4818567Sroot 	return (0);
4826940Ssam }
4836940Ssam 
4846940Ssam dmtodmf(bits)
4856940Ssam 	register int bits;
4866940Ssam {
4876940Ssam 	register int b;
4886940Ssam 
4896940Ssam 	b = bits & 012;
4906940Ssam 	if (bits & DML_ST) b |= DMF_RATE;
4916940Ssam 	if (bits & DML_RTS) b |= DMF_RTS;
4926940Ssam 	if (bits & DML_USR) b |= DMF_USRW;
4936940Ssam 	return(b);
4946940Ssam }
4956940Ssam 
4966940Ssam dmftodm(bits)
4976940Ssam 	register int bits;
4986940Ssam {
4996940Ssam 	register int b;
5006940Ssam 
5016940Ssam 	b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
5026940Ssam 	if (bits & DMF_USRR) b |= DML_USR;
5036940Ssam 	if (bits & DMF_RTS) b |= DML_RTS;
5046940Ssam 	return(b);
5056940Ssam }
5066940Ssam 
5076940Ssam 
5086940Ssam /*
5096940Ssam  * Set parameters from open or stty into the DMF hardware
5106940Ssam  * registers.
5116940Ssam  */
5126940Ssam dmfparam(unit)
5136940Ssam 	register int unit;
5146940Ssam {
5156940Ssam 	register struct tty *tp;
5166940Ssam 	register struct dmfdevice *addr;
5176940Ssam 	register int lpar, lcr;
5186940Ssam 	int s;
5196940Ssam 
5206940Ssam 	tp = &dmf_tty[unit];
5216940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
5226940Ssam 	/*
5236940Ssam 	 * Block interrupts so parameters will be set
5246940Ssam 	 * before the line interrupts.
5256940Ssam 	 */
52621955Sbloom 	s = spltty();
5276940Ssam 	addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
5286940Ssam 	if ((tp->t_ispeed)==0) {
5296971Ssam 		tp->t_state |= TS_HUPCLS;
5308702Sroot 		(void) dmfmctl(unit, DMF_OFF, DMSET);
5316940Ssam 		return;
5326940Ssam 	}
5336940Ssam 	lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
5346940Ssam 	lcr = DMFLCR_ENA;
5356940Ssam 	if ((tp->t_ispeed) == B134)
5366940Ssam 		lpar |= BITS6|PENABLE;
5379550Ssam 	else if (tp->t_flags & (RAW|LITOUT))
5386940Ssam 		lpar |= BITS8;
5396940Ssam 	else {
5406940Ssam 		lpar |= BITS7|PENABLE;
5416940Ssam 		/* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
5426940Ssam 	}
54312450Ssam 	if (tp->t_flags&EVENP)
54412450Ssam 		lpar |= EPAR;
5456940Ssam 	if ((tp->t_ospeed) == B110)
5466940Ssam 		lpar |= TWOSB;
5476940Ssam 	lpar |= (unit&07);
5486940Ssam 	addr->dmflpr = lpar;
54912449Ssam 	SETLCR(addr, lcr);
5506940Ssam 	splx(s);
5516940Ssam }
5526940Ssam 
5536940Ssam /*
5546940Ssam  * DMF32 transmitter interrupt.
5556940Ssam  * Restart the idle line.
5566940Ssam  */
5576940Ssam dmfxint(dmf)
5586940Ssam 	int dmf;
5596940Ssam {
56021955Sbloom 	int u = dmf * 8;
56121955Sbloom 	struct tty *tp0 = &dmf_tty[u];
5626940Ssam 	register struct tty *tp;
5636940Ssam 	register struct dmfdevice *addr;
5646940Ssam 	register struct uba_device *ui;
56521955Sbloom 	register int t;
5666940Ssam 	short cntr;
5676940Ssam 
5686940Ssam 	ui = dmfinfo[dmf];
5696940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
5706940Ssam 	while ((t = addr->dmfcsr) & DMF_TI) {
57121955Sbloom 		if (t & DMF_NXM)
57221955Sbloom 			/* SHOULD RESTART OR SOMETHING... */
57321955Sbloom 			printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
57421955Sbloom 		t = t >> 8 & 7;
57521955Sbloom 		tp = tp0 + t;
5766971Ssam 		tp->t_state &= ~TS_BUSY;
5776971Ssam 		if (tp->t_state&TS_FLUSH)
5786971Ssam 			tp->t_state &= ~TS_FLUSH;
57921955Sbloom 		else if (dmf_dma[u + t]) {
58021955Sbloom 			/*
58121955Sbloom 			 * Do arithmetic in a short to make up
58221955Sbloom 			 * for lost 16&17 bits.
58321955Sbloom 			 */
58421955Sbloom 			addr->dmfcsr = DMFIR_TBA | DMF_IE | t;
58521955Sbloom 			cntr = addr->dmftba -
58621955Sbloom 			    UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
58721955Sbloom 			ndflush(&tp->t_outq, (int)cntr);
5886940Ssam 		}
5896940Ssam 		if (tp->t_line)
5906940Ssam 			(*linesw[tp->t_line].l_start)(tp);
5916940Ssam 		else
5926940Ssam 			dmfstart(tp);
5936940Ssam 	}
5946940Ssam }
5956940Ssam 
5966940Ssam /*
5976940Ssam  * Start (restart) transmission on the given DMF32 line.
5986940Ssam  */
5996940Ssam dmfstart(tp)
6006940Ssam 	register struct tty *tp;
6016940Ssam {
6026940Ssam 	register struct dmfdevice *addr;
6038607Sroot 	register int unit, nch;
6046940Ssam 	int s;
60521955Sbloom 	register int dmf;
6066940Ssam 
6076940Ssam 	unit = minor(tp->t_dev);
60821955Sbloom 	dmf = unit >> 3;
6096940Ssam 	unit &= 07;
6106940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
6116940Ssam 
6126940Ssam 	/*
6136940Ssam 	 * Must hold interrupts in following code to prevent
6146940Ssam 	 * state of the tp from changing.
6156940Ssam 	 */
61621955Sbloom 	s = spltty();
6176940Ssam 	/*
6186940Ssam 	 * If it's currently active, or delaying, no need to do anything.
6196940Ssam 	 */
6206971Ssam 	if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
6216940Ssam 		goto out;
6226940Ssam 	/*
6236940Ssam 	 * If there are still characters in the silo,
6246940Ssam 	 * just reenable the transmitter.
6256940Ssam 	 */
6266940Ssam 	addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
6276940Ssam 	if (addr->dmftsc) {
6286940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
62912449Ssam 		SETLCR(addr, addr->dmflcr|DMF_TE);
6306971Ssam 		tp->t_state |= TS_BUSY;
6316940Ssam 		goto out;
6326940Ssam 	}
6336940Ssam 	/*
6346940Ssam 	 * If there are sleepers, and output has drained below low
6356940Ssam 	 * water mark, wake up the sleepers.
6366940Ssam 	 */
63721955Sbloom 	if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
63821955Sbloom 		if (tp->t_state&TS_ASLEEP) {
63921955Sbloom 			tp->t_state &= ~TS_ASLEEP;
64021955Sbloom 			wakeup((caddr_t)&tp->t_outq);
64121955Sbloom 		}
64221955Sbloom 		if (tp->t_wsel) {
64321955Sbloom 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
64421955Sbloom 			tp->t_wsel = 0;
64521955Sbloom 			tp->t_state &= ~TS_WCOLL;
64621955Sbloom 		}
6476940Ssam 	}
6486940Ssam 	/*
6496940Ssam 	 * Now restart transmission unless the output queue is
6506940Ssam 	 * empty.
6516940Ssam 	 */
6526940Ssam 	if (tp->t_outq.c_cc == 0)
6536940Ssam 		goto out;
6549550Ssam 	if (tp->t_flags & (RAW|LITOUT))
6556940Ssam 		nch = ndqb(&tp->t_outq, 0);
6566940Ssam 	else {
65721955Sbloom 		if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
65821955Sbloom 			/*
65921955Sbloom 		 	* If first thing on queue is a delay process it.
66021955Sbloom 		 	*/
6616940Ssam 			nch = getc(&tp->t_outq);
6626940Ssam 			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
6636971Ssam 			tp->t_state |= TS_TIMEOUT;
6646940Ssam 			goto out;
6656940Ssam 		}
6666940Ssam 	}
6676940Ssam 	/*
6686940Ssam 	 * If characters to transmit, restart transmission.
6696940Ssam 	 */
67021955Sbloom 	if (nch >= dmf_mindma) {
67121955Sbloom 		register car;
67221955Sbloom 
67321955Sbloom 		dmf_dma[minor(tp->t_dev)] = 1;
6746940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
67512449Ssam 		SETLCR(addr, addr->dmflcr|DMF_TE);
6766940Ssam 		car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
6776940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
6786940Ssam 		addr->dmftba = car;
67921955Sbloom 		addr->dmftcc = ((car >> 2) & 0xc000) | nch;
68021955Sbloom 		tp->t_state |= TS_BUSY;
68121955Sbloom 	} else if (nch) {
6826940Ssam 		register char *cp = tp->t_outq.c_cf;
6836940Ssam 		register int i;
6846940Ssam 
68521955Sbloom 		dmf_dma[minor(tp->t_dev)] = 0;
6866940Ssam 		nch = MIN(nch, DMF_SILOCNT);
6876940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
68812449Ssam 		SETLCR(addr, addr->dmflcr|DMF_TE);
6896940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
6906940Ssam 		for (i = 0; i < nch; i++)
6916940Ssam 			addr->dmftbuf = *cp++;
6926940Ssam 		ndflush(&tp->t_outq, nch);
6936971Ssam 		tp->t_state |= TS_BUSY;
6946940Ssam 	}
6956940Ssam out:
6966940Ssam 	splx(s);
6976940Ssam }
6986940Ssam 
6996940Ssam /*
7006940Ssam  * Stop output on a line, e.g. for ^S/^Q or output flush.
7016940Ssam  */
7026940Ssam /*ARGSUSED*/
7036940Ssam dmfstop(tp, flag)
7046940Ssam 	register struct tty *tp;
7056940Ssam {
7066940Ssam 	register struct dmfdevice *addr;
70721955Sbloom 	register unit = minor(tp->t_dev) & 7;
70821955Sbloom 	int s;
7096940Ssam 
7106940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
7116940Ssam 	/*
7126940Ssam 	 * Block input/output interrupts while messing with state.
7136940Ssam 	 */
71421955Sbloom 	s = spltty();
71521955Sbloom 	if (flag) {
71621955Sbloom 		addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
71721955Sbloom 		if (addr->dmftsc) {
71821955Sbloom 			/*
71921955Sbloom 			 * Flush regardless of whether we're transmitting
72021955Sbloom 			 * (TS_BUSY), if the silo contains untransmitted
72121955Sbloom 			 * characters.
72221955Sbloom 			 */
72321955Sbloom 			addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
72421955Sbloom 			SETLCR(addr, addr->dmflcr | DMF_TE | DMF_FLUSH);
72521955Sbloom 			/* this will interrupt so let dmfxint handle the rest */
72621955Sbloom 			tp->t_state |= TS_FLUSH|TS_BUSY;
72721955Sbloom 		}
72821955Sbloom 	} else {
72921955Sbloom 		if (tp->t_state & TS_BUSY) {
73021955Sbloom 			/*
73121955Sbloom 			 * Stop transmission by disabling
73221955Sbloom 			 * the transmitter.  We'll pick up where we
73321955Sbloom 			 * left off by reenabling in dmfstart.
73421955Sbloom 			 */
73521955Sbloom 			addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
73621955Sbloom 			SETLCR(addr, addr->dmflcr &~ DMF_TE);
73721955Sbloom 			/* no interrupt here */
7386971Ssam 			tp->t_state &= ~TS_BUSY;
73921955Sbloom 		}
7406940Ssam 	}
7416940Ssam 	splx(s);
7426940Ssam }
7436940Ssam 
7446940Ssam /*
7456940Ssam  * DMF32 modem control
7466940Ssam  */
7476940Ssam dmfmctl(dev, bits, how)
7486940Ssam 	dev_t dev;
7496940Ssam 	int bits, how;
7506940Ssam {
7516940Ssam 	register struct dmfdevice *dmfaddr;
7526940Ssam 	register int unit, mbits, lcr;
7536940Ssam 	int s;
7546940Ssam 
7556940Ssam 	unit = minor(dev);
7566940Ssam 	dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
7576940Ssam 	unit &= 07;
75821955Sbloom 	s = spltty();
7596940Ssam 	dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
7606940Ssam 	mbits = dmfaddr->dmfrms << 8;
7616940Ssam 	dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
7626940Ssam 	mbits |= dmfaddr->dmftms;
7636940Ssam 	lcr = dmfaddr->dmflcr;
7646940Ssam 	switch (how) {
7656940Ssam 	case DMSET:
76612449Ssam 		mbits = (mbits &0xff00) | bits;
7676940Ssam 		break;
7686940Ssam 
7696940Ssam 	case DMBIS:
7706940Ssam 		mbits |= bits;
7716940Ssam 		break;
7726940Ssam 
7736940Ssam 	case DMBIC:
7746940Ssam 		mbits &= ~bits;
7756940Ssam 		break;
7766940Ssam 
7776940Ssam 	case DMGET:
7786940Ssam 		(void) splx(s);
7796940Ssam 		return(mbits);
7806940Ssam 	}
7816940Ssam 	if (mbits & DMF_BRK)
7826940Ssam 		lcr |= DMF_RBRK;
7836940Ssam 	else
7846940Ssam 		lcr &= ~DMF_RBRK;
78512449Ssam 	lcr = ((mbits & 037) << 8) | (lcr & 0xff);
78612449Ssam 	dmfaddr->dmfun.dmfirw = lcr;
7876940Ssam 	(void) splx(s);
7886940Ssam 	return(mbits);
7896940Ssam }
7906940Ssam 
7916940Ssam /*
7926940Ssam  * Reset state of driver if UBA reset was necessary.
7936940Ssam  * Reset the csr, lpr, and lcr registers on open lines, and
7946940Ssam  * restart transmitters.
7956940Ssam  */
7966940Ssam dmfreset(uban)
7976940Ssam 	int uban;
7986940Ssam {
7996940Ssam 	register int dmf, unit;
8006940Ssam 	register struct tty *tp;
8016940Ssam 	register struct uba_device *ui;
8026940Ssam 	register struct dmfdevice *addr;
8036940Ssam 	int i;
8046940Ssam 
8056940Ssam 	if (dmf_ubinfo[uban] == 0)
8066940Ssam 		return;
8076940Ssam 	dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
8086940Ssam 	    nclist*sizeof (struct cblock), 0);
8096940Ssam 	cbase[uban] = dmf_ubinfo[uban]&0x3ffff;
8106940Ssam 	for (dmf = 0; dmf < NDMF; dmf++) {
8116940Ssam 		ui = dmfinfo[dmf];
8126940Ssam 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
8136940Ssam 			continue;
8146940Ssam 		printf(" dmf%d", dmf);
8156940Ssam 		addr = (struct dmfdevice *)ui->ui_addr;
8166940Ssam 		addr->dmfcsr = DMF_IE;
81721955Sbloom 		addr->dmfrsp = dmf_timeout;
8186940Ssam 		unit = dmf * 8;
8196940Ssam 		for (i = 0; i < 8; i++) {
8206940Ssam 			tp = &dmf_tty[unit];
8216971Ssam 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
8226940Ssam 				dmfparam(unit);
8238702Sroot 				(void) dmfmctl(unit, DMF_ON, DMSET);
8246971Ssam 				tp->t_state &= ~TS_BUSY;
8256940Ssam 				dmfstart(tp);
8266940Ssam 			}
8276940Ssam 			unit++;
8286940Ssam 		}
8296940Ssam 	}
8306940Ssam }
8316940Ssam 
83221955Sbloom /* dmflopen -- open the line printer port on a dmf32
83321955Sbloom  *
83421955Sbloom  */
83521955Sbloom dmflopen(dev,flag)
83621955Sbloom dev_t dev;
83721955Sbloom int flag;
83821955Sbloom {
83921955Sbloom 	register int dmf;
84021955Sbloom 	register struct dmfl_softc *sc;
84121955Sbloom 	register struct uba_device *ui;
84221955Sbloom 	register struct dmfdevice *addr;
84321955Sbloom 
84421955Sbloom 
84521955Sbloom 	dmf = DMFL_UNIT(dev) ;
84621955Sbloom 	if(((sc= &dmfl_softc[dmf])->dmfl_state & OPEN) ||
84721955Sbloom 		((ui=dmfinfo[dmf]) == 0) || ui->ui_alive == 0)
84821955Sbloom 			return(ENXIO);
84921955Sbloom 	addr = (struct dmfdevice *)ui->ui_addr;
85021955Sbloom 	if((addr->dmfl[0] & DMFL_OFFLINE))
85121955Sbloom 	{
85221955Sbloom 		/*printf("dmf: line printer offline/jammed\n");*/
85321955Sbloom 		return(EIO);
85421955Sbloom 	}
85521955Sbloom 	if((addr->dmfl[0]&DMFL_CONV))
85621955Sbloom 	{
85721955Sbloom 		printf("dmf:line printer disconnected\n");
85821955Sbloom 		return(EIO);
85921955Sbloom 	}
86021955Sbloom 
86121955Sbloom 	addr->dmfl[0] = 0;
86221955Sbloom 	sc->dmfl_state |= OPEN;
86321955Sbloom 	return 0;
86421955Sbloom }
86521955Sbloom 
86621955Sbloom dmflclose(dev,flag)
86721955Sbloom dev_t dev;
86821955Sbloom int flag;
86921955Sbloom {
87021955Sbloom 	register int dmf= DMFL_UNIT(dev);
87121955Sbloom 	register struct dmfl_softc *sc = &dmfl_softc[dmf];
87221955Sbloom 
87321955Sbloom 	dmflout(dev,"\f",1);
87421955Sbloom 	sc->dmfl_state = 0;
87521955Sbloom 	if(sc->dmfl_info != 0)
87621955Sbloom 		ubarelse((struct dmfdevice *)(dmfinfo[dmf])->ui_ubanum,
87721955Sbloom 			&(sc->dmfl_info));
87821955Sbloom 
87921955Sbloom 	((struct dmfdevice *)(dmfinfo[dmf]->ui_addr))->dmfl[0]=0;
88021955Sbloom 	return 0;
88121955Sbloom }
88221955Sbloom 
88321955Sbloom dmflwrite(dev,uio)
88421955Sbloom dev_t dev;
88521955Sbloom struct uio *uio;
88621955Sbloom {
88721955Sbloom 	register unsigned int n;
88821955Sbloom 	register int error;
88921955Sbloom 	register struct dmfl_softc *sc;
89021955Sbloom 
89121955Sbloom 	sc = &dmfl_softc[DMFL_UNIT(dev)];
89221955Sbloom 	if(sc->dmfl_state&ERROR) return(EIO);
89321955Sbloom 	while(n=min(DMFL_BUFSIZ,(unsigned)uio->uio_resid))
89421955Sbloom 	{
89521955Sbloom 		if(error=uiomove(&sc->dmfl_buf[0],(int)n,
89621955Sbloom 			UIO_WRITE,uio))
89721955Sbloom 		{
89821955Sbloom 			printf("uio move error\n");
89921955Sbloom 			return(error);
90021955Sbloom 		}
90121955Sbloom 		if(error=dmflout(dev,&sc->dmfl_buf[0],n))
90221955Sbloom 		{
90321955Sbloom 			return(error);
90421955Sbloom 		}
90521955Sbloom 	}
90621955Sbloom 	return 0;
90721955Sbloom }
90821955Sbloom 
90921955Sbloom 
91021955Sbloom /* dmflout -- start io operation to dmf line printer
91121955Sbloom  *		cp is addr of buf of n chars to be sent.
91221955Sbloom  *
91321955Sbloom  *	-- dmf will be put in formatted output mode, this will
91421955Sbloom  *		be selectable from an ioctl if the
91521955Sbloom  *		need ever arises.
91621955Sbloom  */
91721955Sbloom dmflout(dev,cp,n)
91821955Sbloom dev_t dev;
91921955Sbloom char *cp;
92021955Sbloom int n;
92121955Sbloom {
92221955Sbloom 	register struct dmfl_softc *sc;
92321955Sbloom 	register int dmf;
92421955Sbloom 	register struct uba_device *ui;
92521955Sbloom 	register struct dmfdevice *d;
92621955Sbloom 	register unsigned info;
92721955Sbloom 	register unsigned i;
92821955Sbloom 
92921955Sbloom 	dmf = DMFL_UNIT(dev) ;
93021955Sbloom 	sc= &dmfl_softc[dmf];
93121955Sbloom 	if(sc->dmfl_state&ERROR) return(EIO);
93221955Sbloom 	ui= dmfinfo[dmf];
93321955Sbloom 	/* allocate unibus resources, will be released when io
93421955Sbloom 	 * operation is done
93521955Sbloom 	 */
93621955Sbloom 	sc->dmfl_info=
93721955Sbloom 	info=
93821955Sbloom 		uballoc(ui->ui_ubanum,cp,n,0);
93921955Sbloom 	d= (struct dmfdevice *)ui->ui_addr;
94021955Sbloom 	d->dmfl[0] = (2<<8) | DMFL_FORMAT; /* indir reg 2 */
94121955Sbloom 	/* indir reg auto increments on r/w */
94221955Sbloom 	/* SO DON'T CHANGE THE ORDER OF THIS CODE */
94321955Sbloom 	d->dmfl[1] = 0; /* prefix chars & num */
94421955Sbloom 	d->dmfl[1] = 0; /* suffix chars & num */
94521955Sbloom 	d->dmfl[1] = info; 	/* dma lo 16 bits addr */
94621955Sbloom 
94721955Sbloom 	/* NOT DOCUMENTED !! */
94821955Sbloom 	d->dmfl[1] = -n;		/* number of chars */
94921955Sbloom 	/* ----------^-------- */
95021955Sbloom 
95121955Sbloom 	d->dmfl[1] = ((info>>16)&3) /* dma hi 2 bits addr */
95221955Sbloom 		| (1<<8) /* auto cr insert */
95321955Sbloom 		| (1<<9) /* use real ff */
95421955Sbloom 		| (1<<15); /* no u/l conversion */
95521955Sbloom 	d->dmfl[1] = sc->dmfl_lines 	/* lines per page */
95621955Sbloom 		| (sc->dmfl_cols<<8);	/* carriage width */
95721955Sbloom 	sc->dmfl_state |= ASLP;
95821955Sbloom 	i=spltty();
95921955Sbloom 	d->dmfl[0] |= DMFL_PEN|DMFL_IE;
96021955Sbloom 	while(sc->dmfl_state & ASLP)
96121955Sbloom 	{
96221955Sbloom 		sleep(&sc->dmfl_buf[0],(PZERO+8));
96321955Sbloom 		while(sc->dmfl_state&ERROR)
96421955Sbloom 		{
96521955Sbloom 			timeout(dmflint,dmf,10*hz);
96621955Sbloom 			sleep(&sc->dmfl_state,(PZERO+8));
96721955Sbloom 		}
96821955Sbloom 		/*if(sc->dmfl_state&ERROR) return (EIO);*/
96921955Sbloom 	}
97021955Sbloom 	splx(i);
97121955Sbloom 	return(0);
97221955Sbloom }
97321955Sbloom /* dmflint -- handle an interrupt from the line printer part of the dmf32
97421955Sbloom  *
97521955Sbloom  */
97621955Sbloom 
97721955Sbloom dmflint(dmf)
97821955Sbloom int dmf;
97921955Sbloom {
98021955Sbloom 
98121955Sbloom 	register struct uba_device *ui;
98221955Sbloom 	register struct dmfl_softc *sc;
98321955Sbloom 	register struct dmfdevice *d;
98421955Sbloom 
98521955Sbloom 	ui= dmfinfo[dmf];
98621955Sbloom 	sc= &dmfl_softc[dmf];
98721955Sbloom 	d= (struct dmfdevice *)ui->ui_addr;
98821955Sbloom 
98921955Sbloom 	d->dmfl[0] &= ~DMFL_IE;
99021955Sbloom 
99121955Sbloom 	if(sc->dmfl_state&ERROR)
99221955Sbloom 	{
99321955Sbloom 		printf("dmfl: intr while in error state \n");
99421955Sbloom 		if((d->dmfl[0]&DMFL_OFFLINE) == 0)
99521955Sbloom 			sc->dmfl_state &= ~ERROR;
99621955Sbloom 		wakeup(&sc->dmfl_state);
99721955Sbloom 		return;
99821955Sbloom 	}
99921955Sbloom 	if(d->dmfl[0]&DMFL_DMAERR)
100021955Sbloom 	{
100121955Sbloom 		printf("dmf:NXM\n");
100221955Sbloom 	}
100321955Sbloom 	if(d->dmfl[0]&DMFL_OFFLINE)
100421955Sbloom 	{
100521955Sbloom 		printf("dmf:printer error\n");
100621955Sbloom 		sc->dmfl_state |= ERROR;
100721955Sbloom 	}
100821955Sbloom 	if(d->dmfl[0]&DMFL_PDONE)
100921955Sbloom 	{
101021955Sbloom #ifdef notdef
101121955Sbloom 		printf("bytes= %d\n",d->dmfl[1]);
101221955Sbloom 		printf("lines= %d\n",d->dmfl[1]);
101321955Sbloom #endif
101421955Sbloom 	}
101521955Sbloom 	sc->dmfl_state &= ~ASLP;
101621955Sbloom 	wakeup(&sc->dmfl_buf[0]);
101721955Sbloom 	if(sc->dmfl_info != 0)
101821955Sbloom 		ubarelse(ui->ui_ubanum,&sc->dmfl_info);
101921955Sbloom 	sc->dmfl_info = 0;
102021955Sbloom 
102121955Sbloom }
102221955Sbloom 
10236940Ssam /* stubs for interrupt routines for devices not yet supported */
10246940Ssam 
10256940Ssam dmfsrint() { printf("dmfsrint\n"); }
10266940Ssam 
10276940Ssam dmfsxint() { printf("dmfsxint\n"); }
10286940Ssam 
10296940Ssam dmfdaint() { printf("dmfdaint\n"); }
10306940Ssam 
10316940Ssam dmfdbint() { printf("dmfdbint\n"); }
10326940Ssam 
103321955Sbloom 
10346940Ssam #endif
1035