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