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