|
|
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.1 (Berkeley) 6/5/86 ! 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 "dir.h" ! 21: #include "user.h" ! 22: #include "buf.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: } ! 145: ! 146: lpwrite(dev, uio) ! 147: dev_t dev; ! 148: struct uio *uio; ! 149: { ! 150: register unsigned n; ! 151: register char *cp; ! 152: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)]; ! 153: int error; ! 154: ! 155: while (n = MIN(LPBUFSIZE, (unsigned)uio->uio_resid)) { ! 156: cp = sc->sc_inbuf->b_un.b_addr; ! 157: error = uiomove(cp, (int)n, UIO_WRITE, uio); ! 158: if (error) ! 159: return (error); ! 160: do ! 161: lpcanon(dev, *cp++); ! 162: while (--n); ! 163: } ! 164: return (0); ! 165: } ! 166: ! 167: lpcanon(dev, c) ! 168: dev_t dev; ! 169: register int c; ! 170: { ! 171: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)]; ! 172: register int logcol, physcol, s; ! 173: ! 174: if (sc->sc_flags&CAP) { ! 175: register c2; ! 176: ! 177: if (c>='a' && c<='z') ! 178: c += 'A'-'a'; else ! 179: switch (c) { ! 180: ! 181: case '{': ! 182: c2 = '('; ! 183: goto esc; ! 184: ! 185: case '}': ! 186: c2 = ')'; ! 187: goto esc; ! 188: ! 189: case '`': ! 190: c2 = '\''; ! 191: goto esc; ! 192: ! 193: case '|': ! 194: c2 = '!'; ! 195: goto esc; ! 196: ! 197: case '~': ! 198: c2 = '^'; ! 199: ! 200: esc: ! 201: lpcanon(dev, c2); ! 202: sc->sc_logcol--; ! 203: c = '-'; ! 204: } ! 205: } ! 206: logcol = sc->sc_logcol; ! 207: physcol = sc->sc_physcol; ! 208: if (c == ' ') ! 209: logcol++; ! 210: else switch(c) { ! 211: ! 212: case '\t': ! 213: logcol = (logcol+8) & ~7; ! 214: break; ! 215: ! 216: case '\f': ! 217: if (sc->sc_physline == 0 && physcol == 0) ! 218: break; ! 219: /* fall into ... */ ! 220: ! 221: case '\n': ! 222: lpoutput(dev, c); ! 223: if (c == '\f') ! 224: sc->sc_physline = 0; ! 225: else ! 226: sc->sc_physline++; ! 227: physcol = 0; ! 228: /* fall into ... */ ! 229: ! 230: case '\r': ! 231: s = spl4(); ! 232: logcol = 0; ! 233: lpintr(LPUNIT(dev)); ! 234: splx(s); ! 235: break; ! 236: ! 237: case '\b': ! 238: if (logcol > 0) ! 239: logcol--; ! 240: break; ! 241: ! 242: default: ! 243: if (logcol < physcol) { ! 244: lpoutput(dev, '\r'); ! 245: physcol = 0; ! 246: } ! 247: if (logcol < sc->sc_maxcol) { ! 248: while (logcol > physcol) { ! 249: lpoutput(dev, ' '); ! 250: physcol++; ! 251: } ! 252: lpoutput(dev, c); ! 253: physcol++; ! 254: } ! 255: logcol++; ! 256: } ! 257: if (logcol > 1000) /* ignore long lines */ ! 258: logcol = 1000; ! 259: sc->sc_logcol = logcol; ! 260: sc->sc_physcol = physcol; ! 261: } ! 262: ! 263: lpoutput(dev, c) ! 264: dev_t dev; ! 265: int c; ! 266: { ! 267: register struct lp_softc *sc = &lp_softc[LPUNIT(dev)]; ! 268: int s; ! 269: ! 270: if (sc->sc_outq.c_cc >= LPHWAT) { ! 271: s = spl4(); ! 272: lpintr(LPUNIT(dev)); /* unchoke */ ! 273: while (sc->sc_outq.c_cc >= LPHWAT) { ! 274: sc->sc_state |= ASLP; /* must be ERROR */ ! 275: sleep((caddr_t)sc, LPPRI); ! 276: } ! 277: splx(s); ! 278: } ! 279: while (putc(c, &sc->sc_outq)) ! 280: sleep((caddr_t)&lbolt, LPPRI); ! 281: } ! 282: ! 283: lpintr(lp11) ! 284: int lp11; ! 285: { ! 286: register int n; ! 287: register struct lp_softc *sc = &lp_softc[lp11]; ! 288: register struct uba_device *ui = lpinfo[lp11]; ! 289: register struct lpdevice *lpaddr = (struct lpdevice *)ui->ui_addr; ! 290: ! 291: lpaddr->lpsr &= ~IENABLE; ! 292: n = sc->sc_outq.c_cc; ! 293: if (sc->sc_lpchar < 0) ! 294: sc->sc_lpchar = getc(&sc->sc_outq); ! 295: while ((lpaddr->lpsr&DONE) && sc->sc_lpchar >= 0) { ! 296: lpaddr->lpbuf = sc->sc_lpchar; ! 297: sc->sc_lpchar = getc(&sc->sc_outq); ! 298: } ! 299: sc->sc_state |= MOD; ! 300: if (sc->sc_outq.c_cc > 0 && (lpaddr->lpsr&ERROR)==0) ! 301: lpaddr->lpsr |= IENABLE; /* ok and more to do later */ ! 302: if (n>LPLWAT && sc->sc_outq.c_cc<=LPLWAT && sc->sc_state&ASLP) { ! 303: sc->sc_state &= ~ASLP; ! 304: wakeup((caddr_t)sc); /* top half should go on */ ! 305: } ! 306: } ! 307: ! 308: lptout(dev) ! 309: dev_t dev; ! 310: { ! 311: register struct lp_softc *sc; ! 312: register struct uba_device *ui; ! 313: register struct lpdevice *lpaddr; ! 314: ! 315: sc = &lp_softc[LPUNIT(dev)]; ! 316: ui = lpinfo[LPUNIT(dev)]; ! 317: lpaddr = (struct lpdevice *) ui->ui_addr; ! 318: if ((sc->sc_state&MOD) != 0) { ! 319: sc->sc_state &= ~MOD; /* something happened */ ! 320: timeout(lptout, (caddr_t)dev, 2*hz); /* so don't sweat */ ! 321: return; ! 322: } ! 323: if ((sc->sc_state&OPEN) == 0 && sc->sc_outq.c_cc == 0) { ! 324: sc->sc_state &= ~TOUT; /* no longer open */ ! 325: lpaddr->lpsr = 0; ! 326: return; ! 327: } ! 328: if (sc->sc_outq.c_cc && (lpaddr->lpsr&DONE) && (lpaddr->lpsr&ERROR)==0) ! 329: lpintr(LPUNIT(dev)); /* ready to go */ ! 330: timeout(lptout, (caddr_t)dev, 10*hz); ! 331: } ! 332: ! 333: lpreset(uban) ! 334: int uban; ! 335: { ! 336: register struct uba_device *ui; ! 337: register struct lpdevice *lpaddr; ! 338: register int unit; ! 339: ! 340: for (unit = 0; unit < NLP; unit++) { ! 341: if ((ui = lpinfo[unit]) == 0 || ui->ui_ubanum != uban || ! 342: ui->ui_alive == 0) ! 343: continue; ! 344: printf(" lp%d", unit); ! 345: lpaddr = (struct lpdevice *)ui->ui_addr; ! 346: lpaddr->lpsr |= IENABLE; ! 347: } ! 348: } ! 349: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.