1 /* va.c 3.6 06/22/80 */ 2 3 #include "../h/param.h" 4 #include "../h/dir.h" 5 #include "../h/user.h" 6 #include "../h/buf.h" 7 #include "../h/systm.h" 8 #include "../h/map.h" 9 #include "../h/pte.h" 10 #include "../h/uba.h" 11 #include "../h/vcmd.h" 12 13 /* 14 * Benson-Varian matrix printer/plotter 15 * dma interface driver 16 */ 17 int vabdp = 1; 18 19 unsigned minvaph(); 20 21 #define VAPRI (PZERO-1) 22 23 #define ushort unsigned short 24 struct varegs { 25 ushort vaba; 26 short vawc; 27 union { 28 short Vacsw; 29 struct { 30 char Vacsl; 31 char Vacsh; 32 } vacsr; 33 } vacs; 34 short vadata; 35 }; 36 37 #define vacsw vacs.Vacsw 38 #define vacsh vacs.vacsr.Vacsh 39 #define vacsl vacs.vacsr.Vacsl 40 41 #define VAADDR ((struct varegs *)(UBA0_DEV + 0164000)) 42 43 /* vacsw bits */ 44 #define ERROR 0100000 /* Some error has occurred */ 45 #define NPRTIMO 01000 /* DMA timeout error */ 46 #define NOTREADY 0400 /* Something besides NPRTIMO */ 47 #define DONE 0200 48 #define IENABLE 0100 /* Interrupt enable */ 49 #define SUPPLIESLOW 04 50 #define BOTOFFORM 02 51 #define BYTEREVERSE 01 /* Reverse byte order in words */ 52 53 /* vacsh command bytes */ 54 #define VAPLOT 0340 55 #define VAPRINT 0100 56 #define VAPRINTPLOT 0160 57 #define VAAUTOSTEP 0244 58 #define VANOAUTOSTEP 0045 /* unused */ 59 #define VAFORMFEED 0263 /* unused */ 60 #define VASLEW 0265 /* unused */ 61 #define VASTEP 0064 /* unused */ 62 63 struct { 64 char va_open; 65 char va_busy; 66 int va_state; /* State: bits are commands in vcmd.h. */ 67 int va_wc; 68 int va_bufp; 69 struct buf *va_bp; 70 } va11; 71 int va_ubinfo; 72 73 struct buf rvabuf; /* Used by physio for a buffer. */ 74 75 vaopen() 76 { 77 78 if (va11.va_open) { 79 u.u_error = ENXIO; 80 return; 81 } 82 va11.va_open = 1; 83 VAADDR->vawc = 0; 84 va11.va_wc = 0; 85 va11.va_state = 0; 86 VAADDR->vacsl = IENABLE; 87 vatimo(); 88 vacmd(VPRINT); 89 if (u.u_error) 90 vaclose(); 91 } 92 93 vastrategy(bp) 94 register struct buf *bp; 95 { 96 register int e; 97 98 (void) spl4(); 99 while (va11.va_busy) 100 sleep((caddr_t)&va11, VAPRI); 101 va11.va_busy = 1; 102 va11.va_bp = bp; 103 va_ubinfo = ubasetup(bp, vabdp); 104 va11.va_bufp = va_ubinfo & 0x3ffff; 105 if (e = vaerror(DONE)) 106 goto brkout; 107 va11.va_wc = -(bp->b_bcount/2); 108 vastart(); 109 e = vaerror(DONE); /* Wait for DMA to complete */ 110 va11.va_wc = 0; 111 va11.va_bufp = 0; 112 113 /* 114 * After printing a line of characters, VPRINTPLOT mode essentially 115 * reverts to VPLOT mode, plotting things until a new mode is set. 116 * This change is indicated by sending a VAAUTOSTEP command to 117 * the va. We also change va_state to reflect this effective 118 * mode change. 119 */ 120 if (va11.va_state & VPRINTPLOT) { 121 va11.va_state = (va11.va_state & ~VPRINTPLOT) | VPLOT; 122 VAADDR->vacsh = VAAUTOSTEP; 123 e |= vaerror(DONE); 124 } 125 (void) spl0(); 126 brkout: 127 ubafree(va_ubinfo), va_ubinfo = 0; 128 va11.va_bp = 0; 129 va11.va_busy = 0; 130 iodone(bp); 131 if (e) 132 u.u_error = EIO; 133 wakeup((caddr_t)&va11); 134 } 135 136 int vablock = 16384; 137 138 unsigned 139 minvaph(bp) 140 struct buf *bp; 141 { 142 if (bp->b_bcount > vablock) 143 bp->b_bcount = vablock; 144 } 145 146 /*ARGSUSED*/ 147 vawrite(dev) 148 { 149 physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph); 150 } 151 152 /* 153 * Vaerror waits until bit or ERROR gets set, then returns non-zero if 154 * if it was ERROR that was set. 155 */ 156 vaerror(bit) 157 { 158 register int e; 159 160 while ((e = VAADDR->vacsw & (bit|ERROR)) == 0) 161 sleep((caddr_t)&va11, VAPRI); 162 return (e & ERROR); 163 } 164 165 vastart() 166 { 167 if (va11.va_wc) { 168 VAADDR->vaba = va11.va_bufp; 169 VAADDR->vawc = va11.va_wc; 170 return; 171 } 172 } 173 174 /*ARGSUSED*/ 175 vaioctl(dev, cmd, addr, flag) 176 register caddr_t addr; 177 { 178 register int vcmd; 179 180 switch (cmd) { 181 182 case VGETSTATE: 183 (void) suword(addr, va11.va_state); 184 return; 185 186 case VSETSTATE: 187 vcmd = fuword(addr); 188 if (vcmd == -1) { 189 u.u_error = EFAULT; 190 return; 191 } 192 vacmd(vcmd); 193 return; 194 195 default: 196 u.u_error = ENOTTY; /* Not a legal ioctl cmd. */ 197 return; 198 } 199 } 200 201 /* 202 * Send a command code to the va, and wait for it to complete. 203 * If an error occurs, u.u_error is set to EIO. 204 * In any case, update va11.va_state. 205 */ 206 vacmd(vcmd) 207 { 208 (void) spl4(); 209 (void) vaerror(DONE); /* Wait for va to be ready */ 210 switch (vcmd) { 211 212 case VPLOT: 213 /* Must turn on plot AND autostep modes. */ 214 VAADDR->vacsh = VAPLOT; 215 if (vaerror(DONE)) 216 u.u_error = EIO; 217 VAADDR->vacsh = VAAUTOSTEP; 218 break; 219 220 case VPRINT: 221 VAADDR->vacsh = VAPRINT; 222 break; 223 224 case VPRINTPLOT: 225 VAADDR->vacsh = VAPRINTPLOT; 226 break; 227 } 228 va11.va_state = 229 (va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd; 230 231 if (vaerror(DONE)) /* Wait for command to complete. */ 232 u.u_error = EIO; 233 (void) spl0(); 234 } 235 236 vatimo() 237 { 238 if (va11.va_open) 239 timeout(vatimo, (caddr_t)0, HZ/10); 240 vaintr(0); 241 } 242 243 /*ARGSUSED*/ 244 vaintr(dev) 245 { 246 wakeup((caddr_t)&va11); 247 } 248 249 vaclose() 250 { 251 252 va11.va_open = 0; 253 va11.va_busy = 0; 254 va11.va_state = 0; 255 va11.va_wc = 0; 256 va11.va_bufp = 0; 257 VAADDR->vacsl = 0; 258 } 259 260 #define DELAY(N) { register int d; d = N; while (--d > 0); } 261 262 vareset() 263 { 264 265 if (va11.va_open == 0) 266 return; 267 printf(" va"); 268 VAADDR->vacsl = IENABLE; 269 if (va11.va_state & VPLOT) { 270 VAADDR->vacsh = VAPLOT; 271 DELAY(10000); 272 VAADDR->vacsh = VAAUTOSTEP; 273 } else if (va11.va_state & VPRINTPLOT) 274 VAADDR->vacsh = VPRINTPLOT; 275 else 276 VAADDR->vacsh = VAPRINTPLOT; 277 DELAY(10000); 278 if (va11.va_busy == 0) 279 return; 280 if (va_ubinfo) { 281 printf("<%d>", (va_ubinfo>>28)&0xf); 282 ubafree(va_ubinfo), va_ubinfo = 0; 283 } 284 /* This code belongs in vastart() */ 285 va_ubinfo = ubasetup(va11.va_bp, vabdp); 286 va11.va_bufp = va_ubinfo & 0x3ffff; 287 va11.va_wc = (-va11.va_bp->b_bcount/2); 288 /* End badly placed code */ 289 vastart(); 290 } 291