BSD 4_1_snap development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 1 Apr 1981 18:44:36 +0000 (10:44 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 1 Apr 1981 18:44:36 +0000 (10:44 -0800)
Work on file sys/dev/vp.c

Synthesized-from: CSRG/cd1/4.1.snap

sys/dev/vp.c [new file with mode: 0644]

diff --git a/sys/dev/vp.c b/sys/dev/vp.c
new file mode 100644 (file)
index 0000000..8cafa49
--- /dev/null
@@ -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