|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)vp.c 7.1 (Berkeley) 6/5/86 ! 7: */ ! 8: ! 9: #include "vp.h" ! 10: #if NVP > 0 ! 11: /* ! 12: * Versatec matrix printer/plotter ! 13: * dma interface driver ! 14: * ! 15: * SETUP NOTES: ! 16: * Set up both print and plot interrupts to go through the same vector ! 17: * (or kludge probe to reset second vector to first; ! 18: * default 174/200 is already handled). ! 19: * Give the address of the plcsr register in the config specification ! 20: */ ! 21: #include "../machine/pte.h" ! 22: ! 23: #include "param.h" ! 24: #include "dir.h" ! 25: #include "user.h" ! 26: #include "buf.h" ! 27: #include "systm.h" ! 28: #include "map.h" ! 29: #include "ioctl.h" ! 30: #include "vcmd.h" ! 31: #include "uio.h" ! 32: #include "kernel.h" ! 33: ! 34: #include "ubavar.h" ! 35: #include "ubareg.h" ! 36: ! 37: unsigned minvpph(); ! 38: ! 39: #define VPPRI (PZERO-1) ! 40: ! 41: struct vpdevice { ! 42: short plbcr; ! 43: short pbxaddr; ! 44: short prbcr; ! 45: u_short pbaddr; ! 46: short plcsr; ! 47: short plbuf; ! 48: short prcsr; ! 49: u_short prbuf; ! 50: }; ! 51: ! 52: #define VP_ERROR 0100000 ! 53: #define VP_DTCINTR 0040000 ! 54: #define VP_DMAACT 0020000 ! 55: #define VP_READY 0000200 ! 56: #define VP_IENABLE 0000100 ! 57: #define VP_TERMCOM 0000040 ! 58: #define VP_FFCOM 0000020 ! 59: #define VP_EOTCOM 0000010 ! 60: #define VP_CLRCOM 0000004 ! 61: #define VP_RESET 0000002 ! 62: #define VP_SPP 0000001 ! 63: ! 64: struct vp_softc { ! 65: int sc_state; ! 66: int sc_count; ! 67: int sc_bufp; ! 68: struct buf *sc_bp; ! 69: int sc_ubinfo; ! 70: } vp_softc[NVP]; ! 71: ! 72: /* sc_state bits */ ! 73: #define VPSC_BUSY 0001000 ! 74: #define VPSC_MODE 0000700 ! 75: #define VPSC_SPP 0000400 ! 76: #define VPSC_PLOT 0000200 ! 77: #define VPSC_PRINT 0000100 ! 78: #define VPSC_CMNDS 0000076 ! 79: #define VPSC_OPEN 0000001 ! 80: ! 81: struct uba_device *vpdinfo[NVP]; ! 82: ! 83: #define VPUNIT(dev) (minor(dev)) ! 84: ! 85: struct buf rvpbuf[NVP]; ! 86: ! 87: int vpprobe(), vpattach(); ! 88: struct uba_device *vpdinfo[NVP]; ! 89: u_short vpstd[] = { 0777500, 0 }; ! 90: struct uba_driver vpdriver = ! 91: { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo }; ! 92: ! 93: vpprobe(reg) ! 94: caddr_t reg; ! 95: { ! 96: register int br, cvec; /* value-result */ ! 97: register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010); ! 98: ! 99: #ifdef lint ! 100: br = 0; cvec = br; br = cvec; ! 101: vpintr(0); ! 102: #endif ! 103: vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; ! 104: vpaddr->pbaddr = 0; ! 105: vpaddr->pbxaddr = 0; ! 106: vpaddr->prbcr = 1; ! 107: DELAY(10000); ! 108: vpaddr->prcsr = 0; ! 109: /* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */ ! 110: if (cvec == 0200) { ! 111: printf("vp reset vec from 200 to 174\n"); ! 112: cvec = 0174; ! 113: } ! 114: return (sizeof (struct vpdevice)); ! 115: } ! 116: ! 117: /*ARGSUSED*/ ! 118: vpattach(ui) ! 119: struct uba_device *ui; ! 120: { ! 121: ! 122: ui->ui_addr -= 010; ! 123: ui->ui_physaddr -= 010; ! 124: } ! 125: ! 126: vpopen(dev) ! 127: dev_t dev; ! 128: { ! 129: register struct vp_softc *sc; ! 130: register struct vpdevice *vpaddr; ! 131: register struct uba_device *ui; ! 132: ! 133: if (VPUNIT(dev) >= NVP || ! 134: ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) || ! 135: (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) ! 136: return (ENXIO); ! 137: vpaddr = (struct vpdevice *)ui->ui_addr; ! 138: sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET; ! 139: sc->sc_count = 0; ! 140: vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; ! 141: vptimo(dev); ! 142: while (sc->sc_state & VPSC_CMNDS) { ! 143: (void) spl4(); ! 144: if (vpwait(dev)) { ! 145: vpclose(dev); ! 146: return (EIO); ! 147: } ! 148: vpstart(dev); ! 149: (void) spl0(); ! 150: } ! 151: return (0); ! 152: } ! 153: ! 154: vpstrategy(bp) ! 155: register struct buf *bp; ! 156: { ! 157: register int e; ! 158: register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)]; ! 159: register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)]; ! 160: register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr; ! 161: ! 162: (void) spl4(); ! 163: while (sc->sc_state & VPSC_BUSY) ! 164: sleep((caddr_t)sc, VPPRI); ! 165: sc->sc_state |= VPSC_BUSY; ! 166: sc->sc_bp = bp; ! 167: sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP); ! 168: if (e = vpwait(bp->b_dev)) ! 169: goto brkout; ! 170: sc->sc_count = bp->b_bcount; ! 171: vpstart(bp->b_dev); ! 172: while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT) ! 173: sleep((caddr_t)sc, VPPRI); ! 174: sc->sc_count = 0; ! 175: if ((sc->sc_state&VPSC_MODE) == VPSC_SPP) ! 176: sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT; ! 177: (void) spl0(); ! 178: brkout: ! 179: ubarelse(ui->ui_ubanum, &sc->sc_ubinfo); ! 180: sc->sc_state &= ~VPSC_BUSY; ! 181: sc->sc_bp = 0; ! 182: if (e) ! 183: bp->b_flags |= B_ERROR; ! 184: iodone(bp); ! 185: wakeup((caddr_t)sc); ! 186: } ! 187: ! 188: int vpblock = 16384; ! 189: ! 190: unsigned ! 191: minvpph(bp) ! 192: struct buf *bp; ! 193: { ! 194: ! 195: if (bp->b_bcount > vpblock) ! 196: bp->b_bcount = vpblock; ! 197: } ! 198: ! 199: /*ARGSUSED*/ ! 200: vpwrite(dev, uio) ! 201: dev_t dev; ! 202: struct uio *uio; ! 203: { ! 204: ! 205: if (VPUNIT(dev) >= NVP) ! 206: return (ENXIO); ! 207: return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, ! 208: minvpph, uio)); ! 209: } ! 210: ! 211: vpwait(dev) ! 212: dev_t dev; ! 213: { ! 214: register struct vpdevice *vpaddr = ! 215: (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; ! 216: register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; ! 217: register int e; ! 218: ! 219: for (;;) { ! 220: e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr; ! 221: if (e & (VP_READY|VP_ERROR)) ! 222: break; ! 223: sleep((caddr_t)sc, VPPRI); ! 224: } ! 225: /* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */ ! 226: return (e & VP_ERROR); ! 227: } ! 228: ! 229: vpstart(dev) ! 230: dev_t; ! 231: { ! 232: register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; ! 233: register struct vpdevice *vpaddr = ! 234: (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; ! 235: short bit; ! 236: ! 237: if (sc->sc_count) { ! 238: vpaddr->pbaddr = sc->sc_ubinfo; ! 239: vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30; ! 240: if (sc->sc_state & (VPSC_PRINT|VPSC_SPP)) ! 241: vpaddr->prbcr = sc->sc_count; ! 242: else ! 243: vpaddr->plbcr = sc->sc_count; ! 244: return; ! 245: } ! 246: for (bit = 1; bit != 0; bit <<= 1) ! 247: if (sc->sc_state&bit&VPSC_CMNDS) { ! 248: vpaddr->plcsr |= bit; ! 249: sc->sc_state &= ~bit; ! 250: return; ! 251: } ! 252: } ! 253: ! 254: /*ARGSUSED*/ ! 255: vpioctl(dev, cmd, data, flag) ! 256: dev_t dev; ! 257: int cmd; ! 258: register caddr_t data; ! 259: int flag; ! 260: { ! 261: register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; ! 262: register struct vpdevice *vpaddr = ! 263: (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; ! 264: ! 265: switch (cmd) { ! 266: ! 267: case VGETSTATE: ! 268: *(int *)data = sc->sc_state; ! 269: return (0); ! 270: ! 271: case VSETSTATE: ! 272: sc->sc_state = ! 273: (sc->sc_state & ~VPSC_MODE) | ! 274: ((*(int *)data) & (VPSC_MODE|VPSC_CMNDS)); ! 275: break; ! 276: ! 277: default: ! 278: return (ENOTTY); ! 279: } ! 280: (void) spl4(); ! 281: (void) vpwait(dev); ! 282: if (sc->sc_state&VPSC_SPP) ! 283: vpaddr->plcsr |= VP_SPP; ! 284: else ! 285: vpaddr->plcsr &= ~VP_SPP; ! 286: sc->sc_count = 0; ! 287: while (sc->sc_state & VPSC_CMNDS) { ! 288: (void) vpwait(dev); ! 289: vpstart(dev); ! 290: } ! 291: (void) spl0(); ! 292: return (0); ! 293: } ! 294: ! 295: vptimo(dev) ! 296: dev_t dev; ! 297: { ! 298: register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; ! 299: ! 300: if (sc->sc_state&VPSC_OPEN) ! 301: timeout(vptimo, (caddr_t)dev, hz/10); ! 302: vpintr(dev); ! 303: } ! 304: ! 305: /*ARGSUSED*/ ! 306: vpintr(dev) ! 307: dev_t dev; ! 308: { ! 309: register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; ! 310: ! 311: wakeup((caddr_t)sc); ! 312: } ! 313: ! 314: vpclose(dev) ! 315: dev_t dev; ! 316: { ! 317: register struct vp_softc *sc = &vp_softc[VPUNIT(dev)]; ! 318: register struct vpdevice *vpaddr = ! 319: (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr; ! 320: ! 321: sc->sc_state = 0; ! 322: sc->sc_count = 0; ! 323: vpaddr->plcsr = 0; ! 324: } ! 325: ! 326: vpreset(uban) ! 327: int uban; ! 328: { ! 329: register int vp11; ! 330: register struct uba_device *ui; ! 331: register struct vp_softc *sc = vp_softc; ! 332: register struct vpdevice *vpaddr; ! 333: ! 334: for (vp11 = 0; vp11 < NVP; vp11++, sc++) { ! 335: if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 || ! 336: ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0) ! 337: continue; ! 338: printf(" vp%d", vp11); ! 339: vpaddr = (struct vpdevice *)ui->ui_addr; ! 340: vpaddr->prcsr = VP_IENABLE|VP_DTCINTR; ! 341: if ((sc->sc_state & VPSC_BUSY) == 0) ! 342: continue; ! 343: sc->sc_ubinfo = 0; ! 344: sc->sc_count = sc->sc_bp->b_bcount; ! 345: vpstart(sc->sc_bp->b_dev); ! 346: } ! 347: } ! 348: ! 349: vpselect() ! 350: { ! 351: return (1); ! 352: } ! 353: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.