|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)ppi.c 7.3 (Berkeley) 12/16/90 ! 34: */ ! 35: ! 36: /* ! 37: * Printer/Plotter HPIB interface ! 38: */ ! 39: ! 40: #include "ppi.h" ! 41: #if NPPI > 0 ! 42: ! 43: #include "sys/param.h" ! 44: #include "sys/errno.h" ! 45: #include "sys/uio.h" ! 46: #include "sys/malloc.h" ! 47: ! 48: #include "device.h" ! 49: #include "ppiioctl.h" ! 50: ! 51: int ppiattach(), ppistart(), ppitimo(); ! 52: struct driver ppidriver = { ! 53: ppiattach, "ppi", ppistart, ! 54: }; ! 55: ! 56: struct ppi_softc { ! 57: int sc_flags; ! 58: struct devqueue sc_dq; ! 59: struct hp_device *sc_hd; ! 60: struct ppiparam sc_param; ! 61: #define sc_burst sc_param.burst ! 62: #define sc_timo sc_param.timo ! 63: #define sc_delay sc_param.delay ! 64: int sc_sec; ! 65: } ppi_softc[NPPI]; ! 66: ! 67: /* sc_flags values */ ! 68: #define PPIF_ALIVE 0x01 ! 69: #define PPIF_OPEN 0x02 ! 70: #define PPIF_UIO 0x04 ! 71: #define PPIF_TIMO 0x08 ! 72: #define PPIF_DELAY 0x10 ! 73: ! 74: #define UNIT(x) minor(x) ! 75: ! 76: #ifdef DEBUG ! 77: int ppidebug = 0x80; ! 78: #define PDB_FOLLOW 0x01 ! 79: #define PDB_IO 0x02 ! 80: #define PDB_NOCHECK 0x80 ! 81: #endif ! 82: ! 83: ppiattach(hd) ! 84: register struct hp_device *hd; ! 85: { ! 86: register struct ppi_softc *sc = &ppi_softc[hd->hp_unit]; ! 87: ! 88: #ifdef DEBUG ! 89: if ((ppidebug & PDB_NOCHECK) == 0) ! 90: #endif ! 91: /* ! 92: * XXX: the printer/plotter doesn't seem to really return ! 93: * an ID but this will at least prevent us from mistaking ! 94: * a cs80 disk or tape for a ppi device. ! 95: */ ! 96: if (hpibid(hd->hp_ctlr, hd->hp_slave) & 0x200) ! 97: return(0); ! 98: sc->sc_flags = PPIF_ALIVE; ! 99: sc->sc_dq.dq_ctlr = hd->hp_ctlr; ! 100: sc->sc_dq.dq_unit = hd->hp_unit; ! 101: sc->sc_dq.dq_slave = hd->hp_slave; ! 102: sc->sc_dq.dq_driver = &ppidriver; ! 103: sc->sc_hd = hd; ! 104: return(1); ! 105: } ! 106: ! 107: ppiopen(dev, flags) ! 108: dev_t dev; ! 109: { ! 110: register int unit = UNIT(dev); ! 111: register struct ppi_softc *sc = &ppi_softc[unit]; ! 112: ! 113: if (unit >= NPPI || (sc->sc_flags & PPIF_ALIVE) == 0) ! 114: return(ENXIO); ! 115: #ifdef DEBUG ! 116: if (ppidebug & PDB_FOLLOW) ! 117: printf("ppiopen(%x, %x): flags %x\n", ! 118: dev, flags, sc->sc_flags); ! 119: #endif ! 120: if (sc->sc_flags & PPIF_OPEN) ! 121: return(EBUSY); ! 122: sc->sc_flags |= PPIF_OPEN; ! 123: sc->sc_burst = PPI_BURST; ! 124: sc->sc_timo = ppimstohz(PPI_TIMO); ! 125: sc->sc_delay = ppimstohz(PPI_DELAY); ! 126: sc->sc_sec = -1; ! 127: return(0); ! 128: } ! 129: ! 130: ppiclose(dev, flags) ! 131: dev_t dev; ! 132: { ! 133: register int unit = UNIT(dev); ! 134: register struct ppi_softc *sc = &ppi_softc[unit]; ! 135: ! 136: #ifdef DEBUG ! 137: if (ppidebug & PDB_FOLLOW) ! 138: printf("ppiclose(%x, %x): flags %x\n", ! 139: dev, flags, sc->sc_flags); ! 140: #endif ! 141: sc->sc_flags &= ~PPIF_OPEN; ! 142: return(0); ! 143: } ! 144: ! 145: ppistart(unit) ! 146: int unit; ! 147: { ! 148: #ifdef DEBUG ! 149: if (ppidebug & PDB_FOLLOW) ! 150: printf("ppistart(%x)\n", unit); ! 151: #endif ! 152: ppi_softc[unit].sc_flags &= ~PPIF_DELAY; ! 153: wakeup(&ppi_softc[unit]); ! 154: } ! 155: ! 156: ppitimo(unit) ! 157: int unit; ! 158: { ! 159: #ifdef DEBUG ! 160: if (ppidebug & PDB_FOLLOW) ! 161: printf("ppitimo(%x)\n", unit); ! 162: #endif ! 163: ppi_softc[unit].sc_flags &= ~(PPIF_UIO|PPIF_TIMO); ! 164: wakeup(&ppi_softc[unit]); ! 165: } ! 166: ! 167: ppiread(dev, uio) ! 168: dev_t dev; ! 169: struct uio *uio; ! 170: { ! 171: ! 172: #ifdef DEBUG ! 173: if (ppidebug & PDB_FOLLOW) ! 174: printf("ppiread(%x, %x)\n", dev, uio); ! 175: #endif ! 176: return (ppirw(dev, uio)); ! 177: } ! 178: ! 179: ppiwrite(dev, uio) ! 180: dev_t dev; ! 181: struct uio *uio; ! 182: { ! 183: ! 184: #ifdef DEBUG ! 185: if (ppidebug & PDB_FOLLOW) ! 186: printf("ppiwrite(%x, %x)\n", dev, uio); ! 187: #endif ! 188: return (ppirw(dev, uio)); ! 189: } ! 190: ! 191: ppirw(dev, uio) ! 192: dev_t dev; ! 193: register struct uio *uio; ! 194: { ! 195: int unit = UNIT(dev); ! 196: register struct ppi_softc *sc = &ppi_softc[unit]; ! 197: register int s, len, cnt; ! 198: register char *cp; ! 199: int error = 0, gotdata = 0; ! 200: int buflen; ! 201: char *buf; ! 202: ! 203: if (uio->uio_resid == 0) ! 204: return(0); ! 205: ! 206: #ifdef DEBUG ! 207: if (ppidebug & (PDB_FOLLOW|PDB_IO)) ! 208: printf("ppirw(%x, %x, %c): burst %d, timo %d, resid %x\n", ! 209: dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W', ! 210: sc->sc_burst, sc->sc_timo, uio->uio_resid); ! 211: #endif ! 212: buflen = MIN(sc->sc_burst, uio->uio_resid); ! 213: buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK); ! 214: sc->sc_flags |= PPIF_UIO; ! 215: if (sc->sc_timo > 0) { ! 216: sc->sc_flags |= PPIF_TIMO; ! 217: timeout(ppitimo, unit, sc->sc_timo); ! 218: } ! 219: while (uio->uio_resid > 0) { ! 220: len = MIN(buflen, uio->uio_resid); ! 221: cp = buf; ! 222: if (uio->uio_rw == UIO_WRITE) { ! 223: error = uiomove(cp, len, uio); ! 224: if (error) ! 225: break; ! 226: } ! 227: again: ! 228: s = splbio(); ! 229: if ((sc->sc_flags & PPIF_UIO) && hpibreq(&sc->sc_dq) == 0) ! 230: sleep(sc, PRIBIO+1); ! 231: /* ! 232: * Check if we timed out during sleep or uiomove ! 233: */ ! 234: (void) splsoftclock(); ! 235: if ((sc->sc_flags & PPIF_UIO) == 0) { ! 236: #ifdef DEBUG ! 237: if (ppidebug & PDB_IO) ! 238: printf("ppirw: uiomove/sleep timo, flags %x\n", ! 239: sc->sc_flags); ! 240: #endif ! 241: if (sc->sc_flags & PPIF_TIMO) { ! 242: untimeout(ppitimo, unit); ! 243: sc->sc_flags &= ~PPIF_TIMO; ! 244: } ! 245: splx(s); ! 246: break; ! 247: } ! 248: splx(s); ! 249: /* ! 250: * Perform the operation ! 251: */ ! 252: if (uio->uio_rw == UIO_WRITE) ! 253: cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, ! 254: sc->sc_sec, cp, len); ! 255: else ! 256: cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, ! 257: sc->sc_sec, cp, len); ! 258: s = splbio(); ! 259: hpibfree(&sc->sc_dq); ! 260: #ifdef DEBUG ! 261: if (ppidebug & PDB_IO) ! 262: printf("ppirw: %s(%d, %d, %x, %x, %d) -> %d\n", ! 263: uio->uio_rw == UIO_READ ? "recv" : "send", ! 264: sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, ! 265: sc->sc_sec, cp, len, cnt); ! 266: #endif ! 267: splx(s); ! 268: if (uio->uio_rw == UIO_READ) { ! 269: if (cnt) { ! 270: error = uiomove(cp, cnt, uio); ! 271: if (error) ! 272: break; ! 273: gotdata++; ! 274: } ! 275: /* ! 276: * Didn't get anything this time, but did in the past. ! 277: * Consider us done. ! 278: */ ! 279: else if (gotdata) ! 280: break; ! 281: } ! 282: s = splsoftclock(); ! 283: /* ! 284: * Operation timeout (or non-blocking), quit now. ! 285: */ ! 286: if ((sc->sc_flags & PPIF_UIO) == 0) { ! 287: #ifdef DEBUG ! 288: if (ppidebug & PDB_IO) ! 289: printf("ppirw: timeout/done\n"); ! 290: #endif ! 291: splx(s); ! 292: break; ! 293: } ! 294: /* ! 295: * Implement inter-read delay ! 296: */ ! 297: if (sc->sc_delay > 0) { ! 298: sc->sc_flags |= PPIF_DELAY; ! 299: timeout(ppistart, unit, sc->sc_delay); ! 300: error = tsleep(sc, PCATCH|PZERO+1, "hpib", 0); ! 301: if (error) { ! 302: splx(s); ! 303: break; ! 304: } ! 305: } ! 306: splx(s); ! 307: /* ! 308: * Must not call uiomove again til we've used all data ! 309: * that we already grabbed. ! 310: */ ! 311: if (uio->uio_rw == UIO_WRITE && cnt != len) { ! 312: cp += cnt; ! 313: len -= cnt; ! 314: cnt = 0; ! 315: goto again; ! 316: } ! 317: } ! 318: s = splsoftclock(); ! 319: if (sc->sc_flags & PPIF_TIMO) { ! 320: untimeout(ppitimo, unit); ! 321: sc->sc_flags &= ~PPIF_TIMO; ! 322: } ! 323: if (sc->sc_flags & PPIF_DELAY) { ! 324: untimeout(ppistart, unit); ! 325: sc->sc_flags &= ~PPIF_DELAY; ! 326: } ! 327: splx(s); ! 328: /* ! 329: * Adjust for those chars that we uiomove'ed but never wrote ! 330: */ ! 331: if (uio->uio_rw == UIO_WRITE && cnt != len) { ! 332: uio->uio_resid += (len - cnt); ! 333: #ifdef DEBUG ! 334: if (ppidebug & PDB_IO) ! 335: printf("ppirw: short write, adjust by %d\n", ! 336: len-cnt); ! 337: #endif ! 338: } ! 339: free(buf, M_DEVBUF); ! 340: #ifdef DEBUG ! 341: if (ppidebug & (PDB_FOLLOW|PDB_IO)) ! 342: printf("ppirw: return %d, resid %d\n", error, uio->uio_resid); ! 343: #endif ! 344: return (error); ! 345: } ! 346: ! 347: ppiioctl(dev, cmd, data, flag) ! 348: dev_t dev; ! 349: int cmd; ! 350: caddr_t data; ! 351: int flag; ! 352: { ! 353: struct ppi_softc *sc = &ppi_softc[UNIT(dev)]; ! 354: struct ppiparam *pp, *upp; ! 355: int error = 0; ! 356: ! 357: switch (cmd) { ! 358: case PPIIOCGPARAM: ! 359: pp = &sc->sc_param; ! 360: upp = (struct ppiparam *)data; ! 361: upp->burst = pp->burst; ! 362: upp->timo = ppihztoms(pp->timo); ! 363: upp->delay = ppihztoms(pp->delay); ! 364: break; ! 365: case PPIIOCSPARAM: ! 366: pp = &sc->sc_param; ! 367: upp = (struct ppiparam *)data; ! 368: if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX || ! 369: upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX) ! 370: return(EINVAL); ! 371: pp->burst = upp->burst; ! 372: pp->timo = ppimstohz(upp->timo); ! 373: pp->delay = ppimstohz(upp->delay); ! 374: break; ! 375: case PPIIOCSSEC: ! 376: sc->sc_sec = *(int *)data; ! 377: break; ! 378: default: ! 379: return(EINVAL); ! 380: } ! 381: return (error); ! 382: } ! 383: ! 384: ppihztoms(h) ! 385: int h; ! 386: { ! 387: extern int hz; ! 388: register int m = h; ! 389: ! 390: if (m > 0) ! 391: m = m * 1000 / hz; ! 392: return(m); ! 393: } ! 394: ! 395: ppimstohz(m) ! 396: int m; ! 397: { ! 398: extern int hz; ! 399: register int h = m; ! 400: ! 401: if (h > 0) { ! 402: h = h * hz / 1000; ! 403: if (h == 0) ! 404: h = 1000 / hz; ! 405: } ! 406: return(h); ! 407: } ! 408: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.