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