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

  1. /*
  2.  * Copyright (c) 1988 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Computer Consoles Inc.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  *    @(#)dr.c    7.9 (Berkeley) 12/16/90
  37.  */
  38.  
  39. #include "dr.h"
  40. #if NDR > 0
  41. /*
  42.  * DRV11-W DMA interface driver.
  43.  *
  44.  * UNTESTED WITH 4.3
  45.  */
  46. #include "../include/mtpr.h"
  47. #include "../include/pte.h"
  48.  
  49. #include "sys/param.h"
  50. #include "sys/conf.h"
  51. #include "sys/user.h"
  52. #include "sys/proc.h"
  53. #include "sys/map.h"
  54. #include "sys/ioctl.h"
  55. #include "sys/buf.h"
  56. #include "sys/vm.h"
  57. #include "sys/kernel.h"
  58.  
  59. #include "../vba/vbavar.h"
  60. #include "../vba/drreg.h"
  61.  
  62. #define YES 1
  63. #define NO  0
  64.  
  65. struct  vba_device  *drinfo[NDR];
  66. struct  dr_aux dr_aux[NDR];
  67.  
  68. unsigned drminphys();
  69. int     drprobe(), drintr(), drattach(), drtimo(), drrwtimo();
  70. int     drstrategy();
  71. extern    struct  vba_device  *drinfo[];
  72. static    long drstd[] = { 0 };
  73. struct  vba_driver drdriver =
  74.     { drprobe, 0, drattach, 0, drstd, "rs", drinfo };
  75.  
  76. #define RSUNIT(dev) (minor(dev) & 7)
  77. #define SPL_UP spl5
  78.  
  79. /* -------- Per-unit data -------- */
  80.  
  81. extern struct dr_aux dr_aux[];
  82.  
  83. #ifdef DR_DEBUG
  84. long    DR11 = 0;
  85. #endif
  86.  
  87. drprobe(reg, vi)
  88.     caddr_t reg;
  89.     struct vba_device *vi;
  90. {
  91.     register int br, cvec;        /* must be r12, r11 */
  92.     struct rsdevice *dr;
  93.  
  94. #ifdef lint
  95.     br = 0; cvec = br; br = cvec;
  96.     drintr(0);
  97. #endif
  98.     if (badaddr(reg, 2))
  99.         return (0);
  100.     dr = (struct rsdevice *)reg;
  101.     dr->dr_intvect = --vi->ui_hd->vh_lastiv;
  102. #ifdef DR_DEBUG
  103.     printf("dprobe: Set interrupt vector %lx and init\n",dr->dr_intvec);
  104. #endif
  105.     /* generate interrupt here for autoconfig */
  106.     dr->dr_cstat = MCLR;        /* init board and device */
  107. #ifdef DR_DEBUG
  108.     printf("drprobe: Initial status %lx\n", dr->dr_cstat);
  109. #endif
  110.     br = 0x18, cvec = dr->dr_intvect;    /* XXX */
  111.     return (sizeof (struct rsdevice));        /* DR11 exist */
  112. }
  113.  
  114. /* ARGSUSED */
  115. drattach(ui)
  116.     struct vba_device *ui;
  117. {
  118.     register struct dr_aux *rsd;
  119.  
  120.     rsd = &dr_aux[ui->ui_unit];
  121.     rsd->dr_flags = DR_PRES;        /* This dr11 is present */
  122.     rsd->dr_addr = (struct rsdevice *)ui->ui_addr; /* Save addr of this dr11 */
  123.     rsd->dr_istat = 0;
  124.     rsd->dr_bycnt = 0;
  125.     rsd->dr_cmd = 0;
  126.     rsd->currenttimo = 0;
  127. }
  128.  
  129. /*ARGSUSED*/
  130. dropen(dev, flag)
  131.     dev_t dev;
  132.     int flag;
  133. {
  134.     register int unit = RSUNIT(dev);
  135.     register struct rsdevice *dr;
  136.     register struct dr_aux *rsd;
  137.  
  138.     if (drinfo[unit] == 0 || !drinfo[unit]->ui_alive)
  139.         return (ENXIO);
  140.     dr = RSADDR(unit);
  141.     rsd = &dr_aux[unit];
  142.     if (rsd->dr_flags & DR_OPEN) {
  143. #ifdef DR_DEBUG
  144.         printf("\ndropen: dr11 unit %ld already open",unit);
  145. #endif
  146.         return (ENXIO);              /* DR11 already open */
  147.     }
  148.     rsd->dr_flags |= DR_OPEN;    /* Mark it OPEN */
  149.     rsd->dr_istat = 0;        /* Clear status of previous interrupt */
  150.     rsd->rtimoticks = hz;        /* Set read no stall timout to 1 sec */
  151.     rsd->wtimoticks = hz*60;    /* Set write no stall timout to 1 min */
  152.     dr->dr_cstat = DR_ZERO;        /* Clear function & latches */
  153.     dr->dr_pulse = (RDMA | RATN);    /* clear leftover attn & e-o-r flags */
  154.     drtimo(dev);            /* start the self kicker */
  155.     return (0);
  156. }
  157.  
  158. drclose (dev)
  159.     dev_t dev;
  160. {
  161.     register int unit = RSUNIT(dev);
  162.     register struct dr_aux *dra;
  163.     register struct rsdevice *rs;
  164.     register short s;
  165.  
  166.     dra = &dr_aux[unit];
  167.     if ((dra->dr_flags & DR_OPEN) == 0) {
  168. #ifdef DR_DEBUG
  169.         printf("\ndrclose: DR11 device %ld not open",unit);
  170. #endif
  171.         return;
  172.     }
  173.     dra->dr_flags &= ~(DR_OPEN|DR_ACTV);
  174.     rs = dra->dr_addr;
  175.     s = SPL_UP();
  176.     rs->dr_cstat = DR_ZERO;
  177.     if (dra->dr_buf.b_flags & B_BUSY) {
  178.         dra->dr_buf.b_flags &= ~B_BUSY;
  179.         wakeup((caddr_t)&dra->dr_buf.b_flags);
  180.     }
  181.     splx(s);
  182.     return (0);
  183. }
  184.  
  185.  
  186. /*    drread() works exactly like drwrite() except that the
  187.     B_READ flag is used when physio() is called
  188. */
  189. drread (dev, uio)
  190.     dev_t dev;
  191.     struct uio *uio;
  192. {    register struct dr_aux *dra;
  193.     register struct buf *bp;
  194.     register int spl, err;
  195.     register int unit = RSUNIT(dev);
  196.  
  197.     if (uio->uio_iov->iov_len <= 0 ||    /* Negative count */
  198.         uio->uio_iov->iov_len & 1 ||    /* odd count */
  199.         (int)uio->uio_iov->iov_base & 1)    /* odd destination address */
  200.         return (EINVAL);
  201. #ifdef DR_DEBUG
  202.     if (DR11 & 8)
  203.         printf("\ndrread: (len:%ld)(base:%lx)",
  204.             uio->uio_iov->iov_len,(int)uio->uio_iov->iov_base); 
  205. #endif
  206.     dra = &dr_aux[RSUNIT(dev)];
  207.     dra->dr_op = DR_READ;
  208.     bp =  &dra->dr_buf;
  209.     bp->b_resid = 0;
  210.     if (dra->dr_flags & DR_NORSTALL) {
  211.         /*
  212.          * We are in no stall mode, start the timer,
  213.          * raise IPL so nothing can stop us once the
  214.          * timer's running
  215.          */
  216.         spl = SPL_UP();
  217.         timeout(drrwtimo, (caddr_t)((dra->currenttimo<<8) | unit),
  218.             (int)dra->rtimoticks);
  219.         err = physio(drstrategy, bp, dev,B_READ, drminphys, uio);
  220.         splx(spl);
  221.         if (err)
  222.             return (err);
  223.         dra->currenttimo++;    /* Update current timeout number */
  224.         /* Did we timeout */
  225.         if (dra->dr_flags & DR_TMDM)
  226.             dra->dr_flags &= ~DR_TMDM; /* Clear timeout flag */
  227.         return (err);
  228.     }
  229.     return (physio(drstrategy, bp, dev,B_READ, drminphys, uio));
  230. }
  231.  
  232. drwrite(dev, uio)
  233.     dev_t dev;
  234.     struct uio *uio;
  235. {    register struct dr_aux *dra;
  236.     register struct buf *bp;
  237.     register int unit = RSUNIT(dev);
  238.     int spl, err;
  239.  
  240.     if (uio->uio_iov->iov_len <= 0 || uio->uio_iov->iov_len & 1 ||
  241.         (int)uio->uio_iov->iov_base & 1)
  242.         return (EINVAL);
  243. #ifdef DR_DEBUG
  244.     if (DR11 & 4)
  245.         printf("\ndrwrite: (len:%ld)(base:%lx)",
  246.             uio->uio_iov->iov_len,(int)uio->uio_iov->iov_base); 
  247. #endif
  248.     dra = &dr_aux[RSUNIT(dev)];
  249.     dra->dr_op = DR_WRITE;
  250.     bp =  &dra->dr_buf;
  251.     bp->b_resid = 0;
  252.     if (dra->dr_flags & DR_NOWSTALL) {
  253.         /*
  254.          * We are in no stall mode, start the timer,
  255.          * raise IPL so nothing can stop us once the
  256.          * timer's running
  257.          */
  258.         spl = SPL_UP();
  259.         timeout(drrwtimo,(caddr_t)((dra->currenttimo<<8) | unit),
  260.             (int)dra->wtimoticks);
  261.         err = physio (drstrategy, bp, dev,B_WRITE, drminphys, uio);
  262.         splx(spl);
  263.         if (err)
  264.             return (err);
  265.         dra->currenttimo++;    /* Update current timeout number */
  266.         /* Did we timeout */
  267.         if (dra->dr_flags & DR_TMDM)
  268.             dra->dr_flags &= ~DR_TMDM;    /* Clear timeout flag */
  269.         return (err);
  270.     }
  271.     return (physio(drstrategy, bp, dev,B_WRITE, drminphys, uio));
  272. }
  273.  
  274. /*
  275.  * Routine used by calling program to issue commands to dr11 driver and 
  276.  * through it to the device.
  277.  * It is also used to read status from the device and driver and to wait 
  278.  * for attention interrupts.
  279.  * Status is returned in an 8 elements unsigned short integer array, the 
  280.  * first two elements of the array are also used to pass arguments to 
  281.  * drioctl() if required.
  282.  * The function bits to be written to the dr11 are included in the cmd
  283.  * argument. Even if they are not being written to the dr11 in a particular
  284.  * drioctl() call, they will update the copy of cmd that is stored in the
  285.  * driver. When drstrategy() is called, this updated copy is used if a 
  286.  * deferred function bit write has been specified. The "side effect" of
  287.  * calls to the drioctl() requires that the last call prior to a read or
  288.  * write has an appropriate copy of the function bits in cmd if they are
  289.  * to be used in drstrategy().
  290.  * When used as command value, the contents of data[0] is the command
  291.  * parameter.
  292.  */
  293. drioctl(dev, cmd, data)
  294.     dev_t dev;
  295.     int cmd;
  296.     long *data;
  297. {
  298.     register int unit = RSUNIT(dev);
  299.     register struct dr_aux *dra;
  300.     register struct rsdevice *rsaddr = RSADDR(unit);
  301.     int s, error = 0;
  302.     u_short status;
  303.     long temp;
  304.  
  305. #ifdef DR_DEBUG
  306.     if (DR11 & 0x10)
  307.         printf("\ndrioctl: (dev:%lx)(cmd:%lx)(data:%lx)(data[0]:%lx)",
  308.             dev,cmd,data,data[0]);
  309. #endif
  310.     dra = &dr_aux[unit];
  311.     dra->dr_cmd = 0;    /* Fresh copy; clear all previous flags */
  312.     switch (cmd) {
  313.  
  314.     case DRWAIT:        /* Wait for attention interrupt */
  315. #ifdef DR_DEBUG
  316.         printf("\ndrioctl: wait for attention interrupt");
  317. #endif
  318.         s = SPL_UP();
  319.         /* 
  320.          * If the attention flag in dr_flags is set, it probably
  321.          * means that an attention has arrived by the time a
  322.          * previous DMA end-of-range interrupt was serviced. If
  323.          * ATRX is set, we will return with out sleeping, since
  324.          * we have received an attention since the last call to
  325.          * wait on attention.  This may not be appropriate for
  326.          * some applications.
  327.          */
  328.         if ((dra->dr_flags & DR_ATRX) == 0) {
  329.             dra->dr_flags |= DR_ATWT;    /* Set waiting flag */
  330.             /*
  331.              * Enable interrupt; use pulse reg.
  332.              * so function bits are not changed
  333.              */
  334.             rsaddr->dr_pulse = IENB;
  335.             error = tsleep((caddr_t)&dra->dr_cmd, DRPRI | PCATCH,
  336.                 devio, 0);
  337.         }
  338.         splx(s);
  339.         break;
  340.  
  341.     case DRPIOW:            /* Write to p-i/o register */
  342.         rsaddr->dr_data = data[0];
  343.         break;
  344.  
  345.     case DRPACL:            /* Send pulse to device */
  346.         rsaddr->dr_pulse = FCN2;
  347.         break;
  348.  
  349.     case DRDACL:            /* Defer alco pulse until go */
  350.         dra->dr_cmd |= DR_DACL;
  351.         break;
  352.  
  353.     case DRPCYL:            /* Set cycle with next go */
  354.         dra->dr_cmd |= DR_PCYL;
  355.         break;
  356.  
  357.     case DRDFCN:            /* Update function with next go */
  358.         dra->dr_cmd |= DR_DFCN;
  359.         break;
  360.  
  361.     case DRRATN:            /* Reset attention flag */
  362.         rsaddr->dr_pulse = RATN;
  363.         break;
  364.  
  365.     case DRRDMA:            /* Reset DMA e-o-r flag */
  366.         rsaddr->dr_pulse = RDMA;
  367.         break;
  368.  
  369.     case DRSFCN:            /* Set function bits */
  370.         temp = data[0] & DR_FMSK;
  371.         /*
  372.          * This has a very important side effect -- It clears
  373.          * the interrupt enable flag. That is fine for this driver,
  374.          * but if it is desired to leave interrupt enable at all
  375.          * times, it will be necessary to read the status register
  376.          * first to get IENB, or carry a software flag that indicates
  377.          * whether interrupts are set, and or this into the control
  378.          * register value being written.
  379.          */
  380.         rsaddr->dr_cstat = temp;
  381.         break;
  382.  
  383.     case DRRPER:            /* Clear parity flag */
  384.         rsaddr->dr_pulse = RPER;
  385.         break;
  386.  
  387.     case DRSETRSTALL:        /* Set read stall mode. */
  388.         dra->dr_flags &= (~DR_NORSTALL);
  389.         break;
  390.  
  391.     case DRSETNORSTALL:        /* Set no stall read  mode. */
  392.         dra->dr_flags |= DR_NORSTALL;
  393.         break;
  394.  
  395.     case DRGETRSTALL:        /* Returns true if in read stall mode */
  396.         data[0]  = (dra->dr_flags & DR_NORSTALL)? 0 : 1;
  397.         break;
  398.  
  399.     case DRSETRTIMEOUT:        /* Set read stall timeout (1/10 secs) */
  400.         if (data[0] < 1)
  401.             error = EINVAL;
  402.         dra->rtimoticks = (data[0] * hz )/10;
  403.         break;
  404.  
  405.     case DRGETRTIMEOUT:        /* Return read stall timeout */
  406.         data[0] = ((dra->rtimoticks)*10)/hz;
  407.         break;
  408.  
  409.     case DRSETWSTALL:        /* Set write stall mode. */
  410.         dra->dr_flags &= (~DR_NOWSTALL);
  411.         break;
  412.  
  413.     case DRSETNOWSTALL:        /* Set write stall mode. */
  414.         dra->dr_flags |= DR_NOWSTALL;
  415.         break;
  416.  
  417.     case DRGETWSTALL:        /* Return true if in write stall mode */
  418.         data[0] = (dra->dr_flags & DR_NOWSTALL)? 0 : 1;
  419.         break;
  420.  
  421.     case DRSETWTIMEOUT:        /* Set write stall timeout (1/10's) */
  422.         if (data[0] < 1)
  423.             error = EINVAL;
  424.         dra->wtimoticks = (data[0] * hz )/10;
  425.         break;
  426.  
  427.     case DRGETWTIMEOUT:        /* Return write stall timeout */
  428.         data[0] = ((dra->wtimoticks)*10)/hz;
  429.         break;
  430.  
  431.     case DRWRITEREADY:        /* Return true if can write data */
  432.         data[0] = (rsaddr->dr_cstat & STTA)? 1 : 0;
  433.         break;
  434.  
  435.     case DRREADREADY:        /* Return true if data to be read */
  436.         data[0] = (rsaddr->dr_cstat & STTB)? 1 : 0;
  437.         break;
  438.  
  439.     case DRBUSY:            /* Return true if device busy */
  440.         /*
  441.          * Internally this is the DR11-W
  442.          * STAT C bit, but there is a bug in the Omega 500/FIFO
  443.          * interface board that it cannot drive this signal low
  444.          * for certain DR11-W ctlr such as the Ikon. We use the
  445.          * REDY signal of the CSR on the Ikon DR11-W instead. 
  446.          */
  447. #ifdef notdef
  448.         data[0] = (rsaddr->dr_cstat & STTC)? 1 : 0;
  449. #else
  450.         data[0] = ((rsaddr->dr_cstat & REDY)? 0 : 1);
  451. #endif
  452.         break;
  453.  
  454.     case DRRESET:            /* Reset device */
  455.         /* Reset DMA ATN RPER flag */
  456.         rsaddr->dr_pulse = (MCLR|RDMA|RATN|RPER);
  457.         DELAY(0x1f000);
  458.         while ((rsaddr->dr_cstat & REDY) == 0 && error == 0)
  459.             /* Wakeup by drtimo() */
  460.             error = tsleep((caddr_t)dra, DRPRI | PCATCH, devio, 0);    
  461.         dra->dr_istat = 0;
  462.         dra->dr_cmd = 0;
  463.         dra->currenttimo = 0;
  464.         break;
  465.  
  466.     case DR11STAT: {        /* Copy back dr11 status to user */
  467.         register struct dr11io *dr = (struct dr11io *)data;
  468.         dr->arg[0] = dra->dr_flags;
  469.         dr->arg[1] = rsaddr->dr_cstat;
  470.         dr->arg[2] = dra->dr_istat;    /* Status at last interrupt */
  471.         dr->arg[3] = rsaddr->dr_data;    /* P-i/o input data */
  472.         status = (u_short)((rsaddr->dr_addmod << 8) & 0xff00);
  473.         dr->arg[4] = status | (u_short)(rsaddr->dr_intvect & 0xff);
  474.         dr->arg[5] = rsaddr->dr_range;
  475.         dr->arg[6] = rsaddr->dr_rahi;
  476.         dr->arg[7] = rsaddr->dr_ralo;
  477.         break;
  478.     }
  479.     case DR11LOOP:            /* Perform loopback test */
  480.         /*
  481.          * NB: MUST HAVE LOOPBACK CABLE ATTACHED --
  482.          * Test results are printed on system console
  483.          */
  484.         if (error = suser(u.u_cred, &u.u_acflag))
  485.             break;
  486.         dr11loop(rsaddr, dra, unit);
  487.         break;
  488.  
  489.     default:
  490.         return (EINVAL);
  491.     }
  492. #ifdef DR_DEBUG
  493.     if (DR11 & 0x10)
  494.         printf("**** (data[0]:%lx)",data[0]);
  495. #endif
  496.     return (error);
  497. }
  498.  
  499. #define NPAT    2
  500. #define DMATBL    20
  501. u_short    tstpat[DMATBL] = { 0xAAAA, 0x5555};
  502. long    DMAin = 0;
  503.  
  504. /*
  505.  * Perform loopback test -- MUST HAVE LOOPBACK CABLE ATTACHED
  506.  * Test results are printed on system console
  507.  */
  508. dr11loop(dr, dra, unit)
  509.     struct rsdevice *dr;
  510.     struct dr_aux *dra;
  511.     int unit;
  512. {
  513.     register long result, ix;
  514.     long addr, wait;
  515.  
  516.     dr->dr_cstat = MCLR;        /* Clear board & device, disable intr */
  517.     printf("\n\t ----- DR11 unit %ld loopback test -----", unit);
  518.     printf("\n\t Program I/O ...");
  519.     for (ix=0;ix<NPAT;ix++) {
  520.         dr->dr_data = tstpat[ix];    /* Write to Data out register */
  521.         result = dr->dr_data & 0xFFFF;    /* Read it back */
  522.         if (result != tstpat[ix]) {
  523.             printf("Failed, expected : %lx --- actual : %lx",
  524.                 tstpat[ix], result);
  525.             return;
  526.         }
  527.     }
  528.     printf("OK\n\t Functions & Status Bits ...");
  529.     dr->dr_cstat = (FCN1 | FCN3);
  530.     result = dr->dr_cstat & 0xffff;        /* Read them back */
  531.     if ((result & (STTC | STTA)) != (STTC |STTA)) {
  532.         printf("Failed, expected : %lx --- actual : %lx, ISR:%lx",
  533.             (STTA|STTC), (result & (STTA|STTC)), result);
  534.         return;
  535.     }
  536.     dr->dr_cstat = FCN2;
  537.     result = dr->dr_cstat & 0xffff;        /* Read them back */
  538.     if ((result & STTB) != STTB) {
  539.         printf("Failed, expected : %lx --- actual : %lx, ISR:%lx",
  540.             STTB, (result & STTB), result);
  541.         return;
  542.     }
  543.     printf("OK\n\t DMA output ...");
  544.     if (DMAin)
  545.         goto dmain;
  546.     /* Initialize DMA data buffer */
  547.     for (ix=0; ix<DMATBL; ix++)
  548.         tstpat[ix] = 0xCCCC + ix;
  549.     tstpat[DMATBL-1] = 0xCCCC;    /* Last word output */
  550.     /* Setup normal DMA */
  551.     addr = (long)vtoph((struct proc *)0, (unsigned)tstpat);
  552.     dr->dr_walo = (addr >> 1) & 0xffff;
  553.     dr->dr_wahi = (addr >> 17) & 0x7fff;
  554.     /* Set DMA range count: (number of words - 1) */
  555.     dr->dr_range = DMATBL - 1;
  556.     /* Set address modifier code to be used for DMA access to memory */
  557.     dr->dr_addmod = DRADDMOD;
  558.  
  559.     /*
  560.      * Clear dmaf and attf to assure a clean dma start, also disable
  561.      * attention interrupt
  562.      */
  563.     dr->dr_pulse = RDMA|RATN|RMSK;  /* Use pulse register */
  564.     dr->dr_cstat = GO|CYCL;          /* GO...... */
  565.  
  566.     /* Wait for DMA complete; REDY and DMAF are true in ISR */
  567.     wait = 0;
  568.     while ((result=(dr->dr_cstat & (REDY|DMAF))) != (REDY|DMAF)) {
  569.         printf("\n\tWait for DMA complete...ISR : %lx", result);
  570.         if (++wait > 5) {
  571.             printf("\n\t DMA output fails...timeout!!, ISR:%lx",
  572.                 result);
  573.             return;
  574.         }
  575.     }
  576.     result = dr->dr_data & 0xffff;        /* Read last word output */    
  577.     if (result != 0xCCCC) {
  578.         printf("\n\t Fails, expected : %lx --- actual : %lx",
  579.             0xCCCC, result);
  580.         return;
  581.     }
  582.     printf("OK\n\t DMA input ...");
  583. dmain:
  584.     dr->dr_data = 0x1111;        /* DMA input data */
  585.     /* Setup normal DMA */
  586.     addr = (long)vtoph((struct proc *)0, (unsigned)tstpat);
  587.     dr->dr_walo = (addr >> 1) & 0xffff;
  588.     dr->dr_wahi = (addr >> 17) & 0x7fff;
  589.     dr->dr_range = DMATBL - 1;
  590.     dr->dr_addmod = (char)DRADDMOD;
  591.     dr->dr_cstat = FCN1;        /* Set FCN1 in ICR to DMA in*/
  592.     if ((dra->dr_flags & DR_LOOPTST) == 0) {
  593.         /* Use pulse reg */  
  594.         dr->dr_pulse = RDMA|RATN|RMSK|CYCL|GO;
  595.         /* Wait for DMA complete; REDY and DMAF are true in ISR */
  596.         wait = 0;
  597.         while ((result=(dr->dr_cstat & (REDY|DMAF))) != (REDY|DMAF)) {
  598.             printf("\n\tWait for DMA to complete...ISR:%lx",result);
  599.             if (++wait > 5) {
  600.                 printf("\n\t DMA input timeout!!, ISR:%lx",
  601.                     result);
  602.                 return;
  603.             }
  604.         }
  605.     } else  {
  606.         /* Enable DMA e-o-r interrupt */
  607.         dr->dr_pulse = IENB|RDMA|RATN|CYCL|GO;
  608.         /* Wait for DMA complete; DR_LOOPTST is false in dra->dr_flags*/
  609.         wait = 0;
  610.         while (dra->dr_flags & DR_LOOPTST) { 
  611.             result = dr->dr_cstat & 0xffff;
  612.             printf("\n\tWait for DMA e-o-r intr...ISR:%lx", result);
  613.             if (++wait > 7) {
  614.                 printf("\n\t DMA e-o-r timeout!!, ISR:%lx",
  615.                     result);
  616.                 dra->dr_flags &= ~DR_LOOPTST;
  617.                 return;
  618.             }
  619.         }
  620.         dra->dr_flags |= DR_LOOPTST;
  621.     }
  622.     mtpr(P1DC, tstpat);            /* Purge cache */
  623.     mtpr(P1DC, 0x3ff+tstpat);
  624.     for (ix=0; ix<DMATBL; ix++) {
  625.         if (tstpat[ix] != 0x1111) {
  626.             printf("\n\t Fails, ix:%d, expected:%x --- actual:%x",
  627.                 ix, 0x1111, tstpat[ix]);
  628.             return;
  629.         }
  630.     }
  631.     if ((dra->dr_flags & DR_LOOPTST) == 0) {
  632.         dra->dr_flags |= DR_LOOPTST;
  633.         printf(" OK..\n\tDMA end of range interrupt...");
  634.         goto dmain;
  635.     }
  636.     printf(" OK..\n\tAttention interrupt....");
  637.     dr->dr_pulse = IENB|RDMA;
  638.     dr->dr_pulse = FCN2;
  639.     /* Wait for ATTN interrupt; DR_LOOPTST is false in dra->dr_flags*/
  640.     wait = 0;
  641.     while (dra->dr_flags & DR_LOOPTST) { 
  642.         result = dr->dr_cstat & 0xffff;
  643.         printf("\n\tWait for Attention intr...ISR:%lx",result);
  644.         if (++wait > 7) {
  645.             printf("\n\t Attention interrupt timeout!!, ISR:%lx",
  646.                 result);
  647.             dra->dr_flags &= ~DR_LOOPTST;
  648.             return;
  649.         }
  650.     }
  651.     dra->dr_flags &= ~DR_LOOPTST;
  652.     printf(" OK..\n\tDone...");
  653. }
  654.  
  655. /* Reset state on Unibus reset */
  656. /*ARGSUSED*/
  657. drreset(uban)
  658.     int uban;
  659. {
  660.  
  661. }
  662.  
  663. /*
  664.  * An interrupt is caused either by an error,
  665.  * base address overflow, or transfer complete
  666.  */
  667. drintr(dr11)
  668.     int dr11;
  669. {
  670.     register struct dr_aux *dra = &dr_aux[dr11];
  671.     register struct rsdevice *rsaddr = RSADDR(dr11);
  672.     register struct buf *bp;
  673.     register short status;
  674.  
  675.     status = rsaddr->dr_cstat & 0xffff;    /* get board status register */
  676.     dra->dr_istat = status;
  677. #ifdef DR_DEBUG
  678.     if (DR11 & 2)
  679.         printf("\ndrintr: dr11 status : %lx",status & 0xffff);
  680. #endif
  681.     if (dra->dr_flags & DR_LOOPTST) {    /* doing loopback test */
  682.         dra->dr_flags &= ~DR_LOOPTST;
  683.         return;
  684.     }
  685.     /*
  686.      * Make sure this is not a stray interrupt; at least one of dmaf or attf
  687.      * must be set. Note that if the dr11 interrupt enable latch is reset 
  688.      * during a hardware interrupt ack sequence, and by the we get to this 
  689.      * point in the interrupt code it will be 0. This is done to give the
  690.      * programmer some control over how the two more-or-less independent
  691.      * interrupt sources on the board are handled.
  692.      * If the attention flag is set when drstrategy() is called to start a
  693.      * dma read or write an interrupt will be generated as soon as the
  694.      * strategy routine enables interrupts for dma end-of-range. This will
  695.      * cause execution of the interrupt routine (not necessarily bad) and
  696.      * will cause the interrupt enable mask to be reset (very bad since the
  697.      * dma end-of-range condition will not be able to generate an interrupt
  698.      * when it occurs) causing the dma operation to time-out (even though
  699.      * the dma transfer will be done successfully) or hang the process if a
  700.      * software time-out capability is not implemented. One way to avoid 
  701.      * this situation is to check for a pending attention interrupt (attf
  702.      * set) by calling drioctl() before doing a read or a write. For the
  703.      * time being this driver will solve the problem by clearing the attf
  704.      * flag in the status register before enabling interrupts in
  705.      * drstrategy().
  706.      *
  707.      * **** The IKON 10084 for which this driver is written will set both
  708.      * attf and dmaf if dma is terminated by an attention pulse. This will
  709.      * cause a wakeup(&dr_aux), which will be ignored since it is not being 
  710.      * waited on, and an iodone(bp) which is the desired action. Some other
  711.      * dr11 emulators, in particular the IKON 10077 for the Multibus, donot
  712.      * dmaf in this case. This may require some addtional code in the inter-
  713.      * rupt routine to ensure that en iodone(bp) is issued when dma is term-
  714.      * inated by attention.
  715.      */
  716.     bp = dra->dr_actf;
  717.     if ((status & (ATTF | DMAF)) == 0) {
  718.         printf("dr%d: stray interrupt, status=%x", dr11, status);
  719.         return;
  720.     }
  721.     if (status & DMAF) {        /* End-of-range interrupt */
  722.         dra->dr_flags |= DR_DMAX;
  723.  
  724. #ifdef DR_DEBUG
  725.         if (DR11 & 2)
  726.         printf("\ndrintr: e-o-r interrupt,cstat:%lx,dr_flags:%lx",
  727.             status&0xffff, dra->dr_flags & DR_ACTV);
  728. #endif
  729.         if ((dra->dr_flags & DR_ACTV) == 0) {
  730.             /* We are not doing DMA !! */
  731.             bp->b_flags |= B_ERROR;
  732.         } else {
  733.             if (dra->dr_op == DR_READ)
  734.                 mtpr(P1DC, bp->b_un.b_addr);
  735.             dra->dr_bycnt -= bp->b_bcount;
  736.             if (dra->dr_bycnt >0) {
  737.                 bp->b_un.b_addr += bp->b_bcount;
  738.                 bp->b_bcount = (dra->dr_bycnt > NBPG) ? NBPG:
  739.                     dra->dr_bycnt;
  740.                 drstart(rsaddr, dra, bp);
  741.                 return;
  742.             }
  743.         }
  744.         dra->dr_flags &= ~DR_ACTV;
  745.         wakeup((caddr_t)dra);        /* Wakeup waiting in drwait() */
  746.         rsaddr->dr_pulse = (RPER|RDMA|RATN); /* reset dma e-o-r flag */
  747.     }
  748.     /*
  749.      * Now test for attention interrupt -- It may be set in addition to 
  750.      * the dma e-o-r interrupt. If we get one we will issue a wakeup to
  751.      * the drioctl() routine which is presumable waiting for one.
  752.      * The program may have to monitor the attention interrupt received
  753.      * flag in addition to doing waits for the interrupt. Futhermore, 
  754.      * interrupts are not enabled unless dma is in progress or drioctl()
  755.      * has been called to wait for attention -- this may produce some
  756.      * strange results if attf is set on the dr11 when a read or a write
  757.      * is initiated, since that will enables interrupts.
  758.      * **** The appropriate code for this interrupt routine will probably
  759.      * be rather application dependent.
  760.      */
  761.     if (status & ATTF) {
  762.         dra->dr_flags |= DR_ATRX;
  763.         dra->dr_flags &= ~DR_ATWT;
  764.         rsaddr->dr_cstat = RATN;    /* reset attention flag */
  765.         /*
  766.          * Some applications which use attention to terminate
  767.          * dma may also want to issue an iodone() here to
  768.          * wakeup physio().
  769.          */
  770.         wakeup((caddr_t)&dra->dr_cmd);
  771.     }
  772. }
  773.  
  774. unsigned
  775. drminphys(bp)
  776.     struct buf *bp;
  777. {
  778.  
  779.     if (bp->b_bcount > 65536)
  780.         bp->b_bcount = 65536;
  781. }
  782.  
  783. /*
  784.  * This routine performs the device unique operations on the DR11W
  785.  * it is passed as an argument to and invoked by physio
  786.  */
  787. drstrategy (bp)
  788.     register struct buf *bp;
  789. {
  790.     register int s;
  791.     int unit = RSUNIT(bp->b_dev);
  792.     register struct rsdevice *rsaddr = RSADDR(unit);
  793.     register struct dr_aux *dra = &dr_aux[unit];
  794.     register int ok;
  795. #ifdef DR_DEBUG
  796.     register char *caddr;
  797.     long drva();
  798. #endif
  799.  
  800.     if ((dra->dr_flags & DR_OPEN) == 0) {    /* Device not open */
  801.         bp->b_error = ENXIO;
  802.         bp->b_flags |= B_ERROR;
  803.         iodone (bp);
  804.         return;
  805.     }
  806.     while (dra->dr_flags & DR_ACTV)
  807.         /* Device is active; should never be in here... */
  808.         (void) tsleep((caddr_t)&dra->dr_flags, DRPRI, devio, 0);
  809.     dra->dr_actf = bp;
  810. #ifdef DR_DEBUG
  811.     drva(dra, bp->b_proc, bp->b_un.b_addr, bp->b_bcount);
  812. #endif
  813.     dra->dr_oba = bp->b_un.b_addr;    /* Save original addr, count */
  814.     dra->dr_obc = bp->b_bcount;
  815.     dra->dr_bycnt = bp->b_bcount;    /* Save xfer count used by drintr() */
  816.     if ((((long)bp->b_un.b_addr & 0x3fffffff) >> PGSHIFT) !=
  817.         ((((long)bp->b_un.b_addr & 0x3fffffff) + bp->b_bcount) >> PGSHIFT))
  818.         bp->b_bcount = NBPG - (((long)bp->b_un.b_addr) & PGOFSET);
  819.     dra->dr_flags |= DR_ACTV;    /* Mark active (use in intr handler) */
  820.     s = SPL_UP();
  821.     drstart(rsaddr,dra,bp);
  822.     splx(s);
  823.     ok = drwait(rsaddr,dra);
  824. #ifdef DR_DEBUG
  825.     if (DR11 & 0x40) {
  826.         caddr = (char *)dra->dr_oba;
  827.         if (dra->dr_op == DR_READ)
  828.             printf("\nAfter read: (%lx)(%lx)",
  829.                 caddr[0]&0xff, caddr[1]&0xff);
  830.     }
  831. #endif
  832.     dra->dr_flags &= ~DR_ACTV;        /* Clear active flag */
  833.     bp->b_un.b_addr = dra->dr_oba;    /* Restore original addr, count */
  834.     bp->b_bcount = dra->dr_obc;
  835.     if (!ok)
  836.         bp->b_flags |= B_ERROR;
  837.     /* Mark buffer B_DONE,so physstrat() in ml/machdep.c won't sleep */
  838.     iodone(bp);            
  839.     wakeup((caddr_t)&dra->dr_flags);
  840.     /*
  841.      * Return to the calling program (physio()). Physio() will sleep
  842.      * until awaken by a call to iodone() in the interupt handler --
  843.      * which will be called by the dispatcher when it receives dma
  844.      * end-of-range interrupt.
  845.      */
  846. }
  847.  
  848. drwait(rs, dr)
  849.     register struct rsdevice *rs;
  850.     register struct dr_aux *dr;
  851. {
  852.     int s;
  853.  
  854.     s = SPL_UP();
  855.     while (dr->dr_flags & DR_ACTV)
  856.         (void) tsleep((caddr_t)dr, DRPRI, devio, 0);
  857.     splx(s);
  858.     if (dr->dr_flags & DR_TMDM) {        /* DMA timed out */
  859.         dr->dr_flags &= ~DR_TMDM;
  860.         return (0);
  861.     }
  862.     if (rs->dr_cstat & (PERR|BERR|TERR)) {
  863.         dr->dr_actf->b_flags |= B_ERROR;
  864.         return (0);
  865.     }
  866.     dr->dr_flags &= ~DR_DMAX;
  867.     return (1);
  868. }
  869.  
  870. /*
  871.  *
  872.  * The lower 8-bit of tinfo is the minor device number, the
  873.  * remaining higher 8-bit is the current timout number
  874.  */
  875. drrwtimo(tinfo)
  876.     register u_long tinfo;
  877. {
  878.     register long unit = tinfo & 0xff;
  879.     register struct dr_aux *dr = &dr_aux[unit];
  880.     register struct rsdevice *rs = dr->dr_addr;
  881.  
  882.     /*
  883.      * If this is not the timeout that drwrite/drread is waiting
  884.      * for then we should just go away
  885.      */
  886.     if ((tinfo &~ 0xff) != (dr->currenttimo << 8))
  887.         return;
  888.     /* Mark the device timed out */
  889.     dr->dr_flags |= DR_TMDM;
  890.     dr->dr_flags &= ~DR_ACTV;
  891.     rs->dr_pulse = RMSK;            /* Inihibit interrupt */
  892.     rs->dr_pulse = (RPER|RDMA|RATN|IENB);    /* Clear DMA logic */
  893.     /*
  894.      * Some applications will not issue a master after dma timeout,
  895.      * since doing so sends an INIT H pulse to the external device,
  896.      * which may produce undesirable side-effects.
  897.      */
  898.     /* Wake up process waiting in drwait() and flag the error */
  899.     dr->dr_actf->b_flags |= B_ERROR;
  900.     wakeup((caddr_t)dr->dr_cmd);
  901. }
  902.  
  903. /*
  904.  * Kick the driver every second
  905.  */
  906. drtimo(dev)
  907.     dev_t dev;
  908. {
  909.     register int unit = RSUNIT(dev);
  910.     register struct dr_aux *dr;
  911.  
  912.     dr = &dr_aux[unit];
  913.     if (dr->dr_flags & DR_OPEN)
  914.         timeout(drtimo, (caddr_t)dev, hz);
  915.     wakeup((caddr_t)dr);    /* Wakeup any process waiting for interrupt */
  916. }
  917.  
  918. #ifdef DR_DEBUG
  919. drva(dra, p, va, bcnt)
  920.     struct dr_aux *dra;
  921.     struct proc *p;
  922.     char *va;
  923.     long bcnt;
  924. {
  925.     register long first, last , np;
  926.  
  927.     if (DR11 & 0x20)  {
  928.         first = ((long)(vtoph(p, (unsigned)va))) >> 10;
  929.         last = ((long)(vtoph(p, (unsigned)va+bcnt))) >> 10;
  930.         np = bcnt / 0x3ff;
  931.         printf("\ndrva: (op:%ld)(first:%ld)(last:%ld)(np:%ld)(cnt:%ld)",
  932.             dra->dr_op,first,last,np,bcnt);
  933.     }
  934. }
  935. #endif
  936.  
  937. drstart(rsaddr, dra, bp)
  938.     register struct rsdevice *rsaddr;
  939.     register struct dr_aux *dra;
  940.     register struct buf *bp;
  941. {
  942.     register long addr;
  943.     u_short go;
  944.  
  945. #ifdef DR_DEBUG
  946.     if (dra->dr_op == DR_READ && (DR11 & 8)) {
  947.         char *caddr = (char *)bp->b_un.b_addr;
  948.         printf("\ndrstart: READ, bcnt:%ld",bp->b_bcount);
  949.         printf(",(%lx)(%lx)",caddr[0]&0xff,caddr[1]&0xff);
  950.     }
  951. #endif
  952.     /* we are doing raw IO, bp->b_un.b_addr is user's address */
  953.     addr = (long)vtoph(bp->b_proc, (unsigned)bp->b_un.b_addr);
  954.     /*
  955.      * Set DMA address into DR11 interace registers: DR11 requires that
  956.      * the address be right shifted 1 bit position before it is written
  957.      * to the board (The board will left shift it one bit position before
  958.      * it places the address on the bus
  959.      */
  960.     rsaddr->dr_walo = (addr >> 1) & 0xffff;
  961.     rsaddr->dr_wahi = (addr >> 17) & 0x7fff;
  962.     /* Set DMA range count: (number of words - 1) */
  963.     rsaddr->dr_range = (bp->b_bcount >> 1) - 1;
  964.     /* Set address modifier code to be used for DMA access to memory */
  965.     rsaddr->dr_addmod = DRADDMOD;
  966.     /*
  967.      * Now determine whether this is a read or a write. ***** This is
  968.      * probably only usefull for link mode operation, since dr11 doesnot
  969.      * controll the direction of data transfer. The C1 control input 
  970.      * controls whether the hardware is doing a read or a write. In link
  971.      * mode this is controlled by function 1 latch (looped back by the
  972.      * cable) and could be set the program. In the general case, the dr11
  973.      * doesnot know in advance what the direction of transfer is - although
  974.      * the program and protocol logic probably is
  975.      */
  976. #ifdef DR_DEBUG
  977.     if (DR11 & 1)
  978.         printf(
  979. "\ndrstrat: about to GO..,dr_cmd:%lx,drstat:%lx,drcnt:%ld,cdata:%lx,OP:%ld",
  980.             dra->dr_cmd, rsaddr->dr_cstat, rsaddr->dr_range,
  981.             rsaddr->dr_data, dra->dr_op);
  982. #endif
  983.     /*
  984.      * Update function latches may have been done already by drioctl() if
  985.      * request from drioctl()
  986.      */
  987.     if (dra->dr_cmd & DR_DFCN) {        /* deferred function write */
  988.         dra->dr_cmd &= ~DR_DFCN;    /* Clear request */
  989.         go = dra->dr_cmd & DR_FMSK;    /* mask out fcn bits */
  990.         rsaddr->dr_cstat = go;        /* Write it to the board */
  991.     }
  992.     /* Clear dmaf and attf to assure a clean dma start */
  993.     rsaddr->dr_pulse = RATN|RDMA|RPER;
  994.     rsaddr->dr_cstat = IENB|GO|CYCL|dra->dr_op; /* GO...... */
  995.     /*
  996.      * Now check for software cycle request -- usually
  997.      * by transmitter in link mode.
  998.      */
  999.     if (dra->dr_cmd & DR_PCYL) {
  1000.         dra->dr_cmd &= ~DR_PCYL;    /* Clear request */
  1001.         rsaddr->dr_pulse = CYCL;    /* Use pulse register again */
  1002.     }
  1003.     /*
  1004.      * Now check for deferred ACLO FCNT2 pulse request -- usually to tell
  1005.      * the transmitter (via its attention) that we have enabled dma.
  1006.      */
  1007.     if (dra->dr_cmd & DR_DACL) {
  1008.         dra->dr_cmd &= ~DR_DACL;    /* Clear request */
  1009.         rsaddr->dr_pulse = FCN2;    /* Use pulse register again */
  1010.     }
  1011. }
  1012. #endif  NDR
  1013.