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