1*23361Smckusick /* 2*23361Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23361Smckusick * All rights reserved. The Berkeley software License Agreement 4*23361Smckusick * specifies the terms and conditions for redistribution. 5*23361Smckusick * 6*23361Smckusick * @(#)va.c 6.3 (Berkeley) 06/08/85 7*23361Smckusick */ 841Sbill 91938Swnj #include "va.h" 101564Sbill #if NVA > 0 111564Sbill /* 123183Swnj * Varian printer plotter 131564Sbill */ 149784Ssam #include "../machine/pte.h" 159784Ssam 1617085Sbloom #include "param.h" 1717085Sbloom #include "dir.h" 1817085Sbloom #include "user.h" 1917085Sbloom #include "buf.h" 2017085Sbloom #include "systm.h" 2117085Sbloom #include "map.h" 2217085Sbloom #include "ioctl.h" 2317085Sbloom #include "vcmd.h" 2417085Sbloom #include "uio.h" 2517085Sbloom #include "kernel.h" 2641Sbill 2717085Sbloom #include "ubareg.h" 2817085Sbloom #include "ubavar.h" 299363Smckusick 309364Smckusick int vadebug = 0; 319364Smckusick #define dprintf if(vadebug)printf 329364Smckusick 33287Sbill unsigned minvaph(); 3441Sbill 3541Sbill #define VAPRI (PZERO-1) 3641Sbill 373183Swnj struct vadevice { 383183Swnj u_short vaba; /* buffer address */ 393183Swnj short vawc; /* word count (2's complement) */ 4041Sbill union { 413183Swnj short Vacsw; /* control status as word */ 423183Swnj struct { /* control status as bytes */ 43287Sbill char Vacsl; 44287Sbill char Vacsh; 45287Sbill } vacsr; 46287Sbill } vacs; 473183Swnj short vadata; /* programmed i/o data buffer */ 4841Sbill }; 4941Sbill 50287Sbill #define vacsw vacs.Vacsw 51287Sbill #define vacsh vacs.vacsr.Vacsh 52287Sbill #define vacsl vacs.vacsr.Vacsl 53287Sbill 54287Sbill /* vacsw bits */ 553183Swnj #define VA_ERROR 0100000 /* some error has occurred */ 563183Swnj #define VA_NPRTIMO 0001000 /* DMA timeout error */ 573183Swnj #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 583183Swnj #define VA_DONE 0000200 593183Swnj #define VA_IENABLE 0000100 /* interrupt enable */ 609362Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 619364Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 623183Swnj #define VA_SUPPLIESLOW 0000004 633183Swnj #define VA_BOTOFFORM 0000002 643183Swnj #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 6541Sbill 66287Sbill /* vacsh command bytes */ 673183Swnj #define VAPLOT 0000340 683183Swnj #define VAPRINT 0000100 693183Swnj #define VAPRINTPLOT 0000160 703183Swnj #define VAAUTOSTEP 0000244 713183Swnj #define VANOAUTOSTEP 0000045 723183Swnj #define VAFORMFEED 0000263 733183Swnj #define VASLEW 0000265 743183Swnj #define VASTEP 0000064 7541Sbill 763183Swnj struct va_softc { 779364Smckusick u_char sc_openf; /* exclusive open flag */ 789364Smckusick u_char sc_iostate; /* kind of I/O going on */ 799364Smckusick #define VAS_IDLE 0 /* no I/O, free */ 809364Smckusick #define VAS_PIO 1 /* programmed I/O */ 819364Smckusick #define VAS_DMA 2 /* DMA, block pio */ 829364Smckusick #define VAS_WANT 4 /* wakeup when iostate changes */ 839364Smckusick short sc_tocnt; /* time out counter */ 849364Smckusick short sc_info; /* csw passed from vaintr */ 859364Smckusick int sc_state; /* print/plot state of device */ 863183Swnj } va_softc[NVA]; 8741Sbill 883183Swnj #define VAUNIT(dev) (minor(dev)) 893183Swnj 903183Swnj struct buf rvabuf[NVA]; 913183Swnj 929364Smckusick int vaprobe(), vaslave(), vaattach(), vadgo(); 933183Swnj struct uba_device *vadinfo[NVA]; 949364Smckusick struct uba_ctlr *vaminfo[NVA]; 959364Smckusick struct buf vabhdr[NVA]; 963183Swnj u_short vastd[] = { 0764000, 0 }; 973183Swnj struct uba_driver vadriver = 989364Smckusick { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo }; 993183Swnj 1003183Swnj vaprobe(reg) 1013183Swnj caddr_t reg; 10241Sbill { 1033183Swnj register int br, cvec; /* value-result */ 1043183Swnj register struct vadevice *vaaddr = (struct vadevice *)reg; 10541Sbill 1069267Smckusick #ifdef lint 1079267Smckusick br = 0; cvec = br; br = cvec; 1089267Smckusick vaintr(0); 1099267Smckusick #endif 1109364Smckusick #ifndef UCBVAX 1113183Swnj vaaddr->vacsl = VA_IENABLE; 1123183Swnj vaaddr->vaba = 0; 1133183Swnj vaaddr->vacsh = VAPLOT; 1149364Smckusick vaaddr->vacsl = VA_IENABLE|VA_DMAGO; 1159364Smckusick vaaddr->vawc = -1; 1169364Smckusick DELAY(10000); 1179361Smckusick vaaddr->vacsl = 0; 1189364Smckusick vaaddr->vawc = 0; 1199364Smckusick #else 1209364Smckusick br=0x14; 1219364Smckusick cvec=0170; 1229362Smckusick #endif 1239362Smckusick return (sizeof (struct vadevice)); 1243183Swnj } 1253183Swnj 1263183Swnj /*ARGSUSED*/ 1279364Smckusick vaslave(ui, reg) 1289364Smckusick struct uba_device *ui; 1299364Smckusick caddr_t reg; 1309364Smckusick { 1319364Smckusick 1329364Smckusick ui->ui_dk = 0; 1339364Smckusick return (ui->ui_unit <= 0); 1349364Smckusick } 1359364Smckusick 1369364Smckusick /*ARGSUSED*/ 1373183Swnj vaattach(ui) 1383183Swnj struct uba_device *ui; 1393183Swnj { 1403183Swnj 1419364Smckusick ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit]; 1423183Swnj } 1433183Swnj 1443183Swnj vaopen(dev) 1453183Swnj dev_t dev; 1463183Swnj { 1473183Swnj register struct va_softc *sc; 1483183Swnj register struct vadevice *vaaddr; 1493183Swnj register struct uba_device *ui; 1509363Smckusick int error; 1519364Smckusick int unit = VAUNIT(dev); 1523183Swnj 1539392Smckusick if (unit >= NVA || (sc = &va_softc[unit])->sc_openf || 1549392Smckusick (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0) 1559363Smckusick return (ENXIO); 1563183Swnj vaaddr = (struct vadevice *)ui->ui_addr; 1573183Swnj sc->sc_openf = 1; 1583183Swnj vaaddr->vawc = 0; 1593183Swnj sc->sc_state = 0; 1609364Smckusick sc->sc_tocnt = 0; 1619364Smckusick sc->sc_iostate = VAS_IDLE; 1623183Swnj vaaddr->vacsl = VA_IENABLE; 1633183Swnj vatimo(dev); 1649363Smckusick error = vacmd(dev, VPRINT); 1659363Smckusick if (error) 1663183Swnj vaclose(dev); 1679363Smckusick return (error); 16841Sbill } 16941Sbill 17041Sbill vastrategy(bp) 17141Sbill register struct buf *bp; 17241Sbill { 1739364Smckusick register struct uba_device *ui; 1749364Smckusick register struct uba_ctlr *um; 1759364Smckusick int s; 17641Sbill 1779364Smckusick dprintf("vastrategy(%x)\n", bp); 1789364Smckusick ui = vadinfo[VAUNIT(bp->b_dev)]; 1799364Smckusick if (ui == 0 || ui->ui_alive == 0) { 1809364Smckusick bp->b_flags |= B_ERROR; 1819364Smckusick iodone(bp); 1829364Smckusick return; 18341Sbill } 1849364Smckusick s = spl4(); 1859364Smckusick um = ui->ui_mi; 1869364Smckusick bp->b_actf = NULL; 1879364Smckusick if (um->um_tab.b_actf->b_actf == NULL) 1889364Smckusick um->um_tab.b_actf->b_actf = bp; 1899364Smckusick else { 1909364Smckusick printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n", 1919364Smckusick bp, um->um_tab.b_actf->b_actf); 1929364Smckusick panic("vastrategy"); 1939364Smckusick um->um_tab.b_actf->b_actl->b_forw = bp; 1949364Smckusick } 1959364Smckusick um->um_tab.b_actf->b_actl = bp; 1969364Smckusick bp = um->um_tab.b_actf; 1979364Smckusick dprintf("vastrategy: bp=%x actf=%x active=%d\n", 1989364Smckusick bp, bp->b_actf, bp->b_active); 1999364Smckusick if (bp->b_actf && bp->b_active == 0) 2009364Smckusick (void) vastart(um); 2019364Smckusick splx(s); 20241Sbill } 20341Sbill 20441Sbill int vablock = 16384; 20541Sbill 20641Sbill unsigned 20741Sbill minvaph(bp) 2083183Swnj struct buf *bp; 20941Sbill { 2103183Swnj 21141Sbill if (bp->b_bcount > vablock) 21241Sbill bp->b_bcount = vablock; 21341Sbill } 21441Sbill 21541Sbill /*ARGSUSED*/ 2169362Smckusick vawrite(dev, uio) 2173183Swnj dev_t dev; 2189362Smckusick struct uio *uio; 21941Sbill { 2209267Smckusick 2219362Smckusick if (VAUNIT(dev) > NVA) 2229363Smckusick return (ENXIO); 2239363Smckusick return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, 2249363Smckusick minvaph, uio)); 22541Sbill } 22641Sbill 2279364Smckusick vastart(um) 2289364Smckusick register struct uba_ctlr *um; 22941Sbill { 2309364Smckusick struct buf *bp; 2319364Smckusick struct vadevice *vaaddr; 2329364Smckusick register struct va_softc *sc; 2339364Smckusick int unit; 23441Sbill 2359364Smckusick dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf); 2369364Smckusick if ((bp = um->um_tab.b_actf->b_actf) == NULL) 2379364Smckusick return; 2389364Smckusick unit = VAUNIT(bp->b_dev); 2399364Smckusick sc = &va_softc[unit]; 2409364Smckusick sc->sc_tocnt = 0; 2419364Smckusick while (sc->sc_iostate&VAS_PIO) { 2429364Smckusick sc->sc_iostate |= VAS_WANT; 2439364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 2449364Smckusick } 2459364Smckusick sc->sc_iostate |= VAS_DMA; 2469364Smckusick vaaddr = (struct vadevice *)um->um_addr; 2479364Smckusick vaaddr->vacsl = 0; 2489364Smckusick vaaddr->vawc = -(bp->b_bcount / 2); 2499364Smckusick um->um_cmd = VA_DMAGO | VA_IENABLE; 2509364Smckusick (void) ubago(vadinfo[unit]); 25141Sbill } 25241Sbill 2539364Smckusick vadgo(um) 2549364Smckusick register struct uba_ctlr *um; 25541Sbill { 2569364Smckusick register struct vadevice *vaaddr = (struct vadevice *)um->um_addr; 2579364Smckusick register struct buf *bp; 2583183Swnj 2599364Smckusick bp = um->um_tab.b_actf; 2609364Smckusick va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0; 2619364Smckusick bp->b_active++; 2629364Smckusick vaaddr->vaba = um->um_ubinfo; 2639364Smckusick vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd; 26441Sbill } 26541Sbill 26641Sbill /*ARGSUSED*/ 2679362Smckusick vaioctl(dev, cmd, data, flag) 2689362Smckusick register caddr_t data; 26941Sbill { 2703183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 27141Sbill 27241Sbill switch (cmd) { 27341Sbill 27441Sbill case VGETSTATE: 2759362Smckusick *(int *)data = sc->sc_state; 2769363Smckusick break; 27741Sbill 27841Sbill case VSETSTATE: 2799363Smckusick return (vacmd(dev, *(int *)data)); 28041Sbill 28141Sbill default: 2829363Smckusick return (ENOTTY); 28341Sbill } 2849363Smckusick return (0); 28541Sbill } 28641Sbill 2873183Swnj vacmd(dev, vcmd) 2883183Swnj dev_t dev; 2893183Swnj int vcmd; 29041Sbill { 2913183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2929363Smckusick int error = 0; 2939364Smckusick int s, cmd; 2943183Swnj 2959364Smckusick s = spl4(); 2969364Smckusick while (sc->sc_iostate&VAS_DMA) { 2979364Smckusick sc->sc_iostate |= VAS_WANT; 2989364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 2999364Smckusick } 3009364Smckusick sc->sc_iostate |= VAS_PIO; 3019364Smckusick sc->sc_tocnt = 0; 3029364Smckusick cmd = 0; 30341Sbill switch (vcmd) { 30441Sbill 30541Sbill case VPLOT: 30641Sbill /* Must turn on plot AND autostep modes. */ 3079364Smckusick if (vadopio(dev, VAPLOT)) 3089363Smckusick error = EIO; 3099364Smckusick cmd = VAAUTOSTEP; 31041Sbill break; 31141Sbill 31241Sbill case VPRINT: 3139364Smckusick cmd = VAPRINT; 31441Sbill break; 31541Sbill 31641Sbill case VPRINTPLOT: 3179364Smckusick cmd = VAPRINTPLOT; 31841Sbill break; 31941Sbill } 3203183Swnj sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 3219364Smckusick if (cmd && vadopio(dev, cmd)) 3229363Smckusick error = EIO; 3239364Smckusick sc->sc_iostate &= ~VAS_PIO; 3249364Smckusick if (sc->sc_iostate&VAS_WANT) { 3259364Smckusick sc->sc_iostate &= ~VAS_WANT; 3269364Smckusick wakeup((caddr_t)&sc->sc_iostate); 3279364Smckusick } 3289364Smckusick splx(s); 3299363Smckusick return (error); 33041Sbill } 33141Sbill 3329364Smckusick vadopio(dev, cmd) 3339364Smckusick dev_t dev; 3349364Smckusick int cmd; 3359364Smckusick { 3369364Smckusick register struct vadevice *vaaddr = 3379364Smckusick (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr; 3389364Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3399364Smckusick 3409364Smckusick sc->sc_info = 0; 3419364Smckusick vaaddr->vacsh = cmd; 3429364Smckusick while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0) 3439364Smckusick sleep((caddr_t)&sc->sc_info, VAPRI); 3449364Smckusick return (sc->sc_info&VA_ERROR); 3459364Smckusick } 3469364Smckusick 3473183Swnj vatimo(dev) 3483183Swnj dev_t dev; 34941Sbill { 3503183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3513183Swnj 3523183Swnj if (sc->sc_openf) 3539364Smckusick timeout(vatimo, (caddr_t)dev, hz/2); 3549364Smckusick if (++sc->sc_tocnt < 2) 3559364Smckusick return; 3569364Smckusick sc->sc_tocnt = 0; 3579364Smckusick dprintf("vatimo: calling vaintr\n"); 3589267Smckusick vaintr(dev); 35941Sbill } 36041Sbill 36141Sbill /*ARGSUSED*/ 36241Sbill vaintr(dev) 3633183Swnj dev_t dev; 36441Sbill { 3659364Smckusick register struct uba_ctlr *um; 3669364Smckusick struct vadevice *vaaddr; 3679364Smckusick struct buf *bp; 3689364Smckusick register int unit = VAUNIT(dev), e; 3699364Smckusick register struct va_softc *sc = &va_softc[unit]; 3703183Swnj 3719364Smckusick um = vaminfo[unit]; 3729364Smckusick vaaddr = (struct vadevice *)um->um_addr; 3739364Smckusick e = vaaddr->vacsw; 3749364Smckusick dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n", 3759364Smckusick um, e, um->um_tab.b_actf->b_active); 3769364Smckusick if ((e&(VA_DONE|VA_ERROR)) == 0) 3779364Smckusick return; 3789364Smckusick vaaddr->vacsl = 0; 3799364Smckusick if ((e&VA_ERROR) && (e&VA_NPRTIMO)) 3809364Smckusick printf("va%d: npr timeout\n", unit); 3819364Smckusick if (sc->sc_iostate&VAS_PIO) { 3829364Smckusick sc->sc_info = e; 3839364Smckusick wakeup((caddr_t)&sc->sc_info); 3849364Smckusick return; 3859364Smckusick } 3869364Smckusick if (um->um_tab.b_actf->b_active) { 3879364Smckusick bp = um->um_tab.b_actf->b_actf; 3889364Smckusick if (e&VA_ERROR) 3899364Smckusick bp->b_flags |= B_ERROR; 3909364Smckusick if (sc->sc_state&VPRINTPLOT) { 3919364Smckusick sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 3929364Smckusick vaaddr->vacsh = VAAUTOSTEP; 3939364Smckusick return; 3949364Smckusick } 3959364Smckusick ubadone(um); 3969364Smckusick um->um_tab.b_actf->b_active = 0; 3979364Smckusick um->um_tab.b_actf->b_actf = bp->b_forw; 3989364Smckusick bp->b_active = 0; 3999364Smckusick bp->b_errcnt = 0; 4009364Smckusick bp->b_resid = 0; 4019364Smckusick iodone(bp); 4029364Smckusick } 4039364Smckusick if (um->um_tab.b_actf->b_actf == 0) { 4049364Smckusick sc->sc_iostate &= ~VAS_DMA; 4059364Smckusick if (sc->sc_iostate&VAS_WANT) { 4069364Smckusick sc->sc_iostate &= ~VAS_WANT; 4079364Smckusick wakeup((caddr_t)&sc->sc_iostate); 4089364Smckusick } 4099364Smckusick return; 4109364Smckusick } 4119364Smckusick if (um->um_tab.b_actf->b_active == 0) 4129364Smckusick vastart(um); 41341Sbill } 41441Sbill 4153183Swnj vaclose(dev) 4163183Swnj dev_t dev; 41741Sbill { 4183183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 4193183Swnj register struct vadevice *vaaddr = 4203183Swnj (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 42141Sbill 4223183Swnj sc->sc_openf = 0; 4233183Swnj sc->sc_state = 0; 4249364Smckusick if (sc->sc_iostate != VAS_IDLE) 4259364Smckusick wakeup((caddr_t)&sc->sc_iostate); 4269364Smckusick sc->sc_iostate = VAS_IDLE; 4273183Swnj vaaddr->vacsl = 0; 4289364Smckusick vaaddr->vawc = 0; 42941Sbill } 430287Sbill 4313183Swnj vareset(uban) 4323183Swnj int uban; 433287Sbill { 4343183Swnj register int va11; 4359364Smckusick register struct uba_ctlr *um; 4363183Swnj register struct vadevice *vaaddr; 4379364Smckusick register struct va_softc *sc; 438287Sbill 4393183Swnj for (va11 = 0; va11 < NVA; va11++, sc++) { 4409364Smckusick if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban || 4419364Smckusick um->um_alive == 0) 4423183Swnj continue; 4439364Smckusick sc = &va_softc[um->um_ctlr]; 4449364Smckusick if (sc->sc_openf == 0) 4459364Smckusick continue; 4463183Swnj printf(" va%d", va11); 4479364Smckusick vaaddr = (struct vadevice *)um->um_addr; 4483183Swnj vaaddr->vacsl = VA_IENABLE; 4493183Swnj if (sc->sc_state & VPLOT) { 4503183Swnj vaaddr->vacsh = VAPLOT; 4513183Swnj DELAY(10000); 4523183Swnj vaaddr->vacsh = VAAUTOSTEP; 4533183Swnj } else if (sc->sc_state & VPRINTPLOT) 4543183Swnj vaaddr->vacsh = VPRINTPLOT; 4553183Swnj else 4563183Swnj vaaddr->vacsh = VAPRINTPLOT; 457287Sbill DELAY(10000); 4589392Smckusick sc->sc_iostate = VAS_IDLE; 4599392Smckusick um->um_tab.b_actf->b_active = 0; 4609392Smckusick um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0; 4619392Smckusick if (um->um_ubinfo) { 4629392Smckusick printf("<%d>", (um->um_ubinfo >> 28) & 0xf); 4639392Smckusick um->um_ubinfo = 0; 4649392Smckusick } 4659364Smckusick (void) vastart(um); 466287Sbill } 467287Sbill } 4686432Ssam 4696432Ssam vaselect() 4706432Ssam { 4719363Smckusick 4726432Ssam return (1); 4736432Ssam } 4741564Sbill #endif 475