|
|
1.1 root 1: /* lp.c 6.1 83/07/29 */
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: #include "../machine/pte.h"
12:
13: #include "../h/param.h"
14: #include "../h/dir.h"
15: #include "../h/user.h"
16: #include "../h/buf.h"
17: #include "../h/systm.h"
18: #include "../h/map.h"
19: #include "../h/uio.h"
20: #include "../h/tty.h"
21: #include "../h/kernel.h"
22:
23: #include "../vaxuba/ubavar.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: short sc_maxcol;
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: 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: if (ui->ui_flags)
77: sc->sc_maxcol = ui->ui_flags;
78: else
79: sc->sc_maxcol = MAXCOL;
80: }
81:
82: lpprobe(reg)
83: caddr_t reg;
84: {
85: register int br, cvec; /* value-result */
86: register struct lpdevice *lpaddr = (struct lpdevice *)reg;
87: #ifdef lint
88: br = 0; cvec = br; br = cvec;
89: lpintr(0);
90: #endif
91:
92: lpaddr->lpsr = IENABLE;
93: DELAY(5);
94: lpaddr->lpsr = 0;
95: return (sizeof (struct lpdevice));
96: }
97:
98: /*ARGSUSED*/
99: lpopen(dev, flag)
100: dev_t dev;
101: int flag;
102: {
103: register int unit;
104: register struct lpdevice *lpaddr;
105: register struct lp_softc *sc;
106: register struct uba_device *ui;
107:
108: if ((unit = LPUNIT(dev)) >= NLP ||
109: (sc = &lp_softc[unit])->sc_state&OPEN ||
110: (ui = lpinfo[unit]) == 0 || ui->ui_alive == 0)
111: return (ENXIO);
112: lpaddr = (struct lpdevice *)ui->ui_addr;
113: if (lpaddr->lpsr&ERROR)
114: return (EIO);
115: sc->sc_state |= OPEN;
116: sc->sc_inbuf = geteblk(512);
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: return (0);
126: }
127:
128: /*ARGSUSED*/
129: lpclose(dev, flag)
130: dev_t dev;
131: int flag;
132: {
133: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
134:
135: lpcanon(dev, '\f');
136: brelse(sc->sc_inbuf);
137: sc->sc_state &= ~OPEN;
138: }
139:
140: lpwrite(dev, uio)
141: dev_t dev;
142: struct uio *uio;
143: {
144: register unsigned n;
145: register char *cp;
146: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
147: int error;
148:
149: while (n = min(512, (unsigned)uio->uio_resid)) {
150: cp = sc->sc_inbuf->b_un.b_addr;
151: error = uiomove(cp, (int)n, UIO_WRITE, uio);
152: if (error)
153: return (error);
154: do
155: lpcanon(dev, *cp++);
156: while (--n);
157: }
158: return (0);
159: }
160:
161: lpcanon(dev, c)
162: dev_t dev;
163: register int c;
164: {
165: register int logcol, physcol;
166: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
167:
168: if (sc->sc_flags&CAP) {
169: register c2;
170:
171: if (c>='a' && c<='z')
172: c += 'A'-'a'; else
173: switch (c) {
174:
175: case '{':
176: c2 = '(';
177: goto esc;
178:
179: case '}':
180: c2 = ')';
181: goto esc;
182:
183: case '`':
184: c2 = '\'';
185: goto esc;
186:
187: case '|':
188: c2 = '!';
189: goto esc;
190:
191: case '~':
192: c2 = '^';
193:
194: esc:
195: lpcanon(dev, c2);
196: sc->sc_logcol--;
197: c = '-';
198: }
199: }
200: logcol = sc->sc_logcol;
201: physcol = sc->sc_physcol;
202: if (c == ' ')
203: logcol++;
204: else switch(c) {
205:
206: case '\t':
207: logcol = (logcol+8) & ~7;
208: break;
209:
210: case '\f':
211: if (sc->sc_physline == 0 && physcol == 0)
212: break;
213: /* fall into ... */
214:
215: case '\n':
216: lpoutput(dev, c);
217: if (c == '\f')
218: sc->sc_physline = 0;
219: else
220: sc->sc_physline++;
221: physcol = 0;
222: /* fall into ... */
223:
224: case '\r':
225: logcol = 0;
226: (void) spl4();
227: lpintr(LPUNIT(dev));
228: (void) spl0();
229: break;
230:
231: case '\b':
232: if (logcol > 0)
233: logcol--;
234: break;
235:
236: default:
237: if (logcol < physcol) {
238: lpoutput(dev, '\r');
239: physcol = 0;
240: }
241: if (logcol < sc->sc_maxcol) {
242: while (logcol > physcol) {
243: lpoutput(dev, ' ');
244: physcol++;
245: }
246: lpoutput(dev, c);
247: physcol++;
248: }
249: logcol++;
250: }
251: if (logcol > 1000) /* ignore long lines */
252: logcol = 1000;
253: sc->sc_logcol = logcol;
254: sc->sc_physcol = physcol;
255: }
256:
257: lpoutput(dev, c)
258: dev_t dev;
259: int c;
260: {
261: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
262:
263: if (sc->sc_outq.c_cc >= LPHWAT) {
264: (void) spl4();
265: lpintr(LPUNIT(dev)); /* unchoke */
266: while (sc->sc_outq.c_cc >= LPHWAT) {
267: sc->sc_state |= ASLP; /* must be ERROR */
268: sleep((caddr_t)sc, LPPRI);
269: }
270: (void) spl0();
271: }
272: while (putc(c, &sc->sc_outq))
273: sleep((caddr_t)&lbolt, LPPRI);
274: }
275:
276: lpintr(lp11)
277: int lp11;
278: {
279: register int n;
280: register struct lp_softc *sc = &lp_softc[lp11];
281: register struct uba_device *ui = lpinfo[lp11];
282: register struct lpdevice *lpaddr = (struct lpdevice *)ui->ui_addr;
283:
284: lpaddr->lpsr &= ~IENABLE;
285: n = sc->sc_outq.c_cc;
286: if (sc->sc_lpchar < 0)
287: sc->sc_lpchar = getc(&sc->sc_outq);
288: while ((lpaddr->lpsr&DONE) && sc->sc_lpchar >= 0) {
289: lpaddr->lpbuf = sc->sc_lpchar;
290: sc->sc_lpchar = getc(&sc->sc_outq);
291: }
292: sc->sc_state |= MOD;
293: if (sc->sc_outq.c_cc > 0 && (lpaddr->lpsr&ERROR)==0)
294: lpaddr->lpsr |= IENABLE; /* ok and more to do later */
295: if (n>LPLWAT && sc->sc_outq.c_cc<=LPLWAT && sc->sc_state&ASLP) {
296: sc->sc_state &= ~ASLP;
297: wakeup((caddr_t)sc); /* top half should go on */
298: }
299: }
300:
301: lptout(dev)
302: dev_t dev;
303: {
304: register struct lp_softc *sc;
305: register struct uba_device *ui;
306: register struct lpdevice *lpaddr;
307:
308: sc = &lp_softc[LPUNIT(dev)];
309: ui = lpinfo[LPUNIT(dev)];
310: lpaddr = (struct lpdevice *) ui->ui_addr;
311: if ((sc->sc_state&MOD) != 0) {
312: sc->sc_state &= ~MOD; /* something happened */
313: timeout(lptout, (caddr_t)dev, 2*hz); /* so don't sweat */
314: return;
315: }
316: if ((sc->sc_state&OPEN) == 0) {
317: sc->sc_state &= ~TOUT; /* no longer open */
318: lpaddr->lpsr = 0;
319: return;
320: }
321: if (sc->sc_outq.c_cc && (lpaddr->lpsr&DONE) && (lpaddr->lpsr&ERROR)==0)
322: lpintr(LPUNIT(dev)); /* ready to go */
323: timeout(lptout, (caddr_t)dev, 10*hz);
324: }
325:
326: lpreset(uban)
327: int uban;
328: {
329: register struct uba_device *ui;
330: register struct lpdevice *lpaddr;
331: register int unit;
332:
333: for (unit = 0; unit < NLP; unit++) {
334: if ((ui = lpinfo[unit]) == 0 || ui->ui_ubanum != uban ||
335: ui->ui_alive == 0)
336: continue;
337: printf(" lp%d", unit);
338: lpaddr = (struct lpdevice *)ui->ui_addr;
339: lpaddr->lpsr |= IENABLE;
340: }
341: }
342: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.