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