home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / tahoe / vba / ik.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  17.1 KB  |  729 lines

  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
  729.