1*9364Smckusick /* va.c 4.17 82/11/27 */ 241Sbill 31938Swnj #include "va.h" 41564Sbill #if NVA > 0 51564Sbill /* 63183Swnj * Varian printer plotter 71564Sbill */ 841Sbill #include "../h/param.h" 941Sbill #include "../h/dir.h" 1041Sbill #include "../h/user.h" 1141Sbill #include "../h/buf.h" 1241Sbill #include "../h/systm.h" 1341Sbill #include "../h/map.h" 1441Sbill #include "../h/pte.h" 1541Sbill #include "../h/vcmd.h" 169362Smckusick #include "../h/uio.h" 1741Sbill 189363Smckusick #include "../vaxuba/ubareg.h" 199363Smckusick #include "../vaxuba/ubavar.h" 209363Smckusick 21*9364Smckusick int vadebug = 0; 22*9364Smckusick #define dprintf if(vadebug)printf 23*9364Smckusick 24287Sbill unsigned minvaph(); 2541Sbill 2641Sbill #define VAPRI (PZERO-1) 2741Sbill 283183Swnj struct vadevice { 293183Swnj u_short vaba; /* buffer address */ 303183Swnj short vawc; /* word count (2's complement) */ 3141Sbill union { 323183Swnj short Vacsw; /* control status as word */ 333183Swnj struct { /* control status as bytes */ 34287Sbill char Vacsl; 35287Sbill char Vacsh; 36287Sbill } vacsr; 37287Sbill } vacs; 383183Swnj short vadata; /* programmed i/o data buffer */ 3941Sbill }; 4041Sbill 41287Sbill #define vacsw vacs.Vacsw 42287Sbill #define vacsh vacs.vacsr.Vacsh 43287Sbill #define vacsl vacs.vacsr.Vacsl 44287Sbill 45287Sbill /* vacsw bits */ 463183Swnj #define VA_ERROR 0100000 /* some error has occurred */ 473183Swnj #define VA_NPRTIMO 0001000 /* DMA timeout error */ 483183Swnj #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 493183Swnj #define VA_DONE 0000200 503183Swnj #define VA_IENABLE 0000100 /* interrupt enable */ 519362Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 52*9364Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 533183Swnj #define VA_SUPPLIESLOW 0000004 543183Swnj #define VA_BOTOFFORM 0000002 553183Swnj #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 5641Sbill 57287Sbill /* vacsh command bytes */ 583183Swnj #define VAPLOT 0000340 593183Swnj #define VAPRINT 0000100 603183Swnj #define VAPRINTPLOT 0000160 613183Swnj #define VAAUTOSTEP 0000244 623183Swnj #define VANOAUTOSTEP 0000045 633183Swnj #define VAFORMFEED 0000263 643183Swnj #define VASLEW 0000265 653183Swnj #define VASTEP 0000064 6641Sbill 673183Swnj struct va_softc { 68*9364Smckusick u_char sc_openf; /* exclusive open flag */ 69*9364Smckusick u_char sc_iostate; /* kind of I/O going on */ 70*9364Smckusick #define VAS_IDLE 0 /* no I/O, free */ 71*9364Smckusick #define VAS_PIO 1 /* programmed I/O */ 72*9364Smckusick #define VAS_DMA 2 /* DMA, block pio */ 73*9364Smckusick #define VAS_WANT 4 /* wakeup when iostate changes */ 74*9364Smckusick short sc_tocnt; /* time out counter */ 75*9364Smckusick short sc_info; /* csw passed from vaintr */ 76*9364Smckusick int sc_state; /* print/plot state of device */ 773183Swnj } va_softc[NVA]; 7841Sbill 793183Swnj #define VAUNIT(dev) (minor(dev)) 803183Swnj 813183Swnj struct buf rvabuf[NVA]; 823183Swnj 83*9364Smckusick int vaprobe(), vaslave(), vaattach(), vadgo(); 843183Swnj struct uba_device *vadinfo[NVA]; 85*9364Smckusick struct uba_ctlr *vaminfo[NVA]; 86*9364Smckusick struct buf vabhdr[NVA]; 873183Swnj u_short vastd[] = { 0764000, 0 }; 883183Swnj struct uba_driver vadriver = 89*9364Smckusick { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo }; 903183Swnj 913183Swnj vaprobe(reg) 923183Swnj caddr_t reg; 9341Sbill { 943183Swnj register int br, cvec; /* value-result */ 953183Swnj register struct vadevice *vaaddr = (struct vadevice *)reg; 9641Sbill 979267Smckusick #ifdef lint 989267Smckusick br = 0; cvec = br; br = cvec; 999267Smckusick vaintr(0); 1009267Smckusick #endif 101*9364Smckusick #ifndef UCBVAX 1023183Swnj vaaddr->vacsl = VA_IENABLE; 1033183Swnj vaaddr->vaba = 0; 1043183Swnj vaaddr->vacsh = VAPLOT; 105*9364Smckusick vaaddr->vacsl = VA_IENABLE|VA_DMAGO; 106*9364Smckusick vaaddr->vawc = -1; 107*9364Smckusick DELAY(10000); 1089361Smckusick vaaddr->vacsl = 0; 109*9364Smckusick vaaddr->vawc = 0; 110*9364Smckusick #else 111*9364Smckusick br=0x14; 112*9364Smckusick cvec=0170; 1139362Smckusick #endif 1149362Smckusick return (sizeof (struct vadevice)); 1153183Swnj } 1163183Swnj 1173183Swnj /*ARGSUSED*/ 118*9364Smckusick vaslave(ui, reg) 119*9364Smckusick struct uba_device *ui; 120*9364Smckusick caddr_t reg; 121*9364Smckusick { 122*9364Smckusick 123*9364Smckusick ui->ui_dk = 0; 124*9364Smckusick return (ui->ui_unit <= 0); 125*9364Smckusick } 126*9364Smckusick 127*9364Smckusick /*ARGSUSED*/ 1283183Swnj vaattach(ui) 1293183Swnj struct uba_device *ui; 1303183Swnj { 1313183Swnj 132*9364Smckusick ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit]; 1333183Swnj } 1343183Swnj 1353183Swnj vaopen(dev) 1363183Swnj dev_t dev; 1373183Swnj { 1383183Swnj register struct va_softc *sc; 1393183Swnj register struct vadevice *vaaddr; 1403183Swnj register struct uba_device *ui; 1419363Smckusick int error; 142*9364Smckusick int unit = VAUNIT(dev); 1433183Swnj 1449363Smckusick (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) 1459363Smckusick return (ENXIO); 1463183Swnj vaaddr = (struct vadevice *)ui->ui_addr; 1473183Swnj sc->sc_openf = 1; 1483183Swnj vaaddr->vawc = 0; 1493183Swnj sc->sc_state = 0; 150*9364Smckusick sc->sc_tocnt = 0; 151*9364Smckusick sc->sc_iostate = VAS_IDLE; 1523183Swnj vaaddr->vacsl = VA_IENABLE; 1533183Swnj vatimo(dev); 1549363Smckusick error = vacmd(dev, VPRINT); 1559363Smckusick if (error) 1563183Swnj vaclose(dev); 1579363Smckusick return (error); 15841Sbill } 15941Sbill 16041Sbill vastrategy(bp) 16141Sbill register struct buf *bp; 16241Sbill { 163*9364Smckusick register struct uba_device *ui; 164*9364Smckusick register struct uba_ctlr *um; 165*9364Smckusick int s; 16641Sbill 167*9364Smckusick dprintf("vastrategy(%x)\n", bp); 168*9364Smckusick ui = vadinfo[VAUNIT(bp->b_dev)]; 169*9364Smckusick if (ui == 0 || ui->ui_alive == 0) { 170*9364Smckusick bp->b_flags |= B_ERROR; 171*9364Smckusick iodone(bp); 172*9364Smckusick return; 17341Sbill } 174*9364Smckusick s = spl4(); 175*9364Smckusick um = ui->ui_mi; 176*9364Smckusick bp->b_actf = NULL; 177*9364Smckusick if (um->um_tab.b_actf->b_actf == NULL) 178*9364Smckusick um->um_tab.b_actf->b_actf = bp; 179*9364Smckusick else { 180*9364Smckusick printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n", 181*9364Smckusick bp, um->um_tab.b_actf->b_actf); 182*9364Smckusick panic("vastrategy"); 183*9364Smckusick um->um_tab.b_actf->b_actl->b_forw = bp; 184*9364Smckusick } 185*9364Smckusick um->um_tab.b_actf->b_actl = bp; 186*9364Smckusick bp = um->um_tab.b_actf; 187*9364Smckusick dprintf("vastrategy: bp=%x actf=%x active=%d\n", 188*9364Smckusick bp, bp->b_actf, bp->b_active); 189*9364Smckusick if (bp->b_actf && bp->b_active == 0) 190*9364Smckusick (void) vastart(um); 191*9364Smckusick splx(s); 19241Sbill } 19341Sbill 19441Sbill int vablock = 16384; 19541Sbill 19641Sbill unsigned 19741Sbill minvaph(bp) 1983183Swnj struct buf *bp; 19941Sbill { 2003183Swnj 20141Sbill if (bp->b_bcount > vablock) 20241Sbill bp->b_bcount = vablock; 20341Sbill } 20441Sbill 20541Sbill /*ARGSUSED*/ 2069362Smckusick vawrite(dev, uio) 2073183Swnj dev_t dev; 2089362Smckusick struct uio *uio; 20941Sbill { 2109267Smckusick 2119362Smckusick if (VAUNIT(dev) > NVA) 2129363Smckusick return (ENXIO); 2139363Smckusick return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, 2149363Smckusick minvaph, uio)); 21541Sbill } 21641Sbill 217*9364Smckusick vastart(um) 218*9364Smckusick register struct uba_ctlr *um; 21941Sbill { 220*9364Smckusick struct buf *bp; 221*9364Smckusick struct vadevice *vaaddr; 222*9364Smckusick register struct va_softc *sc; 223*9364Smckusick int unit; 22441Sbill 225*9364Smckusick dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf); 226*9364Smckusick if ((bp = um->um_tab.b_actf->b_actf) == NULL) 227*9364Smckusick return; 228*9364Smckusick unit = VAUNIT(bp->b_dev); 229*9364Smckusick sc = &va_softc[unit]; 230*9364Smckusick sc->sc_tocnt = 0; 231*9364Smckusick while (sc->sc_iostate&VAS_PIO) { 232*9364Smckusick sc->sc_iostate |= VAS_WANT; 233*9364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 234*9364Smckusick } 235*9364Smckusick sc->sc_iostate |= VAS_DMA; 236*9364Smckusick vaaddr = (struct vadevice *)um->um_addr; 237*9364Smckusick vaaddr->vacsl = 0; 238*9364Smckusick vaaddr->vawc = -(bp->b_bcount / 2); 239*9364Smckusick um->um_cmd = VA_DMAGO | VA_IENABLE; 240*9364Smckusick (void) ubago(vadinfo[unit]); 24141Sbill } 24241Sbill 243*9364Smckusick vadgo(um) 244*9364Smckusick register struct uba_ctlr *um; 24541Sbill { 246*9364Smckusick register struct vadevice *vaaddr = (struct vadevice *)um->um_addr; 247*9364Smckusick register struct buf *bp; 2483183Swnj 249*9364Smckusick bp = um->um_tab.b_actf; 250*9364Smckusick va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0; 251*9364Smckusick bp->b_active++; 252*9364Smckusick vaaddr->vaba = um->um_ubinfo; 253*9364Smckusick vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd; 25441Sbill } 25541Sbill 25641Sbill /*ARGSUSED*/ 2579362Smckusick vaioctl(dev, cmd, data, flag) 2589362Smckusick register caddr_t data; 25941Sbill { 26041Sbill register int vcmd; 2613183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 26241Sbill 26341Sbill switch (cmd) { 26441Sbill 26541Sbill case VGETSTATE: 2669362Smckusick *(int *)data = sc->sc_state; 2679363Smckusick break; 26841Sbill 26941Sbill case VSETSTATE: 2709363Smckusick return (vacmd(dev, *(int *)data)); 2719363Smckusick break; 27241Sbill 27341Sbill default: 2749363Smckusick return (ENOTTY); 27541Sbill } 2769363Smckusick return (0); 27741Sbill } 27841Sbill 2793183Swnj vacmd(dev, vcmd) 2803183Swnj dev_t dev; 2813183Swnj int vcmd; 28241Sbill { 2833183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2849363Smckusick int error = 0; 285*9364Smckusick int s, cmd; 2863183Swnj 287*9364Smckusick s = spl4(); 288*9364Smckusick while (sc->sc_iostate&VAS_DMA) { 289*9364Smckusick sc->sc_iostate |= VAS_WANT; 290*9364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 291*9364Smckusick } 292*9364Smckusick sc->sc_iostate |= VAS_PIO; 293*9364Smckusick sc->sc_tocnt = 0; 294*9364Smckusick cmd = 0; 29541Sbill switch (vcmd) { 29641Sbill 29741Sbill case VPLOT: 29841Sbill /* Must turn on plot AND autostep modes. */ 299*9364Smckusick if (vadopio(dev, VAPLOT)) 3009363Smckusick error = EIO; 301*9364Smckusick cmd = VAAUTOSTEP; 30241Sbill break; 30341Sbill 30441Sbill case VPRINT: 305*9364Smckusick cmd = VAPRINT; 30641Sbill break; 30741Sbill 30841Sbill case VPRINTPLOT: 309*9364Smckusick cmd = VAPRINTPLOT; 31041Sbill break; 31141Sbill } 3123183Swnj sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 313*9364Smckusick if (cmd && vadopio(dev, cmd)) 3149363Smckusick error = EIO; 315*9364Smckusick sc->sc_iostate &= ~VAS_PIO; 316*9364Smckusick if (sc->sc_iostate&VAS_WANT) { 317*9364Smckusick sc->sc_iostate &= ~VAS_WANT; 318*9364Smckusick wakeup((caddr_t)&sc->sc_iostate); 319*9364Smckusick } 320*9364Smckusick splx(s); 3219363Smckusick return (error); 32241Sbill } 32341Sbill 324*9364Smckusick vadopio(dev, cmd) 325*9364Smckusick dev_t dev; 326*9364Smckusick int cmd; 327*9364Smckusick { 328*9364Smckusick register struct vadevice *vaaddr = 329*9364Smckusick (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr; 330*9364Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 331*9364Smckusick 332*9364Smckusick sc->sc_info = 0; 333*9364Smckusick vaaddr->vacsh = cmd; 334*9364Smckusick while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0) 335*9364Smckusick sleep((caddr_t)&sc->sc_info, VAPRI); 336*9364Smckusick return (sc->sc_info&VA_ERROR); 337*9364Smckusick } 338*9364Smckusick 3393183Swnj vatimo(dev) 3403183Swnj dev_t dev; 34141Sbill { 3423183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3433183Swnj 3443183Swnj if (sc->sc_openf) 345*9364Smckusick timeout(vatimo, (caddr_t)dev, hz/2); 346*9364Smckusick if (++sc->sc_tocnt < 2) 347*9364Smckusick return; 348*9364Smckusick sc->sc_tocnt = 0; 349*9364Smckusick dprintf("vatimo: calling vaintr\n"); 3509267Smckusick vaintr(dev); 35141Sbill } 35241Sbill 35341Sbill /*ARGSUSED*/ 35441Sbill vaintr(dev) 3553183Swnj dev_t dev; 35641Sbill { 357*9364Smckusick register struct uba_ctlr *um; 358*9364Smckusick struct vadevice *vaaddr; 359*9364Smckusick struct buf *bp; 360*9364Smckusick register int unit = VAUNIT(dev), e; 361*9364Smckusick register struct va_softc *sc = &va_softc[unit]; 3623183Swnj 363*9364Smckusick um = vaminfo[unit]; 364*9364Smckusick vaaddr = (struct vadevice *)um->um_addr; 365*9364Smckusick e = vaaddr->vacsw; 366*9364Smckusick dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n", 367*9364Smckusick um, e, um->um_tab.b_actf->b_active); 368*9364Smckusick if ((e&(VA_DONE|VA_ERROR)) == 0) 369*9364Smckusick return; 370*9364Smckusick vaaddr->vacsl = 0; 371*9364Smckusick if ((e&VA_ERROR) && (e&VA_NPRTIMO)) 372*9364Smckusick printf("va%d: npr timeout\n", unit); 373*9364Smckusick if (sc->sc_iostate&VAS_PIO) { 374*9364Smckusick sc->sc_info = e; 375*9364Smckusick wakeup((caddr_t)&sc->sc_info); 376*9364Smckusick return; 377*9364Smckusick } 378*9364Smckusick if (um->um_tab.b_actf->b_active) { 379*9364Smckusick bp = um->um_tab.b_actf->b_actf; 380*9364Smckusick if (e&VA_ERROR) 381*9364Smckusick bp->b_flags |= B_ERROR; 382*9364Smckusick if (sc->sc_state&VPRINTPLOT) { 383*9364Smckusick sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 384*9364Smckusick vaaddr->vacsh = VAAUTOSTEP; 385*9364Smckusick return; 386*9364Smckusick } 387*9364Smckusick ubadone(um); 388*9364Smckusick um->um_tab.b_actf->b_active = 0; 389*9364Smckusick um->um_tab.b_actf->b_actf = bp->b_forw; 390*9364Smckusick bp->b_active = 0; 391*9364Smckusick bp->b_errcnt = 0; 392*9364Smckusick bp->b_resid = 0; 393*9364Smckusick iodone(bp); 394*9364Smckusick } 395*9364Smckusick if (um->um_tab.b_actf->b_actf == 0) { 396*9364Smckusick sc->sc_iostate &= ~VAS_DMA; 397*9364Smckusick if (sc->sc_iostate&VAS_WANT) { 398*9364Smckusick sc->sc_iostate &= ~VAS_WANT; 399*9364Smckusick wakeup((caddr_t)&sc->sc_iostate); 400*9364Smckusick } 401*9364Smckusick return; 402*9364Smckusick } 403*9364Smckusick if (um->um_tab.b_actf->b_active == 0) 404*9364Smckusick vastart(um); 40541Sbill } 40641Sbill 4073183Swnj vaclose(dev) 4083183Swnj dev_t dev; 40941Sbill { 4103183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 4113183Swnj register struct vadevice *vaaddr = 4123183Swnj (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 41341Sbill 4143183Swnj sc->sc_openf = 0; 4153183Swnj sc->sc_state = 0; 416*9364Smckusick if (sc->sc_iostate != VAS_IDLE) 417*9364Smckusick wakeup((caddr_t)&sc->sc_iostate); 418*9364Smckusick sc->sc_iostate = VAS_IDLE; 4193183Swnj vaaddr->vacsl = 0; 420*9364Smckusick vaaddr->vawc = 0; 42141Sbill } 422287Sbill 4233183Swnj vareset(uban) 4243183Swnj int uban; 425287Sbill { 4263183Swnj register int va11; 427*9364Smckusick register struct uba_ctlr *um; 4283183Swnj register struct vadevice *vaaddr; 429*9364Smckusick register struct va_softc *sc; 430287Sbill 4313183Swnj for (va11 = 0; va11 < NVA; va11++, sc++) { 432*9364Smckusick if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban || 433*9364Smckusick um->um_alive == 0) 4343183Swnj continue; 435*9364Smckusick sc = &va_softc[um->um_ctlr]; 436*9364Smckusick if (sc->sc_openf == 0) 437*9364Smckusick continue; 4383183Swnj printf(" va%d", va11); 439*9364Smckusick vaaddr = (struct vadevice *)um->um_addr; 4403183Swnj vaaddr->vacsl = VA_IENABLE; 4413183Swnj if (sc->sc_state & VPLOT) { 4423183Swnj vaaddr->vacsh = VAPLOT; 4433183Swnj DELAY(10000); 4443183Swnj vaaddr->vacsh = VAAUTOSTEP; 4453183Swnj } else if (sc->sc_state & VPRINTPLOT) 4463183Swnj vaaddr->vacsh = VPRINTPLOT; 4473183Swnj else 4483183Swnj vaaddr->vacsh = VAPRINTPLOT; 449287Sbill DELAY(10000); 450*9364Smckusick (void) vastart(um); 451287Sbill } 452287Sbill } 4536432Ssam 4546432Ssam vaselect() 4556432Ssam { 4569363Smckusick 4576432Ssam return (1); 4586432Ssam } 4591564Sbill #endif 460