1 /* va.c 4.10 81/07/08 */ 2 3 #include "va.h" 4 #if NVA > 0 5 /* 6 * Varian printer plotter 7 */ 8 #include "../h/param.h" 9 #include "../h/dir.h" 10 #include "../h/user.h" 11 #include "../h/buf.h" 12 #include "../h/systm.h" 13 #include "../h/map.h" 14 #include "../h/pte.h" 15 #include "../h/ubareg.h" 16 #include "../h/ubavar.h" 17 #include "../h/vcmd.h" 18 19 unsigned minvaph(); 20 21 #define VAPRI (PZERO-1) 22 23 struct vadevice { 24 u_short vaba; /* buffer address */ 25 short vawc; /* word count (2's complement) */ 26 union { 27 short Vacsw; /* control status as word */ 28 struct { /* control status as bytes */ 29 char Vacsl; 30 char Vacsh; 31 } vacsr; 32 } vacs; 33 short vadata; /* programmed i/o data buffer */ 34 }; 35 36 #define vacsw vacs.Vacsw 37 #define vacsh vacs.vacsr.Vacsh 38 #define vacsl vacs.vacsr.Vacsl 39 40 /* vacsw bits */ 41 #define VA_ERROR 0100000 /* some error has occurred */ 42 #define VA_NPRTIMO 0001000 /* DMA timeout error */ 43 #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 44 #define VA_DONE 0000200 45 #define VA_IENABLE 0000100 /* interrupt enable */ 46 #define VA_SUPPLIESLOW 0000004 47 #define VA_BOTOFFORM 0000002 48 #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 49 50 /* vacsh command bytes */ 51 #define VAPLOT 0000340 52 #define VAPRINT 0000100 53 #define VAPRINTPLOT 0000160 54 #define VAAUTOSTEP 0000244 55 #define VANOAUTOSTEP 0000045 56 #define VAFORMFEED 0000263 57 #define VASLEW 0000265 58 #define VASTEP 0000064 59 60 struct va_softc { 61 char sc_openf; 62 char sc_busy; 63 int sc_state; 64 int sc_wc; 65 struct buf *sc_bp; 66 int sc_ubinfo; 67 } va_softc[NVA]; 68 69 #define VAUNIT(dev) (minor(dev)) 70 71 struct buf rvabuf[NVA]; 72 73 int vaprobe(), vaattach(); 74 struct uba_device *vadinfo[NVA]; 75 u_short vastd[] = { 0764000, 0 }; 76 struct uba_driver vadriver = 77 { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo }; 78 79 vaprobe(reg) 80 caddr_t reg; 81 { 82 register int br, cvec; /* value-result */ 83 register struct vadevice *vaaddr = (struct vadevice *)reg; 84 85 vaaddr->vacsl = VA_IENABLE; 86 vaaddr->vaba = 0; 87 vaaddr->vacsh = VAPLOT; 88 vaaddr->vacsl = 0; 89 vaaddr->vawc = -1; 90 DELAY(10000); 91 vaaddr->vacsl = 0; 92 } 93 94 /*ARGSUSED*/ 95 vaattach(ui) 96 struct uba_device *ui; 97 { 98 99 } 100 101 vaopen(dev) 102 dev_t dev; 103 { 104 register struct va_softc *sc; 105 register struct vadevice *vaaddr; 106 register struct uba_device *ui; 107 108 if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf || 109 (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) { 110 u.u_error = ENXIO; 111 return; 112 } 113 vaaddr = (struct vadevice *)ui->ui_addr; 114 sc->sc_openf = 1; 115 vaaddr->vawc = 0; 116 sc->sc_wc = 0; 117 sc->sc_state = 0; 118 vaaddr->vacsl = VA_IENABLE; 119 vatimo(dev); 120 vacmd(dev, VPRINT); 121 if (u.u_error) 122 vaclose(dev); 123 } 124 125 vastrategy(bp) 126 register struct buf *bp; 127 { 128 register int e; 129 register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)]; 130 register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)]; 131 register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr; 132 133 (void) spl4(); 134 while (sc->sc_busy) 135 sleep((caddr_t)sc, VAPRI); 136 sc->sc_busy = 1; 137 sc->sc_bp = bp; 138 sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 139 if (e = vawait(bp->b_dev)) 140 goto brkout; 141 sc->sc_wc = -(bp->b_bcount/2); 142 vastart(bp->b_dev); 143 e = vawait(bp->b_dev); 144 sc->sc_wc = 0; 145 if (sc->sc_state & VPRINTPLOT) { 146 sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 147 vaaddr->vacsh = VAAUTOSTEP; 148 e |= vawait(bp->b_dev); 149 } 150 (void) spl0(); 151 brkout: 152 ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 153 sc->sc_bp = 0; 154 sc->sc_busy = 0; 155 iodone(bp); 156 if (e) 157 u.u_error = EIO; 158 wakeup((caddr_t)sc); 159 } 160 161 int vablock = 16384; 162 163 unsigned 164 minvaph(bp) 165 struct buf *bp; 166 { 167 168 if (bp->b_bcount > vablock) 169 bp->b_bcount = vablock; 170 } 171 172 /*ARGSUSED*/ 173 vawrite(dev) 174 dev_t dev; 175 { 176 177 physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph); 178 } 179 180 vawait(dev) 181 dev_t dev; 182 { 183 register struct vadevice *vaaddr = 184 (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 185 register int e; 186 187 while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0) 188 sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI); 189 if (e & VA_NPRTIMO) 190 printf("va%d: npr timeout\n", VAUNIT(dev)); 191 return (e & VA_ERROR); 192 } 193 194 vastart(dev) 195 dev_t; 196 { 197 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 198 register struct vadevice *vaaddr = 199 (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 200 201 if (sc->sc_wc == 0) 202 return; 203 vaaddr->vaba = sc->sc_ubinfo; 204 vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30; 205 vaaddr->vawc = sc->sc_wc; 206 } 207 208 /*ARGSUSED*/ 209 vaioctl(dev, cmd, addr, flag) 210 register caddr_t addr; 211 { 212 register int vcmd; 213 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 214 215 switch (cmd) { 216 217 case VGETSTATE: 218 (void) suword(addr, sc->sc_state); 219 return; 220 221 case VSETSTATE: 222 vcmd = fuword(addr); 223 if (vcmd == -1) { 224 u.u_error = EFAULT; 225 return; 226 } 227 vacmd(dev, vcmd); 228 return; 229 230 default: 231 u.u_error = ENOTTY; 232 return; 233 } 234 } 235 236 vacmd(dev, vcmd) 237 dev_t dev; 238 int vcmd; 239 { 240 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 241 register struct vadevice *vaaddr = 242 (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 243 244 (void) spl4(); 245 (void) vawait(dev); 246 switch (vcmd) { 247 248 case VPLOT: 249 /* Must turn on plot AND autostep modes. */ 250 vaaddr->vacsh = VAPLOT; 251 if (vawait(dev)) 252 u.u_error = EIO; 253 vaaddr->vacsh = VAAUTOSTEP; 254 break; 255 256 case VPRINT: 257 vaaddr->vacsh = VAPRINT; 258 break; 259 260 case VPRINTPLOT: 261 vaaddr->vacsh = VAPRINTPLOT; 262 break; 263 } 264 sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 265 if (vawait(dev)) 266 u.u_error = EIO; 267 (void) spl0(); 268 } 269 270 vatimo(dev) 271 dev_t dev; 272 { 273 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 274 275 if (sc->sc_openf) 276 timeout(vatimo, (caddr_t)dev, hz/10); 277 vaintr(dev); 278 } 279 280 /*ARGSUSED*/ 281 vaintr(dev) 282 dev_t dev; 283 { 284 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 285 286 wakeup((caddr_t)sc); 287 } 288 289 vaclose(dev) 290 dev_t dev; 291 { 292 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 293 register struct vadevice *vaaddr = 294 (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 295 296 sc->sc_openf = 0; 297 sc->sc_busy = 0; 298 sc->sc_state = 0; 299 sc->sc_ubinfo = 0; 300 vaaddr->vacsl = 0; 301 } 302 303 vareset(uban) 304 int uban; 305 { 306 register int va11; 307 register struct uba_device *ui; 308 register struct va_softc *sc = va_softc; 309 register struct vadevice *vaaddr; 310 311 for (va11 = 0; va11 < NVA; va11++, sc++) { 312 if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 || 313 ui->ui_ubanum != uban || sc->sc_openf == 0) 314 continue; 315 printf(" va%d", va11); 316 vaaddr = (struct vadevice *)ui->ui_addr; 317 vaaddr->vacsl = VA_IENABLE; 318 if (sc->sc_state & VPLOT) { 319 vaaddr->vacsh = VAPLOT; 320 DELAY(10000); 321 vaaddr->vacsh = VAAUTOSTEP; 322 } else if (sc->sc_state & VPRINTPLOT) 323 vaaddr->vacsh = VPRINTPLOT; 324 else 325 vaaddr->vacsh = VAPRINTPLOT; 326 DELAY(10000); 327 if (sc->sc_busy == 0) 328 continue; 329 if (sc->sc_ubinfo) { 330 printf("<%d>", (sc->sc_ubinfo>>28)&0xf); 331 ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 332 } 333 sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP); 334 sc->sc_wc = -(sc->sc_bp->b_bcount/2); 335 vastart(sc->sc_bp->b_dev); 336 } 337 } 338 #endif 339