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

VxWorks

开发平台:

C/C++

  1. /* if_enp.c - CMC ENP 10/L Ethernet network interface driver */
  2. /* Copyright 1984-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 03d,15jul97,spm  added ARP request to SIOCSIFADDR ioctl handler;
  8.                  added support for promiscuous mode to SIOCSIFFLAGS
  9. 03c,25apr97,gnn  added multicast by turning on promiscuous mode.
  10. 03b,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.4
  11. 03a,16dec96,map  doc: fixed ENP-10/L jumper diagram [SPR# 3025]
  12. 02z,14oct93,wmd  Added htons() for pPacketType assignments (SPR #2060).
  13. 02y,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  14. 02x,19feb93,jdi  documentation cleanup.
  15. 02w,02feb93,dzb  updated copyright.  removed HK68/V2F referrence (SPR #1876). 
  16. 02v,13oct92,rfs  Added documentation.
  17. 02u,16sep92,rfs  Reinstated interrupting of the ENP after putting outgoing
  18.                  packets on the transmit ring, even though the documentation
  19.                  is conflicting on this action, and some boards work fine
  20.                  without it.
  21. 02t,09sep92,gae  documentation tweaks.
  22. 02s,04sep92,ccc  added address modifier parameter to attach() routine.
  23. 02r,06aug92,rfs  Functional changes:
  24.                    Eliminated init() routine.  Added errno setting for all
  25.                    error cases in the attach() routine.  Added rejection of
  26.                    multiple attach() calls per unit.  Eliminated obsolete use
  27.                    of transmit output queue.  Moved driver control structures
  28.                    to BSS.  Corrected the ioctl() routine.  Added Tx semaphore.
  29.                    Added write pipe flushing.  Added rejection of work if the
  30.                    interface flags are down.  Revised Rx event handling.
  31.                  Cosmetic changes:
  32.                    Changed name of driver control structure, changed all
  33.                    references to it, changed name of all pointers to it.  Added
  34.                    many comments.  Typedef'd common structures and changed all
  35.                    usages to the new type.  General cleanup and convention
  36.                    adherence.
  37. 02q,27jul92,ccc  used sysBusToLocalAdrs() to compute bus address,
  38.                  fixed warnings.
  39. 02p,18jul92,smb  Changed errno.h to errnoLib.h.
  40. 02o,26may92,rrr  the tree shuffle
  41.                   -changed includes to have absolute path from h/
  42. 02n,05may92,wmd  changed LITTLE_ENDIAN to _LITTLE_ENDIAN, BYTE_ORDER to
  43.                  _BYTE_ORDER, cleaned up ansi warnings.
  44. 02m,15jan92,wmd  Added conditional to use ntohl for little Endian in enpput()
  45.                  and initialized pEnpDev->enp_mode with 0x8000 (960 only).
  46. 02l,17oct91,yao  added support for CPU32.
  47. 02k,04oct91,rrr  passed through the ansification filter
  48.                   -changed functions to ansi style
  49.                   -changed includes to have absolute path from h/
  50.                   -fixed #else and #endif
  51.                   -changed READ, WRITE UPDATE to O_RDONLY O_WRONLY O_RDWR
  52.                   -changed VOID to void
  53.                   -changed copyright notice
  54. 02j,22aug91,hdn  fixed bug in enpgetaddr.
  55. 02i,19jun91,km   some modifications for 960 -- not verified correct.
  56.                  +gae  compiled in enpShow; added enpDump for debug.
  57.                  fixed some usages of ENPDEVICE_OLD (for old CMC LINK-10 ROMs).
  58. 02h,29apr91,hdn  use SIZEOF_ETHERHEADER instead of sizeof(ether_header).
  59. 02g,10apr91,jdi  documentation cleanup; doc review by elh.
  60. 02f,25oct90,gae  made access of "lost carrier" 32-bit register be two 16-bit
  61.                  access -- some boards generate a bus error.
  62. 02e,20oct90,gae  added detection of "lost carrier"; added but ifdef'd out
  63.                  enpShow routine; cleanup.
  64. 02d,02oct90,hjb  de-linted.
  65. 02c,19sep90,dab  made enpinit() return int.  made bcopy_to_mbufs() call in
  66.                  enpread() to use width of 1 for 680[01]0 cpus.
  67. 02b,26aug90,hjb  added a hack to avoid prob caused when copying data from
  68.                  hkv2f a word at a time into ENP memory starting at an odd-byte
  69.                  boundary.
  70. 02a,10aug90,dnw  added forward declarations for void functions.
  71.                  added include of if_subr.h.
  72. 01z,11jul90,hjb  removed code that uses gotIp which is no longer necessary.
  73.                  made enpread() void.  changed references to do_protocol()
  74.                  to do_protocol_with_type().
  75. 01y,26jun90,hjb  copy_from_mbufs() & m_freem() fix; fixed enpattach() error msg
  76. 01x,07may90,hjb  changed bcopy_to_mbufs to copy 16 bits at a time.
  77. 01w,19apr90,hjb  deleted param.h, modifications for bcopy_from_mbufs().
  78. 01v,22mar90,hjb  changed copy_to_mbuf() to bcopy_to_mbuf() with argument
  79.                  bcopyBytes() to fix the problems associated with using
  80.                  ENP with hkv2f caused by bcopy'ing more than a byte at a time
  81.                  over VME.
  82. 01u,18mar90,hjb  reduction of redundant code and addition of cluster support.
  83. 01t,06aug89,gae  changed iv68k.h to iv.h.
  84. 01s,25may89,hjb  enpioctl() SIOCSIFFLAGS, check for IFF_UP before calling
  85.                  enpinit().
  86. 01r,24may89,rdc  enpintr no longer does netJobAdd if task level is
  87.                  already processing packets. (fixes netRing overflows)
  88.                  enpoutput now bumps if_opackets.
  89. 01q,17apr89,del  fixed comment in enpgetaddr.
  90. 01q,13apr89,del  fixed problem introduced by CMC when they changed to
  91.                  version 4.0 Link-10 roms.
  92. 01p,05aug88,dnw  fixed oversight in enpreset in 01o.
  93. 01o,04aug88,dnw  fixed bug causing occasional initialization failure.
  94.                  simplified reset.
  95. 01n,23jun88,rdc  added IFF_BROADCAST to if_flags.
  96. 01m,05jun88,dnw  changed enp_softc to array of ptrs to descriptors.
  97.                  increased NENP from 1 to 4.
  98. 01l,30may88,dnw  changed to v4 names.
  99. 01k,22feb88,jcf  made kernel independent.
  100. 01j,20feb88,dnw  cleanup, lint.
  101. 01i,10feb88,rdc  re-installed enpreset which i accidently trashed in 01g.
  102.                  optimized packet reception by calling ipintr only once
  103.                  for a bunch of packets.
  104. 01h,14jan88,jcf  extended maximum firmware initialization wait to 15 seconds
  105. 01g,05jan88,rdc  added include of systm.h
  106. 01f,20nov87,ecs  lint
  107.            &dnw  changed enpattach to take int vec num instead of vec adrs.
  108. 01e,19nov87,dnw  changed to program interrupt vector.
  109.                  changed initial wait loop to use vxMemProbe.
  110. 01d,08nov87,dnw  added output hook code.
  111.                  changed calling sequence to input hook.
  112. 01c,21oct87,ecs  delinted
  113. 01b,28aug87,dnw  removed unnecessary includes.
  114.                  added input hook code.
  115.                  clean up.
  116. 01a,21jul87,rdc  adapted from cmc's 4.2 driver.
  117. */
  118. /*
  119. This module implements the CMC ENP 10/L Ethernet network interface driver.
  120. This driver is designed to be moderately generic, operating unmodified 
  121. across the range of architectures and targets supported by VxWorks.
  122. To achieve this, the driver must be given several target-specific
  123. parameters.  These parameters, and the mechanisms used to communicate them
  124. to the driver, are detailed below.  This driver supports up to four
  125. individual units per CPU.
  126. BOARD LAYOUT
  127. The diagram below shows the relevant jumpers for VxWorks configuration.
  128. Default values are: I/O address 0x00de0000, Standard Addressing (A24),
  129. interrupt level 3.
  130. .bS
  131. ______________________________              _______________________________
  132. |             P1             |    ENP-10    |             P2              |
  133. |                            ----------------                             |
  134. |                   ::::X::                L                              |
  135. |                   INT LVL                L INT ACK                      |
  136. |                                          R                              |
  137. |                                                                         |
  138. |                                                                         |
  139. |                                                                         |
  140. |                                                                         |
  141. |                                                                         |
  142. |                                                                         |
  143. |                                                                         |
  144. |   "                                                                     |
  145. |   " IO ADRS                                                             |
  146. |   -                                            -------  -------         |
  147. |   "                                           |  ROM  ||  ROM  |        |
  148. |   "                                           |LINK-10||LINK-10|        |
  149. |   "                                           |       ||       |        |
  150. |   "                                           | HIGH  ||  LOW  |        |
  151. |                                               |  U4   ||  U3   |        |
  152. |                                                ---^---  ---^---         |
  153. |_________________________________________________________________________|
  154. .bE
  155. .bS
  156. ______________________________              _______________________________
  157. |             P1             |  ENP-10/L    |             P2              |
  158. |  JP17    JP16      JP15    ----------------                ----------   |
  159. |  X:XX=_: ::X::::   ::::X::          " JP14                |  ROM     |  |
  160. |          ADRS BITS INT LVL          " ADRS BITS (EXT)     > LINK-10  |  |
  161. |                                     "                     |  LOW  U63|  |
  162. |    JP12                             "                      ==========   |
  163. |  " STD/                             "                     |  ROM     |  |
  164. |  " EXT                              "                     > LINK-10  |  |
  165. |  "                                  "                     |  HIGH U62|  |
  166. |  "                                  "                      ----------   |
  167. |  -                                  _ JP13 TIMEOUT                      |
  168. |                                     " JP13 TIMEOUT*                     |
  169. |  "                                                                      |
  170. |  " INT ACK                                                              |
  171. |  - JP11                                                                 |
  172. |            _. JP7 SYSCLOCK                                              |
  173. |            ._ JP7 SYSCLOCK*                                             |
  174. |      ._ JP8                                                             |
  175. |                                                                         |
  176. |                                                                         |
  177. |                                                                         |
  178. |_________________________________________________________________________|
  179. .bE
  180. EXTERNAL INTERFACE
  181. This driver provides the standard external interface with the following
  182. exceptions.  All initialization is performed within the attach routine;
  183. there is no separate initialization routine.  Therefore, in the global interface
  184. structure, the function pointer to the initialization routine is NULL.
  185. The only user-callable routine is enpattach(), which publishes the `enp'
  186. interface and initializes the driver and device.
  187. TARGET-SPECIFIC PARAMETERS
  188. .iP "base VME address of ENP memory"
  189. This parameter is passed to the driver by enpattach().
  190. The ENP board presents an area of its memory to the VME bus.  This
  191. address is jumper selectable on the ENP.  This parameter is the same as
  192. the address selected on the ENP.
  193. .iP "VME address modifier code"
  194. This parameter is passed to the driver by enpattach().
  195. It specifies the AM (address modifier) code to use when the driver accesses
  196. the VME address space of the ENP board.
  197. .iP "interrupt vector"
  198. This parameter is passed to the driver by enpattach().
  199. It specifies the interrupt vector to be used by the driver
  200. to service an interrupt from the ENP board.  The driver will connect
  201. the interrupt handler to this vector by calling intConnect().
  202. .iP "interrupt level"
  203. This parameter is passed to the driver by enpattach().
  204. It specifies the interrupt level that is associated with the
  205. interrupt vector.  The driver enables the interrupt from the ENP by
  206. calling sysIntEnable() and passing this parameter.
  207. .LP
  208. SYSTEM RESOURCE USAGE
  209. When implemented, this driver requires the following system resources:
  210.     - one mutual exclusion semaphore
  211.     - one interrupt vector
  212.     - 76 bytes in the initialized data section (data)
  213.     - 808 bytes in the uninitialized data section (BSS)
  214. The above data and BSS requirements are for the MC68020 architecture 
  215. and may vary for other architectures.  Code size (text) varies greatly between
  216. architectures and is therefore not quoted here.
  217. The ENP board provides the buffers for all packets transmitted and received.
  218. Therefore, the driver does not require any system memory to share with the
  219. device.  This also eliminates all data cache coherency issues.
  220. SEE ALSO: ifLib
  221. */
  222. #include "vxWorks.h"
  223. #include "net/mbuf.h"
  224. #include "net/protosw.h"
  225. #include "sys/ioctl.h"
  226. #include "sys/socket.h"
  227. #include "errnoLib.h"
  228. #include "net/uio.h"
  229. #include "net/if.h"
  230. #include "net/route.h"
  231. #include "netinet/in.h"
  232. #include "netinet/in_systm.h"
  233. #include "netinet/ip.h"
  234. #include "netinet/ip_var.h"
  235. #include "netinet/in_var.h"
  236. #include "netinet/if_ether.h"
  237. #include "drv/netif/if_enp.h"
  238. #include "etherLib.h"
  239. #include "vme.h"
  240. #include "iv.h"
  241. #include "iosLib.h"
  242. #include "ioLib.h"
  243. #include "memLib.h"
  244. #include "net/systm.h"
  245. #include "net/if_subr.h"
  246. #include "sysLib.h"
  247. #include "vxLib.h"
  248. #include "stdio.h"
  249. #include "intLib.h"
  250. #include "logLib.h"
  251. #include "string.h"
  252. #include "netLib.h"
  253. #include "stdlib.h"
  254. #include "semLib.h"
  255. #include "cacheLib.h"
  256. /***** LOCAL DEFINITIONS *****/
  257. #undef ENP_DEBUG            /* define to display error/status messages */
  258. #define MAX_UNITS    4                  /* max units to support */
  259. /* Typedefs for external structures that are not typedef'd in their .h files */
  260. typedef struct mbuf MBUF;
  261. typedef struct arpcom IDR;                  /* Interface Data Record wrapper */
  262. typedef struct ifnet IFNET;                 /* real Interface Data Record */
  263. typedef struct sockaddr SOCK;
  264. #ifdef BSD43_DRIVER
  265. /* The Ethernet header */
  266. typedef struct enet_hdr
  267.     {
  268.     char dst [6];
  269.     char src [6];
  270.     u_short type;
  271.     } ENET_HDR;
  272. #endif
  273. #define ENET_HDR_SIZ        sizeof(ENET_HDR)
  274. #define ENET_HDR_REAL_SIZ   14
  275. /* The definition of the driver control structure */
  276. typedef struct drv_ctrl
  277.     {
  278.     IDR         idr;                    /* interface data record */
  279.     BOOL        attached;               /* TRUE if attach() has succeeded */
  280.     ENPDEVICE   *enpAddr;               /* VME address of board */
  281.     ENPSTAT     enpStat;                /* duplicate copy of ENP statisics */
  282.     ULONG       lostCarrier;            /* statistic counter */
  283.     int         enpIntLevel;            /* VME interrupt level */
  284.     int         enpIntVec;              /* VME interrupt vector */
  285.     BOOL        taskLevelActive;        /* netTask processing packets */
  286. #ifdef BSD43_DRIVER
  287.     SEM_ID      TxSem;                  /* transmitter semaphore */
  288. #endif
  289.     } DRV_CTRL;
  290. /***** LOCALS *****/
  291. /* The array of driver control structures, one per unit supported */
  292. LOCAL DRV_CTRL drvCtrl [MAX_UNITS];
  293. /*LOCAL*/ BOOL enpNewROM;       /* TRUE if LINK-10 v4.0 or higher */
  294. /***** FUNCTION DECLARATIONS *****/
  295. /* those not defined in header files */
  296. extern int splimp (void);
  297. extern void splx (int spl);
  298. /* forward static functions */
  299. static int enpIoctl (IDR *pIDR, int cmd, caddr_t data);
  300. #ifdef BSD43_DRIVER
  301. static int enpOutput (IDR *pIDR, MBUF *pMbuf, SOCK *dst);
  302. #else
  303. LOCAL void enpTxStartup (DRV_CTRL * pDrvCtrl);
  304. #endif
  305. static int enpringput (RING *rp, BCB *pBCB);
  306. static int enpringget (RING *rp);
  307. static void enpIntr (int unit);
  308. static void enpRxEvent (int unit);
  309. static void enpgetaddr (int unit);
  310. static BOOL enpringempty (RING *rp);
  311. #ifdef BSD43_DRIVER
  312. static BOOL convertDestAddr
  313.             (
  314.             IDR *pIDR,
  315.             SOCK *pDestSktAddr,
  316.             char *pDestEnetAddr,
  317.             u_short *pPacketType,
  318.             MBUF *pMbuf
  319.             );
  320. #endif
  321. static STATUS enpReset (int unit);
  322. static STATUS enpRxPktProcess (int unit);
  323. /*******************************************************************************
  324. *
  325. * enpattach - publish the `enp' network interface and initialize the driver and device
  326. *
  327. * This routine publishes the `enp' interface by filling in a network 
  328. * interface record and adding this record to the system list.  It also
  329. * initializes the driver and the device to the operational state.
  330. *
  331. * RETURNS: OK or ERROR.
  332. */
  333. STATUS enpattach
  334.     (
  335.     int unit,           /* unit number                     */
  336.     char *addr,         /* address of enp's shared memory  */
  337.     int ivec,           /* interrupt vector to connect to  */
  338.     int ilevel,         /* interrupt level                 */
  339.     int enpAddrAm       /* address VME address modifier */
  340.     )
  341.     {
  342.     int        delay;
  343.     short      status;
  344.     int        temp;
  345.     ENPDEVICE  *pEnpDev;
  346.     char       *enpBase;
  347.     DRV_CTRL   *pDrvCtrl;
  348. #ifdef ENP_DEBUG
  349.     printf ( "nenp: attach: unit=%d, addr=%x, ivec=%d, ilevel=%d, Am=%dn",
  350.              unit, addr, ivec, ilevel, enpAddrAm );
  351. #endif
  352.     /* Safety check unit number */
  353.     if (unit < 0 || unit >= MAX_UNITS)
  354.         {
  355.         errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  356.         return (ERROR);
  357.         }
  358.     /* Get pointer to our driver control structure */
  359.     pDrvCtrl = & drvCtrl [unit];
  360.     /* Check for multiple invocation per unit */
  361.     if (pDrvCtrl->attached)
  362.         return (OK);
  363.     /* Publish the interface data record */
  364. #ifdef BSD43_DRIVER
  365.     ether_attach    ( & pDrvCtrl->idr.ac_if, unit, "enp", (FUNCPTR) NULL,
  366.                       (FUNCPTR) enpIoctl, (FUNCPTR) enpOutput,
  367.                       (FUNCPTR) enpReset);
  368. #else
  369.     ether_attach ( 
  370.                  &pDrvCtrl->idr.ac_if, unit, 
  371.                  "enp", 
  372.                  (FUNCPTR)NULL,
  373.                  (FUNCPTR)enpIoctl, 
  374.                  (FUNCPTR)ether_output,
  375.                  (FUNCPTR)enpReset
  376.                  );
  377.     pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)enpTxStartup;
  378. #endif
  379. #ifdef BSD43_DRIVER
  380.     /* Create the transmit semaphore. */
  381.     pDrvCtrl->TxSem = semMCreate    (
  382.                                     SEM_Q_PRIORITY |
  383.                                     SEM_DELETE_SAFE |
  384.                                     SEM_INVERSION_SAFE
  385.                                     );
  386.     if (pDrvCtrl->TxSem == NULL)
  387.         {
  388. #ifdef ENP_DEBUG
  389.         printf ("enp: error creating transmitter semaphoren");
  390. #endif
  391.         return (ERROR);
  392.         }
  393. #endif
  394.     /* Determine local address and AM codes to access the controller */
  395.     if (sysBusToLocalAdrs (enpAddrAm, addr, &enpBase) == ERROR)
  396.         {
  397.         errnoSet (EFAULT);
  398.         return (ERROR);
  399.         }
  400. #ifdef ENP_DEBUG
  401.     printf ( "enp: attach: local addr=%xn", enpBase );
  402. #endif
  403.     pEnpDev = (ENPDEVICE *) enpBase;
  404.     enpBase += 0x1000;  /* memory is offset from board base address */
  405.     /* Connect the interrupt handler */
  406.     (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec),
  407.                        (VOIDFUNCPTR)enpIntr, unit);
  408.     /* wait for kernel reset to finish */
  409.     delay = 15 * sysClkRateGet ();
  410.     while (1)
  411.         {
  412.         /* Test for response on the buss */
  413.         if  (
  414.             vxMemProbe  (
  415.                         (char *) & pEnpDev->enp_status,
  416.                         O_RDONLY,
  417.                         sizeof (short),
  418.                         (char *) & status
  419.                         )
  420.             == OK
  421.             )
  422.             {
  423.             /* Check status word */
  424.             if ( (ntohs (status) & STS_READY) != 0 )
  425.                 break;
  426.             }
  427.         /* Check for timeout */
  428.         if (--delay <= 0)
  429.             {
  430.             (void) errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  431.             return (ERROR);
  432.             }
  433.         taskDelay (sysClkRateGet() / 30);       /* 1/30th of a second */
  434.         }
  435.     /* start link level firmware */
  436.     pEnpDev->enp_intvector = htons (ivec);
  437.     temp = htonl ((u_long) enpBase);
  438.     WRITELONG (&pEnpDev->enp_base, temp);
  439. #if  CPU_FAMILY==I960
  440.     pEnpDev->enp_mode = htons (0x0080);
  441. #endif /* CPU_FAMILY==I960 */
  442.     pEnpDev->enp_go = htons (GOVAL);
  443.     CACHE_PIPE_FLUSH ();
  444.     /* wait for the link level firmware to finish initialization */
  445.     delay = 15 * sysClkRateGet ();
  446.     while ((ntohs (pEnpDev->enp_state) & S_ENPRUN) == 0)
  447.         {
  448.         if (--delay <= 0)
  449.             {
  450.             (void) errnoSet (S_ioLib_DEVICE_ERROR);
  451.             return (ERROR);
  452.             }
  453.         taskDelay (sysClkRateGet() / 30);       /* 1/30th of a second */
  454.         }
  455.     pDrvCtrl->enpAddr     = pEnpDev;
  456.     pDrvCtrl->enpIntLevel = ilevel;
  457.     pDrvCtrl->enpIntVec   = ivec;
  458.     enpgetaddr (unit);
  459.     (void) sysIntEnable (ilevel);
  460.     /* Raise the interface flags */
  461.     pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_MULTICAST;
  462.     /* Set our success indicator */
  463.     pDrvCtrl->attached = TRUE;
  464.     return (OK);
  465.     }
  466. /*******************************************************************************
  467. *
  468. * enpReset - reset the interface
  469. */
  470. LOCAL STATUS enpReset
  471.     (
  472.     int unit
  473.     )
  474.     {
  475.     DRV_CTRL *pDrvCtrl;
  476.     ENPDEVICE *pEnpDev;
  477. #ifdef ENP_DEBUG
  478.     printf ( "enp: reset: unit=%dn", unit );
  479. #endif
  480.     /* Safety check unit number */
  481.     if (unit < 0 || unit >= MAX_UNITS)
  482.         {
  483.         errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  484.         return (ERROR);
  485.         }
  486.     pDrvCtrl = & drvCtrl[unit];
  487.     pEnpDev = pDrvCtrl->enpAddr;
  488.     pDrvCtrl->idr.ac_if.if_flags = 0;
  489.     RESET_ENP (pEnpDev);
  490.     /* reset the status word that enpattach watches to know when enp is reset;
  491.      * this is necessary because the enp doesn't clear this status immediately
  492.      * on reset.  Re-initializing the enp after a reset (i.e. in VxWorks
  493.      * init after boot rom reset) could get fooled if we rely on enp to clear
  494.      * the READY bit in this status.
  495.      */
  496.     pEnpDev->enp_status = 0;
  497.     CACHE_PIPE_FLUSH ();
  498.     return (OK);
  499.     }
  500. /*******************************************************************************
  501. *
  502. * enpIntr - the driver's interrupt handler
  503. *
  504. * The ENP board will only interrupt us to notify us that there are packets
  505. * to be processed.  The processing of each packet is done by netTask.  This
  506. * routine simply queues our job for netTask.
  507. */
  508. LOCAL void enpIntr
  509.     (
  510.     int unit
  511.     )
  512.     {
  513.     DRV_CTRL *pDrvCtrl;
  514.     /* Safety check unit number */
  515.     if (unit < 0 || unit >= MAX_UNITS)
  516.         return;
  517.     pDrvCtrl = & drvCtrl [unit];
  518.     sysBusIntAck (pDrvCtrl->enpIntLevel);
  519.     if (!pDrvCtrl->taskLevelActive)
  520.         {
  521.         /* indicate that enpHandleInt is q'd */
  522.         pDrvCtrl->taskLevelActive = TRUE;
  523.         (void) netJobAdd ((FUNCPTR)enpRxEvent, unit, 0,0,0,0);
  524.         /* see comment in enpHandleInt */
  525.         }
  526.     }
  527. /*******************************************************************************
  528. *
  529. * enpRxEvent - handler for receive events
  530. */
  531. LOCAL void enpRxEvent
  532.     (
  533.     int unit
  534.     )
  535.     {
  536.     DRV_CTRL  *pDrvCtrl;
  537.     ENPDEVICE *pDev;
  538.     pDrvCtrl = & drvCtrl [unit];
  539.     pDev = pDrvCtrl->enpAddr;
  540.     splx (0);       /* Give up the spl semaphore taken for us by netTask. */
  541.     /* the following loop attempts to pull multiple buffers off of the
  542.      * input queue;  the boolean "taskLevelActive" is used to inform
  543.      * the interrupt level code that we're already processing input
  544.      * buffers, so there's no need to do a netJobAdd, thereby decreasing
  545.      * the possibility of a net task ring buffer overflow.
  546.      */
  547.     do
  548.         {
  549.         pDrvCtrl->taskLevelActive = TRUE;
  550.         while (!enpringempty ((RING*) &pDev->enp_tohost))
  551.             {
  552.             if ( enpRxPktProcess (unit) == ERROR )
  553.                 {
  554.                 pDrvCtrl->taskLevelActive = FALSE;
  555.                 splimp ();      /* Take the spl semaphore for netTask */
  556.                 return;
  557.                 }
  558.             }
  559.         pDrvCtrl->taskLevelActive = FALSE;
  560.         /* check once more after resetting taskLevelActive to avoid race */
  561.         }
  562.     while (!enpringempty ((RING*) &pDev->enp_tohost));
  563.     splimp ();      /* Take the spl semaphore for netTask */
  564.     }
  565. /*******************************************************************************
  566. *
  567. * enpRxPktProcess - process the next received packet
  568. *
  569. * Copy packets from a BCB into an mbuf and hand it to the next higher layer.
  570. */
  571. LOCAL STATUS enpRxPktProcess
  572.     (
  573.     int unit
  574.     )
  575.     {
  576.     int             len;
  577.     int             temp;
  578.     DRV_CTRL        *pDrvCtrl;
  579.     ENET_HDR        *pEnetHdr;
  580.     MBUF            *pMbuf;
  581.     BCB             *pBCB;
  582.     ENPDEVICE       *pDev;
  583.     unsigned char   *pData;
  584.     /* Get control pointers */
  585.     pDrvCtrl = & drvCtrl [unit];
  586.     pDev = pDrvCtrl->enpAddr;
  587.     /* Check ifnet flags. Return if incorrect. */
  588.     if  (
  589.         (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
  590.         (IFF_UP | IFF_RUNNING)
  591.         )
  592.         return (ERROR);
  593.     /* Get pointer to next packet */
  594.     pBCB = (BCB*) enpringget ((RING*) &pDev->enp_tohost);
  595.     if (pBCB == NULL)                     /* unlikely error */
  596.         return (ERROR);
  597.     /* Bump the incoming packet statistic */
  598.     pDrvCtrl->idr.ac_if.if_ipackets++;
  599.     /* Get length of packet */
  600.     len = ntohs (pBCB->b_msglen);
  601.     /* Get pointer to packet */
  602.     READLONG ((& pBCB->b_addr), &temp);
  603.     pEnetHdr = (ENET_HDR *) ntohl (temp);
  604.     /* call input hook if any */
  605.     if (etherInputHookRtn != NULL)
  606.         {
  607.         if  (
  608.             (*etherInputHookRtn) (& pDrvCtrl->idr.ac_if, (char *) pEnetHdr, len)
  609.             == 1
  610.             )
  611.             {
  612.             (void) enpringput ((RING *)&pDev->enp_enpfree, pBCB);
  613.             return (OK);
  614.             }
  615.         }
  616.     /* Adjust length; subtract size of header */
  617.     len -= ENET_HDR_REAL_SIZ;
  618.     /* Get pointer to data section of the packet */
  619.     pData = ((unsigned char *) pEnetHdr) + ENET_HDR_REAL_SIZ;
  620.     /* copy data from enp to mbuf a word at a time */
  621. #if (CPU == MC68000) || (CPU == MC68010) || (CPU == CPU32)
  622.     pMbuf = bcopy_to_mbufs (pData, len, 0, (IFNET *) &pDrvCtrl->idr.ac_if, 1);
  623. #else
  624.     pMbuf = bcopy_to_mbufs (pData, len, 0, (IFNET *) &pDrvCtrl->idr.ac_if, 2);
  625. #endif  /* (CPU == MC68000) || (CPU == MC68010) || (CPU == CPU32) */
  626.     if (pMbuf != NULL)
  627. #ifdef BSD43_DRIVER
  628.         do_protocol_with_type   (
  629.                                 ntohs (pEnetHdr->type),
  630.                                 pMbuf,
  631.                                 & pDrvCtrl->idr,
  632.                                 len
  633.                                 );
  634. #else
  635.         do_protocol (pEnetHdr, pMbuf, &pDrvCtrl->idr, len);
  636. #endif
  637.     else
  638.         ++pDrvCtrl->idr.ac_if.if_ierrors;       /* bump error stat */
  639.     (void) enpringput ((RING *)&pDev->enp_enpfree, pBCB);
  640.     return (OK);
  641.     }
  642. #ifdef BSD43_DRIVER
  643. /*******************************************************************************
  644. *
  645. * enpOutput - the driver's output routine
  646. *
  647. * The destination address is passed to this function as a pointer to a
  648. * generic socket address structure.  This address information is first
  649. * converted to the six byte destination address and type field that we
  650. * need to build a proper Ethernet frame.
  651. *
  652. * The data to be sent out is held in a chain of mbufs.  This function is
  653. * passed a pointer to the head mbuf.  The data in each mbuf fragment must
  654. * be copied to the device's packet buffer.
  655. */
  656. LOCAL STATUS enpOutput
  657.     (
  658.     IDR *pIDR,
  659.     MBUF *pMbuf,
  660.     SOCK *pDest
  661.     )
  662.     {
  663.     int         lostCarrier;
  664.     int         blen;
  665.     u_short     packetType;
  666.     u_char      *bufStart;
  667.     DRV_CTRL    *pDrvCtrl;
  668.     ENPDEVICE   *pDev;
  669.     MBUF        *pTempMbuf;
  670.     BCB         *pBCB;
  671.     u_char      *pBuf;
  672.     char        destEnetAddr [6];
  673. #ifdef ENP_DEBUG
  674.     printf ( "enp: output: pIDR=%x, pMbuf=%x, pDest=%xn",
  675.              pIDR, pMbuf, pDest );
  676. #endif
  677.     /* Check ifnet flags. Return error if incorrect. */
  678.     if  (
  679.         (pIDR->ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=
  680.         (IFF_UP | IFF_RUNNING)
  681.         )
  682.         return (ENETDOWN);
  683.     /* Attempt to convert socket addr into enet addr and packet type.
  684.      * Note that if ARP resolution of the address is required, the ARP
  685.      * module will call our routine again to transmit the ARP request
  686.      * packet.  This means we may actually call ourselves recursively!
  687.      */
  688.     if (convertDestAddr (pIDR,pDest, destEnetAddr, &packetType, pMbuf) == FALSE)
  689.         return (OK);    /* I KNOW returning OK is stupid, but it is correct */
  690.     /* Get driver control pointer */
  691.     pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit];
  692.     pDev = (ENPDEVICE *) pDrvCtrl->enpAddr;
  693.     /* Obtain exclusive access to transmitter.  This is necessary because
  694.      * certain events can cause netTask to run a job that attempts to transmit
  695.      * a packet.  We can only allow one task here at a time.
  696.      */
  697.     semTake (pDrvCtrl->TxSem, WAIT_FOREVER);
  698.     /* some boards (eg. iv3201a,hkv2f,mv133) get bus errors with 32bit access */
  699.     READLONG (&pDev->enp_stat.e_lost_carrier, &lostCarrier);
  700.     lostCarrier = ntohl (lostCarrier);
  701.     if (lostCarrier > pDrvCtrl->lostCarrier)
  702.         {
  703.         /* The test should probably be "not equal", however, roll-over
  704.          * will take a long time.  After reset pDrvCtrl->lostCarrier won't
  705.          * be in sync -- we should initialize (i.e. read) it elsewhere.
  706.          *
  707.          * Keep a separate count of lost carrier so statics don't
  708.          * get messed up.
  709.          */
  710.         pDrvCtrl->lostCarrier = lostCarrier;
  711. #ifdef ENP_DEBUG
  712.         logMsg  ("enp%d: lost carriern",
  713.                 pDrvCtrl->idr.ac_if.if_unit, 0, 0, 0, 0, 0);
  714. #endif
  715.         }
  716.     /* If no resource available, discard packet */
  717.     if (enpringempty ((RING *) &pDev->enp_hostfree))
  718.         {
  719.         semGive (pDrvCtrl->TxSem);          /* Release exclusive access. */
  720.         m_freem (pMbuf);
  721.         return (OK);
  722.         }
  723.     pBCB = (BCB *) enpringget ((RING *)&pDev->enp_hostfree);
  724.     /* Get pointer to buffer to fill with outgoing packet */
  725.     READLONG ((&pBCB->b_addr),  &bufStart);
  726.     bufStart = (u_char *) ntohl ((int)bufStart);
  727.     /* First fill in the Ethernet header */
  728.     pBuf = bufStart;
  729.     bcopyBytes (destEnetAddr, (char *) pBuf, 6);
  730.     pBuf += 6;
  731.     bcopyBytes ((char *) pDrvCtrl->idr.ac_enaddr, (char *) pBuf, 6);
  732.     pBuf += 6;
  733.     bcopyBytes ( (char *)&packetType, (char *) pBuf, 2);
  734.     pBuf += 2;
  735.     /* copy data from mbufs to enp a word at a time.
  736.      * most other netif drivers use copy_from_mbufs() to accomplish
  737.      * this task.  we're doing this manually here because we
  738.      * need to take care of a special case (hkv2f + ENP, see below).
  739.      */
  740.     pTempMbuf = pMbuf;                      /* copy ptr */
  741.     while (pTempMbuf != NULL)
  742.         {
  743.         /* if destination adrs starts at odd byte boundary
  744.          * copy a byte at a time.  copying a word from hkv2f into ENP memory
  745.          * starting at an odd byte causes problems.
  746.          */
  747.         if (((int) pBuf & 1) == 1)
  748.             bcopyBytes  (
  749.                         mtod (pTempMbuf, char *),
  750.                         (char *) pBuf,
  751.                         (int) pTempMbuf->m_len
  752.                         );
  753.         else
  754.             {
  755.             blen = pTempMbuf->m_len >> 1;
  756.             /* copy 2 bytes at a time */
  757.             bcopyWords (mtod (pTempMbuf, char *), (char *) pBuf, blen);
  758.             /* copy the remaining byte if any */
  759.             blen <<= 1;
  760.             if (blen != pTempMbuf->m_len)
  761.                 {
  762.                 *((char *) (pBuf + blen)) =
  763.                     *((char *) (mtod (pTempMbuf, char *) + blen));
  764.                 }
  765.             }
  766.         /* Move pointer ahead, and get next mbuf pointer */
  767.         pBuf += pTempMbuf->m_len;
  768.         pTempMbuf = pTempMbuf->m_next;
  769.         }
  770.     /* Done with mbufs, release them to system */
  771.     m_freem (pMbuf);
  772.     /* Set length of packet */
  773.     blen = max ( MINPKTSIZE, ((int) pBuf - (int) bufStart) );
  774.     pBCB->b_len = htons (blen);
  775.     /* Put the BCB on the outgoing ring, and if this is the only entry on
  776.      * the ring, generate an interrupt to the ENP by writing to the special
  777.      * location in the shared memory space.  Some boards require this
  778.      * interrupt, while others work fine without it, and still others perform
  779.      * a reset instead of the interrupt.  Go figure.
  780.      */
  781.     if ( enpringput ((RING *) & pDev->enp_toenp, pBCB) == 1 )
  782.         pDev->enp_iow.hst2enp_interrupt = ENPVAL;
  783.     /* Bump the statistic counter. */
  784.     pIDR->ac_if.if_opackets++;
  785.     /* Release exclusive access. */
  786.     semGive (pDrvCtrl->TxSem);
  787.     return (OK);
  788.     }
  789. #else
  790. /*******************************************************************************
  791. *
  792. * enpTxStartup - kick start the transmitter after generic ether_output
  793. *
  794. */
  795. LOCAL void enpTxStartup
  796.     (
  797.     DRV_CTRL * pDrvCtrl  /* pointer to driver control structure */
  798.     )
  799.     {
  800.     int         lostCarrier;
  801.     int         blen;
  802.     u_char      *bufStart;
  803.     ENPDEVICE   *pDev;
  804.     MBUF        *pTempMbuf;
  805.     BCB         *pBCB;
  806.     u_char      *pBuf;
  807.     MBUF * pMbuf;
  808.     pDev = (ENPDEVICE *) pDrvCtrl->enpAddr;
  809.     /* BSD 4.4 drivers already have exclusive access - no semaphore needed. */
  810.     /* some boards (eg. iv3201a,hkv2f,mv133) get bus errors with 32bit access */
  811.     READLONG (&pDev->enp_stat.e_lost_carrier, &lostCarrier);
  812.     lostCarrier = ntohl (lostCarrier);
  813.     if (lostCarrier > pDrvCtrl->lostCarrier)
  814.         {
  815.         /* The test should probably be "not equal", however, roll-over
  816.          * will take a long time.  After reset pDrvCtrl->lostCarrier won't
  817.          * be in sync -- we should initialize (i.e. read) it elsewhere.
  818.          *
  819.          * Keep a separate count of lost carrier so statics don't
  820.          * get messed up.
  821.          */
  822.         pDrvCtrl->lostCarrier = lostCarrier;
  823. #ifdef ENP_DEBUG
  824.         logMsg  ("enp%d: lost carriern",
  825.                 pDrvCtrl->idr.ac_if.if_unit, 0, 0, 0, 0, 0);
  826. #endif
  827.         }
  828.     while (pDrvCtrl->idr.ac_if.if_snd.ifq_head)
  829.         {
  830.         IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);
  831.         /* If no resource available, discard packet */
  832.         if (enpringempty ((RING *) &pDev->enp_hostfree))
  833.             {
  834.             if (pMbuf != NULL)
  835.                 m_freem (pMbuf);
  836.             break;
  837.             }
  838.         pBCB = (BCB *) enpringget ((RING *)&pDev->enp_hostfree);
  839.         /* Get pointer to buffer to fill with outgoing packet */
  840.         READLONG ((&pBCB->b_addr),  &bufStart);
  841.         bufStart = (u_char *) ntohl ((int)bufStart);
  842.         pBuf = bufStart;
  843.         /* copy data from mbufs to enp a word at a time.
  844.          * most other netif drivers use copy_from_mbufs() to accomplish
  845.          * this task.  we're doing this manually here because we
  846.          * need to take care of a special case (hkv2f + ENP, see below).
  847.          */
  848.         pTempMbuf = pMbuf;                      /* copy ptr */
  849.         while (pTempMbuf != NULL)
  850.             {
  851.             /* if destination adrs starts at odd byte boundary
  852.              * copy a byte at a time.  copying a word from hkv2f into ENP memory
  853.              * starting at an odd byte causes problems.
  854.              */
  855.             if (((int) pBuf & 1) == 1)
  856.                 bcopyBytes  (
  857.                             mtod (pTempMbuf, char *),
  858.                             (char *) pBuf,
  859.                             (int) pTempMbuf->m_len
  860.                             );
  861.             else
  862.                 {
  863.                 blen = pTempMbuf->m_len >> 1;
  864.                 /* copy 2 bytes at a time */
  865.                 bcopyWords (mtod (pTempMbuf, char *), (char *) pBuf, blen);
  866.                 /* copy the remaining byte if any */
  867.                 blen <<= 1;
  868.                 if (blen != pTempMbuf->m_len)
  869.                     {
  870.                     *((char *) (pBuf + blen)) =
  871.                         *((char *) (mtod (pTempMbuf, char *) + blen));
  872.                     }
  873.                 }
  874.             /* Move pointer ahead, and get next mbuf pointer */
  875.             pBuf += pTempMbuf->m_len;
  876.             pTempMbuf = pTempMbuf->m_next;
  877.             }
  878.         /* Done with mbufs, release them to system */
  879.         m_freem (pMbuf);
  880.         /* Set length of packet */
  881.         blen = max ( MINPKTSIZE, ((int) pBuf - (int) bufStart) );
  882.         pBCB->b_len = htons (blen);
  883.         /* Put the BCB on the outgoing ring, and if this is the only entry on
  884.          * the ring, generate an interrupt to the ENP by writing to the special
  885.          * location in the shared memory space.  Some boards require this
  886.          * interrupt, while others work fine without it, and still others 
  887.          * perform a reset instead of the interrupt.  Go figure.
  888.          */
  889.         if ( enpringput ((RING *) & pDev->enp_toenp, pBCB) == 1 )
  890.             pDev->enp_iow.hst2enp_interrupt = ENPVAL;
  891.         /* Bump the statistic counter. */
  892.         pDrvCtrl->idr.ac_if.if_opackets++;
  893.         }
  894.     return;
  895.     }
  896. #endif
  897. /*******************************************************************************
  898. *
  899. * enpIoctl - ioctl for interface
  900. *
  901. * RETURNS: 0, or EINVAL
  902. */
  903. LOCAL int enpIoctl
  904.     (
  905.     IDR *pIDR,
  906.     int cmd,
  907.     caddr_t data
  908.     )
  909.     {
  910.     int error;
  911.     ENPDEVICE* pEnpDev;
  912.     DRV_CTRL* pDrvCtrl;
  913.     
  914.     pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit];
  915. #ifdef ENP_DEBUG
  916.     printf ( "enp: ioctl: pIDR=%x, cmd=%x, data=%xn", pIDR, cmd, data );
  917. #endif
  918.     error = 0;
  919.     switch (cmd)
  920.         {
  921.         case SIOCSIFADDR:
  922.             ((struct arpcom *)pIDR)->ac_ipaddr = IA_SIN (data)->sin_addr;
  923.             arpwhohas (pIDR, &IA_SIN (data)->sin_addr);
  924.             break;
  925.         case SIOCSIFFLAGS:
  926.             /* set promiscuous bit according to flags */
  927.             if (pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC) 
  928.                 {
  929.                 pEnpDev = pDrvCtrl->enpAddr;
  930.                 pEnpDev->enp_mode |= 0x1000;
  931.                 }
  932.             else
  933.                 {
  934.                 pEnpDev = pDrvCtrl->enpAddr;
  935.                 pEnpDev->enp_mode &= ~0x1000;
  936.                 }   
  937.             break;
  938.             /* Just set the thing into promiscuous mode. */
  939.         case SIOCADDMULTI:
  940.         case SIOCDELMULTI:
  941.             pEnpDev = pDrvCtrl->enpAddr;
  942.             pEnpDev->enp_mode |= 0x1000;
  943.             break;
  944.         default:
  945.             error = EINVAL;
  946.         }
  947.     return (error);
  948.     }
  949. /*******************************************************************************
  950. *
  951. * enpgetaddr - get hardwired ethernet address.
  952. *
  953. * Read the ethernet address off the board, one byte at a time.
  954. *
  955. * INTERNAL
  956. * CMC changed the LINK-10 ROMs and did not make the change
  957. * to ENPDEVICE backward compatable with v3.x.
  958. * To determine the proper ENPDEVICE structure (or rather LINK-10
  959. * revision) the Ethernet base address should be 0.
  960. * If it is we assume that the LINK-10 PROMs are v4.0.
  961. * This assumtion is based on the hope that the new LINK-10 ROMs will
  962. * leave the RING32 buffers that were inserted in the ENPDEVICE structure
  963. * set to 0 after a reset. This seems to work. (see if_enp.h for differences
  964. * in the ENPDEVICE structure).
  965. * The fields e_stat, and/or e_netaddr (AKA enp_stat and enp_addr) should
  966. * are dependent on the ROM version.
  967. */
  968. LOCAL void enpgetaddr
  969.     (
  970.     int unit
  971.     )
  972.     {
  973.     DRV_CTRL *pDrvCtrl          = & drvCtrl[unit];
  974.     ENPDEVICE_OLD *oldaddr = (ENPDEVICE_OLD *) pDrvCtrl->enpAddr;
  975.     ENPDEVICE     *addr    = pDrvCtrl->enpAddr;
  976.     USHORT        *pChk    = (USHORT *) &oldaddr->enp_addr.e_baseaddr;
  977.     /* check version of LINK-10 PROMs */
  978.     enpNewROM = (*pChk == 0x00);        /* TRUE = new ROMs */
  979.     if (enpNewROM)
  980.         {
  981.         bcopyBytes  (
  982.                     (caddr_t) & addr->enp_addr.e_baseaddr,
  983.                     (caddr_t) pDrvCtrl->idr.ac_enaddr,
  984.                     sizeof (pDrvCtrl->idr.ac_enaddr)
  985.                     );
  986.         }
  987.     else
  988.         {
  989.         /* CMC LINK-10 v4.0 PROMs */
  990.         bcopyBytes  (
  991.                     (caddr_t) & oldaddr->enp_addr.e_baseaddr,
  992.                     (caddr_t) pDrvCtrl->idr.ac_enaddr,
  993.                     sizeof (pDrvCtrl->idr.ac_enaddr)
  994.                     );
  995.         }
  996.     }
  997. /*******************************************************************************
  998. *
  999. * enpringempty - check for ring empty.
  1000. *
  1001. * RETURNS: TRUE or FALSE
  1002. */
  1003. LOCAL BOOL enpringempty
  1004.     (
  1005.     RING *rp
  1006.     )
  1007.     {
  1008.     return (rp->r_rdidx == rp->r_wrtidx);
  1009.     }
  1010. /*******************************************************************************
  1011. *
  1012. * enpringput - write to next ring location
  1013. *
  1014. * RETURNS: Number of entries left in ring or 0 if full.
  1015. */
  1016. LOCAL int enpringput
  1017.     (
  1018.     RING *rp,
  1019.     BCB *pBCB
  1020.     )
  1021.     {
  1022.     int idx;
  1023.     int wrtidx = ntohs (rp->r_wrtidx);
  1024.     int rdidx  = ntohs (rp->r_rdidx);
  1025.     int size   = ntohs (rp->r_size);
  1026.     idx = (wrtidx + 1) & (size-1);
  1027.     if (idx != rdidx)
  1028.         {
  1029.         pBCB = (BCB *) htonl ((u_long) pBCB);
  1030.         WRITELONG (&rp->r_slot[ wrtidx ], pBCB);
  1031.         rp->r_wrtidx = htons (idx);
  1032.         CACHE_PIPE_FLUSH ();
  1033.         if ((idx -= rdidx) < 0)
  1034.             idx += size;
  1035.         return (idx);                   /* num ring entries */
  1036.         }
  1037.     return (0);
  1038.     }
  1039. /*******************************************************************************
  1040. *
  1041. * enpringget - get the next item from a ring
  1042. *
  1043. * RETURNS: Pointer to next item or 0 if none.
  1044. */
  1045. LOCAL int enpringget
  1046.     (
  1047.     RING *rp
  1048.     )
  1049.     {
  1050.     int buf = 0;
  1051.     int wrtidx = ntohs (rp->r_wrtidx);
  1052.     int rdidx  = ntohs (rp->r_rdidx);
  1053.     int size   = ntohs (rp->r_size);
  1054.     if  (rdidx != wrtidx)
  1055.         {
  1056.         READLONG (&rp->r_slot [rdidx], &buf);
  1057.         buf = ntohl (buf);
  1058.         rp->r_rdidx = htons ((++rdidx) & (size-1));
  1059.         CACHE_PIPE_FLUSH ();
  1060.         }
  1061.     return (buf);
  1062.     }
  1063. /*******************************************************************************
  1064. *
  1065. * enpShow - show ENP-10 statistics
  1066. *
  1067. * INTERNAL
  1068. * This works only on some versions of the ENP 10/L onboard software
  1069. * e.g. LINK-10 4.0 is fine, 3.1 is not.
  1070. *
  1071. * RETURNS: 0
  1072. *
  1073. * NOMANUAL
  1074. */
  1075. STATUS enpShow
  1076.     (
  1077.     int unit,   /* interface unit */
  1078.     BOOL zap    /* zero totals */
  1079.     )
  1080.     {
  1081.     int             ix;
  1082.     int             status;
  1083.     DRV_CTRL        *pDrvCtrl;
  1084.     ENPDEVICE       *addr;
  1085.     ENPDEVICE_OLD   *oldaddr;
  1086.     static char *e_message [] =
  1087.         {
  1088.         "successful transmissions",
  1089.         "multiple retries on xmit",
  1090.         "single retries",
  1091.         "too many retries",
  1092.         "transmission delayed",
  1093.         "xmit data chaining failed",
  1094.         "transmit data fetch failed",
  1095.         "collision after xmit",
  1096.         "lost carrier",
  1097.         "xmit length > 1518",
  1098.         "transceiver mismatch",
  1099.         "xmit memory error",
  1100.         "good receptions",
  1101.         "no recv buff available",
  1102.         "checksum failed",
  1103.         "crc error AND data length != 0 mod 8",
  1104.         "rcv data chain failure",
  1105.         "receive data store failed",
  1106.         "rcv memory error"
  1107.         };
  1108.     /* Safety check unit number */
  1109.     if (unit < 0 || unit >= MAX_UNITS)
  1110.         {
  1111.         errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);
  1112.         return (ERROR);
  1113.         }
  1114.     pDrvCtrl = & drvCtrl [unit];
  1115.     addr     = pDrvCtrl->enpAddr;
  1116.     oldaddr  = (ENPDEVICE_OLD *) pDrvCtrl->enpAddr;
  1117.     printf ("enp%d (v%s):n", unit, (enpNewROM ? "4.x" : "3.x"));
  1118.     for (ix = 0; ix < NELEMENTS(e_message); ix++)
  1119.         {
  1120.         if (enpNewROM)
  1121.             {
  1122.             READLONG ((&addr->enp_stat.e_stat [ix]), &status);
  1123.             }
  1124.         else
  1125.             {
  1126.             READLONG ((&oldaddr->enp_stat.e_stat [ix]), &status);
  1127.             }
  1128.         status = ntohl (status);
  1129.         printf ("    %-30.30s  %4dn", e_message [ix],
  1130.                 status - pDrvCtrl->enpStat.e_stat [ix]);
  1131.         if (zap)
  1132.             pDrvCtrl->enpStat.e_stat [ix] = status;
  1133.         }
  1134.     return (OK);
  1135.     }
  1136. #if     FALSE
  1137. /*******************************************************************************
  1138. *
  1139. * enpDumpRing - dump particular ring
  1140. *
  1141. * RETURNS: N/A
  1142. */
  1143. LOCAL void enpDumpRing (rn, rp)
  1144.     char *rn;           /* ring name */
  1145.     RING32 *rp;         /* ring pointer */
  1146.     {
  1147.     int ix;
  1148.     int temp;
  1149.     printf ("    %s: rdidx = 0x%04.4x, wridx = 0x%04.4x, size = 0x%04.4xn",
  1150.         rn, ntohs (rp->r_rdidx), ntohs (rp->r_wrtidx), ntohs (rp->r_size));
  1151.     for (ix = 0; ix < 32;)
  1152.         {
  1153.         if ((ix % 6) == 0)
  1154.             printf ("      ");
  1155.         READLONG (&rp->r_slot[ix], &temp);
  1156.         printf ("%02.2d:%08.8x ", ix , ntohl (temp));
  1157.         if ((++ix % 6) == 0)
  1158.             printf ("n");
  1159.         }
  1160.     printf ("n");
  1161.     }
  1162. /*******************************************************************************
  1163. *
  1164. * enpDump - dump ring
  1165. *
  1166. * RETURNS: N/A
  1167. *
  1168. * NOMANUAL
  1169. */
  1170. void enpDump (unit, ring)
  1171.     int unit;           /* interface unit */
  1172.     BOOL ring;          /* true if dump ring structure */
  1173.     {
  1174.     DRV_CTRL *pDrvCtrl          = & drvCtrl[unit];
  1175.     ENPDEVICE *addr        = pDrvCtrl->enpAddr;
  1176.     ENPDEVICE_OLD *oldaddr = (ENPDEVICE_OLD *) pDrvCtrl->enpAddr;
  1177.     int temp;
  1178.     if (enpNewROM)
  1179.         {
  1180.         temp = ntohs (addr->enp_state);
  1181.         printf ("enp%d: is %sn", unit, temp & S_ENPRUN ? "running" : "down!");
  1182.         if ((temp & S_ENPRUN) == 0x0)
  1183.             return;
  1184.         printf ("    state = 0x%04.4x, mode  = 0x%04.4xn",
  1185.             ntohs (addr->enp_state), ntohs (addr->enp_mode) );
  1186.         READLONG (&addr->enp_base, &temp);
  1187.         printf ("    base  = 0x%08.8xn", ntohl (temp));
  1188.         printf ("    run   = 0x%04.4x, ivec  = 0x%04.4xnn",
  1189.             ntohs (addr->enp_enprun), ntohs (addr->enp_intvector));
  1190.         if (ring)
  1191.             {
  1192.             enpDumpRing ("toenp",    &addr->enp_toenp);
  1193.             enpDumpRing ("hostfree", &addr->enp_hostfree);
  1194.             enpDumpRing ("tohost",   &addr->enp_tohost);
  1195.             enpDumpRing ("enpfree",  &addr->enp_enpfree);
  1196.          /* enpDumpRing ("rcvdma",   &addr->enp_rcvdma); */
  1197.          /* enpDumpRing ("rcv_d",    &addr->enp_rvc_d); */
  1198.             }
  1199.         }
  1200.     else
  1201.         {
  1202.         temp = ntohs (oldaddr->enp_state);
  1203.         printf ("enp%d: is %sn", unit, temp & S_ENPRUN ? "running" : "down!");
  1204.         if ((temp & S_ENPRUN) == 0x0)
  1205.             return;
  1206.         printf ("    state = 0x%04.4x, mode  = 0x%04.4xn",
  1207.                 ntohs (oldaddr->enp_state), ntohs (oldaddr->enp_mode) );
  1208.         READLONG (&oldaddr->enp_base, &temp);
  1209.         printf ("    base  = 0x%08.8xn", ntohl (temp));
  1210.         printf ("    run   = 0x%04.4x, ivec  = 0x%04.4xnn",
  1211.                 ntohs (oldaddr->enp_enprun), ntohs (oldaddr->enp_intvector));
  1212.         if (ring)
  1213.             {
  1214.             enpDumpRing ("toenp",    &oldaddr->enp_toenp);
  1215.             enpDumpRing ("hostfree", &oldaddr->enp_hostfree);
  1216.             enpDumpRing ("tohost",   &oldaddr->enp_tohost);
  1217.             enpDumpRing ("enpfree",  &oldaddr->enp_enpfree);
  1218.             }
  1219.         }
  1220.     }
  1221. #endif  /* FALSE */
  1222. #ifdef BSD43_DRIVER
  1223. #include "sys/socket.h"
  1224. /*******************************************************************************
  1225. *
  1226. * convertDestAddr - converts socket addr into enet addr and packet type
  1227. *
  1228. */
  1229. static BOOL convertDestAddr
  1230.     (
  1231.     IDR *pIDR,                          /* ptr to i/f data record */
  1232.     SOCK *pDestSktAddr,                 /* ptr to a generic sock addr */
  1233.     char *pDestEnetAddr,                /* where to write enet addr */
  1234.     u_short *pPacketType,               /* where to write packet type */
  1235.     MBUF *pMbuf                         /* ptr to mbuf data */
  1236.     )
  1237.     {
  1238.     extern BOOL arpresolve();           /* we call this */
  1239.     /***** Internet family *****/
  1240.     {
  1241.     struct in_addr destIPAddr;              /* not used */
  1242.     int trailers;                           /* not supported */
  1243.      if (pDestSktAddr->sa_family == AF_INET)
  1244.         {
  1245.         *pPacketType = htons(ETHERTYPE_IP);            /* stuff packet type */
  1246.         destIPAddr = ((struct sockaddr_in *) pDestSktAddr)->sin_addr;
  1247.         if (!arpresolve (pIDR, pMbuf, &destIPAddr, pDestEnetAddr, &trailers))
  1248.             return (FALSE);     /* if not yet resolved */
  1249.         return (TRUE);
  1250.         }
  1251.     }
  1252.     /***** Generic family *****/
  1253.     {
  1254.     ENET_HDR *pEnetHdr;
  1255.     if (pDestSktAddr->sa_family == AF_UNSPEC)
  1256.         {
  1257.         pEnetHdr = (ENET_HDR *) pDestSktAddr->sa_data;      /* ptr to hdr */
  1258.         bcopy (pEnetHdr->dst, pDestEnetAddr, 6);            /* copy dst addr */
  1259.         *pPacketType = htons(pEnetHdr->type);                      /* copy type */
  1260.         return (TRUE);
  1261.         }
  1262.     }
  1263.     /* Unsupported family */
  1264.     return (FALSE);
  1265.     } /* End of convertDestAddr() */
  1266. #endif
  1267. /* END OF FILE */