1 /* va.c 4.19 82/12/17 */ 2 3 #include "va.h" 4 #if NVA > 0 5 /* 6 * Varian printer plotter 7 */ 8 #include "../machine/pte.h" 9 10 #include "../h/param.h" 11 #include "../h/dir.h" 12 #include "../h/user.h" 13 #include "../h/buf.h" 14 #include "../h/systm.h" 15 #include "../h/map.h" 16 #include "../h/vcmd.h" 17 #include "../h/uio.h" 18 19 #include "../vaxuba/ubareg.h" 20 #include "../vaxuba/ubavar.h" 21 22 int vadebug = 0; 23 #define dprintf if(vadebug)printf 24 25 unsigned minvaph(); 26 27 #define VAPRI (PZERO-1) 28 29 struct vadevice { 30 u_short vaba; /* buffer address */ 31 short vawc; /* word count (2's complement) */ 32 union { 33 short Vacsw; /* control status as word */ 34 struct { /* control status as bytes */ 35 char Vacsl; 36 char Vacsh; 37 } vacsr; 38 } vacs; 39 short vadata; /* programmed i/o data buffer */ 40 }; 41 42 #define vacsw vacs.Vacsw 43 #define vacsh vacs.vacsr.Vacsh 44 #define vacsl vacs.vacsr.Vacsl 45 46 /* vacsw bits */ 47 #define VA_ERROR 0100000 /* some error has occurred */ 48 #define VA_NPRTIMO 0001000 /* DMA timeout error */ 49 #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 50 #define VA_DONE 0000200 51 #define VA_IENABLE 0000100 /* interrupt enable */ 52 #define VA_DMAGO 0000010 /* DMA go bit */ 53 #define VA_DMAGO 0000010 /* DMA go bit */ 54 #define VA_SUPPLIESLOW 0000004 55 #define VA_BOTOFFORM 0000002 56 #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 57 58 /* vacsh command bytes */ 59 #define VAPLOT 0000340 60 #define VAPRINT 0000100 61 #define VAPRINTPLOT 0000160 62 #define VAAUTOSTEP 0000244 63 #define VANOAUTOSTEP 0000045 64 #define VAFORMFEED 0000263 65 #define VASLEW 0000265 66 #define VASTEP 0000064 67 68 struct va_softc { 69 u_char sc_openf; /* exclusive open flag */ 70 u_char sc_iostate; /* kind of I/O going on */ 71 #define VAS_IDLE 0 /* no I/O, free */ 72 #define VAS_PIO 1 /* programmed I/O */ 73 #define VAS_DMA 2 /* DMA, block pio */ 74 #define VAS_WANT 4 /* wakeup when iostate changes */ 75 short sc_tocnt; /* time out counter */ 76 short sc_info; /* csw passed from vaintr */ 77 int sc_state; /* print/plot state of device */ 78 } va_softc[NVA]; 79 80 #define VAUNIT(dev) (minor(dev)) 81 82 struct buf rvabuf[NVA]; 83 84 int vaprobe(), vaslave(), vaattach(), vadgo(); 85 struct uba_device *vadinfo[NVA]; 86 struct uba_ctlr *vaminfo[NVA]; 87 struct buf vabhdr[NVA]; 88 u_short vastd[] = { 0764000, 0 }; 89 struct uba_driver vadriver = 90 { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo }; 91 92 vaprobe(reg) 93 caddr_t reg; 94 { 95 register int br, cvec; /* value-result */ 96 register struct vadevice *vaaddr = (struct vadevice *)reg; 97 98 #ifdef lint 99 br = 0; cvec = br; br = cvec; 100 vaintr(0); 101 #endif 102 #ifndef UCBVAX 103 vaaddr->vacsl = VA_IENABLE; 104 vaaddr->vaba = 0; 105 vaaddr->vacsh = VAPLOT; 106 vaaddr->vacsl = VA_IENABLE|VA_DMAGO; 107 vaaddr->vawc = -1; 108 DELAY(10000); 109 vaaddr->vacsl = 0; 110 vaaddr->vawc = 0; 111 #else 112 br=0x14; 113 cvec=0170; 114 #endif 115 return (sizeof (struct vadevice)); 116 } 117 118 /*ARGSUSED*/ 119 vaslave(ui, reg) 120 struct uba_device *ui; 121 caddr_t reg; 122 { 123 124 ui->ui_dk = 0; 125 return (ui->ui_unit <= 0); 126 } 127 128 /*ARGSUSED*/ 129 vaattach(ui) 130 struct uba_device *ui; 131 { 132 133 ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit]; 134 } 135 136 vaopen(dev) 137 dev_t dev; 138 { 139 register struct va_softc *sc; 140 register struct vadevice *vaaddr; 141 register struct uba_device *ui; 142 int error; 143 int unit = VAUNIT(dev); 144 145 if (unit >= NVA || (sc = &va_softc[unit])->sc_openf || 146 (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0) 147 return (ENXIO); 148 vaaddr = (struct vadevice *)ui->ui_addr; 149 sc->sc_openf = 1; 150 vaaddr->vawc = 0; 151 sc->sc_state = 0; 152 sc->sc_tocnt = 0; 153 sc->sc_iostate = VAS_IDLE; 154 vaaddr->vacsl = VA_IENABLE; 155 vatimo(dev); 156 error = vacmd(dev, VPRINT); 157 if (error) 158 vaclose(dev); 159 return (error); 160 } 161 162 vastrategy(bp) 163 register struct buf *bp; 164 { 165 register struct uba_device *ui; 166 register struct uba_ctlr *um; 167 int s; 168 169 dprintf("vastrategy(%x)\n", bp); 170 ui = vadinfo[VAUNIT(bp->b_dev)]; 171 if (ui == 0 || ui->ui_alive == 0) { 172 bp->b_flags |= B_ERROR; 173 iodone(bp); 174 return; 175 } 176 s = spl4(); 177 um = ui->ui_mi; 178 bp->b_actf = NULL; 179 if (um->um_tab.b_actf->b_actf == NULL) 180 um->um_tab.b_actf->b_actf = bp; 181 else { 182 printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n", 183 bp, um->um_tab.b_actf->b_actf); 184 panic("vastrategy"); 185 um->um_tab.b_actf->b_actl->b_forw = bp; 186 } 187 um->um_tab.b_actf->b_actl = bp; 188 bp = um->um_tab.b_actf; 189 dprintf("vastrategy: bp=%x actf=%x active=%d\n", 190 bp, bp->b_actf, bp->b_active); 191 if (bp->b_actf && bp->b_active == 0) 192 (void) vastart(um); 193 splx(s); 194 } 195 196 int vablock = 16384; 197 198 unsigned 199 minvaph(bp) 200 struct buf *bp; 201 { 202 203 if (bp->b_bcount > vablock) 204 bp->b_bcount = vablock; 205 } 206 207 /*ARGSUSED*/ 208 vawrite(dev, uio) 209 dev_t dev; 210 struct uio *uio; 211 { 212 213 if (VAUNIT(dev) > NVA) 214 return (ENXIO); 215 return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, 216 minvaph, uio)); 217 } 218 219 vastart(um) 220 register struct uba_ctlr *um; 221 { 222 struct buf *bp; 223 struct vadevice *vaaddr; 224 register struct va_softc *sc; 225 int unit; 226 227 dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf); 228 if ((bp = um->um_tab.b_actf->b_actf) == NULL) 229 return; 230 unit = VAUNIT(bp->b_dev); 231 sc = &va_softc[unit]; 232 sc->sc_tocnt = 0; 233 while (sc->sc_iostate&VAS_PIO) { 234 sc->sc_iostate |= VAS_WANT; 235 sleep((caddr_t)&sc->sc_iostate, VAPRI); 236 } 237 sc->sc_iostate |= VAS_DMA; 238 vaaddr = (struct vadevice *)um->um_addr; 239 vaaddr->vacsl = 0; 240 vaaddr->vawc = -(bp->b_bcount / 2); 241 um->um_cmd = VA_DMAGO | VA_IENABLE; 242 (void) ubago(vadinfo[unit]); 243 } 244 245 vadgo(um) 246 register struct uba_ctlr *um; 247 { 248 register struct vadevice *vaaddr = (struct vadevice *)um->um_addr; 249 register struct buf *bp; 250 251 bp = um->um_tab.b_actf; 252 va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0; 253 bp->b_active++; 254 vaaddr->vaba = um->um_ubinfo; 255 vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd; 256 } 257 258 /*ARGSUSED*/ 259 vaioctl(dev, cmd, data, flag) 260 register caddr_t data; 261 { 262 register int vcmd; 263 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 264 265 switch (cmd) { 266 267 case VGETSTATE: 268 *(int *)data = sc->sc_state; 269 break; 270 271 case VSETSTATE: 272 return (vacmd(dev, *(int *)data)); 273 break; 274 275 default: 276 return (ENOTTY); 277 } 278 return (0); 279 } 280 281 vacmd(dev, vcmd) 282 dev_t dev; 283 int vcmd; 284 { 285 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 286 int error = 0; 287 int s, cmd; 288 289 s = spl4(); 290 while (sc->sc_iostate&VAS_DMA) { 291 sc->sc_iostate |= VAS_WANT; 292 sleep((caddr_t)&sc->sc_iostate, VAPRI); 293 } 294 sc->sc_iostate |= VAS_PIO; 295 sc->sc_tocnt = 0; 296 cmd = 0; 297 switch (vcmd) { 298 299 case VPLOT: 300 /* Must turn on plot AND autostep modes. */ 301 if (vadopio(dev, VAPLOT)) 302 error = EIO; 303 cmd = VAAUTOSTEP; 304 break; 305 306 case VPRINT: 307 cmd = VAPRINT; 308 break; 309 310 case VPRINTPLOT: 311 cmd = VAPRINTPLOT; 312 break; 313 } 314 sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 315 if (cmd && vadopio(dev, cmd)) 316 error = EIO; 317 sc->sc_iostate &= ~VAS_PIO; 318 if (sc->sc_iostate&VAS_WANT) { 319 sc->sc_iostate &= ~VAS_WANT; 320 wakeup((caddr_t)&sc->sc_iostate); 321 } 322 splx(s); 323 return (error); 324 } 325 326 vadopio(dev, cmd) 327 dev_t dev; 328 int cmd; 329 { 330 register struct vadevice *vaaddr = 331 (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr; 332 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 333 334 sc->sc_info = 0; 335 vaaddr->vacsh = cmd; 336 while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0) 337 sleep((caddr_t)&sc->sc_info, VAPRI); 338 return (sc->sc_info&VA_ERROR); 339 } 340 341 vatimo(dev) 342 dev_t dev; 343 { 344 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 345 346 if (sc->sc_openf) 347 timeout(vatimo, (caddr_t)dev, hz/2); 348 if (++sc->sc_tocnt < 2) 349 return; 350 sc->sc_tocnt = 0; 351 dprintf("vatimo: calling vaintr\n"); 352 vaintr(dev); 353 } 354 355 /*ARGSUSED*/ 356 vaintr(dev) 357 dev_t dev; 358 { 359 register struct uba_ctlr *um; 360 struct vadevice *vaaddr; 361 struct buf *bp; 362 register int unit = VAUNIT(dev), e; 363 register struct va_softc *sc = &va_softc[unit]; 364 365 um = vaminfo[unit]; 366 vaaddr = (struct vadevice *)um->um_addr; 367 e = vaaddr->vacsw; 368 dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n", 369 um, e, um->um_tab.b_actf->b_active); 370 if ((e&(VA_DONE|VA_ERROR)) == 0) 371 return; 372 vaaddr->vacsl = 0; 373 if ((e&VA_ERROR) && (e&VA_NPRTIMO)) 374 printf("va%d: npr timeout\n", unit); 375 if (sc->sc_iostate&VAS_PIO) { 376 sc->sc_info = e; 377 wakeup((caddr_t)&sc->sc_info); 378 return; 379 } 380 if (um->um_tab.b_actf->b_active) { 381 bp = um->um_tab.b_actf->b_actf; 382 if (e&VA_ERROR) 383 bp->b_flags |= B_ERROR; 384 if (sc->sc_state&VPRINTPLOT) { 385 sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 386 vaaddr->vacsh = VAAUTOSTEP; 387 return; 388 } 389 ubadone(um); 390 um->um_tab.b_actf->b_active = 0; 391 um->um_tab.b_actf->b_actf = bp->b_forw; 392 bp->b_active = 0; 393 bp->b_errcnt = 0; 394 bp->b_resid = 0; 395 iodone(bp); 396 } 397 if (um->um_tab.b_actf->b_actf == 0) { 398 sc->sc_iostate &= ~VAS_DMA; 399 if (sc->sc_iostate&VAS_WANT) { 400 sc->sc_iostate &= ~VAS_WANT; 401 wakeup((caddr_t)&sc->sc_iostate); 402 } 403 return; 404 } 405 if (um->um_tab.b_actf->b_active == 0) 406 vastart(um); 407 } 408 409 vaclose(dev) 410 dev_t dev; 411 { 412 register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 413 register struct vadevice *vaaddr = 414 (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 415 416 sc->sc_openf = 0; 417 sc->sc_state = 0; 418 if (sc->sc_iostate != VAS_IDLE) 419 wakeup((caddr_t)&sc->sc_iostate); 420 sc->sc_iostate = VAS_IDLE; 421 vaaddr->vacsl = 0; 422 vaaddr->vawc = 0; 423 } 424 425 vareset(uban) 426 int uban; 427 { 428 register int va11; 429 register struct uba_ctlr *um; 430 register struct vadevice *vaaddr; 431 register struct va_softc *sc; 432 433 for (va11 = 0; va11 < NVA; va11++, sc++) { 434 if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban || 435 um->um_alive == 0) 436 continue; 437 sc = &va_softc[um->um_ctlr]; 438 if (sc->sc_openf == 0) 439 continue; 440 printf(" va%d", va11); 441 vaaddr = (struct vadevice *)um->um_addr; 442 vaaddr->vacsl = VA_IENABLE; 443 if (sc->sc_state & VPLOT) { 444 vaaddr->vacsh = VAPLOT; 445 DELAY(10000); 446 vaaddr->vacsh = VAAUTOSTEP; 447 } else if (sc->sc_state & VPRINTPLOT) 448 vaaddr->vacsh = VPRINTPLOT; 449 else 450 vaaddr->vacsh = VAPRINTPLOT; 451 DELAY(10000); 452 sc->sc_iostate = VAS_IDLE; 453 um->um_tab.b_actf->b_active = 0; 454 um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0; 455 if (um->um_ubinfo) { 456 printf("<%d>", (um->um_ubinfo >> 28) & 0xf); 457 um->um_ubinfo = 0; 458 } 459 (void) vastart(um); 460 } 461 } 462 463 vaselect() 464 { 465 466 return (1); 467 } 468 #endif 469