date and time created 80/12/17 23:37:34 by wnj
[unix-history] / usr / src / sys / vax / uba / lp.c
CommitLineData
3f431cc4
BJ
1From IngVAX:root Wed Apr 9 02:43:54 1980
2To: 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
37struct lpregs {
38 short lpsr;
39 short lpbuf;
40};
41
42struct {
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
63extern lbolt;
64int lptout();
65
66/*ARGSUSED*/
67lpopen(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*/
91lpclose(dev, flag)
92{
93
94 brelse(lp11.inbuf);
95 lp11.state &= ~OPEN;
96 lpcanon('\f');
97}
98
99lpwrite()
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
113lpcanon(c)
114register 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
218lpoutput(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
234int lpchar = -1;
235
236lpintr()
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 }
249nomore:
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
259lptout()
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*/
280lpioctl(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
313lpreset()
314{
315
316 printf("lp ");
317 LPADDR->lpsr |= IENABLE;
318}
319