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.1 (Berkeley) 6/5/86 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