|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1986 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: * @(#)ik.c 7.7 (Berkeley) 12/16/90 ! 34: */ ! 35: ! 36: #include "ik.h" ! 37: #if NIK > 0 ! 38: /* ! 39: * PS300/IKON DR-11W Device Driver. ! 40: */ ! 41: #include "sys/param.h" ! 42: #include "sys/buf.h" ! 43: #include "sys/cmap.h" ! 44: #include "sys/conf.h" ! 45: #include "sys/dkstat.h" ! 46: #include "sys/map.h" ! 47: #include "sys/systm.h" ! 48: #include "sys/user.h" ! 49: #include "sys/vmmac.h" ! 50: #include "sys/proc.h" ! 51: #include "sys/kernel.h" ! 52: #include "sys/syslog.h" ! 53: ! 54: #include "../include/mtpr.h" ! 55: #include "../include/pte.h" ! 56: ! 57: #include "../vba/vbavar.h" ! 58: #include "../vba/ikreg.h" ! 59: #include "../vba/psreg.h" ! 60: #include "../vba/psproto.h" ! 61: ! 62: int ikprobe(), ikattach(), iktimer(); ! 63: struct vba_device *ikinfo[NIK]; ! 64: long ikstd[] = { 0 }; ! 65: struct vba_driver ikdriver = { ikprobe, 0, ikattach, 0, ikstd, "ik", ikinfo }; ! 66: ! 67: #define splik() spl4() ! 68: /* ! 69: * Devices are organized in pairs with the odd valued ! 70: * device being used for ``diagnostic'' purposes. That ! 71: * is diagnostic devices don't get auto-attach'd and ! 72: * detach'd on open-close. ! 73: */ ! 74: #define IKUNIT(dev) (minor(dev) >> 1) ! 75: #define IKDIAG(dev) (minor(dev) & 01) /* is a diagnostic unit */ ! 76: ! 77: struct ik_softc { ! 78: uid_t is_uid; /* uid of open processes */ ! 79: u_short is_timeout; /* current timeout (seconds) */ ! 80: u_short is_error; /* internal error codes */ ! 81: u_short is_flags; ! 82: #define IKF_ATTACHED 0x1 /* unit is attached (not used yet) */ ! 83: union { ! 84: u_short w[2]; ! 85: u_long l; ! 86: } is_nameaddr; /* address of last symbol lookup */ ! 87: caddr_t is_buf[PS_MAXDMA];/* i/o buffer XXX */ ! 88: } ik_softc[NIK]; ! 89: ! 90: struct buf iktab[NIK]; /* unit command queue headers */ ! 91: struct buf rikbuf[NIK]; /* buffers for read/write operations */ ! 92: struct buf cikbuf[NIK]; /* buffers for control operations */ ! 93: ! 94: /* buf overlay definitions */ ! 95: #define b_command b_resid ! 96: ! 97: int ikdiotimo = PS_DIOTIMO; /* dio polling timeout */ ! 98: int iktimeout = PS_TIMEOUT; /* attention/dma timeout (in hz) */ ! 99: ! 100: ikprobe(reg, vi) ! 101: caddr_t reg; ! 102: struct vba_device *vi; ! 103: { ! 104: register int br, cvec; /* r12, r11 */ ! 105: register struct ikdevice *ik; ! 106: ! 107: #ifdef lint ! 108: br = 0; cvec = br; br = cvec; ! 109: ikintr(0); ! 110: #endif ! 111: if (badaddr(reg, 2)) ! 112: return (0); ! 113: ik = (struct ikdevice *)reg; ! 114: ik->ik_vec = --vi->ui_hd->vh_lastiv; ! 115: /* ! 116: * Use extended non-privileged address modifier ! 117: * to avoid address overlap with 24-bit devices. ! 118: */ ! 119: ik->ik_mod = 0xf1; /* address modifier */ ! 120: /* ! 121: * Try and reset the PS300. Since this ! 122: * won't work if it's powered off, we ! 123: * can't use sucess/failure to decide ! 124: * if the device is present. ! 125: */ ! 126: br = 0; ! 127: (void) psreset(ik, IKCSR_IENA); ! 128: if (br == 0) /* XXX */ ! 129: br = 0x18, cvec = ik->ik_vec; /* XXX */ ! 130: return (sizeof (struct ikdevice)); ! 131: } ! 132: ! 133: /* ! 134: * Perform a ``hard'' reset. ! 135: */ ! 136: psreset(ik, iena) ! 137: register struct ikdevice *ik; ! 138: { ! 139: ! 140: ik->ik_csr = IKCSR_MCLR|iena; ! 141: DELAY(10000); ! 142: ik->ik_csr = IKCSR_FNC3|iena; ! 143: if (!iena) ! 144: return (dioread(ik) == PS_RESET); ! 145: return (1); ! 146: } ! 147: ! 148: ikattach(vi) ! 149: struct vba_device *vi; ! 150: { ! 151: ! 152: ik_softc[vi->ui_unit].is_uid = -1; ! 153: } ! 154: ! 155: /* ! 156: * Open a PS300 and attach. We allow multiple ! 157: * processes with the same uid to share a unit. ! 158: */ ! 159: /*ARGSUSED*/ ! 160: ikopen(dev, flag) ! 161: dev_t dev; ! 162: int flag; ! 163: { ! 164: register int unit = IKUNIT(dev); ! 165: register struct ik_softc *sc; ! 166: struct vba_device *vi; ! 167: struct ikdevice *ik; ! 168: int reset; ! 169: ! 170: if (unit >= NIK || (vi = ikinfo[unit]) == 0 || vi->ui_alive == 0) ! 171: return (ENXIO); ! 172: sc = &ik_softc[unit]; ! 173: if (sc->is_uid != (uid_t)-1 && sc->is_uid != u.u_uid) ! 174: return (EBUSY); ! 175: if (sc->is_uid == (uid_t)-1) { ! 176: sc->is_timeout = 0; ! 177: timeout(iktimer, (caddr_t)unit, hz); ! 178: /* ! 179: * Perform PS300 attach for first process. ! 180: */ ! 181: if (!IKDIAG(dev)) { ! 182: reset = 0; ! 183: again: ! 184: if (ikcommand(dev, PS_ATTACH, 1)) { ! 185: /* ! 186: * If attach fails, perform a hard ! 187: * reset once, then retry the command. ! 188: */ ! 189: ik = (struct ikdevice *)ikinfo[unit]->ui_addr; ! 190: if (!reset++ && psreset(ik, 0)) ! 191: goto again; ! 192: untimeout(iktimer, (caddr_t)unit); ! 193: return (EIO); ! 194: } ! 195: } ! 196: sc->is_uid = u.u_uid; ! 197: } ! 198: return (0); ! 199: } ! 200: ! 201: /*ARGSUSED*/ ! 202: ikclose(dev, flag) ! 203: dev_t dev; ! 204: int flag; ! 205: { ! 206: int unit = IKUNIT(dev); ! 207: register struct ik_softc *sc = &ik_softc[unit]; ! 208: ! 209: if (!IKDIAG(dev)) ! 210: (void) ikcommand(dev, PS_DETACH, 1); /* auto detach */ ! 211: sc->is_uid = -1; ! 212: untimeout(iktimer, (caddr_t)unit); ! 213: return (0); ! 214: } ! 215: ! 216: ikread(dev, uio) ! 217: dev_t dev; ! 218: struct uio *uio; ! 219: { ! 220: ! 221: return (ikrw(dev, uio, B_READ)); ! 222: } ! 223: ! 224: ikwrite(dev, uio) ! 225: dev_t dev; ! 226: struct uio *uio; ! 227: { ! 228: ! 229: return (ikrw(dev, uio, B_WRITE)); ! 230: } ! 231: ! 232: /* ! 233: * Take read/write request and perform physical i/o ! 234: * transaction with PS300. This involves constructing ! 235: * a physical i/o request vector based on the uio ! 236: * vector, performing the dma, and, finally, moving ! 237: * the data to it's final destination (because of CCI ! 238: * VERSAbus bogosities). ! 239: */ ! 240: ikrw(dev, uio, rw) ! 241: dev_t dev; ! 242: register struct uio *uio; ! 243: int rw; ! 244: { ! 245: int error, unit = IKUNIT(dev), s, wrcmd; ! 246: register struct buf *bp; ! 247: register struct iovec *iov; ! 248: register struct psalist *ap; ! 249: struct ik_softc *sc = &ik_softc[unit]; ! 250: ! 251: if (unit >= NIK) ! 252: return (ENXIO); ! 253: bp = &rikbuf[unit]; ! 254: error = 0, iov = uio->uio_iov, wrcmd = PS_WRPHY; ! 255: for (; !error && uio->uio_iovcnt; iov++, uio->uio_iovcnt--) { ! 256: /* ! 257: * Hack way to set PS300 address w/o doing an lseek ! 258: * and specify write physical w/ refresh synchronization. ! 259: */ ! 260: if (iov->iov_len == 0) { ! 261: if ((int)iov->iov_base&PSIO_SYNC) ! 262: wrcmd = PS_WRPHY_SYNC; ! 263: uio->uio_offset = (int)iov->iov_base & ~PSIO_SYNC; ! 264: continue; ! 265: } ! 266: if (iov->iov_len > PS_MAXDMA) { ! 267: sc->is_error = PSERROR_INVALBC, error = EINVAL; ! 268: continue; ! 269: } ! 270: if ((int)uio->uio_offset&01) { ! 271: sc->is_error = PSERROR_BADADDR, error = EINVAL; ! 272: continue; ! 273: } ! 274: s = splbio(); ! 275: while (bp->b_flags&B_BUSY) { ! 276: bp->b_flags |= B_WANTED; ! 277: sleep((caddr_t)bp, PRIBIO+1); ! 278: } ! 279: splx(s); ! 280: bp->b_flags = B_BUSY | rw; ! 281: /* ! 282: * Construct address descriptor in buffer. ! 283: */ ! 284: ap = (struct psalist *)sc->is_buf; ! 285: ap->nblocks = 1; ! 286: /* work-around dr300 word swapping */ ! 287: ap->addr[0] = uio->uio_offset & 0xffff; ! 288: ap->addr[1] = uio->uio_offset >> 16; ! 289: ap->wc = (iov->iov_len + 1) >> 1; ! 290: if (rw == B_WRITE) { ! 291: error = copyin(iov->iov_base, (caddr_t)&ap[1], ! 292: (unsigned)iov->iov_len); ! 293: if (!error) ! 294: error = ikcommand(dev, wrcmd, ! 295: iov->iov_len + sizeof (*ap)); ! 296: } else { ! 297: caddr_t cp; ! 298: int len; ! 299: ! 300: error = ikcommand(dev, PS_RDPHY, sizeof (*ap)); ! 301: cp = (caddr_t)&ap[1], len = iov->iov_len; ! 302: for (; len > 0; len -= NBPG, cp += NBPG) ! 303: mtpr(P1DC, cp); ! 304: if (!error) ! 305: error = copyout((caddr_t)&ap[1], iov->iov_base, ! 306: (unsigned)iov->iov_len); ! 307: } ! 308: (void) splbio(); ! 309: if (bp->b_flags&B_WANTED) ! 310: wakeup((caddr_t)bp); ! 311: splx(s); ! 312: uio->uio_resid -= iov->iov_len; ! 313: uio->uio_offset += iov->iov_len; ! 314: bp->b_flags &= ~(B_BUSY|B_WANTED); ! 315: } ! 316: return (error); ! 317: } ! 318: ! 319: /* ! 320: * Perform a PS300 command. ! 321: */ ! 322: ikcommand(dev, com, count) ! 323: dev_t dev; ! 324: int com, count; ! 325: { ! 326: register struct buf *bp; ! 327: register int s; ! 328: int error; ! 329: ! 330: bp = &cikbuf[IKUNIT(dev)]; ! 331: s = splik(); ! 332: while (bp->b_flags&B_BUSY) { ! 333: if (bp->b_flags&B_DONE) ! 334: break; ! 335: bp->b_flags |= B_WANTED; ! 336: sleep((caddr_t)bp, PRIBIO); ! 337: } ! 338: bp->b_flags = B_BUSY|B_READ; ! 339: splx(s); ! 340: bp->b_dev = dev; ! 341: bp->b_command = com; ! 342: bp->b_bcount = count; ! 343: ikstrategy(bp); ! 344: error = biowait(bp); ! 345: if (bp->b_flags&B_WANTED) ! 346: wakeup((caddr_t)bp); ! 347: bp->b_flags &= B_ERROR; ! 348: return (error); ! 349: } ! 350: ! 351: /* ! 352: * Physio strategy routine ! 353: */ ! 354: ikstrategy(bp) ! 355: register struct buf *bp; ! 356: { ! 357: register struct buf *dp; ! 358: ! 359: /* ! 360: * Put request at end of controller queue. ! 361: */ ! 362: dp = &iktab[IKUNIT(bp->b_dev)]; ! 363: bp->av_forw = NULL; ! 364: (void) splik(); ! 365: if (dp->b_actf != NULL) { ! 366: dp->b_actl->av_forw = bp; ! 367: dp->b_actl = bp; ! 368: } else ! 369: dp->b_actf = dp->b_actl = bp; ! 370: if (!dp->b_active) ! 371: ikstart(dp); ! 372: (void) spl0(); ! 373: } ! 374: ! 375: /* ! 376: * Start the next command on the controller's queue. ! 377: */ ! 378: ikstart(dp) ! 379: register struct buf *dp; ! 380: { ! 381: register struct buf *bp; ! 382: register struct ikdevice *ik; ! 383: register struct ik_softc *sc; ! 384: u_short bc, csr; ! 385: u_int addr; ! 386: int unit; ! 387: ! 388: loop: ! 389: /* ! 390: * Pull a request off the controller queue ! 391: */ ! 392: if ((bp = dp->b_actf) == NULL) { ! 393: dp->b_active = 0; ! 394: return; ! 395: } ! 396: /* ! 397: * Mark controller busy and process this request. ! 398: */ ! 399: dp->b_active = 1; ! 400: unit = IKUNIT(bp->b_dev); ! 401: sc = &ik_softc[unit]; ! 402: ik = (struct ikdevice *)ikinfo[unit]->ui_addr; ! 403: switch ((int)bp->b_command) { ! 404: ! 405: case PS_ATTACH: /* logical unit attach */ ! 406: case PS_DETACH: /* logical unit detach */ ! 407: case PS_LOOKUP: /* name lookup */ ! 408: case PS_RDPHY: /* physical i/o read */ ! 409: case PS_WRPHY: /* physical i/o write */ ! 410: case PS_WRPHY_SYNC: /* physical i/o write w/ sync */ ! 411: /* ! 412: * Handshake command and, optionally, ! 413: * byte count and byte swap flag. ! 414: */ ! 415: if (sc->is_error = diowrite(ik, (u_short)bp->b_command)) ! 416: goto bad; ! 417: if (bp->b_command < PS_DETACH) { ! 418: if (sc->is_error = diowrite(ik, (u_short)bp->b_bcount)) ! 419: goto bad; ! 420: if (sc->is_error = diowrite(ik, (u_short)0 /* !swab */)) ! 421: goto bad; ! 422: } ! 423: /* ! 424: * Set timeout and wait for an attention interrupt. ! 425: */ ! 426: sc->is_timeout = iktimeout; ! 427: return; ! 428: ! 429: case PS_DMAOUT: /* dma data host->PS300 */ ! 430: bc = bp->b_bcount; ! 431: csr = IKCSR_CYCLE; ! 432: break; ! 433: ! 434: case PS_DMAIN: /* dma data PS300->host */ ! 435: bc = bp->b_bcount; ! 436: csr = IKCSR_CYCLE|IKCSR_FNC1; ! 437: break; ! 438: ! 439: default: ! 440: log(LOG_ERR, "ik%d: bad cmd %x\n", unit, bp->b_command); ! 441: sc->is_error = PSERROR_BADCMD; ! 442: goto bad; ! 443: } ! 444: /* initiate dma transfer */ ! 445: addr = vtoph((struct proc *)0, (unsigned)sc->is_buf); ! 446: ik->ik_bahi = addr >> 17; ! 447: ik->ik_balo = (addr >> 1) & 0xffff; ! 448: ik->ik_wc = ((bc + 1) >> 1) - 1; /* round & convert */ ! 449: ik->ik_pulse = IKPULSE_RATTF|IKPULSE_RDMAF; ! 450: sc->is_timeout = iktimeout; ! 451: ik->ik_csr = IKCSR_IENA|IKCSR_GO|csr; ! 452: return; ! 453: bad: ! 454: bp->b_flags |= B_ERROR; ! 455: dp->b_actf = bp->av_forw; /* remove from queue */ ! 456: biodone(bp); ! 457: goto loop; ! 458: } ! 459: ! 460: #define FETCHWORD(i) { \ ! 461: v = dioread(ik); \ ! 462: if (v == -1) { \ ! 463: sc->is_error = PSERROR_NAMETIMO; \ ! 464: goto bad; \ ! 465: } \ ! 466: sc->is_nameaddr.w[i] = v; \ ! 467: } ! 468: ! 469: /* ! 470: * Process a device interrupt. ! 471: */ ! 472: ikintr(ikon) ! 473: int ikon; ! 474: { ! 475: register struct ikdevice *ik; ! 476: register struct buf *bp, *dp; ! 477: struct ik_softc *sc; ! 478: register u_short data; ! 479: int v; ! 480: ! 481: /* should go by controller, but for now... */ ! 482: if (ikinfo[ikon] == 0) ! 483: return; ! 484: ik = (struct ikdevice *)ikinfo[ikon]->ui_addr; ! 485: /* ! 486: * Discard all non-attention interrupts. The ! 487: * interrupts we're throwing away should all be ! 488: * associated with DMA completion. ! 489: */ ! 490: data = ik->ik_data; ! 491: if ((ik->ik_csr&(IKCSR_ATTF|IKCSR_STATC)) != IKCSR_ATTF) { ! 492: ik->ik_pulse = IKPULSE_RATTF|IKPULSE_RDMAF|IKPULSE_SIENA; ! 493: return; ! 494: } ! 495: /* ! 496: * Fetch attention code immediately. ! 497: */ ! 498: ik->ik_csr = IKCSR_RATTF|IKCSR_RDMAF|IKCSR_FNC1; ! 499: ik->ik_pulse = IKPULSE_FNC2; ! 500: /* ! 501: * Get device and block structures, and a pointer ! 502: * to the vba_device for the device. We receive an ! 503: * unsolicited interrupt whenever the PS300 is power ! 504: * cycled (so ignore it in that case). ! 505: */ ! 506: dp = &iktab[ikon]; ! 507: if ((bp = dp->b_actf) == NULL) { ! 508: if (PS_CODE(data) != PS_RESET) /* power failure */ ! 509: log(LOG_WARNING, "ik%d: spurious interrupt, code %x\n", ! 510: ikon, data); ! 511: goto enable; ! 512: } ! 513: sc = &ik_softc[IKUNIT(bp->b_dev)]; ! 514: sc->is_timeout = 0; /* disable timer */ ! 515: switch (PS_CODE(data)) { ! 516: ! 517: case PS_LOOKUP: /* name lookup */ ! 518: if (data == PS_LOOKUP) { /* dma name */ ! 519: bp->b_command = PS_DMAOUT; ! 520: goto opcont; ! 521: } ! 522: if (data == PS_DMAOK(PS_LOOKUP)) { ! 523: /* reenable interrupt and wait for address */ ! 524: sc->is_timeout = iktimeout; ! 525: goto enable; ! 526: } ! 527: /* ! 528: * Address should be present, extract it one ! 529: * word at a time from the PS300 (yech). ! 530: */ ! 531: if (data != PS_ADROK(PS_LOOKUP)) ! 532: goto bad; ! 533: FETCHWORD(0); ! 534: FETCHWORD(1); ! 535: goto opdone; ! 536: ! 537: case PS_WRPHY_SYNC: /* physical i/o write w/ sync */ ! 538: if (data == PS_WRPHY_SYNC) { /* start dma transfer */ ! 539: bp->b_command = PS_DMAOUT; ! 540: goto opcont; ! 541: } ! 542: if (data != PS_DMAOK(PS_WRPHY_SYNC)) ! 543: goto bad; ! 544: goto opdone; ! 545: ! 546: case PS_WRPHY: /* physical i/o write */ ! 547: if (data == PS_WRPHY) { /* start dma transfer */ ! 548: bp->b_command = PS_DMAOUT; ! 549: goto opcont; ! 550: } ! 551: if (data != PS_DMAOK(PS_WRPHY)) ! 552: goto bad; ! 553: goto opdone; ! 554: ! 555: case PS_ATTACH: /* attach unit */ ! 556: case PS_DETACH: /* detach unit */ ! 557: case PS_ABORT: /* abort code from ps300 */ ! 558: if (data != bp->b_command) ! 559: goto bad; ! 560: goto opdone; ! 561: ! 562: case PS_RDPHY: /* physical i/o read */ ! 563: if (data == PS_RDPHY) { /* dma address list */ ! 564: bp->b_command = PS_DMAOUT; ! 565: goto opcont; ! 566: } ! 567: if (data == PS_ADROK(PS_RDPHY)) { ! 568: /* collect read byte count and start dma */ ! 569: bp->b_bcount = dioread(ik); ! 570: if (bp->b_bcount == -1) ! 571: goto bad; ! 572: bp->b_command = PS_DMAIN; ! 573: goto opcont; ! 574: } ! 575: if (data == PS_DMAOK(PS_RDPHY)) ! 576: goto opdone; ! 577: goto bad; ! 578: } ! 579: bad: ! 580: sc->is_error = data; ! 581: bp->b_flags |= B_ERROR; ! 582: opdone: ! 583: dp->b_actf = bp->av_forw; /* remove from queue */ ! 584: biodone(bp); ! 585: opcont: ! 586: ikstart(dp); ! 587: enable: ! 588: ik->ik_pulse = IKPULSE_SIENA; /* explicitly reenable */ ! 589: } ! 590: ! 591: /* ! 592: * Watchdog timer. ! 593: */ ! 594: iktimer(unit) ! 595: int unit; ! 596: { ! 597: register struct ik_softc *sc = &ik_softc[unit]; ! 598: ! 599: if (sc->is_timeout && --sc->is_timeout == 0) { ! 600: register struct buf *dp, *bp; ! 601: int s; ! 602: ! 603: log(LOG_ERR, "ik%d: timeout\n", unit); ! 604: s = splik(); ! 605: /* should abort current command */ ! 606: dp = &iktab[unit]; ! 607: if (bp = dp->b_actf) { ! 608: sc->is_error = PSERROR_CMDTIMO; ! 609: bp->b_flags |= B_ERROR; ! 610: dp->b_actf = bp->av_forw; /* remove from queue */ ! 611: biodone(bp); ! 612: ikstart(dp); ! 613: } ! 614: splx(s); ! 615: } ! 616: timeout(iktimer, (caddr_t)unit, hz); ! 617: } ! 618: ! 619: /* ! 620: * Handshake read from DR300. ! 621: */ ! 622: dioread(ik) ! 623: register struct ikdevice *ik; ! 624: { ! 625: register int t; ! 626: u_short data; ! 627: ! 628: for (t = ikdiotimo; t > 0; t--) ! 629: if ((ik->ik_csr&(IKCSR_ATTF|IKCSR_STATC)) == IKCSR_ATTF) { ! 630: data = ik->ik_data; ! 631: ik->ik_csr = IKCSR_RATTF|IKCSR_RDMAF|IKCSR_FNC1; ! 632: ik->ik_pulse = IKPULSE_FNC2; ! 633: return (data); ! 634: } ! 635: return (-1); ! 636: } ! 637: ! 638: /* ! 639: * Handshake write to DR300. ! 640: * ! 641: * Interrupts are enabled before completing the work ! 642: * so the caller should either be at splik or be ! 643: * prepared to take the interrupt immediately. ! 644: */ ! 645: diowrite(ik, v) ! 646: register struct ikdevice *ik; ! 647: u_short v; ! 648: { ! 649: register int t; ! 650: register u_short csr; ! 651: ! 652: top: ! 653: /* ! 654: * Deposit data and generate dr300 attention ! 655: */ ! 656: ik->ik_data = v; ! 657: ik->ik_csr = IKCSR_RDMAF|IKCSR_RATTF; ! 658: ik->ik_pulse = IKPULSE_FNC2; ! 659: for (t = ikdiotimo; t > 0; t--) { ! 660: csr = ik->ik_csr; ! 661: #define IKCSR_DONE (IKCSR_STATA|IKCSR_STATC) ! 662: if ((csr&IKCSR_DONE) == IKCSR_DONE) { ! 663: /* ! 664: * Done, complete handshake by notifying dr300. ! 665: */ ! 666: ik->ik_csr = IKCSR_IENA; /* ~IKCSR_FNC1 */ ! 667: ik->ik_pulse = IKPULSE_FNC2; ! 668: return (0); ! 669: } ! 670: /* beware of potential deadlock with dioread */ ! 671: if ((csr&(IKCSR_ATTF|IKCSR_STATC)) == IKCSR_ATTF) ! 672: goto top; ! 673: } ! 674: ik->ik_csr = IKCSR_IENA; ! 675: return (PSERROR_DIOTIMO); ! 676: } ! 677: ! 678: /*ARGSUSED*/ ! 679: ikioctl(dev, cmd, data, flag) ! 680: dev_t dev; ! 681: int cmd; ! 682: caddr_t data; ! 683: int flag; ! 684: { ! 685: int error = 0, unit = IKUNIT(dev), s; ! 686: register struct ik_softc *sc = &ik_softc[unit]; ! 687: ! 688: switch (cmd) { ! 689: ! 690: case PSIOGETERROR: /* get error code for last operation */ ! 691: *(int *)data = sc->is_error; ! 692: break; ! 693: ! 694: case PSIOLOOKUP: { /* PS300 name lookup */ ! 695: register struct pslookup *lp = (struct pslookup *)data; ! 696: register struct buf *bp; ! 697: ! 698: if (lp->pl_len > PS_MAXNAMELEN) ! 699: return (EINVAL); ! 700: bp = &rikbuf[unit]; ! 701: s = splbio(); ! 702: while (bp->b_flags&B_BUSY) { ! 703: bp->b_flags |= B_WANTED; ! 704: sleep((caddr_t)bp, PRIBIO+1); ! 705: } ! 706: splx(s); ! 707: bp->b_flags = B_BUSY | B_WRITE; ! 708: error = copyin(lp->pl_name, (caddr_t)sc->is_buf, ! 709: (unsigned)lp->pl_len); ! 710: if (error == 0) { ! 711: if (lp->pl_len&1) ! 712: sc->is_buf[lp->pl_len] = '\0'; ! 713: error = ikcommand(dev, PS_LOOKUP, lp->pl_len); ! 714: } ! 715: s = splbio(); ! 716: if (bp->b_flags&B_WANTED) ! 717: wakeup((caddr_t)bp); ! 718: splx(s); ! 719: bp->b_flags &= ~(B_BUSY|B_WANTED); ! 720: lp->pl_addr = sc->is_nameaddr.l; ! 721: break; ! 722: } ! 723: default: ! 724: return (ENOTTY); ! 725: } ! 726: return (error); ! 727: } ! 728: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.