Commit | Line | Data |
---|---|---|
3f431cc4 BJ |
1 | From IngVAX:root Wed Apr 9 02:43:54 1980 |
2 | To: vax:bill | |
3 | ||
4 | /* lp.c 4.1 %G% */ | |
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 |