1*10877Ssam /* vp.c 4.23 83/02/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" 213184Swnj #include "../h/vcmd.h" 227737Sroot #include "../h/uio.h" 23*10877Ssam #include "../h/kernel.h" 2444Sbill 258484Sroot #include "../vaxuba/ubavar.h" 268484Sroot #include "../vaxuba/ubareg.h" 278484Sroot 2844Sbill unsigned minvpph(); 2944Sbill 3044Sbill #define VPPRI (PZERO-1) 3144Sbill 323184Swnj struct vpdevice { 3344Sbill short plbcr; 341903Swnj short pbxaddr; 3544Sbill short prbcr; 363184Swnj u_short pbaddr; 3744Sbill short plcsr; 3844Sbill short plbuf; 3944Sbill short prcsr; 403184Swnj u_short prbuf; 4144Sbill }; 4244Sbill 433184Swnj #define VP_ERROR 0100000 443184Swnj #define VP_DTCINTR 0040000 453184Swnj #define VP_DMAACT 0020000 463184Swnj #define VP_READY 0000200 473184Swnj #define VP_IENABLE 0000100 483184Swnj #define VP_TERMCOM 0000040 493184Swnj #define VP_FFCOM 0000020 503184Swnj #define VP_EOTCOM 0000010 513184Swnj #define VP_CLRCOM 0000004 523184Swnj #define VP_RESET 0000002 533184Swnj #define VP_SPP 0000001 5444Sbill 553184Swnj struct vp_softc { 563184Swnj int sc_state; 573184Swnj int sc_count; 583184Swnj int sc_bufp; 593184Swnj struct buf *sc_bp; 603184Swnj int sc_ubinfo; 613184Swnj } vp_softc[NVP]; 6244Sbill 633184Swnj /* sc_state bits */ 643184Swnj #define VPSC_BUSY 0001000 653184Swnj #define VPSC_MODE 0000700 663184Swnj #define VPSC_SPP 0000400 673184Swnj #define VPSC_PLOT 0000200 683184Swnj #define VPSC_PRINT 0000100 693184Swnj #define VPSC_CMNDS 0000076 703184Swnj #define VPSC_OPEN 0000001 7144Sbill 723184Swnj struct uba_device *vpdinfo[NVP]; 7344Sbill 743184Swnj #define VPUNIT(dev) (minor(dev)) 753184Swnj 763184Swnj struct buf rvpbuf[NVP]; 773184Swnj 783184Swnj int vpprobe(), vpattach(); 793184Swnj struct uba_device *vpdinfo[NVP]; 803184Swnj u_short vpstd[] = { 0777500, 0 }; 813184Swnj struct uba_driver vpdriver = 823184Swnj { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 833184Swnj 843184Swnj vpprobe(reg) 853184Swnj caddr_t reg; 8644Sbill { 873184Swnj register int br, cvec; /* value-result */ 883184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 8944Sbill 904942Swnj #ifdef lint 914942Swnj br = 0; cvec = br; br = cvec; 924942Swnj vpintr(0); 934942Swnj #endif 943184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 953184Swnj vpaddr->pbaddr = 0; 963184Swnj vpaddr->pbxaddr = 0; 973439Swnj vpaddr->prbcr = 1; 983184Swnj DELAY(10000); 993184Swnj vpaddr->prcsr = 0; 1006859Ssam #if ERNIE || CAD || UCBVAX 1013439Swnj /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ 1023439Swnj if (cvec == 0200) { 1033439Swnj printf("vp reset vec from 200 to 174\n"); 1043439Swnj cvec = 0174; 1053439Swnj } 1063439Swnj #endif 1077408Skre return (sizeof (struct vpdevice)); 1083184Swnj } 1093184Swnj 1103184Swnj /*ARGSUSED*/ 1113184Swnj vpattach(ui) 1123184Swnj struct uba_device *ui; 1133184Swnj { 1143184Swnj 1153184Swnj ui->ui_addr -= 010; 1163184Swnj ui->ui_physaddr -= 010; 1173184Swnj } 1183184Swnj 1193184Swnj vpopen(dev) 1203184Swnj dev_t dev; 1213184Swnj { 1223184Swnj register struct vp_softc *sc; 1233184Swnj register struct vpdevice *vpaddr; 1243184Swnj register struct uba_device *ui; 1253184Swnj 1263184Swnj if (VPUNIT(dev) >= NVP || 1273184Swnj ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 1288578Sroot (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) 1298578Sroot return (ENXIO); 1303184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 1313184Swnj sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 1323184Swnj sc->sc_count = 0; 1333184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 1343184Swnj vptimo(dev); 1353184Swnj while (sc->sc_state & VPSC_CMNDS) { 136134Sbill (void) spl4(); 1373184Swnj if (vpwait(dev)) { 1383184Swnj vpclose(dev); 1398578Sroot return (EIO); 14044Sbill } 1413184Swnj vpstart(dev); 142134Sbill (void) spl0(); 14344Sbill } 1448578Sroot return (0); 14544Sbill } 14644Sbill 14744Sbill vpstrategy(bp) 14844Sbill register struct buf *bp; 14944Sbill { 15044Sbill register int e; 1513184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 1523184Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 1533184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 15444Sbill 155134Sbill (void) spl4(); 1563184Swnj while (sc->sc_state & VPSC_BUSY) 1573184Swnj sleep((caddr_t)sc, VPPRI); 1583184Swnj sc->sc_state |= VPSC_BUSY; 1593184Swnj sc->sc_bp = bp; 1603184Swnj sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 1613184Swnj if (e = vpwait(bp->b_dev)) 16244Sbill goto brkout; 1633184Swnj sc->sc_count = bp->b_bcount; 1643184Swnj vpstart(bp->b_dev); 1653184Swnj while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 1663184Swnj sleep((caddr_t)sc, VPPRI); 1673184Swnj sc->sc_count = 0; 1683184Swnj if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 1693184Swnj sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 170134Sbill (void) spl0(); 17144Sbill brkout: 1723184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 1733184Swnj sc->sc_state &= ~VPSC_BUSY; 1743184Swnj sc->sc_bp = 0; 1758494Sroot if (e) 1768494Sroot bp->b_flags |= B_ERROR; 17744Sbill iodone(bp); 1783184Swnj wakeup((caddr_t)sc); 17944Sbill } 18044Sbill 18144Sbill int vpblock = 16384; 18244Sbill 18344Sbill unsigned 18444Sbill minvpph(bp) 1853184Swnj struct buf *bp; 18644Sbill { 18744Sbill 18844Sbill if (bp->b_bcount > vpblock) 18944Sbill bp->b_bcount = vpblock; 19044Sbill } 19144Sbill 19244Sbill /*ARGSUSED*/ 1938168Sroot vpwrite(dev, uio) 1943184Swnj dev_t dev; 1958168Sroot struct uio *uio; 19644Sbill { 19744Sbill 1987848Sroot if (VPUNIT(dev) >= NVP) 1998168Sroot return (ENXIO); 2008168Sroot return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, 2018168Sroot minvpph, uio)); 20244Sbill } 20344Sbill 2043184Swnj vpwait(dev) 2053184Swnj dev_t dev; 20644Sbill { 2073184Swnj register struct vpdevice *vpaddr = 2083184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2093184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2103184Swnj register int e; 21144Sbill 2123184Swnj for (;;) { 2133184Swnj e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 2143184Swnj if (e & (VP_READY|VP_ERROR)) 2153184Swnj break; 2163184Swnj sleep((caddr_t)sc, VPPRI); 2173184Swnj } 2188494Sroot /* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */ 2193184Swnj return (e & VP_ERROR); 22044Sbill } 22144Sbill 2223184Swnj vpstart(dev) 2233184Swnj dev_t; 22444Sbill { 2253184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2263184Swnj register struct vpdevice *vpaddr = 2273184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2283184Swnj short bit; 22944Sbill 2303184Swnj if (sc->sc_count) { 2313184Swnj vpaddr->pbaddr = sc->sc_ubinfo; 2323184Swnj vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 2333184Swnj if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2343184Swnj vpaddr->prbcr = sc->sc_count; 23544Sbill else 2363184Swnj vpaddr->plbcr = sc->sc_count; 23744Sbill return; 23844Sbill } 23944Sbill for (bit = 1; bit != 0; bit <<= 1) 2403184Swnj if (sc->sc_state&bit&VPSC_CMNDS) { 2413184Swnj vpaddr->plcsr |= bit; 2423184Swnj sc->sc_state &= ~bit; 24344Sbill return; 24444Sbill } 24544Sbill } 24644Sbill 24744Sbill /*ARGSUSED*/ 24844Sbill vpioctl(dev, cmd, addr, flag) 2493184Swnj dev_t dev; 2503184Swnj int cmd; 25144Sbill register caddr_t addr; 2523184Swnj int flag; 25344Sbill { 25444Sbill register int m; 2553184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2563184Swnj register struct vpdevice *vpaddr = 2573184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 25844Sbill 25944Sbill switch (cmd) { 26044Sbill 2613184Swnj case VGETSTATE: 2623184Swnj (void) suword(addr, sc->sc_state); 2638578Sroot break; 26444Sbill 2653184Swnj case VSETSTATE: 26644Sbill m = fuword(addr); 2678578Sroot if (m == -1) 2688578Sroot return (EFAULT); 2693184Swnj sc->sc_state = 2703184Swnj (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 27144Sbill break; 27244Sbill 27344Sbill default: 2748578Sroot return (ENOTTY); 27544Sbill } 276134Sbill (void) spl4(); 2773184Swnj (void) vpwait(dev); 2783184Swnj if (sc->sc_state&VPSC_SPP) 2793184Swnj vpaddr->plcsr |= VP_SPP; 28044Sbill else 2813184Swnj vpaddr->plcsr &= ~VP_SPP; 2823184Swnj sc->sc_count = 0; 2833184Swnj while (sc->sc_state & VPSC_CMNDS) { 2843184Swnj (void) vpwait(dev); 2853184Swnj vpstart(dev); 28644Sbill } 287134Sbill (void) spl0(); 2888578Sroot return (0); 28944Sbill } 29044Sbill 2913184Swnj vptimo(dev) 2923184Swnj dev_t dev; 29344Sbill { 2943184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 29544Sbill 2963184Swnj if (sc->sc_state&VPSC_OPEN) 2973184Swnj timeout(vptimo, (caddr_t)dev, hz/10); 2983184Swnj vpintr(dev); 29944Sbill } 30044Sbill 30144Sbill /*ARGSUSED*/ 30244Sbill vpintr(dev) 3033184Swnj dev_t dev; 30444Sbill { 3053184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 30644Sbill 3073184Swnj wakeup((caddr_t)sc); 30844Sbill } 30944Sbill 3103184Swnj vpclose(dev) 3113184Swnj dev_t dev; 31244Sbill { 3133184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3143184Swnj register struct vpdevice *vpaddr = 3153184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 31644Sbill 3173184Swnj sc->sc_state = 0; 3183184Swnj sc->sc_count = 0; 3193184Swnj vpaddr->plcsr = 0; 32044Sbill } 321288Sbill 3223184Swnj vpreset(uban) 3233184Swnj int uban; 324288Sbill { 3253184Swnj register int vp11; 3263184Swnj register struct uba_device *ui; 3273184Swnj register struct vp_softc *sc = vp_softc; 3283184Swnj register struct vpdevice *vpaddr; 329288Sbill 3303184Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 3313184Swnj if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 3323184Swnj ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 3333184Swnj continue; 3343184Swnj printf(" vp%d", vp11); 3353184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 3363184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 3373184Swnj if ((sc->sc_state & VPSC_BUSY) == 0) 3383184Swnj continue; 3398578Sroot sc->sc_ubinfo = 0; 3403184Swnj sc->sc_count = sc->sc_bp->b_bcount; 3413184Swnj vpstart(sc->sc_bp->b_dev); 342288Sbill } 343288Sbill } 3446432Ssam 3456432Ssam vpselect() 3466432Ssam { 3476432Ssam return (1); 3486432Ssam } 3491565Sbill #endif 350