1*6859Ssam /* vp.c 4.14 82/05/19 */ 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/ubavar.h" 213184Swnj #include "../h/ubareg.h" 223184Swnj #include "../h/vcmd.h" 2344Sbill 2444Sbill unsigned minvpph(); 2544Sbill 2644Sbill #define VPPRI (PZERO-1) 2744Sbill 283184Swnj struct vpdevice { 2944Sbill short plbcr; 301903Swnj short pbxaddr; 3144Sbill short prbcr; 323184Swnj u_short pbaddr; 3344Sbill short plcsr; 3444Sbill short plbuf; 3544Sbill short prcsr; 363184Swnj u_short prbuf; 3744Sbill }; 3844Sbill 393184Swnj #define VP_ERROR 0100000 403184Swnj #define VP_DTCINTR 0040000 413184Swnj #define VP_DMAACT 0020000 423184Swnj #define VP_READY 0000200 433184Swnj #define VP_IENABLE 0000100 443184Swnj #define VP_TERMCOM 0000040 453184Swnj #define VP_FFCOM 0000020 463184Swnj #define VP_EOTCOM 0000010 473184Swnj #define VP_CLRCOM 0000004 483184Swnj #define VP_RESET 0000002 493184Swnj #define VP_SPP 0000001 5044Sbill 513184Swnj struct vp_softc { 523184Swnj int sc_state; 533184Swnj int sc_count; 543184Swnj int sc_bufp; 553184Swnj struct buf *sc_bp; 563184Swnj int sc_ubinfo; 573184Swnj } vp_softc[NVP]; 5844Sbill 593184Swnj /* sc_state bits */ 603184Swnj #define VPSC_BUSY 0001000 613184Swnj #define VPSC_MODE 0000700 623184Swnj #define VPSC_SPP 0000400 633184Swnj #define VPSC_PLOT 0000200 643184Swnj #define VPSC_PRINT 0000100 653184Swnj #define VPSC_CMNDS 0000076 663184Swnj #define VPSC_OPEN 0000001 6744Sbill 683184Swnj struct uba_device *vpdinfo[NVP]; 6944Sbill 703184Swnj #define VPUNIT(dev) (minor(dev)) 713184Swnj 723184Swnj struct buf rvpbuf[NVP]; 733184Swnj 743184Swnj int vpprobe(), vpattach(); 753184Swnj struct uba_device *vpdinfo[NVP]; 763184Swnj u_short vpstd[] = { 0777500, 0 }; 773184Swnj struct uba_driver vpdriver = 783184Swnj { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 793184Swnj 803184Swnj vpprobe(reg) 813184Swnj caddr_t reg; 8244Sbill { 833184Swnj register int br, cvec; /* value-result */ 843184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 8544Sbill 864942Swnj #ifdef lint 874942Swnj br = 0; cvec = br; br = cvec; 884942Swnj vpintr(0); 894942Swnj #endif 903184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 913184Swnj vpaddr->pbaddr = 0; 923184Swnj vpaddr->pbxaddr = 0; 933439Swnj vpaddr->prbcr = 1; 943184Swnj DELAY(10000); 953184Swnj vpaddr->prcsr = 0; 96*6859Ssam #if ERNIE || CAD || UCBVAX 973439Swnj /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ 983439Swnj if (cvec == 0200) { 993439Swnj printf("vp reset vec from 200 to 174\n"); 1003439Swnj cvec = 0174; 1013439Swnj } 1023439Swnj #endif 1033184Swnj } 1043184Swnj 1053184Swnj /*ARGSUSED*/ 1063184Swnj vpattach(ui) 1073184Swnj struct uba_device *ui; 1083184Swnj { 1093184Swnj 1103184Swnj ui->ui_addr -= 010; 1113184Swnj ui->ui_physaddr -= 010; 1123184Swnj } 1133184Swnj 1143184Swnj vpopen(dev) 1153184Swnj dev_t dev; 1163184Swnj { 1173184Swnj register struct vp_softc *sc; 1183184Swnj register struct vpdevice *vpaddr; 1193184Swnj register struct uba_device *ui; 1203184Swnj 1213184Swnj if (VPUNIT(dev) >= NVP || 1223184Swnj ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 1233184Swnj (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) { 12444Sbill u.u_error = ENXIO; 12544Sbill return; 12644Sbill } 1273184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 1283184Swnj sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 1293184Swnj sc->sc_count = 0; 1303184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 1313184Swnj vptimo(dev); 1323184Swnj while (sc->sc_state & VPSC_CMNDS) { 133134Sbill (void) spl4(); 1343184Swnj if (vpwait(dev)) { 1353184Swnj vpclose(dev); 13644Sbill u.u_error = EIO; 13744Sbill return; 13844Sbill } 1393184Swnj vpstart(dev); 140134Sbill (void) spl0(); 14144Sbill } 14244Sbill } 14344Sbill 14444Sbill vpstrategy(bp) 14544Sbill register struct buf *bp; 14644Sbill { 14744Sbill register int e; 1483184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 1493184Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 1503184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 15144Sbill 152134Sbill (void) spl4(); 1533184Swnj while (sc->sc_state & VPSC_BUSY) 1543184Swnj sleep((caddr_t)sc, VPPRI); 1553184Swnj sc->sc_state |= VPSC_BUSY; 1563184Swnj sc->sc_bp = bp; 1573184Swnj sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 1583184Swnj if (e = vpwait(bp->b_dev)) 15944Sbill goto brkout; 1603184Swnj sc->sc_count = bp->b_bcount; 1613184Swnj vpstart(bp->b_dev); 1623184Swnj while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 1633184Swnj sleep((caddr_t)sc, VPPRI); 1643184Swnj sc->sc_count = 0; 1653184Swnj if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 1663184Swnj sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 167134Sbill (void) spl0(); 16844Sbill brkout: 1693184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 1703184Swnj sc->sc_state &= ~VPSC_BUSY; 1713184Swnj sc->sc_bp = 0; 17244Sbill iodone(bp); 17344Sbill if (e) 17444Sbill u.u_error = EIO; 1753184Swnj wakeup((caddr_t)sc); 17644Sbill } 17744Sbill 17844Sbill int vpblock = 16384; 17944Sbill 18044Sbill unsigned 18144Sbill minvpph(bp) 1823184Swnj struct buf *bp; 18344Sbill { 18444Sbill 18544Sbill if (bp->b_bcount > vpblock) 18644Sbill bp->b_bcount = vpblock; 18744Sbill } 18844Sbill 18944Sbill /*ARGSUSED*/ 19044Sbill vpwrite(dev) 1913184Swnj dev_t dev; 19244Sbill { 19344Sbill 1943184Swnj physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph); 19544Sbill } 19644Sbill 1973184Swnj vpwait(dev) 1983184Swnj dev_t dev; 19944Sbill { 2003184Swnj register struct vpdevice *vpaddr = 2013184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2023184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2033184Swnj register int e; 20444Sbill 2053184Swnj for (;;) { 2063184Swnj e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 2073184Swnj if (e & (VP_READY|VP_ERROR)) 2083184Swnj break; 2093184Swnj sleep((caddr_t)sc, VPPRI); 2103184Swnj } 2113184Swnj /* I wish i could tell whether an error indicated an npr timeout */ 2123184Swnj return (e & VP_ERROR); 21344Sbill } 21444Sbill 2153184Swnj vpstart(dev) 2163184Swnj dev_t; 21744Sbill { 2183184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2193184Swnj register struct vpdevice *vpaddr = 2203184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2213184Swnj short bit; 22244Sbill 2233184Swnj if (sc->sc_count) { 2243184Swnj vpaddr->pbaddr = sc->sc_ubinfo; 2253184Swnj vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 2263184Swnj if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2273184Swnj vpaddr->prbcr = sc->sc_count; 22844Sbill else 2293184Swnj vpaddr->plbcr = sc->sc_count; 23044Sbill return; 23144Sbill } 23244Sbill for (bit = 1; bit != 0; bit <<= 1) 2333184Swnj if (sc->sc_state&bit&VPSC_CMNDS) { 2343184Swnj vpaddr->plcsr |= bit; 2353184Swnj sc->sc_state &= ~bit; 23644Sbill return; 23744Sbill } 23844Sbill } 23944Sbill 24044Sbill /*ARGSUSED*/ 24144Sbill vpioctl(dev, cmd, addr, flag) 2423184Swnj dev_t dev; 2433184Swnj int cmd; 24444Sbill register caddr_t addr; 2453184Swnj int flag; 24644Sbill { 24744Sbill register int m; 2483184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2493184Swnj register struct vpdevice *vpaddr = 2503184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 25144Sbill 25244Sbill switch (cmd) { 25344Sbill 2543184Swnj case VGETSTATE: 2553184Swnj (void) suword(addr, sc->sc_state); 25644Sbill return; 25744Sbill 2583184Swnj case VSETSTATE: 25944Sbill m = fuword(addr); 26044Sbill if (m == -1) { 26144Sbill u.u_error = EFAULT; 26244Sbill return; 26344Sbill } 2643184Swnj sc->sc_state = 2653184Swnj (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 26644Sbill break; 26744Sbill 26844Sbill default: 26944Sbill u.u_error = ENOTTY; 27044Sbill return; 27144Sbill } 272134Sbill (void) spl4(); 2733184Swnj (void) vpwait(dev); 2743184Swnj if (sc->sc_state&VPSC_SPP) 2753184Swnj vpaddr->plcsr |= VP_SPP; 27644Sbill else 2773184Swnj vpaddr->plcsr &= ~VP_SPP; 2783184Swnj sc->sc_count = 0; 2793184Swnj while (sc->sc_state & VPSC_CMNDS) { 2803184Swnj (void) vpwait(dev); 2813184Swnj vpstart(dev); 28244Sbill } 283134Sbill (void) spl0(); 28444Sbill } 28544Sbill 2863184Swnj vptimo(dev) 2873184Swnj dev_t dev; 28844Sbill { 2893184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 29044Sbill 2913184Swnj if (sc->sc_state&VPSC_OPEN) 2923184Swnj timeout(vptimo, (caddr_t)dev, hz/10); 2933184Swnj vpintr(dev); 29444Sbill } 29544Sbill 29644Sbill /*ARGSUSED*/ 29744Sbill vpintr(dev) 2983184Swnj dev_t dev; 29944Sbill { 3003184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 30144Sbill 3023184Swnj wakeup((caddr_t)sc); 30344Sbill } 30444Sbill 3053184Swnj vpclose(dev) 3063184Swnj dev_t dev; 30744Sbill { 3083184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3093184Swnj register struct vpdevice *vpaddr = 3103184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 31144Sbill 3123184Swnj sc->sc_state = 0; 3133184Swnj sc->sc_count = 0; 3143184Swnj vpaddr->plcsr = 0; 31544Sbill } 316288Sbill 3173184Swnj vpreset(uban) 3183184Swnj int uban; 319288Sbill { 3203184Swnj register int vp11; 3213184Swnj register struct uba_device *ui; 3223184Swnj register struct vp_softc *sc = vp_softc; 3233184Swnj register struct vpdevice *vpaddr; 324288Sbill 3253184Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 3263184Swnj if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 3273184Swnj ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 3283184Swnj continue; 3293184Swnj printf(" vp%d", vp11); 3303184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 3313184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 3323184Swnj if ((sc->sc_state & VPSC_BUSY) == 0) 3333184Swnj continue; 3343184Swnj if (sc->sc_ubinfo) { 3353184Swnj printf("<%d>", (sc->sc_ubinfo>>28)&0xf); 3363184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 3373184Swnj } 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