1*1921Swnj From IngVAX:root Wed Apr 9 02:43:54 1980 2*1921Swnj To: vax:bill 3*1921Swnj 4*1921Swnj /* lp.c 4.1 12/17/80 */ 5*1921Swnj 6*1921Swnj #include "../conf/lp.h" 7*1921Swnj #if NLP > 0 8*1921Swnj /* 9*1921Swnj * LP-11 Line printer driver 10*1921Swnj * 11*1921Swnj * This driver is only set up to handle one printer; 12*1921Swnj * thats all our user-level spoolers can handle anyways right now. 13*1921Swnj * 14*1921Swnj * This driver has been modified to work on printers where 15*1921Swnj * leaving IENABLE set would cause continuous interrupts. 16*1921Swnj */ 17*1921Swnj 18*1921Swnj #include "../h/param.h" 19*1921Swnj #include "../h/dir.h" 20*1921Swnj #include "../h/user.h" 21*1921Swnj #include "../h/buf.h" 22*1921Swnj #include "../h/systm.h" 23*1921Swnj #include "../h/map.h" 24*1921Swnj #include "../h/pte.h" 25*1921Swnj #include "../h/uba.h" 26*1921Swnj #include "../h/ioctl.h" 27*1921Swnj #include "../h/tty.h" 28*1921Swnj #include "../h/lpio.h" 29*1921Swnj 30*1921Swnj #define LPPRI (PZERO+8) 31*1921Swnj #define IENABLE 0100 32*1921Swnj #define DONE 0200 33*1921Swnj #define ERROR 0100000 34*1921Swnj #define LPLWAT 650 35*1921Swnj #define LPHWAT 800 36*1921Swnj 37*1921Swnj struct lpregs { 38*1921Swnj short lpsr; 39*1921Swnj short lpbuf; 40*1921Swnj }; 41*1921Swnj 42*1921Swnj struct { 43*1921Swnj struct clist outq; 44*1921Swnj int state; 45*1921Swnj int physcol; 46*1921Swnj int logcol; 47*1921Swnj int physline; 48*1921Swnj struct lpioctl lpio; 49*1921Swnj struct buf *inbuf; 50*1921Swnj } lp11; 51*1921Swnj #define flags lpio.lp_flags 52*1921Swnj #define ejline lpio.lp_ejline 53*1921Swnj #define indent lpio.lp_indent 54*1921Swnj #define maxcol lpio.lp_maxcol 55*1921Swnj #define skpline lpio.lp_skpline 56*1921Swnj 57*1921Swnj /* bits for state */ 58*1921Swnj #define OPEN 1 /* device is open */ 59*1921Swnj #define TOUT 2 /* timeout is active */ 60*1921Swnj #define MOD 4 /* device state has been modified */ 61*1921Swnj #define ASLP 8 /* awaiting draining of printer */ 62*1921Swnj 63*1921Swnj extern lbolt; 64*1921Swnj int lptout(); 65*1921Swnj 66*1921Swnj /*ARGSUSED*/ 67*1921Swnj lpopen(dev, flag) 68*1921Swnj { 69*1921Swnj 70*1921Swnj if (lp11.state&OPEN || LPADDR->lpsr&ERROR) { 71*1921Swnj u.u_error = EIO; 72*1921Swnj return; 73*1921Swnj } 74*1921Swnj lp11.state |= OPEN; 75*1921Swnj lp11.inbuf = geteblk(); 76*1921Swnj lp11.flags = LPFLAGS; 77*1921Swnj lp11.ejline = EJLINE; 78*1921Swnj lp11.indent = INDENT; 79*1921Swnj lp11.maxcol = MAXCOL; 80*1921Swnj lp11.skpline = SKPLINE; 81*1921Swnj spl4(); 82*1921Swnj if ((lp11.state&TOUT) == 0) { 83*1921Swnj lp11.state |= TOUT; 84*1921Swnj timeout(lptout, 0, 10*HZ); 85*1921Swnj } 86*1921Swnj spl0(); 87*1921Swnj lpcanon('\f'); 88*1921Swnj } 89*1921Swnj 90*1921Swnj /*ARGSUSED*/ 91*1921Swnj lpclose(dev, flag) 92*1921Swnj { 93*1921Swnj 94*1921Swnj brelse(lp11.inbuf); 95*1921Swnj lp11.state &= ~OPEN; 96*1921Swnj lpcanon('\f'); 97*1921Swnj } 98*1921Swnj 99*1921Swnj lpwrite() 100*1921Swnj { 101*1921Swnj register c, n; 102*1921Swnj register char *cp; 103*1921Swnj 104*1921Swnj while (n = min(BSIZE, u.u_count)) { 105*1921Swnj cp = lp11.inbuf->b_un.b_addr; 106*1921Swnj iomove(cp, n, B_WRITE); 107*1921Swnj do 108*1921Swnj lpcanon(*cp++); 109*1921Swnj while (--n); 110*1921Swnj } 111*1921Swnj } 112*1921Swnj 113*1921Swnj lpcanon(c) 114*1921Swnj register c; 115*1921Swnj { 116*1921Swnj register int logcol, physcol; 117*1921Swnj 118*1921Swnj #ifdef HALFASCII 119*1921Swnj if (lp11.flags&CAP) { 120*1921Swnj register c2; 121*1921Swnj 122*1921Swnj if (c>='a' && c<='z') 123*1921Swnj c += 'A'-'a'; else 124*1921Swnj switch (c) { 125*1921Swnj 126*1921Swnj case '{': 127*1921Swnj c2 = '('; 128*1921Swnj goto esc; 129*1921Swnj 130*1921Swnj case '}': 131*1921Swnj c2 = ')'; 132*1921Swnj goto esc; 133*1921Swnj 134*1921Swnj case '`': 135*1921Swnj c2 = '\''; 136*1921Swnj goto esc; 137*1921Swnj 138*1921Swnj case '|': 139*1921Swnj c2 = '!'; 140*1921Swnj goto esc; 141*1921Swnj 142*1921Swnj case '~': 143*1921Swnj c2 = '^'; 144*1921Swnj 145*1921Swnj esc: 146*1921Swnj lpcanon(c2); 147*1921Swnj lp11.logcol--; 148*1921Swnj c = '-'; 149*1921Swnj } 150*1921Swnj } 151*1921Swnj #endif HALFASCII 152*1921Swnj logcol = lp11.logcol; 153*1921Swnj physcol = lp11.physcol; 154*1921Swnj if (c == ' ') 155*1921Swnj logcol++; 156*1921Swnj else switch(c) { 157*1921Swnj 158*1921Swnj case '\t': 159*1921Swnj logcol = lp11.indent + ((logcol-lp11.indent+8) & ~7); 160*1921Swnj break; 161*1921Swnj 162*1921Swnj case '\n': 163*1921Swnj lp11.physline++; 164*1921Swnj if (lp11.physline >= lp11.ejline) 165*1921Swnj c = '\f'; 166*1921Swnj /* fall through */ 167*1921Swnj 168*1921Swnj case '\f': 169*1921Swnj physcol = 0; 170*1921Swnj if (lp11.physline == 0 && (lp11.flags&SAVEPAPER)) 171*1921Swnj ; 172*1921Swnj else { 173*1921Swnj lpoutput(c); 174*1921Swnj if (c == '\f') { 175*1921Swnj lp11.physline = 0; 176*1921Swnj if (lp11.flags & SKIPFOLD) { 177*1921Swnj int i; 178*1921Swnj for (i = 0; i < lp11.skpline; i++) 179*1921Swnj lpoutput('\n'); 180*1921Swnj } 181*1921Swnj } 182*1921Swnj } 183*1921Swnj /* fall into ... */ 184*1921Swnj 185*1921Swnj case '\r': 186*1921Swnj logcol = lp11.indent; 187*1921Swnj spl4(); 188*1921Swnj lpintr(); 189*1921Swnj spl0(); 190*1921Swnj break; 191*1921Swnj 192*1921Swnj case '\b': 193*1921Swnj if (logcol > 0) 194*1921Swnj logcol--; 195*1921Swnj break; 196*1921Swnj 197*1921Swnj default: 198*1921Swnj if (logcol < physcol) { 199*1921Swnj lpoutput('\r'); 200*1921Swnj physcol = 0; 201*1921Swnj } 202*1921Swnj if (logcol < lp11.maxcol) { 203*1921Swnj while (logcol > physcol) { 204*1921Swnj lpoutput(' '); 205*1921Swnj physcol++; 206*1921Swnj } 207*1921Swnj lpoutput(c); 208*1921Swnj physcol++; 209*1921Swnj } 210*1921Swnj logcol++; 211*1921Swnj } 212*1921Swnj if (logcol > 1000) /* ignore long lines */ 213*1921Swnj logcol = 1000; 214*1921Swnj lp11.logcol = logcol; 215*1921Swnj lp11.physcol = physcol; 216*1921Swnj } 217*1921Swnj 218*1921Swnj lpoutput(c) 219*1921Swnj { 220*1921Swnj 221*1921Swnj if (lp11.outq.c_cc >= LPHWAT) { 222*1921Swnj spl4(); 223*1921Swnj lpintr(); /* unchoke */ 224*1921Swnj while (lp11.outq.c_cc >= LPHWAT) { 225*1921Swnj lp11.state |= ASLP; /* must be ERROR */ 226*1921Swnj sleep((caddr_t)&lp11, LPPRI); 227*1921Swnj } 228*1921Swnj spl0(); 229*1921Swnj } 230*1921Swnj while (putc(c, &lp11.outq)) 231*1921Swnj sleep((caddr_t)&lbolt, LPPRI); 232*1921Swnj } 233*1921Swnj 234*1921Swnj int lpchar = -1; 235*1921Swnj 236*1921Swnj lpintr() 237*1921Swnj { 238*1921Swnj register int n; 239*1921Swnj int i; 240*1921Swnj 241*1921Swnj LPADDR->lpsr &= ~IENABLE; 242*1921Swnj n = lp11.outq.c_cc; 243*1921Swnj if (lpchar < 0) 244*1921Swnj lpchar = getc(&lp11); 245*1921Swnj while ((LPADDR->lpsr&DONE) && lpchar >= 0) { 246*1921Swnj LPADDR->lpbuf = lpchar; 247*1921Swnj lpchar = getc(&lp11); 248*1921Swnj } 249*1921Swnj nomore: 250*1921Swnj lp11.state |= MOD; 251*1921Swnj if (lp11.outq.c_cc > 0 && (LPADDR->lpsr&ERROR)==0) 252*1921Swnj LPADDR->lpsr |= IENABLE; /* ok and more to do later */ 253*1921Swnj if (n>LPLWAT && lp11.outq.c_cc<=LPLWAT && lp11.state&ASLP) { 254*1921Swnj lp11.state &= ~ASLP; 255*1921Swnj wakeup((caddr_t)&lp11); /* top half should go on */ 256*1921Swnj } 257*1921Swnj } 258*1921Swnj 259*1921Swnj lptout() 260*1921Swnj { 261*1921Swnj register short *sr; 262*1921Swnj 263*1921Swnj if ((lp11.state&MOD) != 0) { 264*1921Swnj lp11.state &= ~MOD; /* something happened */ 265*1921Swnj timeout(lptout, 0, 2*HZ); /* so don't sweat */ 266*1921Swnj return; 267*1921Swnj } 268*1921Swnj sr = &LPADDR->lpsr; 269*1921Swnj if ((lp11.state&OPEN) == 0) { 270*1921Swnj lp11.state &= ~TOUT; /* no longer open */ 271*1921Swnj *sr = 0; 272*1921Swnj return; 273*1921Swnj } 274*1921Swnj if (lp11.outq.c_cc && (*sr&DONE) && (*sr&ERROR)==0) 275*1921Swnj lpintr(); /* ready to go */ 276*1921Swnj timeout(lptout, 0, 10*HZ); 277*1921Swnj } 278*1921Swnj 279*1921Swnj /*ARGSUSED*/ 280*1921Swnj lpioctl(dev, cmd, addr, flag) 281*1921Swnj dev_t dev; 282*1921Swnj caddr_t addr; 283*1921Swnj { 284*1921Swnj register int m; 285*1921Swnj struct lpioctl lpio; 286*1921Swnj 287*1921Swnj switch (cmd) { 288*1921Swnj 289*1921Swnj case LGETSTATE: 290*1921Swnj copyout((caddr_t)&lp11.lpio, addr, sizeof (lp11.lpio)); 291*1921Swnj return; 292*1921Swnj 293*1921Swnj case LSETSTATE: 294*1921Swnj m = copyin(addr, (caddr_t)&lpio, sizeof (lpio)); 295*1921Swnj if (m < 0) { 296*1921Swnj u.u_error = EFAULT; 297*1921Swnj return; 298*1921Swnj } 299*1921Swnj if (lpio.lp_indent <= 0 || lpio.lp_indent >= lpio.lp_maxcol || 300*1921Swnj lpio.lp_ejline <= 2 || lpio.lp_ejline <= lpio.lp_skpline || 301*1921Swnj lpio.lp_skpline < 0 || lpio.lp_maxcol <= 10) 302*1921Swnj u.u_error = EINVAL; 303*1921Swnj else 304*1921Swnj lp11.lpio = lpio; 305*1921Swnj return; 306*1921Swnj 307*1921Swnj default: 308*1921Swnj u.u_error = ENOTTY; 309*1921Swnj return; 310*1921Swnj } 311*1921Swnj } 312*1921Swnj 313*1921Swnj lpreset() 314*1921Swnj { 315*1921Swnj 316*1921Swnj printf("lp "); 317*1921Swnj LPADDR->lpsr |= IENABLE; 318*1921Swnj } 319*1921Swnj 320