name changes
[unix-history] / usr / src / sys / vax / uba / lp.c
CommitLineData
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
34struct lpregs {
35 short lpsr;
36 short lpbuf;
37};
38
39struct {
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
58extern lbolt;
59int lptout();
60
61/*ARGSUSED*/
62lpopen(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*/
84lpclose(dev, flag)
85{
86
fb5a911f 87 lpcanon('\f');
3f431cc4
BJ
88 brelse(lp11.inbuf);
89 lp11.state &= ~OPEN;
3f431cc4
BJ
90}
91
92lpwrite()
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
106lpcanon(c)
107register 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
202lpoutput(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
218int lpchar = -1;
219
220lpintr()
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
242lptout()
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*/
263lpioctl(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
296lpreset()
297{
298
299 printf("lp ");
300 LPADDR->lpsr |= IENABLE;
301}
fb5a911f 302