1*1a7b9a25Ssam /* vp.c 4.22 82/12/17 */ 2b177495dSbill 316a40936Swnj #include "vp.h" 47d993dedSbill #if NVP > 0 57d993dedSbill /* 67d993dedSbill * Versatec matrix printer/plotter 77d993dedSbill * dma interface driver 83a2852a0Swnj * 93a2852a0Swnj * SETUP NOTES: 103a2852a0Swnj * Set up both print and plot interrupts to go through the same vector 113a2852a0Swnj * Give the address of the plcsr register in the config specification 127d993dedSbill */ 13*1a7b9a25Ssam #include "../machine/pte.h" 14*1a7b9a25Ssam 15b177495dSbill #include "../h/param.h" 16b177495dSbill #include "../h/dir.h" 17b177495dSbill #include "../h/user.h" 18b177495dSbill #include "../h/buf.h" 19b177495dSbill #include "../h/systm.h" 20b177495dSbill #include "../h/map.h" 212d065d45Swnj #include "../h/vcmd.h" 228ad11d3dSroot #include "../h/uio.h" 23b177495dSbill 24b1c32dd2Sroot #include "../vaxuba/ubavar.h" 25b1c32dd2Sroot #include "../vaxuba/ubareg.h" 26b1c32dd2Sroot 27b177495dSbill unsigned minvpph(); 28b177495dSbill 29b177495dSbill #define VPPRI (PZERO-1) 30b177495dSbill 312d065d45Swnj struct vpdevice { 32b177495dSbill short plbcr; 33f87bbbe0Swnj short pbxaddr; 34b177495dSbill short prbcr; 352d065d45Swnj u_short pbaddr; 36b177495dSbill short plcsr; 37b177495dSbill short plbuf; 38b177495dSbill short prcsr; 392d065d45Swnj u_short prbuf; 40b177495dSbill }; 41b177495dSbill 422d065d45Swnj #define VP_ERROR 0100000 432d065d45Swnj #define VP_DTCINTR 0040000 442d065d45Swnj #define VP_DMAACT 0020000 452d065d45Swnj #define VP_READY 0000200 462d065d45Swnj #define VP_IENABLE 0000100 472d065d45Swnj #define VP_TERMCOM 0000040 482d065d45Swnj #define VP_FFCOM 0000020 492d065d45Swnj #define VP_EOTCOM 0000010 502d065d45Swnj #define VP_CLRCOM 0000004 512d065d45Swnj #define VP_RESET 0000002 522d065d45Swnj #define VP_SPP 0000001 53b177495dSbill 542d065d45Swnj struct vp_softc { 552d065d45Swnj int sc_state; 562d065d45Swnj int sc_count; 572d065d45Swnj int sc_bufp; 582d065d45Swnj struct buf *sc_bp; 592d065d45Swnj int sc_ubinfo; 602d065d45Swnj } vp_softc[NVP]; 61b177495dSbill 622d065d45Swnj /* sc_state bits */ 632d065d45Swnj #define VPSC_BUSY 0001000 642d065d45Swnj #define VPSC_MODE 0000700 652d065d45Swnj #define VPSC_SPP 0000400 662d065d45Swnj #define VPSC_PLOT 0000200 672d065d45Swnj #define VPSC_PRINT 0000100 682d065d45Swnj #define VPSC_CMNDS 0000076 692d065d45Swnj #define VPSC_OPEN 0000001 70b177495dSbill 712d065d45Swnj struct uba_device *vpdinfo[NVP]; 72b177495dSbill 732d065d45Swnj #define VPUNIT(dev) (minor(dev)) 742d065d45Swnj 752d065d45Swnj struct buf rvpbuf[NVP]; 762d065d45Swnj 772d065d45Swnj int vpprobe(), vpattach(); 782d065d45Swnj struct uba_device *vpdinfo[NVP]; 792d065d45Swnj u_short vpstd[] = { 0777500, 0 }; 802d065d45Swnj struct uba_driver vpdriver = 812d065d45Swnj { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; 822d065d45Swnj 832d065d45Swnj vpprobe(reg) 842d065d45Swnj caddr_t reg; 852d065d45Swnj { 862d065d45Swnj register int br, cvec; /* value-result */ 872d065d45Swnj register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); 882d065d45Swnj 89acc57956Swnj #ifdef lint 90acc57956Swnj br = 0; cvec = br; br = cvec; 91acc57956Swnj vpintr(0); 92acc57956Swnj #endif 932d065d45Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 942d065d45Swnj vpaddr->pbaddr = 0; 952d065d45Swnj vpaddr->pbxaddr = 0; 963a2852a0Swnj vpaddr->prbcr = 1; 972d065d45Swnj DELAY(10000); 982d065d45Swnj vpaddr->prcsr = 0; 992fc095daSsam #if ERNIE || CAD || UCBVAX 1003a2852a0Swnj /* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */ 1013a2852a0Swnj if (cvec == 0200) { 1023a2852a0Swnj printf("vp reset vec from 200 to 174\n"); 1033a2852a0Swnj cvec = 0174; 1043a2852a0Swnj } 1053a2852a0Swnj #endif 1064c931468Skre return (sizeof (struct vpdevice)); 1072d065d45Swnj } 1082d065d45Swnj 1092d065d45Swnj /*ARGSUSED*/ 1102d065d45Swnj vpattach(ui) 1112d065d45Swnj struct uba_device *ui; 112b177495dSbill { 113b177495dSbill 1142d065d45Swnj ui->ui_addr -= 010; 1152d065d45Swnj ui->ui_physaddr -= 010; 1162d065d45Swnj } 1172d065d45Swnj 1182d065d45Swnj vpopen(dev) 1192d065d45Swnj dev_t dev; 1202d065d45Swnj { 1212d065d45Swnj register struct vp_softc *sc; 1222d065d45Swnj register struct vpdevice *vpaddr; 1232d065d45Swnj register struct uba_device *ui; 1242d065d45Swnj 1252d065d45Swnj if (VPUNIT(dev) >= NVP || 1262d065d45Swnj ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || 127855a1f9dSroot (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) 128855a1f9dSroot return (ENXIO); 1292d065d45Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 1302d065d45Swnj sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; 1312d065d45Swnj sc->sc_count = 0; 1322d065d45Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 1332d065d45Swnj vptimo(dev); 1342d065d45Swnj while (sc->sc_state & VPSC_CMNDS) { 135bea55ee8Sbill (void) spl4(); 1362d065d45Swnj if (vpwait(dev)) { 1372d065d45Swnj vpclose(dev); 138855a1f9dSroot return (EIO); 139b177495dSbill } 1402d065d45Swnj vpstart(dev); 141bea55ee8Sbill (void) spl0(); 142b177495dSbill } 143855a1f9dSroot return (0); 144b177495dSbill } 145b177495dSbill 146b177495dSbill vpstrategy(bp) 147b177495dSbill register struct buf *bp; 148b177495dSbill { 149b177495dSbill register int e; 1502d065d45Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; 1512d065d45Swnj register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; 1522d065d45Swnj register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; 153b177495dSbill 154bea55ee8Sbill (void) spl4(); 1552d065d45Swnj while (sc->sc_state & VPSC_BUSY) 1562d065d45Swnj sleep((caddr_t)sc, VPPRI); 1572d065d45Swnj sc->sc_state |= VPSC_BUSY; 1582d065d45Swnj sc->sc_bp = bp; 1592d065d45Swnj sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); 1602d065d45Swnj if (e = vpwait(bp->b_dev)) 161b177495dSbill goto brkout; 1622d065d45Swnj sc->sc_count = bp->b_bcount; 1632d065d45Swnj vpstart(bp->b_dev); 1642d065d45Swnj while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) 1652d065d45Swnj sleep((caddr_t)sc, VPPRI); 1662d065d45Swnj sc->sc_count = 0; 1672d065d45Swnj if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) 1682d065d45Swnj sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; 169bea55ee8Sbill (void) spl0(); 170b177495dSbill brkout: 1712d065d45Swnj ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); 1722d065d45Swnj sc->sc_state &= ~VPSC_BUSY; 1732d065d45Swnj sc->sc_bp = 0; 174b177495dSbill if (e) 175738f6459Sroot bp->b_flags |= B_ERROR; 176738f6459Sroot iodone(bp); 1772d065d45Swnj wakeup((caddr_t)sc); 178b177495dSbill } 179b177495dSbill 180b177495dSbill int vpblock = 16384; 181b177495dSbill 182b177495dSbill unsigned 183b177495dSbill minvpph(bp) 184b177495dSbill struct buf *bp; 185b177495dSbill { 186b177495dSbill 187b177495dSbill if (bp->b_bcount > vpblock) 188b177495dSbill bp->b_bcount = vpblock; 189b177495dSbill } 190b177495dSbill 191b177495dSbill /*ARGSUSED*/ 192731660efSroot vpwrite(dev, uio) 1932d065d45Swnj dev_t dev; 194731660efSroot struct uio *uio; 195b177495dSbill { 196b177495dSbill 197ea492ea6Sroot if (VPUNIT(dev) >= NVP) 198731660efSroot return (ENXIO); 199731660efSroot return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, 200731660efSroot minvpph, uio)); 201b177495dSbill } 202b177495dSbill 2032d065d45Swnj vpwait(dev) 2042d065d45Swnj dev_t dev; 205b177495dSbill { 2062d065d45Swnj register struct vpdevice *vpaddr = 2072d065d45Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2082d065d45Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2092d065d45Swnj register int e; 210b177495dSbill 2112d065d45Swnj for (;;) { 2122d065d45Swnj e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; 2132d065d45Swnj if (e & (VP_READY|VP_ERROR)) 2142d065d45Swnj break; 2152d065d45Swnj sleep((caddr_t)sc, VPPRI); 2162d065d45Swnj } 217738f6459Sroot /* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */ 2182d065d45Swnj return (e & VP_ERROR); 219b177495dSbill } 220b177495dSbill 2212d065d45Swnj vpstart(dev) 2222d065d45Swnj dev_t; 223b177495dSbill { 2242d065d45Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2252d065d45Swnj register struct vpdevice *vpaddr = 2262d065d45Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 2272d065d45Swnj short bit; 228b177495dSbill 2292d065d45Swnj if (sc->sc_count) { 2302d065d45Swnj vpaddr->pbaddr = sc->sc_ubinfo; 2312d065d45Swnj vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; 2322d065d45Swnj if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) 2332d065d45Swnj vpaddr->prbcr = sc->sc_count; 234b177495dSbill else 2352d065d45Swnj vpaddr->plbcr = sc->sc_count; 236b177495dSbill return; 237b177495dSbill } 238b177495dSbill for (bit = 1; bit != 0; bit <<= 1) 2392d065d45Swnj if (sc->sc_state&bit&VPSC_CMNDS) { 2402d065d45Swnj vpaddr->plcsr |= bit; 2412d065d45Swnj sc->sc_state &= ~bit; 242b177495dSbill return; 243b177495dSbill } 244b177495dSbill } 245b177495dSbill 246b177495dSbill /*ARGSUSED*/ 247b177495dSbill vpioctl(dev, cmd, addr, flag) 2482d065d45Swnj dev_t dev; 2492d065d45Swnj int cmd; 250b177495dSbill register caddr_t addr; 2512d065d45Swnj int flag; 252b177495dSbill { 253b177495dSbill register int m; 2542d065d45Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 2552d065d45Swnj register struct vpdevice *vpaddr = 2562d065d45Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 257b177495dSbill 258b177495dSbill switch (cmd) { 259b177495dSbill 2602d065d45Swnj case VGETSTATE: 2612d065d45Swnj (void) suword(addr, sc->sc_state); 262855a1f9dSroot break; 263b177495dSbill 2642d065d45Swnj case VSETSTATE: 265b177495dSbill m = fuword(addr); 266855a1f9dSroot if (m == -1) 267855a1f9dSroot return (EFAULT); 2682d065d45Swnj sc->sc_state = 2692d065d45Swnj (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS)); 270b177495dSbill break; 271b177495dSbill 272b177495dSbill default: 273855a1f9dSroot return (ENOTTY); 274b177495dSbill } 275bea55ee8Sbill (void) spl4(); 2762d065d45Swnj (void) vpwait(dev); 2772d065d45Swnj if (sc->sc_state&VPSC_SPP) 2782d065d45Swnj vpaddr->plcsr |= VP_SPP; 279b177495dSbill else 2802d065d45Swnj vpaddr->plcsr &= ~VP_SPP; 2812d065d45Swnj sc->sc_count = 0; 2822d065d45Swnj while (sc->sc_state & VPSC_CMNDS) { 2832d065d45Swnj (void) vpwait(dev); 2842d065d45Swnj vpstart(dev); 285b177495dSbill } 286bea55ee8Sbill (void) spl0(); 287855a1f9dSroot return (0); 288b177495dSbill } 289b177495dSbill 2902d065d45Swnj vptimo(dev) 2912d065d45Swnj dev_t dev; 292b177495dSbill { 2932d065d45Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 294b177495dSbill 2952d065d45Swnj if (sc->sc_state&VPSC_OPEN) 2962d065d45Swnj timeout(vptimo, (caddr_t)dev, hz/10); 2972d065d45Swnj vpintr(dev); 298b177495dSbill } 299b177495dSbill 300b177495dSbill /*ARGSUSED*/ 301b177495dSbill vpintr(dev) 3022d065d45Swnj dev_t dev; 303b177495dSbill { 3042d065d45Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 305b177495dSbill 3062d065d45Swnj wakeup((caddr_t)sc); 307b177495dSbill } 308b177495dSbill 3092d065d45Swnj vpclose(dev) 3102d065d45Swnj dev_t dev; 311b177495dSbill { 3122d065d45Swnj register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; 3132d065d45Swnj register struct vpdevice *vpaddr = 3142d065d45Swnj (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; 315b177495dSbill 3162d065d45Swnj sc->sc_state = 0; 3172d065d45Swnj sc->sc_count = 0; 3182d065d45Swnj vpaddr->plcsr = 0; 319b177495dSbill } 320bd93d430Sbill 3212d065d45Swnj vpreset(uban) 3222d065d45Swnj int uban; 323bd93d430Sbill { 3242d065d45Swnj register int vp11; 3252d065d45Swnj register struct uba_device *ui; 3262d065d45Swnj register struct vp_softc *sc = vp_softc; 3272d065d45Swnj register struct vpdevice *vpaddr; 328bd93d430Sbill 3292d065d45Swnj for (vp11 = 0; vp11 < NVP; vp11++, sc++) { 3302d065d45Swnj if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || 3312d065d45Swnj ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) 3322d065d45Swnj continue; 3332d065d45Swnj printf(" vp%d", vp11); 3342d065d45Swnj vpaddr = (struct vpdevice *)ui->ui_addr; 3352d065d45Swnj vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; 3362d065d45Swnj if ((sc->sc_state & VPSC_BUSY) == 0) 3372d065d45Swnj continue; 338855a1f9dSroot sc->sc_ubinfo = 0; 3392d065d45Swnj sc->sc_count = sc->sc_bp->b_bcount; 3402d065d45Swnj vpstart(sc->sc_bp->b_dev); 3412d065d45Swnj } 342bd93d430Sbill } 343bc3f32ddSsam 344bc3f32ddSsam vpselect() 345bc3f32ddSsam { 346bc3f32ddSsam return (1); 347bc3f32ddSsam } 3487d993dedSbill #endif 349