1*7737Sroot /* vp.c 4.16 82/08/13 */ 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" 23*7737Sroot #include "../h/uio.h" 2444Sbill 2544Sbill unsigned minvpph(); 2644Sbill 2744Sbill #define VPPRI (PZERO-1) 2844Sbill 293184Swnj struct vpdevice { 3044Sbill short plbcr; 311903Swnj short pbxaddr; 3244Sbill short prbcr; 333184Swnj u_short pbaddr; 3444Sbill short plcsr; 3544Sbill short plbuf; 3644Sbill short prcsr; 373184Swnj u_short prbuf; 3844Sbill }; 3944Sbill 403184Swnj #define VP_ERROR 0100000 413184Swnj #define VP_DTCINTR 0040000 423184Swnj #define VP_DMAACT 0020000 433184Swnj #define VP_READY 0000200 443184Swnj #define VP_IENABLE 0000100 453184Swnj #define VP_TERMCOM 0000040 463184Swnj #define VP_FFCOM 0000020 473184Swnj #define VP_EOTCOM 0000010 483184Swnj #define VP_CLRCOM 0000004 493184Swnj #define VP_RESET 0000002 503184Swnj #define VP_SPP 0000001 5144Sbill 523184Swnj struct vp_softc { 533184Swnj int sc_state; 543184Swnj int sc_count; 553184Swnj int sc_bufp; 563184Swnj struct buf *sc_bp; 573184Swnj int sc_ubinfo; 583184Swnj } vp_softc[NVP]; 5944Sbill 603184Swnj /* sc_state bits */ 613184Swnj #define VPSC_BUSY 0001000 623184Swnj #define VPSC_MODE 0000700 633184Swnj #define VPSC_SPP 0000400 643184Swnj #define VPSC_PLOT 0000200 653184Swnj #define VPSC_PRINT 0000100 663184Swnj #define VPSC_CMNDS 0000076 673184Swnj #define VPSC_OPEN 0000001 6844Sbill 693184Swnj struct uba_device *vpdinfo[NVP]; 7044Sbill 713184Swnj #define VPUNIT(dev) (minor(dev)) 723184Swnj 733184Swnj struct buf rvpbuf[NVP]; 743184Swnj 753184Swnj int vpprobe(), vpattach(); 763184Swnj struct uba_device *vpdinfo[NVP]; 773184Swnj u_short vpstd[] = { 0777500, 0 }; 783184Swnj struct uba_driver vpdriver = 793184Swnj { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 803184Swnj 813184Swnj vpprobe(reg) 823184Swnj caddr_t reg; 8344Sbill { 843184Swnj register int br, cvec; /* value-result */ 853184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 8644Sbill 874942Swnj #ifdef lint 884942Swnj br = 0; cvec = br; br = cvec; 894942Swnj vpintr(0); 904942Swnj #endif 913184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 923184Swnj vpaddr->pbaddr = 0; 933184Swnj vpaddr->pbxaddr = 0; 943439Swnj vpaddr->prbcr = 1; 953184Swnj DELAY(10000); 963184Swnj vpaddr->prcsr = 0; 976859Ssam #if ERNIE || CAD || UCBVAX 983439Swnj /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ 993439Swnj if (cvec == 0200) { 1003439Swnj printf("vp reset vec from 200 to 174\n"); 1013439Swnj cvec = 0174; 1023439Swnj } 1033439Swnj #endif 1047408Skre return (sizeof (struct vpdevice)); 1053184Swnj } 1063184Swnj 1073184Swnj /*ARGSUSED*/ 1083184Swnj vpattach(ui) 1093184Swnj struct uba_device *ui; 1103184Swnj { 1113184Swnj 1123184Swnj ui->ui_addr -= 010; 1133184Swnj ui->ui_physaddr -= 010; 1143184Swnj } 1153184Swnj 1163184Swnj vpopen(dev) 1173184Swnj dev_t dev; 1183184Swnj { 1193184Swnj register struct vp_softc *sc; 1203184Swnj register struct vpdevice *vpaddr; 1213184Swnj register struct uba_device *ui; 1223184Swnj 1233184Swnj if (VPUNIT(dev) >= NVP || 1243184Swnj ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 1253184Swnj (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) { 12644Sbill u.u_error = ENXIO; 12744Sbill return; 12844Sbill } 1293184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 1303184Swnj sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 1313184Swnj sc->sc_count = 0; 1323184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 1333184Swnj vptimo(dev); 1343184Swnj while (sc->sc_state & VPSC_CMNDS) { 135134Sbill (void) spl4(); 1363184Swnj if (vpwait(dev)) { 1373184Swnj vpclose(dev); 13844Sbill u.u_error = EIO; 13944Sbill return; 14044Sbill } 1413184Swnj vpstart(dev); 142134Sbill (void) spl0(); 14344Sbill } 14444Sbill } 14544Sbill 14644Sbill vpstrategy(bp) 14744Sbill register struct buf *bp; 14844Sbill { 14944Sbill register int e; 1503184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 1513184Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 1523184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 15344Sbill 154134Sbill (void) spl4(); 1553184Swnj while (sc->sc_state & VPSC_BUSY) 1563184Swnj sleep((caddr_t)sc, VPPRI); 1573184Swnj sc->sc_state |= VPSC_BUSY; 1583184Swnj sc->sc_bp = bp; 1593184Swnj sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 1603184Swnj if (e = vpwait(bp->b_dev)) 16144Sbill goto brkout; 1623184Swnj sc->sc_count = bp->b_bcount; 1633184Swnj vpstart(bp->b_dev); 1643184Swnj while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 1653184Swnj sleep((caddr_t)sc, VPPRI); 1663184Swnj sc->sc_count = 0; 1673184Swnj if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 1683184Swnj sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 169134Sbill (void) spl0(); 17044Sbill brkout: 1713184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 1723184Swnj sc->sc_state &= ~VPSC_BUSY; 1733184Swnj sc->sc_bp = 0; 17444Sbill iodone(bp); 17544Sbill if (e) 17644Sbill u.u_error = EIO; 1773184Swnj wakeup((caddr_t)sc); 17844Sbill } 17944Sbill 18044Sbill int vpblock = 16384; 18144Sbill 18244Sbill unsigned 18344Sbill minvpph(bp) 1843184Swnj struct buf *bp; 18544Sbill { 18644Sbill 18744Sbill if (bp->b_bcount > vpblock) 18844Sbill bp->b_bcount = vpblock; 18944Sbill } 19044Sbill 19144Sbill /*ARGSUSED*/ 19244Sbill vpwrite(dev) 1933184Swnj dev_t dev; 19444Sbill { 19544Sbill 196*7737Sroot physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph, 0); 19744Sbill } 19844Sbill 1993184Swnj vpwait(dev) 2003184Swnj dev_t dev; 20144Sbill { 2023184Swnj register struct vpdevice *vpaddr = 2033184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2043184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2053184Swnj register int e; 20644Sbill 2073184Swnj for (;;) { 2083184Swnj e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 2093184Swnj if (e & (VP_READY|VP_ERROR)) 2103184Swnj break; 2113184Swnj sleep((caddr_t)sc, VPPRI); 2123184Swnj } 2133184Swnj /* I wish i could tell whether an error indicated an npr timeout */ 2143184Swnj return (e & VP_ERROR); 21544Sbill } 21644Sbill 2173184Swnj vpstart(dev) 2183184Swnj dev_t; 21944Sbill { 2203184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2213184Swnj register struct vpdevice *vpaddr = 2223184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2233184Swnj short bit; 22444Sbill 2253184Swnj if (sc->sc_count) { 2263184Swnj vpaddr->pbaddr = sc->sc_ubinfo; 2273184Swnj vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 2283184Swnj if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2293184Swnj vpaddr->prbcr = sc->sc_count; 23044Sbill else 2313184Swnj vpaddr->plbcr = sc->sc_count; 23244Sbill return; 23344Sbill } 23444Sbill for (bit = 1; bit != 0; bit <<= 1) 2353184Swnj if (sc->sc_state&bit&VPSC_CMNDS) { 2363184Swnj vpaddr->plcsr |= bit; 2373184Swnj sc->sc_state &= ~bit; 23844Sbill return; 23944Sbill } 24044Sbill } 24144Sbill 24244Sbill /*ARGSUSED*/ 24344Sbill vpioctl(dev, cmd, addr, flag) 2443184Swnj dev_t dev; 2453184Swnj int cmd; 24644Sbill register caddr_t addr; 2473184Swnj int flag; 24844Sbill { 24944Sbill register int m; 2503184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2513184Swnj register struct vpdevice *vpaddr = 2523184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 25344Sbill 25444Sbill switch (cmd) { 25544Sbill 2563184Swnj case VGETSTATE: 2573184Swnj (void) suword(addr, sc->sc_state); 25844Sbill return; 25944Sbill 2603184Swnj case VSETSTATE: 26144Sbill m = fuword(addr); 26244Sbill if (m == -1) { 26344Sbill u.u_error = EFAULT; 26444Sbill return; 26544Sbill } 2663184Swnj sc->sc_state = 2673184Swnj (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 26844Sbill break; 26944Sbill 27044Sbill default: 27144Sbill u.u_error = ENOTTY; 27244Sbill return; 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(); 28644Sbill } 28744Sbill 2883184Swnj vptimo(dev) 2893184Swnj dev_t dev; 29044Sbill { 2913184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 29244Sbill 2933184Swnj if (sc->sc_state&VPSC_OPEN) 2943184Swnj timeout(vptimo, (caddr_t)dev, hz/10); 2953184Swnj vpintr(dev); 29644Sbill } 29744Sbill 29844Sbill /*ARGSUSED*/ 29944Sbill vpintr(dev) 3003184Swnj dev_t dev; 30144Sbill { 3023184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 30344Sbill 3043184Swnj wakeup((caddr_t)sc); 30544Sbill } 30644Sbill 3073184Swnj vpclose(dev) 3083184Swnj dev_t dev; 30944Sbill { 3103184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3113184Swnj register struct vpdevice *vpaddr = 3123184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 31344Sbill 3143184Swnj sc->sc_state = 0; 3153184Swnj sc->sc_count = 0; 3163184Swnj vpaddr->plcsr = 0; 31744Sbill } 318288Sbill 3193184Swnj vpreset(uban) 3203184Swnj int uban; 321288Sbill { 3223184Swnj register int vp11; 3233184Swnj register struct uba_device *ui; 3243184Swnj register struct vp_softc *sc = vp_softc; 3253184Swnj register struct vpdevice *vpaddr; 326288Sbill 3273184Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 3283184Swnj if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 3293184Swnj ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 3303184Swnj continue; 3313184Swnj printf(" vp%d", vp11); 3323184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 3333184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 3343184Swnj if ((sc->sc_state & VPSC_BUSY) == 0) 3353184Swnj continue; 3363184Swnj if (sc->sc_ubinfo) { 3373184Swnj printf("<%d>", (sc->sc_ubinfo>>28)&0xf); 3383184Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 3393184Swnj } 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