return(1)!
[unix-history] / usr / src / sys / vax / uba / lp.c
CommitLineData
fd1e4b7b 1/* lp.c 4.18 81/04/02 */
3f431cc4 2
66b4fb09 3#include "lp.h"
ca063532 4#if NLP > 0
3f431cc4
BJ
5/*
6 * LP-11 Line printer driver
7 *
3f431cc4
BJ
8 * This driver has been modified to work on printers where
9 * leaving IENABLE set would cause continuous interrupts.
683f0425
MT
10 *
11 * TODO:
683f0425 12 * Test driver on multiple printers
3f431cc4
BJ
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"
ca063532 22#include "../h/ubavar.h"
3f431cc4
BJ
23#include "../h/ioctl.h"
24#include "../h/tty.h"
3f431cc4
BJ
25
26#define LPPRI (PZERO+8)
27#define IENABLE 0100
28#define DONE 0200
29#define ERROR 0100000
30#define LPLWAT 650
31#define LPHWAT 800
32
ca063532
MT
33#define MAXCOL 132
34#define CAP 1
35
36#define LPUNIT(dev) (minor(dev) >> 3)
37
38struct lpdevice {
3f431cc4
BJ
39 short lpsr;
40 short lpbuf;
41};
42
ca063532
MT
43struct lp_softc {
44 struct clist sc_outq;
45 int sc_state;
46 int sc_physcol;
47 int sc_logcol;
48 int sc_physline;
49 char sc_flags;
50 int sc_lpchar;
51 struct buf *sc_inbuf;
52} lp_softc[NLP];
53
54struct uba_device *lpinfo[NLP];
55
56int lpprobe(), lpattach(), lptout();
57u_short lpstd[] = { 0177514 };
58struct uba_driver lpdriver =
59 { lpprobe, 0, lpattach, 0, lpstd, "lp", lpinfo };
3f431cc4
BJ
60
61/* bits for state */
62#define OPEN 1 /* device is open */
63#define TOUT 2 /* timeout is active */
64#define MOD 4 /* device state has been modified */
65#define ASLP 8 /* awaiting draining of printer */
66
67extern lbolt;
68int lptout();
69
5ffed226
BJ
70lpattach(ui)
71 struct uba_device *ui;
72{
73 register struct lp_softc *sc;
74
75 sc = &lp_softc[ui->ui_unit];
76 sc->sc_lpchar = -1;
77}
78
79lpprobe(reg)
80 caddr_t reg;
81{
c2213eb5 82 register int br, cvec; /* value-result */
5ffed226
BJ
83 register struct lpdevice *lpaddr = (struct lpdevice *)reg;
84
85 lpaddr->lpsr = IENABLE;
c2213eb5 86 DELAY(5);
5ffed226
BJ
87 lpaddr->lpsr = 0;
88}
89
3f431cc4
BJ
90/*ARGSUSED*/
91lpopen(dev, flag)
5ffed226
BJ
92 dev_t dev;
93 int flag;
3f431cc4 94{
ca063532
MT
95 register int unit;
96 register struct lpdevice *lpaddr;
97 register struct lp_softc *sc;
98 register struct uba_device *ui;
99
5ffed226
BJ
100 if ((unit = LPUNIT(dev)) >= NLP ||
101 (sc = &lp_softc[unit])->sc_state&OPEN ||
102 (ui = lpinfo[unit]) == 0 || ui->ui_alive == 0) {
ca063532
MT
103 u.u_error = ENXIO;
104 return;
105 }
5ffed226
BJ
106 lpaddr = (struct lpdevice *)ui->ui_addr;
107 if (lpaddr->lpsr&ERROR) {
3f431cc4
BJ
108 u.u_error = EIO;
109 return;
110 }
ca063532
MT
111 sc->sc_state |= OPEN;
112 sc->sc_inbuf = geteblk();
113 sc->sc_flags = minor(dev) & 07;
a0eab615 114 (void) spl4();
ca063532
MT
115 if ((sc->sc_state&TOUT) == 0) {
116 sc->sc_state |= TOUT;
117 timeout(lptout, dev, 10*hz);
3f431cc4 118 }
a0eab615 119 (void) spl0();
5ffed226 120 lpcanon(dev, '\f');
3f431cc4
BJ
121}
122
123/*ARGSUSED*/
124lpclose(dev, flag)
5ffed226
BJ
125 dev_t dev;
126 int flag;
3f431cc4 127{
5ffed226 128 register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
3f431cc4 129
5ffed226 130 lpcanon(dev, '\f');
ca063532
MT
131 brelse(sc->sc_inbuf);
132 sc->sc_state &= ~OPEN;
3f431cc4
BJ
133}
134
ca063532 135lpwrite(dev)
5ffed226 136 dev_t dev;
3f431cc4 137{
ca063532 138 register int n;
3f431cc4 139 register char *cp;
5ffed226 140 register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
3f431cc4
BJ
141
142 while (n = min(BSIZE, u.u_count)) {
ca063532 143 cp = sc->sc_inbuf->b_un.b_addr;
3f431cc4
BJ
144 iomove(cp, n, B_WRITE);
145 do
5ffed226 146 lpcanon(dev, *cp++);
3f431cc4
BJ
147 while (--n);
148 }
149}
150
5ffed226
BJ
151lpcanon(dev, c)
152 dev_t dev;
153 register int c;
3f431cc4
BJ
154{
155 register int logcol, physcol;
5ffed226 156 register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
3f431cc4 157
ca063532 158 if (sc->sc_flags&CAP) {
3f431cc4
BJ
159 register c2;
160
161 if (c>='a' && c<='z')
162 c += 'A'-'a'; else
163 switch (c) {
164
165 case '{':
166 c2 = '(';
167 goto esc;
168
169 case '}':
170 c2 = ')';
171 goto esc;
172
173 case '`':
174 c2 = '\'';
175 goto esc;
176
177 case '|':
178 c2 = '!';
179 goto esc;
180
181 case '~':
182 c2 = '^';
183
184 esc:
5ffed226 185 lpcanon(dev, c2);
ca063532 186 sc->sc_logcol--;
3f431cc4
BJ
187 c = '-';
188 }
189 }
ca063532
MT
190 logcol = sc->sc_logcol;
191 physcol = sc->sc_physcol;
3f431cc4
BJ
192 if (c == ' ')
193 logcol++;
194 else switch(c) {
195
196 case '\t':
36abf8b6 197 logcol = (logcol+8) & ~7;
3f431cc4
BJ
198 break;
199
3f431cc4 200 case '\f':
ca063532 201 if (sc->sc_physline == 0 && physcol == 0)
ea588cf0 202 break;
fb5a911f
MT
203 /* fall into ... */
204
205 case '\n':
5ffed226 206 lpoutput(dev, c);
ea588cf0 207 if (c == '\f')
ca063532 208 sc->sc_physline = 0;
ea588cf0 209 else
ca063532 210 sc->sc_physline++;
fb5a911f 211 physcol = 0;
3f431cc4
BJ
212 /* fall into ... */
213
214 case '\r':
ca063532 215 logcol = 0;
a0eab615 216 (void) spl4();
5ffed226 217 lpintr(LPUNIT(dev));
a0eab615 218 (void) spl0();
3f431cc4
BJ
219 break;
220
221 case '\b':
222 if (logcol > 0)
223 logcol--;
224 break;
225
226 default:
227 if (logcol < physcol) {
5ffed226 228 lpoutput(dev, '\r');
3f431cc4
BJ
229 physcol = 0;
230 }
ca063532 231 if (logcol < MAXCOL) {
3f431cc4 232 while (logcol > physcol) {
5ffed226 233 lpoutput(dev, ' ');
3f431cc4
BJ
234 physcol++;
235 }
5ffed226 236 lpoutput(dev, c);
3f431cc4
BJ
237 physcol++;
238 }
239 logcol++;
240 }
241 if (logcol > 1000) /* ignore long lines */
242 logcol = 1000;
ca063532
MT
243 sc->sc_logcol = logcol;
244 sc->sc_physcol = physcol;
3f431cc4
BJ
245}
246
5ffed226
BJ
247lpoutput(dev, c)
248 dev_t dev;
249 int c;
3f431cc4 250{
5ffed226 251 register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
3f431cc4 252
ca063532 253 if (sc->sc_outq.c_cc >= LPHWAT) {
a0eab615 254 (void) spl4();
5ffed226 255 lpintr(LPUNIT(dev)); /* unchoke */
ca063532
MT
256 while (sc->sc_outq.c_cc >= LPHWAT) {
257 sc->sc_state |= ASLP; /* must be ERROR */
258 sleep((caddr_t)sc, LPPRI);
3f431cc4 259 }
a0eab615 260 (void) spl0();
3f431cc4 261 }
ca063532 262 while (putc(c, &sc->sc_outq))
3f431cc4
BJ
263 sleep((caddr_t)&lbolt, LPPRI);
264}
265
5ffed226
BJ
266lpintr(lp11)
267 int lp11;
3f431cc4
BJ
268{
269 register int n;
5ffed226
BJ
270 register struct lp_softc *sc = &lp_softc[lp11];
271 register struct uba_device *ui = lpinfo[lp11];
272 register struct lpdevice *lpaddr = (struct lpdevice *)ui->ui_addr;
ca063532 273
ca063532
MT
274 lpaddr->lpsr &= ~IENABLE;
275 n = sc->sc_outq.c_cc;
276 if (sc->sc_lpchar < 0)
277 sc->sc_lpchar = getc(&sc->sc_outq);
278 while ((lpaddr->lpsr&DONE) && sc->sc_lpchar >= 0) {
279 lpaddr->lpbuf = sc->sc_lpchar;
280 sc->sc_lpchar = getc(&sc->sc_outq);
3f431cc4 281 }
ca063532
MT
282 sc->sc_state |= MOD;
283 if (sc->sc_outq.c_cc > 0 && (lpaddr->lpsr&ERROR)==0)
284 lpaddr->lpsr |= IENABLE; /* ok and more to do later */
285 if (n>LPLWAT && sc->sc_outq.c_cc<=LPLWAT && sc->sc_state&ASLP) {
286 sc->sc_state &= ~ASLP;
287 wakeup((caddr_t)sc); /* top half should go on */
3f431cc4
BJ
288 }
289}
290
ca063532 291lptout(dev)
5ffed226 292 dev_t dev;
3f431cc4 293{
ca063532
MT
294 register struct lp_softc *sc;
295 register struct uba_device *ui;
296 register struct lpdevice *lpaddr;
297
298 sc = &lp_softc[LPUNIT(dev)];
299 ui = lpinfo[LPUNIT(dev)];
300 lpaddr = (struct lpdevice *) ui->ui_addr;
301 if ((sc->sc_state&MOD) != 0) {
302 sc->sc_state &= ~MOD; /* something happened */
303 timeout(lptout, dev, 2*hz); /* so don't sweat */
3f431cc4
BJ
304 return;
305 }
ca063532
MT
306 if ((sc->sc_state&OPEN) == 0) {
307 sc->sc_state &= ~TOUT; /* no longer open */
308 lpaddr->lpsr = 0;
3f431cc4
BJ
309 return;
310 }
ca063532 311 if (sc->sc_outq.c_cc && (lpaddr->lpsr&DONE) && (lpaddr->lpsr&ERROR)==0)
5ffed226 312 lpintr(LPUNIT(dev)); /* ready to go */
ca063532 313 timeout(lptout, dev, 10*hz);
3f431cc4
BJ
314}
315
ca063532 316lpreset(uban)
5ffed226 317 int uban;
3f431cc4 318{
ca063532
MT
319 register struct uba_device *ui;
320 register struct lpdevice *lpaddr;
321 register int unit;
322
5ffed226
BJ
323 for (unit = 0; unit < NLP; unit++) {
324 if ((ui = lpinfo[unit]) == 0 || ui->ui_ubanum != uban ||
325 ui->ui_alive == 0)
ca063532
MT
326 continue;
327 printf(" lp%d", unit);
5ffed226 328 lpaddr = (struct lpdevice *)ui->ui_addr;
ca063532 329 lpaddr->lpsr |= IENABLE;
3f431cc4
BJ
330 }
331}