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