1*15074Skarels /* vp.c 6.3 83/09/25 */ 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 11*15074Skarels * (or kludge probe to reset second vector to first; 12*15074Skarels * default 174/200 is already handled). 133439Swnj * Give the address of the plcsr register in the config specification 141565Sbill */ 159785Ssam #include "../machine/pte.h" 169785Ssam 1744Sbill #include "../h/param.h" 1844Sbill #include "../h/dir.h" 1944Sbill #include "../h/user.h" 2044Sbill #include "../h/buf.h" 2144Sbill #include "../h/systm.h" 2244Sbill #include "../h/map.h" 2311522Ssam #include "../h/ioctl.h" 243184Swnj #include "../h/vcmd.h" 257737Sroot #include "../h/uio.h" 2610877Ssam #include "../h/kernel.h" 2744Sbill 288484Sroot #include "../vaxuba/ubavar.h" 298484Sroot #include "../vaxuba/ubareg.h" 308484Sroot 3144Sbill unsigned minvpph(); 3244Sbill 33*15074Skarels #define VPPRI (PZERO-1) 34*15074Skarels 35*15074Skarels struct vpdevice { 36*15074Skarels short plbcr; 37*15074Skarels short pbxaddr; 38*15074Skarels short prbcr; 39*15074Skarels u_short pbaddr; 40*15074Skarels short plcsr; 41*15074Skarels short plbuf; 42*15074Skarels short prcsr; 43*15074Skarels u_short prbuf; 44*15074Skarels }; 45*15074Skarels 46*15074Skarels #define VP_ERROR 0100000 47*15074Skarels #define VP_DTCINTR 0040000 48*15074Skarels #define VP_DMAACT 0020000 49*15074Skarels #define VP_READY 0000200 50*15074Skarels #define VP_IENABLE 0000100 51*15074Skarels #define VP_TERMCOM 0000040 52*15074Skarels #define VP_FFCOM 0000020 53*15074Skarels #define VP_EOTCOM 0000010 54*15074Skarels #define VP_CLRCOM 0000004 55*15074Skarels #define VP_RESET 0000002 56*15074Skarels #define VP_SPP 0000001 57*15074Skarels 583184Swnj struct vp_softc { 593184Swnj int sc_state; 603184Swnj int sc_count; 61*15074Skarels int sc_bufp; 62*15074Skarels struct buf *sc_bp; 63*15074Skarels int sc_ubinfo; 643184Swnj } vp_softc[NVP]; 6544Sbill 663184Swnj /* sc_state bits */ 67*15074Skarels #define VPSC_BUSY 0001000 683184Swnj #define VPSC_MODE 0000700 69*15074Skarels #define VPSC_SPP 0000400 70*15074Skarels #define VPSC_PLOT 0000200 71*15074Skarels #define VPSC_PRINT 0000100 723184Swnj #define VPSC_CMNDS 0000076 73*15074Skarels #define VPSC_OPEN 0000001 7444Sbill 753184Swnj struct uba_device *vpdinfo[NVP]; 7644Sbill 773184Swnj #define VPUNIT(dev) (minor(dev)) 783184Swnj 793184Swnj struct buf rvpbuf[NVP]; 803184Swnj 81*15074Skarels int vpprobe(), vpattach(); 823184Swnj struct uba_device *vpdinfo[NVP]; 833184Swnj u_short vpstd[] = { 0777500, 0 }; 843184Swnj struct uba_driver vpdriver = 85*15074Skarels { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 863184Swnj 873184Swnj vpprobe(reg) 883184Swnj caddr_t reg; 8944Sbill { 903184Swnj register int br, cvec; /* value-result */ 913184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 9244Sbill 934942Swnj #ifdef lint 944942Swnj br = 0; cvec = br; br = cvec; 954942Swnj vpintr(0); 964942Swnj #endif 973184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 983184Swnj vpaddr->pbaddr = 0; 993184Swnj vpaddr->pbxaddr = 0; 1003439Swnj vpaddr->prbcr = 1; 1013184Swnj DELAY(10000); 1023184Swnj vpaddr->prcsr = 0; 103*15074Skarels /* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */ 1043439Swnj if (cvec == 0200) { 1053439Swnj printf("vp reset vec from 200 to 174\n"); 1063439Swnj cvec = 0174; 1073439Swnj } 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 127*15074Skarels if (VPUNIT(dev) >= NVP || 128*15074Skarels ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 129*15074Skarels (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) 1308578Sroot return (ENXIO); 1313184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 132*15074Skarels sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 133*15074Skarels sc->sc_count = 0; 1343184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 135*15074Skarels vptimo(dev); 136*15074Skarels while (sc->sc_state & VPSC_CMNDS) { 137*15074Skarels (void) spl4(); 138*15074Skarels if (vpwait(dev)) { 139*15074Skarels vpclose(dev); 140*15074Skarels return (EIO); 141*15074Skarels } 142*15074Skarels vpstart(dev); 143*15074Skarels (void) spl0(); 144*15074Skarels } 145*15074Skarels return (0); 14644Sbill } 14744Sbill 14844Sbill vpstrategy(bp) 14944Sbill register struct buf *bp; 15044Sbill { 151*15074Skarels 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 156*15074Skarels (void) spl4(); 157*15074Skarels while (sc->sc_state & VPSC_BUSY) 158*15074Skarels sleep((caddr_t)sc, VPPRI); 159*15074Skarels sc->sc_state |= VPSC_BUSY; 160*15074Skarels sc->sc_bp = bp; 161*15074Skarels sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 162*15074Skarels if (e = vpwait(bp->b_dev)) 163*15074Skarels goto brkout; 164*15074Skarels sc->sc_count = bp->b_bcount; 165*15074Skarels vpstart(bp->b_dev); 166*15074Skarels while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 167*15074Skarels sleep((caddr_t)sc, VPPRI); 168*15074Skarels sc->sc_count = 0; 169*15074Skarels if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 170*15074Skarels sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 171*15074Skarels (void) spl0(); 172*15074Skarels brkout: 173*15074Skarels ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 174*15074Skarels sc->sc_state &= ~VPSC_BUSY; 175*15074Skarels sc->sc_bp = 0; 176*15074Skarels if (e) 1778494Sroot bp->b_flags |= B_ERROR; 178*15074Skarels iodone(bp); 179*15074Skarels 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 205*15074Skarels vpwait(dev) 206*15074Skarels dev_t dev; 20744Sbill { 208*15074Skarels register struct vpdevice *vpaddr = 209*15074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 210*15074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 211*15074Skarels register int e; 21244Sbill 213*15074Skarels for (;;) { 214*15074Skarels e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 215*15074Skarels if (e & (VP_READY|VP_ERROR)) 216*15074Skarels break; 217*15074Skarels sleep((caddr_t)sc, VPPRI); 218*15074Skarels } 219*15074Skarels /* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */ 220*15074Skarels return (e & VP_ERROR); 22144Sbill } 22244Sbill 223*15074Skarels vpstart(dev) 224*15074Skarels dev_t; 22544Sbill { 226*15074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 227*15074Skarels register struct vpdevice *vpaddr = 228*15074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 229*15074Skarels short bit; 23044Sbill 2313184Swnj if (sc->sc_count) { 232*15074Skarels vpaddr->pbaddr = sc->sc_ubinfo; 233*15074Skarels vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 234*15074Skarels if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2353184Swnj vpaddr->prbcr = sc->sc_count; 23644Sbill else 2373184Swnj vpaddr->plbcr = sc->sc_count; 238*15074Skarels return; 23944Sbill } 240*15074Skarels for (bit = 1; bit != 0; bit <<= 1) 241*15074Skarels if (sc->sc_state&bit&VPSC_CMNDS) { 242*15074Skarels vpaddr->plcsr |= bit; 243*15074Skarels sc->sc_state &= ~bit; 244*15074Skarels return; 245*15074Skarels } 24644Sbill } 24744Sbill 24844Sbill /*ARGSUSED*/ 24911815Ssam vpioctl(dev, cmd, data, flag) 250*15074Skarels dev_t dev; 251*15074Skarels int cmd; 25211815Ssam register caddr_t data; 253*15074Skarels int flag; 25444Sbill { 255*15074Skarels register int m; 2563184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 257*15074Skarels register struct vpdevice *vpaddr = 258*15074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 25944Sbill 26044Sbill switch (cmd) { 26144Sbill 2623184Swnj case VGETSTATE: 26311815Ssam *(int *)data = sc->sc_state; 2648578Sroot break; 26544Sbill 2663184Swnj case VSETSTATE: 267*15074Skarels sc->sc_state = 268*15074Skarels (sc->sc_state & ~VPSC_MODE) | 269*15074Skarels ((*(int *)data) & (VPSC_MODE|VPSC_CMNDS)); 270*15074Skarels break; 27144Sbill 27244Sbill default: 2738578Sroot return (ENOTTY); 27444Sbill } 275*15074Skarels (void) spl4(); 276*15074Skarels (void) vpwait(dev); 277*15074Skarels if (sc->sc_state&VPSC_SPP) 278*15074Skarels vpaddr->plcsr |= VP_SPP; 279*15074Skarels else 280*15074Skarels vpaddr->plcsr &= ~VP_SPP; 281*15074Skarels sc->sc_count = 0; 282*15074Skarels while (sc->sc_state & VPSC_CMNDS) { 283*15074Skarels (void) vpwait(dev); 284*15074Skarels vpstart(dev); 28544Sbill } 286*15074Skarels (void) spl0(); 2878578Sroot return (0); 28844Sbill } 28944Sbill 2903184Swnj vptimo(dev) 2913184Swnj dev_t dev; 29244Sbill { 2933184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 29444Sbill 295*15074Skarels if (sc->sc_state&VPSC_OPEN) 296*15074Skarels timeout(vptimo, (caddr_t)dev, hz/10); 2973184Swnj vpintr(dev); 29844Sbill } 29944Sbill 30044Sbill /*ARGSUSED*/ 30144Sbill vpintr(dev) 3023184Swnj dev_t dev; 30344Sbill { 304*15074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 30544Sbill 306*15074Skarels wakeup((caddr_t)sc); 30744Sbill } 30844Sbill 3093184Swnj vpclose(dev) 3103184Swnj dev_t dev; 31144Sbill { 3123184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3133184Swnj register struct vpdevice *vpaddr = 3143184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 31544Sbill 3163184Swnj sc->sc_state = 0; 317*15074Skarels sc->sc_count = 0; 3183184Swnj vpaddr->plcsr = 0; 31944Sbill } 320288Sbill 3213184Swnj vpreset(uban) 3223184Swnj int uban; 323288Sbill { 3243184Swnj register int vp11; 325*15074Skarels register struct uba_device *ui; 326*15074Skarels register struct vp_softc *sc = vp_softc; 3273184Swnj register struct vpdevice *vpaddr; 328288Sbill 3293184Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 330*15074Skarels if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 331*15074Skarels ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 3323184Swnj continue; 3333184Swnj printf(" vp%d", vp11); 334*15074Skarels vpaddr = (struct vpdevice *)ui->ui_addr; 3353184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 336*15074Skarels if ((sc->sc_state & VPSC_BUSY) == 0) 337*15074Skarels continue; 338*15074Skarels sc->sc_ubinfo = 0; 339*15074Skarels sc->sc_count = sc->sc_bp->b_bcount; 340*15074Skarels vpstart(sc->sc_bp->b_dev); 341288Sbill } 342288Sbill } 3436432Ssam 3446432Ssam vpselect() 3456432Ssam { 3466432Ssam return (1); 3476432Ssam } 3481565Sbill #endif 349