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*45810Sbostic * @(#)vp.c 7.5 (Berkeley) 12/16/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 */
21*45810Sbostic #include "../include/pte.h"
229785Ssam
23*45810Sbostic #include "sys/param.h"
24*45810Sbostic #include "sys/user.h"
25*45810Sbostic #include "sys/buf.h"
26*45810Sbostic #include "sys/systm.h"
27*45810Sbostic #include "sys/map.h"
28*45810Sbostic #include "sys/ioctl.h"
29*45810Sbostic #include "sys/vcmd.h"
30*45810Sbostic #include "sys/uio.h"
31*45810Sbostic #include "sys/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
vpprobe(reg)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
vpopen(dev)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)) {
14440728Skarels (void) vpclose(dev);
14515074Skarels return (EIO);
14615074Skarels }
14715074Skarels vpstart(dev);
14815074Skarels (void) spl0();
14915074Skarels }
15015074Skarels return (0);
15144Sbill }
15244Sbill
vpstrategy(bp)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
minvpph(bp)19044Sbill minvpph(bp)
1913184Swnj struct buf *bp;
19244Sbill {
19344Sbill
19444Sbill if (bp->b_bcount > vpblock)
19544Sbill bp->b_bcount = vpblock;
19644Sbill }
19744Sbill
19844Sbill /*ARGSUSED*/
vpwrite(dev,uio)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
vpwait(dev)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*/
vpioctl(dev,cmd,data,flag)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
vptimo(dev)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*/
vpintr(dev)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
vpclose(dev)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;
32340728Skarels return (0);
32444Sbill }
325288Sbill
vpreset(uban)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
vpselect()3496432Ssam vpselect()
3506432Ssam {
3516432Ssam return (1);
3526432Ssam }
3531565Sbill #endif
354