xref: /csrg-svn/sys/vax/uba/lp.c (revision 1921)
1*1921Swnj From IngVAX:root  Wed Apr  9 02:43:54 1980
2*1921Swnj To: vax:bill
3*1921Swnj 
4*1921Swnj /*	lp.c	4.1	12/17/80	*/
5*1921Swnj 
6*1921Swnj #include "../conf/lp.h"
7*1921Swnj #if NLP > 0
8*1921Swnj /*
9*1921Swnj  * LP-11 Line printer driver
10*1921Swnj  *
11*1921Swnj  * This driver is only set up to handle one printer;
12*1921Swnj  * thats all our user-level spoolers can handle anyways right now.
13*1921Swnj  *
14*1921Swnj  * This driver has been modified to work on printers where
15*1921Swnj  * leaving IENABLE set would cause continuous interrupts.
16*1921Swnj  */
17*1921Swnj 
18*1921Swnj #include "../h/param.h"
19*1921Swnj #include "../h/dir.h"
20*1921Swnj #include "../h/user.h"
21*1921Swnj #include "../h/buf.h"
22*1921Swnj #include "../h/systm.h"
23*1921Swnj #include "../h/map.h"
24*1921Swnj #include "../h/pte.h"
25*1921Swnj #include "../h/uba.h"
26*1921Swnj #include "../h/ioctl.h"
27*1921Swnj #include "../h/tty.h"
28*1921Swnj #include "../h/lpio.h"
29*1921Swnj 
30*1921Swnj #define	LPPRI	(PZERO+8)
31*1921Swnj #define	IENABLE	0100
32*1921Swnj #define	DONE	0200
33*1921Swnj #define	ERROR	0100000
34*1921Swnj #define	LPLWAT	650
35*1921Swnj #define	LPHWAT	800
36*1921Swnj 
37*1921Swnj struct lpregs {
38*1921Swnj 	short	lpsr;
39*1921Swnj 	short	lpbuf;
40*1921Swnj };
41*1921Swnj 
42*1921Swnj struct {
43*1921Swnj 	struct	clist outq;
44*1921Swnj 	int	state;
45*1921Swnj 	int	physcol;
46*1921Swnj 	int	logcol;
47*1921Swnj 	int	physline;
48*1921Swnj 	struct	lpioctl lpio;
49*1921Swnj 	struct	buf *inbuf;
50*1921Swnj } lp11;
51*1921Swnj #define	flags	lpio.lp_flags
52*1921Swnj #define	ejline	lpio.lp_ejline
53*1921Swnj #define	indent	lpio.lp_indent
54*1921Swnj #define	maxcol	lpio.lp_maxcol
55*1921Swnj #define	skpline	lpio.lp_skpline
56*1921Swnj 
57*1921Swnj /* bits for state */
58*1921Swnj #define	OPEN		1	/* device is open */
59*1921Swnj #define	TOUT		2	/* timeout is active */
60*1921Swnj #define	MOD		4	/* device state has been modified */
61*1921Swnj #define	ASLP		8	/* awaiting draining of printer */
62*1921Swnj 
63*1921Swnj extern	lbolt;
64*1921Swnj int	lptout();
65*1921Swnj 
66*1921Swnj /*ARGSUSED*/
67*1921Swnj lpopen(dev, flag)
68*1921Swnj {
69*1921Swnj 
70*1921Swnj 	if (lp11.state&OPEN || LPADDR->lpsr&ERROR) {
71*1921Swnj 		u.u_error = EIO;
72*1921Swnj 		return;
73*1921Swnj 	}
74*1921Swnj 	lp11.state |= OPEN;
75*1921Swnj 	lp11.inbuf = geteblk();
76*1921Swnj 	lp11.flags = LPFLAGS;
77*1921Swnj 	lp11.ejline = EJLINE;
78*1921Swnj 	lp11.indent = INDENT;
79*1921Swnj 	lp11.maxcol = MAXCOL;
80*1921Swnj 	lp11.skpline = SKPLINE;
81*1921Swnj 	spl4();
82*1921Swnj 	if ((lp11.state&TOUT) == 0) {
83*1921Swnj 		lp11.state |= TOUT;
84*1921Swnj 		timeout(lptout, 0, 10*HZ);
85*1921Swnj 	}
86*1921Swnj 	spl0();
87*1921Swnj 	lpcanon('\f');
88*1921Swnj }
89*1921Swnj 
90*1921Swnj /*ARGSUSED*/
91*1921Swnj lpclose(dev, flag)
92*1921Swnj {
93*1921Swnj 
94*1921Swnj 	brelse(lp11.inbuf);
95*1921Swnj 	lp11.state &= ~OPEN;
96*1921Swnj 	lpcanon('\f');
97*1921Swnj }
98*1921Swnj 
99*1921Swnj lpwrite()
100*1921Swnj {
101*1921Swnj 	register c, n;
102*1921Swnj 	register char *cp;
103*1921Swnj 
104*1921Swnj 	while (n = min(BSIZE, u.u_count)) {
105*1921Swnj 		cp = lp11.inbuf->b_un.b_addr;
106*1921Swnj 		iomove(cp, n, B_WRITE);
107*1921Swnj 		do
108*1921Swnj 			lpcanon(*cp++);
109*1921Swnj 		while (--n);
110*1921Swnj 	}
111*1921Swnj }
112*1921Swnj 
113*1921Swnj lpcanon(c)
114*1921Swnj register c;
115*1921Swnj {
116*1921Swnj 	register int logcol, physcol;
117*1921Swnj 
118*1921Swnj #ifdef HALFASCII
119*1921Swnj 	if (lp11.flags&CAP) {
120*1921Swnj 		register c2;
121*1921Swnj 
122*1921Swnj 		if (c>='a' && c<='z')
123*1921Swnj 			c += 'A'-'a'; else
124*1921Swnj 		switch (c) {
125*1921Swnj 
126*1921Swnj 		case '{':
127*1921Swnj 			c2 = '(';
128*1921Swnj 			goto esc;
129*1921Swnj 
130*1921Swnj 		case '}':
131*1921Swnj 			c2 = ')';
132*1921Swnj 			goto esc;
133*1921Swnj 
134*1921Swnj 		case '`':
135*1921Swnj 			c2 = '\'';
136*1921Swnj 			goto esc;
137*1921Swnj 
138*1921Swnj 		case '|':
139*1921Swnj 			c2 = '!';
140*1921Swnj 			goto esc;
141*1921Swnj 
142*1921Swnj 		case '~':
143*1921Swnj 			c2 = '^';
144*1921Swnj 
145*1921Swnj 		esc:
146*1921Swnj 			lpcanon(c2);
147*1921Swnj 			lp11.logcol--;
148*1921Swnj 			c = '-';
149*1921Swnj 		}
150*1921Swnj 	}
151*1921Swnj #endif HALFASCII
152*1921Swnj 	logcol = lp11.logcol;
153*1921Swnj 	physcol = lp11.physcol;
154*1921Swnj 	if (c == ' ')
155*1921Swnj 		logcol++;
156*1921Swnj 	else switch(c) {
157*1921Swnj 
158*1921Swnj 	case '\t':
159*1921Swnj 		logcol = lp11.indent + ((logcol-lp11.indent+8) & ~7);
160*1921Swnj 		break;
161*1921Swnj 
162*1921Swnj 	case '\n':
163*1921Swnj 		lp11.physline++;
164*1921Swnj 		if (lp11.physline >= lp11.ejline)
165*1921Swnj 			c = '\f';
166*1921Swnj 		/* fall through */
167*1921Swnj 
168*1921Swnj 	case '\f':
169*1921Swnj 		physcol = 0;
170*1921Swnj 		if (lp11.physline == 0 && (lp11.flags&SAVEPAPER))
171*1921Swnj 			;
172*1921Swnj 		else {
173*1921Swnj 			lpoutput(c);
174*1921Swnj 			if (c == '\f') {
175*1921Swnj 				lp11.physline = 0;
176*1921Swnj 				if (lp11.flags & SKIPFOLD) {
177*1921Swnj 					int i;
178*1921Swnj 					for (i = 0; i < lp11.skpline; i++)
179*1921Swnj 						lpoutput('\n');
180*1921Swnj 				}
181*1921Swnj 			}
182*1921Swnj 		}
183*1921Swnj 		/* fall into ... */
184*1921Swnj 
185*1921Swnj 	case '\r':
186*1921Swnj 		logcol = lp11.indent;
187*1921Swnj 		spl4();
188*1921Swnj 		lpintr();
189*1921Swnj 		spl0();
190*1921Swnj 		break;
191*1921Swnj 
192*1921Swnj 	case '\b':
193*1921Swnj 		if (logcol > 0)
194*1921Swnj 			logcol--;
195*1921Swnj 		break;
196*1921Swnj 
197*1921Swnj 	default:
198*1921Swnj 		if (logcol < physcol) {
199*1921Swnj 			lpoutput('\r');
200*1921Swnj 			physcol = 0;
201*1921Swnj 		}
202*1921Swnj 		if (logcol < lp11.maxcol) {
203*1921Swnj 			while (logcol > physcol) {
204*1921Swnj 				lpoutput(' ');
205*1921Swnj 				physcol++;
206*1921Swnj 			}
207*1921Swnj 			lpoutput(c);
208*1921Swnj 			physcol++;
209*1921Swnj 		}
210*1921Swnj 		logcol++;
211*1921Swnj 	}
212*1921Swnj 	if (logcol > 1000)	/* ignore long lines  */
213*1921Swnj 		logcol = 1000;
214*1921Swnj 	lp11.logcol = logcol;
215*1921Swnj 	lp11.physcol = physcol;
216*1921Swnj }
217*1921Swnj 
218*1921Swnj lpoutput(c)
219*1921Swnj {
220*1921Swnj 
221*1921Swnj 	if (lp11.outq.c_cc >= LPHWAT) {
222*1921Swnj 		spl4();
223*1921Swnj 		lpintr();				/* unchoke */
224*1921Swnj 		while (lp11.outq.c_cc >= LPHWAT) {
225*1921Swnj 			lp11.state |= ASLP;		/* must be ERROR */
226*1921Swnj 			sleep((caddr_t)&lp11, LPPRI);
227*1921Swnj 		}
228*1921Swnj 		spl0();
229*1921Swnj 	}
230*1921Swnj 	while (putc(c, &lp11.outq))
231*1921Swnj 		sleep((caddr_t)&lbolt, LPPRI);
232*1921Swnj }
233*1921Swnj 
234*1921Swnj int	lpchar = -1;
235*1921Swnj 
236*1921Swnj lpintr()
237*1921Swnj {
238*1921Swnj 	register int n;
239*1921Swnj 	int i;
240*1921Swnj 
241*1921Swnj 	LPADDR->lpsr &= ~IENABLE;
242*1921Swnj 	n = lp11.outq.c_cc;
243*1921Swnj 	if (lpchar < 0)
244*1921Swnj 		lpchar = getc(&lp11);
245*1921Swnj 	while ((LPADDR->lpsr&DONE) && lpchar >= 0) {
246*1921Swnj 		LPADDR->lpbuf = lpchar;
247*1921Swnj 		lpchar = getc(&lp11);
248*1921Swnj 	}
249*1921Swnj nomore:
250*1921Swnj 	lp11.state |= MOD;
251*1921Swnj 	if (lp11.outq.c_cc > 0 && (LPADDR->lpsr&ERROR)==0)
252*1921Swnj 		LPADDR->lpsr |= IENABLE;	/* ok and more to do later */
253*1921Swnj 	if (n>LPLWAT && lp11.outq.c_cc<=LPLWAT && lp11.state&ASLP) {
254*1921Swnj 		lp11.state &= ~ASLP;
255*1921Swnj 		wakeup((caddr_t)&lp11);		/* top half should go on */
256*1921Swnj 	}
257*1921Swnj }
258*1921Swnj 
259*1921Swnj lptout()
260*1921Swnj {
261*1921Swnj 	register short *sr;
262*1921Swnj 
263*1921Swnj 	if ((lp11.state&MOD) != 0) {
264*1921Swnj 		lp11.state &= ~MOD;		/* something happened */
265*1921Swnj 		timeout(lptout, 0, 2*HZ);	/* so don't sweat */
266*1921Swnj 		return;
267*1921Swnj 	}
268*1921Swnj 	sr = &LPADDR->lpsr;
269*1921Swnj 	if ((lp11.state&OPEN) == 0) {
270*1921Swnj 		lp11.state &= ~TOUT;		/* no longer open */
271*1921Swnj 		*sr = 0;
272*1921Swnj 		return;
273*1921Swnj 	}
274*1921Swnj 	if (lp11.outq.c_cc && (*sr&DONE) && (*sr&ERROR)==0)
275*1921Swnj 		lpintr();			/* ready to go */
276*1921Swnj 	timeout(lptout, 0, 10*HZ);
277*1921Swnj }
278*1921Swnj 
279*1921Swnj /*ARGSUSED*/
280*1921Swnj lpioctl(dev, cmd, addr, flag)
281*1921Swnj 	dev_t dev;
282*1921Swnj 	caddr_t addr;
283*1921Swnj {
284*1921Swnj 	register int m;
285*1921Swnj 	struct lpioctl lpio;
286*1921Swnj 
287*1921Swnj 	switch (cmd) {
288*1921Swnj 
289*1921Swnj 	case LGETSTATE:
290*1921Swnj 		copyout((caddr_t)&lp11.lpio, addr, sizeof (lp11.lpio));
291*1921Swnj 		return;
292*1921Swnj 
293*1921Swnj 	case LSETSTATE:
294*1921Swnj 		m = copyin(addr, (caddr_t)&lpio, sizeof (lpio));
295*1921Swnj 		if (m < 0) {
296*1921Swnj 			u.u_error = EFAULT;
297*1921Swnj 			return;
298*1921Swnj 		}
299*1921Swnj 		if (lpio.lp_indent <= 0 || lpio.lp_indent >= lpio.lp_maxcol ||
300*1921Swnj 		    lpio.lp_ejline <= 2 || lpio.lp_ejline <= lpio.lp_skpline ||
301*1921Swnj 		    lpio.lp_skpline < 0 || lpio.lp_maxcol <= 10)
302*1921Swnj 			u.u_error = EINVAL;
303*1921Swnj 		else
304*1921Swnj 			lp11.lpio = lpio;
305*1921Swnj 		return;
306*1921Swnj 
307*1921Swnj 	default:
308*1921Swnj 		u.u_error = ENOTTY;
309*1921Swnj 		return;
310*1921Swnj 	}
311*1921Swnj }
312*1921Swnj 
313*1921Swnj lpreset()
314*1921Swnj {
315*1921Swnj 
316*1921Swnj 	printf("lp ");
317*1921Swnj 	LPADDR->lpsr |= IENABLE;
318*1921Swnj }
319*1921Swnj 
320