|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)lp.c 7.7 (Berkeley) 4/12/90
7: */
8:
9: #include "lp.h"
10: #if NLP > 0
11: /*
12: * LP-11 Line printer driver
13: *
14: * This driver has been modified to work on printers where
15: * leaving IENABLE set would cause continuous interrupts.
16: */
17: #include "machine/pte.h"
18:
19: #include "param.h"
20: #include "user.h"
21: #include "buf.h"
22: #include "conf.h"
23: #include "systm.h"
24: #include "map.h"
25: #include "uio.h"
26: #include "ioctl.h"
27: #include "tty.h"
28: #include "kernel.h"
29:
30: #include "ubavar.h"
31:
32: #define LPPRI (PZERO+8)
33: #define IENABLE 0100
34: #define DONE 0200
35: #define ERROR 0100000
36: #define LPLWAT 650
37: #define LPHWAT 800
38:
39: #define LPBUFSIZE 1024
40: #define MAXCOL 132
41: #define CAP 1
42:
43: #define LPUNIT(dev) (minor(dev) >> 3)
44:
45: struct lpdevice {
46: short lpsr;
47: short lpbuf;
48: };
49:
50: struct lp_softc {
51: struct clist sc_outq;
52: int sc_state;
53: int sc_physcol;
54: int sc_logcol;
55: int sc_physline;
56: char sc_flags;
57: short sc_maxcol;
58: int sc_lpchar;
59: struct buf *sc_inbuf;
60: } lp_softc[NLP];
61:
62: struct uba_device *lpinfo[NLP];
63:
64: int lpprobe(), lpattach(), lptout();
65: u_short lpstd[] = { 0177514, 0 };
66: struct uba_driver lpdriver =
67: { lpprobe, 0, lpattach, 0, lpstd, "lp", lpinfo };
68:
69: /* bits for state */
70: #define OPEN 1 /* device is open */
71: #define TOUT 2 /* timeout is active */
72: #define MOD 4 /* device state has been modified */
73: #define ASLP 8 /* awaiting draining of printer */
74:
75: lpattach(ui)
76: struct uba_device *ui;
77: {
78: register struct lp_softc *sc;
79:
80: sc = &lp_softc[ui->ui_unit];
81: sc->sc_lpchar = -1;
82: if (ui->ui_flags)
83: sc->sc_maxcol = ui->ui_flags;
84: else
85: sc->sc_maxcol = MAXCOL;
86: }
87:
88: lpprobe(reg)
89: caddr_t reg;
90: {
91: register int br, cvec; /* value-result */
92: register struct lpdevice *lpaddr = (struct lpdevice *)reg;
93: #ifdef lint
94: br = 0; cvec = br; br = cvec;
95: lpintr(0);
96: #endif
97:
98: lpaddr->lpsr = IENABLE;
99: DELAY(5);
100: lpaddr->lpsr = 0;
101: return (sizeof (struct lpdevice));
102: }
103:
104: /*ARGSUSED*/
105: lpopen(dev, flag)
106: dev_t dev;
107: int flag;
108: {
109: register struct lpdevice *lpaddr;
110: register struct lp_softc *sc;
111: register struct uba_device *ui;
112: register int unit, s;
113:
114: if ((unit = LPUNIT(dev)) >= NLP ||
115: (sc = &lp_softc[unit])->sc_state&OPEN ||
116: (ui = lpinfo[unit]) == 0 || ui->ui_alive == 0)
117: return (ENXIO);
118: lpaddr = (struct lpdevice *)ui->ui_addr;
119: if (lpaddr->lpsr&ERROR)
120: return (EIO);
121: sc->sc_state |= OPEN;
122: sc->sc_inbuf = geteblk(LPBUFSIZE);
123: sc->sc_flags = minor(dev) & 07;
124: s = spl4();
125: if ((sc->sc_state&TOUT) == 0) {
126: sc->sc_state |= TOUT;
127: timeout(lptout, (caddr_t)dev, 10*hz);
128: }
129: splx(s);
130: lpcanon(dev, '\f');
131: return (0);
132: }
133:
134: /*ARGSUSED*/
135: lpclose(dev, flag)
136: dev_t dev;
137: int flag;
138: {
139: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
140:
141: lpcanon(dev, '\f');
142: brelse(sc->sc_inbuf);
143: sc->sc_state &= ~OPEN;
144: return (0);
145: }
146:
147: lpwrite(dev, uio)
148: dev_t dev;
149: struct uio *uio;
150: {
151: register unsigned n;
152: register char *cp;
153: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
154: int error;
155:
156: while (n = MIN(LPBUFSIZE, (unsigned)uio->uio_resid)) {
157: cp = sc->sc_inbuf->b_un.b_addr;
158: error = uiomove(cp, (int)n, uio);
159: if (error)
160: return (error);
161: do
162: lpcanon(dev, *cp++);
163: while (--n);
164: }
165: return (0);
166: }
167:
168: lpcanon(dev, c)
169: dev_t dev;
170: register int c;
171: {
172: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
173: register int logcol, physcol, s;
174:
175: if (sc->sc_flags&CAP) {
176: register c2;
177:
178: if (c>='a' && c<='z')
179: c += 'A'-'a'; else
180: switch (c) {
181:
182: case '{':
183: c2 = '(';
184: goto esc;
185:
186: case '}':
187: c2 = ')';
188: goto esc;
189:
190: case '`':
191: c2 = '\'';
192: goto esc;
193:
194: case '|':
195: c2 = '!';
196: goto esc;
197:
198: case '~':
199: c2 = '^';
200:
201: esc:
202: lpcanon(dev, c2);
203: sc->sc_logcol--;
204: c = '-';
205: }
206: }
207: logcol = sc->sc_logcol;
208: physcol = sc->sc_physcol;
209: if (c == ' ')
210: logcol++;
211: else switch(c) {
212:
213: case '\t':
214: logcol = (logcol+8) & ~7;
215: break;
216:
217: case '\f':
218: if (sc->sc_physline == 0 && physcol == 0)
219: break;
220: /* fall into ... */
221:
222: case '\n':
223: lpoutput(dev, c);
224: if (c == '\f')
225: sc->sc_physline = 0;
226: else
227: sc->sc_physline++;
228: physcol = 0;
229: /* fall into ... */
230:
231: case '\r':
232: s = spl4();
233: logcol = 0;
234: lpintr(LPUNIT(dev));
235: splx(s);
236: break;
237:
238: case '\b':
239: if (logcol > 0)
240: logcol--;
241: break;
242:
243: default:
244: if (logcol < physcol) {
245: lpoutput(dev, '\r');
246: physcol = 0;
247: }
248: if (logcol < sc->sc_maxcol) {
249: while (logcol > physcol) {
250: lpoutput(dev, ' ');
251: physcol++;
252: }
253: lpoutput(dev, c);
254: physcol++;
255: }
256: logcol++;
257: }
258: if (logcol > 1000) /* ignore long lines */
259: logcol = 1000;
260: sc->sc_logcol = logcol;
261: sc->sc_physcol = physcol;
262: }
263:
264: lpoutput(dev, c)
265: dev_t dev;
266: int c;
267: {
268: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
269: int s, error = 0;
270:
271: if (sc->sc_outq.c_cc >= LPHWAT) {
272: s = spl4();
273: lpintr(LPUNIT(dev)); /* unchoke */
274: while (sc->sc_outq.c_cc >= LPHWAT && error == 0) {
275: sc->sc_state |= ASLP; /* must be ERROR */
276: error = tsleep((caddr_t)sc, LPPRI | PCATCH,
277: devout, 0);
278: }
279: splx(s);
280: }
281: while (error == 0 && putc(c, &sc->sc_outq))
282: error = tsleep((caddr_t)&lbolt, LPPRI | PCATCH,
283: ttybuf, 0);
284: return (error);
285: }
286:
287: lpintr(lp11)
288: int lp11;
289: {
290: register int n;
291: register struct lp_softc *sc = &lp_softc[lp11];
292: register struct uba_device *ui = lpinfo[lp11];
293: register struct lpdevice *lpaddr = (struct lpdevice *)ui->ui_addr;
294:
295: lpaddr->lpsr &= ~IENABLE;
296: n = sc->sc_outq.c_cc;
297: if (sc->sc_lpchar < 0)
298: sc->sc_lpchar = getc(&sc->sc_outq);
299: while ((lpaddr->lpsr&DONE) && sc->sc_lpchar >= 0) {
300: lpaddr->lpbuf = sc->sc_lpchar;
301: sc->sc_lpchar = getc(&sc->sc_outq);
302: }
303: sc->sc_state |= MOD;
304: if (sc->sc_outq.c_cc > 0 && (lpaddr->lpsr&ERROR)==0)
305: lpaddr->lpsr |= IENABLE; /* ok and more to do later */
306: if (n>LPLWAT && sc->sc_outq.c_cc<=LPLWAT && sc->sc_state&ASLP) {
307: sc->sc_state &= ~ASLP;
308: wakeup((caddr_t)sc); /* top half should go on */
309: }
310: }
311:
312: lptout(dev)
313: dev_t dev;
314: {
315: register struct lp_softc *sc;
316: register struct uba_device *ui;
317: register struct lpdevice *lpaddr;
318:
319: sc = &lp_softc[LPUNIT(dev)];
320: ui = lpinfo[LPUNIT(dev)];
321: lpaddr = (struct lpdevice *) ui->ui_addr;
322: if ((sc->sc_state&MOD) != 0) {
323: sc->sc_state &= ~MOD; /* something happened */
324: timeout(lptout, (caddr_t)dev, 2*hz); /* so don't sweat */
325: return;
326: }
327: if ((sc->sc_state&OPEN) == 0 && sc->sc_outq.c_cc == 0) {
328: sc->sc_state &= ~TOUT; /* no longer open */
329: lpaddr->lpsr = 0;
330: return;
331: }
332: if (sc->sc_outq.c_cc && (lpaddr->lpsr&DONE) && (lpaddr->lpsr&ERROR)==0)
333: lpintr(LPUNIT(dev)); /* ready to go */
334: timeout(lptout, (caddr_t)dev, 10*hz);
335: }
336:
337: lpreset(uban)
338: int uban;
339: {
340: register struct uba_device *ui;
341: register struct lpdevice *lpaddr;
342: register int unit;
343:
344: for (unit = 0; unit < NLP; unit++) {
345: if ((ui = lpinfo[unit]) == 0 || ui->ui_ubanum != uban ||
346: ui->ui_alive == 0)
347: continue;
348: printf(" lp%d", unit);
349: lpaddr = (struct lpdevice *)ui->ui_addr;
350: lpaddr->lpsr |= IENABLE;
351: }
352: }
353: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.