1*9784Ssam /* va.c 4.19 82/12/17 */ 241Sbill 31938Swnj #include "va.h" 41564Sbill #if NVA > 0 51564Sbill /* 63183Swnj * Varian printer plotter 71564Sbill */ 8*9784Ssam #include "../machine/pte.h" 9*9784Ssam 1041Sbill #include "../h/param.h" 1141Sbill #include "../h/dir.h" 1241Sbill #include "../h/user.h" 1341Sbill #include "../h/buf.h" 1441Sbill #include "../h/systm.h" 1541Sbill #include "../h/map.h" 1641Sbill #include "../h/vcmd.h" 179362Smckusick #include "../h/uio.h" 1841Sbill 199363Smckusick #include "../vaxuba/ubareg.h" 209363Smckusick #include "../vaxuba/ubavar.h" 219363Smckusick 229364Smckusick int vadebug = 0; 239364Smckusick #define dprintf if(vadebug)printf 249364Smckusick 25287Sbill unsigned minvaph(); 2641Sbill 2741Sbill #define VAPRI (PZERO-1) 2841Sbill 293183Swnj struct vadevice { 303183Swnj u_short vaba; /* buffer address */ 313183Swnj short vawc; /* word count (2's complement) */ 3241Sbill union { 333183Swnj short Vacsw; /* control status as word */ 343183Swnj struct { /* control status as bytes */ 35287Sbill char Vacsl; 36287Sbill char Vacsh; 37287Sbill } vacsr; 38287Sbill } vacs; 393183Swnj short vadata; /* programmed i/o data buffer */ 4041Sbill }; 4141Sbill 42287Sbill #define vacsw vacs.Vacsw 43287Sbill #define vacsh vacs.vacsr.Vacsh 44287Sbill #define vacsl vacs.vacsr.Vacsl 45287Sbill 46287Sbill /* vacsw bits */ 473183Swnj #define VA_ERROR 0100000 /* some error has occurred */ 483183Swnj #define VA_NPRTIMO 0001000 /* DMA timeout error */ 493183Swnj #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 503183Swnj #define VA_DONE 0000200 513183Swnj #define VA_IENABLE 0000100 /* interrupt enable */ 529362Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 539364Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 543183Swnj #define VA_SUPPLIESLOW 0000004 553183Swnj #define VA_BOTOFFORM 0000002 563183Swnj #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 5741Sbill 58287Sbill /* vacsh command bytes */ 593183Swnj #define VAPLOT 0000340 603183Swnj #define VAPRINT 0000100 613183Swnj #define VAPRINTPLOT 0000160 623183Swnj #define VAAUTOSTEP 0000244 633183Swnj #define VANOAUTOSTEP 0000045 643183Swnj #define VAFORMFEED 0000263 653183Swnj #define VASLEW 0000265 663183Swnj #define VASTEP 0000064 6741Sbill 683183Swnj struct va_softc { 699364Smckusick u_char sc_openf; /* exclusive open flag */ 709364Smckusick u_char sc_iostate; /* kind of I/O going on */ 719364Smckusick #define VAS_IDLE 0 /* no I/O, free */ 729364Smckusick #define VAS_PIO 1 /* programmed I/O */ 739364Smckusick #define VAS_DMA 2 /* DMA, block pio */ 749364Smckusick #define VAS_WANT 4 /* wakeup when iostate changes */ 759364Smckusick short sc_tocnt; /* time out counter */ 769364Smckusick short sc_info; /* csw passed from vaintr */ 779364Smckusick int sc_state; /* print/plot state of device */ 783183Swnj } va_softc[NVA]; 7941Sbill 803183Swnj #define VAUNIT(dev) (minor(dev)) 813183Swnj 823183Swnj struct buf rvabuf[NVA]; 833183Swnj 849364Smckusick int vaprobe(), vaslave(), vaattach(), vadgo(); 853183Swnj struct uba_device *vadinfo[NVA]; 869364Smckusick struct uba_ctlr *vaminfo[NVA]; 879364Smckusick struct buf vabhdr[NVA]; 883183Swnj u_short vastd[] = { 0764000, 0 }; 893183Swnj struct uba_driver vadriver = 909364Smckusick { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo }; 913183Swnj 923183Swnj vaprobe(reg) 933183Swnj caddr_t reg; 9441Sbill { 953183Swnj register int br, cvec; /* value-result */ 963183Swnj register struct vadevice *vaaddr = (struct vadevice *)reg; 9741Sbill 989267Smckusick #ifdef lint 999267Smckusick br = 0; cvec = br; br = cvec; 1009267Smckusick vaintr(0); 1019267Smckusick #endif 1029364Smckusick #ifndef UCBVAX 1033183Swnj vaaddr->vacsl = VA_IENABLE; 1043183Swnj vaaddr->vaba = 0; 1053183Swnj vaaddr->vacsh = VAPLOT; 1069364Smckusick vaaddr->vacsl = VA_IENABLE|VA_DMAGO; 1079364Smckusick vaaddr->vawc = -1; 1089364Smckusick DELAY(10000); 1099361Smckusick vaaddr->vacsl = 0; 1109364Smckusick vaaddr->vawc = 0; 1119364Smckusick #else 1129364Smckusick br=0x14; 1139364Smckusick cvec=0170; 1149362Smckusick #endif 1159362Smckusick return (sizeof (struct vadevice)); 1163183Swnj } 1173183Swnj 1183183Swnj /*ARGSUSED*/ 1199364Smckusick vaslave(ui, reg) 1209364Smckusick struct uba_device *ui; 1219364Smckusick caddr_t reg; 1229364Smckusick { 1239364Smckusick 1249364Smckusick ui->ui_dk = 0; 1259364Smckusick return (ui->ui_unit <= 0); 1269364Smckusick } 1279364Smckusick 1289364Smckusick /*ARGSUSED*/ 1293183Swnj vaattach(ui) 1303183Swnj struct uba_device *ui; 1313183Swnj { 1323183Swnj 1339364Smckusick ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit]; 1343183Swnj } 1353183Swnj 1363183Swnj vaopen(dev) 1373183Swnj dev_t dev; 1383183Swnj { 1393183Swnj register struct va_softc *sc; 1403183Swnj register struct vadevice *vaaddr; 1413183Swnj register struct uba_device *ui; 1429363Smckusick int error; 1439364Smckusick int unit = VAUNIT(dev); 1443183Swnj 1459392Smckusick if (unit >= NVA || (sc = &va_softc[unit])->sc_openf || 1469392Smckusick (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0) 1479363Smckusick return (ENXIO); 1483183Swnj vaaddr = (struct vadevice *)ui->ui_addr; 1493183Swnj sc->sc_openf = 1; 1503183Swnj vaaddr->vawc = 0; 1513183Swnj sc->sc_state = 0; 1529364Smckusick sc->sc_tocnt = 0; 1539364Smckusick sc->sc_iostate = VAS_IDLE; 1543183Swnj vaaddr->vacsl = VA_IENABLE; 1553183Swnj vatimo(dev); 1569363Smckusick error = vacmd(dev, VPRINT); 1579363Smckusick if (error) 1583183Swnj vaclose(dev); 1599363Smckusick return (error); 16041Sbill } 16141Sbill 16241Sbill vastrategy(bp) 16341Sbill register struct buf *bp; 16441Sbill { 1659364Smckusick register struct uba_device *ui; 1669364Smckusick register struct uba_ctlr *um; 1679364Smckusick int s; 16841Sbill 1699364Smckusick dprintf("vastrategy(%x)\n", bp); 1709364Smckusick ui = vadinfo[VAUNIT(bp->b_dev)]; 1719364Smckusick if (ui == 0 || ui->ui_alive == 0) { 1729364Smckusick bp->b_flags |= B_ERROR; 1739364Smckusick iodone(bp); 1749364Smckusick return; 17541Sbill } 1769364Smckusick s = spl4(); 1779364Smckusick um = ui->ui_mi; 1789364Smckusick bp->b_actf = NULL; 1799364Smckusick if (um->um_tab.b_actf->b_actf == NULL) 1809364Smckusick um->um_tab.b_actf->b_actf = bp; 1819364Smckusick else { 1829364Smckusick printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n", 1839364Smckusick bp, um->um_tab.b_actf->b_actf); 1849364Smckusick panic("vastrategy"); 1859364Smckusick um->um_tab.b_actf->b_actl->b_forw = bp; 1869364Smckusick } 1879364Smckusick um->um_tab.b_actf->b_actl = bp; 1889364Smckusick bp = um->um_tab.b_actf; 1899364Smckusick dprintf("vastrategy: bp=%x actf=%x active=%d\n", 1909364Smckusick bp, bp->b_actf, bp->b_active); 1919364Smckusick if (bp->b_actf && bp->b_active == 0) 1929364Smckusick (void) vastart(um); 1939364Smckusick splx(s); 19441Sbill } 19541Sbill 19641Sbill int vablock = 16384; 19741Sbill 19841Sbill unsigned 19941Sbill minvaph(bp) 2003183Swnj struct buf *bp; 20141Sbill { 2023183Swnj 20341Sbill if (bp->b_bcount > vablock) 20441Sbill bp->b_bcount = vablock; 20541Sbill } 20641Sbill 20741Sbill /*ARGSUSED*/ 2089362Smckusick vawrite(dev, uio) 2093183Swnj dev_t dev; 2109362Smckusick struct uio *uio; 21141Sbill { 2129267Smckusick 2139362Smckusick if (VAUNIT(dev) > NVA) 2149363Smckusick return (ENXIO); 2159363Smckusick return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, 2169363Smckusick minvaph, uio)); 21741Sbill } 21841Sbill 2199364Smckusick vastart(um) 2209364Smckusick register struct uba_ctlr *um; 22141Sbill { 2229364Smckusick struct buf *bp; 2239364Smckusick struct vadevice *vaaddr; 2249364Smckusick register struct va_softc *sc; 2259364Smckusick int unit; 22641Sbill 2279364Smckusick dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf); 2289364Smckusick if ((bp = um->um_tab.b_actf->b_actf) == NULL) 2299364Smckusick return; 2309364Smckusick unit = VAUNIT(bp->b_dev); 2319364Smckusick sc = &va_softc[unit]; 2329364Smckusick sc->sc_tocnt = 0; 2339364Smckusick while (sc->sc_iostate&VAS_PIO) { 2349364Smckusick sc->sc_iostate |= VAS_WANT; 2359364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 2369364Smckusick } 2379364Smckusick sc->sc_iostate |= VAS_DMA; 2389364Smckusick vaaddr = (struct vadevice *)um->um_addr; 2399364Smckusick vaaddr->vacsl = 0; 2409364Smckusick vaaddr->vawc = -(bp->b_bcount / 2); 2419364Smckusick um->um_cmd = VA_DMAGO | VA_IENABLE; 2429364Smckusick (void) ubago(vadinfo[unit]); 24341Sbill } 24441Sbill 2459364Smckusick vadgo(um) 2469364Smckusick register struct uba_ctlr *um; 24741Sbill { 2489364Smckusick register struct vadevice *vaaddr = (struct vadevice *)um->um_addr; 2499364Smckusick register struct buf *bp; 2503183Swnj 2519364Smckusick bp = um->um_tab.b_actf; 2529364Smckusick va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0; 2539364Smckusick bp->b_active++; 2549364Smckusick vaaddr->vaba = um->um_ubinfo; 2559364Smckusick vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd; 25641Sbill } 25741Sbill 25841Sbill /*ARGSUSED*/ 2599362Smckusick vaioctl(dev, cmd, data, flag) 2609362Smckusick register caddr_t data; 26141Sbill { 26241Sbill register int vcmd; 2633183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 26441Sbill 26541Sbill switch (cmd) { 26641Sbill 26741Sbill case VGETSTATE: 2689362Smckusick *(int *)data = sc->sc_state; 2699363Smckusick break; 27041Sbill 27141Sbill case VSETSTATE: 2729363Smckusick return (vacmd(dev, *(int *)data)); 2739363Smckusick break; 27441Sbill 27541Sbill default: 2769363Smckusick return (ENOTTY); 27741Sbill } 2789363Smckusick return (0); 27941Sbill } 28041Sbill 2813183Swnj vacmd(dev, vcmd) 2823183Swnj dev_t dev; 2833183Swnj int vcmd; 28441Sbill { 2853183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2869363Smckusick int error = 0; 2879364Smckusick int s, cmd; 2883183Swnj 2899364Smckusick s = spl4(); 2909364Smckusick while (sc->sc_iostate&VAS_DMA) { 2919364Smckusick sc->sc_iostate |= VAS_WANT; 2929364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 2939364Smckusick } 2949364Smckusick sc->sc_iostate |= VAS_PIO; 2959364Smckusick sc->sc_tocnt = 0; 2969364Smckusick cmd = 0; 29741Sbill switch (vcmd) { 29841Sbill 29941Sbill case VPLOT: 30041Sbill /* Must turn on plot AND autostep modes. */ 3019364Smckusick if (vadopio(dev, VAPLOT)) 3029363Smckusick error = EIO; 3039364Smckusick cmd = VAAUTOSTEP; 30441Sbill break; 30541Sbill 30641Sbill case VPRINT: 3079364Smckusick cmd = VAPRINT; 30841Sbill break; 30941Sbill 31041Sbill case VPRINTPLOT: 3119364Smckusick cmd = VAPRINTPLOT; 31241Sbill break; 31341Sbill } 3143183Swnj sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 3159364Smckusick if (cmd && vadopio(dev, cmd)) 3169363Smckusick error = EIO; 3179364Smckusick sc->sc_iostate &= ~VAS_PIO; 3189364Smckusick if (sc->sc_iostate&VAS_WANT) { 3199364Smckusick sc->sc_iostate &= ~VAS_WANT; 3209364Smckusick wakeup((caddr_t)&sc->sc_iostate); 3219364Smckusick } 3229364Smckusick splx(s); 3239363Smckusick return (error); 32441Sbill } 32541Sbill 3269364Smckusick vadopio(dev, cmd) 3279364Smckusick dev_t dev; 3289364Smckusick int cmd; 3299364Smckusick { 3309364Smckusick register struct vadevice *vaaddr = 3319364Smckusick (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr; 3329364Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3339364Smckusick 3349364Smckusick sc->sc_info = 0; 3359364Smckusick vaaddr->vacsh = cmd; 3369364Smckusick while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0) 3379364Smckusick sleep((caddr_t)&sc->sc_info, VAPRI); 3389364Smckusick return (sc->sc_info&VA_ERROR); 3399364Smckusick } 3409364Smckusick 3413183Swnj vatimo(dev) 3423183Swnj dev_t dev; 34341Sbill { 3443183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3453183Swnj 3463183Swnj if (sc->sc_openf) 3479364Smckusick timeout(vatimo, (caddr_t)dev, hz/2); 3489364Smckusick if (++sc->sc_tocnt < 2) 3499364Smckusick return; 3509364Smckusick sc->sc_tocnt = 0; 3519364Smckusick dprintf("vatimo: calling vaintr\n"); 3529267Smckusick vaintr(dev); 35341Sbill } 35441Sbill 35541Sbill /*ARGSUSED*/ 35641Sbill vaintr(dev) 3573183Swnj dev_t dev; 35841Sbill { 3599364Smckusick register struct uba_ctlr *um; 3609364Smckusick struct vadevice *vaaddr; 3619364Smckusick struct buf *bp; 3629364Smckusick register int unit = VAUNIT(dev), e; 3639364Smckusick register struct va_softc *sc = &va_softc[unit]; 3643183Swnj 3659364Smckusick um = vaminfo[unit]; 3669364Smckusick vaaddr = (struct vadevice *)um->um_addr; 3679364Smckusick e = vaaddr->vacsw; 3689364Smckusick dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n", 3699364Smckusick um, e, um->um_tab.b_actf->b_active); 3709364Smckusick if ((e&(VA_DONE|VA_ERROR)) == 0) 3719364Smckusick return; 3729364Smckusick vaaddr->vacsl = 0; 3739364Smckusick if ((e&VA_ERROR) && (e&VA_NPRTIMO)) 3749364Smckusick printf("va%d: npr timeout\n", unit); 3759364Smckusick if (sc->sc_iostate&VAS_PIO) { 3769364Smckusick sc->sc_info = e; 3779364Smckusick wakeup((caddr_t)&sc->sc_info); 3789364Smckusick return; 3799364Smckusick } 3809364Smckusick if (um->um_tab.b_actf->b_active) { 3819364Smckusick bp = um->um_tab.b_actf->b_actf; 3829364Smckusick if (e&VA_ERROR) 3839364Smckusick bp->b_flags |= B_ERROR; 3849364Smckusick if (sc->sc_state&VPRINTPLOT) { 3859364Smckusick sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 3869364Smckusick vaaddr->vacsh = VAAUTOSTEP; 3879364Smckusick return; 3889364Smckusick } 3899364Smckusick ubadone(um); 3909364Smckusick um->um_tab.b_actf->b_active = 0; 3919364Smckusick um->um_tab.b_actf->b_actf = bp->b_forw; 3929364Smckusick bp->b_active = 0; 3939364Smckusick bp->b_errcnt = 0; 3949364Smckusick bp->b_resid = 0; 3959364Smckusick iodone(bp); 3969364Smckusick } 3979364Smckusick if (um->um_tab.b_actf->b_actf == 0) { 3989364Smckusick sc->sc_iostate &= ~VAS_DMA; 3999364Smckusick if (sc->sc_iostate&VAS_WANT) { 4009364Smckusick sc->sc_iostate &= ~VAS_WANT; 4019364Smckusick wakeup((caddr_t)&sc->sc_iostate); 4029364Smckusick } 4039364Smckusick return; 4049364Smckusick } 4059364Smckusick if (um->um_tab.b_actf->b_active == 0) 4069364Smckusick vastart(um); 40741Sbill } 40841Sbill 4093183Swnj vaclose(dev) 4103183Swnj dev_t dev; 41141Sbill { 4123183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 4133183Swnj register struct vadevice *vaaddr = 4143183Swnj (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 41541Sbill 4163183Swnj sc->sc_openf = 0; 4173183Swnj sc->sc_state = 0; 4189364Smckusick if (sc->sc_iostate != VAS_IDLE) 4199364Smckusick wakeup((caddr_t)&sc->sc_iostate); 4209364Smckusick sc->sc_iostate = VAS_IDLE; 4213183Swnj vaaddr->vacsl = 0; 4229364Smckusick vaaddr->vawc = 0; 42341Sbill } 424287Sbill 4253183Swnj vareset(uban) 4263183Swnj int uban; 427287Sbill { 4283183Swnj register int va11; 4299364Smckusick register struct uba_ctlr *um; 4303183Swnj register struct vadevice *vaaddr; 4319364Smckusick register struct va_softc *sc; 432287Sbill 4333183Swnj for (va11 = 0; va11 < NVA; va11++, sc++) { 4349364Smckusick if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban || 4359364Smckusick um->um_alive == 0) 4363183Swnj continue; 4379364Smckusick sc = &va_softc[um->um_ctlr]; 4389364Smckusick if (sc->sc_openf == 0) 4399364Smckusick continue; 4403183Swnj printf(" va%d", va11); 4419364Smckusick vaaddr = (struct vadevice *)um->um_addr; 4423183Swnj vaaddr->vacsl = VA_IENABLE; 4433183Swnj if (sc->sc_state & VPLOT) { 4443183Swnj vaaddr->vacsh = VAPLOT; 4453183Swnj DELAY(10000); 4463183Swnj vaaddr->vacsh = VAAUTOSTEP; 4473183Swnj } else if (sc->sc_state & VPRINTPLOT) 4483183Swnj vaaddr->vacsh = VPRINTPLOT; 4493183Swnj else 4503183Swnj vaaddr->vacsh = VAPRINTPLOT; 451287Sbill DELAY(10000); 4529392Smckusick sc->sc_iostate = VAS_IDLE; 4539392Smckusick um->um_tab.b_actf->b_active = 0; 4549392Smckusick um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0; 4559392Smckusick if (um->um_ubinfo) { 4569392Smckusick printf("<%d>", (um->um_ubinfo >> 28) & 0xf); 4579392Smckusick um->um_ubinfo = 0; 4589392Smckusick } 4599364Smckusick (void) vastart(um); 460287Sbill } 461287Sbill } 4626432Ssam 4636432Ssam vaselect() 4646432Ssam { 4659363Smckusick 4666432Ssam return (1); 4676432Ssam } 4681564Sbill #endif 469