xref: /csrg-svn/sys/vax/uba/dmf.c (revision 21955)
1*21955Sbloom /*	dmf.c	6.6	85/06/04	*/
26940Ssam 
36940Ssam #include "dmf.h"
46940Ssam #if NDMF > 0
56940Ssam /*
66940Ssam  * DMF32 driver
76940Ssam  *
8*21955Sbloom  *
96940Ssam  * TODO:
106940Ssam  *	test with modem
116940Ssam  *	load as much as possible into silo
126940Ssam  *	use auto XON/XOFF
136940Ssam  *	test reset code
14*21955Sbloom  ****************************
15*21955Sbloom  * DMF32 line printer driver
16*21955Sbloom  *
17*21955Sbloom  * the line printer on dmfx is indicated by a minor device code of 128+x
18*21955Sbloom  *
19*21955Sbloom  * the flags field of the config file is interpreted like so:
20*21955Sbloom  * bits		meaning
21*21955Sbloom  * ----		-------
22*21955Sbloom  * 0-7		soft carrier bits for ttys part of dmf32
23*21955Sbloom  * 8-15		number of cols/line on the line printer
24*21955Sbloom  *			if 0, 132 will be used.
25*21955Sbloom  * 16-23	number of lines/page on the line printer
26*21955Sbloom  *			if 0, 66 will be used.
27*21955Sbloom  *
286940Ssam  */
299772Ssam #include "../machine/pte.h"
309772Ssam 
316940Ssam #include "bk.h"
3216063Skarels #include "uba.h"
3317124Sbloom #include "param.h"
3417124Sbloom #include "conf.h"
3517124Sbloom #include "dir.h"
3617124Sbloom #include "user.h"
3717124Sbloom #include "ioctl.h"
3817124Sbloom #include "tty.h"
3917124Sbloom #include "map.h"
4017124Sbloom #include "buf.h"
4117124Sbloom #include "vm.h"
4217124Sbloom #include "bkmac.h"
4317124Sbloom #include "clist.h"
4417124Sbloom #include "file.h"
4517124Sbloom #include "uio.h"
46*21955Sbloom #include "kernel.h"
4718312Sralph #include "syslog.h"
486940Ssam 
4917124Sbloom #include "ubareg.h"
5017124Sbloom #include "ubavar.h"
5117124Sbloom #include "dmfreg.h"
528473Sroot 
536940Ssam /*
546940Ssam  * Definition of the driver for the auto-configuration program.
556940Ssam  */
566940Ssam int	dmfprobe(), dmfattach(), dmfrint(), dmfxint();
57*21955Sbloom int	dmflint();
586940Ssam struct	uba_device *dmfinfo[NDMF];
596940Ssam u_short	dmfstd[] = { 0 };
606940Ssam struct	uba_driver dmfdriver =
616940Ssam 	{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
626940Ssam 
63*21955Sbloom int	dmf_timeout = 50;		/* silo timeout, in ms */
64*21955Sbloom int	dmf_mindma = 4;			/* don't dma below this point */
65*21955Sbloom 
666940Ssam /*
676940Ssam  * Local variables for the driver
686940Ssam  */
696940Ssam char	dmf_speeds[] =
706940Ssam 	{ 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
716940Ssam 
726940Ssam struct	tty dmf_tty[NDMF*8];
736940Ssam char	dmfsoftCAR[NDMF];
74*21955Sbloom 
75*21955Sbloom struct dmfl_softc
76*21955Sbloom {
77*21955Sbloom 	unsigned dmfl_state; 		/* soft state bits */
78*21955Sbloom 	unsigned dmfl_info;		/* uba info */
79*21955Sbloom 	unsigned short dmfl_lines;	/* lines per page (66 def.) */
80*21955Sbloom 	unsigned short dmfl_cols; 	/* cols per line (132 def.) */
81*21955Sbloom 	char dmfl_buf[DMFL_BUFSIZ];
82*21955Sbloom } dmfl_softc[NDMF];
83*21955Sbloom 
84*21955Sbloom /*
85*21955Sbloom  * convert device number into DMF line printer unit number
86*21955Sbloom  */
87*21955Sbloom #define	DMFL_UNIT(d)	(minor(d)&0xF)	/* up to 16 DMFs */
88*21955Sbloom 
89*21955Sbloom #define ASLP 1		/* waiting for interrupt from dmf */
90*21955Sbloom #define OPEN 2		/* line printer is open */
91*21955Sbloom #define ERROR 4		/* error while printing, driver
92*21955Sbloom 			 refuses to do anything till closed */
93*21955Sbloom 
948778Sroot #ifndef lint
958778Sroot int	ndmf = NDMF*8;			/* used by iostat */
968778Sroot #endif
976940Ssam int	dmfact;				/* mask of active dmf's */
986940Ssam int	dmfstart(), ttrstrt();
996940Ssam 
1006940Ssam /*
1016940Ssam  * The clist space is mapped by the driver onto each UNIBUS.
1026940Ssam  * The UBACVT macro converts a clist space address for unibus uban
1036940Ssam  * into an i/o space address for the DMA routine.
1046940Ssam  */
10516063Skarels int	dmf_ubinfo[NUBA];		/* info about allocated unibus map */
10616063Skarels static int cbase[NUBA];			/* base address in unibus map */
1076940Ssam #define	UBACVT(x, uban)		(cbase[uban] + ((x)-(char *)cfree))
108*21955Sbloom char	dmf_dma[NDMF*8];
1096940Ssam 
1106940Ssam /*
1116940Ssam  * Routine for configuration to set dmf interrupt.
1126940Ssam  */
1136940Ssam /*ARGSUSED*/
1146940Ssam dmfprobe(reg, ctlr)
1156940Ssam 	caddr_t reg;
116*21955Sbloom 	struct uba_device *ctlr;
1176940Ssam {
1186940Ssam 	register int br, cvec;		/* these are ``value-result'' */
1196940Ssam 	register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
120*21955Sbloom 	register int i;
121*21955Sbloom 	register unsigned int a;
122*21955Sbloom 	static char *dmfdevs[]=
123*21955Sbloom 		{"parallel","printer","synch","asynch"};
124*21955Sbloom 	unsigned int dmfoptions;
1256940Ssam 
1266940Ssam #ifdef lint
1276940Ssam 	br = 0; cvec = br; br = cvec;
1288808Sroot 	dmfxint(0); dmfrint(0);
1298808Sroot 	dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint();
1306940Ssam #endif
131*21955Sbloom 	/*
132*21955Sbloom 	 * Pick the usual size DMF vector here (don't decrement it here).
133*21955Sbloom 	 * grab configuration; note that the DMF32
134*21955Sbloom 	 * doesn't seem to put the right bits in this
135*21955Sbloom 	 * register until AFTER the interrupt vector is set.
136*21955Sbloom 	 */
1376940Ssam 	br = 0x15;
138*21955Sbloom 	cvec = (uba_hd[numuba].uh_lastiv - 4*8);
139*21955Sbloom 	dmfaddr->dmfccsr0 = (cvec >> 2) ;
140*21955Sbloom 	dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
141*21955Sbloom 
142*21955Sbloom 	/* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
143*21955Sbloom 	if (dmfoptions == DMFC_ASYNC) {
144*21955Sbloom 		/* Async portion only  -  vmz/32n */
145*21955Sbloom 		/* device dmf0 csr 0160400	vector dmfrint dmfxint  */
146*21955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 8);	/* only 8 bytes req'd */
147*21955Sbloom 		dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;	/* program 020 less   */
148*21955Sbloom 		printf("dmf%d: Able vmz32/n\n", ctlr->ui_unit);
149*21955Sbloom 	}
150*21955Sbloom 	else if (dmfoptions == DMFC_LP) {
151*21955Sbloom 		/* LP portion only - vmz/lp */
152*21955Sbloom 		/* device dmf0 csr 0160400	vector dmflint */
153*21955Sbloom 
154*21955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 8);	/* only 8 bytes req'd */
155*21955Sbloom 		dmfaddr->dmfccsr0 = (cvec - 3*8) >> 2;	/* program 030 less   */
156*21955Sbloom 		printf("dmf%d: Able vmz/lp\n", ctlr->ui_unit);
157*21955Sbloom 	}
158*21955Sbloom 	else {
159*21955Sbloom 		/* anything else we program like a dec dmf32	*/
160*21955Sbloom 		/* device dmf0 vector dmfsrint dmfsxint dmfdaint dmfdbint dmfrint dmfxint dmflint */
161*21955Sbloom 
162*21955Sbloom 		cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
163*21955Sbloom 		dmfaddr->dmfccsr0 = (cvec >> 2) ;
164*21955Sbloom 		a = (dmfaddr->dmfccsr0>>12) & 0xf;
165*21955Sbloom 		printf("dmf%d:", ctlr->ui_unit);
166*21955Sbloom 		for(i=0;a != 0;++i,a >>= 1) {
167*21955Sbloom 			if(a&1)
168*21955Sbloom 				printf(" %s",dmfdevs[i]);
169*21955Sbloom 		}
170*21955Sbloom 		printf(".\n");
171*21955Sbloom 	}
172*21955Sbloom 
173*21955Sbloom 	if (dmfoptions & DMFC_LP)
174*21955Sbloom 		dmfaddr->dmfl[0] = DMFL_RESET;
1756940Ssam 	/* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */
1767412Skre 	return (sizeof (struct dmfdevice));
1776940Ssam }
1786940Ssam 
1796940Ssam /*
1806940Ssam  * Routine called to attach a dmf.
1816940Ssam  */
1826940Ssam dmfattach(ui)
1836940Ssam 	struct uba_device *ui;
1846940Ssam {
185*21955Sbloom 	register int cols = (ui->ui_flags>>8) & 0xff;
186*21955Sbloom 	register int lines = (ui->ui_flags>>16) & 0xff;
1876940Ssam 
188*21955Sbloom 	dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff;
189*21955Sbloom 	dmfl_softc[ui->ui_unit].dmfl_cols = cols==0?DMFL_DEFCOLS:cols;
190*21955Sbloom 	dmfl_softc[ui->ui_unit].dmfl_lines = lines==0?DMFL_DEFLINES:lines;
1916940Ssam }
1926940Ssam 
1936940Ssam 
1946940Ssam /*
1956940Ssam  * Open a DMF32 line, mapping the clist onto the uba if this
1966940Ssam  * is the first dmf on this uba.  Turn on this dmf if this is
1976940Ssam  * the first use of it.
1986940Ssam  */
1996940Ssam /*ARGSUSED*/
2006940Ssam dmfopen(dev, flag)
2016940Ssam 	dev_t dev;
2026940Ssam {
2036940Ssam 	register struct tty *tp;
2046940Ssam 	register int unit, dmf;
2056940Ssam 	register struct dmfdevice *addr;
2066940Ssam 	register struct uba_device *ui;
2076940Ssam 	int s;
2086940Ssam 
2096940Ssam 	unit = minor(dev);
210*21955Sbloom 	if(unit & 0200)
211*21955Sbloom 		return(dmflopen(dev,flag));
2126940Ssam 	dmf = unit >> 3;
2138567Sroot 	if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
2148567Sroot 		return (ENXIO);
2156940Ssam 	tp = &dmf_tty[unit];
2168567Sroot 	if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
2178567Sroot 		return (EBUSY);
2186940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
2196940Ssam 	tp->t_addr = (caddr_t)addr;
2206940Ssam 	tp->t_oproc = dmfstart;
2216971Ssam 	tp->t_state |= TS_WOPEN;
2226940Ssam 	/*
2236940Ssam 	 * While setting up state for this uba and this dmf,
2246940Ssam 	 * block uba resets which can clear the state.
2256940Ssam 	 */
226*21955Sbloom 	s = spltty();
2276940Ssam 	if (dmf_ubinfo[ui->ui_ubanum] == 0) {
2286940Ssam 		dmf_ubinfo[ui->ui_ubanum] =
2296940Ssam 		    uballoc(ui->ui_ubanum, (caddr_t)cfree,
2306940Ssam 			nclist*sizeof(struct cblock), 0);
2316940Ssam 		cbase[ui->ui_ubanum] = dmf_ubinfo[ui->ui_ubanum]&0x3ffff;
2326940Ssam 	}
2336940Ssam 	if ((dmfact&(1<<dmf)) == 0) {
2346940Ssam 		addr->dmfcsr |= DMF_IE;
2356940Ssam 		dmfact |= (1<<dmf);
236*21955Sbloom 		addr->dmfrsp = dmf_timeout;
2376940Ssam 	}
2386940Ssam 	splx(s);
2396940Ssam 	/*
2406940Ssam 	 * If this is first open, initialze tty state to default.
2416940Ssam 	 */
2426971Ssam 	if ((tp->t_state&TS_ISOPEN) == 0) {
2436940Ssam 		ttychars(tp);
2446940Ssam 		if (tp->t_ispeed == 0) {
2456940Ssam 			tp->t_ispeed = B300;
2466940Ssam 			tp->t_ospeed = B300;
2476940Ssam 			tp->t_flags = ODDP|EVENP|ECHO;
2486940Ssam 		}
2496940Ssam 		dmfparam(unit);
2506940Ssam 	}
2516940Ssam 	/*
2526940Ssam 	 * Wait for carrier, then process line discipline specific open.
2536940Ssam 	 */
2546940Ssam 	if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
2556940Ssam 	    (dmfsoftCAR[dmf] & (1<<(unit&07))))
2566971Ssam 		tp->t_state |= TS_CARR_ON;
257*21955Sbloom 	s = spltty();
2586971Ssam 	while ((tp->t_state & TS_CARR_ON) == 0) {
2596971Ssam 		tp->t_state |= TS_WOPEN;
2606940Ssam 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
2616940Ssam 	}
2626940Ssam 	splx(s);
2638567Sroot 	return ((*linesw[tp->t_line].l_open)(dev, tp));
2646940Ssam }
2656940Ssam 
2666940Ssam /*
2676940Ssam  * Close a DMF32 line.
2686940Ssam  */
2696940Ssam /*ARGSUSED*/
2706940Ssam dmfclose(dev, flag)
2716940Ssam 	dev_t dev;
2726940Ssam 	int flag;
2736940Ssam {
2746940Ssam 	register struct tty *tp;
2756940Ssam 	register unit;
2766940Ssam 
2776940Ssam 	unit = minor(dev);
278*21955Sbloom 	if(unit & 0200)
279*21955Sbloom 		return(dmflclose(dev,flag));
280*21955Sbloom 
2816940Ssam 	tp = &dmf_tty[unit];
2826940Ssam 	(*linesw[tp->t_line].l_close)(tp);
2838702Sroot 	(void) dmfmctl(unit, DMF_BRK, DMBIC);
2846971Ssam 	if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
2858702Sroot 		(void) dmfmctl(unit, DMF_OFF, DMSET);
2866940Ssam 	ttyclose(tp);
2876940Ssam }
2886940Ssam 
2897726Sroot dmfread(dev, uio)
2906940Ssam 	dev_t dev;
2917726Sroot 	struct uio *uio;
2926940Ssam {
2936940Ssam 	register struct tty *tp;
2946940Ssam 
295*21955Sbloom 	if(minor(dev)&0200)
296*21955Sbloom 		return(ENXIO);
2976940Ssam 	tp = &dmf_tty[minor(dev)];
2987726Sroot 	return ((*linesw[tp->t_line].l_read)(tp, uio));
2996940Ssam }
3006940Ssam 
3017832Sroot dmfwrite(dev, uio)
3026940Ssam 	dev_t dev;
3037832Sroot 	struct uio *uio;
3046940Ssam {
3056940Ssam 	register struct tty *tp;
3066940Ssam 
307*21955Sbloom 	if(minor(dev)&0200)
308*21955Sbloom 		return(dmflwrite(dev,uio));
3096940Ssam 	tp = &dmf_tty[minor(dev)];
3108530Sroot 	return ((*linesw[tp->t_line].l_write)(tp, uio));
3116940Ssam }
3126940Ssam 
3136940Ssam /*
3146940Ssam  * DMF32 receiver interrupt.
3156940Ssam  */
3166940Ssam dmfrint(dmf)
3176940Ssam 	int dmf;
3186940Ssam {
3196940Ssam 	register c;
3206940Ssam 	register struct dmfdevice *addr;
3216940Ssam 	register struct tty *tp0;
322*21955Sbloom 	register dev;
323*21955Sbloom 	int unit;
32412449Ssam 	int overrun = 0, s;
3256940Ssam 
326*21955Sbloom 	{
327*21955Sbloom 		register struct uba_device *ui;
328*21955Sbloom 
329*21955Sbloom 		ui = dmfinfo[dmf];
330*21955Sbloom 		if (ui == 0 || ui->ui_alive == 0)
331*21955Sbloom 			return;
332*21955Sbloom 		addr = (struct dmfdevice *)ui->ui_addr;
333*21955Sbloom 	}
334*21955Sbloom 	tp0 = &dmf_tty[dmf * 8];
3356940Ssam 	/*
3366940Ssam 	 * Loop fetching characters from the silo for this
3376940Ssam 	 * dmf until there are no more in the silo.
3386940Ssam 	 */
3396940Ssam 	while ((c = addr->dmfrbuf) < 0) {
340*21955Sbloom 		register struct tty *tp;
341*21955Sbloom 
342*21955Sbloom 		unit = (c >> 8) & 07;
343*21955Sbloom 		tp = tp0 + unit;
344*21955Sbloom 		dev = unit + dmf * 8;
3456940Ssam 		if (c & DMF_DSC) {
346*21955Sbloom 			s = spltty();
347*21955Sbloom 			addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
3486940Ssam 			if (addr->dmfrms & DMF_CAR) {
3496971Ssam 				if ((tp->t_state & TS_CARR_ON) == 0) {
3506940Ssam 					wakeup((caddr_t)&tp->t_rawq);
3516971Ssam 					tp->t_state |= TS_CARR_ON;
3526940Ssam 				}
3536940Ssam 			} else {
3546971Ssam 				if (tp->t_state & TS_CARR_ON) {
3556940Ssam 					gsignal(tp->t_pgrp, SIGHUP);
3566940Ssam 					gsignal(tp->t_pgrp, SIGCONT);
3576940Ssam 					addr->dmfcsr = DMF_IE | DMFIR_LCR |
358*21955Sbloom 						unit;
3596940Ssam 					addr->dmftms = 0;
36012776Ssam 					ttyflush(tp, FREAD|FWRITE);
3616940Ssam 				}
3626971Ssam 				tp->t_state &= ~TS_CARR_ON;
3636940Ssam 			}
36412449Ssam 			splx(s);
3656940Ssam 			continue;
3666940Ssam 		}
3676971Ssam 		if ((tp->t_state&TS_ISOPEN)==0) {
3686940Ssam 			wakeup((caddr_t)tp);
3696940Ssam 			continue;
3706940Ssam 		}
371*21955Sbloom 		if(c & (DMF_PE|DMF_DO|DMF_FE)) {
372*21955Sbloom 			if (c & DMF_PE)
373*21955Sbloom 				if ((tp->t_flags&(EVENP|ODDP))==EVENP
374*21955Sbloom 			 	|| (tp->t_flags&(EVENP|ODDP))==ODDP )
375*21955Sbloom 					continue;
376*21955Sbloom 			if ((c & DMF_DO) && overrun == 0) {
377*21955Sbloom 				log(KERN_RECOV, "dmf%d: silo overflow\n", dmf);
378*21955Sbloom 				overrun = 1;
379*21955Sbloom 			}
380*21955Sbloom 			if (c & DMF_FE)
381*21955Sbloom 				/*
382*21955Sbloom 			 	* At framing error (break) generate
383*21955Sbloom 			 	* a null (in raw mode, for getty), or a
384*21955Sbloom 			 	* interrupt (in cooked/cbreak mode).
385*21955Sbloom 			 	*/
386*21955Sbloom 				if (tp->t_flags&RAW)
387*21955Sbloom 					c = 0;
388*21955Sbloom 				else
389*21955Sbloom 					c = tp->t_intrc;
3906940Ssam 		}
3916940Ssam #if NBK > 0
3926940Ssam 		if (tp->t_line == NETLDISC) {
3936940Ssam 			c &= 0177;
3946940Ssam 			BKINPUT(c, tp);
3956940Ssam 		} else
3966940Ssam #endif
3976940Ssam 			(*linesw[tp->t_line].l_rint)(c, tp);
3986940Ssam 	}
3996940Ssam }
4006940Ssam 
4016940Ssam /*
4026940Ssam  * Ioctl for DMF32.
4036940Ssam  */
4046940Ssam /*ARGSUSED*/
4057630Ssam dmfioctl(dev, cmd, data, flag)
4066940Ssam 	dev_t dev;
4077630Ssam 	caddr_t data;
4086940Ssam {
4096940Ssam 	register struct tty *tp;
4106940Ssam 	register int unit = minor(dev);
4118567Sroot 	int error;
4126940Ssam 
413*21955Sbloom 	if(unit & 0200)
414*21955Sbloom 		return (ENOTTY);
4156940Ssam 	tp = &dmf_tty[unit];
4168567Sroot 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
4178567Sroot 	if (error >= 0)
4188567Sroot 		return (error);
4198567Sroot 	error = ttioctl(tp, cmd, data, flag);
4208567Sroot 	if (error >= 0) {
42117562Sbloom 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
42217562Sbloom 		    cmd == TIOCLBIC || cmd == TIOCLSET)
4236940Ssam 			dmfparam(unit);
4248567Sroot 		return (error);
4258567Sroot 	}
4268567Sroot 	switch (cmd) {
4276940Ssam 
4286940Ssam 	case TIOCSBRK:
4298702Sroot 		(void) dmfmctl(dev, DMF_BRK, DMBIS);
4306940Ssam 		break;
4317630Ssam 
4326940Ssam 	case TIOCCBRK:
4338702Sroot 		(void) dmfmctl(dev, DMF_BRK, DMBIC);
4346940Ssam 		break;
4357630Ssam 
4366940Ssam 	case TIOCSDTR:
4378702Sroot 		(void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
4386940Ssam 		break;
4397630Ssam 
4406940Ssam 	case TIOCCDTR:
4418702Sroot 		(void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
4426940Ssam 		break;
4437630Ssam 
4446940Ssam 	case TIOCMSET:
4458702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
4466940Ssam 		break;
4477630Ssam 
4486940Ssam 	case TIOCMBIS:
4498702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
4506940Ssam 		break;
4517630Ssam 
4526940Ssam 	case TIOCMBIC:
4538702Sroot 		(void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
4546940Ssam 		break;
4557630Ssam 
4566940Ssam 	case TIOCMGET:
4577630Ssam 		*(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
4586940Ssam 		break;
4597630Ssam 
4606940Ssam 	default:
4618567Sroot 		return (ENOTTY);
4626940Ssam 	}
4638567Sroot 	return (0);
4646940Ssam }
4656940Ssam 
4666940Ssam dmtodmf(bits)
4676940Ssam 	register int bits;
4686940Ssam {
4696940Ssam 	register int b;
4706940Ssam 
4716940Ssam 	b = bits & 012;
4726940Ssam 	if (bits & DML_ST) b |= DMF_RATE;
4736940Ssam 	if (bits & DML_RTS) b |= DMF_RTS;
4746940Ssam 	if (bits & DML_USR) b |= DMF_USRW;
4756940Ssam 	return(b);
4766940Ssam }
4776940Ssam 
4786940Ssam dmftodm(bits)
4796940Ssam 	register int bits;
4806940Ssam {
4816940Ssam 	register int b;
4826940Ssam 
4836940Ssam 	b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
4846940Ssam 	if (bits & DMF_USRR) b |= DML_USR;
4856940Ssam 	if (bits & DMF_RTS) b |= DML_RTS;
4866940Ssam 	return(b);
4876940Ssam }
4886940Ssam 
4896940Ssam 
4906940Ssam /*
4916940Ssam  * Set parameters from open or stty into the DMF hardware
4926940Ssam  * registers.
4936940Ssam  */
4946940Ssam dmfparam(unit)
4956940Ssam 	register int unit;
4966940Ssam {
4976940Ssam 	register struct tty *tp;
4986940Ssam 	register struct dmfdevice *addr;
4996940Ssam 	register int lpar, lcr;
5006940Ssam 	int s;
5016940Ssam 
5026940Ssam 	tp = &dmf_tty[unit];
5036940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
5046940Ssam 	/*
5056940Ssam 	 * Block interrupts so parameters will be set
5066940Ssam 	 * before the line interrupts.
5076940Ssam 	 */
508*21955Sbloom 	s = spltty();
5096940Ssam 	addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
5106940Ssam 	if ((tp->t_ispeed)==0) {
5116971Ssam 		tp->t_state |= TS_HUPCLS;
5128702Sroot 		(void) dmfmctl(unit, DMF_OFF, DMSET);
5136940Ssam 		return;
5146940Ssam 	}
5156940Ssam 	lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
5166940Ssam 	lcr = DMFLCR_ENA;
5176940Ssam 	if ((tp->t_ispeed) == B134)
5186940Ssam 		lpar |= BITS6|PENABLE;
5199550Ssam 	else if (tp->t_flags & (RAW|LITOUT))
5206940Ssam 		lpar |= BITS8;
5216940Ssam 	else {
5226940Ssam 		lpar |= BITS7|PENABLE;
5236940Ssam 		/* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
5246940Ssam 	}
52512450Ssam 	if (tp->t_flags&EVENP)
52612450Ssam 		lpar |= EPAR;
5276940Ssam 	if ((tp->t_ospeed) == B110)
5286940Ssam 		lpar |= TWOSB;
5296940Ssam 	lpar |= (unit&07);
5306940Ssam 	addr->dmflpr = lpar;
53112449Ssam 	SETLCR(addr, lcr);
5326940Ssam 	splx(s);
5336940Ssam }
5346940Ssam 
5356940Ssam /*
5366940Ssam  * DMF32 transmitter interrupt.
5376940Ssam  * Restart the idle line.
5386940Ssam  */
5396940Ssam dmfxint(dmf)
5406940Ssam 	int dmf;
5416940Ssam {
542*21955Sbloom 	int u = dmf * 8;
543*21955Sbloom 	struct tty *tp0 = &dmf_tty[u];
5446940Ssam 	register struct tty *tp;
5456940Ssam 	register struct dmfdevice *addr;
5466940Ssam 	register struct uba_device *ui;
547*21955Sbloom 	register int t;
5486940Ssam 	short cntr;
5496940Ssam 
5506940Ssam 	ui = dmfinfo[dmf];
5516940Ssam 	addr = (struct dmfdevice *)ui->ui_addr;
5526940Ssam 	while ((t = addr->dmfcsr) & DMF_TI) {
553*21955Sbloom 		if (t & DMF_NXM)
554*21955Sbloom 			/* SHOULD RESTART OR SOMETHING... */
555*21955Sbloom 			printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
556*21955Sbloom 		t = t >> 8 & 7;
557*21955Sbloom 		tp = tp0 + t;
5586971Ssam 		tp->t_state &= ~TS_BUSY;
5596971Ssam 		if (tp->t_state&TS_FLUSH)
5606971Ssam 			tp->t_state &= ~TS_FLUSH;
561*21955Sbloom 		else if (dmf_dma[u + t]) {
562*21955Sbloom 			/*
563*21955Sbloom 			 * Do arithmetic in a short to make up
564*21955Sbloom 			 * for lost 16&17 bits.
565*21955Sbloom 			 */
566*21955Sbloom 			addr->dmfcsr = DMFIR_TBA | DMF_IE | t;
567*21955Sbloom 			cntr = addr->dmftba -
568*21955Sbloom 			    UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
569*21955Sbloom 			ndflush(&tp->t_outq, (int)cntr);
5706940Ssam 		}
5716940Ssam 		if (tp->t_line)
5726940Ssam 			(*linesw[tp->t_line].l_start)(tp);
5736940Ssam 		else
5746940Ssam 			dmfstart(tp);
5756940Ssam 	}
5766940Ssam }
5776940Ssam 
5786940Ssam /*
5796940Ssam  * Start (restart) transmission on the given DMF32 line.
5806940Ssam  */
5816940Ssam dmfstart(tp)
5826940Ssam 	register struct tty *tp;
5836940Ssam {
5846940Ssam 	register struct dmfdevice *addr;
5858607Sroot 	register int unit, nch;
5866940Ssam 	int s;
587*21955Sbloom 	register int dmf;
5886940Ssam 
5896940Ssam 	unit = minor(tp->t_dev);
590*21955Sbloom 	dmf = unit >> 3;
5916940Ssam 	unit &= 07;
5926940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
5936940Ssam 
5946940Ssam 	/*
5956940Ssam 	 * Must hold interrupts in following code to prevent
5966940Ssam 	 * state of the tp from changing.
5976940Ssam 	 */
598*21955Sbloom 	s = spltty();
5996940Ssam 	/*
6006940Ssam 	 * If it's currently active, or delaying, no need to do anything.
6016940Ssam 	 */
6026971Ssam 	if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
6036940Ssam 		goto out;
6046940Ssam 	/*
6056940Ssam 	 * If there are still characters in the silo,
6066940Ssam 	 * just reenable the transmitter.
6076940Ssam 	 */
6086940Ssam 	addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
6096940Ssam 	if (addr->dmftsc) {
6106940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
61112449Ssam 		SETLCR(addr, addr->dmflcr|DMF_TE);
6126971Ssam 		tp->t_state |= TS_BUSY;
6136940Ssam 		goto out;
6146940Ssam 	}
6156940Ssam 	/*
6166940Ssam 	 * If there are sleepers, and output has drained below low
6176940Ssam 	 * water mark, wake up the sleepers.
6186940Ssam 	 */
619*21955Sbloom 	if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
620*21955Sbloom 		if (tp->t_state&TS_ASLEEP) {
621*21955Sbloom 			tp->t_state &= ~TS_ASLEEP;
622*21955Sbloom 			wakeup((caddr_t)&tp->t_outq);
623*21955Sbloom 		}
624*21955Sbloom 		if (tp->t_wsel) {
625*21955Sbloom 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
626*21955Sbloom 			tp->t_wsel = 0;
627*21955Sbloom 			tp->t_state &= ~TS_WCOLL;
628*21955Sbloom 		}
6296940Ssam 	}
6306940Ssam 	/*
6316940Ssam 	 * Now restart transmission unless the output queue is
6326940Ssam 	 * empty.
6336940Ssam 	 */
6346940Ssam 	if (tp->t_outq.c_cc == 0)
6356940Ssam 		goto out;
6369550Ssam 	if (tp->t_flags & (RAW|LITOUT))
6376940Ssam 		nch = ndqb(&tp->t_outq, 0);
6386940Ssam 	else {
639*21955Sbloom 		if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
640*21955Sbloom 			/*
641*21955Sbloom 		 	* If first thing on queue is a delay process it.
642*21955Sbloom 		 	*/
6436940Ssam 			nch = getc(&tp->t_outq);
6446940Ssam 			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
6456971Ssam 			tp->t_state |= TS_TIMEOUT;
6466940Ssam 			goto out;
6476940Ssam 		}
6486940Ssam 	}
6496940Ssam 	/*
6506940Ssam 	 * If characters to transmit, restart transmission.
6516940Ssam 	 */
652*21955Sbloom 	if (nch >= dmf_mindma) {
653*21955Sbloom 		register car;
654*21955Sbloom 
655*21955Sbloom 		dmf_dma[minor(tp->t_dev)] = 1;
6566940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
65712449Ssam 		SETLCR(addr, addr->dmflcr|DMF_TE);
6586940Ssam 		car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
6596940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
6606940Ssam 		addr->dmftba = car;
661*21955Sbloom 		addr->dmftcc = ((car >> 2) & 0xc000) | nch;
662*21955Sbloom 		tp->t_state |= TS_BUSY;
663*21955Sbloom 	} else if (nch) {
6646940Ssam 		register char *cp = tp->t_outq.c_cf;
6656940Ssam 		register int i;
6666940Ssam 
667*21955Sbloom 		dmf_dma[minor(tp->t_dev)] = 0;
6686940Ssam 		nch = MIN(nch, DMF_SILOCNT);
6696940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
67012449Ssam 		SETLCR(addr, addr->dmflcr|DMF_TE);
6716940Ssam 		addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
6726940Ssam 		for (i = 0; i < nch; i++)
6736940Ssam 			addr->dmftbuf = *cp++;
6746940Ssam 		ndflush(&tp->t_outq, nch);
6756971Ssam 		tp->t_state |= TS_BUSY;
6766940Ssam 	}
6776940Ssam out:
6786940Ssam 	splx(s);
6796940Ssam }
6806940Ssam 
6816940Ssam /*
6826940Ssam  * Stop output on a line, e.g. for ^S/^Q or output flush.
6836940Ssam  */
6846940Ssam /*ARGSUSED*/
6856940Ssam dmfstop(tp, flag)
6866940Ssam 	register struct tty *tp;
6876940Ssam {
6886940Ssam 	register struct dmfdevice *addr;
689*21955Sbloom 	register unit = minor(tp->t_dev) & 7;
690*21955Sbloom 	int s;
6916940Ssam 
6926940Ssam 	addr = (struct dmfdevice *)tp->t_addr;
6936940Ssam 	/*
6946940Ssam 	 * Block input/output interrupts while messing with state.
6956940Ssam 	 */
696*21955Sbloom 	s = spltty();
697*21955Sbloom 	if (flag) {
698*21955Sbloom 		addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
699*21955Sbloom 		if (addr->dmftsc) {
700*21955Sbloom 			/*
701*21955Sbloom 			 * Flush regardless of whether we're transmitting
702*21955Sbloom 			 * (TS_BUSY), if the silo contains untransmitted
703*21955Sbloom 			 * characters.
704*21955Sbloom 			 */
705*21955Sbloom 			addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
706*21955Sbloom 			SETLCR(addr, addr->dmflcr | DMF_TE | DMF_FLUSH);
707*21955Sbloom 			/* this will interrupt so let dmfxint handle the rest */
708*21955Sbloom 			tp->t_state |= TS_FLUSH|TS_BUSY;
709*21955Sbloom 		}
710*21955Sbloom 	} else {
711*21955Sbloom 		if (tp->t_state & TS_BUSY) {
712*21955Sbloom 			/*
713*21955Sbloom 			 * Stop transmission by disabling
714*21955Sbloom 			 * the transmitter.  We'll pick up where we
715*21955Sbloom 			 * left off by reenabling in dmfstart.
716*21955Sbloom 			 */
717*21955Sbloom 			addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
718*21955Sbloom 			SETLCR(addr, addr->dmflcr &~ DMF_TE);
719*21955Sbloom 			/* no interrupt here */
7206971Ssam 			tp->t_state &= ~TS_BUSY;
721*21955Sbloom 		}
7226940Ssam 	}
7236940Ssam 	splx(s);
7246940Ssam }
7256940Ssam 
7266940Ssam /*
7276940Ssam  * DMF32 modem control
7286940Ssam  */
7296940Ssam dmfmctl(dev, bits, how)
7306940Ssam 	dev_t dev;
7316940Ssam 	int bits, how;
7326940Ssam {
7336940Ssam 	register struct dmfdevice *dmfaddr;
7346940Ssam 	register int unit, mbits, lcr;
7356940Ssam 	int s;
7366940Ssam 
7376940Ssam 	unit = minor(dev);
7386940Ssam 	dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
7396940Ssam 	unit &= 07;
740*21955Sbloom 	s = spltty();
7416940Ssam 	dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
7426940Ssam 	mbits = dmfaddr->dmfrms << 8;
7436940Ssam 	dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
7446940Ssam 	mbits |= dmfaddr->dmftms;
7456940Ssam 	lcr = dmfaddr->dmflcr;
7466940Ssam 	switch (how) {
7476940Ssam 	case DMSET:
74812449Ssam 		mbits = (mbits &0xff00) | bits;
7496940Ssam 		break;
7506940Ssam 
7516940Ssam 	case DMBIS:
7526940Ssam 		mbits |= bits;
7536940Ssam 		break;
7546940Ssam 
7556940Ssam 	case DMBIC:
7566940Ssam 		mbits &= ~bits;
7576940Ssam 		break;
7586940Ssam 
7596940Ssam 	case DMGET:
7606940Ssam 		(void) splx(s);
7616940Ssam 		return(mbits);
7626940Ssam 	}
7636940Ssam 	if (mbits & DMF_BRK)
7646940Ssam 		lcr |= DMF_RBRK;
7656940Ssam 	else
7666940Ssam 		lcr &= ~DMF_RBRK;
76712449Ssam 	lcr = ((mbits & 037) << 8) | (lcr & 0xff);
76812449Ssam 	dmfaddr->dmfun.dmfirw = lcr;
7696940Ssam 	(void) splx(s);
7706940Ssam 	return(mbits);
7716940Ssam }
7726940Ssam 
7736940Ssam /*
7746940Ssam  * Reset state of driver if UBA reset was necessary.
7756940Ssam  * Reset the csr, lpr, and lcr registers on open lines, and
7766940Ssam  * restart transmitters.
7776940Ssam  */
7786940Ssam dmfreset(uban)
7796940Ssam 	int uban;
7806940Ssam {
7816940Ssam 	register int dmf, unit;
7826940Ssam 	register struct tty *tp;
7836940Ssam 	register struct uba_device *ui;
7846940Ssam 	register struct dmfdevice *addr;
7856940Ssam 	int i;
7866940Ssam 
7876940Ssam 	if (dmf_ubinfo[uban] == 0)
7886940Ssam 		return;
7896940Ssam 	dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
7906940Ssam 	    nclist*sizeof (struct cblock), 0);
7916940Ssam 	cbase[uban] = dmf_ubinfo[uban]&0x3ffff;
7926940Ssam 	for (dmf = 0; dmf < NDMF; dmf++) {
7936940Ssam 		ui = dmfinfo[dmf];
7946940Ssam 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
7956940Ssam 			continue;
7966940Ssam 		printf(" dmf%d", dmf);
7976940Ssam 		addr = (struct dmfdevice *)ui->ui_addr;
7986940Ssam 		addr->dmfcsr = DMF_IE;
799*21955Sbloom 		addr->dmfrsp = dmf_timeout;
8006940Ssam 		unit = dmf * 8;
8016940Ssam 		for (i = 0; i < 8; i++) {
8026940Ssam 			tp = &dmf_tty[unit];
8036971Ssam 			if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
8046940Ssam 				dmfparam(unit);
8058702Sroot 				(void) dmfmctl(unit, DMF_ON, DMSET);
8066971Ssam 				tp->t_state &= ~TS_BUSY;
8076940Ssam 				dmfstart(tp);
8086940Ssam 			}
8096940Ssam 			unit++;
8106940Ssam 		}
8116940Ssam 	}
8126940Ssam }
8136940Ssam 
814*21955Sbloom /* dmflopen -- open the line printer port on a dmf32
815*21955Sbloom  *
816*21955Sbloom  */
817*21955Sbloom dmflopen(dev,flag)
818*21955Sbloom dev_t dev;
819*21955Sbloom int flag;
820*21955Sbloom {
821*21955Sbloom 	register int dmf;
822*21955Sbloom 	register struct dmfl_softc *sc;
823*21955Sbloom 	register struct uba_device *ui;
824*21955Sbloom 	register struct dmfdevice *addr;
825*21955Sbloom 
826*21955Sbloom 
827*21955Sbloom 	dmf = DMFL_UNIT(dev) ;
828*21955Sbloom 	if(((sc= &dmfl_softc[dmf])->dmfl_state & OPEN) ||
829*21955Sbloom 		((ui=dmfinfo[dmf]) == 0) || ui->ui_alive == 0)
830*21955Sbloom 			return(ENXIO);
831*21955Sbloom 	addr = (struct dmfdevice *)ui->ui_addr;
832*21955Sbloom 	if((addr->dmfl[0] & DMFL_OFFLINE))
833*21955Sbloom 	{
834*21955Sbloom 		/*printf("dmf: line printer offline/jammed\n");*/
835*21955Sbloom 		return(EIO);
836*21955Sbloom 	}
837*21955Sbloom 	if((addr->dmfl[0]&DMFL_CONV))
838*21955Sbloom 	{
839*21955Sbloom 		printf("dmf:line printer disconnected\n");
840*21955Sbloom 		return(EIO);
841*21955Sbloom 	}
842*21955Sbloom 
843*21955Sbloom 	addr->dmfl[0] = 0;
844*21955Sbloom 	sc->dmfl_state |= OPEN;
845*21955Sbloom 	return 0;
846*21955Sbloom }
847*21955Sbloom 
848*21955Sbloom dmflclose(dev,flag)
849*21955Sbloom dev_t dev;
850*21955Sbloom int flag;
851*21955Sbloom {
852*21955Sbloom 	register int dmf= DMFL_UNIT(dev);
853*21955Sbloom 	register struct dmfl_softc *sc = &dmfl_softc[dmf];
854*21955Sbloom 
855*21955Sbloom 	dmflout(dev,"\f",1);
856*21955Sbloom 	sc->dmfl_state = 0;
857*21955Sbloom 	if(sc->dmfl_info != 0)
858*21955Sbloom 		ubarelse((struct dmfdevice *)(dmfinfo[dmf])->ui_ubanum,
859*21955Sbloom 			&(sc->dmfl_info));
860*21955Sbloom 
861*21955Sbloom 	((struct dmfdevice *)(dmfinfo[dmf]->ui_addr))->dmfl[0]=0;
862*21955Sbloom 	return 0;
863*21955Sbloom }
864*21955Sbloom 
865*21955Sbloom dmflwrite(dev,uio)
866*21955Sbloom dev_t dev;
867*21955Sbloom struct uio *uio;
868*21955Sbloom {
869*21955Sbloom 	register unsigned int n;
870*21955Sbloom 	register int error;
871*21955Sbloom 	register struct dmfl_softc *sc;
872*21955Sbloom 
873*21955Sbloom 	sc = &dmfl_softc[DMFL_UNIT(dev)];
874*21955Sbloom 	if(sc->dmfl_state&ERROR) return(EIO);
875*21955Sbloom 	while(n=min(DMFL_BUFSIZ,(unsigned)uio->uio_resid))
876*21955Sbloom 	{
877*21955Sbloom 		if(error=uiomove(&sc->dmfl_buf[0],(int)n,
878*21955Sbloom 			UIO_WRITE,uio))
879*21955Sbloom 		{
880*21955Sbloom 			printf("uio move error\n");
881*21955Sbloom 			return(error);
882*21955Sbloom 		}
883*21955Sbloom 		if(error=dmflout(dev,&sc->dmfl_buf[0],n))
884*21955Sbloom 		{
885*21955Sbloom 			return(error);
886*21955Sbloom 		}
887*21955Sbloom 	}
888*21955Sbloom 	return 0;
889*21955Sbloom }
890*21955Sbloom 
891*21955Sbloom 
892*21955Sbloom /* dmflout -- start io operation to dmf line printer
893*21955Sbloom  *		cp is addr of buf of n chars to be sent.
894*21955Sbloom  *
895*21955Sbloom  *	-- dmf will be put in formatted output mode, this will
896*21955Sbloom  *		be selectable from an ioctl if the
897*21955Sbloom  *		need ever arises.
898*21955Sbloom  */
899*21955Sbloom dmflout(dev,cp,n)
900*21955Sbloom dev_t dev;
901*21955Sbloom char *cp;
902*21955Sbloom int n;
903*21955Sbloom {
904*21955Sbloom 	register struct dmfl_softc *sc;
905*21955Sbloom 	register int dmf;
906*21955Sbloom 	register struct uba_device *ui;
907*21955Sbloom 	register struct dmfdevice *d;
908*21955Sbloom 	register unsigned info;
909*21955Sbloom 	register unsigned i;
910*21955Sbloom 
911*21955Sbloom 	dmf = DMFL_UNIT(dev) ;
912*21955Sbloom 	sc= &dmfl_softc[dmf];
913*21955Sbloom 	if(sc->dmfl_state&ERROR) return(EIO);
914*21955Sbloom 	ui= dmfinfo[dmf];
915*21955Sbloom 	/* allocate unibus resources, will be released when io
916*21955Sbloom 	 * operation is done
917*21955Sbloom 	 */
918*21955Sbloom 	sc->dmfl_info=
919*21955Sbloom 	info=
920*21955Sbloom 		uballoc(ui->ui_ubanum,cp,n,0);
921*21955Sbloom 	d= (struct dmfdevice *)ui->ui_addr;
922*21955Sbloom 	d->dmfl[0] = (2<<8) | DMFL_FORMAT; /* indir reg 2 */
923*21955Sbloom 	/* indir reg auto increments on r/w */
924*21955Sbloom 	/* SO DON'T CHANGE THE ORDER OF THIS CODE */
925*21955Sbloom 	d->dmfl[1] = 0; /* prefix chars & num */
926*21955Sbloom 	d->dmfl[1] = 0; /* suffix chars & num */
927*21955Sbloom 	d->dmfl[1] = info; 	/* dma lo 16 bits addr */
928*21955Sbloom 
929*21955Sbloom 	/* NOT DOCUMENTED !! */
930*21955Sbloom 	d->dmfl[1] = -n;		/* number of chars */
931*21955Sbloom 	/* ----------^-------- */
932*21955Sbloom 
933*21955Sbloom 	d->dmfl[1] = ((info>>16)&3) /* dma hi 2 bits addr */
934*21955Sbloom 		| (1<<8) /* auto cr insert */
935*21955Sbloom 		| (1<<9) /* use real ff */
936*21955Sbloom 		| (1<<15); /* no u/l conversion */
937*21955Sbloom 	d->dmfl[1] = sc->dmfl_lines 	/* lines per page */
938*21955Sbloom 		| (sc->dmfl_cols<<8);	/* carriage width */
939*21955Sbloom 	sc->dmfl_state |= ASLP;
940*21955Sbloom 	i=spltty();
941*21955Sbloom 	d->dmfl[0] |= DMFL_PEN|DMFL_IE;
942*21955Sbloom 	while(sc->dmfl_state & ASLP)
943*21955Sbloom 	{
944*21955Sbloom 		sleep(&sc->dmfl_buf[0],(PZERO+8));
945*21955Sbloom 		while(sc->dmfl_state&ERROR)
946*21955Sbloom 		{
947*21955Sbloom 			timeout(dmflint,dmf,10*hz);
948*21955Sbloom 			sleep(&sc->dmfl_state,(PZERO+8));
949*21955Sbloom 		}
950*21955Sbloom 		/*if(sc->dmfl_state&ERROR) return (EIO);*/
951*21955Sbloom 	}
952*21955Sbloom 	splx(i);
953*21955Sbloom 	return(0);
954*21955Sbloom }
955*21955Sbloom /* dmflint -- handle an interrupt from the line printer part of the dmf32
956*21955Sbloom  *
957*21955Sbloom  */
958*21955Sbloom 
959*21955Sbloom dmflint(dmf)
960*21955Sbloom int dmf;
961*21955Sbloom {
962*21955Sbloom 
963*21955Sbloom 	register struct uba_device *ui;
964*21955Sbloom 	register struct dmfl_softc *sc;
965*21955Sbloom 	register struct dmfdevice *d;
966*21955Sbloom 
967*21955Sbloom 	ui= dmfinfo[dmf];
968*21955Sbloom 	sc= &dmfl_softc[dmf];
969*21955Sbloom 	d= (struct dmfdevice *)ui->ui_addr;
970*21955Sbloom 
971*21955Sbloom 	d->dmfl[0] &= ~DMFL_IE;
972*21955Sbloom 
973*21955Sbloom 	if(sc->dmfl_state&ERROR)
974*21955Sbloom 	{
975*21955Sbloom 		printf("dmfl: intr while in error state \n");
976*21955Sbloom 		if((d->dmfl[0]&DMFL_OFFLINE) == 0)
977*21955Sbloom 			sc->dmfl_state &= ~ERROR;
978*21955Sbloom 		wakeup(&sc->dmfl_state);
979*21955Sbloom 		return;
980*21955Sbloom 	}
981*21955Sbloom 	if(d->dmfl[0]&DMFL_DMAERR)
982*21955Sbloom 	{
983*21955Sbloom 		printf("dmf:NXM\n");
984*21955Sbloom 	}
985*21955Sbloom 	if(d->dmfl[0]&DMFL_OFFLINE)
986*21955Sbloom 	{
987*21955Sbloom 		printf("dmf:printer error\n");
988*21955Sbloom 		sc->dmfl_state |= ERROR;
989*21955Sbloom 	}
990*21955Sbloom 	if(d->dmfl[0]&DMFL_PDONE)
991*21955Sbloom 	{
992*21955Sbloom #ifdef notdef
993*21955Sbloom 		printf("bytes= %d\n",d->dmfl[1]);
994*21955Sbloom 		printf("lines= %d\n",d->dmfl[1]);
995*21955Sbloom #endif
996*21955Sbloom 	}
997*21955Sbloom 	sc->dmfl_state &= ~ASLP;
998*21955Sbloom 	wakeup(&sc->dmfl_buf[0]);
999*21955Sbloom 	if(sc->dmfl_info != 0)
1000*21955Sbloom 		ubarelse(ui->ui_ubanum,&sc->dmfl_info);
1001*21955Sbloom 	sc->dmfl_info = 0;
1002*21955Sbloom 
1003*21955Sbloom }
1004*21955Sbloom 
10056940Ssam /* stubs for interrupt routines for devices not yet supported */
10066940Ssam 
10076940Ssam dmfsrint() { printf("dmfsrint\n"); }
10086940Ssam 
10096940Ssam dmfsxint() { printf("dmfsxint\n"); }
10106940Ssam 
10116940Ssam dmfdaint() { printf("dmfdaint\n"); }
10126940Ssam 
10136940Ssam dmfdbint() { printf("dmfdbint\n"); }
10146940Ssam 
1015*21955Sbloom 
10166940Ssam #endif
1017