1*3184Swnj /* vp.c 4.8 81/03/10 */ 244Sbill 31939Swnj #include "vp.h" 41565Sbill #if NVP > 0 51565Sbill /* 61565Sbill * Versatec matrix printer/plotter 71565Sbill * dma interface driver 81565Sbill */ 944Sbill #include "../h/param.h" 1044Sbill #include "../h/dir.h" 1144Sbill #include "../h/user.h" 1244Sbill #include "../h/buf.h" 1344Sbill #include "../h/systm.h" 1444Sbill #include "../h/map.h" 1544Sbill #include "../h/pte.h" 16*3184Swnj #include "../h/ubavar.h" 17*3184Swnj #include "../h/ubareg.h" 18*3184Swnj #include "../h/vcmd.h" 1944Sbill 2044Sbill unsigned minvpph(); 2144Sbill 2244Sbill #define VPPRI (PZERO-1) 2344Sbill 24*3184Swnj struct vpdevice { 2544Sbill short plbcr; 261903Swnj short pbxaddr; 2744Sbill short prbcr; 28*3184Swnj u_short pbaddr; 2944Sbill short plcsr; 3044Sbill short plbuf; 3144Sbill short prcsr; 32*3184Swnj u_short prbuf; 3344Sbill }; 3444Sbill 35*3184Swnj #define VP_ERROR 0100000 36*3184Swnj #define VP_DTCINTR 0040000 37*3184Swnj #define VP_DMAACT 0020000 38*3184Swnj #define VP_READY 0000200 39*3184Swnj #define VP_IENABLE 0000100 40*3184Swnj #define VP_TERMCOM 0000040 41*3184Swnj #define VP_FFCOM 0000020 42*3184Swnj #define VP_EOTCOM 0000010 43*3184Swnj #define VP_CLRCOM 0000004 44*3184Swnj #define VP_RESET 0000002 45*3184Swnj #define VP_SPP 0000001 4644Sbill 47*3184Swnj struct vp_softc { 48*3184Swnj int sc_state; 49*3184Swnj int sc_count; 50*3184Swnj int sc_bufp; 51*3184Swnj struct buf *sc_bp; 52*3184Swnj int sc_ubinfo; 53*3184Swnj } vp_softc[NVP]; 5444Sbill 55*3184Swnj /* sc_state bits */ 56*3184Swnj #define VPSC_BUSY 0001000 57*3184Swnj #define VPSC_MODE 0000700 58*3184Swnj #define VPSC_SPP 0000400 59*3184Swnj #define VPSC_PLOT 0000200 60*3184Swnj #define VPSC_PRINT 0000100 61*3184Swnj #define VPSC_CMNDS 0000076 62*3184Swnj #define VPSC_OPEN 0000001 6344Sbill 64*3184Swnj struct uba_device *vpdinfo[NVP]; 6544Sbill 66*3184Swnj #define VPUNIT(dev) (minor(dev)) 67*3184Swnj 68*3184Swnj struct buf rvpbuf[NVP]; 69*3184Swnj 70*3184Swnj int vpprobe(), vpattach(); 71*3184Swnj struct uba_device *vpdinfo[NVP]; 72*3184Swnj u_short vpstd[] = { 0777500, 0 }; 73*3184Swnj struct uba_driver vpdriver = 74*3184Swnj { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 75*3184Swnj 76*3184Swnj vpprobe(reg) 77*3184Swnj caddr_t reg; 7844Sbill { 79*3184Swnj register int br, cvec; /* value-result */ 80*3184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 8144Sbill 82*3184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 83*3184Swnj vpaddr->pbaddr = 0; 84*3184Swnj vpaddr->pbxaddr = 0; 85*3184Swnj vpaddr->plbcr = 1; 86*3184Swnj DELAY(10000); 87*3184Swnj vpaddr->prcsr = 0; 88*3184Swnj } 89*3184Swnj 90*3184Swnj /*ARGSUSED*/ 91*3184Swnj vpattach(ui) 92*3184Swnj struct uba_device *ui; 93*3184Swnj { 94*3184Swnj 95*3184Swnj ui->ui_addr -= 010; 96*3184Swnj ui->ui_physaddr -= 010; 97*3184Swnj } 98*3184Swnj 99*3184Swnj vpopen(dev) 100*3184Swnj dev_t dev; 101*3184Swnj { 102*3184Swnj register struct vp_softc *sc; 103*3184Swnj register struct vpdevice *vpaddr; 104*3184Swnj register struct uba_device *ui; 105*3184Swnj 106*3184Swnj if (VPUNIT(dev) >= NVP || 107*3184Swnj ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 108*3184Swnj (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) { 10944Sbill u.u_error = ENXIO; 11044Sbill return; 11144Sbill } 112*3184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 113*3184Swnj sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 114*3184Swnj sc->sc_count = 0; 115*3184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 116*3184Swnj vptimo(dev); 117*3184Swnj while (sc->sc_state & VPSC_CMNDS) { 118134Sbill (void) spl4(); 119*3184Swnj if (vpwait(dev)) { 120*3184Swnj vpclose(dev); 12144Sbill u.u_error = EIO; 12244Sbill return; 12344Sbill } 124*3184Swnj vpstart(dev); 125134Sbill (void) spl0(); 12644Sbill } 12744Sbill } 12844Sbill 12944Sbill vpstrategy(bp) 13044Sbill register struct buf *bp; 13144Sbill { 13244Sbill register int e; 133*3184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 134*3184Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 135*3184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 13644Sbill 137134Sbill (void) spl4(); 138*3184Swnj while (sc->sc_state & VPSC_BUSY) 139*3184Swnj sleep((caddr_t)sc, VPPRI); 140*3184Swnj sc->sc_state |= VPSC_BUSY; 141*3184Swnj sc->sc_bp = bp; 142*3184Swnj sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 143*3184Swnj if (e = vpwait(bp->b_dev)) 14444Sbill goto brkout; 145*3184Swnj sc->sc_count = bp->b_bcount; 146*3184Swnj vpstart(bp->b_dev); 147*3184Swnj while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 148*3184Swnj sleep((caddr_t)sc, VPPRI); 149*3184Swnj sc->sc_count = 0; 150*3184Swnj if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 151*3184Swnj sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 152134Sbill (void) spl0(); 15344Sbill brkout: 154*3184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 155*3184Swnj sc->sc_state &= ~VPSC_BUSY; 156*3184Swnj sc->sc_bp = 0; 15744Sbill iodone(bp); 15844Sbill if (e) 15944Sbill u.u_error = EIO; 160*3184Swnj wakeup((caddr_t)sc); 16144Sbill } 16244Sbill 16344Sbill int vpblock = 16384; 16444Sbill 16544Sbill unsigned 16644Sbill minvpph(bp) 167*3184Swnj struct buf *bp; 16844Sbill { 16944Sbill 17044Sbill if (bp->b_bcount > vpblock) 17144Sbill bp->b_bcount = vpblock; 17244Sbill } 17344Sbill 17444Sbill /*ARGSUSED*/ 17544Sbill vpwrite(dev) 176*3184Swnj dev_t dev; 17744Sbill { 17844Sbill 179*3184Swnj physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph); 18044Sbill } 18144Sbill 182*3184Swnj vpwait(dev) 183*3184Swnj dev_t dev; 18444Sbill { 185*3184Swnj register struct vpdevice *vpaddr = 186*3184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 187*3184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 188*3184Swnj register int e; 18944Sbill 190*3184Swnj for (;;) { 191*3184Swnj e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 192*3184Swnj if (e & (VP_READY|VP_ERROR)) 193*3184Swnj break; 194*3184Swnj sleep((caddr_t)sc, VPPRI); 195*3184Swnj } 196*3184Swnj /* I wish i could tell whether an error indicated an npr timeout */ 197*3184Swnj return (e & VP_ERROR); 19844Sbill } 19944Sbill 200*3184Swnj vpstart(dev) 201*3184Swnj dev_t; 20244Sbill { 203*3184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 204*3184Swnj register struct vpdevice *vpaddr = 205*3184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 206*3184Swnj short bit; 20744Sbill 208*3184Swnj if (sc->sc_count) { 209*3184Swnj vpaddr->pbaddr = sc->sc_ubinfo; 210*3184Swnj vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 211*3184Swnj if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 212*3184Swnj vpaddr->prbcr = sc->sc_count; 21344Sbill else 214*3184Swnj vpaddr->plbcr = sc->sc_count; 21544Sbill return; 21644Sbill } 21744Sbill for (bit = 1; bit != 0; bit <<= 1) 218*3184Swnj if (sc->sc_state&bit&VPSC_CMNDS) { 219*3184Swnj vpaddr->plcsr |= bit; 220*3184Swnj sc->sc_state &= ~bit; 22144Sbill return; 22244Sbill } 22344Sbill } 22444Sbill 22544Sbill /*ARGSUSED*/ 22644Sbill vpioctl(dev, cmd, addr, flag) 227*3184Swnj dev_t dev; 228*3184Swnj int cmd; 22944Sbill register caddr_t addr; 230*3184Swnj int flag; 23144Sbill { 23244Sbill register int m; 233*3184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 234*3184Swnj register struct vpdevice *vpaddr = 235*3184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 23644Sbill 23744Sbill switch (cmd) { 23844Sbill 239*3184Swnj case VGETSTATE: 240*3184Swnj (void) suword(addr, sc->sc_state); 24144Sbill return; 24244Sbill 243*3184Swnj case VSETSTATE: 24444Sbill m = fuword(addr); 24544Sbill if (m == -1) { 24644Sbill u.u_error = EFAULT; 24744Sbill return; 24844Sbill } 249*3184Swnj sc->sc_state = 250*3184Swnj (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 25144Sbill break; 25244Sbill 25344Sbill default: 25444Sbill u.u_error = ENOTTY; 25544Sbill return; 25644Sbill } 257134Sbill (void) spl4(); 258*3184Swnj (void) vpwait(dev); 259*3184Swnj if (sc->sc_state&VPSC_SPP) 260*3184Swnj vpaddr->plcsr |= VP_SPP; 26144Sbill else 262*3184Swnj vpaddr->plcsr &= ~VP_SPP; 263*3184Swnj sc->sc_count = 0; 264*3184Swnj while (sc->sc_state & VPSC_CMNDS) { 265*3184Swnj (void) vpwait(dev); 266*3184Swnj vpstart(dev); 26744Sbill } 268134Sbill (void) spl0(); 26944Sbill } 27044Sbill 271*3184Swnj vptimo(dev) 272*3184Swnj dev_t dev; 27344Sbill { 274*3184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 27544Sbill 276*3184Swnj if (sc->sc_state&VPSC_OPEN) 277*3184Swnj timeout(vptimo, (caddr_t)dev, hz/10); 278*3184Swnj vpintr(dev); 27944Sbill } 28044Sbill 28144Sbill /*ARGSUSED*/ 28244Sbill vpintr(dev) 283*3184Swnj dev_t dev; 28444Sbill { 285*3184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 28644Sbill 287*3184Swnj wakeup((caddr_t)sc); 28844Sbill } 28944Sbill 290*3184Swnj vpclose(dev) 291*3184Swnj dev_t dev; 29244Sbill { 293*3184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 294*3184Swnj register struct vpdevice *vpaddr = 295*3184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 29644Sbill 297*3184Swnj sc->sc_state = 0; 298*3184Swnj sc->sc_count = 0; 299*3184Swnj vpaddr->plcsr = 0; 30044Sbill } 301288Sbill 302*3184Swnj vpreset(uban) 303*3184Swnj int uban; 304288Sbill { 305*3184Swnj register int vp11; 306*3184Swnj register struct uba_device *ui; 307*3184Swnj register struct vp_softc *sc = vp_softc; 308*3184Swnj register struct vpdevice *vpaddr; 309288Sbill 310*3184Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 311*3184Swnj if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 312*3184Swnj ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 313*3184Swnj continue; 314*3184Swnj printf(" vp%d", vp11); 315*3184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 316*3184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 317*3184Swnj if ((sc->sc_state & VPSC_BUSY) == 0) 318*3184Swnj continue; 319*3184Swnj if (sc->sc_ubinfo) { 320*3184Swnj printf("<%d>", (sc->sc_ubinfo>>28)&0xf); 321*3184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 322*3184Swnj } 323*3184Swnj sc->sc_count = sc->sc_bp->b_bcount; 324*3184Swnj vpstart(sc->sc_bp->b_dev); 325288Sbill } 326288Sbill } 3271565Sbill #endif 328