Annotation of sys/arch/hp300/dev/ppi.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ppi.c,v 1.16 2006/04/13 20:08:12 miod Exp $ */
! 2: /* $NetBSD: ppi.c,v 1.13 1997/04/02 22:37:33 scottr Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
! 6: * Copyright (c) 1982, 1990, 1993
! 7: * The Regents of the University of California. All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. 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 8.1 (Berkeley) 6/16/93
! 34: */
! 35:
! 36: /*
! 37: * Printer/Plotter HPIB interface
! 38: */
! 39:
! 40: #include <sys/param.h>
! 41: #include <sys/systm.h>
! 42: #include <sys/conf.h>
! 43: #include <sys/device.h>
! 44: #include <sys/errno.h>
! 45: #include <sys/kernel.h>
! 46: #include <sys/malloc.h>
! 47: #include <sys/proc.h>
! 48: #include <sys/timeout.h>
! 49: #include <sys/uio.h>
! 50:
! 51: #include <hp300/dev/hpibvar.h>
! 52:
! 53: #include <hp300/dev/ppiioctl.h>
! 54:
! 55: struct ppi_softc {
! 56: struct device sc_dev;
! 57: int sc_flags;
! 58: struct hpibqueue sc_hq; /* HP-IB job queue entry */
! 59: struct ppiparam sc_param;
! 60: #define sc_burst sc_param.burst
! 61: #define sc_timo sc_param.timo
! 62: #define sc_delay sc_param.delay
! 63: int sc_sec;
! 64: int sc_slave; /* HP-IB slave address */
! 65: struct timeout sc_to; /* ppitimo timeout */
! 66: struct timeout sc_start_to; /* ppistart timeout */
! 67: };
! 68:
! 69: /* sc_flags values */
! 70: #define PPIF_ALIVE 0x01
! 71: #define PPIF_OPEN 0x02
! 72: #define PPIF_UIO 0x04
! 73: #define PPIF_TIMO 0x08
! 74: #define PPIF_DELAY 0x10
! 75:
! 76: int ppimatch(struct device *, void *, void *);
! 77: void ppiattach(struct device *, struct device *, void *);
! 78:
! 79: struct cfattach ppi_ca = {
! 80: sizeof(struct ppi_softc), ppimatch, ppiattach
! 81: };
! 82:
! 83: struct cfdriver ppi_cd = {
! 84: NULL, "ppi", DV_DULL
! 85: };
! 86:
! 87: void ppistart(void *);
! 88: void ppinoop(void *);
! 89:
! 90: void ppitimo(void *);
! 91: int ppirw(dev_t, struct uio *);
! 92: int ppihztoms(int);
! 93: int ppimstohz(int);
! 94:
! 95: cdev_decl(ppi);
! 96:
! 97: #define UNIT(x) minor(x)
! 98:
! 99: #ifdef DEBUG
! 100: int ppidebug = 0x80;
! 101: #define PDB_FOLLOW 0x01
! 102: #define PDB_IO 0x02
! 103: #define PDB_NOCHECK 0x80
! 104: #endif
! 105:
! 106: int
! 107: ppimatch(parent, match, aux)
! 108: struct device *parent;
! 109: void *match, *aux;
! 110: {
! 111: struct cfdata *cf = match;
! 112: struct hpibbus_attach_args *ha = aux;
! 113:
! 114: /*
! 115: * The printer/plotter doesn't return an ID tag.
! 116: * The check below prevents us from matching a CS80
! 117: * device by mistake.
! 118: */
! 119: if (ha->ha_id & 0x200)
! 120: return (0);
! 121:
! 122: /*
! 123: * To prevent matching all unused slots on the bus, we
! 124: * don't allow wildcarded locators.
! 125: */
! 126: if (cf->hpibbuscf_slave == HPIBBUS_SLAVE_UNK ||
! 127: cf->hpibbuscf_punit == HPIBBUS_PUNIT_UNK)
! 128: return (0);
! 129:
! 130: return (1);
! 131: }
! 132:
! 133: void
! 134: ppiattach(parent, self, aux)
! 135: struct device *parent, *self;
! 136: void *aux;
! 137: {
! 138: struct ppi_softc *sc = (struct ppi_softc *)self;
! 139: struct hpibbus_attach_args *ha = aux;
! 140:
! 141: printf("\n");
! 142:
! 143: sc->sc_slave = ha->ha_slave;
! 144:
! 145: /* Initialize the hpib queue entry. */
! 146: sc->sc_hq.hq_softc = sc;
! 147: sc->sc_hq.hq_slave = sc->sc_slave;
! 148: sc->sc_hq.hq_start = ppistart;
! 149: sc->sc_hq.hq_go = ppinoop;
! 150: sc->sc_hq.hq_intr = ppinoop;
! 151:
! 152: sc->sc_flags = PPIF_ALIVE;
! 153:
! 154: /* Initialize timeout structures */
! 155: timeout_set(&sc->sc_to, ppitimo, sc);
! 156: timeout_set(&sc->sc_start_to, ppistart, sc);
! 157: }
! 158:
! 159: void
! 160: ppinoop(arg)
! 161: void *arg;
! 162: {
! 163: /* Noop! */
! 164: }
! 165:
! 166: int
! 167: ppiopen(dev, flags, fmt, p)
! 168: dev_t dev;
! 169: int flags, fmt;
! 170: struct proc *p;
! 171: {
! 172: int unit = UNIT(dev);
! 173: struct ppi_softc *sc;
! 174:
! 175: if (unit >= ppi_cd.cd_ndevs ||
! 176: (sc = ppi_cd.cd_devs[unit]) == NULL ||
! 177: (sc->sc_flags & PPIF_ALIVE) == 0)
! 178: return (ENXIO);
! 179:
! 180: #ifdef DEBUG
! 181: if (ppidebug & PDB_FOLLOW)
! 182: printf("ppiopen(%x, %x): flags %x\n",
! 183: dev, flags, sc->sc_flags);
! 184: #endif
! 185: if (sc->sc_flags & PPIF_OPEN)
! 186: return (EBUSY);
! 187: sc->sc_flags |= PPIF_OPEN;
! 188: sc->sc_burst = PPI_BURST;
! 189: sc->sc_timo = ppimstohz(PPI_TIMO);
! 190: sc->sc_delay = ppimstohz(PPI_DELAY);
! 191: sc->sc_sec = -1;
! 192: return(0);
! 193: }
! 194:
! 195: int
! 196: ppiclose(dev, flags, fmt, p)
! 197: dev_t dev;
! 198: int flags, fmt;
! 199: struct proc *p;
! 200: {
! 201: int unit = UNIT(dev);
! 202: struct ppi_softc *sc = ppi_cd.cd_devs[unit];
! 203:
! 204: #ifdef DEBUG
! 205: if (ppidebug & PDB_FOLLOW)
! 206: printf("ppiclose(%x, %x): flags %x\n",
! 207: dev, flags, sc->sc_flags);
! 208: #endif
! 209: sc->sc_flags &= ~PPIF_OPEN;
! 210: return(0);
! 211: }
! 212:
! 213: void
! 214: ppistart(arg)
! 215: void *arg;
! 216: {
! 217: struct ppi_softc *sc = arg;
! 218:
! 219: #ifdef DEBUG
! 220: if (ppidebug & PDB_FOLLOW)
! 221: printf("ppistart(%x)\n", sc->sc_dev.dv_unit);
! 222: #endif
! 223: sc->sc_flags &= ~PPIF_DELAY;
! 224: wakeup(sc);
! 225: }
! 226:
! 227: void
! 228: ppitimo(arg)
! 229: void *arg;
! 230: {
! 231: struct ppi_softc *sc = arg;
! 232:
! 233: #ifdef DEBUG
! 234: if (ppidebug & PDB_FOLLOW)
! 235: printf("ppitimo(%x)\n", sc->sc_dev.dv_unit);
! 236: #endif
! 237: sc->sc_flags &= ~(PPIF_UIO|PPIF_TIMO);
! 238: wakeup(sc);
! 239: }
! 240:
! 241: int
! 242: ppiread(dev, uio, flags)
! 243: dev_t dev;
! 244: struct uio *uio;
! 245: int flags;
! 246: {
! 247:
! 248: #ifdef DEBUG
! 249: if (ppidebug & PDB_FOLLOW)
! 250: printf("ppiread(%x, %p)\n", dev, uio);
! 251: #endif
! 252: return (ppirw(dev, uio));
! 253: }
! 254:
! 255: int
! 256: ppiwrite(dev, uio, flags)
! 257: dev_t dev;
! 258: struct uio *uio;
! 259: int flags;
! 260: {
! 261:
! 262: #ifdef DEBUG
! 263: if (ppidebug & PDB_FOLLOW)
! 264: printf("ppiwrite(%x, %p)\n", dev, uio);
! 265: #endif
! 266: return (ppirw(dev, uio));
! 267: }
! 268:
! 269: int
! 270: ppirw(dev, uio)
! 271: dev_t dev;
! 272: struct uio *uio;
! 273: {
! 274: int unit = UNIT(dev);
! 275: struct ppi_softc *sc = ppi_cd.cd_devs[unit];
! 276: int s, len, cnt;
! 277: char *cp;
! 278: int error = 0, gotdata = 0;
! 279: int buflen, ctlr, slave;
! 280: char *buf;
! 281:
! 282: if (uio->uio_resid == 0)
! 283: return(0);
! 284:
! 285: ctlr = sc->sc_dev.dv_parent->dv_unit;
! 286: slave = sc->sc_slave;
! 287:
! 288: #ifdef DEBUG
! 289: if (ppidebug & (PDB_FOLLOW|PDB_IO))
! 290: printf("ppirw(%x, %p, %c): burst %d, timo %d, resid %x\n",
! 291: dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
! 292: sc->sc_burst, sc->sc_timo, uio->uio_resid);
! 293: #endif
! 294: buflen = min(sc->sc_burst, uio->uio_resid);
! 295: buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
! 296: sc->sc_flags |= PPIF_UIO;
! 297: if (sc->sc_timo > 0) {
! 298: sc->sc_flags |= PPIF_TIMO;
! 299: timeout_add(&sc->sc_to, sc->sc_timo);
! 300: }
! 301: len = cnt = 0;
! 302: while (uio->uio_resid > 0) {
! 303: len = min(buflen, uio->uio_resid);
! 304: cp = buf;
! 305: if (uio->uio_rw == UIO_WRITE) {
! 306: error = uiomove(cp, len, uio);
! 307: if (error)
! 308: break;
! 309: }
! 310: again:
! 311: s = splbio();
! 312: if ((sc->sc_flags & PPIF_UIO) &&
! 313: hpibreq(sc->sc_dev.dv_parent, &sc->sc_hq) == 0)
! 314: tsleep(sc, PRIBIO+1, "ppirw", 0);
! 315: /*
! 316: * Check if we timed out during sleep or uiomove
! 317: */
! 318: if ((sc->sc_flags & PPIF_UIO) == 0) {
! 319: #ifdef DEBUG
! 320: if (ppidebug & PDB_IO)
! 321: printf("ppirw: uiomove/sleep timo, flags %x\n",
! 322: sc->sc_flags);
! 323: #endif
! 324: if (sc->sc_flags & PPIF_TIMO) {
! 325: timeout_del(&sc->sc_to);
! 326: sc->sc_flags &= ~PPIF_TIMO;
! 327: }
! 328: splx(s);
! 329: break;
! 330: }
! 331: /*
! 332: * Perform the operation
! 333: */
! 334: if (uio->uio_rw == UIO_WRITE)
! 335: cnt = hpibsend(ctlr, slave, sc->sc_sec, cp, len);
! 336: else
! 337: cnt = hpibrecv(ctlr, slave, sc->sc_sec, cp, len);
! 338: hpibfree(sc->sc_dev.dv_parent, &sc->sc_hq);
! 339: #ifdef DEBUG
! 340: if (ppidebug & PDB_IO)
! 341: printf("ppirw: %s(%d, %d, %x, %p, %d) -> %d\n",
! 342: uio->uio_rw == UIO_READ ? "recv" : "send",
! 343: ctlr, slave, sc->sc_sec, cp, len, cnt);
! 344: #endif
! 345: if (uio->uio_rw == UIO_READ) {
! 346: if (cnt) {
! 347: error = uiomove(cp, cnt, uio);
! 348: if (error) {
! 349: splx(s);
! 350: break;
! 351: }
! 352: gotdata++;
! 353: }
! 354: /*
! 355: * Didn't get anything this time, but did in the past.
! 356: * Consider us done.
! 357: */
! 358: else if (gotdata) {
! 359: splx(s);
! 360: break;
! 361: }
! 362: }
! 363: /*
! 364: * Operation timeout (or non-blocking), quit now.
! 365: */
! 366: if ((sc->sc_flags & PPIF_UIO) == 0) {
! 367: #ifdef DEBUG
! 368: if (ppidebug & PDB_IO)
! 369: printf("ppirw: timeout/done\n");
! 370: #endif
! 371: splx(s);
! 372: break;
! 373: }
! 374: /*
! 375: * Implement inter-read delay
! 376: */
! 377: if (sc->sc_delay > 0) {
! 378: sc->sc_flags |= PPIF_DELAY;
! 379: timeout_add(&sc->sc_start_to, sc->sc_delay);
! 380: error = tsleep(sc, (PCATCH|PZERO) + 1, "hpib", 0);
! 381: if (error) {
! 382: splx(s);
! 383: break;
! 384: }
! 385: }
! 386: /*
! 387: * Must not call uiomove again til we've used all data
! 388: * that we already grabbed.
! 389: */
! 390: if (uio->uio_rw == UIO_WRITE && cnt != len) {
! 391: cp += cnt;
! 392: len -= cnt;
! 393: cnt = 0;
! 394: splx(s);
! 395: goto again;
! 396: }
! 397: splx(s);
! 398: }
! 399: if (sc->sc_flags & PPIF_TIMO) {
! 400: timeout_del(&sc->sc_to);
! 401: sc->sc_flags &= ~PPIF_TIMO;
! 402: }
! 403: if (sc->sc_flags & PPIF_DELAY) {
! 404: timeout_del(&sc->sc_start_to);
! 405: sc->sc_flags &= ~PPIF_DELAY;
! 406: }
! 407: /*
! 408: * Adjust for those chars that we uiomove'ed but never wrote
! 409: */
! 410: if (uio->uio_rw == UIO_WRITE && cnt != len) {
! 411: uio->uio_resid += (len - cnt);
! 412: #ifdef DEBUG
! 413: if (ppidebug & PDB_IO)
! 414: printf("ppirw: short write, adjust by %d\n",
! 415: len-cnt);
! 416: #endif
! 417: }
! 418: free(buf, M_DEVBUF);
! 419: #ifdef DEBUG
! 420: if (ppidebug & (PDB_FOLLOW|PDB_IO))
! 421: printf("ppirw: return %d, resid %d\n", error, uio->uio_resid);
! 422: #endif
! 423: return (error);
! 424: }
! 425:
! 426: int
! 427: ppiioctl(dev, cmd, data, flag, p)
! 428: dev_t dev;
! 429: u_long cmd;
! 430: caddr_t data;
! 431: int flag;
! 432: struct proc *p;
! 433: {
! 434: struct ppi_softc *sc = ppi_cd.cd_devs[UNIT(dev)];
! 435: struct ppiparam *pp, *upp;
! 436: int tmp;
! 437: int error = 0;
! 438:
! 439: switch (cmd) {
! 440: case PPIIOCGPARAM:
! 441: pp = &sc->sc_param;
! 442: upp = (struct ppiparam *)data;
! 443: upp->burst = pp->burst;
! 444: upp->timo = ppihztoms(pp->timo);
! 445: upp->delay = ppihztoms(pp->delay);
! 446: break;
! 447: case PPIIOCSPARAM:
! 448: pp = &sc->sc_param;
! 449: upp = (struct ppiparam *)data;
! 450: if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX ||
! 451: upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX)
! 452: return(EINVAL);
! 453: pp->burst = upp->burst;
! 454: pp->timo = ppimstohz(upp->timo);
! 455: pp->delay = ppimstohz(upp->delay);
! 456: break;
! 457: case PPIIOCSSEC:
! 458: tmp = *(int *)data;
! 459: if (tmp == -1 || (tmp >= 0 && tmp <= 0x1f))
! 460: sc->sc_sec = tmp;
! 461: else
! 462: error = EINVAL;
! 463: break;
! 464: default:
! 465: return (ENOTTY);
! 466: }
! 467: return (error);
! 468: }
! 469:
! 470: int
! 471: ppihztoms(h)
! 472: int h;
! 473: {
! 474: int m = h;
! 475:
! 476: if (m > 0)
! 477: m = m * 1000 / hz;
! 478: return(m);
! 479: }
! 480:
! 481: int
! 482: ppimstohz(m)
! 483: int m;
! 484: {
! 485: int h = m;
! 486:
! 487: if (h > 0) {
! 488: h = h * hz / 1000;
! 489: if (h == 0)
! 490: h = 1000 / hz;
! 491: }
! 492: return(h);
! 493: }
CVSweb