1*9363Smckusick /* va.c 4.13.1.3 82/11/27 */ 241Sbill 31938Swnj #include "va.h" 41564Sbill #if NVA > 0 51564Sbill /* 63183Swnj * Varian printer plotter 71564Sbill */ 841Sbill #include "../h/param.h" 941Sbill #include "../h/dir.h" 1041Sbill #include "../h/user.h" 1141Sbill #include "../h/buf.h" 1241Sbill #include "../h/systm.h" 1341Sbill #include "../h/map.h" 1441Sbill #include "../h/pte.h" 1541Sbill #include "../h/vcmd.h" 169362Smckusick #include "../h/uio.h" 1741Sbill 18*9363Smckusick #include "../vaxuba/ubareg.h" 19*9363Smckusick #include "../vaxuba/ubavar.h" 20*9363Smckusick 21287Sbill unsigned minvaph(); 2241Sbill 2341Sbill #define VAPRI (PZERO-1) 2441Sbill 253183Swnj struct vadevice { 263183Swnj u_short vaba; /* buffer address */ 273183Swnj short vawc; /* word count (2's complement) */ 2841Sbill union { 293183Swnj short Vacsw; /* control status as word */ 303183Swnj struct { /* control status as bytes */ 31287Sbill char Vacsl; 32287Sbill char Vacsh; 33287Sbill } vacsr; 34287Sbill } vacs; 353183Swnj short vadata; /* programmed i/o data buffer */ 3641Sbill }; 3741Sbill 38287Sbill #define vacsw vacs.Vacsw 39287Sbill #define vacsh vacs.vacsr.Vacsh 40287Sbill #define vacsl vacs.vacsr.Vacsl 41287Sbill 42287Sbill /* vacsw bits */ 433183Swnj #define VA_ERROR 0100000 /* some error has occurred */ 443183Swnj #define VA_NPRTIMO 0001000 /* DMA timeout error */ 453183Swnj #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 463183Swnj #define VA_DONE 0000200 473183Swnj #define VA_IENABLE 0000100 /* interrupt enable */ 489362Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 493183Swnj #define VA_SUPPLIESLOW 0000004 503183Swnj #define VA_BOTOFFORM 0000002 513183Swnj #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 5241Sbill 53287Sbill /* vacsh command bytes */ 543183Swnj #define VAPLOT 0000340 553183Swnj #define VAPRINT 0000100 563183Swnj #define VAPRINTPLOT 0000160 573183Swnj #define VAAUTOSTEP 0000244 583183Swnj #define VANOAUTOSTEP 0000045 593183Swnj #define VAFORMFEED 0000263 603183Swnj #define VASLEW 0000265 613183Swnj #define VASTEP 0000064 6241Sbill 633183Swnj struct va_softc { 649361Smckusick char sc_openf; 659361Smckusick char sc_busy; 669361Smckusick int sc_state; 679361Smckusick int sc_wc; 689361Smckusick struct buf *sc_bp; 699361Smckusick int sc_ubinfo; 703183Swnj } va_softc[NVA]; 7141Sbill 723183Swnj #define VAUNIT(dev) (minor(dev)) 733183Swnj 743183Swnj struct buf rvabuf[NVA]; 753183Swnj 769361Smckusick int vaprobe(), vaattach(); 773183Swnj struct uba_device *vadinfo[NVA]; 783183Swnj u_short vastd[] = { 0764000, 0 }; 793183Swnj struct uba_driver vadriver = 809361Smckusick { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo }; 813183Swnj 823183Swnj vaprobe(reg) 833183Swnj caddr_t reg; 8441Sbill { 853183Swnj register int br, cvec; /* value-result */ 863183Swnj register struct vadevice *vaaddr = (struct vadevice *)reg; 8741Sbill 889267Smckusick #ifdef lint 899267Smckusick br = 0; cvec = br; br = cvec; 909267Smckusick vaintr(0); 919267Smckusick #endif 923183Swnj vaaddr->vacsl = VA_IENABLE; 933183Swnj vaaddr->vaba = 0; 943183Swnj vaaddr->vacsh = VAPLOT; 959362Smckusick #ifndef VARIANGOBIT 969361Smckusick vaaddr->vacsl = 0; 979362Smckusick #endif 983183Swnj vaaddr->vawc = -1; 999361Smckusick DELAY(100000); 1003183Swnj vaaddr->vacsl = 0; 1019362Smckusick return (sizeof (struct vadevice)); 1023183Swnj } 1033183Swnj 1043183Swnj /*ARGSUSED*/ 1053183Swnj vaattach(ui) 1063183Swnj struct uba_device *ui; 1073183Swnj { 1083183Swnj 1093183Swnj } 1103183Swnj 1113183Swnj vaopen(dev) 1123183Swnj dev_t dev; 1133183Swnj { 1143183Swnj register struct va_softc *sc; 1153183Swnj register struct vadevice *vaaddr; 1163183Swnj register struct uba_device *ui; 117*9363Smckusick int error; 1183183Swnj 1199361Smckusick if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf || 120*9363Smckusick (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) 121*9363Smckusick return (ENXIO); 1223183Swnj vaaddr = (struct vadevice *)ui->ui_addr; 1233183Swnj sc->sc_openf = 1; 1243183Swnj vaaddr->vawc = 0; 1259361Smckusick sc->sc_wc = 0; 1263183Swnj sc->sc_state = 0; 1273183Swnj vaaddr->vacsl = VA_IENABLE; 1283183Swnj vatimo(dev); 129*9363Smckusick error = vacmd(dev, VPRINT); 130*9363Smckusick if (error) 1313183Swnj vaclose(dev); 132*9363Smckusick return (error); 13341Sbill } 13441Sbill 13541Sbill vastrategy(bp) 13641Sbill register struct buf *bp; 13741Sbill { 1389361Smckusick register int e; 1399361Smckusick register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)]; 1409361Smckusick register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)]; 1419361Smckusick register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr; 14241Sbill 1439361Smckusick (void) spl4(); 1449361Smckusick while (sc->sc_busy) 1459361Smckusick sleep((caddr_t)sc, VAPRI); 1469361Smckusick sc->sc_busy = 1; 1479361Smckusick sc->sc_bp = bp; 1489361Smckusick sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 1499361Smckusick if (e = vawait(bp->b_dev)) 1509361Smckusick goto brkout; 1519361Smckusick sc->sc_wc = -(bp->b_bcount/2); 1529361Smckusick vastart(bp->b_dev); 1539361Smckusick e = vawait(bp->b_dev); 1549361Smckusick sc->sc_wc = 0; 1559361Smckusick if (sc->sc_state & VPRINTPLOT) { 1569361Smckusick sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 1579361Smckusick vaaddr->vacsh = VAAUTOSTEP; 1589361Smckusick e |= vawait(bp->b_dev); 15941Sbill } 1609361Smckusick (void) spl0(); 1619361Smckusick brkout: 1629361Smckusick ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 1639361Smckusick sc->sc_bp = 0; 1649361Smckusick sc->sc_busy = 0; 165*9363Smckusick if (e) 166*9363Smckusick bp->b_flags |= B_ERROR; 1679361Smckusick iodone(bp); 1689361Smckusick wakeup((caddr_t)sc); 16941Sbill } 17041Sbill 17141Sbill int vablock = 16384; 17241Sbill 17341Sbill unsigned 17441Sbill minvaph(bp) 1753183Swnj struct buf *bp; 17641Sbill { 1773183Swnj 17841Sbill if (bp->b_bcount > vablock) 17941Sbill bp->b_bcount = vablock; 18041Sbill } 18141Sbill 18241Sbill /*ARGSUSED*/ 1839362Smckusick vawrite(dev, uio) 1843183Swnj dev_t dev; 1859362Smckusick struct uio *uio; 18641Sbill { 1879267Smckusick 1889362Smckusick if (VAUNIT(dev) > NVA) 189*9363Smckusick return (ENXIO); 190*9363Smckusick return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, 191*9363Smckusick minvaph, uio)); 19241Sbill } 19341Sbill 1949361Smckusick vawait(dev) 1959361Smckusick dev_t dev; 19641Sbill { 1979361Smckusick register struct vadevice *vaaddr = 1989361Smckusick (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 1999361Smckusick register int e; 20041Sbill 2019361Smckusick while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0) 2029361Smckusick sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI); 2039361Smckusick if (e & VA_NPRTIMO) 2049361Smckusick printf("va%d: npr timeout\n", VAUNIT(dev)); 2059361Smckusick return (e & VA_ERROR); 20641Sbill } 20741Sbill 2089361Smckusick vastart(dev) 2099361Smckusick dev_t; 21041Sbill { 2119361Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2129361Smckusick register struct vadevice *vaaddr = 2139361Smckusick (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 2143183Swnj 2159361Smckusick if (sc->sc_wc == 0) 2169361Smckusick return; 2179361Smckusick vaaddr->vaba = sc->sc_ubinfo; 2189362Smckusick #ifndef VARIANGOBIT 2199361Smckusick vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30; 2209362Smckusick #else 2219362Smckusick vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30 | VA_IENABLE | VA_DMAGO; 2229362Smckusick #endif 2239361Smckusick vaaddr->vawc = sc->sc_wc; 22441Sbill } 22541Sbill 22641Sbill /*ARGSUSED*/ 2279362Smckusick vaioctl(dev, cmd, data, flag) 2289362Smckusick register caddr_t data; 22941Sbill { 23041Sbill register int vcmd; 2313183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 23241Sbill 23341Sbill switch (cmd) { 23441Sbill 23541Sbill case VGETSTATE: 2369362Smckusick *(int *)data = sc->sc_state; 237*9363Smckusick break; 23841Sbill 23941Sbill case VSETSTATE: 240*9363Smckusick return (vacmd(dev, *(int *)data)); 241*9363Smckusick break; 24241Sbill 24341Sbill default: 244*9363Smckusick return (ENOTTY); 24541Sbill } 246*9363Smckusick return (0); 24741Sbill } 24841Sbill 2493183Swnj vacmd(dev, vcmd) 2503183Swnj dev_t dev; 2513183Swnj int vcmd; 25241Sbill { 2533183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2549361Smckusick register struct vadevice *vaaddr = 2559361Smckusick (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 256*9363Smckusick int error = 0; 2573183Swnj 2589361Smckusick (void) spl4(); 2599361Smckusick (void) vawait(dev); 26041Sbill switch (vcmd) { 26141Sbill 26241Sbill case VPLOT: 26341Sbill /* Must turn on plot AND autostep modes. */ 2649361Smckusick vaaddr->vacsh = VAPLOT; 2659361Smckusick if (vawait(dev)) 266*9363Smckusick error = EIO; 2679361Smckusick vaaddr->vacsh = VAAUTOSTEP; 26841Sbill break; 26941Sbill 27041Sbill case VPRINT: 2719361Smckusick vaaddr->vacsh = VAPRINT; 27241Sbill break; 27341Sbill 27441Sbill case VPRINTPLOT: 2759361Smckusick vaaddr->vacsh = VAPRINTPLOT; 27641Sbill break; 27741Sbill } 2783183Swnj sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 2799361Smckusick if (vawait(dev)) 280*9363Smckusick error = EIO; 2819361Smckusick (void) spl0(); 282*9363Smckusick return (error); 28341Sbill } 28441Sbill 2853183Swnj vatimo(dev) 2863183Swnj dev_t dev; 28741Sbill { 2883183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2893183Swnj 2903183Swnj if (sc->sc_openf) 2919361Smckusick timeout(vatimo, (caddr_t)dev, hz/10); 2929267Smckusick vaintr(dev); 29341Sbill } 29441Sbill 29541Sbill /*ARGSUSED*/ 29641Sbill vaintr(dev) 2973183Swnj dev_t dev; 29841Sbill { 2999361Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3003183Swnj 3019361Smckusick wakeup((caddr_t)sc); 30241Sbill } 30341Sbill 3043183Swnj vaclose(dev) 3053183Swnj dev_t dev; 30641Sbill { 3073183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3083183Swnj register struct vadevice *vaaddr = 3093183Swnj (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 31041Sbill 3113183Swnj sc->sc_openf = 0; 3129361Smckusick sc->sc_busy = 0; 3133183Swnj sc->sc_state = 0; 3149361Smckusick sc->sc_ubinfo = 0; 3153183Swnj vaaddr->vacsl = 0; 31641Sbill } 317287Sbill 3183183Swnj vareset(uban) 3193183Swnj int uban; 320287Sbill { 3213183Swnj register int va11; 3229361Smckusick register struct uba_device *ui; 3239361Smckusick register struct va_softc *sc = va_softc; 3243183Swnj register struct vadevice *vaaddr; 325287Sbill 3263183Swnj for (va11 = 0; va11 < NVA; va11++, sc++) { 3279361Smckusick if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 || 3289361Smckusick ui->ui_ubanum != uban || sc->sc_openf == 0) 3293183Swnj continue; 3303183Swnj printf(" va%d", va11); 3319361Smckusick vaaddr = (struct vadevice *)ui->ui_addr; 3323183Swnj vaaddr->vacsl = VA_IENABLE; 3333183Swnj if (sc->sc_state & VPLOT) { 3343183Swnj vaaddr->vacsh = VAPLOT; 3353183Swnj DELAY(10000); 3363183Swnj vaaddr->vacsh = VAAUTOSTEP; 3373183Swnj } else if (sc->sc_state & VPRINTPLOT) 3383183Swnj vaaddr->vacsh = VPRINTPLOT; 3393183Swnj else 3403183Swnj vaaddr->vacsh = VAPRINTPLOT; 341287Sbill DELAY(10000); 3429361Smckusick if (sc->sc_busy == 0) 3439361Smckusick continue; 3449361Smckusick sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP); 3459361Smckusick sc->sc_wc = -(sc->sc_bp->b_bcount/2); 3469361Smckusick vastart(sc->sc_bp->b_dev); 347287Sbill } 348287Sbill } 3496432Ssam 3506432Ssam vaselect() 3516432Ssam { 352*9363Smckusick 3536432Ssam return (1); 3546432Ssam } 3551564Sbill #endif 356