123362Smckusick /* 229260Smckusick * 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*40728Skarels * @(#)vp.c 7.4 (Berkeley) 04/03/90 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 */ 2137511Smckusick #include "machine/pte.h" 229785Ssam 2317086Sbloom #include "param.h" 2417086Sbloom #include "user.h" 2517086Sbloom #include "buf.h" 2617086Sbloom #include "systm.h" 2717086Sbloom #include "map.h" 2817086Sbloom #include "ioctl.h" 2917086Sbloom #include "vcmd.h" 3017086Sbloom #include "uio.h" 3117086Sbloom #include "kernel.h" 3244Sbill 3317086Sbloom #include "ubavar.h" 3417086Sbloom #include "ubareg.h" 358484Sroot 3644Sbill unsigned minvpph(); 3744Sbill 3815074Skarels #define VPPRI (PZERO-1) 3915074Skarels 4015074Skarels struct vpdevice { 4115074Skarels short plbcr; 4215074Skarels short pbxaddr; 4315074Skarels short prbcr; 4415074Skarels u_short pbaddr; 4515074Skarels short plcsr; 4615074Skarels short plbuf; 4715074Skarels short prcsr; 4815074Skarels u_short prbuf; 4915074Skarels }; 5015074Skarels 5115074Skarels #define VP_ERROR 0100000 5215074Skarels #define VP_DTCINTR 0040000 5315074Skarels #define VP_DMAACT 0020000 5415074Skarels #define VP_READY 0000200 5515074Skarels #define VP_IENABLE 0000100 5615074Skarels #define VP_TERMCOM 0000040 5715074Skarels #define VP_FFCOM 0000020 5815074Skarels #define VP_EOTCOM 0000010 5915074Skarels #define VP_CLRCOM 0000004 6015074Skarels #define VP_RESET 0000002 6115074Skarels #define VP_SPP 0000001 6215074Skarels 633184Swnj struct vp_softc { 643184Swnj int sc_state; 653184Swnj int sc_count; 6615074Skarels int sc_bufp; 6715074Skarels struct buf *sc_bp; 6815074Skarels int sc_ubinfo; 693184Swnj } vp_softc[NVP]; 7044Sbill 713184Swnj /* sc_state bits */ 7215074Skarels #define VPSC_BUSY 0001000 733184Swnj #define VPSC_MODE 0000700 7415074Skarels #define VPSC_SPP 0000400 7515074Skarels #define VPSC_PLOT 0000200 7615074Skarels #define VPSC_PRINT 0000100 773184Swnj #define VPSC_CMNDS 0000076 7815074Skarels #define VPSC_OPEN 0000001 7944Sbill 803184Swnj struct uba_device *vpdinfo[NVP]; 8144Sbill 823184Swnj #define VPUNIT(dev) (minor(dev)) 833184Swnj 843184Swnj struct buf rvpbuf[NVP]; 853184Swnj 8615074Skarels int vpprobe(), vpattach(); 873184Swnj struct uba_device *vpdinfo[NVP]; 883184Swnj u_short vpstd[] = { 0777500, 0 }; 893184Swnj struct uba_driver vpdriver = 9015074Skarels { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 913184Swnj 923184Swnj vpprobe(reg) 933184Swnj caddr_t reg; 9444Sbill { 953184Swnj register int br, cvec; /* value-result */ 963184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 9744Sbill 984942Swnj #ifdef lint 994942Swnj br = 0; cvec = br; br = cvec; 1004942Swnj vpintr(0); 1014942Swnj #endif 1023184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 1033184Swnj vpaddr->pbaddr = 0; 1043184Swnj vpaddr->pbxaddr = 0; 1053439Swnj vpaddr->prbcr = 1; 1063184Swnj DELAY(10000); 1073184Swnj vpaddr->prcsr = 0; 10815074Skarels /* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */ 1093439Swnj if (cvec == 0200) { 1103439Swnj printf("vp reset vec from 200 to 174\n"); 1113439Swnj cvec = 0174; 1123439Swnj } 1137408Skre return (sizeof (struct vpdevice)); 1143184Swnj } 1153184Swnj 1163184Swnj /*ARGSUSED*/ 1173184Swnj vpattach(ui) 1183184Swnj struct uba_device *ui; 1193184Swnj { 1203184Swnj 1213184Swnj ui->ui_addr -= 010; 1223184Swnj ui->ui_physaddr -= 010; 1233184Swnj } 1243184Swnj 1253184Swnj vpopen(dev) 1263184Swnj dev_t dev; 1273184Swnj { 1283184Swnj register struct vp_softc *sc; 1293184Swnj register struct vpdevice *vpaddr; 1303184Swnj register struct uba_device *ui; 1313184Swnj 13215074Skarels if (VPUNIT(dev) >= NVP || 13315074Skarels ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 13415074Skarels (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) 1358578Sroot return (ENXIO); 1363184Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 13715074Skarels sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 13815074Skarels sc->sc_count = 0; 1393184Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 14015074Skarels vptimo(dev); 14115074Skarels while (sc->sc_state & VPSC_CMNDS) { 14215074Skarels (void) spl4(); 14315074Skarels if (vpwait(dev)) { 144*40728Skarels (void) vpclose(dev); 14515074Skarels return (EIO); 14615074Skarels } 14715074Skarels vpstart(dev); 14815074Skarels (void) spl0(); 14915074Skarels } 15015074Skarels return (0); 15144Sbill } 15244Sbill 15344Sbill vpstrategy(bp) 15444Sbill register struct buf *bp; 15544Sbill { 15615074Skarels register int e; 1573184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 1583184Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 1593184Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 16044Sbill 16115074Skarels (void) spl4(); 16215074Skarels while (sc->sc_state & VPSC_BUSY) 16315074Skarels sleep((caddr_t)sc, VPPRI); 16415074Skarels sc->sc_state |= VPSC_BUSY; 16515074Skarels sc->sc_bp = bp; 16615074Skarels sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 16715074Skarels if (e = vpwait(bp->b_dev)) 16815074Skarels goto brkout; 16915074Skarels sc->sc_count = bp->b_bcount; 17015074Skarels vpstart(bp->b_dev); 17115074Skarels while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 17215074Skarels sleep((caddr_t)sc, VPPRI); 17315074Skarels sc->sc_count = 0; 17415074Skarels if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 17515074Skarels sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 17615074Skarels (void) spl0(); 17715074Skarels brkout: 17815074Skarels ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 17915074Skarels sc->sc_state &= ~VPSC_BUSY; 18015074Skarels sc->sc_bp = 0; 18115074Skarels if (e) 1828494Sroot bp->b_flags |= B_ERROR; 18315074Skarels iodone(bp); 18415074Skarels wakeup((caddr_t)sc); 18544Sbill } 18644Sbill 18744Sbill int vpblock = 16384; 18844Sbill 18944Sbill unsigned 19044Sbill minvpph(bp) 1913184Swnj struct buf *bp; 19244Sbill { 19344Sbill 19444Sbill if (bp->b_bcount > vpblock) 19544Sbill bp->b_bcount = vpblock; 19644Sbill } 19744Sbill 19844Sbill /*ARGSUSED*/ 1998168Sroot vpwrite(dev, uio) 2003184Swnj dev_t dev; 2018168Sroot struct uio *uio; 20244Sbill { 20344Sbill 2047848Sroot if (VPUNIT(dev) >= NVP) 2058168Sroot return (ENXIO); 2068168Sroot return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, 2078168Sroot minvpph, uio)); 20844Sbill } 20944Sbill 21015074Skarels vpwait(dev) 21115074Skarels dev_t dev; 21244Sbill { 21315074Skarels register struct vpdevice *vpaddr = 21415074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 21515074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 21615074Skarels register int e; 21744Sbill 21815074Skarels for (;;) { 21915074Skarels e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 22015074Skarels if (e & (VP_READY|VP_ERROR)) 22115074Skarels break; 22215074Skarels sleep((caddr_t)sc, VPPRI); 22315074Skarels } 22415074Skarels /* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */ 22515074Skarels return (e & VP_ERROR); 22644Sbill } 22744Sbill 22815074Skarels vpstart(dev) 22915074Skarels dev_t; 23044Sbill { 23115074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 23215074Skarels register struct vpdevice *vpaddr = 23315074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 23415074Skarels short bit; 23544Sbill 2363184Swnj if (sc->sc_count) { 23715074Skarels vpaddr->pbaddr = sc->sc_ubinfo; 23815074Skarels vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 23915074Skarels if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2403184Swnj vpaddr->prbcr = sc->sc_count; 24144Sbill else 2423184Swnj vpaddr->plbcr = sc->sc_count; 24315074Skarels return; 24444Sbill } 24515074Skarels for (bit = 1; bit != 0; bit <<= 1) 24615074Skarels if (sc->sc_state&bit&VPSC_CMNDS) { 24715074Skarels vpaddr->plcsr |= bit; 24815074Skarels sc->sc_state &= ~bit; 24915074Skarels return; 25015074Skarels } 25144Sbill } 25244Sbill 25344Sbill /*ARGSUSED*/ 25411815Ssam vpioctl(dev, cmd, data, flag) 25515074Skarels dev_t dev; 25615074Skarels int cmd; 25711815Ssam register caddr_t data; 25815074Skarels int flag; 25944Sbill { 2603184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 26115074Skarels register struct vpdevice *vpaddr = 26215074Skarels (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 26344Sbill 26444Sbill switch (cmd) { 26544Sbill 2663184Swnj case VGETSTATE: 26711815Ssam *(int *)data = sc->sc_state; 26818611Skarels return (0); 26944Sbill 2703184Swnj case VSETSTATE: 27115074Skarels sc->sc_state = 27215074Skarels (sc->sc_state & ~VPSC_MODE) | 27315074Skarels ((*(int *)data) & (VPSC_MODE|VPSC_CMNDS)); 27415074Skarels break; 27544Sbill 27644Sbill default: 2778578Sroot return (ENOTTY); 27844Sbill } 27915074Skarels (void) spl4(); 28015074Skarels (void) vpwait(dev); 28115074Skarels if (sc->sc_state&VPSC_SPP) 28215074Skarels vpaddr->plcsr |= VP_SPP; 28315074Skarels else 28415074Skarels vpaddr->plcsr &= ~VP_SPP; 28515074Skarels sc->sc_count = 0; 28615074Skarels while (sc->sc_state & VPSC_CMNDS) { 28715074Skarels (void) vpwait(dev); 28815074Skarels vpstart(dev); 28944Sbill } 29015074Skarels (void) spl0(); 2918578Sroot return (0); 29244Sbill } 29344Sbill 2943184Swnj vptimo(dev) 2953184Swnj dev_t dev; 29644Sbill { 2973184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 29844Sbill 29915074Skarels if (sc->sc_state&VPSC_OPEN) 30015074Skarels timeout(vptimo, (caddr_t)dev, hz/10); 3013184Swnj vpintr(dev); 30244Sbill } 30344Sbill 30444Sbill /*ARGSUSED*/ 30544Sbill vpintr(dev) 3063184Swnj dev_t dev; 30744Sbill { 30815074Skarels register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 30944Sbill 31015074Skarels wakeup((caddr_t)sc); 31144Sbill } 31244Sbill 3133184Swnj vpclose(dev) 3143184Swnj dev_t dev; 31544Sbill { 3163184Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3173184Swnj register struct vpdevice *vpaddr = 3183184Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 31944Sbill 3203184Swnj sc->sc_state = 0; 32115074Skarels sc->sc_count = 0; 3223184Swnj vpaddr->plcsr = 0; 323*40728Skarels return (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