123362Smckusick /* 2*29260Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323362Smckusick * All rights reserved. The Berkeley software License Agreement 423362Smckusick * specifies the terms and conditions for redistribution. 523362Smckusick * 6*29260Smckusick * @(#)vp.c 7.1 (Berkeley) 06/05/86 723362Smckusick */ 844Sbill 91939Swnj #include "vp.h" 101565Sbill #if NVP > 0 111565Sbill /* 121565Sbill * Versatec matrix printer/plotter 131565Sbill * dma interface driver 143439Swnj * 153439Swnj * SETUP NOTES: 163439Swnj * Set up both print and plot interrupts to go through the same vector 1715074Skarels * (or kludge probe to reset second vector to first; 1815074Skarels * default 174/200 is already handled). 193439Swnj * Give the address of the plcsr register in the config specification 201565Sbill */ 219785Ssam #include "../machine/pte.h" 229785Ssam 2317086Sbloom #include "param.h" 2417086Sbloom #include "dir.h" 2517086Sbloom #include "user.h" 2617086Sbloom #include "buf.h" 2717086Sbloom #include "systm.h" 2817086Sbloom #include "map.h" 2917086Sbloom #include "ioctl.h" 3017086Sbloom #include "vcmd.h" 3117086Sbloom #include "uio.h" 3217086Sbloom #include "kernel.h" 3344Sbill 3417086Sbloom #include "ubavar.h" 3517086Sbloom #include "ubareg.h" 368484Sroot 3744Sbill unsigned minvpph(); 3844Sbill 3915074Skarels #define VPPRI (PZERO-1) 4015074Skarels 4115074Skarels struct vpdevice { 4215074Skarels short plbcr; 4315074Skarels short pbxaddr; 4415074Skarels short prbcr; 4515074Skarels u_short pbaddr; 4615074Skarels short plcsr; 4715074Skarels short plbuf; 4815074Skarels short prcsr; 4915074Skarels u_short prbuf; 5015074Skarels }; 5115074Skarels 5215074Skarels #define VP_ERROR 0100000 5315074Skarels #define VP_DTCINTR 0040000 5415074Skarels #define VP_DMAACT 0020000 5515074Skarels #define VP_READY 0000200 5615074Skarels #define VP_IENABLE 0000100 5715074Skarels #define VP_TERMCOM 0000040 5815074Skarels #define VP_FFCOM 0000020 5915074Skarels #define VP_EOTCOM 0000010 6015074Skarels #define VP_CLRCOM 0000004 6115074Skarels #define VP_RESET 0000002 6215074Skarels #define VP_SPP 0000001 6315074Skarels 643184Swnj struct vp_softc { 653184Swnj int sc_state; 663184Swnj int sc_count; 6715074Skarels int sc_bufp; 6815074Skarels struct buf *sc_bp; 6915074Skarels int sc_ubinfo; 703184Swnj } vp_softc[NVP]; 7144Sbill 723184Swnj /* sc_state bits */ 7315074Skarels #define VPSC_BUSY 0001000 743184Swnj #define VPSC_MODE 0000700 7515074Skarels #define VPSC_SPP 0000400 7615074Skarels #define VPSC_PLOT 0000200 7715074Skarels #define VPSC_PRINT 0000100 783184Swnj #define VPSC_CMNDS 0000076 7915074Skarels #define VPSC_OPEN 0000001 8044Sbill 813184Swnj struct uba_device *vpdinfo[NVP]; 8244Sbill 833184Swnj #define VPUNIT(dev) (minor(dev)) 843184Swnj 853184Swnj struct buf rvpbuf[NVP]; 863184Swnj 8715074Skarels int vpprobe(), vpattach(); 883184Swnj struct uba_device *vpdinfo[NVP]; 893184Swnj u_short vpstd[] = { 0777500, 0 }; 903184Swnj struct uba_driver vpdriver = 9115074Skarels { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 923184Swnj 933184Swnj vpprobe(reg) 943184Swnj caddr_t reg; 9544Sbill { 963184Swnj register int br, cvec; /* value-result */ 973184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 9844Sbill 994942Swnj #ifdef lint 1004942Swnj br = 0; cvec = br; br = cvec; 1014942Swnj vpintr(0); 1024942Swnj #endif 1033184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 1043184Swnj vpaddr->pbaddr = 0; 1053184Swnj vpaddr->pbxaddr = 0; 1063439Swnj vpaddr->prbcr = 1; 1073184Swnj DELAY(10000); 1083184Swnj vpaddr->prcsr = 0; 10915074Skarels /* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */ 1103439Swnj if (cvec == 0200) { 1113439Swnj printf("vp reset vec from 200 to 174\n"); 1123439Swnj cvec = 0174; 1133439Swnj } 1147408Skre return (sizeof (struct vpdevice)); 1153184Swnj } 1163184Swnj 1173184Swnj /*ARGSUSED*/ 1183184Swnj vpattach(ui) 1193184Swnj struct uba_device *ui; 1203184Swnj { 1213184Swnj 1223184Swnj ui->ui_addr -= 010; 1233184Swnj ui->ui_physaddr -= 010; 1243184Swnj } 1253184Swnj 1263184Swnj vpopen(dev) 1273184Swnj dev_t dev; 1283184Swnj { 1293184Swnj register struct vp_softc *sc; 1303184Swnj register struct vpdevice *vpaddr; 1313184Swnj register struct uba_device *ui; 1323184Swnj 13315074Skarels if (VPUNIT(dev) >= NVP || 13415074Skarels ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 13515074Skarels (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) 1368578Sroot return (ENXIO); 1373184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 13815074Skarels sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 13915074Skarels sc->sc_count = 0; 1403184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 14115074Skarels vptimo(dev); 14215074Skarels while (sc->sc_state & VPSC_CMNDS) { 14315074Skarels (void) spl4(); 14415074Skarels if (vpwait(dev)) { 14515074Skarels vpclose(dev); 14615074Skarels return (EIO); 14715074Skarels } 14815074Skarels vpstart(dev); 14915074Skarels (void) spl0(); 15015074Skarels } 15115074Skarels return (0); 15244Sbill } 15344Sbill 15444Sbill vpstrategy(bp) 15544Sbill register struct buf *bp; 15644Sbill { 15715074Skarels register int e; 1583184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 1593184Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 1603184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 16144Sbill 16215074Skarels (void) spl4(); 16315074Skarels while (sc->sc_state & VPSC_BUSY) 16415074Skarels sleep((caddr_t)sc, VPPRI); 16515074Skarels sc->sc_state |= VPSC_BUSY; 16615074Skarels sc->sc_bp = bp; 16715074Skarels sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 16815074Skarels if (e = vpwait(bp->b_dev)) 16915074Skarels goto brkout; 17015074Skarels sc->sc_count = bp->b_bcount; 17115074Skarels vpstart(bp->b_dev); 17215074Skarels while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 17315074Skarels sleep((caddr_t)sc, VPPRI); 17415074Skarels sc->sc_count = 0; 17515074Skarels if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 17615074Skarels sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 17715074Skarels (void) spl0(); 17815074Skarels brkout: 17915074Skarels ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 18015074Skarels sc->sc_state &= ~VPSC_BUSY; 18115074Skarels sc->sc_bp = 0; 18215074Skarels if (e) 1838494Sroot bp->b_flags |= B_ERROR; 18415074Skarels iodone(bp); 18515074Skarels wakeup((caddr_t)sc); 18644Sbill } 18744Sbill 18844Sbill int vpblock = 16384; 18944Sbill 19044Sbill unsigned 19144Sbill minvpph(bp) 1923184Swnj struct buf *bp; 19344Sbill { 19444Sbill 19544Sbill if (bp->b_bcount > vpblock) 19644Sbill bp->b_bcount = vpblock; 19744Sbill } 19844Sbill 19944Sbill /*ARGSUSED*/ 2008168Sroot vpwrite(dev, uio) 2013184Swnj dev_t dev; 2028168Sroot struct uio *uio; 20344Sbill { 20444Sbill 2057848Sroot if (VPUNIT(dev) >= NVP) 2068168Sroot return (ENXIO); 2078168Sroot return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, 2088168Sroot minvpph, uio)); 20944Sbill } 21044Sbill 21115074Skarels vpwait(dev) 21215074Skarels dev_t dev; 21344Sbill { 21415074Skarels register struct vpdevice *vpaddr = 21515074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 21615074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 21715074Skarels register int e; 21844Sbill 21915074Skarels for (;;) { 22015074Skarels e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 22115074Skarels if (e & (VP_READY|VP_ERROR)) 22215074Skarels break; 22315074Skarels sleep((caddr_t)sc, VPPRI); 22415074Skarels } 22515074Skarels /* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */ 22615074Skarels return (e & VP_ERROR); 22744Sbill } 22844Sbill 22915074Skarels vpstart(dev) 23015074Skarels dev_t; 23144Sbill { 23215074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 23315074Skarels register struct vpdevice *vpaddr = 23415074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 23515074Skarels short bit; 23644Sbill 2373184Swnj if (sc->sc_count) { 23815074Skarels vpaddr->pbaddr = sc->sc_ubinfo; 23915074Skarels vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 24015074Skarels if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2413184Swnj vpaddr->prbcr = sc->sc_count; 24244Sbill else 2433184Swnj vpaddr->plbcr = sc->sc_count; 24415074Skarels return; 24544Sbill } 24615074Skarels for (bit = 1; bit != 0; bit <<= 1) 24715074Skarels if (sc->sc_state&bit&VPSC_CMNDS) { 24815074Skarels vpaddr->plcsr |= bit; 24915074Skarels sc->sc_state &= ~bit; 25015074Skarels return; 25115074Skarels } 25244Sbill } 25344Sbill 25444Sbill /*ARGSUSED*/ 25511815Ssam vpioctl(dev, cmd, data, flag) 25615074Skarels dev_t dev; 25715074Skarels int cmd; 25811815Ssam register caddr_t data; 25915074Skarels int flag; 26044Sbill { 2613184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 26215074Skarels register struct vpdevice *vpaddr = 26315074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 26444Sbill 26544Sbill switch (cmd) { 26644Sbill 2673184Swnj case VGETSTATE: 26811815Ssam *(int *)data = sc->sc_state; 26918611Skarels return (0); 27044Sbill 2713184Swnj case VSETSTATE: 27215074Skarels sc->sc_state = 27315074Skarels (sc->sc_state & ~VPSC_MODE) | 27415074Skarels ((*(int *)data) & (VPSC_MODE|VPSC_CMNDS)); 27515074Skarels break; 27644Sbill 27744Sbill default: 2788578Sroot return (ENOTTY); 27944Sbill } 28015074Skarels (void) spl4(); 28115074Skarels (void) vpwait(dev); 28215074Skarels if (sc->sc_state&VPSC_SPP) 28315074Skarels vpaddr->plcsr |= VP_SPP; 28415074Skarels else 28515074Skarels vpaddr->plcsr &= ~VP_SPP; 28615074Skarels sc->sc_count = 0; 28715074Skarels while (sc->sc_state & VPSC_CMNDS) { 28815074Skarels (void) vpwait(dev); 28915074Skarels vpstart(dev); 29044Sbill } 29115074Skarels (void) spl0(); 2928578Sroot return (0); 29344Sbill } 29444Sbill 2953184Swnj vptimo(dev) 2963184Swnj dev_t dev; 29744Sbill { 2983184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 29944Sbill 30015074Skarels if (sc->sc_state&VPSC_OPEN) 30115074Skarels timeout(vptimo, (caddr_t)dev, hz/10); 3023184Swnj vpintr(dev); 30344Sbill } 30444Sbill 30544Sbill /*ARGSUSED*/ 30644Sbill vpintr(dev) 3073184Swnj dev_t dev; 30844Sbill { 30915074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 31044Sbill 31115074Skarels wakeup((caddr_t)sc); 31244Sbill } 31344Sbill 3143184Swnj vpclose(dev) 3153184Swnj dev_t dev; 31644Sbill { 3173184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3183184Swnj register struct vpdevice *vpaddr = 3193184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 32044Sbill 3213184Swnj sc->sc_state = 0; 32215074Skarels sc->sc_count = 0; 3233184Swnj vpaddr->plcsr = 0; 32444Sbill } 325288Sbill 3263184Swnj vpreset(uban) 3273184Swnj int uban; 328288Sbill { 3293184Swnj register int vp11; 33015074Skarels register struct uba_device *ui; 33115074Skarels register struct vp_softc *sc = vp_softc; 3323184Swnj register struct vpdevice *vpaddr; 333288Sbill 3343184Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 33515074Skarels if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 33615074Skarels ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 3373184Swnj continue; 3383184Swnj printf(" vp%d", vp11); 33915074Skarels vpaddr = (struct vpdevice *)ui->ui_addr; 3403184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 34115074Skarels if ((sc->sc_state & VPSC_BUSY) == 0) 34215074Skarels continue; 34315074Skarels sc->sc_ubinfo = 0; 34415074Skarels sc->sc_count = sc->sc_bp->b_bcount; 34515074Skarels vpstart(sc->sc_bp->b_dev); 346288Sbill } 347288Sbill } 3486432Ssam 3496432Ssam vpselect() 3506432Ssam { 3516432Ssam return (1); 3526432Ssam } 3531565Sbill #endif 354