From: CSRG Date: Wed, 1 Apr 1981 18:44:36 +0000 (-0800) Subject: BSD 4_1_snap development X-Git-Tag: BSD-4_1_snap~405 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/ac9aa4fd311612c4aea07c03eddccce72aefbc84 BSD 4_1_snap development Work on file sys/dev/vp.c Synthesized-from: CSRG/cd1/4.1.snap --- diff --git a/sys/dev/vp.c b/sys/dev/vp.c new file mode 100644 index 0000000000..8cafa4921d --- /dev/null +++ b/sys/dev/vp.c @@ -0,0 +1,338 @@ +/* vp.c 4.9 81/04/02 */ + +#include "vp.h" +#if NVP > 0 +/* + * Versatec matrix printer/plotter + * dma interface driver + * + * SETUP NOTES: + * Set up both print and plot interrupts to go through the same vector + * Give the address of the plcsr register in the config specification + */ +#include "../h/param.h" +#include "../h/dir.h" +#include "../h/user.h" +#include "../h/buf.h" +#include "../h/systm.h" +#include "../h/map.h" +#include "../h/pte.h" +#include "../h/ubavar.h" +#include "../h/ubareg.h" +#include "../h/vcmd.h" + +unsigned minvpph(); + +#define VPPRI (PZERO-1) + +struct vpdevice { + short plbcr; + short pbxaddr; + short prbcr; + u_short pbaddr; + short plcsr; + short plbuf; + short prcsr; + u_short prbuf; +}; + +#define VP_ERROR 0100000 +#define VP_DTCINTR 0040000 +#define VP_DMAACT 0020000 +#define VP_READY 0000200 +#define VP_IENABLE 0000100 +#define VP_TERMCOM 0000040 +#define VP_FFCOM 0000020 +#define VP_EOTCOM 0000010 +#define VP_CLRCOM 0000004 +#define VP_RESET 0000002 +#define VP_SPP 0000001 + +struct vp_softc { + int sc_state; + int sc_count; + int sc_bufp; + struct buf *sc_bp; + int sc_ubinfo; +} vp_softc[NVP]; + +/* sc_state bits */ +#define VPSC_BUSY 0001000 +#define VPSC_MODE 0000700 +#define VPSC_SPP 0000400 +#define VPSC_PLOT 0000200 +#define VPSC_PRINT 0000100 +#define VPSC_CMNDS 0000076 +#define VPSC_OPEN 0000001 + +struct uba_device *vpdinfo[NVP]; + +#define VPUNIT(dev) (minor(dev)) + +struct buf rvpbuf[NVP]; + +int vpprobe(), vpattach(); +struct uba_device *vpdinfo[NVP]; +u_short vpstd[] = { 0777500, 0 }; +struct uba_driver vpdriver = + { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; + +vpprobe(reg) + caddr_t reg; +{ + register int br, cvec; /* value-result */ + register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); + + vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; + vpaddr->pbaddr = 0; + vpaddr->pbxaddr = 0; + vpaddr->prbcr = 1; + DELAY(10000); + vpaddr->prcsr = 0; +#ifdef ERNIE + /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ + if (cvec == 0200) { + printf("vp reset vec from 200 to 174\n"); + cvec = 0174; + } +#endif +} + +/*ARGSUSED*/ +vpattach(ui) + struct uba_device *ui; +{ + + ui->ui_addr -= 010; + ui->ui_physaddr -= 010; +} + +vpopen(dev) + dev_t dev; +{ + register struct vp_softc *sc; + register struct vpdevice *vpaddr; + register struct uba_device *ui; + + if (VPUNIT(dev) >= NVP || + ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || + (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) { + u.u_error = ENXIO; + return; + } + vpaddr = (struct vpdevice *)ui->ui_addr; + sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; + sc->sc_count = 0; + vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; + vptimo(dev); + while (sc->sc_state & VPSC_CMNDS) { + (void) spl4(); + if (vpwait(dev)) { + vpclose(dev); + u.u_error = EIO; + return; + } + vpstart(dev); + (void) spl0(); + } +} + +vpstrategy(bp) + register struct buf *bp; +{ + register int e; + register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; + register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; + register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; + + (void) spl4(); + while (sc->sc_state & VPSC_BUSY) + sleep((caddr_t)sc, VPPRI); + sc->sc_state |= VPSC_BUSY; + sc->sc_bp = bp; + sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); + if (e = vpwait(bp->b_dev)) + goto brkout; + sc->sc_count = bp->b_bcount; + vpstart(bp->b_dev); + while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) + sleep((caddr_t)sc, VPPRI); + sc->sc_count = 0; + if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) + sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; + (void) spl0(); +brkout: + ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); + sc->sc_state &= ~VPSC_BUSY; + sc->sc_bp = 0; + iodone(bp); + if (e) + u.u_error = EIO; + wakeup((caddr_t)sc); +} + +int vpblock = 16384; + +unsigned +minvpph(bp) + struct buf *bp; +{ + + if (bp->b_bcount > vpblock) + bp->b_bcount = vpblock; +} + +/*ARGSUSED*/ +vpwrite(dev) + dev_t dev; +{ + + physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph); +} + +vpwait(dev) + dev_t dev; +{ + register struct vpdevice *vpaddr = + (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; + register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; + register int e; + + for (;;) { + e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; + if (e & (VP_READY|VP_ERROR)) + break; + sleep((caddr_t)sc, VPPRI); + } + /* I wish i could tell whether an error indicated an npr timeout */ + return (e & VP_ERROR); +} + +vpstart(dev) + dev_t; +{ + register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; + register struct vpdevice *vpaddr = + (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; + short bit; + + if (sc->sc_count) { + vpaddr->pbaddr = sc->sc_ubinfo; + vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; + if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) + vpaddr->prbcr = sc->sc_count; + else + vpaddr->plbcr = sc->sc_count; + return; + } + for (bit = 1; bit != 0; bit <<= 1) + if (sc->sc_state&bit&VPSC_CMNDS) { + vpaddr->plcsr |= bit; + sc->sc_state &= ~bit; + return; + } +} + +/*ARGSUSED*/ +vpioctl(dev, cmd, addr, flag) + dev_t dev; + int cmd; + register caddr_t addr; + int flag; +{ + register int m; + register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; + register struct vpdevice *vpaddr = + (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; + + switch (cmd) { + + case VGETSTATE: + (void) suword(addr, sc->sc_state); + return; + + case VSETSTATE: + m = fuword(addr); + if (m == -1) { + u.u_error = EFAULT; + return; + } + sc->sc_state = + (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); + break; + + default: + u.u_error = ENOTTY; + return; + } + (void) spl4(); + (void) vpwait(dev); + if (sc->sc_state&VPSC_SPP) + vpaddr->plcsr |= VP_SPP; + else + vpaddr->plcsr &= ~VP_SPP; + sc->sc_count = 0; + while (sc->sc_state & VPSC_CMNDS) { + (void) vpwait(dev); + vpstart(dev); + } + (void) spl0(); +} + +vptimo(dev) + dev_t dev; +{ + register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; + + if (sc->sc_state&VPSC_OPEN) + timeout(vptimo, (caddr_t)dev, hz/10); + vpintr(dev); +} + +/*ARGSUSED*/ +vpintr(dev) + dev_t dev; +{ + register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; + + wakeup((caddr_t)sc); +} + +vpclose(dev) + dev_t dev; +{ + register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; + register struct vpdevice *vpaddr = + (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; + + sc->sc_state = 0; + sc->sc_count = 0; + vpaddr->plcsr = 0; +} + +vpreset(uban) + int uban; +{ + register int vp11; + register struct uba_device *ui; + register struct vp_softc *sc = vp_softc; + register struct vpdevice *vpaddr; + + for (vp11 = 0; vp11 < NVP; vp11++, sc++) { + if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || + ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) + continue; + printf(" vp%d", vp11); + vpaddr = (struct vpdevice *)ui->ui_addr; + vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; + if ((sc->sc_state & VPSC_BUSY) == 0) + continue; + if (sc->sc_ubinfo) { + printf("<%d>", (sc->sc_ubinfo>>28)&0xf); + ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); + } + sc->sc_count = sc->sc_bp->b_bcount; + vpstart(sc->sc_bp->b_dev); + } +} +#endif