Commit | Line | Data |
---|---|---|
4dde4b74 | 1 | /* lp.c 4.6 81/02/16 */ |
3f431cc4 | 2 | |
66b4fb09 | 3 | #include "lp.h" |
4dde4b74 | 4 | #if NLP11 > 0 |
3f431cc4 BJ |
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 | |
3f431cc4 BJ |
49 | #define indent lpio.lp_indent |
50 | #define maxcol lpio.lp_maxcol | |
3f431cc4 BJ |
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; | |
3f431cc4 BJ |
72 | lp11.indent = INDENT; |
73 | lp11.maxcol = MAXCOL; | |
3f431cc4 BJ |
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 | ||
fb5a911f | 87 | lpcanon('\f'); |
3f431cc4 BJ |
88 | brelse(lp11.inbuf); |
89 | lp11.state &= ~OPEN; | |
3f431cc4 BJ |
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 | ||
3f431cc4 | 155 | case '\f': |
fb5a911f | 156 | if (lp11.physline == 0 && physcol == 0) |
ea588cf0 | 157 | break; |
fb5a911f MT |
158 | /* fall into ... */ |
159 | ||
160 | case '\n': | |
ea588cf0 BJ |
161 | lpoutput(c); |
162 | if (c == '\f') | |
163 | lp11.physline = 0; | |
164 | else | |
165 | lp11.physline++; | |
fb5a911f | 166 | physcol = 0; |
3f431cc4 BJ |
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 | } | |
3f431cc4 BJ |
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 | } | |
fb5a911f | 302 |