123361Smckusick /*
229259Smckusick * Copyright (c) 1982, 1986 Regents of the University of California.
323361Smckusick * All rights reserved. The Berkeley software License Agreement
423361Smckusick * specifies the terms and conditions for redistribution.
523361Smckusick *
6*45810Sbostic * @(#)va.c 7.4 (Berkeley) 12/16/90
723361Smckusick */
841Sbill
91938Swnj #include "va.h"
101564Sbill #if NVA > 0
111564Sbill /*
123183Swnj * Varian printer plotter
131564Sbill */
14*45810Sbostic #include "../include/pte.h"
159784Ssam
16*45810Sbostic #include "sys/param.h"
17*45810Sbostic #include "sys/user.h"
18*45810Sbostic #include "sys/buf.h"
19*45810Sbostic #include "sys/systm.h"
20*45810Sbostic #include "sys/map.h"
21*45810Sbostic #include "sys/ioctl.h"
22*45810Sbostic #include "sys/vcmd.h"
23*45810Sbostic #include "sys/uio.h"
24*45810Sbostic #include "sys/kernel.h"
2541Sbill
2617085Sbloom #include "ubareg.h"
2717085Sbloom #include "ubavar.h"
289363Smckusick
299364Smckusick int vadebug = 0;
309364Smckusick #define dprintf if(vadebug)printf
319364Smckusick
32287Sbill unsigned minvaph();
3341Sbill
3441Sbill #define VAPRI (PZERO-1)
3541Sbill
363183Swnj struct vadevice {
373183Swnj u_short vaba; /* buffer address */
383183Swnj short vawc; /* word count (2's complement) */
3941Sbill union {
403183Swnj short Vacsw; /* control status as word */
413183Swnj struct { /* control status as bytes */
42287Sbill char Vacsl;
43287Sbill char Vacsh;
44287Sbill } vacsr;
45287Sbill } vacs;
463183Swnj short vadata; /* programmed i/o data buffer */
4741Sbill };
4841Sbill
49287Sbill #define vacsw vacs.Vacsw
50287Sbill #define vacsh vacs.vacsr.Vacsh
51287Sbill #define vacsl vacs.vacsr.Vacsl
52287Sbill
53287Sbill /* vacsw bits */
543183Swnj #define VA_ERROR 0100000 /* some error has occurred */
553183Swnj #define VA_NPRTIMO 0001000 /* DMA timeout error */
563183Swnj #define VA_NOTREADY 0000400 /* something besides NPRTIMO */
573183Swnj #define VA_DONE 0000200
583183Swnj #define VA_IENABLE 0000100 /* interrupt enable */
599362Smckusick #define VA_DMAGO 0000010 /* DMA go bit */
609364Smckusick #define VA_DMAGO 0000010 /* DMA go bit */
613183Swnj #define VA_SUPPLIESLOW 0000004
623183Swnj #define VA_BOTOFFORM 0000002
633183Swnj #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */
6441Sbill
65287Sbill /* vacsh command bytes */
663183Swnj #define VAPLOT 0000340
673183Swnj #define VAPRINT 0000100
683183Swnj #define VAPRINTPLOT 0000160
693183Swnj #define VAAUTOSTEP 0000244
703183Swnj #define VANOAUTOSTEP 0000045
713183Swnj #define VAFORMFEED 0000263
723183Swnj #define VASLEW 0000265
733183Swnj #define VASTEP 0000064
7441Sbill
753183Swnj struct va_softc {
769364Smckusick u_char sc_openf; /* exclusive open flag */
779364Smckusick u_char sc_iostate; /* kind of I/O going on */
789364Smckusick #define VAS_IDLE 0 /* no I/O, free */
799364Smckusick #define VAS_PIO 1 /* programmed I/O */
809364Smckusick #define VAS_DMA 2 /* DMA, block pio */
819364Smckusick #define VAS_WANT 4 /* wakeup when iostate changes */
829364Smckusick short sc_tocnt; /* time out counter */
839364Smckusick short sc_info; /* csw passed from vaintr */
849364Smckusick int sc_state; /* print/plot state of device */
853183Swnj } va_softc[NVA];
8641Sbill
873183Swnj #define VAUNIT(dev) (minor(dev))
883183Swnj
893183Swnj struct buf rvabuf[NVA];
903183Swnj
919364Smckusick int vaprobe(), vaslave(), vaattach(), vadgo();
923183Swnj struct uba_device *vadinfo[NVA];
939364Smckusick struct uba_ctlr *vaminfo[NVA];
949364Smckusick struct buf vabhdr[NVA];
953183Swnj u_short vastd[] = { 0764000, 0 };
963183Swnj struct uba_driver vadriver =
979364Smckusick { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo };
983183Swnj
vaprobe(reg)993183Swnj vaprobe(reg)
1003183Swnj caddr_t reg;
10141Sbill {
1023183Swnj register int br, cvec; /* value-result */
1033183Swnj register struct vadevice *vaaddr = (struct vadevice *)reg;
10441Sbill
1059267Smckusick #ifdef lint
1069267Smckusick br = 0; cvec = br; br = cvec;
1079267Smckusick vaintr(0);
1089267Smckusick #endif
1099364Smckusick #ifndef UCBVAX
1103183Swnj vaaddr->vacsl = VA_IENABLE;
1113183Swnj vaaddr->vaba = 0;
1123183Swnj vaaddr->vacsh = VAPLOT;
1139364Smckusick vaaddr->vacsl = VA_IENABLE|VA_DMAGO;
1149364Smckusick vaaddr->vawc = -1;
1159364Smckusick DELAY(10000);
1169361Smckusick vaaddr->vacsl = 0;
1179364Smckusick vaaddr->vawc = 0;
1189364Smckusick #else
1199364Smckusick br=0x14;
1209364Smckusick cvec=0170;
1219362Smckusick #endif
1229362Smckusick return (sizeof (struct vadevice));
1233183Swnj }
1243183Swnj
1253183Swnj /*ARGSUSED*/
1269364Smckusick vaslave(ui, reg)
1279364Smckusick struct uba_device *ui;
1289364Smckusick caddr_t reg;
1299364Smckusick {
1309364Smckusick
1319364Smckusick ui->ui_dk = 0;
1329364Smckusick return (ui->ui_unit <= 0);
1339364Smckusick }
1349364Smckusick
1359364Smckusick /*ARGSUSED*/
1363183Swnj vaattach(ui)
1373183Swnj struct uba_device *ui;
1383183Swnj {
1393183Swnj
1409364Smckusick ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit];
1413183Swnj }
1423183Swnj
vaopen(dev)1433183Swnj vaopen(dev)
1443183Swnj dev_t dev;
1453183Swnj {
1463183Swnj register struct va_softc *sc;
1473183Swnj register struct vadevice *vaaddr;
1483183Swnj register struct uba_device *ui;
1499363Smckusick int error;
1509364Smckusick int unit = VAUNIT(dev);
1513183Swnj
1529392Smckusick if (unit >= NVA || (sc = &va_softc[unit])->sc_openf ||
1539392Smckusick (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0)
1549363Smckusick return (ENXIO);
1553183Swnj vaaddr = (struct vadevice *)ui->ui_addr;
1563183Swnj sc->sc_openf = 1;
1573183Swnj vaaddr->vawc = 0;
1583183Swnj sc->sc_state = 0;
1599364Smckusick sc->sc_tocnt = 0;
1609364Smckusick sc->sc_iostate = VAS_IDLE;
1613183Swnj vaaddr->vacsl = VA_IENABLE;
1623183Swnj vatimo(dev);
1639363Smckusick error = vacmd(dev, VPRINT);
1649363Smckusick if (error)
1653183Swnj vaclose(dev);
1669363Smckusick return (error);
16741Sbill }
16841Sbill
vastrategy(bp)16941Sbill vastrategy(bp)
17041Sbill register struct buf *bp;
17141Sbill {
1729364Smckusick register struct uba_device *ui;
1739364Smckusick register struct uba_ctlr *um;
1749364Smckusick int s;
17541Sbill
1769364Smckusick dprintf("vastrategy(%x)\n", bp);
1779364Smckusick ui = vadinfo[VAUNIT(bp->b_dev)];
1789364Smckusick if (ui == 0 || ui->ui_alive == 0) {
1799364Smckusick bp->b_flags |= B_ERROR;
1809364Smckusick iodone(bp);
1819364Smckusick return;
18241Sbill }
1839364Smckusick s = spl4();
1849364Smckusick um = ui->ui_mi;
1859364Smckusick bp->b_actf = NULL;
1869364Smckusick if (um->um_tab.b_actf->b_actf == NULL)
1879364Smckusick um->um_tab.b_actf->b_actf = bp;
1889364Smckusick else {
1899364Smckusick printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n",
1909364Smckusick bp, um->um_tab.b_actf->b_actf);
1919364Smckusick panic("vastrategy");
1929364Smckusick um->um_tab.b_actf->b_actl->b_forw = bp;
1939364Smckusick }
1949364Smckusick um->um_tab.b_actf->b_actl = bp;
1959364Smckusick bp = um->um_tab.b_actf;
1969364Smckusick dprintf("vastrategy: bp=%x actf=%x active=%d\n",
1979364Smckusick bp, bp->b_actf, bp->b_active);
1989364Smckusick if (bp->b_actf && bp->b_active == 0)
1999364Smckusick (void) vastart(um);
2009364Smckusick splx(s);
20141Sbill }
20241Sbill
20341Sbill int vablock = 16384;
20441Sbill
20541Sbill unsigned
minvaph(bp)20641Sbill minvaph(bp)
2073183Swnj struct buf *bp;
20841Sbill {
2093183Swnj
21041Sbill if (bp->b_bcount > vablock)
21141Sbill bp->b_bcount = vablock;
21241Sbill }
21341Sbill
21441Sbill /*ARGSUSED*/
vawrite(dev,uio)2159362Smckusick vawrite(dev, uio)
2163183Swnj dev_t dev;
2179362Smckusick struct uio *uio;
21841Sbill {
2199267Smckusick
2209362Smckusick if (VAUNIT(dev) > NVA)
2219363Smckusick return (ENXIO);
2229363Smckusick return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE,
2239363Smckusick minvaph, uio));
22441Sbill }
22541Sbill
vastart(um)2269364Smckusick vastart(um)
2279364Smckusick register struct uba_ctlr *um;
22841Sbill {
2299364Smckusick struct buf *bp;
2309364Smckusick struct vadevice *vaaddr;
2319364Smckusick register struct va_softc *sc;
2329364Smckusick int unit;
23341Sbill
2349364Smckusick dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf);
2359364Smckusick if ((bp = um->um_tab.b_actf->b_actf) == NULL)
2369364Smckusick return;
2379364Smckusick unit = VAUNIT(bp->b_dev);
2389364Smckusick sc = &va_softc[unit];
2399364Smckusick sc->sc_tocnt = 0;
2409364Smckusick while (sc->sc_iostate&VAS_PIO) {
2419364Smckusick sc->sc_iostate |= VAS_WANT;
2429364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI);
2439364Smckusick }
2449364Smckusick sc->sc_iostate |= VAS_DMA;
2459364Smckusick vaaddr = (struct vadevice *)um->um_addr;
2469364Smckusick vaaddr->vacsl = 0;
2479364Smckusick vaaddr->vawc = -(bp->b_bcount / 2);
2489364Smckusick um->um_cmd = VA_DMAGO | VA_IENABLE;
2499364Smckusick (void) ubago(vadinfo[unit]);
25041Sbill }
25141Sbill
vadgo(um)2529364Smckusick vadgo(um)
2539364Smckusick register struct uba_ctlr *um;
25441Sbill {
2559364Smckusick register struct vadevice *vaaddr = (struct vadevice *)um->um_addr;
2569364Smckusick register struct buf *bp;
2573183Swnj
2589364Smckusick bp = um->um_tab.b_actf;
2599364Smckusick va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0;
2609364Smckusick bp->b_active++;
2619364Smckusick vaaddr->vaba = um->um_ubinfo;
2629364Smckusick vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd;
26341Sbill }
26441Sbill
26541Sbill /*ARGSUSED*/
vaioctl(dev,cmd,data,flag)2669362Smckusick vaioctl(dev, cmd, data, flag)
2679362Smckusick register caddr_t data;
26841Sbill {
2693183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)];
27041Sbill
27141Sbill switch (cmd) {
27241Sbill
27341Sbill case VGETSTATE:
2749362Smckusick *(int *)data = sc->sc_state;
2759363Smckusick break;
27641Sbill
27741Sbill case VSETSTATE:
2789363Smckusick return (vacmd(dev, *(int *)data));
27941Sbill
28041Sbill default:
2819363Smckusick return (ENOTTY);
28241Sbill }
2839363Smckusick return (0);
28441Sbill }
28541Sbill
vacmd(dev,vcmd)2863183Swnj vacmd(dev, vcmd)
2873183Swnj dev_t dev;
2883183Swnj int vcmd;
28941Sbill {
2903183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2919363Smckusick int error = 0;
2929364Smckusick int s, cmd;
2933183Swnj
2949364Smckusick s = spl4();
2959364Smckusick while (sc->sc_iostate&VAS_DMA) {
2969364Smckusick sc->sc_iostate |= VAS_WANT;
2979364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI);
2989364Smckusick }
2999364Smckusick sc->sc_iostate |= VAS_PIO;
3009364Smckusick sc->sc_tocnt = 0;
3019364Smckusick cmd = 0;
30241Sbill switch (vcmd) {
30341Sbill
30441Sbill case VPLOT:
30541Sbill /* Must turn on plot AND autostep modes. */
3069364Smckusick if (vadopio(dev, VAPLOT))
3079363Smckusick error = EIO;
3089364Smckusick cmd = VAAUTOSTEP;
30941Sbill break;
31041Sbill
31141Sbill case VPRINT:
3129364Smckusick cmd = VAPRINT;
31341Sbill break;
31441Sbill
31541Sbill case VPRINTPLOT:
3169364Smckusick cmd = VAPRINTPLOT;
31741Sbill break;
31841Sbill }
3193183Swnj sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
3209364Smckusick if (cmd && vadopio(dev, cmd))
3219363Smckusick error = EIO;
3229364Smckusick sc->sc_iostate &= ~VAS_PIO;
3239364Smckusick if (sc->sc_iostate&VAS_WANT) {
3249364Smckusick sc->sc_iostate &= ~VAS_WANT;
3259364Smckusick wakeup((caddr_t)&sc->sc_iostate);
3269364Smckusick }
3279364Smckusick splx(s);
3289363Smckusick return (error);
32941Sbill }
33041Sbill
vadopio(dev,cmd)3319364Smckusick vadopio(dev, cmd)
3329364Smckusick dev_t dev;
3339364Smckusick int cmd;
3349364Smckusick {
3359364Smckusick register struct vadevice *vaaddr =
3369364Smckusick (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr;
3379364Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3389364Smckusick
3399364Smckusick sc->sc_info = 0;
3409364Smckusick vaaddr->vacsh = cmd;
3419364Smckusick while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0)
3429364Smckusick sleep((caddr_t)&sc->sc_info, VAPRI);
3439364Smckusick return (sc->sc_info&VA_ERROR);
3449364Smckusick }
3459364Smckusick
vatimo(dev)3463183Swnj vatimo(dev)
3473183Swnj dev_t dev;
34841Sbill {
3493183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3503183Swnj
3513183Swnj if (sc->sc_openf)
3529364Smckusick timeout(vatimo, (caddr_t)dev, hz/2);
3539364Smckusick if (++sc->sc_tocnt < 2)
3549364Smckusick return;
3559364Smckusick sc->sc_tocnt = 0;
3569364Smckusick dprintf("vatimo: calling vaintr\n");
3579267Smckusick vaintr(dev);
35841Sbill }
35941Sbill
36041Sbill /*ARGSUSED*/
vaintr(dev)36141Sbill vaintr(dev)
3623183Swnj dev_t dev;
36341Sbill {
3649364Smckusick register struct uba_ctlr *um;
3659364Smckusick struct vadevice *vaaddr;
3669364Smckusick struct buf *bp;
3679364Smckusick register int unit = VAUNIT(dev), e;
3689364Smckusick register struct va_softc *sc = &va_softc[unit];
3693183Swnj
3709364Smckusick um = vaminfo[unit];
3719364Smckusick vaaddr = (struct vadevice *)um->um_addr;
3729364Smckusick e = vaaddr->vacsw;
3739364Smckusick dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n",
3749364Smckusick um, e, um->um_tab.b_actf->b_active);
3759364Smckusick if ((e&(VA_DONE|VA_ERROR)) == 0)
3769364Smckusick return;
3779364Smckusick vaaddr->vacsl = 0;
3789364Smckusick if ((e&VA_ERROR) && (e&VA_NPRTIMO))
3799364Smckusick printf("va%d: npr timeout\n", unit);
3809364Smckusick if (sc->sc_iostate&VAS_PIO) {
3819364Smckusick sc->sc_info = e;
3829364Smckusick wakeup((caddr_t)&sc->sc_info);
3839364Smckusick return;
3849364Smckusick }
3859364Smckusick if (um->um_tab.b_actf->b_active) {
3869364Smckusick bp = um->um_tab.b_actf->b_actf;
3879364Smckusick if (e&VA_ERROR)
3889364Smckusick bp->b_flags |= B_ERROR;
3899364Smckusick if (sc->sc_state&VPRINTPLOT) {
3909364Smckusick sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
3919364Smckusick vaaddr->vacsh = VAAUTOSTEP;
3929364Smckusick return;
3939364Smckusick }
3949364Smckusick ubadone(um);
3959364Smckusick um->um_tab.b_actf->b_active = 0;
3969364Smckusick um->um_tab.b_actf->b_actf = bp->b_forw;
3979364Smckusick bp->b_active = 0;
3989364Smckusick bp->b_errcnt = 0;
3999364Smckusick bp->b_resid = 0;
4009364Smckusick iodone(bp);
4019364Smckusick }
4029364Smckusick if (um->um_tab.b_actf->b_actf == 0) {
4039364Smckusick sc->sc_iostate &= ~VAS_DMA;
4049364Smckusick if (sc->sc_iostate&VAS_WANT) {
4059364Smckusick sc->sc_iostate &= ~VAS_WANT;
4069364Smckusick wakeup((caddr_t)&sc->sc_iostate);
4079364Smckusick }
4089364Smckusick return;
4099364Smckusick }
4109364Smckusick if (um->um_tab.b_actf->b_active == 0)
4119364Smckusick vastart(um);
41241Sbill }
41341Sbill
vaclose(dev)4143183Swnj vaclose(dev)
4153183Swnj dev_t dev;
41641Sbill {
4173183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)];
4183183Swnj register struct vadevice *vaaddr =
4193183Swnj (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
42041Sbill
4213183Swnj sc->sc_openf = 0;
4223183Swnj sc->sc_state = 0;
4239364Smckusick if (sc->sc_iostate != VAS_IDLE)
4249364Smckusick wakeup((caddr_t)&sc->sc_iostate);
4259364Smckusick sc->sc_iostate = VAS_IDLE;
4263183Swnj vaaddr->vacsl = 0;
4279364Smckusick vaaddr->vawc = 0;
42841Sbill }
429287Sbill
vareset(uban)4303183Swnj vareset(uban)
4313183Swnj int uban;
432287Sbill {
4333183Swnj register int va11;
4349364Smckusick register struct uba_ctlr *um;
4353183Swnj register struct vadevice *vaaddr;
4369364Smckusick register struct va_softc *sc;
437287Sbill
4383183Swnj for (va11 = 0; va11 < NVA; va11++, sc++) {
4399364Smckusick if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban ||
4409364Smckusick um->um_alive == 0)
4413183Swnj continue;
4429364Smckusick sc = &va_softc[um->um_ctlr];
4439364Smckusick if (sc->sc_openf == 0)
4449364Smckusick continue;
4453183Swnj printf(" va%d", va11);
4469364Smckusick vaaddr = (struct vadevice *)um->um_addr;
4473183Swnj vaaddr->vacsl = VA_IENABLE;
4483183Swnj if (sc->sc_state & VPLOT) {
4493183Swnj vaaddr->vacsh = VAPLOT;
4503183Swnj DELAY(10000);
4513183Swnj vaaddr->vacsh = VAAUTOSTEP;
4523183Swnj } else if (sc->sc_state & VPRINTPLOT)
4533183Swnj vaaddr->vacsh = VPRINTPLOT;
4543183Swnj else
4553183Swnj vaaddr->vacsh = VAPRINTPLOT;
456287Sbill DELAY(10000);
4579392Smckusick sc->sc_iostate = VAS_IDLE;
4589392Smckusick um->um_tab.b_actf->b_active = 0;
4599392Smckusick um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0;
4609392Smckusick if (um->um_ubinfo) {
4619392Smckusick printf("<%d>", (um->um_ubinfo >> 28) & 0xf);
4629392Smckusick um->um_ubinfo = 0;
4639392Smckusick }
4649364Smckusick (void) vastart(um);
465287Sbill }
466287Sbill }
4676432Ssam
vaselect()4686432Ssam vaselect()
4696432Ssam {
4709363Smckusick
4716432Ssam return (1);
4726432Ssam }
4731564Sbill #endif
474