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

VxWorks

开发平台:

C/C++

  1. /* nicEvbEnd.c - National Semiconductor ST-NIC Chip network interface driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01j,16may02,wap  Release dmaSem before passing packets up the stack (SPR
  8.                  #77005)
  9. 01i,02aug00,stv  removed netMblkClChainFree() in Pollsend routine (SPR# 32885).
  10. 01h,11jun00,ham  removed reference to etherLib.
  11. 01g,01dec99,stv  freed mBlk chain before returning ERROR (SPR #28492).
  12. 01f,10feb98,sut  added poll mode support
  13. 01e,09feb98,sut  added multicast support
  14. 01d,08feb98,sut  got working
  15. 01c,25jan98,sut  working with initMem
  16. 01b,21jan98,sut  investcating descritor
  17. 01a,20jan99,sut  from netif/if_nicEvb.c
  18. */
  19. /*
  20. This module implements the National Semiconductor 83902A ST-NIC Ethernet
  21. network interface driver.
  22. This driver is non-generic and is for use on the IBM EVB403 board.  
  23. The driver must be given several target-specific parameters.  These
  24. parameters, and the mechanisms used to communicate them to the driver, are
  25. detailed below.
  26. BOARD LAYOUT
  27. This device is on-board.  No jumpering diagram is necessary.
  28. EXTERNAL INTERFACE
  29. The only external interface is the nicEvbEndLoad() routine, which expects
  30. the <initString> parameter as input.  This parameter passes in a 
  31. colon-delimited string of the format:
  32. <unit>:<nic_addr>:<int_vector>:<int_level>
  33. The nicEvbEndLoad() function uses strtok() to parse the string.
  34. TARGET-SPECIFIC PARAMETERS
  35. .IP <unit>
  36. A convenient holdover from the former model.  This parameter is used only
  37. in the string name for the driver.
  38. .IP <nic_addr>
  39. Base address for NIC chip
  40. .IP <int_vector>
  41. Configures the NIC device to generate hardware interrupts for various events
  42. within the device. Thus, it contains an interrupt handler routine.  The driver
  43. calls sysIntConnect() to connect its interrupt handler to the interrupt vector.
  44. .IP <int_level>
  45. This parameter is passed to an external support routine, sysLanIntEnable(),
  46. which is described below in "External Support Requirements." This routine 
  47. is called during as part of driver's initialization.  It handles any 
  48. board-specific operations required to allow the servicing of a NIC 
  49. interrupt on targets that use additional interrupt controller devices to 
  50. help organize and service the various interrupt sources.  This parameter 
  51. makes it possible for this driver to avoid all board-specific knowledge of 
  52. such devices.  
  53. .iP "device restart/reset delay"
  54. The global variable nicRestartDelay (UINT32), defined in this file, 
  55. should be initialized in the BSP sysHwInit() routine. nicRestartDelay is 
  56. used only with PowerPC platform and is equal to the number of time base 
  57. increments which makes for 1.6 msec. This corresponds to the delay necessary 
  58. to respect when restarting or resetting the device.
  59. .LP
  60. EXTERNAL SUPPORT REQUIREMENTS
  61. This driver requires several external support functions, defined as macros:
  62. .CS
  63.     SYS_INT_CONNECT(pDrvCtrl, routine, arg)
  64.     SYS_INT_DISCONNECT (pDrvCtrl, routine, arg)
  65.     SYS_INT_ENABLE(pDrvCtrl)
  66. .CE
  67. There are default values in the source code for these macros.  They presume
  68. memory-mapped accesses to the device registers and the normal intConnect(),
  69. and intEnable() BSP functions.  The first argument to each is the device
  70. controller structure. Thus, each has access back to all the device-specific
  71. information.  Having the pointer in the macro facilitates the addition 
  72. of new features to this driver.
  73. SYSTEM RESOURCE USAGE
  74. When implemented, this driver requires the following system resources:
  75.     - one mutual exclusion semaphore
  76.     - one interrupt vector
  77. SEE ALSO: muxLib
  78. */
  79. /* configurations */
  80. #define NIC_INSTRUMENT /* instrument the driver */
  81. #undef DRV_DEBUG /* log debug messages */
  82. #if (CPU_FAMILY == PPC)
  83. #define NIC_USE_PPCTIMEBASE
  84. #else   /* CPU_FAMILY == PPC */
  85. #undef NIC_USE_PPCTIMEBASE
  86. #endif /* CPU_FAMILY == PPC */
  87. /* 
  88.  * NIC_FASTER, if defined, improved the driver throuput, however the driver
  89.  * seems to be less reliable. Left undefined for now.
  90.  */
  91. #undef NIC_FASTER /* improve throuput but less stable */
  92. /* includes */
  93. #include "vxWorks.h"
  94. #include "wdLib.h"
  95. #include "iv.h"
  96. #include "vme.h"
  97. #include "net/mbuf.h"
  98. #include "net/unixLib.h"
  99. #include "net/protosw.h"
  100. #include "sys/socket.h"
  101. #include "sys/ioctl.h"
  102. #include "errno.h"
  103. #include "memLib.h"
  104. #include "intLib.h"
  105. #include "net/route.h"
  106. #include "iosLib.h"
  107. #include "errnoLib.h"
  108. #ifdef DRV_DEBUG
  109. #include "logLib.h"
  110. #endif
  111. #include "cacheLib.h"
  112. #include "netLib.h"
  113. #include "stdio.h"
  114. #include "stdlib.h"
  115. #include "sysLib.h"
  116. #include "net/systm.h"
  117. #include "sys/times.h"
  118. #include "net/if_subr.h"
  119. #include "netinet/if_ether.h"
  120. #include "drv/end/nicEvbEnd.h"
  121. #undef ETHER_MAP_IP_MULTICAST
  122. #include "etherMultiLib.h"
  123. #include "end.h"
  124. #include "endLib.h"
  125. #include "lstLib.h"
  126. #include "semLib.h"
  127. /* defines */
  128. #define NIC_EVB_DEV_NAME "nicEvb"
  129. #define NIC_EVB_DEV_NAME_LEN 7
  130. #define NIC_EVB_EADR_LEN 6
  131. #define NIC_EVB_SPEED 10000000 /* HELP */
  132. #define NIC_TRANS_TIMEOUT 400 /* times to poll for end of Tx */
  133. #define NIC_CRC_POLY 0x04c11db7
  134. /* debug macros */
  135. #ifdef DRV_DEBUG
  136. #define DRV_DEBUG_OFF 0x0000
  137. #define DRV_DEBUG_RX 0x0001
  138. #define DRV_DEBUG_TX 0x0002
  139. #define DRV_DEBUG_INT 0x0004
  140. #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
  141. #define DRV_DEBUG_POLL_RX 0x0008
  142. #define DRV_DEBUG_POLL_TX 0x0010
  143. #define DRV_DEBUG_LOAD 0x0020
  144. #define DRV_DEBUG_IOCTL 0x0040
  145. #define DRV_DEBUG_POLL_REDIR 0x10000
  146. #define DRV_DEBUG_LOG_NVRAM 0x20000
  147. #define DRV_DEBUG_MB 0x40000
  148. #ifdef LOCAL
  149. #undef LOCAL
  150. #define LOCAL
  151. NET_POOL nicNetPool;
  152. #endif
  153. /* int nicEvbDebug = DRV_DEBUG_LOAD | DRV_DEBUG_TX | DRV_DEBUG_RX; */
  154. int nicEvbDebug = DRV_DEBUG_POLL;
  155. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  156. if (nicEvbDebug & FLG)
  157.             logMsg(X0, X1, X2, X3, X4, X5, X6);
  158. #define DRV_PRINT(FLG, X0, X1, X2, X3, X4, X5, X6)
  159. if (nicEvbDebug & FLG)
  160.             printf(X0, X1, X2, X3, X4, X5, X6);
  161. #else /*DRV_DEBUG*/
  162. #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
  163. #define DRV_PRINT(DBG_SW,X)
  164. #endif /*DRV_DEBUG*/
  165. /*
  166.  * Default macro definitions for BSP interface.
  167.  * These macros can be redefined in a wrapper file, to generate
  168.  * a new module with an optimized interface.
  169.  */
  170. #ifndef SYS_INT_CONNECT
  171. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) 
  172.     {
  173.     IMPORT STATUS sysIntConnect(); 
  174.     *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), 
  175.      rtn, (int)arg); 
  176.     }
  177. #endif /*SYS_INT_CONNECT*/
  178. #ifndef SYS_INT_DISCONNECT
  179. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) 
  180.     { 
  181.     *pResult = OK; 
  182.     }
  183. #endif /*SYS_INT_DISCONNECT*/
  184. #ifndef SYS_INT_ENABLE
  185. #define SYS_INT_ENABLE(ivec) 
  186.     { 
  187.     IMPORT void sysLanIntEnable();      
  188.     sysLanIntEnable (ivec);
  189.     }
  190. #endif /*SYS_INT_ENABLE*/
  191. #ifndef SYS_ENET_ADDR_GET
  192. #define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress) 
  193.     { 
  194.     IMPORT sysEnetAddrGet (int, char*);
  195.     nicEvbEnetAddrGet (pDrvCtrl, pAddress); 
  196.     }
  197. #endif /* SYS_ENET_ADDR_GET */
  198. #define DRV_FLAGS_SET(setBits)                                          
  199. (pDrvCtrl->flags |= (setBits))
  200. #define DRV_FLAGS_ISSET(setBits)                                        
  201. (pDrvCtrl->flags & (setBits))
  202. #define DRV_FLAGS_CLR(clrBits)                                          
  203. (pDrvCtrl->flags &= ~(clrBits))
  204. #define DRV_FLAGS_GET()                                                 
  205.         (pDrvCtrl->flags)
  206. #define NIC_IS_IN_POLL_MODE()
  207. ((DRV_FLAGS_GET() & NIC_FLAG_POLL) == NIC_FLAG_POLL)
  208. /* A shortcut for getting the hardware address from the MIB II stuff. */
  209. #define END_HADDR(pEnd)
  210. ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  211. #define END_HADDR_LEN(pEnd) 
  212. ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  213. #define END_FLAGS_ISSET(pEnd, setBits) 
  214.             ((pEnd)->flags & (setBits))
  215. /* typedefs */
  216. typedef struct rx_hdr
  217.     {
  218.     UINT8 status; /* status of packet */
  219.     UINT8 nextRxPage; /* page next pkt starts at */
  220.     UINT8 cntL; /* low byte of frame length */
  221.     UINT8 cntH; /* high byte of frame length */
  222.     } NIC_RX_HDR;
  223. #define NIC_RX_HDR_SZ sizeof(NIC_RX_HDR)
  224. typedef struct rx_frame
  225.     {
  226.     UINT16 pad1;
  227.     NIC_RX_HDR rxHdr; /* receive status header */
  228.     struct ether_header enetHdr; /* ethernet header */
  229.     UINT8 data [ETHERMTU];/* frame data */
  230.     UINT32 fcs; /* frame check sequence */
  231.     UINT8 refCnt; /* loaner reference count */
  232.     UINT8 pad2;
  233.     } NIC_RX_FRAME;
  234. /*
  235.  * Macros for read and write descriptors.
  236.  *
  237.  */
  238. #define NIC_FRAME_DATA_ADDR_GET(pFrame) 
  239. pFrame = ((char *)(pFrame) + sizeof(UINT16) + sizeof(NIC_RX_HDR_SZ));
  240. #define NIC_RBR_LEN ((PSTOP - PSTART) + 1)
  241. #define NIC_BUF_SZ sizeof(NIC_RX_FRAME)
  242. #define NIC_ETH_CRC_LEN 4
  243. typedef char* NIC_CLUSTER;
  244. typedef struct nic_end_device /* driver control structure */
  245.     {
  246.     END_OBJ end; /* The class we inherit from. */
  247.     int unit; /* unit number */
  248.     int rmdIndex; /* current RMD index */
  249.     int rringSize; /* RMD ring size */
  250.     int  rringLen; /* RMD ring length (bytes) */
  251.     UCHAR enetAddr[NIC_EVB_EADR_LEN]; /* ethernet address */
  252.     BOOL txBlocked;  /* transmit flow control */
  253.     BOOL         txCleaning;    
  254.     NIC_DEVICE* pNic; /* address of NIC chip */
  255.     int          ivec; /* interrupt vector */
  256.     int ilevel; /* interrupt level */
  257.     SEM_ID       dmaSem; /* exclusive use of remote DMA */
  258.     UINT8 nextPkt; /* NIC buf page for next pkt */
  259.     NIC_CLUSTER pRxCluster; /* Rx frame memory */
  260.     CL_POOL_ID pClPoolId;
  261.     NIC_DRV_FLAG flags; /* device specific flags */
  262.     } NICEVB_END_DEVICE;
  263. /* globals */
  264. UINT32  nicEvbRestartDelay = 30000;/* number of time base ticks to wait for */
  265. /* when resetting the chip */
  266. UINT32 nicIntNb = 0; /* number of receive interrupt */
  267. UINT32 nicTxTimeout = 0; /* number of transmit time-out */
  268. #ifdef NIC_INSTRUMENT
  269. UINT32 nicRestartNb = 0; /* number of restart due to ring overflow */
  270. UINT32 nicLen = 0; /* lenght of the current received packet */
  271. UINT32 nicHdrStat = 0; /* status byte of the current received packet */
  272. UINT32 nicNextPage = 0; /* page pointer to the next received packet */
  273. UINT32 nicCurrentPage = 0; /* start page of the current packet */
  274. UINT32 nicTxNb = 0; /* number of transmitted packets */
  275. UINT32 nicInitNb = 0; /* number of time device is re-initialized */
  276. #endif
  277. /* locals */
  278. /* forward declarations */
  279. LOCAL int nicEvbMblkDataLenGet (M_BLK* pMblk);
  280. LOCAL void nicEvbEnetAddrGet (NICEVB_END_DEVICE* pDrvCtrl, char* pAddress);
  281. LOCAL void nicEvbMARSet (NICEVB_END_DEVICE* pDrvCtrl, UINT8 index, BOOL bSet);
  282. LOCAL void nicEvbAddrFilterSet (NICEVB_END_DEVICE *pDrvCtrl, char* pAddr, BOOL bSet);
  283. LOCAL int nicEvbHashIndex (char* eAddr);
  284. LOCAL void nicEvbReset (NICEVB_END_DEVICE* pDrvCtrl);
  285. LOCAL void nicEvbInt (NICEVB_END_DEVICE* pDrvCtrl);
  286. LOCAL void nicEvbRestart (NICEVB_END_DEVICE *pDrvCtrl, UINT8 cr);
  287. LOCAL void nicEvbHandleInt (NICEVB_END_DEVICE *pDrvCtrl);
  288. LOCAL BOOL nicEvbRead (NICEVB_END_DEVICE *pDrvCtrl);
  289. LOCAL NIC_CLUSTER nicEvbReadFrame (NICEVB_END_DEVICE* pDrvCtrl);
  290. LOCAL STATUS nicEvbToStack (NICEVB_END_DEVICE* pDrvCtrl, NIC_CLUSTER pCluster);
  291. LOCAL void nicEvbConfig (NICEVB_END_DEVICE* pDrvCtrl);
  292. LOCAL STATUS nicEvbPktBufRead (NICEVB_END_DEVICE *pDrvCtrl, UINT32
  293.                                   nicBufAddr, UINT32 len, char *pData);
  294. LOCAL void nicEvbWriteCr (NIC_DEVICE *pNic, UINT8 value);
  295. LOCAL void nicEvbWriteReg (NIC_DEVICE *pNic, volatile UINT8 *pReg,
  296.                                 UINT8 value, UINT8 page);
  297. LOCAL UINT8 nicEvbReadReg (NIC_DEVICE *pNic, volatile UINT8 *pReg, char page);
  298. LOCAL STATUS nicEvbTransmit (NICEVB_END_DEVICE *pDrvCtrl,
  299.                                 M_BLK* pMblk, BOOL waitFlag);
  300. LOCAL void nicEvbWritePort (UINT8 value);
  301. LOCAL STATUS nicEvbReceive (NICEVB_END_DEVICE *pDrvCtrl,
  302.                                UINT32 nicBufAddr, char *pData, int len);
  303. LOCAL UINT8 nicEvbReadPort (void);
  304. LOCAL void nicLoanFree (NICEVB_END_DEVICE *pDrvCtrl, NIC_RX_FRAME *pRx);
  305. LOCAL BOOL nicEvbPagePtrUpdate (NICEVB_END_DEVICE * pDrvCtrl,
  306.                                      NIC_CLUSTER pRxCluster);
  307. LOCAL void nicEvbResetDelay (void);
  308. LOCAL STATUS nicEvbInitParse (NICEVB_END_DEVICE* pDrvCtrl, char * initString);
  309. LOCAL STATUS nicEvbInitMem (NICEVB_END_DEVICE* pDrvCtrl);
  310. /* END Specific interfaces. */
  311. END_OBJ * nicEvbEndLoad (char *initString);
  312. LOCAL STATUS nicEvbUnload (NICEVB_END_DEVICE* pDrvCtrl);
  313. LOCAL STATUS nicEvbStart (NICEVB_END_DEVICE* pDrvCtrl);
  314. LOCAL STATUS nicEvbStop (NICEVB_END_DEVICE* pDrvCtrl);
  315. LOCAL int nicEvbIoctl (NICEVB_END_DEVICE* pDrvCtrl, int cmd, caddr_t data);
  316. LOCAL STATUS nicEvbSend (NICEVB_END_DEVICE* pDrvCtrl, M_BLK *pMblk);
  317. LOCAL STATUS nicEvbMCastAddrAdd (NICEVB_END_DEVICE *pDrvCtrl, char* pAddress);
  318. LOCAL STATUS nicEvbMCastAddrDel (NICEVB_END_DEVICE *pDrvCtrl, char* pAddress);
  319. LOCAL STATUS nicEvbMCastAddrGet (NICEVB_END_DEVICE *pDrvCtrl, 
  320.                                       MULTI_TABLE *pTable);
  321. LOCAL STATUS nicEvbPollSend (NICEVB_END_DEVICE *pDrvCtrl, M_BLK *pMblk);
  322. LOCAL STATUS nicEvbPollReceive (NICEVB_END_DEVICE *pDrvCtrl, M_BLK *pMblk);
  323. LOCAL STATUS nicEvbPollStart (NICEVB_END_DEVICE *pDrvCtrl);
  324. LOCAL STATUS nicEvbPollStop (NICEVB_END_DEVICE *pDrvCtrl);
  325. /*
  326.  * Declare our function table.  This is static across all driver
  327.  * instances.
  328.  */
  329. LOCAL NET_FUNCS nicEvbFuncTable =
  330.     {
  331.     (FUNCPTR)nicEvbStart, /* Function to start the device. */
  332.     (FUNCPTR)nicEvbStop, /* Function to stop the device. */
  333.     (FUNCPTR)nicEvbUnload, /* Unloading function for the driver. */
  334.     (FUNCPTR)nicEvbIoctl, /* Ioctl function for the driver. */
  335.     (FUNCPTR)nicEvbSend, /* Send function for the driver. */
  336.     (FUNCPTR)nicEvbMCastAddrAdd, /* Multicast address add */
  337.     (FUNCPTR)nicEvbMCastAddrDel, /* Multicast address delete */
  338.     (FUNCPTR)nicEvbMCastAddrGet, /* Multicast table retrieve */
  339.     (FUNCPTR)nicEvbPollSend,  /* Polling send function for the driver. */
  340.     (FUNCPTR)nicEvbPollReceive, /* Polling receive function for the driver. */
  341.     endEtherAddressForm,        /* Put address info into a packet.  */
  342.     endEtherPacketDataGet,      /* Get a pointer to packet data. */
  343.     endEtherPacketAddrGet       /* Get packet addresses. */
  344.     };
  345. /******************************************************************************
  346. *
  347. * nicEndLoad - initialize the driver and device
  348. *
  349. * This routine initializes the driver and the device to the operational state.
  350. * All of the device-specific parameters are passed in <initString>, which
  351. * expects a string of the following format:
  352. *
  353. * <unit>:<base_addr>:<int_vector>:<int_level>
  354. *
  355. * This routine can be called in two modes. If it is called with an empty but
  356. * allocated string, it places the name of this device (that is, "ln") into 
  357. * the <initString> and returns 0.
  358. *
  359. * If the string is allocated and not empty, the routine attempts to load
  360. * the driver using the values specified in the string.
  361. *
  362. * RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
  363. * device if the <initString> was NULL.
  364. */
  365. END_OBJ* nicEvbEndLoad
  366.     (
  367.     char* initString /* string to be parse by the driver */
  368.     )
  369.     {
  370.     NICEVB_END_DEVICE *pDrvCtrl;
  371.     DRV_LOG (DRV_DEBUG_LOAD, "Loading nic...n", 1, 2, 3, 4, 5, 6);
  372.     if (initString == NULL)
  373.         return (NULL);
  374.     
  375.     if (initString[0] == NULL)
  376.         {
  377.         bcopy((char *)NIC_EVB_DEV_NAME, initString, NIC_EVB_DEV_NAME_LEN);
  378.         return (0);
  379.         }
  380.     
  381.     /* allocate the device structure */
  382.     pDrvCtrl = (NICEVB_END_DEVICE *)calloc (sizeof (NICEVB_END_DEVICE), 1);
  383.     if (pDrvCtrl == NULL)
  384. goto errorExit;
  385.     /* init device object */
  386.     pDrvCtrl->pRxCluster = NULL;
  387.     pDrvCtrl->flags = 0x00;    
  388.     
  389.     /* parse the init string, filling in the device structure */
  390.     if (nicEvbInitParse (pDrvCtrl, initString) == ERROR)
  391. goto errorExit;
  392.     
  393.     /* Have the BSP hand us our address. */
  394.     SYS_ENET_ADDR_GET(pDrvCtrl,(char*)&(pDrvCtrl->enetAddr));
  395.     /* initialize the END and MIB2 parts of the structure */
  396.     if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, NIC_EVB_DEV_NAME,
  397.     pDrvCtrl->unit, &nicEvbFuncTable,
  398.                       "ST-NIC Enhanced Network Driver") == ERROR
  399.      || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
  400.                       &pDrvCtrl->enetAddr[0], NIC_EVB_EADR_LEN, ETHERMTU,
  401.                       NIC_EVB_SPEED)
  402.     == ERROR)
  403. goto errorExit;
  404.     /* Perform memory allocation */
  405.     if (nicEvbInitMem (pDrvCtrl) == ERROR)
  406. goto errorExit;
  407.     /* set the flags to indicate readiness */
  408.     END_OBJ_READY (&pDrvCtrl->end,
  409.                    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
  410.     
  411.     DRV_LOG (DRV_DEBUG_LOAD, "Done loading nicEvb...n", 1, 2, 3, 4, 5, 6);
  412.     return (&pDrvCtrl->end);
  413.     errorExit:
  414.         {
  415.         nicEvbUnload (pDrvCtrl);
  416.         return NULL;
  417.         }
  418.     }
  419. /*******************************************************************************
  420. *
  421. * nicEvbInitParse - parse the initialization string
  422. *
  423. * Parse the input string.  Fill in values in the driver control structure.
  424. * The initialization string format is:
  425. * <unit>:<base_adrs>:<vecnum>:<intLvl>
  426. *
  427. * .IP <unit>
  428. * Device unit number, a small integer.
  429. * .IP <base_adrs>
  430. * Base address for NIC device
  431. * .IP <vecNum>
  432. * Interrupt vector number (used with sysIntConnect() ).
  433. * .IP <intLvl>
  434. * Interrupt level.
  435. *
  436. * RETURNS: OK, or ERROR if any arguments are invalid.
  437. */
  438. STATUS nicEvbInitParse
  439.     (
  440.     NICEVB_END_DEVICE * pDrvCtrl,
  441.     char * initString
  442.     )
  443.     {
  444.     char * tok;
  445.     char * pHolder = NULL;
  446.     long address;
  447.     
  448.     /* Parse the initString */
  449.     /* Unit number. */
  450.     tok = strtok_r (initString, ":", &pHolder);
  451.     if (tok == NULL)
  452. return ERROR;
  453.     pDrvCtrl->unit = atoi (tok);
  454.     /* NIC address. */
  455.     
  456.     tok = strtok_r (NULL, ":", &pHolder);
  457.     if (tok == NULL)
  458. return ERROR;
  459.     address = strtoul (tok, NULL, 16);
  460.     pDrvCtrl->pNic = (NIC_DEVICE* )address;
  461.     /* Interrupt vector. */
  462.     tok = strtok_r (NULL, ":", &pHolder);
  463.     if (tok == NULL)
  464. return ERROR;
  465.     pDrvCtrl->ivec = atoi (tok);
  466.     /* Interrupt level. */
  467.     tok = strtok_r (NULL, ":", &pHolder);
  468.     if (tok == NULL)
  469. return ERROR;
  470.     pDrvCtrl->ilevel = atoi (tok);
  471.     DRV_LOG (DRV_DEBUG_LOAD, "Processed all arugmentsn", 1, 2, 3, 4, 5, 6);
  472.     DRV_LOG (DRV_DEBUG_LOAD, "Address %p Level %u ivec %dn",
  473.                pDrvCtrl->pNic, pDrvCtrl->ilevel, pDrvCtrl->ivec, 4, 5, 6);    
  474.     return OK;
  475.     }
  476. /*******************************************************************************
  477. *
  478. * nicEvbInitMem - initialize memory for Lance chip
  479. *
  480. * Using data in the control structure, setup and initialize the memory
  481. * areas needed.  If the memory address is not already specified, then allocate
  482. * cache safe memory.
  483. *
  484. * RETURNS: OK or ERROR.
  485. */
  486. LOCAL STATUS nicEvbInitMem
  487.     (
  488.     NICEVB_END_DEVICE * pDrvCtrl /* device to be initialized */
  489.     )
  490.     {
  491.     M_CL_CONFIG mclBlkConfig;
  492.     CL_DESC clDesc; /* cluster description */
  493.     pDrvCtrl->rringSize = NIC_RBR_LEN; /* size of the whole ring */
  494.     pDrvCtrl->rringLen = pDrvCtrl->rringSize * NIC_BUF_SZ; /* rec ring len */    
  495.     pDrvCtrl->rmdIndex = 0; /* init recv buf index */
  496.     pDrvCtrl->nextPkt = CURR; /* reset to initial value */
  497.     /* for remote DMA access */
  498.     
  499.     pDrvCtrl->dmaSem = semMCreate (SEM_Q_PRIORITY);
  500.     
  501.     
  502.     /*
  503.      * Allocate receive buffers from our own private pool.
  504.      */
  505.     /* Initialize net buffer pool for tx/rx buffers */
  506.     bzero ((char *)&mclBlkConfig, sizeof(mclBlkConfig));
  507.     bzero ((char *)&clDesc, sizeof(clDesc));
  508.     
  509.     if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  510.         return (ERROR);
  511.     mclBlkConfig.mBlkNum  = pDrvCtrl->rringSize * 8;
  512.     clDesc.clNum   = pDrvCtrl->rringSize * 8;
  513.     mclBlkConfig.clBlkNum = clDesc.clNum;
  514.     mclBlkConfig.memSize = (mclBlkConfig.mBlkNum * (MSIZE + sizeof (long))) +
  515.                           (mclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));
  516.     if ((mclBlkConfig.memArea = (char *) memalign (sizeof(long),
  517.                                                    mclBlkConfig.memSize)) == NULL)
  518.         return (ERROR);
  519.     
  520.     clDesc.clSize  = NIC_BUF_SZ;
  521.     clDesc.memSize = ((clDesc.clNum * (clDesc.clSize + 4)) + 4);
  522.    clDesc.memArea = memalign (sizeof(long), clDesc.memSize);
  523.    pDrvCtrl->pRxCluster = (NIC_CLUSTER)clDesc.memArea;
  524.    
  525.    if (clDesc.memArea == NULL)
  526.         {
  527.         DRV_LOG (DRV_DEBUG_LOAD, "system memory unavailablen", 1, 2, 3, 4, 5, 6);
  528.         return (ERROR);
  529.         }
  530.     /* Initialize the net buffer pool with transmit buffers */    
  531.     if (netPoolInit(pDrvCtrl->end.pNetPool, &mclBlkConfig,
  532.                     &clDesc, 1, NULL) == ERROR)
  533.         
  534.         {
  535.         DRV_LOG (DRV_DEBUG_LOAD, "Could not init bufferingn",
  536.                  1, 2, 3, 4, 5, 6);
  537.         return (ERROR);
  538.         }
  539.     
  540. #ifdef DRV_DEBUG
  541.     nicNetPool = *pDrvCtrl->end.pNetPool;
  542. #endif
  543.     /* Store the cluster pool id as others need it later. */
  544.     pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool, NIC_BUF_SZ, FALSE);
  545.     
  546.     /* Setup the receive ring */
  547.     return OK;
  548.     }
  549. /*******************************************************************************
  550. *
  551. * nicEvbStart - start the device
  552. *
  553. * This function calls BSP functions to connect interrupts and start the
  554. * device running in interrupt mode.
  555. *
  556. * RETURNS: OK or ERROR
  557. *
  558. */
  559. LOCAL STATUS nicEvbStart
  560.     (
  561.     NICEVB_END_DEVICE *pDrvCtrl
  562.     )
  563.     {
  564.     STATUS result;
  565.     pDrvCtrl->txCleaning = FALSE;
  566.     pDrvCtrl->txBlocked = FALSE;
  567.     
  568.     SYS_INT_CONNECT (pDrvCtrl, nicEvbInt, (int)pDrvCtrl, &result);
  569.     
  570.     if (result == ERROR)
  571. return ERROR;
  572.     
  573.     DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
  574.     /* reset the device */
  575.     nicEvbReset (pDrvCtrl);
  576.     nicEvbConfig (pDrvCtrl); /* device config */
  577.     /* mark the interface -- up */
  578.     END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
  579.     
  580.     SYS_INT_ENABLE (pDrvCtrl->ivec);
  581.     
  582.     DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
  583.     return (OK);
  584.     }
  585. /*******************************************************************************
  586. *
  587. * nicEvbConfig - configure the NIC chip and program address
  588. *
  589. * This routine follows the algorythm in the ST-NIC manual for enabling
  590. * a NIC device on an active network.  Essentially, this routine initializes
  591. * the NIC device.
  592. *
  593. * RETURNS: N/A.
  594. */
  595. LOCAL void nicEvbConfig
  596.     (
  597.     NICEVB_END_DEVICE * pDrvCtrl /* device to be configured */    
  598.     )
  599.     {
  600.     NIC_DEVICE* pNic = pDrvCtrl->pNic;
  601.     UCHAR* pEnetAddr = pDrvCtrl->enetAddr;
  602.     
  603.     nicEvbWriteCr (pNic, RPAGE0 | STP | ABORT);
  604.     nicEvbResetDelay ();
  605.     nicEvbWriteReg (pNic, &pNic->Dcr, NOTLS | FIFO8, RPAGE0);
  606.     /* clear remote DMA byte count registers */
  607.     nicEvbWriteReg (pNic, &pNic->Rbcr0, 0, RPAGE0);             
  608.     nicEvbWriteReg (pNic, &pNic->Rbcr1, 0, RPAGE0);
  609.     /* accept broadcast and multicast, but not runt */
  610.     /* MULTI */
  611.     nicEvbWriteReg (pNic, &pNic->Rcr, AB, RPAGE0);    
  612.     nicEvbWriteReg (pNic, &pNic->Rcr, (AB | AM), RPAGE0);
  613.     nicEvbWriteReg (pNic, &pNic->Tcr, MODE1, RPAGE0); /* int loopback mode */
  614.     nicEvbWriteReg (pNic, &pNic->Pstart, PSTART, RPAGE0);
  615.     nicEvbWriteReg (pNic, &pNic->Pstop, PSTOP, RPAGE0);
  616.     nicEvbWriteReg (pNic, &pNic->Bnry, BNRY, RPAGE0);
  617.     nicEvbWriteReg (pNic, &pNic->Isr, 0xff, RPAGE0); /* clr pending ints */
  618.     nicEvbWriteReg (pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* enable int */
  619.     
  620.     /* set up page 1 registers */
  621.     nicEvbWriteReg (pNic, &pNic->Par0, pEnetAddr [0], RPAGE1);
  622.     nicEvbWriteReg (pNic, &pNic->Par1, pEnetAddr [1], RPAGE1);
  623.     nicEvbWriteReg (pNic, &pNic->Par2, pEnetAddr [2], RPAGE1);
  624.     nicEvbWriteReg (pNic, &pNic->Par3, pEnetAddr [3], RPAGE1);
  625.     nicEvbWriteReg (pNic, &pNic->Par4, pEnetAddr [4], RPAGE1);
  626.     nicEvbWriteReg (pNic, &pNic->Par5, pEnetAddr [5], RPAGE1);
  627.     nicEvbWriteReg (pNic, &pNic->nic_pg1.mar0, 0x00, RPAGE1);
  628.     nicEvbWriteReg (pNic, &pNic->nic_pg1.mar1, 0x00, RPAGE1);
  629.     nicEvbWriteReg (pNic, &pNic->nic_pg1.mar2, 0x00, RPAGE1);
  630.     nicEvbWriteReg (pNic, &pNic->nic_pg1.mar3, 0x00, RPAGE1);
  631.     nicEvbWriteReg (pNic, &pNic->nic_pg1.mar4, 0x00, RPAGE1);
  632.     nicEvbWriteReg (pNic, &pNic->nic_pg1.mar5, 0x00, RPAGE1);
  633.     nicEvbWriteReg (pNic, &pNic->nic_pg1.mar6, 0x00, RPAGE1);
  634.     nicEvbWriteReg (pNic, &pNic->nic_pg1.mar7, 0x00, RPAGE1);
  635.     
  636.     nicEvbWriteReg (pNic, &pNic->Curr, CURR, RPAGE1);
  637.     nicEvbWriteCr (pNic, RPAGE0 | ABORT | STA); /* back to page 0 */
  638.     nicEvbWriteReg (pNic, &pNic->Tcr, MODE0, RPAGE0); /* Tx normal mode */
  639.     }
  640. /*******************************************************************************
  641. *
  642. * nicEvbResetDelay - performs the delay required before resetting the chip 
  643. *
  644. * This routine performs a 1.6 ms delay for PowerPC architecture if 
  645. * using the internal PPC time base (the number of time base increment to
  646. * count for 1.6 msec is defined by the value nicRestartDelay which must 
  647. * be set in the BSP), or waits for one system clock tick otherwise.
  648. *
  649. * RETURNS: N/A.
  650. */
  651.  
  652. LOCAL void nicEvbResetDelay (void)
  653.     {
  654. #ifdef  NIC_USE_PPCTIMEBASE
  655.     UINT32 tbu1, tbu2;
  656.     UINT32 tbl1, tbl2;
  657. #endif
  658. #ifdef  NIC_USE_PPCTIMEBASE
  659.     vxTimeBaseGet (&tbu1, &tbl1);
  660.     while (1)  {
  661.         vxTimeBaseGet (&tbu2, &tbl2);
  662.         if ((tbu2-tbu1) != 0)
  663.             vxTimeBaseGet (&tbu1, &tbl1);
  664.         else
  665.     if ((tbl2 - tbl1) > nicEvbRestartDelay)
  666.              break;
  667.         }
  668. #else
  669.     taskDelay (1);                      /* wait at least 1.6 mSec */
  670. #endif
  671.     }
  672. /*******************************************************************************
  673. *
  674. * nicEvbWriteCr - write to the NIC command register
  675. *
  676. * RETURNS: N/A.
  677. */
  678. LOCAL void nicEvbWriteCr
  679.     (
  680.     NIC_DEVICE *pNic,
  681.     UINT8 value
  682.     )
  683.     {
  684.     int level = intLock ();
  685.     do {
  686.         pNic->Cr = value;
  687.         } while (!((*(volatile UINT8 *)NIC_DMA) & ACC_MASK));
  688.     intUnlock (level);
  689.     }
  690. /*******************************************************************************
  691. *
  692. * nicEvbWriteReg - write to a NIC register
  693. *
  694. * RETURNS: N/A.
  695. */
  696. LOCAL void nicEvbWriteReg 
  697.     (
  698.     NIC_DEVICE * pNic,
  699.     volatile UINT8 * pReg,
  700.     UINT8 value,
  701.     UINT8 page
  702.     )
  703.     {
  704.     volatile UINT8 * nicDma = (volatile UINT8 *) NIC_DMA;
  705.     UINT8 cr;
  706.     int level = intLock ();
  707.     do {
  708. cr = pNic->Cr;
  709. } while (!((*nicDma) & ACC_MASK));
  710.     if ((cr & PBMASK) != page)
  711. do {
  712.     pNic->Cr = (cr & 0x3f) | page;
  713.     } while (!((*nicDma) & ACC_MASK));
  714.     do {
  715. *pReg = value;
  716. } while (!((*nicDma) & ACC_MASK));
  717.     intUnlock (level);
  718.     }
  719. /*******************************************************************************
  720. *
  721. * nicReadReg - read from a NIC register
  722. *
  723. * RETURNS: the register value.
  724. */
  725. LOCAL UINT8 nicEvbReadReg 
  726.     (
  727.     NIC_DEVICE * pNic,
  728.     volatile UINT8 * pReg,
  729.     char page
  730.     )
  731.     {
  732.     volatile UINT8 * nicDma = (volatile UINT8 *) NIC_DMA;
  733.     UINT8 cr;
  734.     int level = intLock ();
  735.     do {
  736. cr = pNic->Cr;
  737. } while (!((*nicDma) & ACC_MASK));
  738.     if ((cr & PBMASK) != page)
  739. do {
  740.     pNic->Cr = (cr & 0x3f) | page;
  741.     } while (!((*nicDma) & ACC_MASK));
  742.     do {
  743. cr = *pReg;
  744. } while (!((*nicDma) & ACC_MASK));
  745.     intUnlock (level);
  746.     return (cr);
  747.     }
  748. /*******************************************************************************
  749. *
  750. * nicEvbReadPort - read from the DMA port
  751. *
  752. * RETURNS: the DMA port value.
  753. */
  754. LOCAL UINT8 nicEvbReadPort (void)
  755.     {
  756.     UINT8 value;
  757. #ifndef NIC_FASTER
  758.     int level = intLock ();
  759. #endif
  760.     do
  761. {
  762. value = *(volatile UINT8 *) NIC_PORT;
  763.         }
  764.     while (!((*(volatile UINT8 *) NIC_DMA) & ACC_MASK));
  765. #ifndef NIC_FASTER
  766.     intUnlock (level);
  767. #endif
  768.     return (value);
  769.     }
  770. /*******************************************************************************
  771. *
  772. * nicEvbReceive - receive data from the NIC network interface
  773. *
  774. * This routine transfers data from the NIC device ring buffers via the
  775. * remote DMA.
  776. *
  777. * RETURNS: OK, always.
  778. */
  779. LOCAL STATUS nicEvbReceive 
  780.     (
  781.     NICEVB_END_DEVICE* pDrvCtrl,    
  782.     UINT32 nicBufAddr, 
  783.     char* pData, 
  784.     int len
  785.     )
  786.     {
  787.     NIC_DEVICE * pNic = pDrvCtrl->pNic;
  788.     int residual;
  789.     int dmaCnt;
  790.     int ix;
  791. #ifdef NIC_FASTER
  792.     nicEvbWriteReg(pNic, &pNic->Imr, 0, RPAGE0); /* disable all interrupts */
  793. #endif
  794.     DRV_LOG (DRV_DEBUG_RX, "nicReceive: nicBufAddr:%u pData:%p len:%dn",
  795.              nicBufAddr, pData, len, 0, 0, 0);        
  796.     
  797.     if ((nicBufAddr + len) < (PSTOP * PACKET_SIZE))
  798. {
  799. nicEvbWriteReg (pNic, &pNic->Rbcr0, (len & 0xff), RPAGE0);
  800. nicEvbWriteReg (pNic, &pNic->Rbcr1, ((len & 0xff00) >> 8), RPAGE0);
  801. nicEvbWriteReg (pNic, &pNic->Rsar0, (nicBufAddr & 0xff), RPAGE0);
  802. nicEvbWriteReg (pNic, &pNic->Rsar1, (((nicBufAddr & 0xff00)>> 8)), RPAGE0);
  803. nicEvbWriteCr (pNic, RREAD);
  804. for (ix = 0; ix < len; ix ++)
  805.     *pData++ = nicEvbReadPort ();
  806. }
  807.     else
  808. {
  809. residual = (nicBufAddr + len) - (PSTOP * PACKET_SIZE);
  810. dmaCnt = len - residual;
  811. nicEvbWriteReg (pNic, &pNic->Rbcr0, (dmaCnt & 0xff), RPAGE0);
  812. nicEvbWriteReg (pNic, &pNic->Rbcr1, ((dmaCnt & 0xff00) >> 8), RPAGE0);
  813. nicEvbWriteReg (pNic, &pNic->Rsar0, (nicBufAddr & 0xff), RPAGE0);
  814. nicEvbWriteReg (pNic, &pNic->Rsar1, (((nicBufAddr & 0xff00)>> 8)), RPAGE0);
  815. nicEvbWriteCr (pNic, RREAD);
  816. for (ix = 0; ix < dmaCnt; ix++)
  817.     *pData++ = nicEvbReadPort ();
  818. nicEvbWriteReg (pNic, &pNic->Rbcr0, (residual & 0xff), RPAGE0);
  819. nicEvbWriteReg (pNic, &pNic->Rbcr1, ((residual & 0xff00) >> 8), RPAGE0);
  820. nicEvbWriteReg (pNic, &pNic->Rsar0, 0x00, RPAGE0);
  821. nicEvbWriteReg (pNic, &pNic->Rsar1, PSTART, RPAGE0);
  822. nicEvbWriteCr (pNic, RREAD);
  823. for (ix = 0; ix < residual; ix++)
  824.     *pData++ = nicEvbReadPort ();
  825. }
  826. #ifdef NIC_FASTER
  827.     nicEvbWriteReg(pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* re-enable intr. */
  828. #endif
  829.     return (OK);
  830.     } 
  831. /*******************************************************************************
  832. *
  833. * nicEvbPktBufRead - read data from the NIC receive ring buffer
  834. *
  835. * This routine gets exclusive access to the remote DMA, and calls
  836. * nicReceive() to get data from the NIC's receive ring buffer.
  837. *
  838. * RETURNS: OK, or ERROR if obtaining the requested bytes encountered an error.
  839. */
  840. LOCAL STATUS nicEvbPktBufRead
  841.     (
  842.     NICEVB_END_DEVICE* pDrvCtrl,
  843.     UINT32 nicBufAddr,
  844.     UINT32 len,
  845.     char* pData
  846.     )
  847.     {
  848.     STATUS status = OK;
  849.     
  850.     /* avoid starting DMA if device is down to to fatal error */
  851.     if ((END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)) !=
  852.         (IFF_UP | IFF_RUNNING))
  853.         {
  854.         DRV_LOG (DRV_DEBUG_RX, "nicPktBufRead: NOT UP and RUNNINGn",
  855.                  0, 0, 0, 0, 0, 0);        
  856.         return (ERROR);
  857.         }
  858.     if (!NIC_IS_IN_POLL_MODE())
  859.         {
  860.         if (semTake (pDrvCtrl->dmaSem, 100) == ERROR) /* get DMA */
  861.             {
  862.             DRV_LOG (DRV_DEBUG_LOAD, "nicPktBufRead: can't obtain dmaSemn",
  863.                      0, 0, 0, 0, 0, 0);
  864.             semTake (pDrvCtrl->dmaSem, WAIT_FOREVER);
  865.             }
  866.         }
  867.     status = nicEvbReceive (pDrvCtrl, nicBufAddr, pData, len);
  868.     if (!NIC_IS_IN_POLL_MODE())
  869.         semGive(pDrvCtrl->dmaSem);
  870.     return (status);
  871.     }
  872. /*******************************************************************************
  873. *
  874. * nicEvbPagePtrUpdate - updates receive buffer/page pointers
  875. *
  876. * This routine updates the receive buffer/page pointer and the receive
  877. * boundary register (BNRY). The chip is re-initialized if the receive next 
  878. * packet pointer recorded in the current packet header is out of range.
  879. *
  880. * RETURNS: TRUE, or FALSE if next packet pointer is out of range.
  881. */
  882.  
  883. LOCAL BOOL nicEvbPagePtrUpdate
  884.     (
  885.     NICEVB_END_DEVICE* pDrvCtrl,
  886.     NIC_CLUSTER pRxCluster
  887.     )
  888.     {
  889.     NIC_RX_FRAME* pRx = (NIC_RX_FRAME*)pRxCluster;
  890.     NIC_DEVICE* pNic = pDrvCtrl->pNic;
  891.     /* update ring buffer/page pointers */
  892.     if ((pRx->rxHdr.nextRxPage < PSTART)||(pRx->rxHdr.nextRxPage >= PSTOP))
  893.         {
  894.         DRV_LOG (DRV_DEBUG_LOAD,
  895.                  "nicPagePtrUpdate: statusHeader=0x%x nextRxPage=%d IntNb=%dn",
  896.                  pRx->rxHdr.status, pRx->rxHdr.nextRxPage, nicIntNb, 0, 0, 0);
  897. #ifdef NIC_INSTRUMENT
  898.      nicInitNb++;
  899. #endif
  900.         /* TODO MID increament error count */
  901.         /* pDrvCtrl->idr.ac_if.if_ierrors++; */
  902. /* restart the chip - we should never end up here - */
  903.      /* nicEvbConfig (0); HELP was index 0 */
  904.         nicEvbConfig (pDrvCtrl);
  905.      pDrvCtrl->nextPkt = CURR;
  906.         /* mark the interface -- up */
  907.         END_FLAGS_SET (&pDrvCtrl->end,
  908.                        (IFF_UP | IFF_RUNNING | IFF_MULTICAST | IFF_BROADCAST));    
  909.         return (FALSE);
  910.         }
  911.     /* updates the Boundary pointer register (BNRY) */
  912.     if ((pDrvCtrl->nextPkt = pRx->rxHdr.nextRxPage) == PSTART)
  913.         nicEvbWriteReg (pNic, &pNic->Bnry, PSTOP - 1, RPAGE0);
  914.     else
  915.         nicEvbWriteReg (pNic, &pNic->Bnry, pDrvCtrl->nextPkt - 1, RPAGE0);
  916.     return (TRUE);
  917.     }
  918. /*******************************************************************************
  919. *
  920. * nicEvToStack - passes received data to stack
  921. *
  922. * This routine grabs a MBuf from the pool, assigns data pointer to pointes the 
  923. * receive data and passes the MBuf to stack.
  924. *
  925. * RETURNS: OK, or ERROR in case of any error.
  926. */
  927. LOCAL STATUS nicEvbToStack
  928.     (
  929.     NICEVB_END_DEVICE* pDrvCtrl, /* the device */
  930.     NIC_CLUSTER pCluster
  931.     )
  932.     {
  933.     NIC_RX_FRAME* pRx = (NIC_RX_FRAME*)pCluster;    
  934.     CL_BLK_ID pClBlk;
  935.     M_BLK_ID pMblk;
  936.     UINT32 len;
  937.     STATUS nRetValue = ERROR;
  938.     len = pRx->rxHdr.cntL + (pRx->rxHdr.cntH << 8) - NIC_ETH_CRC_LEN;
  939.     
  940.     if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
  941.         {
  942.         DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
  943.         netClFree (pDrvCtrl->end.pNetPool, pCluster);        
  944.         END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  945.         goto cleanRXD;
  946.         }
  947.     /*
  948.      * OK we've got a spare, let's get an M_BLK_ID and marry it to the
  949.      * one in the ring.
  950.      */
  951.     if ((pMblk = mBlkGet(pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) ==
  952.         NULL)
  953.         {
  954.         netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
  955.         netClFree (pDrvCtrl->end.pNetPool, pCluster);                
  956.         DRV_LOG (DRV_DEBUG_MB, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
  957.         END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  958.         goto cleanRXD;
  959.         }
  960.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  961.     /* Join the cluster to the MBlock */
  962.     netClBlkJoin (pClBlk, (char*)pCluster, len, NULL, 0, 0, 0);
  963.     netMblkClJoin (pMblk, pClBlk);
  964.     /* make the packet data coherent */
  965.     /* LN_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len); */
  966.     /* pMblk->mBlkHdr.mData += pDrvCtrl->offset; */
  967.     NIC_FRAME_DATA_ADDR_GET(pCluster);    
  968.     pMblk->mBlkHdr.mLen = len;
  969.     pMblk->mBlkHdr.mData = pCluster;
  970.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  971.     pMblk->mBlkPktHdr.len = len;
  972.     /* Call the upper layer's receive routine. */
  973.     END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
  974.     return nRetValue;
  975. cleanRXD:
  976.     return OK;
  977.     }
  978. /*******************************************************************************
  979. *
  980. * nicEvbRead - read a packet off the interface ring buffer
  981. *
  982. * nicRead copies packets from local memory into an mbuf and hands it to
  983. * the next higher layer (IP).
  984. *
  985. * RETURNS: TRUE, or FALSE if the packet reception encountered errors.
  986. */
  987. LOCAL BOOL nicEvbRead
  988.     (
  989.     NICEVB_END_DEVICE* pDrvCtrl
  990.     )
  991.     {
  992.     NIC_CLUSTER pRxCluster;    
  993.     DRV_LOG (DRV_DEBUG_POLL, "Start Read!n", 1, 2, 3, 4, 5, 6);    
  994.     pRxCluster = (NIC_CLUSTER)nicEvbReadFrame (pDrvCtrl);
  995.     /* Pass the data up to the stack */    
  996.     if (pRxCluster == NULL)
  997.         return FALSE;
  998.     
  999.     nicEvbToStack (pDrvCtrl, pRxCluster);
  1000.     return (TRUE);
  1001.     }
  1002. /*******************************************************************************
  1003. *
  1004. * nicEvbReadFrame - read a packet off the interface ring buffer into a cluster
  1005. *
  1006. * Allocates a new cluster from the cluster pool, and reads the frame from the
  1007. * device into the cluster.
  1008. *
  1009. * RETURNS: a cluster or NULL if any error
  1010. */
  1011. LOCAL NIC_CLUSTER nicEvbReadFrame
  1012.     (
  1013.     NICEVB_END_DEVICE* pDrvCtrl
  1014.     )
  1015.     {
  1016.     NIC_RX_FRAME* pRx;
  1017.     UINT32 len; /* len of Rx pkt */
  1018.     int cur;
  1019.     NIC_CLUSTER pRetCluster = NULL;
  1020.     NIC_DEVICE* pNic = pDrvCtrl->pNic; /* NIC registers */
  1021.     
  1022.     if (!(END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)) ||
  1023.         (pDrvCtrl->nextPkt == (cur = nicEvbReadReg (pNic, &pNic->Curr,
  1024.                                                     RPAGE1))))
  1025.         return (pRetCluster);
  1026.     /*
  1027.      * OK, there is work to be done.
  1028.      * First we copy the NIC receive status header from the NIC buffer
  1029.      * into our local area. This is done so that we can obtain the length
  1030.      * of the packet before copying out the rest of it. Note that the length
  1031.      * field in the NIC header includes the Ethernet header, the data, and
  1032.      * the 4 byte FCS field.
  1033.      */
  1034.     /* Get a cluster */
  1035.     if ((pRx = (NIC_RX_FRAME*)netClusterGet(pDrvCtrl->end.pNetPool,
  1036.                                            pDrvCtrl->pClPoolId)) == NULL)
  1037.         {
  1038.         DRV_LOG (DRV_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
  1039.         END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1040.         return (pRetCluster);
  1041.         }
  1042.     
  1043.     /* read header in cluster*/
  1044.     DRV_LOG (DRV_DEBUG_RX, "nicPktBufRead : Reading Headern", 1, 2, 3, 4, 5, 6);    
  1045.     if (nicEvbPktBufRead (pDrvCtrl, pDrvCtrl->nextPkt << 8,
  1046.                           (NIC_RX_HDR_SZ), (char *) &pRx->rxHdr) == ERROR)
  1047.         {
  1048.         DRV_LOG (DRV_DEBUG_RX,
  1049.                  "nicRead could not read packet headern",
  1050.                  0, 0, 0, 0, 0, 0);
  1051.         return (pRetCluster);
  1052.         }
  1053.     /* TODO */
  1054.     len = pRx->rxHdr.cntL + (pRx->rxHdr.cntH << 8) - NIC_ETH_CRC_LEN;
  1055.     
  1056.     /* valid frame checks */
  1057.     /*
  1058.      * NOTE: if the packet's receive status byte indicates an error
  1059.      * the packet is discarded and the receive page pointers are updated to
  1060.      * point to the next packet.
  1061.      */
  1062. #ifdef NIC_INSTRUMENT
  1063.     nicLen = len;
  1064.     nicHdrStat = pRx->rxHdr.status;
  1065.     nicNextPage = pRx->rxHdr.nextRxPage;
  1066.     nicCurrentPage = cur;
  1067. #endif
  1068.     if ((len < 60) || (len > 1514) || ((pRx->rxHdr.status & ~PHY) != PRX))
  1069. {
  1070.         /* TODO increament error count */
  1071. /* pDrvCtrl->idr.ac_if.if_ierrors++; */
  1072.         DRV_LOG (DRV_DEBUG_LOAD,
  1073.                  "nicRead receive error: statusHeader=0x%x nextRxPage=%d 
  1074.                            currentPage=%d len=%d IntNb=%dn",
  1075.                  pRx->rxHdr.status, pRx->rxHdr.nextRxPage, cur,len,nicIntNb,
  1076.                  0);
  1077.         
  1078.         END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1079. nicEvbPagePtrUpdate (pDrvCtrl, (NIC_CLUSTER)pRx);
  1080.         return (pRetCluster);
  1081. }
  1082.     /* copy Ethernet packet section of the frame */
  1083.     
  1084.     DRV_LOG (DRV_DEBUG_RX, "nicPktBufRead : Reading Framen",
  1085.              1, 2, 3, 4, 5, 6);
  1086.     
  1087.     if (nicEvbPktBufRead (pDrvCtrl, (pDrvCtrl->nextPkt << 8) + NIC_RX_HDR_SZ,
  1088.                           len, (char *) &pRx->enetHdr) == ERROR)
  1089.         {
  1090.         DRV_LOG (DRV_DEBUG_LOAD, "nicRead: Could not read packet datan",
  1091.                  0, 0, 0, 0, 0, 0);
  1092.         END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);        
  1093. nicEvbPagePtrUpdate(pDrvCtrl, (NIC_CLUSTER)pRx);
  1094.         return (pRetCluster);
  1095.         
  1096. }
  1097.     /* update ring buffer/page pointers */
  1098.     if (!nicEvbPagePtrUpdate (pDrvCtrl, (NIC_CLUSTER)pRx))
  1099. {
  1100. return (pRetCluster);
  1101. }
  1102.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);    
  1103.     DRV_LOG (DRV_DEBUG_POLL, "End Read!n", 1, 2, 3, 4, 5, 6);     
  1104.     return (NIC_CLUSTER)pRx;
  1105.     }
  1106. /*******************************************************************************
  1107. *
  1108. * nicEvbRestart - restart chip after receive ring buffer overflow
  1109. *
  1110. * This routine is the task-level handler that deals with a receive DMA
  1111. * overflow condition.  It gets access to the remote DMA, cleans up NIC
  1112. * registers, empties the receive ring buffers, and then resends any
  1113. * packet that was in the midst of transmission when the overflow hit.
  1114. *
  1115. * RETURNS: N/A.
  1116. */
  1117. LOCAL void nicEvbRestart
  1118.     (
  1119.     NICEVB_END_DEVICE* pDrvCtrl,
  1120.     UINT8 cr
  1121.     )
  1122.     {
  1123.     NIC_DEVICE * pNic = pDrvCtrl->pNic; /* NIC registers */
  1124.     BOOL resend = FALSE;
  1125. #ifdef NIC_INSTRUMENT
  1126.     nicRestartNb++;
  1127. #endif
  1128.     nicEvbWriteCr (pNic, STP);
  1129.     nicEvbResetDelay (); /* wait at least 1.6 mSec */
  1130.     if(!NIC_IS_IN_POLL_MODE())
  1131.         {
  1132.         if (semTake(pDrvCtrl->dmaSem, 100) == ERROR)
  1133.             {
  1134.             DRV_LOG (DRV_DEBUG_LOAD, "nicRestart: can't obtain dmaSemn",
  1135.                      0, 0, 0, 0, 0,0);
  1136.             semTake (pDrvCtrl->dmaSem, WAIT_FOREVER);
  1137.             }
  1138.         }
  1139.     nicEvbWriteReg (pNic, &pNic->Rbcr0, 0, RPAGE0);
  1140.     nicEvbWriteReg (pNic, &pNic->Rbcr1, 0, RPAGE0);
  1141.     if ((cr & TXP) && (!(nicEvbReadReg (pNic, &pNic->Isr, RPAGE0) &
  1142.         (TXE | PTX))))
  1143.      resend = TRUE;
  1144.     nicEvbWriteReg (pNic, &pNic->Tcr, MODE1, RPAGE0);
  1145.     nicEvbWriteCr (pNic, RPAGE0 | ABORT | STA); /* back to page 0 */
  1146.     END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);
  1147.     /*
  1148.      * Release the dmaSem semaphore here since a) it will be re-acquired
  1149.      * later if needed and b) we don't want to hold it while sending things
  1150.      * up the stack since this may cause a deadlock if an application
  1151.      * tries to send something down the stack to us. (The send routine
  1152.      * will try to acquire the semaphore while we're still holding it
  1153.      * here.)
  1154.      */
  1155.  
  1156.     if(!NIC_IS_IN_POLL_MODE())
  1157.         semGive(pDrvCtrl->dmaSem);
  1158.     while (nicEvbRead (pDrvCtrl))
  1159. ;
  1160.     if(!NIC_IS_IN_POLL_MODE())
  1161.         {
  1162.         if (semTake(pDrvCtrl->dmaSem, 100) == ERROR)
  1163.             {
  1164.             DRV_LOG (DRV_DEBUG_LOAD, "nicRestart: can't obtain dmaSemn",
  1165.                      0, 0, 0, 0, 0,0);
  1166.             semTake (pDrvCtrl->dmaSem, WAIT_FOREVER);
  1167.             }
  1168.         }
  1169.     nicEvbWriteReg(pNic, &pNic->Isr, OVW, RPAGE0);
  1170.     nicEvbWriteReg (pNic, &pNic->Tcr, MODE0, RPAGE0);
  1171.     if (resend)
  1172.         nicEvbWriteCr (pNic, RPAGE0 | STA | TXP | ABORT);
  1173.     if(!NIC_IS_IN_POLL_MODE())
  1174.         semGive(pDrvCtrl->dmaSem);
  1175.     nicEvbWriteReg (pNic, &pNic->Imr, PRXE | OVWE, RPAGE0);
  1176.     }
  1177. /*******************************************************************************
  1178. *
  1179. * nicEvbHandleInt - deferred receive interrupt handler
  1180. *
  1181. * This function handles the received frames from the device.  It runs in the
  1182. * context of the netTask, which was triggered by a received packet interrupt.
  1183. * Actual processing of the packet is done by calling nicEvbRead().
  1184. *
  1185. * RETURNS: N/A.
  1186. */
  1187. LOCAL void nicEvbHandleInt
  1188.     (
  1189.     NICEVB_END_DEVICE* pDrvCtrl    
  1190.     )
  1191.     {
  1192.     /* empties the receive ring buffer of its packets */
  1193.     while (nicEvbRead (pDrvCtrl));
  1194.     }
  1195. /*******************************************************************************
  1196. *
  1197. * nicIntr - The driver's interrupt handler
  1198. *
  1199. * This function clears the cause of the device interrupt(s) and then acts
  1200. * on the individual possible causes.  The primary goal of this routine is to
  1201. * minimize the time spent in it.  This is accomplished by deferring processing
  1202. * to the netTask via the netJobAdd() function.
  1203. *
  1204. * Note that in case the receiver overruns, we promptly mark the interface as
  1205. * "down" and leave error handling to task-level.   This is in case netTask
  1206. * is in the midst of DMA activity, we must allow it to complete.  The receive
  1207. * handler will give up when it discovers the interface is down, which will
  1208. * then allow netTask to run our OVW handler.  This provides a nice orderly
  1209. * error recovery.
  1210. *
  1211. * RETURNS: N/A.
  1212. */
  1213. LOCAL void nicEvbInt
  1214.     (
  1215.     NICEVB_END_DEVICE* pDrvCtrl
  1216.     )
  1217.     {
  1218.     NIC_DEVICE * pNic = pDrvCtrl->pNic; /* NIC registers */
  1219.     UINT8 isr; /* copy of ISR */
  1220.     UINT8 cr; /* copy of CR */
  1221. #ifdef DRV_DEBUG
  1222.     nicIntNb++;
  1223. #endif
  1224.     DRV_LOG (DRV_DEBUG_INT, "Inside INTn", 1, 2, 3, 4, 5, 6);
  1225.     
  1226.     isr = nicEvbReadReg(pNic, &pNic->Isr, RPAGE0);
  1227.     nicEvbWriteReg(pNic, &pNic->Isr, isr, RPAGE0);
  1228.     /* handle receiver overrun */
  1229.     if  ((isr & OVW) && (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)))
  1230. {
  1231. cr = nicEvbReadReg (pNic, &pNic->Cr, RPAGE0);
  1232. nicEvbWriteReg(pNic, &pNic->Imr, 0, RPAGE0); /* disable all interrupts */
  1233.         /* mark the interface -- down */
  1234.         END_FLAGS_CLR (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
  1235.         
  1236. netJobAdd ((FUNCPTR) nicEvbRestart, (int) pDrvCtrl, cr, 0, 0, 0);
  1237.         return;
  1238. }
  1239.     /* handle packet received */
  1240.     if  ((isr & PRX) && (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)))
  1241. netJobAdd ((FUNCPTR) nicEvbHandleInt, (int) pDrvCtrl, 0, 0, 0, 0);
  1242.     }
  1243. /*******************************************************************************
  1244. *
  1245. * nicEvbSend - the driver's actual output routine
  1246. *
  1247. * This routine accepts outgoing packets from the snd queue, and then 
  1248. * gains exclusive access to the DMA (through a mutex semaphore),
  1249. * then calls nicEvbTransmit() to send the packet out onto the interface.
  1250. *
  1251. * RETURNS: OK, or ERROR if the packet could not be transmitted.
  1252. */
  1253. LOCAL STATUS nicEvbSend
  1254.     (
  1255.     NICEVB_END_DEVICE* pDrvCtrl,
  1256.     M_BLK* pMblk
  1257.     )
  1258.     {
  1259.     int status = OK;
  1260.     DRV_LOG(DRV_DEBUG_TX, "Begin nicEvbSend pDrvCtrl %p pMblk %pn", pDrvCtrl,
  1261.             pMblk, 0, 0, 0, 0);
  1262.     if ((END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)) !=
  1263.         (IFF_UP | IFF_RUNNING))
  1264.         {
  1265.         DRV_LOG(DRV_DEBUG_TX, "Device is NOT UP and RUNNINGn", 0, 0,
  1266.                 0, 0, 0, 0);
  1267. if(!NIC_IS_IN_POLL_MODE())
  1268.         netMblkClChainFree (pMblk); /* free the given mBlk chain */
  1269.         errno = EINVAL;
  1270.         return (ERROR);
  1271.         }
  1272.     if(!NIC_IS_IN_POLL_MODE())
  1273.         {
  1274.         if (semTake (pDrvCtrl->dmaSem, 100) == ERROR) /* get DMA access */
  1275.             {
  1276.             DRV_LOG(DRV_DEBUG_TX, "nicTxStartup: can't obtain dmaSemn",
  1277.                       0, 0, 0, 0, 0, 0);
  1278.             semTake (pDrvCtrl->dmaSem, WAIT_FOREVER);
  1279.             }
  1280.         }
  1281.     /* update statistics */
  1282.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
  1283. #ifdef NIC_INSTRUMENT
  1284.     nicTxNb++;
  1285. #endif
  1286.     /* send packet out over interface */
  1287.     if ((status = nicEvbTransmit (pDrvCtrl, pMblk, TRUE)) == ERROR)
  1288.         {
  1289.         DRV_LOG(DRV_DEBUG_TX, "FAILED nicEvbTransmitn", 0, 0, 0, 0, 0, 0);
  1290.         
  1291.         /* update statistics */
  1292.         END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
  1293.         /* TODO update error count */
  1294.         }
  1295.     if(!NIC_IS_IN_POLL_MODE())
  1296. {
  1297.         semGive (pDrvCtrl->dmaSem);
  1298.      /* free the Mblk chain */
  1299.     
  1300.      netMblkClChainFree (pMblk);
  1301. }
  1302.     
  1303.     DRV_LOG(DRV_DEBUG_TX, "End nicEvbSend n", 0, 0, 0, 0, 0, 0);    
  1304.     
  1305.     return status;    
  1306.     }
  1307. /*******************************************************************************
  1308. *
  1309. * nicEvbTransmit - send data over the NIC network interface
  1310. *
  1311. * This routine transfers data to the NIC device via the remote DMA, and
  1312. * then signal for a transmission.
  1313. *
  1314. * RETURNS: OK, or ERROR if the transmitter signalled an error.
  1315. */
  1316. LOCAL STATUS nicEvbTransmit
  1317.     (
  1318.     NICEVB_END_DEVICE* pDrvCtrl,    
  1319.     M_BLK* pMblk,
  1320.     BOOL waitFlag
  1321.     )
  1322.     {
  1323.     NIC_DEVICE * pNic = pDrvCtrl->pNic;
  1324.     UINT8 cr;
  1325.     UINT8 isr;
  1326.     UINT8* pBuf;
  1327.     int status = OK;
  1328.     int count;
  1329.     int ix;
  1330.     int len;
  1331.     int tranxLen;
  1332.     /* find the length of the packet */    
  1333.     len = nicEvbMblkDataLenGet (pMblk);
  1334.     
  1335.     /* find the length of the packet */
  1336.     tranxLen = max (len, MINPKTSIZE);
  1337.     
  1338. #ifdef NIC_FASTER
  1339.     nicWriteReg(pNic, &pNic->Imr, 0, RPAGE0);   /* disable all interrupts */
  1340. #endif
  1341.     nicEvbWriteReg (pNic, &pNic->Rbcr0, 0x10, RPAGE0);
  1342.     nicEvbWriteCr (pNic, RREAD);
  1343.     nicEvbWriteReg (pNic, &pNic->Rbcr0, (tranxLen & 0x00ff), RPAGE0);
  1344.     nicEvbWriteReg (pNic, &pNic->Rbcr1, (tranxLen & 0xff00) >> 8, RPAGE0);
  1345.     nicEvbWriteReg (pNic, &pNic->Rsar0, 0x00, RPAGE0);
  1346.     nicEvbWriteReg (pNic, &pNic->Rsar1, 0x00, RPAGE0);
  1347.     nicEvbWriteCr (pNic, RWRITE);
  1348.     
  1349.     count = 0;
  1350.     while (pMblk != NULL)
  1351.         {
  1352.         pBuf = (char *)pMblk->mBlkHdr.mData;
  1353.         len  = pMblk->mBlkHdr.mLen;
  1354. for (ix = 0 ; ix < len; ix++)
  1355.     { 
  1356.     count++;
  1357.     nicEvbWritePort (*pBuf++);
  1358.     }
  1359.         pMblk = pMblk->mBlkHdr.mNext;
  1360.         }
  1361.     
  1362.     for (; count < tranxLen; count ++) /* pad out if too short */
  1363. nicEvbWritePort (0);
  1364.     nicEvbWriteReg (pNic, &pNic->Tpsr, 0x00, RPAGE0);
  1365.     nicEvbWriteReg (pNic, &pNic->Tbcr0, (tranxLen & 0x000000ff), RPAGE0);
  1366.     nicEvbWriteReg (pNic, &pNic->Tbcr1, ((tranxLen & 0x0000ff00) >> 8), RPAGE0);
  1367.     cr = nicEvbReadReg (pNic, &pNic->Cr, RPAGE0);
  1368.     nicEvbWriteReg(pNic, &pNic->Isr, (PTX | TXE), RPAGE0);
  1369.     nicEvbWriteCr (pNic, TXP | (cr & (RWRITE | RREAD))); /* start Tx */
  1370.     count = 0;
  1371.     if (waitFlag) /* wait for Tx to end ? */
  1372. {
  1373.         while (count++ < NIC_TRANS_TIMEOUT) /* only poll a few times */
  1374.     {
  1375.             isr = nicEvbReadReg (pNic, &pNic->Isr, RPAGE0);
  1376.     if (isr & TXE) /* error encountered */
  1377.         {
  1378.                 DRV_LOG(DRV_DEBUG_TX, "ERROR in Transmitionn", 
  1379.                           0, 0, 0, 0, 0, 0);                                
  1380.                 status = ERROR;
  1381.         break;
  1382.         }
  1383.     if (isr & PTX) /* Tx done */
  1384.                 {
  1385.                 DRV_LOG(DRV_DEBUG_TX, "Transmit Donen", 
  1386.                           0, 0, 0, 0, 0, 0);                
  1387.         break;
  1388.                 }
  1389.             }
  1390.         if (count >= NIC_TRANS_TIMEOUT) /* error ? */
  1391.     {
  1392.             status = ERROR;
  1393. #ifdef NIC_INSTRUMENT
  1394.     nicTxTimeout++;
  1395. #endif
  1396.             DRV_LOG(DRV_DEBUG_LOAD, "nicTransmit TRANS_TIMEOUT %dn",
  1397.                     nicTxTimeout,0,0,0,0,0);
  1398.     }
  1399.         }
  1400. #ifdef NIC_FASTER
  1401.     nicEvbWriteReg(pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* re-enable intr. */
  1402. #endif
  1403.     return (status);
  1404.     }
  1405. /*******************************************************************************
  1406. *
  1407. * nicEvbMblkDataLenGet - gets the total len of the given Mblk chain packet
  1408. *
  1409. * RETURNS: length of the packet.
  1410. *
  1411. */
  1412. LOCAL int nicEvbMblkDataLenGet
  1413.     (
  1414.     M_BLK* pMblk
  1415.     )
  1416.     {
  1417.     int nPktChainLen = 0;
  1418.     while (pMblk != NULL)
  1419.         {
  1420.         nPktChainLen += pMblk->mBlkHdr.mLen;
  1421.         pMblk = pMblk->mBlkHdr.mNext;
  1422.         }
  1423.         
  1424.     return (nPktChainLen);
  1425.     }
  1426. /*******************************************************************************
  1427. *
  1428. * nicEnetAddrGet - get the Ethernet address.
  1429. *
  1430. * Get ethernet address from the BSP.
  1431. *
  1432. * RETURNS: N/A.
  1433. */
  1434. LOCAL void nicEvbEnetAddrGet
  1435.     (
  1436.     NICEVB_END_DEVICE* pDrvCtrl,
  1437.     char* pAddress
  1438.     )
  1439.     {
  1440.     UINT8 enetAdrs[6];
  1441.     UINT8 count;
  1442.     if (sysEnetAddrGet (pDrvCtrl->unit, enetAdrs) != ERROR )
  1443.         {
  1444.         for (count=0; count<6; count++)
  1445.             pAddress[count] = enetAdrs[5-count];
  1446.         }
  1447.     }
  1448. /*******************************************************************************
  1449. *
  1450. * nicEvbWritePort - write to the DMA port
  1451. *
  1452. * RETURNS: N/A.
  1453. */
  1454. LOCAL void nicEvbWritePort
  1455.     (
  1456.     UINT8 value
  1457.     )
  1458.     {
  1459. #ifndef NIC_FASTER
  1460.     int level = intLock ();
  1461. #endif
  1462.     do 
  1463. {
  1464. *(volatile char *) NIC_PORT = value;
  1465.         }
  1466.     while (!((*(volatile UINT8 *) NIC_DMA) & ACC_MASK));
  1467. #ifndef NIC_FASTER
  1468.     intUnlock (level);
  1469. #endif
  1470.     }    
  1471.     
  1472. /*******************************************************************************
  1473. *
  1474. * nicIoctl - the driver's I/O control routine
  1475. *
  1476. * Perform device-specific commands.
  1477. *
  1478. * RETURNS: 0, or EINVAL if the command 'cmd' is not supported.
  1479. */
  1480. LOCAL int nicEvbIoctl
  1481.     (
  1482.     NICEVB_END_DEVICE* pDrvCtrl,
  1483.     int cmd,
  1484.     caddr_t data    
  1485.     )
  1486.     {
  1487.     int error = 0;
  1488.     DRV_LOG (DRV_DEBUG_LOAD, "nicEvbIoctl Command %dn", cmd, 2, 3, 4, 5, 6);
  1489.     
  1490.     switch (cmd)
  1491. {
  1492.         case EIOCSADDR:
  1493.     if (data == NULL)
  1494. return (EINVAL);
  1495.             bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
  1496.    END_HADDR_LEN(&pDrvCtrl->end));
  1497.             nicEvbConfig (pDrvCtrl); /* HELP  Will it work? */
  1498.             break;
  1499.         case EIOCGADDR:
  1500.     if (data == NULL)
  1501. return (EINVAL);
  1502.             bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
  1503.     END_HADDR_LEN(&pDrvCtrl->end));
  1504.             break;
  1505.         case EIOCSFLAGS:/* no driver-dependent flags */
  1506.             break;
  1507.         case EIOCGFLAGS:
  1508.     *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
  1509.             break;
  1510.         case EIOCMULTIADD:                   /* move to mux */
  1511.             error = nicEvbMCastAddrAdd (pDrvCtrl, (char *)data);
  1512.             break;
  1513.         case EIOCMULTIDEL:                   /* move to mux */
  1514.             error = nicEvbMCastAddrDel (pDrvCtrl, (char *)data);
  1515.             break;
  1516.         case EIOCMULTIGET:                   /* move to mux */
  1517.             error = nicEvbMCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data);
  1518.             break;
  1519.         case EIOCPOLLSTART:                  /* move to mux */
  1520.             error = nicEvbPollStart (pDrvCtrl);
  1521.             break;
  1522.         case EIOCPOLLSTOP:                   /* move to mux */
  1523.             error = nicEvbPollStop (pDrvCtrl);
  1524.             break;            
  1525.         case EIOCGMIB2:
  1526.             if (data == NULL)
  1527.                 return (EINVAL);
  1528.             bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
  1529.                   sizeof(pDrvCtrl->end.mib2Tbl));
  1530.             break;
  1531.         default:
  1532.             error = EINVAL;
  1533. }
  1534.     return (error);
  1535.     } 
  1536. /*******************************************************************************
  1537. *
  1538. * nicEvbStop - stop the device
  1539. *
  1540. * This function calls BSP functions to disconnect interrupts and stop
  1541. * the device from operating in interrupt mode.
  1542. *
  1543. * RETURNS: OK or ERROR
  1544. */
  1545. LOCAL STATUS nicEvbStop
  1546.     (
  1547.     NICEVB_END_DEVICE* pDrvCtrl
  1548.     )
  1549.     {
  1550.     STATUS result = OK;
  1551.     NIC_DEVICE* pNic = pDrvCtrl->pNic;    
  1552.     /* Stop the device. */
  1553.     nicEvbWriteReg(pNic, &pNic->Imr, 0, RPAGE0);  /* disable all interrupts */
  1554.     SYS_INT_DISCONNECT (pDrvCtrl, nicEvbInt, (int)pDrvCtrl, &result);
  1555.     if (result == ERROR)
  1556. {
  1557. DRV_LOG (DRV_DEBUG_LOAD, "Could not diconnect interrupt!n",
  1558.                  1, 2, 3, 4, 5, 6);
  1559. }
  1560.     return (result);
  1561.     }
  1562. /******************************************************************************
  1563. *
  1564. * nicEvbUnload - unload a driver from the system
  1565. *
  1566. * This function first brings down the device, and then frees any
  1567. * stuff that was allocated by the driver in the load function.
  1568. */
  1569. LOCAL STATUS nicEvbUnload
  1570.     (
  1571.     NICEVB_END_DEVICE* pDrvCtrl
  1572.     )
  1573.     {
  1574.     if (pDrvCtrl != NULL)
  1575.         {
  1576.         END_OBJECT_UNLOAD (&pDrvCtrl->end);
  1577.         /* free cluster memory */
  1578.         if (pDrvCtrl->pRxCluster != NULL)
  1579.             free (pDrvCtrl->pRxCluster);
  1580.         }
  1581.     return (OK);
  1582.     }
  1583. /*******************************************************************************
  1584. *
  1585. * nicEvbMCastAddrAdd - add a multicast address
  1586. *
  1587. *
  1588. * RETURNS: OK on success, ERROR otherwise.
  1589. */
  1590. LOCAL STATUS nicEvbMCastAddrAdd
  1591.     (
  1592.     NICEVB_END_DEVICE * pDrvCtrl,
  1593.     char * pAddr
  1594.     )
  1595.     {
  1596.     int retVal;
  1597.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrAddn", 0, 0, 0, 0, 0, 0);
  1598.     retVal = etherMultiAdd (&pDrvCtrl->end.multiList, pAddr);
  1599.     if (retVal == ENETRESET)
  1600.         nicEvbAddrFilterSet (pDrvCtrl, pAddr, TRUE);
  1601.     return OK; /*((retVal == OK) ? OK : ERROR);*/
  1602.     }
  1603. /*******************************************************************************
  1604. *
  1605. * nicEvbMCastAddrDel - remove a multicast address
  1606. *
  1607. *
  1608. * RETURNS: OK on success, ERROR otherwise.
  1609. */
  1610. LOCAL STATUS nicEvbMCastAddrDel
  1611.     (
  1612.     NICEVB_END_DEVICE * pDrvCtrl,
  1613.     char * pAddr
  1614.     )
  1615.     {
  1616.     int retVal;
  1617.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrDeln", 0, 0, 0, 0, 0, 0);
  1618.     retVal = etherMultiDel (&pDrvCtrl->end.multiList, pAddr);
  1619.     if (retVal == ENETRESET)
  1620.         nicEvbAddrFilterSet (pDrvCtrl, pAddr, FALSE);
  1621.     return OK; /*((retVal == OK) ? OK : ERROR);*/
  1622.     }
  1623. /*******************************************************************************
  1624. *
  1625. * nicEvbMCastAddrGet - retreive current multicast address list
  1626. *
  1627. *
  1628. * RETURNS: OK on success; otherwise ERROR.
  1629. */
  1630. LOCAL STATUS nicEvbMCastAddrGet
  1631.     (
  1632.     NICEVB_END_DEVICE * pDrvCtrl,
  1633.     MULTI_TABLE *pTable
  1634.     )
  1635.     {
  1636.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrGetn", 0, 0, 0, 0, 0, 0);
  1637.     return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
  1638.     }
  1639. /*(FIXED)*/
  1640. /*******************************************************************************
  1641. *
  1642. * nicEvbPollStart - starting polling mode
  1643. *
  1644. * RETURNS: OK, always.
  1645. */
  1646. LOCAL STATUS nicEvbPollStart
  1647.     (
  1648.     NICEVB_END_DEVICE * pDrvCtrl
  1649.     )
  1650.     {
  1651.     int intLevel;
  1652.     NIC_DEVICE* pNic = pDrvCtrl->pNic; /* address of NIC chip */
  1653.     DRV_LOG (DRV_DEBUG_POLL, "S ", 0, 0, 0, 0, 0, 0);
  1654.     intLevel = intLock();
  1655.     /* disable all interrupts */
  1656.     nicEvbWriteReg (pNic, &pNic->Imr, 0x00, RPAGE0);
  1657.     DRV_FLAGS_SET(NIC_FLAG_POLL);
  1658.     intUnlock (intLevel);
  1659.     return (OK);    
  1660.     }
  1661. /*******************************************************************************
  1662. *
  1663. * nicEvbPollStop - stop polling mode
  1664. *
  1665. * RETURNS: OK, always.
  1666. */
  1667. LOCAL STATUS nicEvbPollStop
  1668.     (
  1669.     NICEVB_END_DEVICE * pDrvCtrl
  1670.     )
  1671.     {
  1672.     NIC_DEVICE* pNic = pDrvCtrl->pNic; /* address of NIC chip */
  1673.     int intLevel;
  1674.     intLevel = intLock();
  1675.     nicEvbWriteReg (pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* enable int */
  1676.     DRV_FLAGS_CLR(NIC_FLAG_POLL);
  1677.     DRV_LOG (DRV_DEBUG_POLL, "s", 0, 0, 0, 0, 0, 0);
  1678.     
  1679.     intUnlock (intLevel);
  1680.     return (OK);
  1681.     }
  1682. /*******************************************************************************
  1683. *
  1684. * nicEvbPollSend - send a packet in polled mode
  1685. *
  1686. * RETURNS: OK on success, EAGAIN on failure
  1687. */
  1688. LOCAL STATUS nicEvbPollSend
  1689.     (
  1690.     NICEVB_END_DEVICE* pDrvCtrl,
  1691.     M_BLK* pMblk
  1692.     )
  1693.     {
  1694.     return (nicEvbSend (pDrvCtrl, pMblk));
  1695.     }
  1696. /*******************************************************************************
  1697. *
  1698. * nicEvbPollReceive - get a packet in polled mode
  1699. *
  1700. * RETURNS: OK on success, EAGAIN on failure.
  1701. */
  1702. LOCAL STATUS nicEvbPollReceive
  1703.     (
  1704.     NICEVB_END_DEVICE* pDrvCtrl,
  1705.     M_BLK* pMblk
  1706.     )
  1707.     {
  1708.     STATUS nRetValue = OK;
  1709.     NIC_CLUSTER pCluster;
  1710.     int len;
  1711.     
  1712.     DRV_LOG (DRV_DEBUG_POLL, "Start Poll Read!n", 1, 2, 3, 4, 5, 6);
  1713.     if ((pCluster = nicEvbReadFrame (pDrvCtrl)) == NULL)
  1714.         nRetValue = EAGAIN;
  1715.     else
  1716.         {
  1717.         NIC_RX_FRAME* pRx = (NIC_RX_FRAME*)pCluster;
  1718.         
  1719.         len = pRx->rxHdr.cntL + (pRx->rxHdr.cntH << 8) - NIC_ETH_CRC_LEN;
  1720.     
  1721. pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */
  1722. pMblk->mBlkHdr.mLen = len;    /* set the data len */
  1723. pMblk->mBlkPktHdr.len = len;    /* set the total len */
  1724.         NIC_FRAME_DATA_ADDR_GET(pCluster);
  1725.         bcopy (pCluster, (char *)pMblk->mBlkHdr.mData, len);
  1726.         netClFree (pDrvCtrl->end.pNetPool, (char*)pRx);
  1727.         
  1728.         }
  1729.     
  1730.     DRV_LOG (DRV_DEBUG_POLL, "End Poll Read!n", 1, 2, 3, 4, 5, 6);        
  1731.     return nRetValue;
  1732.     }
  1733. /*******************************************************************************
  1734. *
  1735. * nicEvbHashIndex - compute the hash index for an ethernet address
  1736. *
  1737. * RETURNS: hash index for an ethernet address.
  1738. */
  1739. LOCAL int nicEvbHashIndex
  1740.     (
  1741.     char * eAddr
  1742.     )
  1743.     {
  1744.     UINT8 eAddrByte;
  1745.     int index;                       /* hash index - return value */
  1746.     int byte;                        /* loop - counter */
  1747.     int bit;                         /* loop - counter */
  1748.     UINT crc = 0xffffffff;
  1749.     UINT8 msb;
  1750.     for (byte=0; byte<6; byte++)
  1751.         {
  1752.         eAddrByte = eAddr[byte];
  1753.         for (bit=0; bit<8; bit++)
  1754.             {
  1755.             msb = crc >> 31;
  1756.             crc <<= 1;
  1757.             if (msb ^ (eAddrByte & 0x1))
  1758.                 {
  1759.                 crc ^= NIC_CRC_POLY;
  1760.                 crc |= 0x1;
  1761.                 }
  1762.             eAddrByte >>= 1;
  1763.             }
  1764.         }
  1765.     /* Just want the 6 most significant bits. */
  1766.     
  1767.     index = crc >> 26 ;
  1768.     return index;
  1769.     }
  1770.  
  1771. /******************************************************************************
  1772. *
  1773. * nicEvbAddrFilterSet - set the address filter for multicast addresses
  1774. *
  1775. * This routine goes through all of the multicast addresses on the list
  1776. * of addresses (added with the MCastAddrAdd() routine) and sets the
  1777. * device's filter correctly.
  1778. *
  1779. * NOMANUAL
  1780. */
  1781. LOCAL void nicEvbAddrFilterSet
  1782.     (
  1783.     NICEVB_END_DEVICE *pDrvCtrl,
  1784.     char* pAddr,
  1785.     BOOL bSet
  1786.     )
  1787.     {
  1788.     UINT8 nHashIndex;
  1789.     /* get hash index for the address */
  1790.     nHashIndex = nicEvbHashIndex (pAddr);
  1791.     /* Turn on the corresponding bit in the filter. */
  1792.     nicEvbMARSet (pDrvCtrl, nHashIndex, bSet);
  1793.     }
  1794. /*******************************************************************************
  1795. *
  1796. * nicEvbMARSet - sets/resets the MAR for the specified hash index
  1797. *
  1798. * This routine sets/resets the MAR bit for the specified hash index
  1799. *
  1800. * RETURNS: OK or ERROR.
  1801. */
  1802. LOCAL void nicEvbMARSet
  1803.     (
  1804.     NICEVB_END_DEVICE* pDrvCtrl,    
  1805.     UINT8 index, /* hash index */
  1806.     BOOL bSet /* Set/Reset */
  1807.     )
  1808.     {
  1809.     UINT8 nRegOffset = index;
  1810.     UINT8 nBitPosition = index;
  1811.     UINT8 nBitMask = (UINT8)0x01;
  1812.     UINT8 nValue;
  1813.     char* pMAR = (char*)pDrvCtrl->pNic;
  1814.     
  1815.     /* Finde register and bit position */
  1816.     nBitPosition = nBitPosition & 0x07;  /* 3 LSB bits */
  1817.     nRegOffset >>= 3;      /* next 3 bits */
  1818.     nBitMask <<= nBitPosition;
  1819.     pMAR += NIC_IR_MAR0 + nRegOffset;
  1820.     /* set the bit in bit array*/
  1821.     nValue = nicEvbReadReg (pDrvCtrl->pNic, pMAR, RPAGE1);
  1822.     DRV_LOG (DRV_DEBUG_LOAD, "Hash Index:%d MAR Offset:%d value:%dn",
  1823.              index, nRegOffset, nValue, 4, 5, 6);
  1824.     
  1825.     if (bSet)
  1826.         {
  1827.         nValue |= nBitMask; /* set */
  1828.         }
  1829.     else
  1830.         {
  1831.         nBitMask = ~nBitMask; /* reset */
  1832.         nValue &= nBitMask;        
  1833.         }
  1834.     
  1835.     nicEvbWriteReg (pDrvCtrl->pNic, pMAR, nValue, RPAGE1);
  1836.     
  1837.     DRV_LOG (DRV_DEBUG_LOAD, "Hash Index:%d MAR Offset:%d value:%dn",
  1838.              index, nRegOffset, nValue, 4, 5, 6);
  1839.     
  1840.     }
  1841. /* (OLD) */
  1842. /*******************************************************************************
  1843. *
  1844. * nicReset - reset of interface
  1845. *
  1846. * This routine performs a software reset of the ST-NIC device.
  1847. *
  1848. * RETURNS: N/A.
  1849. *
  1850. * NOMANUAL
  1851. */
  1852. LOCAL void nicEvbReset
  1853.     (
  1854.     NICEVB_END_DEVICE* pDrvCtrl
  1855.     )
  1856.     {
  1857.     NIC_DEVICE * pNic = pDrvCtrl->pNic;
  1858.     nicEvbWriteCr (pNic, STP | ABORT | RPAGE0);
  1859.     taskDelay (2); /* wait at least 1.6 mSec */
  1860.     }