1: /*
   2:  * Copyright (c) 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	1.3 (2.11BSD GTE) 1997/2/14
   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 LP_IE set would cause continuous interrupts.
  16:  */
  17: #include "param.h"
  18: #include "systm.h"
  19: #include "user.h"
  20: #include "ioctl.h"
  21: #include "tty.h"
  22: #include "uio.h"
  23: #include "kernel.h"
  24: 
  25: #define LPPRI       (PZERO + 8)
  26: #define LP_IE       0100        /* interrupt enable */
  27: #define LP_RDY      0200        /* ready */
  28: #define LP_ERR      0100000     /* error */
  29: #define LPLWAT      40
  30: #define LPHWAT      400
  31: 
  32: #define LPBUFSIZE   512
  33: #define CAP     1
  34: #ifndef LP_MAXCOL
  35: #define LP_MAXCOL   132
  36: #endif
  37: 
  38: #define LPUNIT(dev) (minor(dev) >> 3)
  39: 
  40: struct lpdevice {
  41:     short   lpcs;
  42:     short   lpdb;
  43: };
  44: 
  45: struct lp_softc {
  46:     struct  clist sc_outq;
  47:     int sc_state;
  48:     int sc_physcol;
  49:     int sc_logcol;
  50:     int sc_physline;
  51:     char    sc_flags;
  52:     int sc_lpchar;
  53: } lp_softc[NLP];
  54: 
  55: struct lpdevice *lp_addr[NLP];
  56: 
  57: int lptout();
  58: 
  59: /* bits for state */
  60: #define OPEN        1   /* device is open */
  61: #define TOUT        2   /* timeout is active */
  62: #define MOD     4   /* device state has been modified */
  63: #define ASLP        8   /* awaiting draining of printer */
  64: 
  65: lpattach(addr, unit)
  66:     struct lpdevice *addr;
  67:     register u_int unit;
  68: {
  69:     if (unit >= NLP)
  70:         return (0);
  71:     lp_addr[unit] = addr;
  72:     return (1);
  73: }
  74: 
  75: /*ARGSUSED*/
  76: lpopen(dev, flag)
  77:     dev_t dev;
  78:     int flag;
  79: {
  80:     register struct lp_softc *sc;
  81:     register int unit, s;
  82: 
  83:     if ((unit = LPUNIT(dev)) >= NLP ||
  84:        (sc = &lp_softc[unit])->sc_state&OPEN ||
  85:        lp_addr[unit] == 0)
  86:         return (ENXIO);
  87:     if (lp_addr[unit]->lpcs&LP_ERR)
  88:         return (EIO);
  89:     sc->sc_state |= OPEN;
  90:     sc->sc_flags = minor(dev) & 07;
  91:     s = spl4();
  92:     if ((sc->sc_state&TOUT) == 0) {
  93:         sc->sc_state |= TOUT;
  94:         timeout(lptout, (caddr_t)dev, 10*hz);
  95:     }
  96:     splx(s);
  97:     lpcanon(dev, '\f');
  98:     return (0);
  99: }
 100: 
 101: /*ARGSUSED*/
 102: lpclose(dev, flag)
 103:     dev_t dev;
 104:     int flag;
 105: {
 106:     register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
 107: 
 108:     lpcanon(dev, '\f');
 109:     sc->sc_state &= ~OPEN;
 110: }
 111: 
 112: lpwrite(dev, uio, flag)
 113:     register dev_t dev;
 114:     register struct uio *uio;
 115:     int flag;
 116: {
 117:     register int n;
 118:     register char *cp;
 119:     char inbuf[LPBUFSIZE];
 120:     int error;
 121: 
 122:     while (n = MIN(LPBUFSIZE, uio->uio_resid)) {
 123:         cp = inbuf;
 124:         error = uiomove(cp, (int)n, uio);
 125:         if (error)
 126:             return (error);
 127:         do
 128:             lpcanon(dev, *cp++);
 129:         while (--n);
 130:     }
 131:     return (0);
 132: }
 133: 
 134: lpcanon(dev, c)
 135:     dev_t dev;
 136:     register int c;
 137: {
 138:     struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
 139:     register int logcol, physcol, s;
 140: 
 141:     if (sc->sc_flags&CAP) {
 142:         register c2;
 143: 
 144:         if (c >= 'a' && c <= 'z')
 145:             c += 'A'-'a'; else
 146:         switch (c) {
 147: 
 148:         case '{':
 149:             c2 = '(';
 150:             goto esc;
 151: 
 152:         case '}':
 153:             c2 = ')';
 154:             goto esc;
 155: 
 156:         case '`':
 157:             c2 = '\'';
 158:             goto esc;
 159: 
 160:         case '|':
 161:             c2 = '!';
 162:             goto esc;
 163: 
 164:         case '~':
 165:             c2 = '^';
 166: 
 167:         esc:
 168:             lpcanon(dev, c2);
 169:             sc->sc_logcol--;
 170:             c = '-';
 171:         }
 172:     }
 173:     logcol = sc->sc_logcol;
 174:     physcol = sc->sc_physcol;
 175:     if (c == ' ')
 176:         logcol++;
 177:     else switch(c) {
 178: 
 179:     case '\t':
 180:         logcol = (logcol + 8) & ~7;
 181:         break;
 182: 
 183:     case '\f':
 184:         if (sc->sc_physline == 0 && physcol == 0)
 185:             break;
 186:         /* fall into ... */
 187: 
 188:     case '\n':
 189:         lpoutput(dev, c);
 190:         if (c == '\f')
 191:             sc->sc_physline = 0;
 192:         else
 193:             sc->sc_physline++;
 194:         physcol = 0;
 195:         /* fall into ... */
 196: 
 197:     case '\r':
 198:         s = spl4();
 199:         logcol = 0;
 200:         lpintr(LPUNIT(dev));
 201:         splx(s);
 202:         break;
 203: 
 204:     case '\b':
 205:         if (logcol > 0)
 206:             logcol--;
 207:         break;
 208: 
 209:     default:
 210:         if (logcol < physcol) {
 211:             lpoutput(dev, '\r');
 212:             physcol = 0;
 213:         }
 214:         if (logcol < LP_MAXCOL) {
 215:             while (logcol > physcol) {
 216:                 lpoutput(dev, ' ');
 217:                 physcol++;
 218:             }
 219:             lpoutput(dev, c);
 220:             physcol++;
 221:         }
 222:         logcol++;
 223:     }
 224:     if (logcol > 1000)  /* ignore long lines  */
 225:         logcol = 1000;
 226:     sc->sc_logcol = logcol;
 227:     sc->sc_physcol = physcol;
 228: }
 229: 
 230: lpoutput(dev, c)
 231:     dev_t dev;
 232:     int c;
 233: {
 234:     register struct lp_softc *sc = &lp_softc[LPUNIT(dev)];
 235:     int s;
 236: 
 237:     if (sc->sc_outq.c_cc >= LPHWAT) {
 238:         s = spl4();
 239:         lpintr(LPUNIT(dev));                /* unchoke */
 240:         while (sc->sc_outq.c_cc >= LPHWAT) {
 241:             sc->sc_state |= ASLP;       /* must be LP_ERR */
 242:             sleep((caddr_t)sc, LPPRI);
 243:         }
 244:         splx(s);
 245:     }
 246:     while (putc(c, &sc->sc_outq))
 247:         sleep((caddr_t)&lbolt, LPPRI);
 248: }
 249: 
 250: lpintr(lp11)
 251:     int lp11;
 252: {
 253:     register int n;
 254:     register struct lp_softc *sc = &lp_softc[lp11];
 255:     register struct lpdevice *lpaddr = lp_addr[lp11];
 256: 
 257:     lpaddr->lpcs &= ~LP_IE;
 258:     n = sc->sc_outq.c_cc;
 259:     if (sc->sc_lpchar < 0)
 260:         sc->sc_lpchar = getc(&sc->sc_outq);
 261:     while ((lpaddr->lpcs & LP_RDY) && sc->sc_lpchar >= 0) {
 262:         lpaddr->lpdb = sc->sc_lpchar;
 263:         sc->sc_lpchar = getc(&sc->sc_outq);
 264:     }
 265:     sc->sc_state |= MOD;
 266:     if (sc->sc_outq.c_cc > 0 && (lpaddr->lpcs&LP_ERR) == 0)
 267:         lpaddr->lpcs |= LP_IE;      /* ok and more to do later */
 268:     if (n>LPLWAT && sc->sc_outq.c_cc<=LPLWAT && sc->sc_state&ASLP) {
 269:         sc->sc_state &= ~ASLP;
 270:         wakeup((caddr_t)sc);        /* top half should go on */
 271:     }
 272: }
 273: 
 274: lptout(dev)
 275:     dev_t dev;
 276: {
 277:     register struct lp_softc *sc;
 278:     register struct lpdevice *lpaddr;
 279: 
 280:     sc = &lp_softc[LPUNIT(dev)];
 281:     lpaddr = lp_addr[LPUNIT(dev)];
 282:     if ((sc->sc_state&MOD) != 0) {
 283:         sc->sc_state &= ~MOD;       /* something happened */
 284:                         /* so don't sweat */
 285:         timeout(lptout, (caddr_t)dev, 2*hz);
 286:         return;
 287:     }
 288:     if ((sc->sc_state&OPEN) == 0 && sc->sc_outq.c_cc == 0) {
 289:         sc->sc_state &= ~TOUT;      /* no longer open */
 290:         lpaddr->lpcs = 0;
 291:         return;
 292:     }
 293:     if (sc->sc_outq.c_cc && (lpaddr->lpcs&LP_RDY) &&
 294:         (lpaddr->lpcs&LP_ERR)==0)
 295:         lpintr(LPUNIT(dev));            /* ready to go */
 296:     timeout(lptout, (caddr_t)dev, 10*hz);
 297: }
 298: #endif

