1*11522Ssam /* vp.c 4.24 83/03/10 */ 244Sbill 31939Swnj #include "vp.h" 41565Sbill #if NVP > 0 51565Sbill /* 61565Sbill * Versatec matrix printer/plotter 71565Sbill * dma interface driver 83439Swnj * 93439Swnj * SETUP NOTES: 103439Swnj * Set up both print and plot interrupts to go through the same vector 113439Swnj * Give the address of the plcsr register in the config specification 121565Sbill */ 139785Ssam #include "../machine/pte.h" 149785Ssam 1544Sbill #include "../h/param.h" 1644Sbill #include "../h/dir.h" 1744Sbill #include "../h/user.h" 1844Sbill #include "../h/buf.h" 1944Sbill #include "../h/systm.h" 2044Sbill #include "../h/map.h" 21*11522Ssam #include "../h/ioctl.h" 223184Swnj #include "../h/vcmd.h" 237737Sroot #include "../h/uio.h" 2410877Ssam #include "../h/kernel.h" 2544Sbill 268484Sroot #include "../vaxuba/ubavar.h" 278484Sroot #include "../vaxuba/ubareg.h" 288484Sroot 2944Sbill unsigned minvpph(); 3044Sbill 3144Sbill #define VPPRI (PZERO-1) 3244Sbill 333184Swnj struct vpdevice { 3444Sbill short plbcr; 351903Swnj short pbxaddr; 3644Sbill short prbcr; 373184Swnj u_short pbaddr; 3844Sbill short plcsr; 3944Sbill short plbuf; 4044Sbill short prcsr; 413184Swnj u_short prbuf; 4244Sbill }; 4344Sbill 443184Swnj #define VP_ERROR 0100000 453184Swnj #define VP_DTCINTR 0040000 463184Swnj #define VP_DMAACT 0020000 473184Swnj #define VP_READY 0000200 483184Swnj #define VP_IENABLE 0000100 493184Swnj #define VP_TERMCOM 0000040 503184Swnj #define VP_FFCOM 0000020 513184Swnj #define VP_EOTCOM 0000010 523184Swnj #define VP_CLRCOM 0000004 533184Swnj #define VP_RESET 0000002 543184Swnj #define VP_SPP 0000001 5544Sbill 563184Swnj struct vp_softc { 573184Swnj int sc_state; 583184Swnj int sc_count; 593184Swnj int sc_bufp; 603184Swnj struct buf *sc_bp; 613184Swnj int sc_ubinfo; 623184Swnj } vp_softc[NVP]; 6344Sbill 643184Swnj /* sc_state bits */ 653184Swnj #define VPSC_BUSY 0001000 663184Swnj #define VPSC_MODE 0000700 673184Swnj #define VPSC_SPP 0000400 683184Swnj #define VPSC_PLOT 0000200 693184Swnj #define VPSC_PRINT 0000100 703184Swnj #define VPSC_CMNDS 0000076 713184Swnj #define VPSC_OPEN 0000001 7244Sbill 733184Swnj struct uba_device *vpdinfo[NVP]; 7444Sbill 753184Swnj #define VPUNIT(dev) (minor(dev)) 763184Swnj 773184Swnj struct buf rvpbuf[NVP]; 783184Swnj 793184Swnj int vpprobe(), vpattach(); 803184Swnj struct uba_device *vpdinfo[NVP]; 813184Swnj u_short vpstd[] = { 0777500, 0 }; 823184Swnj struct uba_driver vpdriver = 833184Swnj { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 843184Swnj 853184Swnj vpprobe(reg) 863184Swnj caddr_t reg; 8744Sbill { 883184Swnj register int br, cvec; /* value-result */ 893184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 9044Sbill 914942Swnj #ifdef lint 924942Swnj br = 0; cvec = br; br = cvec; 934942Swnj vpintr(0); 944942Swnj #endif 953184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 963184Swnj vpaddr->pbaddr = 0; 973184Swnj vpaddr->pbxaddr = 0; 983439Swnj vpaddr->prbcr = 1; 993184Swnj DELAY(10000); 1003184Swnj vpaddr->prcsr = 0; 1016859Ssam #if ERNIE || CAD || UCBVAX 1023439Swnj /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ 1033439Swnj if (cvec == 0200) { 1043439Swnj printf("vp reset vec from 200 to 174\n"); 1053439Swnj cvec = 0174; 1063439Swnj } 1073439Swnj #endif 1087408Skre return (sizeof (struct vpdevice)); 1093184Swnj } 1103184Swnj 1113184Swnj /*ARGSUSED*/ 1123184Swnj vpattach(ui) 1133184Swnj struct uba_device *ui; 1143184Swnj { 1153184Swnj 1163184Swnj ui->ui_addr -= 010; 1173184Swnj ui->ui_physaddr -= 010; 1183184Swnj } 1193184Swnj 1203184Swnj vpopen(dev) 1213184Swnj dev_t dev; 1223184Swnj { 1233184Swnj register struct vp_softc *sc; 1243184Swnj register struct vpdevice *vpaddr; 1253184Swnj register struct uba_device *ui; 1263184Swnj 1273184Swnj if (VPUNIT(dev) >= NVP || 1283184Swnj ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 1298578Sroot (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) 1308578Sroot return (ENXIO); 1313184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 1323184Swnj sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 1333184Swnj sc->sc_count = 0; 1343184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 1353184Swnj vptimo(dev); 1363184Swnj while (sc->sc_state & VPSC_CMNDS) { 137134Sbill (void) spl4(); 1383184Swnj if (vpwait(dev)) { 1393184Swnj vpclose(dev); 1408578Sroot return (EIO); 14144Sbill } 1423184Swnj vpstart(dev); 143134Sbill (void) spl0(); 14444Sbill } 1458578Sroot return (0); 14644Sbill } 14744Sbill 14844Sbill vpstrategy(bp) 14944Sbill register struct buf *bp; 15044Sbill { 15144Sbill register int e; 1523184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 1533184Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 1543184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 15544Sbill 156134Sbill (void) spl4(); 1573184Swnj while (sc->sc_state & VPSC_BUSY) 1583184Swnj sleep((caddr_t)sc, VPPRI); 1593184Swnj sc->sc_state |= VPSC_BUSY; 1603184Swnj sc->sc_bp = bp; 1613184Swnj sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 1623184Swnj if (e = vpwait(bp->b_dev)) 16344Sbill goto brkout; 1643184Swnj sc->sc_count = bp->b_bcount; 1653184Swnj vpstart(bp->b_dev); 1663184Swnj while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 1673184Swnj sleep((caddr_t)sc, VPPRI); 1683184Swnj sc->sc_count = 0; 1693184Swnj if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 1703184Swnj sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 171134Sbill (void) spl0(); 17244Sbill brkout: 1733184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 1743184Swnj sc->sc_state &= ~VPSC_BUSY; 1753184Swnj sc->sc_bp = 0; 1768494Sroot if (e) 1778494Sroot bp->b_flags |= B_ERROR; 17844Sbill iodone(bp); 1793184Swnj wakeup((caddr_t)sc); 18044Sbill } 18144Sbill 18244Sbill int vpblock = 16384; 18344Sbill 18444Sbill unsigned 18544Sbill minvpph(bp) 1863184Swnj struct buf *bp; 18744Sbill { 18844Sbill 18944Sbill if (bp->b_bcount > vpblock) 19044Sbill bp->b_bcount = vpblock; 19144Sbill } 19244Sbill 19344Sbill /*ARGSUSED*/ 1948168Sroot vpwrite(dev, uio) 1953184Swnj dev_t dev; 1968168Sroot struct uio *uio; 19744Sbill { 19844Sbill 1997848Sroot if (VPUNIT(dev) >= NVP) 2008168Sroot return (ENXIO); 2018168Sroot return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, 2028168Sroot minvpph, uio)); 20344Sbill } 20444Sbill 2053184Swnj vpwait(dev) 2063184Swnj dev_t dev; 20744Sbill { 2083184Swnj register struct vpdevice *vpaddr = 2093184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2103184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2113184Swnj register int e; 21244Sbill 2133184Swnj for (;;) { 2143184Swnj e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 2153184Swnj if (e & (VP_READY|VP_ERROR)) 2163184Swnj break; 2173184Swnj sleep((caddr_t)sc, VPPRI); 2183184Swnj } 2198494Sroot /* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */ 2203184Swnj return (e & VP_ERROR); 22144Sbill } 22244Sbill 2233184Swnj vpstart(dev) 2243184Swnj dev_t; 22544Sbill { 2263184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2273184Swnj register struct vpdevice *vpaddr = 2283184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2293184Swnj short bit; 23044Sbill 2313184Swnj if (sc->sc_count) { 2323184Swnj vpaddr->pbaddr = sc->sc_ubinfo; 2333184Swnj vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 2343184Swnj if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2353184Swnj vpaddr->prbcr = sc->sc_count; 23644Sbill else 2373184Swnj vpaddr->plbcr = sc->sc_count; 23844Sbill return; 23944Sbill } 24044Sbill for (bit = 1; bit != 0; bit <<= 1) 2413184Swnj if (sc->sc_state&bit&VPSC_CMNDS) { 2423184Swnj vpaddr->plcsr |= bit; 2433184Swnj sc->sc_state &= ~bit; 24444Sbill return; 24544Sbill } 24644Sbill } 24744Sbill 24844Sbill /*ARGSUSED*/ 24944Sbill vpioctl(dev, cmd, addr, flag) 2503184Swnj dev_t dev; 2513184Swnj int cmd; 25244Sbill register caddr_t addr; 2533184Swnj int flag; 25444Sbill { 25544Sbill register int m; 2563184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2573184Swnj register struct vpdevice *vpaddr = 2583184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 25944Sbill 26044Sbill switch (cmd) { 26144Sbill 2623184Swnj case VGETSTATE: 2633184Swnj (void) suword(addr, sc->sc_state); 2648578Sroot break; 26544Sbill 2663184Swnj case VSETSTATE: 26744Sbill m = fuword(addr); 2688578Sroot if (m == -1) 2698578Sroot return (EFAULT); 2703184Swnj sc->sc_state = 2713184Swnj (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 27244Sbill break; 27344Sbill 27444Sbill default: 2758578Sroot return (ENOTTY); 27644Sbill } 277134Sbill (void) spl4(); 2783184Swnj (void) vpwait(dev); 2793184Swnj if (sc->sc_state&VPSC_SPP) 2803184Swnj vpaddr->plcsr |= VP_SPP; 28144Sbill else 2823184Swnj vpaddr->plcsr &= ~VP_SPP; 2833184Swnj sc->sc_count = 0; 2843184Swnj while (sc->sc_state & VPSC_CMNDS) { 2853184Swnj (void) vpwait(dev); 2863184Swnj vpstart(dev); 28744Sbill } 288134Sbill (void) spl0(); 2898578Sroot return (0); 29044Sbill } 29144Sbill 2923184Swnj vptimo(dev) 2933184Swnj dev_t dev; 29444Sbill { 2953184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 29644Sbill 2973184Swnj if (sc->sc_state&VPSC_OPEN) 2983184Swnj timeout(vptimo, (caddr_t)dev, hz/10); 2993184Swnj vpintr(dev); 30044Sbill } 30144Sbill 30244Sbill /*ARGSUSED*/ 30344Sbill vpintr(dev) 3043184Swnj dev_t dev; 30544Sbill { 3063184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 30744Sbill 3083184Swnj wakeup((caddr_t)sc); 30944Sbill } 31044Sbill 3113184Swnj vpclose(dev) 3123184Swnj dev_t dev; 31344Sbill { 3143184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3153184Swnj register struct vpdevice *vpaddr = 3163184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 31744Sbill 3183184Swnj sc->sc_state = 0; 3193184Swnj sc->sc_count = 0; 3203184Swnj vpaddr->plcsr = 0; 32144Sbill } 322288Sbill 3233184Swnj vpreset(uban) 3243184Swnj int uban; 325288Sbill { 3263184Swnj register int vp11; 3273184Swnj register struct uba_device *ui; 3283184Swnj register struct vp_softc *sc = vp_softc; 3293184Swnj register struct vpdevice *vpaddr; 330288Sbill 3313184Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 3323184Swnj if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 3333184Swnj ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 3343184Swnj continue; 3353184Swnj printf(" vp%d", vp11); 3363184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 3373184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 3383184Swnj if ((sc->sc_state & VPSC_BUSY) == 0) 3393184Swnj continue; 3408578Sroot sc->sc_ubinfo = 0; 3413184Swnj sc->sc_count = sc->sc_bp->b_bcount; 3423184Swnj vpstart(sc->sc_bp->b_dev); 343288Sbill } 344288Sbill } 3456432Ssam 3466432Ssam vpselect() 3476432Ssam { 3486432Ssam return (1); 3496432Ssam } 3501565Sbill #endif 351