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