|
|
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.