1*17085Sbloom /* va.c 6.2 84/08/29 */ 241Sbill 31938Swnj #include "va.h" 41564Sbill #if NVA > 0 51564Sbill /* 63183Swnj * Varian printer plotter 71564Sbill */ 89784Ssam #include "../machine/pte.h" 99784Ssam 10*17085Sbloom #include "param.h" 11*17085Sbloom #include "dir.h" 12*17085Sbloom #include "user.h" 13*17085Sbloom #include "buf.h" 14*17085Sbloom #include "systm.h" 15*17085Sbloom #include "map.h" 16*17085Sbloom #include "ioctl.h" 17*17085Sbloom #include "vcmd.h" 18*17085Sbloom #include "uio.h" 19*17085Sbloom #include "kernel.h" 2041Sbill 21*17085Sbloom #include "ubareg.h" 22*17085Sbloom #include "ubavar.h" 239363Smckusick 249364Smckusick int vadebug = 0; 259364Smckusick #define dprintf if(vadebug)printf 269364Smckusick 27287Sbill unsigned minvaph(); 2841Sbill 2941Sbill #define VAPRI (PZERO-1) 3041Sbill 313183Swnj struct vadevice { 323183Swnj u_short vaba; /* buffer address */ 333183Swnj short vawc; /* word count (2's complement) */ 3441Sbill union { 353183Swnj short Vacsw; /* control status as word */ 363183Swnj struct { /* control status as bytes */ 37287Sbill char Vacsl; 38287Sbill char Vacsh; 39287Sbill } vacsr; 40287Sbill } vacs; 413183Swnj short vadata; /* programmed i/o data buffer */ 4241Sbill }; 4341Sbill 44287Sbill #define vacsw vacs.Vacsw 45287Sbill #define vacsh vacs.vacsr.Vacsh 46287Sbill #define vacsl vacs.vacsr.Vacsl 47287Sbill 48287Sbill /* vacsw bits */ 493183Swnj #define VA_ERROR 0100000 /* some error has occurred */ 503183Swnj #define VA_NPRTIMO 0001000 /* DMA timeout error */ 513183Swnj #define VA_NOTREADY 0000400 /* something besides NPRTIMO */ 523183Swnj #define VA_DONE 0000200 533183Swnj #define VA_IENABLE 0000100 /* interrupt enable */ 549362Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 559364Smckusick #define VA_DMAGO 0000010 /* DMA go bit */ 563183Swnj #define VA_SUPPLIESLOW 0000004 573183Swnj #define VA_BOTOFFORM 0000002 583183Swnj #define VA_BYTEREVERSE 0000001 /* reverse byte order in words */ 5941Sbill 60287Sbill /* vacsh command bytes */ 613183Swnj #define VAPLOT 0000340 623183Swnj #define VAPRINT 0000100 633183Swnj #define VAPRINTPLOT 0000160 643183Swnj #define VAAUTOSTEP 0000244 653183Swnj #define VANOAUTOSTEP 0000045 663183Swnj #define VAFORMFEED 0000263 673183Swnj #define VASLEW 0000265 683183Swnj #define VASTEP 0000064 6941Sbill 703183Swnj struct va_softc { 719364Smckusick u_char sc_openf; /* exclusive open flag */ 729364Smckusick u_char sc_iostate; /* kind of I/O going on */ 739364Smckusick #define VAS_IDLE 0 /* no I/O, free */ 749364Smckusick #define VAS_PIO 1 /* programmed I/O */ 759364Smckusick #define VAS_DMA 2 /* DMA, block pio */ 769364Smckusick #define VAS_WANT 4 /* wakeup when iostate changes */ 779364Smckusick short sc_tocnt; /* time out counter */ 789364Smckusick short sc_info; /* csw passed from vaintr */ 799364Smckusick int sc_state; /* print/plot state of device */ 803183Swnj } va_softc[NVA]; 8141Sbill 823183Swnj #define VAUNIT(dev) (minor(dev)) 833183Swnj 843183Swnj struct buf rvabuf[NVA]; 853183Swnj 869364Smckusick int vaprobe(), vaslave(), vaattach(), vadgo(); 873183Swnj struct uba_device *vadinfo[NVA]; 889364Smckusick struct uba_ctlr *vaminfo[NVA]; 899364Smckusick struct buf vabhdr[NVA]; 903183Swnj u_short vastd[] = { 0764000, 0 }; 913183Swnj struct uba_driver vadriver = 929364Smckusick { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo }; 933183Swnj 943183Swnj vaprobe(reg) 953183Swnj caddr_t reg; 9641Sbill { 973183Swnj register int br, cvec; /* value-result */ 983183Swnj register struct vadevice *vaaddr = (struct vadevice *)reg; 9941Sbill 1009267Smckusick #ifdef lint 1019267Smckusick br = 0; cvec = br; br = cvec; 1029267Smckusick vaintr(0); 1039267Smckusick #endif 1049364Smckusick #ifndef UCBVAX 1053183Swnj vaaddr->vacsl = VA_IENABLE; 1063183Swnj vaaddr->vaba = 0; 1073183Swnj vaaddr->vacsh = VAPLOT; 1089364Smckusick vaaddr->vacsl = VA_IENABLE|VA_DMAGO; 1099364Smckusick vaaddr->vawc = -1; 1109364Smckusick DELAY(10000); 1119361Smckusick vaaddr->vacsl = 0; 1129364Smckusick vaaddr->vawc = 0; 1139364Smckusick #else 1149364Smckusick br=0x14; 1159364Smckusick cvec=0170; 1169362Smckusick #endif 1179362Smckusick return (sizeof (struct vadevice)); 1183183Swnj } 1193183Swnj 1203183Swnj /*ARGSUSED*/ 1219364Smckusick vaslave(ui, reg) 1229364Smckusick struct uba_device *ui; 1239364Smckusick caddr_t reg; 1249364Smckusick { 1259364Smckusick 1269364Smckusick ui->ui_dk = 0; 1279364Smckusick return (ui->ui_unit <= 0); 1289364Smckusick } 1299364Smckusick 1309364Smckusick /*ARGSUSED*/ 1313183Swnj vaattach(ui) 1323183Swnj struct uba_device *ui; 1333183Swnj { 1343183Swnj 1359364Smckusick ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit]; 1363183Swnj } 1373183Swnj 1383183Swnj vaopen(dev) 1393183Swnj dev_t dev; 1403183Swnj { 1413183Swnj register struct va_softc *sc; 1423183Swnj register struct vadevice *vaaddr; 1433183Swnj register struct uba_device *ui; 1449363Smckusick int error; 1459364Smckusick int unit = VAUNIT(dev); 1463183Swnj 1479392Smckusick if (unit >= NVA || (sc = &va_softc[unit])->sc_openf || 1489392Smckusick (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0) 1499363Smckusick return (ENXIO); 1503183Swnj vaaddr = (struct vadevice *)ui->ui_addr; 1513183Swnj sc->sc_openf = 1; 1523183Swnj vaaddr->vawc = 0; 1533183Swnj sc->sc_state = 0; 1549364Smckusick sc->sc_tocnt = 0; 1559364Smckusick sc->sc_iostate = VAS_IDLE; 1563183Swnj vaaddr->vacsl = VA_IENABLE; 1573183Swnj vatimo(dev); 1589363Smckusick error = vacmd(dev, VPRINT); 1599363Smckusick if (error) 1603183Swnj vaclose(dev); 1619363Smckusick return (error); 16241Sbill } 16341Sbill 16441Sbill vastrategy(bp) 16541Sbill register struct buf *bp; 16641Sbill { 1679364Smckusick register struct uba_device *ui; 1689364Smckusick register struct uba_ctlr *um; 1699364Smckusick int s; 17041Sbill 1719364Smckusick dprintf("vastrategy(%x)\n", bp); 1729364Smckusick ui = vadinfo[VAUNIT(bp->b_dev)]; 1739364Smckusick if (ui == 0 || ui->ui_alive == 0) { 1749364Smckusick bp->b_flags |= B_ERROR; 1759364Smckusick iodone(bp); 1769364Smckusick return; 17741Sbill } 1789364Smckusick s = spl4(); 1799364Smckusick um = ui->ui_mi; 1809364Smckusick bp->b_actf = NULL; 1819364Smckusick if (um->um_tab.b_actf->b_actf == NULL) 1829364Smckusick um->um_tab.b_actf->b_actf = bp; 1839364Smckusick else { 1849364Smckusick printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n", 1859364Smckusick bp, um->um_tab.b_actf->b_actf); 1869364Smckusick panic("vastrategy"); 1879364Smckusick um->um_tab.b_actf->b_actl->b_forw = bp; 1889364Smckusick } 1899364Smckusick um->um_tab.b_actf->b_actl = bp; 1909364Smckusick bp = um->um_tab.b_actf; 1919364Smckusick dprintf("vastrategy: bp=%x actf=%x active=%d\n", 1929364Smckusick bp, bp->b_actf, bp->b_active); 1939364Smckusick if (bp->b_actf && bp->b_active == 0) 1949364Smckusick (void) vastart(um); 1959364Smckusick splx(s); 19641Sbill } 19741Sbill 19841Sbill int vablock = 16384; 19941Sbill 20041Sbill unsigned 20141Sbill minvaph(bp) 2023183Swnj struct buf *bp; 20341Sbill { 2043183Swnj 20541Sbill if (bp->b_bcount > vablock) 20641Sbill bp->b_bcount = vablock; 20741Sbill } 20841Sbill 20941Sbill /*ARGSUSED*/ 2109362Smckusick vawrite(dev, uio) 2113183Swnj dev_t dev; 2129362Smckusick struct uio *uio; 21341Sbill { 2149267Smckusick 2159362Smckusick if (VAUNIT(dev) > NVA) 2169363Smckusick return (ENXIO); 2179363Smckusick return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, 2189363Smckusick minvaph, uio)); 21941Sbill } 22041Sbill 2219364Smckusick vastart(um) 2229364Smckusick register struct uba_ctlr *um; 22341Sbill { 2249364Smckusick struct buf *bp; 2259364Smckusick struct vadevice *vaaddr; 2269364Smckusick register struct va_softc *sc; 2279364Smckusick int unit; 22841Sbill 2299364Smckusick dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf); 2309364Smckusick if ((bp = um->um_tab.b_actf->b_actf) == NULL) 2319364Smckusick return; 2329364Smckusick unit = VAUNIT(bp->b_dev); 2339364Smckusick sc = &va_softc[unit]; 2349364Smckusick sc->sc_tocnt = 0; 2359364Smckusick while (sc->sc_iostate&VAS_PIO) { 2369364Smckusick sc->sc_iostate |= VAS_WANT; 2379364Smckusick sleep((caddr_t)&sc->sc_iostate, VAPRI); 2389364Smckusick } 2399364Smckusick sc->sc_iostate |= VAS_DMA; 2409364Smckusick vaaddr = (struct vadevice *)um->um_addr; 2419364Smckusick vaaddr->vacsl = 0; 2429364Smckusick vaaddr->vawc = -(bp->b_bcount / 2); 2439364Smckusick um->um_cmd = VA_DMAGO | VA_IENABLE; 2449364Smckusick (void) ubago(vadinfo[unit]); 24541Sbill } 24641Sbill 2479364Smckusick vadgo(um) 2489364Smckusick register struct uba_ctlr *um; 24941Sbill { 2509364Smckusick register struct vadevice *vaaddr = (struct vadevice *)um->um_addr; 2519364Smckusick register struct buf *bp; 2523183Swnj 2539364Smckusick bp = um->um_tab.b_actf; 2549364Smckusick va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0; 2559364Smckusick bp->b_active++; 2569364Smckusick vaaddr->vaba = um->um_ubinfo; 2579364Smckusick vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd; 25841Sbill } 25941Sbill 26041Sbill /*ARGSUSED*/ 2619362Smckusick vaioctl(dev, cmd, data, flag) 2629362Smckusick register caddr_t data; 26341Sbill { 2643183Swnj register struct va_softc *sc = &va_softc[VAUNIT(dev)]; 26541Sbill 26641Sbill switch (cmd) { 26741Sbill 26841Sbill case VGETSTATE: 2699362Smckusick *(int *)data = sc->sc_state; 2709363Smckusick break; 27141Sbill 27241Sbill case VSETSTATE: 2739363Smckusick return (vacmd(dev, *(int *)data)); 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