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

Defined functions

lpattach defined in line 75; used 2 times
lpcanon defined in line 167; used 4 times
lpclose defined in line 135; never used
lpintr defined in line 283; used 5 times
lpopen defined in line 105; never used
lpoutput defined in line 263; used 4 times
lpprobe defined in line 88; used 2 times
lpreset defined in line 333; never used
lptout defined in line 308; used 4 times
lpwrite defined in line 146; never used

Defined variables

lp_softc defined in line 60; used 8 times
lpdriver defined in line 66; used 1 times
lpinfo defined in line 62; used 5 times
lpstd defined in line 65; used 1 times
  • in line 67

Defined struct's

lp_softc defined in line 50; used 16 times
lpdevice defined in line 45; used 22 times

Defined macros

ASLP defined in line 73; used 3 times
CAP defined in line 41; used 1 times
DONE defined in line 34; used 2 times
ERROR defined in line 35; used 3 times
IENABLE defined in line 33; used 4 times
LPBUFSIZE defined in line 39; used 2 times
LPHWAT defined in line 37; used 2 times
LPLWAT defined in line 36; used 2 times
  • in line 302(2)
LPPRI defined in line 32; used 2 times
LPUNIT defined in line 43; used 10 times
MAXCOL defined in line 40; used 1 times
  • in line 85
MOD defined in line 72; used 3 times
OPEN defined in line 70; used 4 times
TOUT defined in line 71; used 3 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2014
Valid CSS Valid XHTML 1.0 Strict