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