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