1: /*
2: * Copyright (c) 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 1.3 (2.11BSD GTE) 1997/2/14
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 LP_IE set would cause continuous interrupts.
16: */
17: #include "param.h"
18: #include "systm.h"
19: #include "user.h"
20: #include "ioctl.h"
21: #include "tty.h"
22: #include "uio.h"
23: #include "kernel.h"
24:
25: #define LPPRI (PZERO + 8)
26: #define LP_IE 0100 /* interrupt enable */
27: #define LP_RDY 0200 /* ready */
28: #define LP_ERR 0100000 /* error */
29: #define LPLWAT 40
30: #define LPHWAT 400
31:
32: #define LPBUFSIZE 512
33: #define CAP 1
34: #ifndef LP_MAXCOL
35: #define LP_MAXCOL 132
36: #endif
37:
38: #define LPUNIT(dev) (minor(dev) >> 3)
39:
40: struct lpdevice {
41: short lpcs;
42: short lpdb;
43: };
44:
45: struct lp_softc {
46: struct clist sc_outq;
47: int sc_state;
48: int sc_physcol;
49: int sc_logcol;
50: int sc_physline;
51: char sc_flags;
52: int sc_lpchar;
53: } lp_softc[NLP];
54:
55: struct lpdevice *lp_addr[NLP];
56:
57: int lptout();
58:
59: /* bits for state */
60: #define OPEN 1 /* device is open */
61: #define TOUT 2 /* timeout is active */
62: #define MOD 4 /* device state has been modified */
63: #define ASLP 8 /* awaiting draining of printer */
64:
65: lpattach(addr, unit)
66: struct lpdevice *addr;
67: register u_int unit;
68: {
69: if (unit >= NLP)
70: return (0);
71: lp_addr[unit] = addr;
72: return (1);
73: }
74:
75: /*ARGSUSED*/
76: lpopen(dev, flag)
77: dev_t dev;
78: int flag;
79: {
80: register struct lp_softc *sc;
81: register int unit, s;
82:
83: if ((unit = LPUNIT(dev)) >= NLP ||
84: (sc = &lp_softc[unit])->sc_state&OPEN ||
85: lp_addr[unit] == 0)
86: return (ENXIO);
87: if (lp_addr[unit]->lpcs&LP_ERR)
88: return (EIO);
89: sc->sc_state |= OPEN;
90: sc->sc_flags = minor(dev) & 07;
91: s = spl4();
92: if ((sc->sc_state&TOUT) == 0) {
93: sc->sc_state |= TOUT;
94: timeout(lptout, (caddr_t)dev, 10*hz);
95: }
96: splx(s);
97: lpcanon(dev, '\f');
98: return (0);
99: }
100:
101: /*ARGSUSED*/
102: lpclose(dev, flag)
103: dev_t dev;
104: int flag;
105: {
106: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
107:
108: lpcanon(dev, '\f');
109: sc->sc_state &= ~OPEN;
110: }
111:
112: lpwrite(dev, uio, flag)
113: register dev_t dev;
114: register struct uio *uio;
115: int flag;
116: {
117: register int n;
118: register char *cp;
119: char inbuf[LPBUFSIZE];
120: int error;
121:
122: while (n = MIN(LPBUFSIZE, uio->uio_resid)) {
123: cp = inbuf;
124: error = uiomove(cp, (int)n, uio);
125: if (error)
126: return (error);
127: do
128: lpcanon(dev, *cp++);
129: while (--n);
130: }
131: return (0);
132: }
133:
134: lpcanon(dev, c)
135: dev_t dev;
136: register int c;
137: {
138: struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
139: register int logcol, physcol, s;
140:
141: if (sc->sc_flags&CAP) {
142: register c2;
143:
144: if (c >= 'a' && c <= 'z')
145: c += 'A'-'a'; else
146: switch (c) {
147:
148: case '{':
149: c2 = '(';
150: goto esc;
151:
152: case '}':
153: c2 = ')';
154: goto esc;
155:
156: case '`':
157: c2 = '\'';
158: goto esc;
159:
160: case '|':
161: c2 = '!';
162: goto esc;
163:
164: case '~':
165: c2 = '^';
166:
167: esc:
168: lpcanon(dev, c2);
169: sc->sc_logcol--;
170: c = '-';
171: }
172: }
173: logcol = sc->sc_logcol;
174: physcol = sc->sc_physcol;
175: if (c == ' ')
176: logcol++;
177: else switch(c) {
178:
179: case '\t':
180: logcol = (logcol + 8) & ~7;
181: break;
182:
183: case '\f':
184: if (sc->sc_physline == 0 && physcol == 0)
185: break;
186: /* fall into ... */
187:
188: case '\n':
189: lpoutput(dev, c);
190: if (c == '\f')
191: sc->sc_physline = 0;
192: else
193: sc->sc_physline++;
194: physcol = 0;
195: /* fall into ... */
196:
197: case '\r':
198: s = spl4();
199: logcol = 0;
200: lpintr(LPUNIT(dev));
201: splx(s);
202: break;
203:
204: case '\b':
205: if (logcol > 0)
206: logcol--;
207: break;
208:
209: default:
210: if (logcol < physcol) {
211: lpoutput(dev, '\r');
212: physcol = 0;
213: }
214: if (logcol < LP_MAXCOL) {
215: while (logcol > physcol) {
216: lpoutput(dev, ' ');
217: physcol++;
218: }
219: lpoutput(dev, c);
220: physcol++;
221: }
222: logcol++;
223: }
224: if (logcol > 1000) /* ignore long lines */
225: logcol = 1000;
226: sc->sc_logcol = logcol;
227: sc->sc_physcol = physcol;
228: }
229:
230: lpoutput(dev, c)
231: dev_t dev;
232: int c;
233: {
234: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
235: int s;
236:
237: if (sc->sc_outq.c_cc >= LPHWAT) {
238: s = spl4();
239: lpintr(LPUNIT(dev)); /* unchoke */
240: while (sc->sc_outq.c_cc >= LPHWAT) {
241: sc->sc_state |= ASLP; /* must be LP_ERR */
242: sleep((caddr_t)sc, LPPRI);
243: }
244: splx(s);
245: }
246: while (putc(c, &sc->sc_outq))
247: sleep((caddr_t)&lbolt, LPPRI);
248: }
249:
250: lpintr(lp11)
251: int lp11;
252: {
253: register int n;
254: register struct lp_softc *sc = &lp_softc[lp11];
255: register struct lpdevice *lpaddr = lp_addr[lp11];
256:
257: lpaddr->lpcs &= ~LP_IE;
258: n = sc->sc_outq.c_cc;
259: if (sc->sc_lpchar < 0)
260: sc->sc_lpchar = getc(&sc->sc_outq);
261: while ((lpaddr->lpcs & LP_RDY) && sc->sc_lpchar >= 0) {
262: lpaddr->lpdb = sc->sc_lpchar;
263: sc->sc_lpchar = getc(&sc->sc_outq);
264: }
265: sc->sc_state |= MOD;
266: if (sc->sc_outq.c_cc > 0 && (lpaddr->lpcs&LP_ERR) == 0)
267: lpaddr->lpcs |= LP_IE; /* ok and more to do later */
268: if (n>LPLWAT && sc->sc_outq.c_cc<=LPLWAT && sc->sc_state&ASLP) {
269: sc->sc_state &= ~ASLP;
270: wakeup((caddr_t)sc); /* top half should go on */
271: }
272: }
273:
274: lptout(dev)
275: dev_t dev;
276: {
277: register struct lp_softc *sc;
278: register struct lpdevice *lpaddr;
279:
280: sc = &lp_softc[LPUNIT(dev)];
281: lpaddr = lp_addr[LPUNIT(dev)];
282: if ((sc->sc_state&MOD) != 0) {
283: sc->sc_state &= ~MOD; /* something happened */
284: /* so don't sweat */
285: timeout(lptout, (caddr_t)dev, 2*hz);
286: return;
287: }
288: if ((sc->sc_state&OPEN) == 0 && sc->sc_outq.c_cc == 0) {
289: sc->sc_state &= ~TOUT; /* no longer open */
290: lpaddr->lpcs = 0;
291: return;
292: }
293: if (sc->sc_outq.c_cc && (lpaddr->lpcs&LP_RDY) &&
294: (lpaddr->lpcs&LP_ERR)==0)
295: lpintr(LPUNIT(dev)); /* ready to go */
296: timeout(lptout, (caddr_t)dev, 10*hz);
297: }
298: #endif
Defined functions
Defined variables
Defined struct's
Defined macros
ASLP
defined in line
63; used 3 times
CAP
defined in line
33; used 1 times
LPPRI
defined in line
25; used 2 times
LP_IE
defined in line
26; used 2 times
MOD
defined in line
62; used 3 times
OPEN
defined in line
60; used 4 times
TOUT
defined in line
61; used 3 times