1*9392Smckusick /* va.c 4.18 82/11/28 */ 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 219364Smckusick int vadebug = 0; 229364Smckusick #define dprintf if(vadebug)printf 239364Smckusick 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 */ 529364Smckusick #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 { 689364Smckusick u_char sc_openf; /* exclusive open flag */ 699364Smckusick u_char sc_iostate; /* kind of I/O going on */ 709364Smckusick #define VAS_IDLE 0 /* no I/O, free */ 719364Smckusick #define VAS_PIO 1 /* programmed I/O */ 729364Smckusick #define VAS_DMA 2 /* DMA, block pio */ 739364Smckusick #define VAS_WANT 4 /* wakeup when iostate changes */ 749364Smckusick short sc_tocnt; /* time out counter */ 759364Smckusick short sc_info; /* csw passed from vaintr */ 769364Smckusick 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 839364Smckusick int vaprobe(), vaslave(), vaattach(), vadgo(); 843183Swnj struct uba_device *vadinfo[NVA]; 859364Smckusick struct uba_ctlr *vaminfo[NVA]; 869364Smckusick struct buf vabhdr[NVA]; 873183Swnj u_short vastd[] = { 0764000, 0 }; 883183Swnj struct uba_driver vadriver = 899364Smckusick { 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 1019364Smckusick #ifndef UCBVAX 1023183Swnj vaaddr->vacsl = VA_IENABLE; 1033183Swnj vaaddr->vaba = 0; 1043183Swnj vaaddr->vacsh = VAPLOT; 1059364Smckusick vaaddr->vacsl = VA_IENABLE|VA_DMAGO; 1069364Smckusick vaaddr->vawc = -1; 1079364Smckusick DELAY(10000); 1089361Smckusick vaaddr->vacsl = 0; 1099364Smckusick vaaddr->vawc = 0; 1109364Smckusick #else 1119364Smckusick br=0x14; 1129364Smckusick cvec=0170; 1139362Smckusick #endif 1149362Smckusick return (sizeof (struct vadevice)); 1153183Swnj } 1163183Swnj 1173183Swnj /*ARGSUSED*/ 1189364Smckusick vaslave(ui, reg) 1199364Smckusick struct uba_device *ui; 1209364Smckusick caddr_t reg; 1219364Smckusick { 1229364Smckusick 1239364Smckusick ui->ui_dk = 0; 1249364Smckusick return (ui->ui_unit <= 0); 1259364Smckusick } 1269364Smckusick 1279364Smckusick /*ARGSUSED*/ 1283183Swnj vaattach(ui) 1293183Swnj struct uba_device *ui; 1303183Swnj { 1313183Swnj 1329364Smckusick 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; 1429364Smckusick int unit = VAUNIT(dev); 1433183Swnj 144*9392Smckusick if (unit >= NVA || (sc = &va_softc[unit])->sc_openf || 145*9392Smckusick (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0) 1469363Smckusick return (ENXIO); 1473183Swnj vaaddr = (struct vadevice *)ui->ui_addr; 1483183Swnj sc->sc_openf = 1; 1493183Swnj vaaddr->vawc = 0; 1503183Swnj sc->sc_state = 0; 1519364Smckusick sc->sc_tocnt = 0; 1529364Smckusick sc->sc_iostate = VAS_IDLE; 1533183Swnj vaaddr->vacsl = VA_IENABLE; 1543183Swnj vatimo(dev); 1559363Smckusick error = vacmd(dev, VPRINT); 1569363Smckusick if (error) 1573183Swnj vaclose(dev); 1589363Smckusick return (error); 15941Sbill } 16041Sbill 16141Sbill vastrategy(bp) 16241Sbill register struct buf *bp; 16341Sbill { 1649364Smckusick register struct uba_device *ui; 1659364Smckusick register struct uba_ctlr *um; 1669364Smckusick int s; 16741Sbill 1689364Smckusick dprintf("vastrategy(%x)\n", bp); 1699364Smckusick ui = vadinfo[VAUNIT(bp->b_dev)]; 1709364Smckusick if (ui == 0 || ui->ui_alive == 0) { 1719364Smckusick bp->b_flags |= B_ERROR; 1729364Smckusick iodone(bp); 1739364Smckusick return; 17441Sbill } 1759364Smckusick s = spl4(); 1769364Smckusick um = ui->ui_mi; 1779364Smckusick bp->b_actf = NULL; 1789364Smckusick if (um->um_tab.b_actf->b_actf == NULL) 1799364Smckusick um->um_tab.b_actf->b_actf = bp; 1809364Smckusick else { 1819364Smckusick printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n", 1829364Smckusick bp, um->um_tab.b_actf->b_actf); 1839364Smckusick panic("vastrategy"); 1849364Smckusick um->um_tab.b_actf->b_actl->b_forw = bp; 1859364Smckusick } 1869364Smckusick um->um_tab.b_actf->b_actl = bp; 1879364Smckusick bp = um->um_tab.b_actf; 1889364Smckusick dprintf("vastrategy: bp=%x actf=%x active=%d\n", 1899364Smckusick bp, bp->b_actf, bp->b_active); 1909364Smckusick if (bp->b_actf && bp->b_active == 0) 1919364Smckusick (void) vastart(um); 1929364Smckusick splx(s); 19341Sbill } 19441Sbill 19541Sbill int vablock = 16384; 19641Sbill 19741Sbill unsigned 19841Sbill minvaph(bp) 1993183Swnj struct buf *bp; 20041Sbill { 2013183Swnj 20241Sbill if (bp->b_bcount > vablock) 20341Sbill bp->b_bcount = vablock; 20441Sbill } 20541Sbill 20641Sbill /*ARGSUSED*/ 2079362Smckusick vawrite(dev, uio) 2083183Swnj dev_t dev; 2099362Smckusick struct uio *uio; 21041Sbill { 2119267Smckusick 2129362Smckusick if (VAUNIT(dev) > NVA) 2139363Smckusick return (ENXIO); 2149363Smckusick return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, 2159363Smckusick minvaph, uio)); 21641Sbill } 21741Sbill 2189364Smckusick vastart(um) 2199364Smckusick register struct uba_ctlr *um; 22041Sbill { 2219364Smckusick struct buf *bp; 2229364Smckusick struct vadevice *vaaddr; 2239364Smckusick register struct va_softc *sc; 2249364Smckusick int unit; 22541Sbill 2269364Smckusick dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf); 2279364Smckusick if ((bp = um->um_tab.b_actf->b_actf) == NULL) 2289364Smckusick return; 2299364Smckusick unit = VAUNIT(bp->b_dev); 2309364Smckusick sc = &va_softc[unit]; 2319364Smckusick sc->sc_tocnt = 0; 2329364Smckusick while (sc->sc_iostate&VAS_PIO) { 2339364Smckusick sc->sc_iostate |= VAS_WANT; 2349364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 2359364Smckusick } 2369364Smckusick sc->sc_iostate |= VAS_DMA; 2379364Smckusick vaaddr = (struct vadevice *)um->um_addr; 2389364Smckusick vaaddr->vacsl = 0; 2399364Smckusick vaaddr->vawc = -(bp->b_bcount / 2); 2409364Smckusick um->um_cmd = VA_DMAGO | VA_IENABLE; 2419364Smckusick (void) ubago(vadinfo[unit]); 24241Sbill } 24341Sbill 2449364Smckusick vadgo(um) 2459364Smckusick register struct uba_ctlr *um; 24641Sbill { 2479364Smckusick register struct vadevice *vaaddr = (struct vadevice *)um->um_addr; 2489364Smckusick register struct buf *bp; 2493183Swnj 2509364Smckusick bp = um->um_tab.b_actf; 2519364Smckusick va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0; 2529364Smckusick bp->b_active++; 2539364Smckusick vaaddr->vaba = um->um_ubinfo; 2549364Smckusick vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd; 25541Sbill } 25641Sbill 25741Sbill /*ARGSUSED*/ 2589362Smckusick vaioctl(dev, cmd, data, flag) 2599362Smckusick register caddr_t data; 26041Sbill { 26141Sbill register int vcmd; 2623183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 26341Sbill 26441Sbill switch (cmd) { 26541Sbill 26641Sbill case VGETSTATE: 2679362Smckusick *(int *)data = sc->sc_state; 2689363Smckusick break; 26941Sbill 27041Sbill case VSETSTATE: 2719363Smckusick return (vacmd(dev, *(int *)data)); 2729363Smckusick break; 27341Sbill 27441Sbill default: 2759363Smckusick return (ENOTTY); 27641Sbill } 2779363Smckusick return (0); 27841Sbill } 27941Sbill 2803183Swnj vacmd(dev, vcmd) 2813183Swnj dev_t dev; 2823183Swnj int vcmd; 28341Sbill { 2843183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 2859363Smckusick int error = 0; 2869364Smckusick int s, cmd; 2873183Swnj 2889364Smckusick s = spl4(); 2899364Smckusick while (sc->sc_iostate&VAS_DMA) { 2909364Smckusick sc->sc_iostate |= VAS_WANT; 2919364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 2929364Smckusick } 2939364Smckusick sc->sc_iostate |= VAS_PIO; 2949364Smckusick sc->sc_tocnt = 0; 2959364Smckusick cmd = 0; 29641Sbill switch (vcmd) { 29741Sbill 29841Sbill case VPLOT: 29941Sbill /* Must turn on plot AND autostep modes. */ 3009364Smckusick if (vadopio(dev, VAPLOT)) 3019363Smckusick error = EIO; 3029364Smckusick cmd = VAAUTOSTEP; 30341Sbill break; 30441Sbill 30541Sbill case VPRINT: 3069364Smckusick cmd = VAPRINT; 30741Sbill break; 30841Sbill 30941Sbill case VPRINTPLOT: 3109364Smckusick cmd = VAPRINTPLOT; 31141Sbill break; 31241Sbill } 3133183Swnj sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd; 3149364Smckusick if (cmd && vadopio(dev, cmd)) 3159363Smckusick error = EIO; 3169364Smckusick sc->sc_iostate &= ~VAS_PIO; 3179364Smckusick if (sc->sc_iostate&VAS_WANT) { 3189364Smckusick sc->sc_iostate &= ~VAS_WANT; 3199364Smckusick wakeup((caddr_t)&sc->sc_iostate); 3209364Smckusick } 3219364Smckusick splx(s); 3229363Smckusick return (error); 32341Sbill } 32441Sbill 3259364Smckusick vadopio(dev, cmd) 3269364Smckusick dev_t dev; 3279364Smckusick int cmd; 3289364Smckusick { 3299364Smckusick register struct vadevice *vaaddr = 3309364Smckusick (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr; 3319364Smckusick register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3329364Smckusick 3339364Smckusick sc->sc_info = 0; 3349364Smckusick vaaddr->vacsh = cmd; 3359364Smckusick while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0) 3369364Smckusick sleep((caddr_t)&sc->sc_info, VAPRI); 3379364Smckusick return (sc->sc_info&VA_ERROR); 3389364Smckusick } 3399364Smckusick 3403183Swnj vatimo(dev) 3413183Swnj dev_t dev; 34241Sbill { 3433183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 3443183Swnj 3453183Swnj if (sc->sc_openf) 3469364Smckusick timeout(vatimo, (caddr_t)dev, hz/2); 3479364Smckusick if (++sc->sc_tocnt < 2) 3489364Smckusick return; 3499364Smckusick sc->sc_tocnt = 0; 3509364Smckusick dprintf("vatimo: calling vaintr\n"); 3519267Smckusick vaintr(dev); 35241Sbill } 35341Sbill 35441Sbill /*ARGSUSED*/ 35541Sbill vaintr(dev) 3563183Swnj dev_t dev; 35741Sbill { 3589364Smckusick register struct uba_ctlr *um; 3599364Smckusick struct vadevice *vaaddr; 3609364Smckusick struct buf *bp; 3619364Smckusick register int unit = VAUNIT(dev), e; 3629364Smckusick register struct va_softc *sc = &va_softc[unit]; 3633183Swnj 3649364Smckusick um = vaminfo[unit]; 3659364Smckusick vaaddr = (struct vadevice *)um->um_addr; 3669364Smckusick e = vaaddr->vacsw; 3679364Smckusick dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n", 3689364Smckusick um, e, um->um_tab.b_actf->b_active); 3699364Smckusick if ((e&(VA_DONE|VA_ERROR)) == 0) 3709364Smckusick return; 3719364Smckusick vaaddr->vacsl = 0; 3729364Smckusick if ((e&VA_ERROR) && (e&VA_NPRTIMO)) 3739364Smckusick printf("va%d: npr timeout\n", unit); 3749364Smckusick if (sc->sc_iostate&VAS_PIO) { 3759364Smckusick sc->sc_info = e; 3769364Smckusick wakeup((caddr_t)&sc->sc_info); 3779364Smckusick return; 3789364Smckusick } 3799364Smckusick if (um->um_tab.b_actf->b_active) { 3809364Smckusick bp = um->um_tab.b_actf->b_actf; 3819364Smckusick if (e&VA_ERROR) 3829364Smckusick bp->b_flags |= B_ERROR; 3839364Smckusick if (sc->sc_state&VPRINTPLOT) { 3849364Smckusick sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT; 3859364Smckusick vaaddr->vacsh = VAAUTOSTEP; 3869364Smckusick return; 3879364Smckusick } 3889364Smckusick ubadone(um); 3899364Smckusick um->um_tab.b_actf->b_active = 0; 3909364Smckusick um->um_tab.b_actf->b_actf = bp->b_forw; 3919364Smckusick bp->b_active = 0; 3929364Smckusick bp->b_errcnt = 0; 3939364Smckusick bp->b_resid = 0; 3949364Smckusick iodone(bp); 3959364Smckusick } 3969364Smckusick if (um->um_tab.b_actf->b_actf == 0) { 3979364Smckusick sc->sc_iostate &= ~VAS_DMA; 3989364Smckusick if (sc->sc_iostate&VAS_WANT) { 3999364Smckusick sc->sc_iostate &= ~VAS_WANT; 4009364Smckusick wakeup((caddr_t)&sc->sc_iostate); 4019364Smckusick } 4029364Smckusick return; 4039364Smckusick } 4049364Smckusick if (um->um_tab.b_actf->b_active == 0) 4059364Smckusick vastart(um); 40641Sbill } 40741Sbill 4083183Swnj vaclose(dev) 4093183Swnj dev_t dev; 41041Sbill { 4113183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 4123183Swnj register struct vadevice *vaaddr = 4133183Swnj (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr; 41441Sbill 4153183Swnj sc->sc_openf = 0; 4163183Swnj sc->sc_state = 0; 4179364Smckusick if (sc->sc_iostate != VAS_IDLE) 4189364Smckusick wakeup((caddr_t)&sc->sc_iostate); 4199364Smckusick sc->sc_iostate = VAS_IDLE; 4203183Swnj vaaddr->vacsl = 0; 4219364Smckusick vaaddr->vawc = 0; 42241Sbill } 423287Sbill 4243183Swnj vareset(uban) 4253183Swnj int uban; 426287Sbill { 4273183Swnj register int va11; 4289364Smckusick register struct uba_ctlr *um; 4293183Swnj register struct vadevice *vaaddr; 4309364Smckusick register struct va_softc *sc; 431287Sbill 4323183Swnj for (va11 = 0; va11 < NVA; va11++, sc++) { 4339364Smckusick if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban || 4349364Smckusick um->um_alive == 0) 4353183Swnj continue; 4369364Smckusick sc = &va_softc[um->um_ctlr]; 4379364Smckusick if (sc->sc_openf == 0) 4389364Smckusick continue; 4393183Swnj printf(" va%d", va11); 4409364Smckusick vaaddr = (struct vadevice *)um->um_addr; 4413183Swnj vaaddr->vacsl = VA_IENABLE; 4423183Swnj if (sc->sc_state & VPLOT) { 4433183Swnj vaaddr->vacsh = VAPLOT; 4443183Swnj DELAY(10000); 4453183Swnj vaaddr->vacsh = VAAUTOSTEP; 4463183Swnj } else if (sc->sc_state & VPRINTPLOT) 4473183Swnj vaaddr->vacsh = VPRINTPLOT; 4483183Swnj else 4493183Swnj vaaddr->vacsh = VAPRINTPLOT; 450287Sbill DELAY(10000); 451*9392Smckusick sc->sc_iostate = VAS_IDLE; 452*9392Smckusick um->um_tab.b_actf->b_active = 0; 453*9392Smckusick um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0; 454*9392Smckusick if (um->um_ubinfo) { 455*9392Smckusick printf("<%d>", (um->um_ubinfo >> 28) & 0xf); 456*9392Smckusick um->um_ubinfo = 0; 457*9392Smckusick } 4589364Smckusick (void) vastart(um); 459287Sbill } 460287Sbill } 4616432Ssam 4626432Ssam vaselect() 4636432Ssam { 4649363Smckusick 4656432Ssam return (1); 4666432Ssam } 4671564Sbill #endif 468