if_egl.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:56k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* if_egl.c - Interphase Eagle 4207 Ethernet network interface driver */
  2. /* Copyright 1984-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02l,15jul97,spm  removed calls to init routine from ioctl support (SPR #8831)
  8. 02k,19may97,spm  eliminated all compiler warnings
  9. 02j,15may97,spm  reverted to bcopy routines for mbufs in BSD 4.4
  10. 02i,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.4
  11. 02h,23apr93,caf  ansification: added cast to cacheInvalidate parameter.
  12. 02g,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  13. 02f,15jan93,rfs  Non-functional.  Comments and documentation changes.
  14. 02e,09sep92,gae  documentation tweaks.
  15. 02d,18jul92,smb  Changed errno.h to errnoLib.h.
  16. 02c,08jul92,ajm  made cache safe
  17. 02b,26may92,rrr  the tree shuffle
  18.                  -changed includes to have absolute path from h/
  19. 02a,16jan92,gae  major cleanup: more ANSI fixes, eliminated occassional fatal
  20.                  bootrom crashes (reports only 1 in 100 receive errors),
  21.                  nearly made work on 68k, eliminated bit fields.
  22. 01c,07oct91,rrr  some fixes.
  23. 01b,04oct91,rrr  passed through the ansification filter
  24.                  -changed functions to ansi style
  25.                  -changed includes to have absolute path from h/
  26.                  -fixed #else and #endif
  27.                  -changed TINY and UTINY to INT8 and UINT8
  28.                  -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY & O_RDWR
  29.                  -changed VOID to void
  30.                  -changed copyright notice
  31. 01a,14nov90,ajm   written for vxWorks using Unix driver as a base.
  32. */
  33. /*
  34. DESCRIPTION
  35. GENERAL INFORMATION
  36. This module implements the Interphase Eagle 4207 Ethernet network
  37. interface driver.
  38. This driver was created to support the MIPS-based BSPs that are supported
  39. by WRS.  It is therefore not considered generic.  It has not been verified
  40. to work with other BSPs, and hence is not supported for all targets.
  41. BOARD LAYOUT
  42. The diagram below shows the relevant jumpers for VxWorks configuration.
  43. Default values: I/O address 0x00004000, Short Addressing (A16,D16).
  44. .bS
  45. ______________________________              _______________________________
  46. |             P1             |  Eagle 4207  |             P2              |
  47. |                            ----------------                             |
  48. |               SW1 SW2 SW3                 JA7 -.                        |
  49. |               "   "   "                                                 |
  50. |               -   "   "                                                 |
  51. |               -   "   "                                                 |
  52. |               -   -   "                                                 |
  53. |               -   "   "                                                 |
  54. |               -   -   "                                                 |
  55. |               -   -   "                                                 |
  56. |               -   "   "                                                 |
  57. |       Short I/O Adr                                                     |
  58. |                                                                         |
  59. |                                                                         |
  60. |                                                                         |
  61. |                                                                         |
  62. |                                                                         |
  63. |                                                                         |
  64. |                                                                         |
  65. |                                                                         |
  66. |                                                                         |
  67. |_________________________________________________________________________|
  68. .bE
  69. EXTERNAL INTERFACE
  70. This driver provides the standard external interface.
  71. There is one user-callable routine: eglattach().  See the manual entry for this
  72. routine for usage details.
  73. SEE ALSO: ifLib
  74. */
  75. /*
  76. Copyright (C) 1987,1988 Interphase Corporation
  77. Any use, copy or alteration is strictly prohibited
  78. unless authorized by Interphase.
  79. Porting priveledge granted to Wind River Systems on Jan. 9, 1992 by:
  80. Rob Brant - Interphase FAE, 214-919-9110 - rbrant@iphase.com
  81. */
  82. #include "vxWorks.h"
  83. #include "cacheLib.h"
  84. #include "net/mbuf.h"
  85. #include "net/protosw.h"
  86. #include "sys/ioctl.h"
  87. #include "sys/socket.h"
  88. #include "errnoLib.h"
  89. #include "net/if.h"
  90. #include "net/route.h"
  91. #include "netinet/in.h"
  92. #include "netinet/in_systm.h"
  93. #include "netinet/ip.h"
  94. #include "netinet/in_var.h"
  95. #include "netinet/if_ether.h"
  96. #include "iv.h"
  97. #include "vme.h"
  98. #include "stdlib.h"
  99. #include "memLib.h"
  100. #include "logLib.h"
  101. #include "iosLib.h"
  102. #include "intLib.h"
  103. #include "ioLib.h"
  104. #include "vxLib.h"
  105. #include "stdio.h"
  106. #include "net/if_subr.h"
  107. #include "netLib.h"
  108. #include "sysLib.h"
  109. #include "drv/netif/if_egl.h"
  110. /* Externals */
  111. IMPORT int      sysClkRateGet ();
  112. IMPORT int      sysBusIntAck ();
  113. IMPORT ULONG    tickGet ();
  114. IMPORT STATUS   taskDelay ();
  115. IMPORT FUNCPTR  etherInputHookRtn;
  116. IMPORT FUNCPTR  etherOutputHookRtn;
  117. #define NEGL    4       /* Maximum number of Eagle units supported */
  118. #define BLOCKMODE       TRUE    /* allow block mode transmisions */
  119. #define NOINT           0       /* don't want interrupt */
  120. #define INT             1       /* want interrupt */
  121. #define EGL_TOPT        (TT_NORMAL | MEMT_32BIT | VME_AM_EXT_USR_DATA)
  122. #define EGL_TOPT_BLK    (TT_BLOCK  | MEMT_32BIT | VME_AM_EXT_USR_ASCENDING)
  123. #define EGL_MTU         (ETHERMTU+18)   /* Max Packet size, 1500+14+4 */
  124. #define NUM_CQE         MAX_CQE         /* Num Command Queue Entries */
  125. /* Next two MUST be power of 2 */
  126. #define EGL_RX_NRINGS    16              /* Num LANCE Rx Rings */
  127. #define EGL_TX_NRINGS   16              /* Num LANCE Tx Rings */
  128. #define EGL_RX_BUFSZ    2000            /* Max Rx packet */
  129. #define EGL_TX_BUFSZ    2000            /* Max Tx packet */
  130. #define EGL_RX_NBUFF    20              /* Num receive buffers (max possible) */
  131. #define EGL_RX_SLOTS    20              /* Num receive workq entries */
  132. #define EGL_TX_NBUFF    16              /* Num transmit buffers */
  133. #define EGL_TX_SLOTS    16              /* Num transmit workq entries */
  134. #define EGL_RX_IOPBF    0               /* Receive IOPB starting offset */
  135. #define EGL_TX_IOPBF    (EGL_RX_IOPBF+EGL_RX_NBUFF)
  136. #define EGL_MS_SLOTS    1               /* Num misc workq entries */
  137. #define EGL_DM_SLOTS    1               /* Num DMA workq entries */
  138. #define EGL_RX_PRIORITY 1               /* Receive workq priority */
  139. #define EGL_TX_PRIORITY 1               /* Transmit workq priority */
  140. #define EGL_MS_PRIORITY 1               /* misc workq priority */
  141. #define EGL_DM_PRIORITY 1               /* DMA workq priority */
  142. #define EGL_RX_WDIV     0               /* Num receive workq processed */
  143. #define EGL_TX_WDIV     0               /* Num transmit workq processed */
  144. #define EGL_MS_WDIV     0               /* Num misc workq processed */
  145. #define EGL_DM_WDIV     0               /* Num DMA workq processed */
  146. #define EGL_NHBUF       1               /* Num Host Managed Buffers */
  147. #define EGL_NIBUF       16              /* Num Internal Tx Buffers */
  148. #define EGL_BURST       0               /* Send Whole Message */
  149. #define TXINC(x) ((x) = (ULONG)(++x&(EGL_TX_NBUFF-1)))
  150. #define TXDEC(x) ((x) = (ULONG)(--x&(EGL_TX_NBUFF-1)))
  151. #define TXFULL(x) ((x) == EGL_TX_NBUFF)
  152. typedef struct eth_buf
  153.     {
  154.     struct      eth_buf *eth_next;      /* next buffer in chain */
  155.     u_char      eth_dat[EGL_MTU];       /* data storage */
  156.     ULONG       eth_dat_adr;            /* bus address of data */
  157.     int         eth_len;                /* actual data usage */
  158.     IOPB        *iopb;                  /* associated iopb */
  159.     } ETH_BUF;
  160. #define ETH_BUF_SIZE    sizeof(ETH_BUF)
  161. #define ETH_BUF_COUNT   (EGL_RX_NRINGS + EGL_TX_NRINGS)
  162. ETH_BUF *eth_free = NULL;
  163. #define GET_ETH_BUF(buf) 
  164.         { int ms = splimp ();                   
  165.           if (((buf)=eth_free) != NULL)         
  166.           {                                     
  167.                 eth_free = (buf)->eth_next;     
  168.                 (buf)->eth_next = NULL;         
  169.           }                                     
  170.           else                                  
  171.                 panic("out of ETH buffers");    
  172.           splx (ms);                            
  173.         }
  174. #define REL_ETH_BUF(buf) 
  175.         { int ms = splimp ();                   
  176.           (buf)->eth_next = eth_free;           
  177.           eth_free = (buf);                     
  178.           splx (ms);                            
  179.           (buf)->eth_len = 0;                   
  180.         }
  181. /*
  182. * Invalidate the CPU cache since the start and end of an mbuf may occupy
  183. * the same secondary cache line as other data.  Even if we flush and
  184. * invalidate before performing I/O, other data in the line may have been
  185. * read, causing the old data to be placed back in the cache.  We then will
  186. * see stale data after the I/O completes (this occurred in an SA system
  187. * where the mbuf header is in the same secondary cache line as the data --
  188. * and we end up reading mbuf->m_len after invalidating the CPU cache).
  189. */
  190. #define egl_ioflush(eth_buf) 
  191.     { 
  192.     ULONG physical = K1_TO_PHYS(((ULONG)&eth_buf->eth_dat[0])); 
  193.     cacheInvalidate (DATA_CACHE, (void *) PHYS_TO_K0(physical), 
  194.                      eth_buf->eth_len); 
  195.     }
  196. int eglAM       = VME_AM_EXT_USR_DATA;  /* 32-bit addresses */
  197. int eglMemWidth = 4;                    /* VME bcopy transfers = 1,2,4 */
  198. int delay_mult = 13;    /* tuned on the STAR MVP (VLANE = 1) */
  199. /*
  200.  * DELAY(n) should be n microseconds, roughly.
  201.  * [taskDelay(1) at 60Mhz == 16666 usecs.]
  202.  */
  203. #define DELAY(n)        { 
  204.         register int ix = delay_mult*(n); 
  205.         while (--ix > 0); 
  206.         }
  207. /*
  208.  * Ethernet software status per interface.
  209.  *
  210.  * Each interface is referenced by a network interface structure, egl_if,
  211.  * which the routing code uses to locate the interface.  This structure
  212.  * contains the output queue for the interface, its address, ...
  213.  */
  214. typedef struct egl_softc {
  215.     struct arpcom egl_ac;       /* Ethernet Common Part */
  216. #define egl_if          egl_ac.ac_if     /* network-visible interface */
  217. #define egl_enaddr      egl_ac.ac_enaddr /* hardware Ethernet address */
  218.     SHIO        *eglAddr;       /* Pointer to I/O Space */
  219.     USHORT      xmit_vec;       /* Transmit Interrupt Vector */
  220.     USHORT      xmiterr_vec;    /* Transmit Error Interrupt Vector*/
  221.     USHORT      rcv_vec;        /* Receive Interrupt Vector */
  222.     USHORT      rcverr_vec;     /* Receive Error Interrupt Vector*/
  223.     USHORT      qav_vec;        /* Queue Available Interrupt Vector */
  224.     ETH_BUF     *egl_tbinfo[EGL_TX_NBUFF]; /* phys addrs of txbufs */
  225.     ETH_BUF     *egl_rbinfo[EGL_RX_NBUFF]; /* phys addrs of rxbufs */
  226.     ULONG       egl_txadd;      /* add index to xmit packet ring */
  227.     ULONG       egl_txrem;      /* remove index to xmit packet ring */
  228.     CQE         *egl_cqe;       /* index for feed queue */
  229.     ULONG       egl_qmode;      /* queue mode is started */
  230.     ULONG       egl_qfull;      /* feed queue is full */
  231.     ULONG       egl_txcnt;      /* # of mbufs queued in tbuf array */
  232.     ULONG       egl_quecnt;     /* # of transmit commands queued on Eagle */
  233.     ULONG       egl_csr0miss;   /* driver count of receive misses */
  234.     ULONG       egl_csr0mem;    /* driver count of LANCE memory errors */
  235.     CSTB        egl_cstb;       /* Firmware info */
  236.     int         eglIntLevel;    /* VME interrupt level */
  237.     int         eglIntVec;      /* VME interrupt vector */
  238.     CSB         CSBstats;       /* copy of CSB for tracking statistics */
  239. } EGL_SOFTC;
  240. LOCAL EGL_SOFTC *egl_softc [NEGL];
  241. #if     CPU_FAMILY!=MIPS
  242. #define sysWbFlush()
  243. #define K0_TO_PHYS(x)   (x)
  244. #define K1_TO_PHYS(x)   (x)
  245. #define  PHYS_TO_K0(x)   (x)
  246. #define PHYS_TO_K1(x)   (x)
  247. #endif  /* CPU_FAMILY!=MIPS */
  248. /*
  249.  * Macros to set various bits in Queue Entry Control Register (QECR)
  250.  * of the Command Queue Entry (CQE).
  251.  */
  252. /* Tell Eagle to initiate action on this cqe */
  253. #define CQE_GO(qecr)            { sysWbFlush(); qecr = M_QECR_GO; }
  254. /* Check if cqe is available */
  255. #define CQE_BUSY(qecr)  (qecr & M_QECR_GO)
  256. /* Clear cqe GO bit; when should host be doing this??? */
  257. #define CQE_CLR_BUSY(qecr)      { sysWbFlush(); qecr &= ~M_QECR_GO; }
  258. /* Indicate that any commands that are queued up should be aborted on error */
  259. #define CQE_AA_GO(qecr) { sysWbFlush(); qecr |= (M_QECR_GO + M_QECR_AA);}
  260. /* Get the next command queue entry in the command queue XXX bad macro */
  261. #define INC_CQE(cqe) ((x)==&shio->sh_CQE[NUM_CQE-1] ? &shio->sh_CQE[0] ? cqe+1)
  262. /*
  263.  * Macros to check/set bits in the Command Response Status (CRSW) field of the
  264.  * Command Response Block (CRB).
  265.  */
  266. /* clear the crsw */
  267. #define CRB_CLR_DONE(crsw)       { crsw = 0; sysWbFlush(); }
  268. /*#define CRB_CLR_DONE(crsw)     { crsw &= ~M_CRSW_CRBV; sysWbFlush();}*/
  269. /* Check if command is done */
  270. #define CRB_DONE(crsw)          (crsw & M_CRSW_CRBV)
  271. /* Check is the command represented by this CRB is done. */
  272. #define CRB_COMPLETE(crsw)       (crsw & (M_CRSW_CRBV | M_CRSW_CC))
  273. /* Check if the command to start queue mode has completed. */
  274. #define CRB_QSTARTED(crsw)      (crsw & (M_CRSW_CRBV | M_CRSW_QMS))
  275. /* Check if this command queue entry is available. */
  276. #define CRB_QAVAIL(crsw)        (crsw & (M_CRSW_CRBV | M_CRSW_QEA))
  277. #define CRB_ERROR(crsw)         (crsw & (M_CRSW_ER | M_CRSW_EX))
  278. /* Define to display error/status messages. */
  279. #undef EGL_DEBUG
  280. /* forward declarations */
  281. int eglattach ();
  282. int eglShow (int unit, BOOL zap);
  283. static int  egl_config (int unit, int itype);
  284. static int  egl_hangrcv (int unit, int index);
  285. static int  egl_init (int unit);
  286. static void egl_intr (int unit);
  287. static int  egl_ioctl (struct ifnet *ifp, int cmd, caddr_t data);
  288. static int  egl_iworkq (int unit, int itype);
  289. #ifdef BSD43_DRIVER
  290. static int  egl_output (struct ifnet *ifp,struct mbuf *m0,struct sockaddr *dst);
  291. #endif
  292. static int  egl_physreset (int unit);
  293. static void egl_qint (int unit, EGL_SOFTC *egl);
  294. static void egl_recv (int unit, int len, ETH_BUF *eth_buf);
  295. static int  egl_reset (int unit);
  296. static void egl_rint (int unit, EGL_SOFTC *egl, int index, int len);
  297. static void egl_setiopbs (int unit);
  298. #ifdef BSD43_DRIVER
  299. static void egl_start (int unit);
  300. #else
  301. static void egl_start (EGL_SOFTC *egl);
  302. #endif
  303. static void egl_tint (int unit, EGL_SOFTC *egl, int index);
  304. static int  egl_wait (volatile CRB *crb);
  305. /*******************************************************************************
  306. *
  307. * eglattach - publish the interface, and initialize the driver and device
  308. *
  309. * This routine attaches an `egl' Ethernet interface to the network if the
  310. * interface exists.  The routine makes the interface available by filling in
  311. * the network interface record.  The system will initialize the interface
  312. * when it is ready to accept packets.
  313. *
  314. * RETURNS: OK or ERROR.
  315. */
  316. int eglattach
  317.     (
  318.     int unit,           /* unit number */
  319.     char *addr,         /* address of Eagle's shared memory */
  320.     int ivec,           /* interrupt vector to connect to */
  321.     int ilevel          /* interrupt level */
  322.     )
  323.     {
  324.     EGL_SOFTC *egl;
  325.     ETH_BUF *eth_buf;
  326.     int ix;
  327.     USHORT status;
  328.     char *pool;
  329.     volatile SHIO *pEglDev = (SHIO *) addr;
  330. #ifdef EGL_DEBUG
  331.     printf ("egl%d: attaching at vector = %d, level = %d, addr = %#xn",
  332.              unit, ivec, ilevel, addr);
  333. #endif  /* EGL_DEBUG */
  334.     /* wait for kernel reset to finish */
  335.     ix = 15 * sysClkRateGet () / 2;     /* 15 seconds (1/30th sec. below) */
  336.     while (vxMemProbe ((char *) &pEglDev->sh_MCSB, O_RDONLY,
  337.                         sizeof (USHORT), (char *)&status) != OK)
  338.         {
  339.         if (--ix < 0)
  340.             {
  341.             errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  342. #ifdef EGL_DEBUG
  343.             printf (
  344.             "eglattach: controller not present at %#x, status register = %#xn",
  345.                     addr, status);
  346. #endif
  347.             return (ERROR);
  348.             }
  349.         taskDelay (sysClkRateGet () / 30);      /* 1/30th of a second */
  350.         }
  351.     pool = (char*)calloc (1, (ETH_BUF_COUNT + 1) * ETH_BUF_SIZE);
  352.     if (pool == NULL)
  353.         return (ERROR);
  354.     pool = (char *)((int)pool+ETH_BUF_SIZE - ((int)pool & (ETH_BUF_SIZE - 1)));
  355.     eth_buf = (ETH_BUF *)pool;
  356.     for (ix = 0; ix < ETH_BUF_COUNT; ix++)
  357.         {
  358.         REL_ETH_BUF(eth_buf);
  359.         if (sysLocalToBusAdrs (eglAM, &eth_buf->eth_dat[0],
  360.                                (char **)&eth_buf->eth_dat_adr) == ERROR)
  361.             {
  362. #ifdef EGL_DEBUG
  363.             printf ("egl: local address %#x to bus address (AM = %#x) failedn",
  364.                     &eth_buf->eth_dat[0], eglAM);
  365. #endif
  366.             return (ERROR);
  367.             }
  368.         eth_buf++;
  369.         }
  370.     /* allocate and initialize Eagle descriptor */
  371.     egl = (EGL_SOFTC *) calloc (1, sizeof (EGL_SOFTC));
  372.     if (egl == NULL)
  373.         return (ERROR);
  374.     egl_softc [unit] = egl;             /* set ptr to egl descriptor in array */
  375.     egl->eglAddr = (SHIO *) addr;               /* remember device address */
  376.     /* reset the device */
  377.     if (egl_physreset (unit) != 0)
  378.         {
  379. #ifdef EGL_DEBUG
  380.         printf ("egl%d: reset failure.n", unit);
  381. #endif
  382.         errnoSet (S_ioLib_DEVICE_ERROR);
  383.         return (ERROR);
  384.         }
  385.     bcopy ((char*)&pEglDev->sh_CSTB, (char*)&egl->egl_cstb, sizeof(CSTB));
  386.     bzero ((char*)egl->egl_cstb.cstb_FILT, sizeof(egl->egl_cstb.cstb_FILT));
  387.     /* configure the settings */
  388.     if (egl_config (unit, NOINT) == -1)
  389.         {
  390. #ifdef EGL_DEBUG
  391.         printf ("egl%d: configuration failure.n", unit);
  392. #endif
  393.         errnoSet (S_ioLib_DEVICE_ERROR);
  394.         return (ERROR);
  395.         }
  396.     egl->xmit_vec    = LVL_VCT(ilevel,ivec+0);
  397.     egl->xmiterr_vec = LVL_VCT(ilevel,ivec+1);
  398.     egl->rcv_vec     = LVL_VCT(ilevel,ivec+2);
  399.     egl->rcverr_vec  = LVL_VCT(ilevel,ivec+3);
  400.     egl->qav_vec     = LVL_VCT(ilevel,ivec+4);
  401.     bcopy ((char*)egl->egl_cstb.cstb_PHY, (char*)egl->egl_enaddr,
  402.           sizeof(egl->egl_cstb.cstb_PHY));
  403.     egl->eglIntLevel = ilevel;
  404.     egl->eglIntVec   = ivec;
  405. #ifdef BSD43_DRIVER
  406.     ether_attach (&egl->egl_if, unit, "egl", egl_init, egl_ioctl,
  407.                     egl_output, egl_reset);
  408. #else
  409.     ether_attach (
  410.                  &egl->egl_if, 
  411.                  unit, 
  412.                  "egl", 
  413.                  egl_init, 
  414.                  egl_ioctl,
  415.                  ether_output, 
  416.                  egl_reset);
  417.     egl->egl_if.if_start = (FUNCPTR)egl_start;
  418. #endif
  419.     egl->egl_if.if_mtu = ETHERMTU - 4;  /* MTU = 1496 for block bug */
  420.     (void)intConnect (INUM_TO_IVEC (ivec+0), egl_intr, unit);
  421.     /* XXX temporarily while R3K targets don't do vectored VME interrupts */
  422. #if     CPU_FAMILY!=MIPS
  423.     (void)intConnect (INUM_TO_IVEC (ivec+1), egl_intr, unit);
  424.     (void)intConnect (INUM_TO_IVEC (ivec+2), egl_intr, unit);
  425.     (void)intConnect (INUM_TO_IVEC (ivec+3), egl_intr, unit);
  426.     (void)intConnect (INUM_TO_IVEC (ivec+4), egl_intr, unit);
  427. #endif  /* CPU_FAMILY!=MIPS */
  428.     sysIntEnable (ilevel);
  429.     if (egl_init (unit) != 0)
  430.         return (ERROR);
  431.     return (OK);
  432.     }
  433. /*******************************************************************************
  434. *
  435. * egl_config - configure the Eagle to default settings
  436. *
  437. * RETURNS: 0 or -1 on error.
  438. */
  439. LOCAL int egl_config
  440.     (
  441.     int unit,
  442.     int itype
  443.     )
  444.     {
  445.     EGL_SOFTC *egl         = egl_softc [unit];
  446.     volatile SHIO *shio    = egl->eglAddr;
  447.     volatile CIB *cib      = (CIB *)&shio->sh_SCRTCH[0]; /* scratch area */
  448.     volatile IC_IOPB *iopb = (IC_IOPB *)&shio->sh_MCE_IOPB;
  449.     int status             = 0;
  450.     int ix;
  451.     /* Controller Initialization Block */
  452.     cib->cib_RES0 = 0;
  453.     cib->cib_NCQE = NUM_CQE;
  454.     cib->cib_IMOD = (USHORT)M_IMOD_PE;  /* Ethernet */
  455.     cib->cib_NTXR = EGL_TX_NRINGS;      /* LANCE Tx Rings */
  456.     cib->cib_NRXR = EGL_RX_NRINGS;      /* LANCE Rx Rings */
  457.     /* default Physical Address */
  458.     bcopy ((char*)egl->egl_cstb.cstb_PHY, (char*)cib->cib_PHY,
  459.           sizeof(egl->egl_cstb.cstb_PHY));
  460.     /* default Logical Address Filter */
  461.     bcopy ((char*)egl->egl_cstb.cstb_FILT, (char*)cib->cib_FILT,
  462.           sizeof (egl->egl_cstb.cstb_FILT));
  463.     cib->cib_RXSIZ = EGL_RX_BUFSZ;      /* Max Rx Packet */
  464.     cib->cib_NRBUF = EGL_RX_NRINGS;     /* Num Rx Buffers */
  465.     cib->cib_TXSIZ = EGL_TX_BUFSZ;      /* Max Tx Packet */
  466.     cib->cib_NIBUF = EGL_TX_NRINGS;     /* Num Tx Buffers */
  467.     cib->cib_NHBUF = EGL_NHBUF;         /* Num Host Buffers */
  468.     cib->cib_NVECT = egl->qav_vec;      /* needed for error handling */
  469.     cib->cib_EVECT = egl->qav_vec;      /* needed for error handling */
  470.     cib->cib_BURST = EGL_BURST;         /* DMA Burst Count */
  471.     bzero ((char*)cib->cib_RES1, sizeof(cib->cib_RES1));
  472.     /* MCE IOPB */
  473.     iopb->ic_iopb_CMD    = CNTR_INIT;
  474.     /* XXX big-endian or quad alignment? */
  475.     iopb->ic_iopb_OPTION = M_OPT_SG | itype;     /* 0 no int; 1 int */
  476.     iopb->ic_iopb_NVCT   = egl->qav_vec;
  477.     iopb->ic_iopb_EVCT   = egl->qav_vec;
  478.     iopb->ic_iopb_RES0   = 0;
  479.     iopb->ic_iopb_BUFF   = (ULONG)cib - (ULONG)shio;/* CIB offset from shio */
  480.     bzero ((char*)iopb->ic_iopb_RES1, sizeof(iopb->ic_iopb_RES1));
  481.     shio->sh_MCE.cqe_CTAG       = 0;
  482.     shio->sh_MCE.cqe_IOPB_ADDR  = O_MCE_IOPB;
  483.     shio->sh_MCE.cqe_WORK_QUEUE = 0;
  484.     CQE_GO(shio->sh_MCE.cqe_QECR);
  485.     if (!itype)
  486.         {
  487.         ix = egl_wait (&shio->sh_CRB);
  488.         if (CRB_ERROR(ix))
  489.             {
  490. #ifdef EGL_DEBUG
  491.             logMsg ("egl%d: *error* unable to configure interfacen",
  492.                     unit, 0, 0, 0, 0, 0);
  493.             if (iopb->ic_iopb_STATUS)
  494.                 logMsg ("iopb error status = %#xn",
  495.                         iopb->ic_iopb_STATUS, 0, 0, 0, 0, 0);
  496. #endif
  497.             status = -1;
  498.             }
  499.         else if (ix == 0x1000)
  500.             {
  501. #ifdef EGL_DEBUG
  502.             logMsg ("egl%d: *timeout* unable to configure interfacen",
  503.                     unit, 0, 0, 0, 0, 0);
  504. #endif
  505.             status = -1;
  506.             }
  507.         }
  508.     return (status);
  509.     }
  510. /*******************************************************************************
  511. *
  512. * egl_hangrcv - place a receive request for the specified iobp
  513. *
  514. * RETURNS: 1 or 0.
  515. */
  516. LOCAL int egl_hangrcv
  517.     (
  518.     int unit,
  519.     int index
  520.     )
  521.     {
  522.     ETH_BUF *eth_buf;
  523.     volatile IOPB *iopb;
  524.     EGL_SOFTC *egl      = egl_softc [unit];
  525.     volatile SHIO *shio = egl->eglAddr;
  526.     volatile CQE *cqe   = egl->egl_cqe;
  527.     if (egl->egl_qfull != 0)
  528.         {
  529. #ifdef EGL_DEBUG
  530.         logMsg ("egl%d: egl_hangrcv - packet queue fulln", unit, 0, 0, 0, 0,0);
  531. #endif  /* EGL_DEBUG */
  532.         return (0);
  533.         }
  534.     /* place a receive request */
  535.     if (CQE_BUSY(cqe->cqe_QECR))
  536.         {
  537.         egl->egl_qfull++;       /* feed queue full */
  538.         return (0);
  539.         }
  540.     if ((eth_buf = egl->egl_rbinfo[index]) == NULL)
  541.         GET_ETH_BUF(eth_buf);
  542.     iopb                   = eth_buf->iopb;
  543.     iopb->iopb_BUFF        = eth_buf->eth_dat_adr;
  544.     eth_buf->eth_len       = EGL_MTU;
  545.     egl->egl_rbinfo[index] = eth_buf;
  546.     egl_ioflush (eth_buf);
  547.     cqe->cqe_CTAG          = index;
  548.     cqe->cqe_IOPB_ADDR     = (caddr_t)iopb - (caddr_t)shio;
  549.     cqe->cqe_WORK_QUEUE    = EGL_RECVQ;
  550.     CQE_GO(cqe->cqe_QECR);
  551.     if (++egl->egl_cqe == &shio->sh_CQE[MAX_CQE])
  552.         egl->egl_cqe = (CQE *)&shio->sh_CQE[0];
  553.     return (1);
  554.     }
  555. /*******************************************************************************
  556. *
  557. * egl_init - initialization of interface; clear pending operations
  558. *
  559. * RETURNS: 0 or -1.
  560. */
  561. LOCAL int egl_init
  562.     (
  563.     int unit
  564.     )
  565.     {
  566.     EGL_SOFTC *egl      = egl_softc [unit];
  567.     volatile SHIO *shio = egl->eglAddr;
  568.     volatile CRB *crb   = &shio->sh_CRB;
  569.     struct ifnet *ifp   = &egl->egl_if;
  570.     int s;
  571.     int ix;
  572.     ifp->if_flags &= ~(IFF_UP|IFF_RUNNING);
  573.     s = splimp ();
  574.     if (egl_reset (unit) == -1)
  575.         {
  576.         splx (s);
  577.         return (-1);
  578.         }
  579.     /* LANCE is turned OFF now */
  580.     if (egl_config (unit, NOINT) == -1)
  581.         {
  582.         splx (s);
  583.         return (-1);
  584.         }
  585.     /* LANCE is turned ON now */
  586.     egl_setiopbs (unit);                        /* setup iopbs */
  587.     egl->egl_qmode = 0;                         /* not queue mode */
  588.     /* start up queue mode */
  589.     if (egl_iworkq (unit, NOINT) == -1)
  590.         {
  591.         splx (s);
  592. #ifdef EGL_DEBUG
  593.         logMsg ("egl%d: egl_init - failedn", 0, 0, 0, 0, 0, 0);
  594. #endif
  595.         return (-1);
  596.         }
  597.     for (ix = 0; ix < 10000; ix++)
  598.         {
  599.         if (CRB_QSTARTED(crb->crb_CRSW))
  600.             break;
  601.         DELAY(500);
  602.         }
  603.     if (!CRB_QSTARTED(crb->crb_CRSW))
  604.         {
  605. #ifdef EGL_DEBUG
  606.         logMsg ("egl%d: failed to start Q-Moden", unit, 0, 0, 0, 0, 0);
  607. #endif
  608.         splx (s);
  609.         return (-1);
  610.         }
  611.     egl->egl_qmode++;
  612.     CRB_CLR_DONE(crb->crb_CRSW);        /* release Eagle */
  613.     /* initial hang receive requests */
  614.     for (ix = 0; ix < EGL_RX_NBUFF; ix++)
  615.         {
  616.         if (egl_hangrcv (unit, ix) == 0)
  617.             break;
  618.         }
  619.     egl->egl_if.if_flags |= IFF_UP | IFF_RUNNING;
  620. #ifdef BSD43_DRIVER
  621.     egl_start (unit);                   /* start transmits */
  622. #else
  623.     egl_start (egl);
  624. #endif
  625.     splx (s);
  626.     return (0);
  627.     }
  628. /*******************************************************************************
  629. *
  630. * egl_intr - read vector and dispatch to routine handler
  631. */
  632. LOCAL void egl_intr
  633.     (
  634.     int unit
  635.     )
  636.     {
  637. #ifdef EGL_DEBUG
  638.     static char message [150];
  639.     char *nullmsg       = "";
  640. #endif
  641.     EGL_SOFTC *egl      = egl_softc [unit];
  642.     volatile SHIO *shio = egl->eglAddr;
  643.     volatile CRB *crb   = &shio->sh_CRB;
  644.     volatile CSB *csb   = &shio->sh_CSB;
  645.     volatile IOPB tiopb;
  646.     int real_errors;
  647.     int vector;
  648.     int index;
  649.     int len;
  650.     /* ack interrupt, read vector */
  651.     vector = sysBusIntAck (egl->eglIntLevel) & 0x00ff;
  652.     /* XXX temporarily while R3K targets don't do vectored VME interrupts */
  653.     if (vector != (shio->sh_VMEIV & 0x00ff))
  654.         {
  655. #ifdef EGL_DEBUG
  656.         logMsg ("egl%d: vectors disagree: sysBusIntAck = %#x, CSB-vec = %#xn",
  657.                 unit, vector, shio->sh_VMEIV & 0x00ff, 0, 0, 0);
  658. #endif  /* EGL_DEBUG */
  659.         vector = shio->sh_VMEIV & 0x00ff;
  660.         }
  661.     switch (vector - egl->eglIntVec)
  662.         {
  663.         case 0: /* xmit */
  664.             if (shio->sh_RET_IOPB.iopb_LAN1 & (LANCE_TONE | LANCE_TMORE))
  665.                 egl->egl_if.if_collisions++;
  666.             index = crb->crb_CTAG;
  667.             CRB_CLR_DONE(crb->crb_CRSW);        /* release Eagle */
  668.             netJobAdd ((FUNCPTR)egl_tint, unit, (int)egl, index, 0, 0);
  669.             break;
  670.         case 1: /* xmiterr */
  671.             tiopb = shio->sh_RET_IOPB;
  672.             if (tiopb.iopb_LAN1 & LANCE_TERR)
  673.                 {
  674. #ifdef EGL_DEBUG
  675.                 sprintf (message,
  676.                     "egl%d: transmit error LAN1=%#x LAN3=%#x %s%s%s%s%sn",
  677.                     unit, tiopb.iopb_LAN1, tiopb.iopb_LAN3,
  678.                     ((tiopb.iopb_LAN3&LAN3_BUFF) ? "buffer error "   : nullmsg),
  679.                     ((tiopb.iopb_LAN3&LAN3_UFLO) ? "underflow "      : nullmsg),
  680.                     ((tiopb.iopb_LAN3&LAN3_LCOL) ? "late collision " : nullmsg),
  681.                     ((tiopb.iopb_LAN3&LAN3_LCAR) ? "carrier loss "   : nullmsg),
  682.                     ((tiopb.iopb_LAN3&LAN3_RTRY) ? "retry error"     : nullmsg));
  683.                 logMsg (message, 0, 0, 0, 0, 0, 0);
  684. #endif
  685.                 }
  686.             else if (tiopb.iopb_STATUS)
  687.                 {
  688. #ifdef EGL_DEBUG
  689.                 logMsg ("egl%d: transmit error status %#xn",
  690.                         unit, tiopb.iopb_STATUS, 0, 0, 0, 0);
  691. #endif
  692.                 }
  693.             index = crb->crb_CTAG;
  694.             CRB_CLR_DONE(crb->crb_CRSW);        /* release Eagle */
  695.             egl->egl_if.if_oerrors++;
  696.             egl->egl_if.if_opackets--;
  697.             netJobAdd ((FUNCPTR)egl_tint, unit, (int)egl, index, 0, 0);
  698.             break;
  699.         case 2: /* rcv */
  700.             len = shio->sh_RET_IOPB.iopb_LENGTH;/* length of recv packet */
  701.             index = crb->crb_CTAG;
  702.             CRB_CLR_DONE(crb->crb_CRSW);        /* release Eagle */
  703.             netJobAdd ((FUNCPTR)egl_rint, unit, (int)egl, index, len, 0);
  704.             break;
  705.         case 3: /* rcverr */
  706.             len = shio->sh_RET_IOPB.iopb_LENGTH;   /* length of recv packet */
  707.             index = crb->crb_CTAG;
  708.             tiopb = shio->sh_RET_IOPB;
  709.             if (tiopb.iopb_LAN1 & LANCE_RERR)
  710.                 {
  711.                 /* First, check for bogus LANCE errors:
  712.                  * call normal completion code if no "real" errors.
  713.                  */
  714.                 real_errors = tiopb.iopb_LAN1;
  715.                 if ((tiopb.iopb_LAN1&LAN1_OFLO) && (tiopb.iopb_LAN1&LANCE_RENP))
  716.                     real_errors ^= LAN1_OFLO;   /* turn off bogus OFLO */
  717.                 if (!(tiopb.iopb_LAN1&LANCE_RENP)|| (tiopb.iopb_LAN1&LAN1_OFLO))
  718.                     real_errors &= (0xffff - (LAN1_FRAM | LAN1_CRC));
  719.                 if (!(real_errors & (LAN1_FRAM|LAN1_OFLO|LAN1_CRC|LAN1_BUFF)))
  720.                     {
  721.                     /* Error was bogus.  Treat like normal receive int.  */
  722.                     CRB_CLR_DONE(crb->crb_CRSW);        /* release Eagle */
  723.                     netJobAdd ((FUNCPTR)egl_rint, unit, (int)egl, index, len,0);
  724.                     return;
  725.                     }
  726.                 /* looks like a real receive error */
  727. #ifdef EGL_DEBUG
  728.                 sprintf (message,
  729.                         "egl%d: receive error LAN1=%#x LAN3=%#x %s%s%s%sn",
  730.                         unit, tiopb.iopb_LAN1, tiopb.iopb_LAN3,
  731.                         (real_errors&LAN1_FRAM) ? "framing error " : nullmsg,
  732.                         (real_errors&LAN1_OFLO) ? "overflow "      : nullmsg,
  733.                         (real_errors&LAN1_CRC)  ? "CRC error "     : nullmsg,
  734.                         (real_errors&LAN1_BUFF) ? "buffer error"   : nullmsg);
  735. #endif
  736.                 if ((++egl->egl_if.if_ierrors % 100) == 0)
  737.                     {
  738.                     /* Interphase Inc. only reports every 100 errors;
  739.                      * we seem to get a fair number of CRC errors but
  740.                      * probably they're bogus.
  741.                      */
  742. #ifdef EGL_DEBUG
  743.                     logMsg (message, 0, 0, 0, 0, 0, 0);
  744. #endif
  745.                     }
  746.                 }
  747.             else if (tiopb.iopb_STATUS)
  748.                 {
  749.                 /* only interesting if non RERR */
  750. #ifdef EGL_DEBUG
  751.                 logMsg ("egl%d: receive error status %#xn",
  752.                         unit, tiopb.iopb_STATUS, 0, 0, 0, 0);
  753.                 /* valid only if no RERR */
  754.                 if (!tiopb.iopb_LENGTH)
  755.                     logMsg ("egl%d: 0 length receiven", unit, 0, 0, 0, 0, 0);
  756. #endif
  757.                 }
  758.             if (csb->csb_CSR0MISS > egl->egl_csr0miss)
  759.                 {
  760.                 /* any new ones? */
  761.                 egl->egl_csr0miss = csb->csb_CSR0MISS;
  762. #ifdef EGL_DEBUG
  763.                 logMsg ("egl%d: csr0 missed receive packet, count = %dn",
  764.                         unit, egl->egl_csr0miss, 0, 0, 0, 0);
  765. #endif
  766.                 }
  767.             CRB_CLR_DONE(crb->crb_CRSW);        /* release Eagle */
  768.             egl->egl_if.if_ierrors++;
  769.             netJobAdd ((FUNCPTR)egl_rint, unit, (int)egl, index, -1, 0);
  770.             break;
  771.         case 4: /* qav */
  772.             netJobAdd ((FUNCPTR)egl_qint, unit, (int)egl, 0, 0, 0);
  773.             break;
  774.         default:
  775. #ifdef EGL_DEBUG
  776.             logMsg (
  777.             "egl%d: egl_intr - unknown interrupt vector %#xn",
  778.             unit, vector, 0, 0, 0, 0);
  779. #endif
  780.             break;
  781.         }
  782.     }
  783. /*******************************************************************************
  784. *
  785. * egl_ioctl - process an ioctl request
  786. *
  787. * RETURNS: 0 or errno.
  788. */
  789. LOCAL int egl_ioctl
  790.     (
  791.     struct ifnet *ifp,
  792.     int cmd,
  793.     caddr_t data
  794.     )
  795.     {
  796.     int unit       = ifp->if_unit;
  797.     EGL_SOFTC *egl = egl_softc [unit];
  798.     int error      = 0;
  799.     int status;
  800.     int s;
  801.     s = splimp ();
  802.     switch (cmd)
  803.         {
  804.         case SIOCSIFADDR:       /* Set */
  805.             ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr;
  806.             arpwhohas (ifp, &IA_SIN (data)->sin_addr);
  807.             break;
  808.         case SIOCGIFADDR:       /* Get */
  809.             bcopy ((char*)egl->egl_enaddr,
  810.                   (caddr_t) ((struct ifreq *)data)->ifr_addr.sa_data, 6);
  811. #ifdef  EGL_DEBUG
  812.             printf ("egl%d: egl_ioctl - SIOCGIFADDRn", unit);
  813. #endif  /* EGL_DEBUG */
  814.             break;
  815.         case SIOCGIFFLAGS:      /* Get */
  816.             *(short *)data = ifp->if_flags;
  817. #ifdef EGL_DEBUG
  818.             printf ("egl%d: egl_ioctl - SIOCGIFFLAGSn", unit);
  819. #endif  /* EGL_DEBUG */
  820.             break;
  821.         case SIOCSIFFLAGS:      /* Set */
  822.             /* Handled outside module - nothing more to do. */
  823.             break;
  824.         default:
  825. #ifdef EGL_DEBUG
  826.             printf ("egl%d: egl_ioctl - unknown ioctln", unit);
  827. #endif  /* EGL_DEBUG */
  828.             error = EINVAL;
  829.             break;
  830.         }
  831.     splx (s);
  832.     return (error);
  833.     }
  834. /*******************************************************************************
  835. *
  836. * egl_iworkq - initialize work queues
  837. *
  838. * RETURNS: 0 or -1 on error.
  839. */
  840. LOCAL int egl_iworkq
  841.     (
  842.     int unit,
  843.     int itype
  844.     )
  845.     {
  846.     EGL_SOFTC *egl       = egl_softc [unit];
  847.     volatile SHIO *shio  = egl->eglAddr;
  848.     volatile WQCF *iopb  = (WQCF *)&shio->sh_MCE_IOPB;
  849.     volatile USHORT *mcr = &shio->sh_MCSB.mcsb_MCR;
  850.     int ix;
  851.     iopb->wqcf_CMD      = CNTR_INIT_WORKQ;
  852.     iopb->wqcf_OPTION  |= itype;        /* 0 no int; 1 int (M_OPT_IE) */
  853.     iopb->wqcf_NVCT     = egl->qav_vec;
  854.     iopb->wqcf_EVCT     = egl->qav_vec;
  855.     bzero ((char*)iopb->wqcf_RES0, sizeof(iopb->wqcf_RES0));
  856.     iopb->wqcf_WORKQ    = EGL_MISCQ;            /* misc queue */
  857.     iopb->wqcf_WOPT     = 0;
  858.     iopb->wqcf_SLOTS    = EGL_MS_SLOTS;         /* misc queue size */
  859.     iopb->wqcf_PRIORITY = EGL_MS_PRIORITY;      /* misc queue priority */
  860.     iopb->wqcf_WDIV     = EGL_MS_WDIV;          /* misc queue work division */
  861.     bzero ((char*)iopb->wqcf_RES1, sizeof(iopb->wqcf_RES1));
  862.     shio->sh_MCE.cqe_CTAG       = 0;
  863.     shio->sh_MCE.cqe_IOPB_ADDR  = O_MCE_IOPB;
  864.     shio->sh_MCE.cqe_WORK_QUEUE = 0;
  865.     CQE_GO(shio->sh_MCE.cqe_QECR);
  866.     if (!itype)
  867.         {
  868.         ix = egl_wait (&shio->sh_CRB);
  869.         if (CRB_ERROR(ix))
  870.             {
  871. #ifdef EGL_DEBUG
  872.             logMsg ("egl%d: *error* unable to initialize misc workqn",
  873.                     unit, 0, 0, 0, 0, 0);
  874. #endif
  875.             return (-1);
  876.             }
  877.         else if (ix == 0x1000) /* unused value */
  878.             {
  879. #ifdef EGL_DEBUG
  880.             logMsg ("egl%d: *timeout* unable to initialize misc workqn",
  881.                     unit, 0, 0, 0, 0, 0);
  882. #endif
  883.             return (-1);
  884.             }
  885.         }
  886.     else
  887.         {
  888. #ifdef EGL_DEBUG
  889.         logMsg ("egl%d: initialize misc workq donen",
  890.                 unit, 0, 0, 0, 0, 0);
  891. #endif  /* EGL_DEBUG */
  892.         }
  893.     /* DMA MCE IOPB */
  894.     iopb->wqcf_CMD = CNTR_INIT_WORKQ;
  895.     iopb->wqcf_OPTION |= itype;     /* 0 no int; 1 int (M_OPT_IE) */
  896.     iopb->wqcf_NVCT = egl->qav_vec;
  897.     iopb->wqcf_EVCT = egl->qav_vec;
  898.     bzero ((char*)iopb->wqcf_RES0, sizeof(iopb->wqcf_RES0));
  899.     iopb->wqcf_WORKQ    = EGL_DMAQ;             /* misc queue */
  900.     iopb->wqcf_WOPT     = 0;
  901.     iopb->wqcf_SLOTS    = EGL_DM_SLOTS; /* misc queue size */
  902.     iopb->wqcf_PRIORITY = EGL_DM_PRIORITY;      /* misc queue priority */
  903.     iopb->wqcf_WDIV     = EGL_DM_WDIV;          /* misc queue work division */
  904.     bzero ((char*)iopb->wqcf_RES1, sizeof(iopb->wqcf_RES1));
  905.     shio->sh_MCE.cqe_CTAG       = 0;
  906.     shio->sh_MCE.cqe_IOPB_ADDR  = O_MCE_IOPB;
  907.     shio->sh_MCE.cqe_WORK_QUEUE = 0;
  908.     CQE_GO(shio->sh_MCE.cqe_QECR);
  909.     if (!itype)
  910.         {
  911.         ix = egl_wait (&shio->sh_CRB);
  912.         if (CRB_ERROR(ix))
  913.             {
  914. #ifdef EGL_DEBUG
  915.             logMsg ("egl%d: *error* unable to initialize DMA workqn",
  916.                     unit, 0, 0, 0, 0, 0);
  917. #endif
  918.             return (-1);
  919.             }
  920.         else if (ix == 0x1000) /* unused value */
  921.             {
  922. #ifdef EGL_DEBUG
  923.             logMsg ("egl%d: *timeout* unable to initialize DMA workqn",
  924.                     unit, 0, 0, 0, 0, 0);
  925. #endif
  926.             return (-1);
  927.             }
  928.         }
  929.     else
  930.         {
  931. #ifdef EGL_DEBUG
  932.         logMsg ("egl%d: initialize DMA workq donen",
  933.                 unit, 0, 0, 0, 0, 0);
  934. #endif  /* EGL_DEBUG */
  935.         }
  936.     /* receive MCE IOPB */
  937.     iopb->wqcf_CMD     = CNTR_INIT_WORKQ;
  938.     iopb->wqcf_OPTION |= itype;     /* 0 no int; 1 int (M_OPT_IE) */
  939.     iopb->wqcf_NVCT    = egl->qav_vec;
  940.     iopb->wqcf_EVCT    = egl->qav_vec;
  941.     bzero ((char*)iopb->wqcf_RES0, sizeof(iopb->wqcf_RES0));
  942.     iopb->wqcf_WORKQ    = EGL_RECVQ;            /* receive queue */
  943.     iopb->wqcf_WOPT     = 0;
  944.     iopb->wqcf_SLOTS    = EGL_RX_SLOTS;         /* receive queue size */
  945.     iopb->wqcf_PRIORITY = EGL_RX_PRIORITY;      /* receive queue priority */
  946.     iopb->wqcf_WDIV     = EGL_RX_WDIV;          /* receive q work division */
  947.     bzero ((char*)iopb->wqcf_RES1, sizeof(iopb->wqcf_RES1));
  948.     shio->sh_MCE.cqe_CTAG       = 0;
  949.     shio->sh_MCE.cqe_IOPB_ADDR  = O_MCE_IOPB;
  950.     shio->sh_MCE.cqe_WORK_QUEUE = 0;
  951.     CQE_GO(shio->sh_MCE.cqe_QECR);
  952.     if (!itype)
  953.         {
  954.         ix = egl_wait (&shio->sh_CRB);
  955.         if (CRB_ERROR(ix))
  956.             {
  957. #ifdef EGL_DEBUG
  958.             logMsg ("egl%d: *error* unable to initialize receive workqn",
  959.                     unit, 0, 0, 0, 0, 0);
  960. #endif
  961.             return (-1);
  962.             }
  963.         else if (ix == 0x1000) /* unused value */
  964.             {
  965. #ifdef EGL_DEBUG
  966.             logMsg ("egl%d: *timeout* unable to initialize receive workqn",
  967.                     unit, 0, 0, 0, 0, 0);
  968. #endif
  969.             return (-1);
  970.             }
  971.         }
  972.     else
  973.         {
  974. #ifdef EGL_DEBUG
  975.         logMsg ("egl%d: initialize receive workq donen",
  976.                 unit, 0, 0, 0, 0, 0);
  977. #endif  /* EGL_DEBUG */
  978.         }
  979.     /* transmit MCE IOPB */
  980.     iopb->wqcf_CMD     = CNTR_INIT_WORKQ;
  981.     iopb->wqcf_OPTION |= itype;     /* 0 no int; 1 int (M_OPT_IE) */
  982.     iopb->wqcf_NVCT    = egl->qav_vec;
  983.     iopb->wqcf_EVCT    = egl->qav_vec;
  984.     bzero ((char*)iopb->wqcf_RES0, sizeof(iopb->wqcf_RES0));
  985.     iopb->wqcf_WORKQ    = EGL_XMTQN(0);         /* transmit queue 0 */
  986.     iopb->wqcf_WOPT     = 0;
  987.     iopb->wqcf_SLOTS    = EGL_TX_SLOTS;         /* transmit queue size */
  988.     iopb->wqcf_PRIORITY = EGL_TX_PRIORITY;      /* transmit queue priority */
  989.     iopb->wqcf_WDIV     = EGL_TX_WDIV;          /* transmit q work division */
  990.     bzero ((char*)iopb->wqcf_RES1, sizeof(iopb->wqcf_RES1));
  991.     shio->sh_MCE.cqe_CTAG       = 0;
  992.     shio->sh_MCE.cqe_IOPB_ADDR  = O_MCE_IOPB;
  993.     shio->sh_MCE.cqe_WORK_QUEUE = 0;
  994.     CQE_GO(shio->sh_MCE.cqe_QECR);
  995.     if (!itype)
  996.         {
  997.         ix = egl_wait (&shio->sh_CRB);
  998.         if (CRB_ERROR(ix))
  999.             {
  1000. #ifdef EGL_DEBUG
  1001.             logMsg ("egl%d: *error* unable to initialize transmit workqn",
  1002.                     unit, 0, 0, 0, 0, 0);
  1003. #endif
  1004.             return (-1);
  1005.             }
  1006.         else if (ix == 0x1000) /* unused value */
  1007.             {
  1008. #ifdef EGL_DEBUG
  1009.             logMsg ("egl%d: *timeout* unable to initialize transmit workqn",
  1010.                     unit, 0, 0, 0, 0, 0);
  1011. #endif
  1012.             return (-1);
  1013.             }
  1014.         }
  1015.     else
  1016.         {
  1017. #ifdef EGL_DEBUG
  1018.         logMsg ("egl%d: initialize transmit workq donen",
  1019.                 unit, 0, 0, 0, 0, 0);
  1020. #endif  /* EGL_DEBUG */
  1021.         }
  1022.     *mcr |= M_MCR_SQM;  /* start queue mode */
  1023.     sysWbFlush();
  1024.     return (0);
  1025.     }
  1026. #ifdef BSD43_DRIVER
  1027. /*******************************************************************************
  1028. *
  1029. * egl_output - Ethernet output routine
  1030. *
  1031. * RETURNS: ?
  1032. */
  1033. LOCAL int egl_output
  1034.     (
  1035.     struct ifnet *ifp,
  1036.     struct mbuf *m0,
  1037.     struct sockaddr *dst
  1038.     )
  1039.     {
  1040.     return (ether_output (ifp, m0, dst, (FUNCPTR) egl_start,
  1041.                          &egl_softc [ifp->if_unit]->egl_ac));
  1042.     }
  1043. #endif
  1044. /*******************************************************************************
  1045. *
  1046. * egl_physreset - physical reset of the Interphase Eagle card
  1047. *
  1048. * RETURNS: 0 or -1 if reset or diagnostics fail.
  1049. */
  1050. LOCAL STATUS egl_physreset
  1051.     (
  1052.     int unit
  1053.     )
  1054.     {
  1055.     EGL_SOFTC *egl       = egl_softc [unit];
  1056.     volatile SHIO *shio  = egl->eglAddr;
  1057.     volatile USHORT *msr = &shio->sh_MCSB.mcsb_MSR;
  1058.     volatile USHORT *mcr = &shio->sh_MCSB.mcsb_MCR;
  1059.     int ix;
  1060. #ifdef EGL_DEBUG
  1061.     printf ("egl%d: egl_physreset - msr address = %#xn", unit, msr);
  1062. #endif  /* EGL_DEBUG */
  1063.     for (ix = 0; ix < 1000; ix++)
  1064.         {
  1065.         if (!(*msr & M_MSR_CNA) && (*msr & M_MSR_BOK))
  1066.             break;
  1067.         DELAY(8000);
  1068.         }
  1069.     if (ix == 1000)
  1070.         {
  1071. #ifdef EGL_DEBUG
  1072.         printf (
  1073.         "egl%d: diagnostics failed, or controller not available; msr = %#xn",
  1074.                 unit, *msr);
  1075. #endif
  1076.         return (-1);
  1077.         }
  1078.     *msr |= M_MSR_CNA;
  1079.     sysWbFlush();
  1080.     *mcr = M_MCR_RES;   /* reset the Eagle */
  1081.     sysWbFlush();
  1082.     DELAY(500);         /* at least 50usec required */
  1083.     *mcr &= ~M_MCR_RES;
  1084.     sysWbFlush();
  1085.     for (ix = 0; ix < 1000; ix++)
  1086.         {
  1087.         if (!(*msr & M_MSR_CNA))
  1088.             break;
  1089.         DELAY(8000);
  1090.         }
  1091.     if (ix == 1000)
  1092.         {
  1093. #ifdef EGL_DEBUG
  1094.         printf ("egl%d: diagnostics failed during phase 1; msr = %#xn",
  1095.                 unit, *msr);
  1096. #endif
  1097.         return (-1);
  1098.         }
  1099.     /* more delay necessary as reset is not yet done! (Interphase bug) */
  1100.     for (ix = 0; ix < 1000; ix++)
  1101.         {
  1102.         if (*msr & M_MSR_BOK)
  1103.             break;
  1104.         DELAY(8000);
  1105.         }
  1106.     if (ix == 1000)
  1107.         {
  1108. #ifdef EGL_DEBUG
  1109.         printf ("egl%d: diagnostics failed during phase 2; msr = %#xn",
  1110.                 unit, *msr);
  1111. #endif
  1112.         *msr |= M_MSR_BOK; /* re-set board OK (iphase bug) */
  1113.         return (-1);
  1114.         }
  1115.     return (0);
  1116.     }
  1117. /*******************************************************************************
  1118. *
  1119. * egl_qint - Ethernet interface queue entry available interrupt
  1120. */
  1121. LOCAL void egl_qint
  1122.     (
  1123.     int unit,
  1124.     EGL_SOFTC *egl
  1125.     )
  1126.     {
  1127.     volatile SHIO *shio  = egl->eglAddr;
  1128.     volatile CRB *crb    = &shio->sh_CRB;
  1129.     volatile CSB *csb    = &shio->sh_CSB;
  1130.     volatile USHORT *msr = &shio->sh_MCSB.mcsb_MSR;
  1131.     IOPB tiopb;
  1132.     tiopb = shio->sh_RET_IOPB;
  1133.     /* controller not available */
  1134.     if (*msr & M_MSR_CNA)
  1135.         {
  1136. #ifdef EGL_DEBUG
  1137.         logMsg ("egl%d: died and restarted; error status = %#xn",
  1138.                 unit, tiopb.iopb_STATUS, 0, 0, 0, 0);
  1139. #endif
  1140.         /* these errors (among others) will turn the LANCE transmitter
  1141.            off, which will send us here */
  1142.         /* any new ones? */
  1143.         if (csb->csb_CSR0MEM > egl->egl_csr0mem)
  1144.             {
  1145.             egl->egl_csr0mem = csb->csb_CSR0MEM;
  1146. #ifdef EGL_DEBUG
  1147.             logMsg ("egl%d: %d csr0 MEMORY ERRORS caughtn",
  1148.                     unit, egl->egl_csr0mem, 0, 0, 0, 0);
  1149. #endif
  1150.             }
  1151. #ifdef EGL_DEBUG
  1152.         /* save the returned IOPB */
  1153.         logMsg ("returned IOPB: cmd %#x options %#x status %#x nvect %#xn",
  1154.                 tiopb.iopb_CMD, tiopb.iopb_OPTION, tiopb.iopb_STATUS,
  1155.                 tiopb.iopb_NVCT, 0, 0);
  1156.         logMsg ("evect %#x topt %#x buff_addr %#x length %#xn",
  1157.                 tiopb.iopb_EVCT, tiopb.iopb_TOPT,
  1158.                 tiopb.iopb_BUFF, tiopb.iopb_LENGTH, 0, 0);
  1159.         logMsg ("host_buf %#x ptlf %#x sge_cnt %#x lan1 %#x lan3 %#xn",
  1160.                 tiopb.iopb_HBUF, tiopb.iopb_PTLF, tiopb.iopb_SGEC,
  1161.                 tiopb.iopb_LAN1, tiopb.iopb_LAN3, 0);
  1162.         logMsg ("src/dest node %x:%x:%x:%x:%x:%xn",
  1163.                 tiopb.iopb_NODE[0],tiopb.iopb_NODE[1],tiopb.iopb_NODE[2],
  1164.                 tiopb.iopb_NODE[3],tiopb.iopb_NODE[4],tiopb.iopb_NODE[5]);
  1165. #endif  /* EGL_DEBUG */
  1166.         egl_init (unit);
  1167.         return;
  1168.         }
  1169.     if (CRB_QAVAIL(crb->crb_CRSW))
  1170.         {
  1171.         /* feed queue is no longer full */
  1172.         egl->egl_qfull = 0;     /* at least one slot open now */
  1173.         }
  1174.     if (CRB_QSTARTED(crb->crb_CRSW))
  1175.         {
  1176.         /* how about q mode started */
  1177.         egl->egl_qmode++;       /* remember for later */
  1178.         }
  1179.     CRB_CLR_DONE(crb->crb_CRSW);        /* release Eagle */
  1180.     }
  1181. /*******************************************************************************
  1182. *
  1183. * egl_recv - process Ethernet receive completion
  1184. *
  1185. * This procedure handles Ethernet receive completion interrupts.  If
  1186. * input error just drop packet, otherwise examine packet to determine
  1187. * type.  If can't determine length from type, then have to drop packet,
  1188. * otherwise decapsulate packet based on type and pass to type-specific
  1189. * higher-level input routine.
  1190. *
  1191. * RETURNS: ?
  1192. */
  1193. LOCAL void egl_recv
  1194.     (
  1195.     int unit,
  1196.     int len,
  1197.     ETH_BUF *eth_buf
  1198.     )
  1199.     {
  1200.     EGL_SOFTC *egl = egl_softc [unit];
  1201.     struct ether_header *eh;
  1202.     struct mbuf *m;
  1203. #ifdef BSD43_DRIVER
  1204.     int off;
  1205. #endif
  1206.     unsigned char *pData;
  1207.     egl->egl_if.if_ipackets++;
  1208.     /* speed fix (in Eagle firmware) for 14 byte Ethernet header */
  1209.     eh = (struct ether_header *) ((int)eth_buf->eth_dat + 2);
  1210.     /* call input hook if any */
  1211.     if (etherInputHookRtn != NULL &&
  1212.         (* etherInputHookRtn) (&egl->egl_if, (char *) eh, len))
  1213.         {
  1214.         return;
  1215.         }
  1216.     len -=  SIZEOF_ETHERHEADER + 4; /* total length - (ether header + CRC) */
  1217.     pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;
  1218. #ifdef BSD43_DRIVER
  1219.     check_trailer (eh, pData, &len, &off, &egl->egl_if);
  1220.     if (len == 0)
  1221.         return;
  1222.     /* copy data from Eagle to mbuf a word at a time */
  1223.     m = bcopy_to_mbufs (pData, len, off, (struct ifnet *) &egl->egl_if,
  1224.                         eglMemWidth);
  1225.     if (m != NULL)
  1226.         do_protocol_with_type (eh->ether_type, m, &egl->egl_ac, len);
  1227.     else
  1228.         egl->egl_if.if_ierrors++;        /* bump error stat */
  1229. #else
  1230.     m = bcopy_to_mbufs (pData, len, 0, &egl->egl_if, eglMemWidth);
  1231.     if (m != NULL)
  1232.         do_protocol (eh, m, &egl->egl_ac, len);
  1233.     else
  1234.         egl->egl_if.if_ierrors++;        /* bump error stat */
  1235. #endif
  1236.     }
  1237. /*******************************************************************************
  1238. *
  1239. * egl_reset - mark interface as inactive & reset the chip
  1240. *
  1241. * RETURNS: 0 or -1.
  1242. */
  1243. LOCAL STATUS egl_reset
  1244.     (
  1245.     int unit
  1246.     )
  1247.     {
  1248.     EGL_SOFTC *egl;
  1249.     volatile SHIO *shio;
  1250.     struct ifnet *ifp;
  1251.     int s;
  1252.     if (unit < 0 || unit >= NEGL)
  1253.         return (-1);
  1254.     egl  = egl_softc [unit];
  1255.     shio = egl->eglAddr;
  1256.     ifp  = &egl->egl_if;
  1257. #ifdef EGL_DEBUG
  1258.     printf ("egl%d: egl_resetn", unit, 0, 0, 0, 0, 0);
  1259. #endif  /* EGL_DEBUG */
  1260.     s = splimp ();
  1261.     ifp->if_flags &= ~IFF_RUNNING;
  1262.     if (egl_physreset (unit) != OK)
  1263.         {
  1264.         splx (s);
  1265. #ifdef EGL_DEBUG
  1266.         logMsg ("egl%d: reset failedn", unit, 0, 0, 0, 0, 0);
  1267. #endif
  1268.         return (-1);
  1269.         }
  1270.     splx (s);
  1271.     return (0);
  1272.     }
  1273. /*******************************************************************************
  1274. *
  1275. * egl_rint - Ethernet interface receive (& error) interrupt
  1276. */
  1277. LOCAL void egl_rint
  1278.     (
  1279.     int unit,
  1280.     EGL_SOFTC *egl,
  1281.     int index,
  1282.     int len
  1283.     )
  1284.     {
  1285.     ETH_BUF *eth_buf;
  1286.     if (len != -1)
  1287.         {
  1288.         eth_buf = egl->egl_rbinfo[index];
  1289.         egl->egl_rbinfo[index] = NULL;
  1290.         egl_ioflush (eth_buf);          /* definitly need on receive */
  1291.         egl_recv (unit, len, eth_buf);
  1292.         REL_ETH_BUF(eth_buf);
  1293.         }
  1294.     (void)egl_hangrcv (unit, index);    /* hang another receive request */
  1295.     egl->egl_qfull = 0;                 /* at least one slot open now */
  1296.     }
  1297. /*******************************************************************************
  1298. *
  1299. * egl_setiopbs - setup iopb's
  1300. */
  1301. LOCAL void egl_setiopbs
  1302.     (
  1303.     int unit
  1304.     )
  1305.     {
  1306.     EGL_SOFTC *egl = egl_softc [unit];
  1307.     volatile SHIO *shio = egl->eglAddr;
  1308.     volatile IOPB *iopb;
  1309.     int ix;
  1310.     ETH_BUF *eth_buf;
  1311.     iopb = &shio->sh_IOPB[EGL_RX_IOPBF];
  1312.     for (ix = 0; ix < EGL_RX_NBUFF; ix++)
  1313.         {
  1314.         iopb->iopb_OPTION = M_OPT_DMA | M_OPT_IE;
  1315.         iopb->iopb_CMD  = CNTR_RECEIVE;
  1316.         iopb->iopb_NVCT = egl->rcv_vec;
  1317.         iopb->iopb_EVCT = egl->rcverr_vec;
  1318.         if (BLOCKMODE)
  1319.             iopb->iopb_TOPT = EGL_TOPT_BLK | DIR_READ;
  1320.         else
  1321.             iopb->iopb_TOPT = EGL_TOPT | DIR_READ;
  1322.         /* use the Host usable buffer region */
  1323.         if ((eth_buf = egl->egl_rbinfo[ix]) == NULL)
  1324.             GET_ETH_BUF(eth_buf);
  1325.         /* egl_rbinfo[i] always uses iopb at index (EGL_RX_IOPBF+i) */
  1326.         eth_buf->eth_len          = EGL_MTU;
  1327.         egl->egl_rbinfo[ix]       = eth_buf;
  1328.         egl->egl_rbinfo[ix]->iopb = (IOPB*)iopb;
  1329.         egl_ioflush (eth_buf);
  1330.         iopb->iopb_BUFF   = eth_buf->eth_dat_adr;
  1331.         iopb->iopb_LENGTH = EGL_MTU;
  1332.         iopb->iopb_HBUF   = 0;
  1333.         iopb->iopb_PTLF   = 0;
  1334.         bzero ((char*)iopb->iopb_NODE, sizeof(iopb->iopb_NODE));
  1335.         iopb->iopb_SGEC = 0;
  1336.         iopb->iopb_LAN1 = 0;
  1337.         iopb->iopb_LAN3 = 0;
  1338.         iopb++;
  1339.         }
  1340.     iopb = &shio->sh_IOPB[EGL_TX_IOPBF];
  1341.     for (ix = 0; ix < EGL_TX_NBUFF; ix++)
  1342.         {
  1343.         iopb->iopb_CMD = CNTR_TRANSMIT;
  1344.         iopb->iopb_OPTION = M_OPT_DMA | M_OPT_IE;
  1345.         iopb->iopb_NVCT = egl->xmit_vec;
  1346.         iopb->iopb_EVCT = egl->xmiterr_vec;
  1347.         /* We need to recover any hung transmit buffers if
  1348.          * initialization is due to a HW reset after an error
  1349.          * such as a transmit timeout.
  1350.          */
  1351.         if ((eth_buf = egl->egl_tbinfo[ix]) != NULL)
  1352.             {
  1353.             egl->egl_tbinfo[ix] = NULL;
  1354.             egl_ioflush (eth_buf);
  1355.             REL_ETH_BUF(eth_buf);
  1356.             }
  1357.         if (BLOCKMODE)
  1358.             iopb->iopb_TOPT = EGL_TOPT_BLK | DIR_WRITE;
  1359.         else
  1360.             iopb->iopb_TOPT = EGL_TOPT | DIR_WRITE;
  1361.         iopb->iopb_HBUF = 0;
  1362.         iopb->iopb_SGEC = 0;
  1363.         iopb->iopb_LAN1 = 0;
  1364.         iopb->iopb_LAN3 = 0;
  1365.         iopb++;
  1366.         }
  1367.     egl->egl_txadd  = egl->egl_txrem = EGL_TX_NBUFF-1;
  1368.     egl->egl_quecnt = egl->egl_txcnt = 0;
  1369.     egl->egl_cqe    = (CQE *)&shio->sh_CQE[0];
  1370.     }
  1371. /*******************************************************************************
  1372. *
  1373. * egl_start - start or re-start output on interface
  1374. *
  1375. * Get another datagram to send off of the interface queue,
  1376. * and add it to the transmit packet queue for the interface.
  1377. */
  1378. #ifdef BSD43_DRIVER
  1379. LOCAL void egl_start
  1380.     (
  1381.     int unit
  1382.     )
  1383.     {
  1384.     EGL_SOFTC *egl      = egl_softc [unit];
  1385. #else
  1386. LOCAL void egl_start
  1387.     (
  1388.     EGL_SOFTC *  egl
  1389.     )
  1390.     {
  1391. #ifdef EGL_DEBUG
  1392.     int unit = egl->egl_if.if_unit;
  1393. #endif
  1394. #endif
  1395.     volatile SHIO *shio = egl->eglAddr;
  1396.     volatile IOPB *iopb;
  1397.     volatile CQE *cqe;
  1398.     u_char *bufStart;
  1399.     struct mbuf *m;
  1400.     struct ether_header *eh;
  1401.     ETH_BUF *eth_buf;
  1402.     int len;
  1403.     int index;
  1404.     int s;
  1405.     if (TXFULL(egl->egl_txcnt + egl->egl_quecnt))
  1406.         {
  1407. #ifdef EGL_DEBUG
  1408.         logMsg ("egl%d: egl_start - packet queue fulln", unit, 0, 0, 0, 0, 0);
  1409. #endif  /* EGL_DEBUG */
  1410.         return; /* packet queue is full, can't send anything */
  1411.         }
  1412.     s = splimp ();
  1413.     IF_DEQUEUE(&egl->egl_if.if_snd, m);
  1414.     if (m == 0)
  1415.         {
  1416.         splx (s);
  1417.         return;
  1418.         }
  1419.     TXINC(egl->egl_txadd);
  1420.     egl->egl_txcnt++;
  1421.     index = egl->egl_txadd;
  1422.     iopb  = (IOPB *)&shio->sh_IOPB[EGL_TX_IOPBF + index];
  1423.     GET_ETH_BUF(eth_buf);
  1424.     bufStart = &eth_buf->eth_dat[0];
  1425.     copy_from_mbufs (bufStart, m, len);
  1426.     /* call output hook if any */
  1427.     if ((etherOutputHookRtn != NULL) &&
  1428.         (* etherOutputHookRtn) (&egl->egl_if, bufStart, len))
  1429.         {
  1430.         REL_ETH_BUF(eth_buf);
  1431.         splx (s);
  1432.         return;                 /* output hook has processed this packet */
  1433.         }
  1434.     eh = (struct ether_header *)bufStart;
  1435.     if ((len - SIZEOF_ETHERHEADER) < ETHERMIN)
  1436.         len = ETHERMIN + SIZEOF_ETHERHEADER;
  1437.     /* must be modulo 4 in order to use block mode transfers */
  1438.     iopb->iopb_LENGTH = (len + 3) & ~0x3;
  1439.     iopb->iopb_BUFF        = eth_buf->eth_dat_adr;
  1440.     eth_buf->eth_len       = len;
  1441.     egl->egl_tbinfo[index] = eth_buf;
  1442.     egl_ioflush (eth_buf);
  1443.     if (BLOCKMODE)
  1444.         {
  1445.         /* we can (try and) use block mode transfer,
  1446.          * must be aligned on a long-word boundary
  1447.          */
  1448.         if (!(iopb->iopb_BUFF & 0x2))
  1449.             iopb->iopb_TOPT = EGL_TOPT_BLK | DIR_WRITE;
  1450.         else
  1451.             iopb->iopb_TOPT = EGL_TOPT | DIR_WRITE; /* put back to non-block */
  1452.         }
  1453.     iopb->iopb_PTLF = eh->ether_type;
  1454.     /*
  1455.      * Following code performs an efficient copy of the Ethernet
  1456.      * destination address when the src & dst are word aligned.
  1457.      * This avoids a sequence of 6 one byte writes on the VMEbus.
  1458.      */
  1459.     if (((ULONG)eh->ether_dhost & 0x3) == 0)
  1460.         {
  1461.         *(int *)iopb->iopb_NODE       = *(int *)eh->ether_dhost;
  1462.         *(short *)(iopb->iopb_NODE+4) = *(short *)(eh->ether_dhost+4);
  1463.         }
  1464.     else
  1465.         {
  1466.         bcopy ((char*)eh->ether_dhost, (char*)iopb->iopb_NODE,
  1467.                 sizeof(iopb->iopb_NODE));
  1468.         }
  1469.     bcopy ((char*)egl->egl_enaddr, (char*)eh->ether_shost,
  1470.             sizeof(eh->ether_shost));
  1471.     /* send */
  1472.     if (egl->egl_txcnt == 0)
  1473.         {
  1474. #ifdef EGL_DEBUG
  1475.         logMsg ("egl%d: egl_txcnt is nulln", unit, 0, 0, 0, 0, 0);
  1476. #endif
  1477.         splx (s);
  1478.         return;                 /* this should never happen */
  1479.         }
  1480.     if (egl->egl_qfull != 0)
  1481.         {
  1482.         splx (s);
  1483.         return;
  1484.         }
  1485.     cqe = egl->egl_cqe;
  1486.     if (CQE_BUSY(cqe->cqe_QECR))
  1487.         {
  1488.         egl->egl_qfull++;       /* feed queue is full */
  1489.         splx (s);
  1490.         return;
  1491.         }
  1492.     TXINC(egl->egl_txrem);
  1493.     egl->egl_txcnt--;
  1494.     index = egl->egl_txrem;
  1495.     cqe->cqe_CTAG = index;
  1496.     cqe->cqe_IOPB_ADDR = (caddr_t)(&shio->sh_IOPB[EGL_TX_IOPBF] + index) -
  1497.                          (caddr_t)shio;
  1498.     cqe->cqe_WORK_QUEUE = EGL_XMTQN(0); /* TX work queue 0 */
  1499.     CQE_GO(cqe->cqe_QECR);
  1500.     egl->egl_quecnt++;
  1501.     if (++egl->egl_cqe == &shio->sh_CQE[MAX_CQE])
  1502.         egl->egl_cqe = (CQE *)&shio->sh_CQE[0];
  1503. #ifndef BSD43_DRIVER    /* BSD 4.4 ether_output() doesn't bump statistic. */
  1504.     egl->egl_if.if_opackets++;
  1505. #endif
  1506.     splx (s);
  1507.     }
  1508. /*******************************************************************************
  1509. *
  1510. * eglShow - display per unit Eagle driver info
  1511. *
  1512. * RETURNS: 0 or -1 if unit not present.
  1513. *
  1514. * NOMANUAL
  1515. */
  1516. int eglShow
  1517.     (
  1518.     int unit,   /* interface unit */
  1519.     BOOL zap    /* zero totals */
  1520.     )
  1521.     {
  1522.     static char *e_message [] = {
  1523.     "transmit attempts",
  1524.     "   "     DMA completions",
  1525.     "   "     LANCE interrupts",
  1526.     "   "     good",
  1527.     "   "     errors",
  1528.     "   "     dones",
  1529.     "receive attempts",
  1530.     "   "    starvations",
  1531.     "   "    interrupts",
  1532.     "   "    good",
  1533.     "   "    errors",
  1534.     "   "    DMA completions",
  1535.     "   "    dones",
  1536.     "Miscellaneous DMA interrupts",
  1537.     "Total LANCE Interrupts",
  1538.     "LANCE Inits",
  1539.     "CSR0 Babble",
  1540.     " "   Collisions",
  1541.     " "   Misses",
  1542.     " "   Memory Errors"
  1543.     };
  1544.     int ix;
  1545.     volatile SHIO *shio;
  1546.     EGL_SOFTC *egl;
  1547.     if (unit < 0 || unit >= NEGL || (egl = egl_softc [unit]) == NULL)
  1548.         {
  1549. #ifdef EGL_DEBUG
  1550.         printf ("egl%d: no Eagle driver initialized for unitn", unit);
  1551. #endif
  1552.         return (-1);
  1553.         }
  1554.     shio = egl->eglAddr;
  1555.     printf ("egl%d: Firmware revision: ", unit);
  1556.     for (ix = 0; ix < 3; ix++)
  1557.         printf ("%c", shio->sh_CSTB.cstb_FREV [ix]);
  1558.     printf ("  Release date: ");
  1559.     for (ix = 0; ix < 8; ix++)
  1560.         printf ("%c", shio->sh_CSTB.cstb_FDATE [ix]);
  1561.     printf ("n");
  1562.     for (ix = 0; ix < NELEMENTS(e_message); ix++)
  1563.         {
  1564.         printf ("    %-30.30s  %4ldn", e_message [ix],
  1565.                 shio->sh_CSB.csb_stat [ix] - egl->CSBstats.csb_stat [ix]);
  1566.         if (zap)
  1567.             egl->CSBstats.csb_stat [ix] = shio->sh_CSB.csb_stat [ix];
  1568.         }
  1569.     return (0);
  1570.     }
  1571. /*******************************************************************************
  1572. *
  1573. * egl_tint - Ethernet interface transmit (& error) interrupt
  1574. */
  1575. LOCAL void egl_tint
  1576.     (
  1577.     int unit,
  1578.     EGL_SOFTC *egl,
  1579.     int index
  1580.     )
  1581.     {
  1582.     ETH_BUF *eth_buf;
  1583.     eth_buf = egl->egl_tbinfo[index];
  1584.     egl_ioflush (eth_buf);              /* do we need on transmit? */
  1585.     egl->egl_tbinfo[index] = NULL;
  1586.     REL_ETH_BUF(eth_buf);
  1587.     egl->egl_quecnt--;
  1588.     egl->egl_qfull = 0;         /* at least one slot open now */
  1589. #ifdef BSD43_DRIVER
  1590.     egl_start (unit);
  1591. #else
  1592.     egl_start (egl);
  1593. #endif
  1594.     }
  1595. /*******************************************************************************
  1596. *
  1597. * egl_wait -
  1598. */
  1599. LOCAL int egl_wait
  1600.     (
  1601.     volatile CRB *crb
  1602.     )
  1603.     {
  1604.     volatile USHORT *lcrsw = &crb->crb_CRSW;
  1605.     int ix;
  1606.     for (ix = 0; ix < 8000; ix++)
  1607.         {
  1608.         if (*lcrsw & M_CRSW_CRBV)
  1609.             break;
  1610.         DELAY(1000);
  1611.         }
  1612.     /* Check for the Command Response Block Valid bit.  Sometimes
  1613.      * the Eagle turns on "Queue Mode Started" just before completing
  1614.      * a command (don't know why, but has been observed).
  1615.      */
  1616.     if (*lcrsw & M_CRSW_CRBV)
  1617.         {
  1618.         /* Eagle has completed an operation? */
  1619.         CRB_CLR_DONE(*lcrsw);   /* release Eagle */
  1620.         }
  1621.     if (ix == 0)
  1622.         return (0x1000); /* indicate a timeout occurred */
  1623.     return (*lcrsw);
  1624.     }
  1625. #if     FALSE
  1626. void egl_delay (int x)
  1627.     {
  1628.     /* use with timexN() from shell for tuning */
  1629.     DELAY(x);
  1630.     }
  1631. #endif  /* FALSE */