1*9267Smckusick /* va.c 4.15 82/11/16 */ 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" 153183Swnj #include "../h/ubareg.h" 163183Swnj #include "../h/ubavar.h" 1741Sbill #include "../h/vcmd.h" 1841Sbill 19*9267Smckusick int vadebug = 1; 20*9267Smckusick #define dprintf if(vadebug)printf 21*9267Smckusick 22287Sbill unsigned minvaph(); 2341Sbill 2441Sbill #define VAPRI (PZERO-1) 2541Sbill 263183Swnj struct vadevice { 273183Swnj u_short vaba; /* buffer address */ 283183Swnj short vawc; /* word count (2's complement) */ 2941Sbill union { 303183Swnj short Vacsw; /* control status as word */ 313183Swnj struct { /* control status as bytes */ 32287Sbill char Vacsl; 33287Sbill char Vacsh; 34287Sbill } vacsr; 35287Sbill } vacs; 363183Swnj short vadata; /* programmed i/o data buffer */ 3741Sbill }; 3841Sbill 39287Sbill #define vacsw vacs.Vacsw 40287Sbill #define vacsh vacs.vacsr.Vacsh 41287Sbill #define vacsl vacs.vacsr.Vacsl 42287Sbill 43287Sbill /* vacsw bits */ 443183Swnj #define VA_ERROR 0100000 /* some error has occurred */ 453183Swnj #define VA_NPRTIMO 0001000 /* DMA timeout error */ 463183Swnj #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 473183Swnj #define VA_DONE 0000200 483183Swnj #define VA_IENABLE 0000100 /* interrupt enable */ 49*9267Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 503183Swnj #define VA_SUPPLIESLOW 0000004 513183Swnj #define VA_BOTOFFORM 0000002 523183Swnj #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 5341Sbill 54287Sbill /* vacsh command bytes */ 553183Swnj #define VAPLOT 0000340 563183Swnj #define VAPRINT 0000100 573183Swnj #define VAPRINTPLOT 0000160 583183Swnj #define VAAUTOSTEP 0000244 593183Swnj #define VANOAUTOSTEP 0000045 603183Swnj #define VAFORMFEED 0000263 613183Swnj #define VASLEW 0000265 623183Swnj #define VASTEP 0000064 6341Sbill 643183Swnj struct va_softc { 65*9267Smckusick u_char sc_openf; /* exclusive open flag */ 66*9267Smckusick u_char sc_iostate; /* kind of I/O going on */ 67*9267Smckusick #define VAS_IDLE 0 /* no I/O, free */ 68*9267Smckusick #define VAS_PIO 1 /* programmed I/O */ 69*9267Smckusick #define VAS_DMA 2 /* DMA, block pio */ 70*9267Smckusick #define VAS_WANT 4 /* wakeup when iostate changes */ 71*9267Smckusick short sc_tocnt; /* time out counter */ 72*9267Smckusick short sc_info; /* csw passed from vaintr */ 73*9267Smckusick int sc_state; /* print/plot state of device */ 743183Swnj } va_softc[NVA]; 7541Sbill 763183Swnj #define VAUNIT(dev) (minor(dev)) 773183Swnj 783183Swnj struct buf rvabuf[NVA]; 793183Swnj 80*9267Smckusick int vaprobe(), vaslave(), vaattach(), vadgo(); 813183Swnj struct uba_device *vadinfo[NVA]; 82*9267Smckusick struct uba_ctlr *vaminfo[NVA]; 833183Swnj u_short vastd[] = { 0764000, 0 }; 843183Swnj struct uba_driver vadriver = 85*9267Smckusick { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo }; 863183Swnj 873183Swnj vaprobe(reg) 883183Swnj caddr_t reg; 8941Sbill { 903183Swnj register int br, cvec; /* value-result */ 913183Swnj register struct vadevice *vaaddr = (struct vadevice *)reg; 9241Sbill 93*9267Smckusick #ifdef lint 94*9267Smckusick br = 0; cvec = br; br = cvec; 95*9267Smckusick vaintr(0); 96*9267Smckusick #endif 979266Smckusick #ifndef UCBVAX 983183Swnj vaaddr->vacsl = VA_IENABLE; 993183Swnj vaaddr->vaba = 0; 1003183Swnj vaaddr->vacsh = VAPLOT; 1019266Smckusick vaaddr->vacsl = VA_IENABLE|VA_DMAGO; 1023183Swnj vaaddr->vawc = -1; 1039266Smckusick DELAY(10000); 1043183Swnj vaaddr->vacsl = 0; 1059266Smckusick vaaddr->vawc = 0; 1069266Smckusick #else 1079266Smckusick br=0x14; 1089266Smckusick cvec=0170; 1099266Smckusick #endif 1103183Swnj } 1113183Swnj 1123183Swnj /*ARGSUSED*/ 113*9267Smckusick vaslave(ui, reg) 114*9267Smckusick struct uba_device *ui; 115*9267Smckusick caddr_t reg; 116*9267Smckusick { 117*9267Smckusick 118*9267Smckusick ui->ui_dk = 0; 119*9267Smckusick return (ui->ui_unit <= 0); 120*9267Smckusick } 121*9267Smckusick 122*9267Smckusick /*ARGSUSED*/ 1233183Swnj vaattach(ui) 1243183Swnj struct uba_device *ui; 1253183Swnj { 1263183Swnj 1273183Swnj } 1283183Swnj 1293183Swnj vaopen(dev) 1303183Swnj dev_t dev; 1313183Swnj { 1323183Swnj register struct va_softc *sc; 1333183Swnj register struct vadevice *vaaddr; 1343183Swnj register struct uba_device *ui; 135*9267Smckusick int unit = VAUNIT(dev); 1363183Swnj 137*9267Smckusick if (unit >= NVA || (sc = &va_softc[unit])->sc_openf || 138*9267Smckusick (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0) { 13941Sbill u.u_error = ENXIO; 14041Sbill return; 14141Sbill } 1423183Swnj vaaddr = (struct vadevice *)ui->ui_addr; 1433183Swnj sc->sc_openf = 1; 1443183Swnj vaaddr->vawc = 0; 1453183Swnj sc->sc_state = 0; 1469266Smckusick sc->sc_tocnt = 0; 147*9267Smckusick sc->sc_iostate = VAS_IDLE; 1483183Swnj vaaddr->vacsl = VA_IENABLE; 1493183Swnj vatimo(dev); 1503183Swnj vacmd(dev, VPRINT); 15141Sbill if (u.u_error) 1523183Swnj vaclose(dev); 15341Sbill } 15441Sbill 15541Sbill vastrategy(bp) 15641Sbill register struct buf *bp; 15741Sbill { 158*9267Smckusick register struct uba_device *ui; 159*9267Smckusick register struct uba_ctlr *um; 160*9267Smckusick int s; 16141Sbill 162*9267Smckusick dprintf("vastrategy(%x)\n", bp); 163*9267Smckusick ui = vadinfo[VAUNIT(bp->b_dev)]; 164*9267Smckusick if (ui == 0 || ui->ui_alive == 0) { 165*9267Smckusick bp->b_flags |= B_ERROR; 166*9267Smckusick iodone(bp); 167*9267Smckusick return; 16841Sbill } 169*9267Smckusick s = spl4(); 170*9267Smckusick um = ui->ui_mi; 171*9267Smckusick if (um->um_tab.b_actf == NULL) 172*9267Smckusick um->um_tab.b_actf = bp; 173*9267Smckusick else 174*9267Smckusick um->um_tab.b_actl->b_forw = bp; 175*9267Smckusick um->um_tab.b_actl = bp; 176*9267Smckusick bp = &um->um_tab; 177*9267Smckusick dprintf("vastrategy: bp=%x actf=%x active=%x\n", bp, bp->b_actf, bp->b_active); 178*9267Smckusick if (bp->b_actf && bp->b_active == 0) 179*9267Smckusick (void) vastart(um); 180*9267Smckusick splx(s); 18141Sbill } 18241Sbill 18341Sbill int vablock = 16384; 18441Sbill 18541Sbill unsigned 18641Sbill minvaph(bp) 1873183Swnj struct buf *bp; 18841Sbill { 1893183Swnj 19041Sbill if (bp->b_bcount > vablock) 19141Sbill bp->b_bcount = vablock; 19241Sbill } 19341Sbill 19441Sbill /*ARGSUSED*/ 19541Sbill vawrite(dev) 1963183Swnj dev_t dev; 19741Sbill { 198*9267Smckusick 1993183Swnj physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph); 20041Sbill } 20141Sbill 202*9267Smckusick vastart(um) 203*9267Smckusick register struct uba_ctlr *um; 20441Sbill { 205*9267Smckusick struct buf *bp; 206*9267Smckusick struct vadevice *vaaddr; 207*9267Smckusick register struct va_softc *sc; 208*9267Smckusick int unit; 20941Sbill 210*9267Smckusick dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf); 211*9267Smckusick if ((bp = um->um_tab.b_actf) == NULL) 212*9267Smckusick return; 213*9267Smckusick um->um_tab.b_active++; 214*9267Smckusick unit = VAUNIT(bp->b_dev); 215*9267Smckusick sc = &va_softc[unit]; 216*9267Smckusick while (sc->sc_iostate&VAS_PIO) { 217*9267Smckusick sc->sc_iostate |= VAS_WANT; 218*9267Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 2199266Smckusick } 220*9267Smckusick sc->sc_iostate |= VAS_DMA; 221*9267Smckusick vaaddr = (struct vadevice *)um->um_addr; 222*9267Smckusick vaaddr->vacsl = 0; 223*9267Smckusick vaaddr->vawc = -(bp->b_bcount / 2); 224*9267Smckusick um->um_cmd = VA_DMAGO | VA_IENABLE; 225*9267Smckusick (void) ubago(vadinfo[unit]); 22641Sbill } 22741Sbill 228*9267Smckusick vadgo(um) 229*9267Smckusick register struct uba_ctlr *um; 23041Sbill { 231*9267Smckusick register struct vadevice *vaaddr = (struct vadevice *)um->um_addr; 232*9267Smckusick u_short i; 233*9267Smckusick short j; 2343183Swnj 235*9267Smckusick i = um->um_ubinfo; 236*9267Smckusick j = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd; 237*9267Smckusick dprintf("vadgo: vaba 0x%x, vacsl 0%o, vawc 0x%x\n", i, j, vaaddr->vawc); 238*9267Smckusick vaaddr->vaba = um->um_ubinfo; 239*9267Smckusick vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd; 24041Sbill } 24141Sbill 24241Sbill /*ARGSUSED*/ 24341Sbill vaioctl(dev, cmd, addr, flag) 24441Sbill register caddr_t addr; 24541Sbill { 24641Sbill register int vcmd; 2473183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 24841Sbill 24941Sbill switch (cmd) { 25041Sbill 25141Sbill case VGETSTATE: 2523183Swnj (void) suword(addr, sc->sc_state); 25341Sbill return; 25441Sbill 25541Sbill case VSETSTATE: 25641Sbill vcmd = fuword(addr); 25741Sbill if (vcmd == -1) { 25841Sbill u.u_error = EFAULT; 25941Sbill return; 26041Sbill } 2613183Swnj vacmd(dev, vcmd); 26241Sbill return; 26341Sbill 26441Sbill default: 2653183Swnj u.u_error = ENOTTY; 26641Sbill return; 26741Sbill } 26841Sbill } 26941Sbill 2703183Swnj vacmd(dev, vcmd) 2713183Swnj dev_t dev; 2723183Swnj int vcmd; 27341Sbill { 2743183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 275*9267Smckusick int s, cmd; 2763183Swnj 277*9267Smckusick s = spl4(); 278*9267Smckusick while (sc->sc_iostate&VAS_DMA) { 279*9267Smckusick sc->sc_iostate |= VAS_WANT; 280*9267Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 281*9267Smckusick } 282*9267Smckusick sc->sc_iostate |= VAS_PIO; 2839266Smckusick sc->sc_tocnt = 0; 284*9267Smckusick cmd = 0; 28541Sbill switch (vcmd) { 28641Sbill 28741Sbill case VPLOT: 28841Sbill /* Must turn on plot AND autostep modes. */ 289*9267Smckusick if (vadopio(dev, VAPLOT)) 29041Sbill u.u_error = EIO; 291*9267Smckusick cmd = VAAUTOSTEP; 29241Sbill break; 29341Sbill 29441Sbill case VPRINT: 295*9267Smckusick cmd = VAPRINT; 29641Sbill break; 29741Sbill 29841Sbill case VPRINTPLOT: 299*9267Smckusick cmd = VAPRINTPLOT; 30041Sbill break; 30141Sbill } 3023183Swnj sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 303*9267Smckusick if (cmd && vadopio(dev, cmd)) 30441Sbill u.u_error = EIO; 305*9267Smckusick sc->sc_iostate &= ~VAS_PIO; 306*9267Smckusick if (sc->sc_iostate&VAS_WANT) { 307*9267Smckusick sc->sc_iostate &= ~VAS_WANT; 308*9267Smckusick wakeup((caddr_t)&sc->sc_iostate); 309*9267Smckusick } 310*9267Smckusick splx(s); 31141Sbill } 31241Sbill 313*9267Smckusick vadopio(dev, cmd) 314*9267Smckusick dev_t dev; 315*9267Smckusick int cmd; 316*9267Smckusick { 317*9267Smckusick register struct vadevice *vaaddr = 318*9267Smckusick (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr; 319*9267Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 320*9267Smckusick 321*9267Smckusick sc->sc_info = 0; 322*9267Smckusick vaaddr->vacsh = cmd; 323*9267Smckusick while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0) 324*9267Smckusick sleep((caddr_t)&sc->sc_info, VAPRI); 325*9267Smckusick return (sc->sc_info&VA_ERROR); 326*9267Smckusick } 327*9267Smckusick 3283183Swnj vatimo(dev) 3293183Swnj dev_t dev; 33041Sbill { 3313183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3323183Swnj 3333183Swnj if (sc->sc_openf) 3349266Smckusick timeout(vatimo, (caddr_t)dev, hz/2); 335*9267Smckusick if (++sc->sc_tocnt < 2) 336*9267Smckusick return; 337*9267Smckusick sc->sc_tocnt = 0; 338*9267Smckusick dprintf("vatimo: calling vaintr\n"); 339*9267Smckusick vaintr(dev); 34041Sbill } 34141Sbill 34241Sbill /*ARGSUSED*/ 34341Sbill vaintr(dev) 3443183Swnj dev_t dev; 34541Sbill { 346*9267Smckusick register struct uba_ctlr *um; 347*9267Smckusick struct vadevice *vaaddr; 348*9267Smckusick struct buf *bp; 349*9267Smckusick register int unit = VAUNIT(dev), e; 350*9267Smckusick register struct va_softc *sc = &va_softc[unit]; 3513183Swnj 352*9267Smckusick um = vaminfo[unit]; 353*9267Smckusick vaaddr = (struct vadevice *)um->um_addr; 354*9267Smckusick e = vaaddr->vacsw; 355*9267Smckusick dprintf("vaintr: um=%x, e=%x\n", um, e); 356*9267Smckusick if ((e&(VA_DONE|VA_ERROR)) == 0) 357*9267Smckusick return; 358*9267Smckusick vaaddr->vacsl = 0; 359*9267Smckusick if ((e&VA_ERROR) && (e&VA_NPRTIMO)) 360*9267Smckusick printf("va%d: npr timeout\n", unit); 361*9267Smckusick if (sc->sc_iostate&VAS_PIO) { 362*9267Smckusick sc->sc_info = e; 363*9267Smckusick wakeup((caddr_t)&sc->sc_info); 364*9267Smckusick return; 365*9267Smckusick } 366*9267Smckusick if (um->um_tab.b_active) { 367*9267Smckusick bp = um->um_tab.b_actf; 368*9267Smckusick if (e&VA_ERROR) 369*9267Smckusick bp->b_flags |= B_ERROR; 370*9267Smckusick if (sc->sc_state&VPRINTPLOT) { 371*9267Smckusick sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 372*9267Smckusick vaaddr->vacsh = VAAUTOSTEP; 373*9267Smckusick return; 374*9267Smckusick } 375*9267Smckusick } 376*9267Smckusick ubadone(um); 377*9267Smckusick if (um->um_tab.b_active) { 378*9267Smckusick um->um_tab.b_active = 0; 379*9267Smckusick um->um_tab.b_actf = bp->b_forw; 380*9267Smckusick bp->b_active = 0; 381*9267Smckusick bp->b_errcnt = 0; 382*9267Smckusick bp->b_resid = 0; 383*9267Smckusick iodone(bp); 384*9267Smckusick } 385*9267Smckusick if (um->um_tab.b_actf == 0) { 386*9267Smckusick sc->sc_iostate &= ~VAS_DMA; 387*9267Smckusick if (sc->sc_iostate&VAS_WANT) { 388*9267Smckusick sc->sc_iostate &= ~VAS_WANT; 389*9267Smckusick wakeup((caddr_t)&sc->sc_iostate); 390*9267Smckusick } 391*9267Smckusick return; 392*9267Smckusick } 393*9267Smckusick if (um->um_tab.b_active == 0) 394*9267Smckusick vastart(um); 39541Sbill } 39641Sbill 3973183Swnj vaclose(dev) 3983183Swnj dev_t dev; 39941Sbill { 4003183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 4013183Swnj register struct vadevice *vaaddr = 4023183Swnj (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 40341Sbill 4043183Swnj sc->sc_openf = 0; 4053183Swnj sc->sc_state = 0; 406*9267Smckusick if (sc->sc_iostate != VAS_IDLE) 407*9267Smckusick wakeup((caddr_t)&sc->sc_iostate); 408*9267Smckusick sc->sc_iostate = VAS_IDLE; 4093183Swnj vaaddr->vacsl = 0; 4109266Smckusick vaaddr->vawc = 0; 41141Sbill } 412287Sbill 4133183Swnj vareset(uban) 4143183Swnj int uban; 415287Sbill { 4163183Swnj register int va11; 417*9267Smckusick register struct uba_ctlr *um; 4183183Swnj register struct vadevice *vaaddr; 419*9267Smckusick register struct va_softc *sc; 420287Sbill 4213183Swnj for (va11 = 0; va11 < NVA; va11++, sc++) { 422*9267Smckusick if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban || 423*9267Smckusick um->um_alive == 0) 4243183Swnj continue; 425*9267Smckusick sc = &va_softc[um->um_ctlr]; 426*9267Smckusick if (sc->sc_openf == 0) 427*9267Smckusick continue; 4283183Swnj printf(" va%d", va11); 429*9267Smckusick vaaddr = (struct vadevice *)um->um_addr; 4303183Swnj vaaddr->vacsl = VA_IENABLE; 4313183Swnj if (sc->sc_state & VPLOT) { 4323183Swnj vaaddr->vacsh = VAPLOT; 4333183Swnj DELAY(10000); 4343183Swnj vaaddr->vacsh = VAAUTOSTEP; 4353183Swnj } else if (sc->sc_state & VPRINTPLOT) 4363183Swnj vaaddr->vacsh = VPRINTPLOT; 4373183Swnj else 4383183Swnj vaaddr->vacsh = VAPRINTPLOT; 439287Sbill DELAY(10000); 440*9267Smckusick sc->sc_iostate = VAS_IDLE; 441*9267Smckusick um->um_tab.b_active = 0; 442*9267Smckusick um->um_tab.b_actf = um->um_tab.b_actl = 0; 443*9267Smckusick if (um->um_ubinfo) { 444*9267Smckusick printf("<%d>", (um->um_ubinfo >> 28) & 0xf); 445*9267Smckusick ubadone(um); 4463183Swnj } 447*9267Smckusick (void) vastart(um); 448287Sbill } 449287Sbill } 4506432Ssam 4516432Ssam vaselect() 4526432Ssam { 4536432Ssam return (1); 4546432Ssam } 4551564Sbill #endif 456