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