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