1*9361Smckusick /* va.c 4.13.1.1 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" 153183Swnj #include "../h/ubareg.h" 163183Swnj #include "../h/ubavar.h" 1741Sbill #include "../h/vcmd.h" 1841Sbill 19287Sbill unsigned minvaph(); 2041Sbill 2141Sbill #define VAPRI (PZERO-1) 2241Sbill 233183Swnj struct vadevice { 243183Swnj u_short vaba; /* buffer address */ 253183Swnj short vawc; /* word count (2's complement) */ 2641Sbill union { 273183Swnj short Vacsw; /* control status as word */ 283183Swnj struct { /* control status as bytes */ 29287Sbill char Vacsl; 30287Sbill char Vacsh; 31287Sbill } vacsr; 32287Sbill } vacs; 333183Swnj short vadata; /* programmed i/o data buffer */ 3441Sbill }; 3541Sbill 36287Sbill #define vacsw vacs.Vacsw 37287Sbill #define vacsh vacs.vacsr.Vacsh 38287Sbill #define vacsl vacs.vacsr.Vacsl 39287Sbill 40287Sbill /* vacsw bits */ 413183Swnj #define VA_ERROR 0100000 /* some error has occurred */ 423183Swnj #define VA_NPRTIMO 0001000 /* DMA timeout error */ 433183Swnj #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 443183Swnj #define VA_DONE 0000200 453183Swnj #define VA_IENABLE 0000100 /* interrupt enable */ 463183Swnj #define VA_SUPPLIESLOW 0000004 473183Swnj #define VA_BOTOFFORM 0000002 483183Swnj #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 4941Sbill 50287Sbill /* vacsh command bytes */ 513183Swnj #define VAPLOT 0000340 523183Swnj #define VAPRINT 0000100 533183Swnj #define VAPRINTPLOT 0000160 543183Swnj #define VAAUTOSTEP 0000244 553183Swnj #define VANOAUTOSTEP 0000045 563183Swnj #define VAFORMFEED 0000263 573183Swnj #define VASLEW 0000265 583183Swnj #define VASTEP 0000064 5941Sbill 603183Swnj struct va_softc { 61*9361Smckusick char sc_openf; 62*9361Smckusick char sc_busy; 63*9361Smckusick int sc_state; 64*9361Smckusick int sc_wc; 65*9361Smckusick struct buf *sc_bp; 66*9361Smckusick int sc_ubinfo; 673183Swnj } va_softc[NVA]; 6841Sbill 693183Swnj #define VAUNIT(dev) (minor(dev)) 703183Swnj 713183Swnj struct buf rvabuf[NVA]; 723183Swnj 73*9361Smckusick int vaprobe(), vaattach(); 743183Swnj struct uba_device *vadinfo[NVA]; 753183Swnj u_short vastd[] = { 0764000, 0 }; 763183Swnj struct uba_driver vadriver = 77*9361Smckusick { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo }; 783183Swnj 793183Swnj vaprobe(reg) 803183Swnj caddr_t reg; 8141Sbill { 823183Swnj register int br, cvec; /* value-result */ 833183Swnj register struct vadevice *vaaddr = (struct vadevice *)reg; 8441Sbill 859267Smckusick #ifdef lint 869267Smckusick br = 0; cvec = br; br = cvec; 879267Smckusick vaintr(0); 889267Smckusick #endif 893183Swnj vaaddr->vacsl = VA_IENABLE; 903183Swnj vaaddr->vaba = 0; 913183Swnj vaaddr->vacsh = VAPLOT; 92*9361Smckusick vaaddr->vacsl = 0; 933183Swnj vaaddr->vawc = -1; 94*9361Smckusick DELAY(100000); 953183Swnj vaaddr->vacsl = 0; 963183Swnj } 973183Swnj 983183Swnj /*ARGSUSED*/ 993183Swnj vaattach(ui) 1003183Swnj struct uba_device *ui; 1013183Swnj { 1023183Swnj 1033183Swnj } 1043183Swnj 1053183Swnj vaopen(dev) 1063183Swnj dev_t dev; 1073183Swnj { 1083183Swnj register struct va_softc *sc; 1093183Swnj register struct vadevice *vaaddr; 1103183Swnj register struct uba_device *ui; 1113183Swnj 112*9361Smckusick if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf || 113*9361Smckusick (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) { 11441Sbill u.u_error = ENXIO; 11541Sbill return; 11641Sbill } 1173183Swnj vaaddr = (struct vadevice *)ui->ui_addr; 1183183Swnj sc->sc_openf = 1; 1193183Swnj vaaddr->vawc = 0; 120*9361Smckusick sc->sc_wc = 0; 1213183Swnj sc->sc_state = 0; 1223183Swnj vaaddr->vacsl = VA_IENABLE; 1233183Swnj vatimo(dev); 1243183Swnj vacmd(dev, VPRINT); 12541Sbill if (u.u_error) 1263183Swnj vaclose(dev); 12741Sbill } 12841Sbill 12941Sbill vastrategy(bp) 13041Sbill register struct buf *bp; 13141Sbill { 132*9361Smckusick register int e; 133*9361Smckusick register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)]; 134*9361Smckusick register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)]; 135*9361Smckusick register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr; 13641Sbill 137*9361Smckusick (void) spl4(); 138*9361Smckusick while (sc->sc_busy) 139*9361Smckusick sleep((caddr_t)sc, VAPRI); 140*9361Smckusick sc->sc_busy = 1; 141*9361Smckusick sc->sc_bp = bp; 142*9361Smckusick sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 143*9361Smckusick if (e = vawait(bp->b_dev)) 144*9361Smckusick goto brkout; 145*9361Smckusick sc->sc_wc = -(bp->b_bcount/2); 146*9361Smckusick vastart(bp->b_dev); 147*9361Smckusick e = vawait(bp->b_dev); 148*9361Smckusick sc->sc_wc = 0; 149*9361Smckusick if (sc->sc_state & VPRINTPLOT) { 150*9361Smckusick sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 151*9361Smckusick vaaddr->vacsh = VAAUTOSTEP; 152*9361Smckusick e |= vawait(bp->b_dev); 15341Sbill } 154*9361Smckusick (void) spl0(); 155*9361Smckusick brkout: 156*9361Smckusick ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 157*9361Smckusick sc->sc_bp = 0; 158*9361Smckusick sc->sc_busy = 0; 159*9361Smckusick iodone(bp); 160*9361Smckusick if (e) 161*9361Smckusick u.u_error = EIO; 162*9361Smckusick wakeup((caddr_t)sc); 16341Sbill } 16441Sbill 16541Sbill int vablock = 16384; 16641Sbill 16741Sbill unsigned 16841Sbill minvaph(bp) 1693183Swnj struct buf *bp; 17041Sbill { 1713183Swnj 17241Sbill if (bp->b_bcount > vablock) 17341Sbill bp->b_bcount = vablock; 17441Sbill } 17541Sbill 17641Sbill /*ARGSUSED*/ 17741Sbill vawrite(dev) 1783183Swnj dev_t dev; 17941Sbill { 1809267Smckusick 1813183Swnj physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph); 18241Sbill } 18341Sbill 184*9361Smckusick vawait(dev) 185*9361Smckusick dev_t dev; 18641Sbill { 187*9361Smckusick register struct vadevice *vaaddr = 188*9361Smckusick (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 189*9361Smckusick register int e; 19041Sbill 191*9361Smckusick while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0) 192*9361Smckusick sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI); 193*9361Smckusick if (e & VA_NPRTIMO) 194*9361Smckusick printf("va%d: npr timeout\n", VAUNIT(dev)); 195*9361Smckusick return (e & VA_ERROR); 19641Sbill } 19741Sbill 198*9361Smckusick vastart(dev) 199*9361Smckusick dev_t; 20041Sbill { 201*9361Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 202*9361Smckusick register struct vadevice *vaaddr = 203*9361Smckusick (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 2043183Swnj 205*9361Smckusick if (sc->sc_wc == 0) 206*9361Smckusick return; 207*9361Smckusick vaaddr->vaba = sc->sc_ubinfo; 208*9361Smckusick vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30; 209*9361Smckusick vaaddr->vawc = sc->sc_wc; 21041Sbill } 21141Sbill 21241Sbill /*ARGSUSED*/ 21341Sbill vaioctl(dev, cmd, addr, flag) 21441Sbill register caddr_t addr; 21541Sbill { 21641Sbill register int vcmd; 2173183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 21841Sbill 21941Sbill switch (cmd) { 22041Sbill 22141Sbill case VGETSTATE: 2223183Swnj (void) suword(addr, sc->sc_state); 22341Sbill return; 22441Sbill 22541Sbill case VSETSTATE: 22641Sbill vcmd = fuword(addr); 22741Sbill if (vcmd == -1) { 22841Sbill u.u_error = EFAULT; 22941Sbill return; 23041Sbill } 2313183Swnj vacmd(dev, vcmd); 23241Sbill return; 23341Sbill 23441Sbill default: 2353183Swnj u.u_error = ENOTTY; 23641Sbill return; 23741Sbill } 23841Sbill } 23941Sbill 2403183Swnj vacmd(dev, vcmd) 2413183Swnj dev_t dev; 2423183Swnj int vcmd; 24341Sbill { 2443183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 245*9361Smckusick register struct vadevice *vaaddr = 246*9361Smckusick (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 2473183Swnj 248*9361Smckusick (void) spl4(); 249*9361Smckusick (void) vawait(dev); 25041Sbill switch (vcmd) { 25141Sbill 25241Sbill case VPLOT: 25341Sbill /* Must turn on plot AND autostep modes. */ 254*9361Smckusick vaaddr->vacsh = VAPLOT; 255*9361Smckusick if (vawait(dev)) 25641Sbill u.u_error = EIO; 257*9361Smckusick vaaddr->vacsh = VAAUTOSTEP; 25841Sbill break; 25941Sbill 26041Sbill case VPRINT: 261*9361Smckusick vaaddr->vacsh = VAPRINT; 26241Sbill break; 26341Sbill 26441Sbill case VPRINTPLOT: 265*9361Smckusick vaaddr->vacsh = VAPRINTPLOT; 26641Sbill break; 26741Sbill } 2683183Swnj sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 269*9361Smckusick if (vawait(dev)) 27041Sbill u.u_error = EIO; 271*9361Smckusick (void) spl0(); 27241Sbill } 27341Sbill 2743183Swnj vatimo(dev) 2753183Swnj dev_t dev; 27641Sbill { 2773183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2783183Swnj 2793183Swnj if (sc->sc_openf) 280*9361Smckusick timeout(vatimo, (caddr_t)dev, hz/10); 2819267Smckusick vaintr(dev); 28241Sbill } 28341Sbill 28441Sbill /*ARGSUSED*/ 28541Sbill vaintr(dev) 2863183Swnj dev_t dev; 28741Sbill { 288*9361Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2893183Swnj 290*9361Smckusick wakeup((caddr_t)sc); 29141Sbill } 29241Sbill 2933183Swnj vaclose(dev) 2943183Swnj dev_t dev; 29541Sbill { 2963183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2973183Swnj register struct vadevice *vaaddr = 2983183Swnj (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 29941Sbill 3003183Swnj sc->sc_openf = 0; 301*9361Smckusick sc->sc_busy = 0; 3023183Swnj sc->sc_state = 0; 303*9361Smckusick sc->sc_ubinfo = 0; 3043183Swnj vaaddr->vacsl = 0; 30541Sbill } 306287Sbill 3073183Swnj vareset(uban) 3083183Swnj int uban; 309287Sbill { 3103183Swnj register int va11; 311*9361Smckusick register struct uba_device *ui; 312*9361Smckusick register struct va_softc *sc = va_softc; 3133183Swnj register struct vadevice *vaaddr; 314287Sbill 3153183Swnj for (va11 = 0; va11 < NVA; va11++, sc++) { 316*9361Smckusick if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 || 317*9361Smckusick ui->ui_ubanum != uban || sc->sc_openf == 0) 3183183Swnj continue; 3193183Swnj printf(" va%d", va11); 320*9361Smckusick vaaddr = (struct vadevice *)ui->ui_addr; 3213183Swnj vaaddr->vacsl = VA_IENABLE; 3223183Swnj if (sc->sc_state & VPLOT) { 3233183Swnj vaaddr->vacsh = VAPLOT; 3243183Swnj DELAY(10000); 3253183Swnj vaaddr->vacsh = VAAUTOSTEP; 3263183Swnj } else if (sc->sc_state & VPRINTPLOT) 3273183Swnj vaaddr->vacsh = VPRINTPLOT; 3283183Swnj else 3293183Swnj vaaddr->vacsh = VAPRINTPLOT; 330287Sbill DELAY(10000); 331*9361Smckusick if (sc->sc_busy == 0) 332*9361Smckusick continue; 333*9361Smckusick if (sc->sc_ubinfo) { 334*9361Smckusick printf("<%d>", (sc->sc_ubinfo>>28)&0xf); 335*9361Smckusick ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 3363183Swnj } 337*9361Smckusick sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP); 338*9361Smckusick sc->sc_wc = -(sc->sc_bp->b_bcount/2); 339*9361Smckusick vastart(sc->sc_bp->b_dev); 340287Sbill } 341287Sbill } 3426432Ssam 3436432Ssam vaselect() 3446432Ssam { 3456432Ssam return (1); 3466432Ssam } 3471564Sbill #endif 348