Defined functions

lpattach defined in line 65; never used
lpcanon defined in line 134; used 4 times
lpclose defined in line 102; never used
lpintr defined in line 250; used 4 times
lpopen defined in line 76; never used
lpoutput defined in line 230; used 4 times
lptout defined in line 274; used 4 times
lpwrite defined in line 112; never used

Defined variables

lp_addr defined in line 55; used 5 times
lp_softc defined in line 53; used 6 times

Defined struct's

lp_softc defined in line 45; used 12 times
lpdevice defined in line 40; used 8 times

Defined macros

ASLP defined in line 63; used 3 times
CAP defined in line 33; used 1 times
LPBUFSIZE defined in line 32; used 2 times
LPHWAT defined in line 30; used 2 times
LPLWAT defined in line 29; used 2 times
  • in line 268(2)
LPPRI defined in line 25; used 2 times
LPUNIT defined in line 38; used 9 times
LP_ERR defined in line 28; used 3 times
LP_IE defined in line 26; used 2 times
LP_MAXCOL defined in line 35; used 2 times
LP_RDY defined in line 27; used 2 times
MOD defined in line 62; used 3 times
OPEN defined in line 60; used 4 times
TOUT defined in line 61; used 3 times
Last modified: 1997-02-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3455
Valid CSS Valid XHTML 1.0 Strict