xref: /original-bsd/sys/vax/uba/lp.c (revision 71445730)
1*71445730Sbloom /*	lp.c	6.4	84/08/29	*/
28ad6c293Swnj 
39826bf71Swnj #include "lp.h"
419dc5c79Stoy #if NLP > 0
58ad6c293Swnj /*
68ad6c293Swnj  * LP-11 Line printer driver
78ad6c293Swnj  *
88ad6c293Swnj  * This driver has been modified to work on printers where
98ad6c293Swnj  * leaving IENABLE set would cause continuous interrupts.
108ad6c293Swnj  */
11df5e0e02Ssam #include "../machine/pte.h"
128ad6c293Swnj 
13*71445730Sbloom #include "param.h"
14*71445730Sbloom #include "dir.h"
15*71445730Sbloom #include "user.h"
16*71445730Sbloom #include "buf.h"
17*71445730Sbloom #include "systm.h"
18*71445730Sbloom #include "map.h"
19*71445730Sbloom #include "uio.h"
20*71445730Sbloom #include "tty.h"
21*71445730Sbloom #include "kernel.h"
228ad6c293Swnj 
23*71445730Sbloom #include "ubavar.h"
2442b8bd9bSroot 
258ad6c293Swnj #define	LPPRI	(PZERO+8)
268ad6c293Swnj #define	IENABLE	0100
278ad6c293Swnj #define	DONE	0200
288ad6c293Swnj #define	ERROR	0100000
298ad6c293Swnj #define	LPLWAT	650
308ad6c293Swnj #define	LPHWAT	800
318ad6c293Swnj 
3219dc5c79Stoy #define MAXCOL	132
3319dc5c79Stoy #define CAP	1
3419dc5c79Stoy 
3519dc5c79Stoy #define LPUNIT(dev) (minor(dev) >> 3)
3619dc5c79Stoy 
3719dc5c79Stoy struct lpdevice {
388ad6c293Swnj 	short	lpsr;
398ad6c293Swnj 	short	lpbuf;
408ad6c293Swnj };
418ad6c293Swnj 
4219dc5c79Stoy struct lp_softc {
4319dc5c79Stoy 	struct	clist sc_outq;
4419dc5c79Stoy 	int	sc_state;
4519dc5c79Stoy 	int	sc_physcol;
4619dc5c79Stoy 	int	sc_logcol;
4719dc5c79Stoy 	int	sc_physline;
4819dc5c79Stoy 	char	sc_flags;
49767a234cSsam 	short	sc_maxcol;
5019dc5c79Stoy 	int	sc_lpchar;
5119dc5c79Stoy 	struct	buf *sc_inbuf;
5219dc5c79Stoy } lp_softc[NLP];
5319dc5c79Stoy 
5419dc5c79Stoy struct uba_device *lpinfo[NLP];
5519dc5c79Stoy 
5619dc5c79Stoy int lpprobe(), lpattach(), lptout();
5719dc5c79Stoy u_short lpstd[] = { 0177514 };
5819dc5c79Stoy struct uba_driver lpdriver =
5919dc5c79Stoy 	{ lpprobe, 0, lpattach, 0, lpstd, "lp", lpinfo };
608ad6c293Swnj 
618ad6c293Swnj /* bits for state */
628ad6c293Swnj #define	OPEN		1	/* device is open */
638ad6c293Swnj #define	TOUT		2	/* timeout is active */
648ad6c293Swnj #define	MOD		4	/* device state has been modified */
658ad6c293Swnj #define	ASLP		8	/* awaiting draining of printer */
668ad6c293Swnj 
678ad6c293Swnj int	lptout();
688ad6c293Swnj 
6984e24a43Swnj lpattach(ui)
7084e24a43Swnj 	struct uba_device *ui;
7184e24a43Swnj {
7284e24a43Swnj 	register struct lp_softc *sc;
7384e24a43Swnj 
7484e24a43Swnj 	sc = &lp_softc[ui->ui_unit];
7584e24a43Swnj 	sc->sc_lpchar = -1;
76767a234cSsam 	if (ui->ui_flags)
77767a234cSsam 		sc->sc_maxcol = ui->ui_flags;
78767a234cSsam 	else
79767a234cSsam 		sc->sc_maxcol = MAXCOL;
8084e24a43Swnj }
8184e24a43Swnj 
8284e24a43Swnj lpprobe(reg)
8384e24a43Swnj 	caddr_t reg;
8484e24a43Swnj {
853bca611eSwnj 	register int br, cvec;			/* value-result */
8684e24a43Swnj 	register struct lpdevice *lpaddr = (struct lpdevice *)reg;
87573260eeSroot #ifdef lint
88573260eeSroot 	br = 0; cvec = br; br = cvec;
89a0f3106dSwnj 	lpintr(0);
90573260eeSroot #endif
9184e24a43Swnj 
9284e24a43Swnj 	lpaddr->lpsr = IENABLE;
933bca611eSwnj 	DELAY(5);
9484e24a43Swnj 	lpaddr->lpsr = 0;
958b4ceed8Skre 	return (sizeof (struct lpdevice));
9684e24a43Swnj }
9784e24a43Swnj 
988ad6c293Swnj /*ARGSUSED*/
998ad6c293Swnj lpopen(dev, flag)
10019dc5c79Stoy 	dev_t dev;
10184e24a43Swnj 	int flag;
1028ad6c293Swnj {
10319dc5c79Stoy 	register struct lpdevice *lpaddr;
10419dc5c79Stoy 	register struct lp_softc *sc;
10519dc5c79Stoy 	register struct uba_device *ui;
1061d999883Smckusick 	register int unit, s;
1078ad6c293Swnj 
10884e24a43Swnj 	if ((unit = LPUNIT(dev)) >= NLP ||
10984e24a43Swnj 	    (sc = &lp_softc[unit])->sc_state&OPEN ||
1103536053eSroot 	    (ui = lpinfo[unit]) == 0 || ui->ui_alive == 0)
1113536053eSroot 		return (ENXIO);
11219dc5c79Stoy 	lpaddr = (struct lpdevice *)ui->ui_addr;
1133536053eSroot 	if (lpaddr->lpsr&ERROR)
1143536053eSroot 		return (EIO);
11519dc5c79Stoy 	sc->sc_state |= OPEN;
11647d449d1Sroot 	sc->sc_inbuf = geteblk(512);
11719dc5c79Stoy 	sc->sc_flags = minor(dev) & 07;
1181d999883Smckusick 	s = spl4();
11919dc5c79Stoy 	if ((sc->sc_state&TOUT) == 0) {
12019dc5c79Stoy 		sc->sc_state |= TOUT;
121573260eeSroot 		timeout(lptout, (caddr_t)dev, 10*hz);
1228ad6c293Swnj 	}
1231d999883Smckusick 	splx(s);
12484e24a43Swnj 	lpcanon(dev, '\f');
1253536053eSroot 	return (0);
1268ad6c293Swnj }
1278ad6c293Swnj 
1288ad6c293Swnj /*ARGSUSED*/
1298ad6c293Swnj lpclose(dev, flag)
13019dc5c79Stoy 	dev_t dev;
13184e24a43Swnj 	int flag;
1328ad6c293Swnj {
13384e24a43Swnj 	register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
1348ad6c293Swnj 
13584e24a43Swnj 	lpcanon(dev, '\f');
13619dc5c79Stoy 	brelse(sc->sc_inbuf);
13719dc5c79Stoy 	sc->sc_state &= ~OPEN;
1388ad6c293Swnj }
1398ad6c293Swnj 
14025aace65Sroot lpwrite(dev, uio)
14184e24a43Swnj 	dev_t dev;
14225aace65Sroot 	struct uio *uio;
1438ad6c293Swnj {
144573260eeSroot 	register unsigned n;
1458ad6c293Swnj 	register char *cp;
14684e24a43Swnj 	register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
1470d901dbeSroot 	int error;
1488ad6c293Swnj 
149ffffdfffSsam 	while (n = min(512, (unsigned)uio->uio_resid)) {
15019dc5c79Stoy 		cp = sc->sc_inbuf->b_un.b_addr;
151ffffdfffSsam 		error = uiomove(cp, (int)n, UIO_WRITE, uio);
1520d901dbeSroot 		if (error)
1530d901dbeSroot 			return (error);
1548ad6c293Swnj 		do
15584e24a43Swnj 			lpcanon(dev, *cp++);
1568ad6c293Swnj 		while (--n);
1578ad6c293Swnj 	}
1580d901dbeSroot 	return (0);
1598ad6c293Swnj }
1608ad6c293Swnj 
16184e24a43Swnj lpcanon(dev, c)
16284e24a43Swnj 	dev_t dev;
16319dc5c79Stoy 	register int c;
1648ad6c293Swnj {
16584e24a43Swnj 	register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
1661d999883Smckusick 	register int logcol, physcol, s;
1678ad6c293Swnj 
16819dc5c79Stoy 	if (sc->sc_flags&CAP) {
1698ad6c293Swnj 		register c2;
1708ad6c293Swnj 
1718ad6c293Swnj 		if (c>='a' && c<='z')
1728ad6c293Swnj 			c += 'A'-'a'; else
1738ad6c293Swnj 		switch (c) {
1748ad6c293Swnj 
1758ad6c293Swnj 		case '{':
1768ad6c293Swnj 			c2 = '(';
1778ad6c293Swnj 			goto esc;
1788ad6c293Swnj 
1798ad6c293Swnj 		case '}':
1808ad6c293Swnj 			c2 = ')';
1818ad6c293Swnj 			goto esc;
1828ad6c293Swnj 
1838ad6c293Swnj 		case '`':
1848ad6c293Swnj 			c2 = '\'';
1858ad6c293Swnj 			goto esc;
1868ad6c293Swnj 
1878ad6c293Swnj 		case '|':
1888ad6c293Swnj 			c2 = '!';
1898ad6c293Swnj 			goto esc;
1908ad6c293Swnj 
1918ad6c293Swnj 		case '~':
1928ad6c293Swnj 			c2 = '^';
1938ad6c293Swnj 
1948ad6c293Swnj 		esc:
19584e24a43Swnj 			lpcanon(dev, c2);
19619dc5c79Stoy 			sc->sc_logcol--;
1978ad6c293Swnj 			c = '-';
1988ad6c293Swnj 		}
1998ad6c293Swnj 	}
20019dc5c79Stoy 	logcol = sc->sc_logcol;
20119dc5c79Stoy 	physcol = sc->sc_physcol;
2028ad6c293Swnj 	if (c == ' ')
2038ad6c293Swnj 		logcol++;
2048ad6c293Swnj 	else switch(c) {
2058ad6c293Swnj 
2068ad6c293Swnj 	case '\t':
20770b581cfSwnj 		logcol = (logcol+8) & ~7;
2088ad6c293Swnj 		break;
2098ad6c293Swnj 
2108ad6c293Swnj 	case '\f':
21119dc5c79Stoy 		if (sc->sc_physline == 0 && physcol == 0)
212f0b42318Swnj 			break;
213c2e62a0eStoy 		/* fall into ... */
214c2e62a0eStoy 
215c2e62a0eStoy 	case '\n':
21684e24a43Swnj 		lpoutput(dev, c);
217f0b42318Swnj 		if (c == '\f')
21819dc5c79Stoy 			sc->sc_physline = 0;
219f0b42318Swnj 		else
22019dc5c79Stoy 			sc->sc_physline++;
221c2e62a0eStoy 		physcol = 0;
2228ad6c293Swnj 		/* fall into ... */
2238ad6c293Swnj 
2248ad6c293Swnj 	case '\r':
2251d999883Smckusick 		s = spl4();
22619dc5c79Stoy 		logcol = 0;
22784e24a43Swnj 		lpintr(LPUNIT(dev));
2281d999883Smckusick 		splx(s);
2298ad6c293Swnj 		break;
2308ad6c293Swnj 
2318ad6c293Swnj 	case '\b':
2328ad6c293Swnj 		if (logcol > 0)
2338ad6c293Swnj 			logcol--;
2348ad6c293Swnj 		break;
2358ad6c293Swnj 
2368ad6c293Swnj 	default:
2378ad6c293Swnj 		if (logcol < physcol) {
23884e24a43Swnj 			lpoutput(dev, '\r');
2398ad6c293Swnj 			physcol = 0;
2408ad6c293Swnj 		}
241767a234cSsam 		if (logcol < sc->sc_maxcol) {
2428ad6c293Swnj 			while (logcol > physcol) {
24384e24a43Swnj 				lpoutput(dev, ' ');
2448ad6c293Swnj 				physcol++;
2458ad6c293Swnj 			}
24684e24a43Swnj 			lpoutput(dev, c);
2478ad6c293Swnj 			physcol++;
2488ad6c293Swnj 		}
2498ad6c293Swnj 		logcol++;
2508ad6c293Swnj 	}
2518ad6c293Swnj 	if (logcol > 1000)	/* ignore long lines  */
2528ad6c293Swnj 		logcol = 1000;
25319dc5c79Stoy 	sc->sc_logcol = logcol;
25419dc5c79Stoy 	sc->sc_physcol = physcol;
2558ad6c293Swnj }
2568ad6c293Swnj 
25784e24a43Swnj lpoutput(dev, c)
25819dc5c79Stoy 	dev_t dev;
25984e24a43Swnj 	int c;
2608ad6c293Swnj {
26184e24a43Swnj 	register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
2621d999883Smckusick 	int s;
2638ad6c293Swnj 
26419dc5c79Stoy 	if (sc->sc_outq.c_cc >= LPHWAT) {
2651d999883Smckusick 		s = spl4();
26684e24a43Swnj 		lpintr(LPUNIT(dev));				/* unchoke */
26719dc5c79Stoy 		while (sc->sc_outq.c_cc >= LPHWAT) {
26819dc5c79Stoy 			sc->sc_state |= ASLP;		/* must be ERROR */
26919dc5c79Stoy 			sleep((caddr_t)sc, LPPRI);
2708ad6c293Swnj 		}
2711d999883Smckusick 		splx(s);
2728ad6c293Swnj 	}
27319dc5c79Stoy 	while (putc(c, &sc->sc_outq))
2748ad6c293Swnj 		sleep((caddr_t)&lbolt, LPPRI);
2758ad6c293Swnj }
2768ad6c293Swnj 
27784e24a43Swnj lpintr(lp11)
27884e24a43Swnj 	int lp11;
2798ad6c293Swnj {
2808ad6c293Swnj 	register int n;
28184e24a43Swnj 	register struct lp_softc *sc = &lp_softc[lp11];
28284e24a43Swnj 	register struct uba_device *ui = lpinfo[lp11];
28384e24a43Swnj 	register struct lpdevice *lpaddr = (struct lpdevice *)ui->ui_addr;
2848ad6c293Swnj 
28519dc5c79Stoy 	lpaddr->lpsr &= ~IENABLE;
28619dc5c79Stoy 	n = sc->sc_outq.c_cc;
28719dc5c79Stoy 	if (sc->sc_lpchar < 0)
28819dc5c79Stoy 		sc->sc_lpchar = getc(&sc->sc_outq);
28919dc5c79Stoy 	while ((lpaddr->lpsr&DONE) && sc->sc_lpchar >= 0) {
29019dc5c79Stoy 		lpaddr->lpbuf = sc->sc_lpchar;
29119dc5c79Stoy 		sc->sc_lpchar = getc(&sc->sc_outq);
2928ad6c293Swnj 	}
29319dc5c79Stoy 	sc->sc_state |= MOD;
29419dc5c79Stoy 	if (sc->sc_outq.c_cc > 0 && (lpaddr->lpsr&ERROR)==0)
29519dc5c79Stoy 		lpaddr->lpsr |= IENABLE;	/* ok and more to do later */
29619dc5c79Stoy 	if (n>LPLWAT && sc->sc_outq.c_cc<=LPLWAT && sc->sc_state&ASLP) {
29719dc5c79Stoy 		sc->sc_state &= ~ASLP;
29819dc5c79Stoy 		wakeup((caddr_t)sc);		/* top half should go on */
2998ad6c293Swnj 	}
3008ad6c293Swnj }
3018ad6c293Swnj 
30219dc5c79Stoy lptout(dev)
30384e24a43Swnj 	dev_t dev;
3048ad6c293Swnj {
30519dc5c79Stoy 	register struct lp_softc *sc;
30619dc5c79Stoy 	register struct uba_device *ui;
30719dc5c79Stoy 	register struct lpdevice *lpaddr;
3088ad6c293Swnj 
30919dc5c79Stoy 	sc = &lp_softc[LPUNIT(dev)];
31019dc5c79Stoy 	ui = lpinfo[LPUNIT(dev)];
31119dc5c79Stoy 	lpaddr = (struct lpdevice *) ui->ui_addr;
31219dc5c79Stoy 	if ((sc->sc_state&MOD) != 0) {
31319dc5c79Stoy 		sc->sc_state &= ~MOD;		/* something happened */
314573260eeSroot 		timeout(lptout, (caddr_t)dev, 2*hz);	/* so don't sweat */
3158ad6c293Swnj 		return;
3168ad6c293Swnj 	}
3177cda3700Smckusick 	if ((sc->sc_state&OPEN) == 0 && sc->sc_outq.c_cc == 0) {
31819dc5c79Stoy 		sc->sc_state &= ~TOUT;		/* no longer open */
31919dc5c79Stoy 		lpaddr->lpsr = 0;
3208ad6c293Swnj 		return;
3218ad6c293Swnj 	}
32219dc5c79Stoy 	if (sc->sc_outq.c_cc && (lpaddr->lpsr&DONE) && (lpaddr->lpsr&ERROR)==0)
32384e24a43Swnj 		lpintr(LPUNIT(dev));			/* ready to go */
324573260eeSroot 	timeout(lptout, (caddr_t)dev, 10*hz);
3258ad6c293Swnj }
3268ad6c293Swnj 
32719dc5c79Stoy lpreset(uban)
32819dc5c79Stoy 	int uban;
3298ad6c293Swnj {
33019dc5c79Stoy 	register struct uba_device *ui;
33119dc5c79Stoy 	register struct lpdevice *lpaddr;
33219dc5c79Stoy 	register int unit;
3338ad6c293Swnj 
33484e24a43Swnj 	for (unit = 0; unit < NLP; unit++) {
33584e24a43Swnj 		if ((ui = lpinfo[unit]) == 0 || ui->ui_ubanum != uban ||
33684e24a43Swnj 		    ui->ui_alive == 0)
33719dc5c79Stoy 			continue;
33819dc5c79Stoy 		printf(" lp%d", unit);
33919dc5c79Stoy 		lpaddr = (struct lpdevice *)ui->ui_addr;
34019dc5c79Stoy 		lpaddr->lpsr |= IENABLE;
34119dc5c79Stoy 	}
3428ad6c293Swnj }
343ffffdfffSsam #endif
344