1*8578Sroot /* vp.c 4.21 82/10/17 */ 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 */ 1344Sbill #include "../h/param.h" 1444Sbill #include "../h/dir.h" 1544Sbill #include "../h/user.h" 1644Sbill #include "../h/buf.h" 1744Sbill #include "../h/systm.h" 1844Sbill #include "../h/map.h" 1944Sbill #include "../h/pte.h" 203184Swnj #include "../h/vcmd.h" 217737Sroot #include "../h/uio.h" 2244Sbill 238484Sroot #include "../vaxuba/ubavar.h" 248484Sroot #include "../vaxuba/ubareg.h" 258484Sroot 2644Sbill unsigned minvpph(); 2744Sbill 2844Sbill #define VPPRI (PZERO-1) 2944Sbill 303184Swnj struct vpdevice { 3144Sbill short plbcr; 321903Swnj short pbxaddr; 3344Sbill short prbcr; 343184Swnj u_short pbaddr; 3544Sbill short plcsr; 3644Sbill short plbuf; 3744Sbill short prcsr; 383184Swnj u_short prbuf; 3944Sbill }; 4044Sbill 413184Swnj #define VP_ERROR 0100000 423184Swnj #define VP_DTCINTR 0040000 433184Swnj #define VP_DMAACT 0020000 443184Swnj #define VP_READY 0000200 453184Swnj #define VP_IENABLE 0000100 463184Swnj #define VP_TERMCOM 0000040 473184Swnj #define VP_FFCOM 0000020 483184Swnj #define VP_EOTCOM 0000010 493184Swnj #define VP_CLRCOM 0000004 503184Swnj #define VP_RESET 0000002 513184Swnj #define VP_SPP 0000001 5244Sbill 533184Swnj struct vp_softc { 543184Swnj int sc_state; 553184Swnj int sc_count; 563184Swnj int sc_bufp; 573184Swnj struct buf *sc_bp; 583184Swnj int sc_ubinfo; 593184Swnj } vp_softc[NVP]; 6044Sbill 613184Swnj /* sc_state bits */ 623184Swnj #define VPSC_BUSY 0001000 633184Swnj #define VPSC_MODE 0000700 643184Swnj #define VPSC_SPP 0000400 653184Swnj #define VPSC_PLOT 0000200 663184Swnj #define VPSC_PRINT 0000100 673184Swnj #define VPSC_CMNDS 0000076 683184Swnj #define VPSC_OPEN 0000001 6944Sbill 703184Swnj struct uba_device *vpdinfo[NVP]; 7144Sbill 723184Swnj #define VPUNIT(dev) (minor(dev)) 733184Swnj 743184Swnj struct buf rvpbuf[NVP]; 753184Swnj 763184Swnj int vpprobe(), vpattach(); 773184Swnj struct uba_device *vpdinfo[NVP]; 783184Swnj u_short vpstd[] = { 0777500, 0 }; 793184Swnj struct uba_driver vpdriver = 803184Swnj { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 813184Swnj 823184Swnj vpprobe(reg) 833184Swnj caddr_t reg; 8444Sbill { 853184Swnj register int br, cvec; /* value-result */ 863184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 8744Sbill 884942Swnj #ifdef lint 894942Swnj br = 0; cvec = br; br = cvec; 904942Swnj vpintr(0); 914942Swnj #endif 923184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 933184Swnj vpaddr->pbaddr = 0; 943184Swnj vpaddr->pbxaddr = 0; 953439Swnj vpaddr->prbcr = 1; 963184Swnj DELAY(10000); 973184Swnj vpaddr->prcsr = 0; 986859Ssam #if ERNIE || CAD || UCBVAX 993439Swnj /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ 1003439Swnj if (cvec == 0200) { 1013439Swnj printf("vp reset vec from 200 to 174\n"); 1023439Swnj cvec = 0174; 1033439Swnj } 1043439Swnj #endif 1057408Skre return (sizeof (struct vpdevice)); 1063184Swnj } 1073184Swnj 1083184Swnj /*ARGSUSED*/ 1093184Swnj vpattach(ui) 1103184Swnj struct uba_device *ui; 1113184Swnj { 1123184Swnj 1133184Swnj ui->ui_addr -= 010; 1143184Swnj ui->ui_physaddr -= 010; 1153184Swnj } 1163184Swnj 1173184Swnj vpopen(dev) 1183184Swnj dev_t dev; 1193184Swnj { 1203184Swnj register struct vp_softc *sc; 1213184Swnj register struct vpdevice *vpaddr; 1223184Swnj register struct uba_device *ui; 1233184Swnj 1243184Swnj if (VPUNIT(dev) >= NVP || 1253184Swnj ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 126*8578Sroot (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) 127*8578Sroot return (ENXIO); 1283184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 1293184Swnj sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 1303184Swnj sc->sc_count = 0; 1313184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 1323184Swnj vptimo(dev); 1333184Swnj while (sc->sc_state & VPSC_CMNDS) { 134134Sbill (void) spl4(); 1353184Swnj if (vpwait(dev)) { 1363184Swnj vpclose(dev); 137*8578Sroot return (EIO); 13844Sbill } 1393184Swnj vpstart(dev); 140134Sbill (void) spl0(); 14144Sbill } 142*8578Sroot return (0); 14344Sbill } 14444Sbill 14544Sbill vpstrategy(bp) 14644Sbill register struct buf *bp; 14744Sbill { 14844Sbill register int e; 1493184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 1503184Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 1513184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 15244Sbill 153134Sbill (void) spl4(); 1543184Swnj while (sc->sc_state & VPSC_BUSY) 1553184Swnj sleep((caddr_t)sc, VPPRI); 1563184Swnj sc->sc_state |= VPSC_BUSY; 1573184Swnj sc->sc_bp = bp; 1583184Swnj sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 1593184Swnj if (e = vpwait(bp->b_dev)) 16044Sbill goto brkout; 1613184Swnj sc->sc_count = bp->b_bcount; 1623184Swnj vpstart(bp->b_dev); 1633184Swnj while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 1643184Swnj sleep((caddr_t)sc, VPPRI); 1653184Swnj sc->sc_count = 0; 1663184Swnj if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 1673184Swnj sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 168134Sbill (void) spl0(); 16944Sbill brkout: 1703184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 1713184Swnj sc->sc_state &= ~VPSC_BUSY; 1723184Swnj sc->sc_bp = 0; 1738494Sroot if (e) 1748494Sroot bp->b_flags |= B_ERROR; 17544Sbill iodone(bp); 1763184Swnj wakeup((caddr_t)sc); 17744Sbill } 17844Sbill 17944Sbill int vpblock = 16384; 18044Sbill 18144Sbill unsigned 18244Sbill minvpph(bp) 1833184Swnj struct buf *bp; 18444Sbill { 18544Sbill 18644Sbill if (bp->b_bcount > vpblock) 18744Sbill bp->b_bcount = vpblock; 18844Sbill } 18944Sbill 19044Sbill /*ARGSUSED*/ 1918168Sroot vpwrite(dev, uio) 1923184Swnj dev_t dev; 1938168Sroot struct uio *uio; 19444Sbill { 19544Sbill 1967848Sroot if (VPUNIT(dev) >= NVP) 1978168Sroot return (ENXIO); 1988168Sroot return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, 1998168Sroot minvpph, uio)); 20044Sbill } 20144Sbill 2023184Swnj vpwait(dev) 2033184Swnj dev_t dev; 20444Sbill { 2053184Swnj register struct vpdevice *vpaddr = 2063184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2073184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2083184Swnj register int e; 20944Sbill 2103184Swnj for (;;) { 2113184Swnj e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 2123184Swnj if (e & (VP_READY|VP_ERROR)) 2133184Swnj break; 2143184Swnj sleep((caddr_t)sc, VPPRI); 2153184Swnj } 2168494Sroot /* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */ 2173184Swnj return (e & VP_ERROR); 21844Sbill } 21944Sbill 2203184Swnj vpstart(dev) 2213184Swnj dev_t; 22244Sbill { 2233184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2243184Swnj register struct vpdevice *vpaddr = 2253184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2263184Swnj short bit; 22744Sbill 2283184Swnj if (sc->sc_count) { 2293184Swnj vpaddr->pbaddr = sc->sc_ubinfo; 2303184Swnj vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 2313184Swnj if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2323184Swnj vpaddr->prbcr = sc->sc_count; 23344Sbill else 2343184Swnj vpaddr->plbcr = sc->sc_count; 23544Sbill return; 23644Sbill } 23744Sbill for (bit = 1; bit != 0; bit <<= 1) 2383184Swnj if (sc->sc_state&bit&VPSC_CMNDS) { 2393184Swnj vpaddr->plcsr |= bit; 2403184Swnj sc->sc_state &= ~bit; 24144Sbill return; 24244Sbill } 24344Sbill } 24444Sbill 24544Sbill /*ARGSUSED*/ 24644Sbill vpioctl(dev, cmd, addr, flag) 2473184Swnj dev_t dev; 2483184Swnj int cmd; 24944Sbill register caddr_t addr; 2503184Swnj int flag; 25144Sbill { 25244Sbill register int m; 2533184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2543184Swnj register struct vpdevice *vpaddr = 2553184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 25644Sbill 25744Sbill switch (cmd) { 25844Sbill 2593184Swnj case VGETSTATE: 2603184Swnj (void) suword(addr, sc->sc_state); 261*8578Sroot break; 26244Sbill 2633184Swnj case VSETSTATE: 26444Sbill m = fuword(addr); 265*8578Sroot if (m == -1) 266*8578Sroot return (EFAULT); 2673184Swnj sc->sc_state = 2683184Swnj (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 26944Sbill break; 27044Sbill 27144Sbill default: 272*8578Sroot return (ENOTTY); 27344Sbill } 274134Sbill (void) spl4(); 2753184Swnj (void) vpwait(dev); 2763184Swnj if (sc->sc_state&VPSC_SPP) 2773184Swnj vpaddr->plcsr |= VP_SPP; 27844Sbill else 2793184Swnj vpaddr->plcsr &= ~VP_SPP; 2803184Swnj sc->sc_count = 0; 2813184Swnj while (sc->sc_state & VPSC_CMNDS) { 2823184Swnj (void) vpwait(dev); 2833184Swnj vpstart(dev); 28444Sbill } 285134Sbill (void) spl0(); 286*8578Sroot return (0); 28744Sbill } 28844Sbill 2893184Swnj vptimo(dev) 2903184Swnj dev_t dev; 29144Sbill { 2923184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 29344Sbill 2943184Swnj if (sc->sc_state&VPSC_OPEN) 2953184Swnj timeout(vptimo, (caddr_t)dev, hz/10); 2963184Swnj vpintr(dev); 29744Sbill } 29844Sbill 29944Sbill /*ARGSUSED*/ 30044Sbill vpintr(dev) 3013184Swnj dev_t dev; 30244Sbill { 3033184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 30444Sbill 3053184Swnj wakeup((caddr_t)sc); 30644Sbill } 30744Sbill 3083184Swnj vpclose(dev) 3093184Swnj dev_t dev; 31044Sbill { 3113184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3123184Swnj register struct vpdevice *vpaddr = 3133184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 31444Sbill 3153184Swnj sc->sc_state = 0; 3163184Swnj sc->sc_count = 0; 3173184Swnj vpaddr->plcsr = 0; 31844Sbill } 319288Sbill 3203184Swnj vpreset(uban) 3213184Swnj int uban; 322288Sbill { 3233184Swnj register int vp11; 3243184Swnj register struct uba_device *ui; 3253184Swnj register struct vp_softc *sc = vp_softc; 3263184Swnj register struct vpdevice *vpaddr; 327288Sbill 3283184Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 3293184Swnj if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 3303184Swnj ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 3313184Swnj continue; 3323184Swnj printf(" vp%d", vp11); 3333184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 3343184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 3353184Swnj if ((sc->sc_state & VPSC_BUSY) == 0) 3363184Swnj continue; 337*8578Sroot sc->sc_ubinfo = 0; 3383184Swnj sc->sc_count = sc->sc_bp->b_bcount; 3393184Swnj vpstart(sc->sc_bp->b_dev); 340288Sbill } 341288Sbill } 3426432Ssam 3436432Ssam vpselect() 3446432Ssam { 3456432Ssam return (1); 3466432Ssam } 3471565Sbill #endif 348