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

VxWorks

开发平台:

C/C++

  1. /* ns83902End.c - National Semiconductor DP83902A ST-NIC */ 
  2. /* Copyright 1998-2002 Wind River Systems, Inc. */
  3. /* Copyright 1998-2000 Hitachi ULSI Systems Co.,LTD.,All Rights Reserved */
  4. /*
  5. modification history
  6. --------------------
  7. 01j,24apr02,h_k  changed dummy read to read from pDrvCtrl->ioPort (SPR #74019).
  8. 01i,25mar02,h_k  changed overrun handling to be done in ISR and transmit
  9.                  buffer taking from a static data (SPR #74019).
  10. 01h,14jan02,dat  Removing warnings from Diab compiler
  11. 01g,10oct01,dat  SPR 70829, driver used fp register - fixed., removed warnings,
  12.  fixed casts for netClFree, fixed macros
  13. 01f,03oct00,zl   ns83902Send() frees the Mblk chain in non-polled mode only.
  14. 01e,23may00,zl   minor code cleanup.
  15. 01d,29apr00,zl   redone TX interrupts, register read/write.
  16. 01c,21apr00,zl   call netMblkClChainFree only if TX succeeds, use TX interrupts
  17.                   instead of polling.
  18. 01b,10apr00,zl   renamed file to ns83902End.c
  19. 01a,20sep99,zl   written based on nicMsEnd.c and nicEvbEnd.c
  20. */
  21. /*
  22. This module implements the National Semiconductor dp83902A ST-NIC Ethernet
  23. network interface driver.
  24. This driver is moderately generic.  The driver must be given several 
  25. target-specific parameters.  These parameters, and the mechanisms used 
  26. to communicate them to the driver, are detailed below.
  27. The driver supports big-endian or little-endian architectures.
  28. EXTERNAL INTERFACE
  29. The only external interface is the ns83902EndLoad() routine, which expects
  30. the <initString> parameter as input.  This parameter passes in a 
  31. colon-delimited string of the format:
  32.  "<baseAdrs>:<intVec>:<intLvl>:<dmaPort>:<bufSize>:<options>"
  33. The ns83902EndLoad() 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 "baseAdrs"
  39. Base address at which the NIC hardware device registers are located.
  40. .IP "vecNum"
  41. This is the interrupt vector number of the hardware interrupt generated by
  42. this Ethernet device.
  43. .IP "intLvl"
  44. This parameter defines the level of the hardware interrupt.
  45. .IP "dmaPort"
  46. Address of the DMA port used to transfer data to the host CPU.
  47. .IP "bufSize"
  48. Size of the NIC buffer memory in bytes.
  49. .IP "options"
  50. Target specific options:
  51.     bit0 - wide (0: byte, 1: word)
  52.     bit1 - register interval (0: 1byte, 1: 2 bytes)
  53. EXTERNAL SUPPORT REQUIREMENTS
  54. This driver requires four external support functions, and provides a hook
  55. function:
  56. .iP "void sysLanIntEnable (int level)" "" 9 -1
  57. This routine provides a target-specific interface for enabling Ethernet device
  58. interrupts at a specified interrupt level.
  59. .iP "void sysLanIntDisable (void)" "" 9 -1
  60. This routine provides a target-specific interface for disabling Ethernet device
  61. interrupts.
  62. .iP "STATUS sysEnetAddrGet (int unit, char *enetAdrs)" "" 9 -1
  63. This routine provides a target-specific interface for accessing a device
  64. Ethernet address.
  65. .iP "sysNs83902DelayCount" "" 9 -1
  66. This variable is used to introduce at least a 4 bus cycle (BSCK) delay between
  67. successive NIC chip selects.
  68. SYSTEM RESOURCE USAGE
  69. This driver requires the following system resources:
  70.     - one mutual exclusion semaphore
  71.     - one interrupt vector
  72. SEE ALSO: muxLib,
  73. .I "DP83902A ST-NIC Serial Interface Controller for Twisted Pair"
  74. */
  75. /* configurations */
  76. #undef NS83902_INSTRUMENT /* instrument the driver */
  77. #undef NS83902_DEBUG /* log debug messages */
  78. /* includes */
  79. #include "vxWorks.h"
  80. #include "iv.h"
  81. #include "vme.h"
  82. #include "net/mbuf.h"
  83. #include "net/unixLib.h"
  84. #include "net/protosw.h"
  85. #include "sys/socket.h"
  86. #include "sys/ioctl.h"
  87. #include "errno.h"
  88. #include "memLib.h"
  89. #include "intLib.h"
  90. #include "net/route.h"
  91. #include "iosLib.h"
  92. #include "errnoLib.h"
  93. #include "logLib.h"
  94. #include "cacheLib.h"
  95. #include "netLib.h"
  96. #include "stdio.h"
  97. #include "stdlib.h"
  98. #include "sysLib.h"
  99. #include "etherLib.h"
  100. #include "net/systm.h"
  101. #include "sys/times.h"
  102. #include "net/if_subr.h"
  103. #include  "drv/end/ns83902End.h"
  104. #undef ETHER_MAP_IP_MULTICAST
  105. #include "etherMultiLib.h"
  106. #include "end.h"
  107. #include "endLib.h"
  108. #include "lstLib.h"
  109. #include "semLib.h"
  110. /* defines */
  111. #define NS83902_DEV_NAME "nic"
  112. #define NS83902_DEV_NAME_LEN 4
  113. #define NS83902_EADR_LEN 6
  114. #define NS83902_SPEED 10000000 /* 10Mbps or 100Mbps */
  115. #define NS83902_CRC_POLY 0x04c11db7
  116. #define IMR_DISABLE 0
  117. #define IMR_ENABLE (IMR_PRXE | IMR_OVWE | IMR_PTXE | IMR_TXEE)
  118. #define IMR_RX_DISABLE (IMR_OVWE | IMR_PTXE | IMR_TXEE)
  119. /* debug macros */
  120. #ifdef NS83902_DEBUG
  121. #ifdef LOCAL
  122. #undef LOCAL
  123. #define LOCAL
  124. #endif
  125. #define NS83902_DEBUG_OFF 0x0000
  126. #define NS83902_DEBUG_RX 0x0001
  127. #define NS83902_DEBUG_TX 0x0002
  128. #define NS83902_DEBUG_INT 0x0004
  129. #define NS83902_DEBUG_POLL (NS83902_DEBUG_POLL_RX | NS83902_DEBUG_POLL_TX)
  130. #define NS83902_DEBUG_POLL_RX 0x0008
  131. #define NS83902_DEBUG_POLL_TX 0x0010
  132. #define NS83902_DEBUG_LOAD 0x0020
  133. #define NS83902_DEBUG_IOCTL 0x0040
  134. #define NS83902_DEBUG_POLL_REDIR 0x10000
  135. #define NS83902_DEBUG_LOG_NVRAM 0x20000
  136. #define NS83902_DEBUG_MB 0x40000
  137. #define NS83902_DEBUG_TMP 0x80000
  138. int ns83902Debug = NS83902_DEBUG_OFF;
  139. NET_POOL   ns83902NetPool; /* global for easy access of end.pNetPool */
  140. void *     ns83902EndDevice; /* global for easy access of the device */
  141. CL_POOL_ID ns83902ClPoolId; /* global for easy access to cluster pool */
  142. SEM_ID     ns83902DmaSemId; /* global for easy access to sem ID */
  143. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  144.     if (ns83902Debug & FLG)
  145. logMsg(X0, X1, X2, X3, X4, X5, X6);
  146. #else /* NS83902_DEBUG */
  147. #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
  148. #endif /* NS83902_DEBUG */
  149. /*
  150.  * Default macro definitions for BSP interface.
  151.  * These macros can be redefined in a wrapper file, to generate
  152.  * a new module with an optimized interface.
  153.  */
  154. #ifndef SYS_INT_CONNECT
  155. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) 
  156.     do {
  157.     *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),
  158.      rtn, (int)arg); 
  159.     } while (0)
  160. #endif /* SYS_INT_CONNECT */
  161. #ifndef SYS_INT_DISCONNECT
  162. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) 
  163.     do { 
  164.     *pResult = OK; 
  165.     } while (0)
  166. #endif /* SYS_INT_DISCONNECT */
  167. #ifndef SYS_INT_ENABLE
  168. #define SYS_INT_ENABLE(pDrvCtrl) 
  169.     do { 
  170.     IMPORT void sysLanIntEnable(int);      
  171.     sysLanIntEnable (pDrvCtrl->ilevel);
  172.     } while (0)
  173. #endif /* SYS_INT_ENABLE */
  174. #ifndef SYS_INT_DISABLE
  175. #define SYS_INT_DISABLE(pDrvCtrl)                                       
  176.     do {                                                                
  177.     IMPORT STATUS sysLanIntDisable(int);
  178.     sysLanIntDisable(pDrvCtrl->ilevel);
  179.     } while (0)
  180. #endif /*SYS_INT_DISABLE*/
  181. #ifndef SYS_ENET_ADDR_GET
  182. #define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress) 
  183.     do { 
  184.     IMPORT STATUS sysEnetAddrGet (int, char*);
  185.     sysEnetAddrGet (pDrvCtrl->unit, pAddress); 
  186.     } while (0)
  187. #endif /* SYS_ENET_ADDR_GET */
  188. #ifndef SYS_NS83902_DELAY
  189. #define SYS_NS83902_DELAY() 
  190.     do {
  191.     IMPORT UINT32 sysNs83902DelayCount; 
  192.     volatile UINT32 cx = 0;
  193.     for (cx = 0; cx < sysNs83902DelayCount; cx++)
  194. /* spin */ ;  
  195.     } while (0)
  196. #endif /* SYS_NS83902_DELAY */
  197. #ifndef SYS_MS_DELAY
  198. #define SYS_MS_DELAY(delay)
  199.     do {
  200.     IMPORT void sysMsDelay (UINT);
  201.     sysMsDelay (delay);
  202.     } while (0)
  203. #endif /* SYS_MS_DELAY */
  204. #ifndef SYS_IN_SHORT
  205. #define SYS_IN_SHORT(pDrvCtrl,addr,data) 
  206.     do { 
  207.     ((data) = *((volatile USHORT *)(addr))); 
  208.     } while (0)
  209. #endif /* SYS_IN_SHORT*/
  210. #ifndef SYS_OUT_SHORT
  211. #define SYS_OUT_SHORT(pDrvCtrl,addr,value) 
  212.     do { 
  213.     *((volatile USHORT *)(addr)) = (value); 
  214.     } while (0)
  215. #endif /* SYS_OUT_SHORT */
  216. #ifndef SYS_IN_BYTE
  217. #define SYS_IN_BYTE(pDrvCtrl, addr, data) 
  218.     do { 
  219.     ((data) = *((volatile UCHAR *)(addr))); 
  220.     } while (0)
  221. #endif /* SYS_IN_BYTE */
  222. #ifndef SYS_OUT_BYTE
  223. #define SYS_OUT_BYTE(pDrvCtrl, addr, value) 
  224.     do { 
  225.     *((volatile UCHAR *)(addr)) = (value); 
  226.     } while (0)
  227. #endif /* SYS_OUT_BYTE */
  228. /* Setting/Getting on-chip registers */
  229. #define NS83902_CR_GET(pDrvCtrl, value)
  230.     do {
  231.     SYS_IN_BYTE ((pDrvCtrl),
  232.  ((pDrvCtrl)->pNic + 
  233.  (NS83902_CR) * (pDrvCtrl)->regInterval), 
  234.  (value));
  235.     SYS_NS83902_DELAY(); 
  236.     } while (0)
  237. #define NS83902_CR_SET(pDrvCtrl, value)
  238.     do { 
  239.     SYS_OUT_BYTE ((pDrvCtrl),
  240.   ((pDrvCtrl)->pNic + 
  241.   (NS83902_CR) * (pDrvCtrl)->regInterval), 
  242.   (value));
  243.     SYS_NS83902_DELAY(); 
  244.     } while (0)
  245. #define NS83902_REG_GET(pDrvCtrl, reg, value, page) 
  246.     (value = ns83902RegRead (pDrvCtrl, reg, page))
  247. #define NS83902_REG_SET(pDrvCtrl, reg, value, page)
  248.     (ns83902RegSet (pDrvCtrl, reg, value, page))
  249. /* Macros for dealing with flags */
  250. #define DRV_FLAGS_SET(setBits)                                          
  251.     (pDrvCtrl->flags |= (setBits))
  252. #define DRV_FLAGS_ISSET(setBits)                                        
  253.     (pDrvCtrl->flags & (setBits))
  254. #define DRV_FLAGS_CLR(clrBits)                                          
  255.     (pDrvCtrl->flags &= ~(clrBits))
  256. #define DRV_FLAGS_GET()                                                 
  257.     (pDrvCtrl->flags)
  258. #define NS83902_IS_IN_POLL_MODE()
  259.     ((DRV_FLAGS_GET() & NS83902_FLAG_POLL) == NS83902_FLAG_POLL)
  260. #define NS83902_SEM_TAKE(pDrvCtrl, timeout)
  261.     semTake ((pDrvCtrl)->endObj.txSem, timeout)
  262. #define NS83902_SEM_GIVE(pDrvCtrl)
  263.     semGive((pDrvCtrl)->endObj.txSem)
  264. /* A shortcut for getting the hardware address from the MIB II stuff. */
  265. #define END_HADDR(pEnd)
  266.     ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  267. #define END_HADDR_LEN(pEnd) 
  268.     ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  269. #define END_FLAGS_ISSET(pEnd, setBits) 
  270.     ((pEnd)->flags & (setBits))
  271. /*
  272.  * Macros for read and write descriptors.
  273.  *
  274.  */
  275. #define NS83902_RX_BUF_SZ sizeof(NS83902_RX_FRAME)
  276. #define NS83902_RX_HDR_SZ sizeof(NS83902_RX_HDR)
  277. #define NS83902_ETH_CRC_LEN 4
  278. /* typedefs */
  279. typedef struct rx_hdr
  280.     {
  281. #if (_BYTE_ORDER == _BIG_ENDIAN)
  282.     UINT8 nextRxPage; /* page next pkt starts at */
  283.     UINT8 status; /* status of packet */
  284. #else
  285.     UINT8 status; /* status of packet */
  286.     UINT8 nextRxPage; /* page next pkt starts at */
  287. #endif
  288.     UINT16       count;          /* frame length */
  289.     } NS83902_RX_HDR;
  290. typedef struct rx_frame
  291.     {
  292.     UINT16 pad1;
  293.     NS83902_RX_HDR rxHdr; /* receive status header */
  294.     ENET_HDR enetHdr; /* ethernet header */
  295.     UINT8 data[ETHERMTU]; /* frame data */
  296.     } NS83902_RX_FRAME;
  297. typedef char* NS83902_CLUSTER;
  298. typedef struct ns83902_end_device /* driver control structure */
  299.     {
  300.     END_OBJ endObj; /* The class we inherit from. */
  301.     END_ERR lastError; /* Last error passed to muxError */
  302.     int unit; /* unit number */
  303.     int rringSize; /* RMD ring size */
  304.     UCHAR enetAddr[NS83902_EADR_LEN]; /* ethernet address */
  305.     char* pNic; /* address of NIC chip */
  306.     char* ioPort; /* port address of remote DMA */
  307.     NS83902_CLUSTER pCluster; /* Rx frame memory */
  308.     CL_POOL_ID pClPoolId; /* cluster pool */
  309.     int regInterval; /* address diff of adjacent regs */
  310.     BOOL wide; /* I/O port is 16 bit (when TRUE) */
  311.     int          ivec; /* interrupt vector */
  312.     int ilevel; /* interrupt level */
  313.     UINT8 regPage; /* current register page */
  314.     UINT8 txStartPage; /* ptr to Tx start buffer */
  315.     UINT8 rxStartPage; /* ptr to Rx start buffer */
  316.     UINT8 rxStopPage; /* ptr to Rx stop buffer */
  317.     UINT8 nextPage; /* ptr to next page */
  318.     NS83902_DRV_FLAG flags; /* device specific flags */
  319.     BOOL rxHandling; /* rcv task is scheduled */
  320.     BOOL txBlocked; /* to implement flow control */
  321.     BOOL rxOvw; /* overwrite warning */
  322.     BOOL txResend; /* resend need at overwrite */
  323.     } NS83902_END_DEVICE;
  324. /* network buffers configuration */
  325. M_CL_CONFIG ns83902MclBlkConfig =  /* network mbuf configuration table */
  326.     {
  327.     /* 
  328.     no. mBlks no. clBlks memArea memSize
  329.     --------- ---------- ------- -------
  330.     */
  331.     0,  0,  NULL,  0
  332.     };
  333. CL_DESC ns83902ClDescTbl [] = /* cluster pool configuration table */
  334.     {
  335.     /* 
  336.     clSize num memArea memSize
  337.     ------ ---- ------- -------
  338.     */
  339.     {0, 0, NULL, 0}
  340.     }; 
  341. int ns83902ClDescTblNumEnt = (NELEMENTS(ns83902ClDescTbl));
  342. /* globals */
  343. #ifdef NS83902_INSTRUMENT
  344. UINT32  ns83902TxTimeout = 0;   /* number of transmit time-out */
  345. UINT32  ns83902TxError = 0;     /* number of transmit errors */
  346. UINT32 ns83902RestartNb = 0; /* number of restart due to ring overflow */
  347. UINT32 ns83902InitNb = 0; /* number of time device is re-initialized */
  348. UINT32 ns83902TxNb = 0; /* number of transmitted packets */
  349. UINT32 ns83902IntNb = 0; /* number of receive interrupt */
  350. UINT32 ns83902Len = 0; /* lenght of the current received packet */
  351. UINT32 ns83902HdrStat = 0; /* status byte of the current received packet */
  352. UINT32 ns83902NextPage = 0; /* page pointer to the next received packet */
  353. UINT32 ns83902CurrentPage = 0; /* start page of the current packet */
  354. #endif
  355. /* forward declarations */
  356. LOCAL void  ns83902MARSet (NS83902_END_DEVICE* pDrvCtrl, UINT8 index, 
  357.        BOOL bSet);
  358. LOCAL STATUS  ns83902AddrFilterSet (NS83902_END_DEVICE *pDrvCtrl, 
  359.       char* pAddr, BOOL bSet);
  360. LOCAL int ns83902HashIndex (char* eAddr);
  361. LOCAL void ns83902Int (NS83902_END_DEVICE* pDrvCtrl);
  362. LOCAL void ns83902Restart (NS83902_END_DEVICE *pDrvCtrl, UINT8 cr);
  363. LOCAL void ns83902HandleInt (NS83902_END_DEVICE *pDrvCtrl);
  364. LOCAL void ns83902Recv (NS83902_END_DEVICE *pDrvCtrl,
  365.      NS83902_CLUSTER pCluster);
  366. LOCAL NS83902_CLUSTER ns83902ReadFrame (NS83902_END_DEVICE* pDrvCtrl);
  367. LOCAL void  ns83902Config (NS83902_END_DEVICE* pDrvCtrl);
  368. LOCAL STATUS ns83902PktBufRead (NS83902_END_DEVICE *pDrvCtrl, UINT32
  369.                                   ns83902BufAddr, UINT32 len, char *pData);
  370. LOCAL STATUS ns83902Transmit (NS83902_END_DEVICE *pDrvCtrl, M_BLK* pMblk);
  371. LOCAL void ns83902ReadPort (NS83902_END_DEVICE* pDrvCtrl, 
  372.  char *pBuf, int len);
  373. LOCAL void  ns83902WritePort (NS83902_END_DEVICE* pDrvCtrl, 
  374.   char *pBuf, int len);
  375. LOCAL STATUS  ns83902InitParse (NS83902_END_DEVICE* pDrvCtrl, 
  376.   char * initString);
  377. LOCAL STATUS  ns83902InitMem (NS83902_END_DEVICE* pDrvCtrl);
  378. LOCAL void ns83902EnetAddrGet (NS83902_END_DEVICE* pDrvCtrl, char* addr);
  379. LOCAL void  ns83902RegSet (NS83902_END_DEVICE* pDrvCtrl, int reg, 
  380.        int value, int page);
  381. LOCAL UINT8  ns83902RegRead (NS83902_END_DEVICE* pDrvCtrl, int reg, 
  382.        int page);
  383. /* END Specific interfaces. */
  384. END_OBJ * ns83902EndLoad (char *initString);
  385. LOCAL STATUS ns83902Unload (NS83902_END_DEVICE* pDrvCtrl);
  386. LOCAL STATUS ns83902Start (NS83902_END_DEVICE* pDrvCtrl);
  387. LOCAL STATUS ns83902Stop (NS83902_END_DEVICE* pDrvCtrl);
  388. LOCAL int ns83902Ioctl (NS83902_END_DEVICE* pDrvCtrl, int cmd, 
  389.       caddr_t data);
  390. LOCAL STATUS ns83902Send (NS83902_END_DEVICE* pDrvCtrl, M_BLK *pMblk);
  391. LOCAL STATUS ns83902MCastAddrAdd (NS83902_END_DEVICE *pDrvCtrl, 
  392.      char* pAddress);
  393. LOCAL STATUS ns83902MCastAddrDel (NS83902_END_DEVICE *pDrvCtrl, 
  394.      char* pAddress);
  395. LOCAL STATUS ns83902MCastAddrGet (NS83902_END_DEVICE *pDrvCtrl, 
  396.                                      MULTI_TABLE *pTable);
  397. LOCAL STATUS ns83902PollSend (NS83902_END_DEVICE *pDrvCtrl, M_BLK *pMblk);
  398. LOCAL STATUS ns83902PollReceive (NS83902_END_DEVICE *pDrvCtrl, M_BLK *pMblk);
  399. LOCAL STATUS ns83902PollStart (NS83902_END_DEVICE *pDrvCtrl);
  400. LOCAL STATUS ns83902PollStop (NS83902_END_DEVICE *pDrvCtrl);
  401. /*
  402.  * Declare our function table.  This is static across all driver
  403.  * instances.
  404.  */
  405. LOCAL NET_FUNCS ns83902FuncTable =
  406.     {
  407.     (FUNCPTR)ns83902Start, /* Function to start the device. */
  408.     (FUNCPTR)ns83902Stop, /* Function to stop the device. */
  409.     (FUNCPTR)ns83902Unload, /* Unloading function */
  410.     (FUNCPTR)ns83902Ioctl, /* Ioctl function */
  411.     (FUNCPTR)ns83902Send, /* Send function */
  412.     (FUNCPTR)ns83902MCastAddrAdd, /* Multicast address add */
  413.     (FUNCPTR)ns83902MCastAddrDel, /* Multicast address delete */
  414.     (FUNCPTR)ns83902MCastAddrGet, /* Multicast table retrieve */
  415.     (FUNCPTR)ns83902PollSend, /* Polling send function  */
  416.     (FUNCPTR)ns83902PollReceive, /* Polling receive function */
  417.     endEtherAddressForm, /* Put address info into a packet.  */
  418.     endEtherPacketDataGet, /* Get a pointer to packet data. */
  419.     endEtherPacketAddrGet, /* Get packet addresses. */
  420.     NULL /* Bind function */
  421.     };
  422. /******************************************************************************
  423. *
  424. * ns83902EndLoad - initialize the driver and device
  425. *
  426. * This routine initializes the driver and the device to the operational state.
  427. * All of the device-specific parameters are passed in <initString>.
  428. * This routine can be called in two modes. If it is called with an empty but
  429. * allocated string, it places the name of this device (that is, "ln") into 
  430. * the <initString> and returns 0.
  431. *
  432. * If the string is allocated and not empty, the routine attempts to load
  433. * the driver using the values specified in the string.
  434. *
  435. * RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
  436. * device if the <initString> was NULL.
  437. */
  438. END_OBJ* ns83902EndLoad
  439.     (
  440.     char* initString /* string to be parsed */
  441.     )
  442.     {
  443.     NS83902_END_DEVICE *pDrvCtrl;
  444.     DRV_LOG (NS83902_DEBUG_LOAD, "Loading ns83902End...n", 1, 2, 3, 4, 5, 6);
  445.     if (initString == NULL)
  446.         return (NULL);
  447.     
  448.     if (initString[0] == '')
  449.         {
  450.         bcopy((char *)NS83902_DEV_NAME, initString, NS83902_DEV_NAME_LEN);
  451.         return (0);
  452.         }
  453.     
  454.     /* allocate the device structure */
  455.     pDrvCtrl = (NS83902_END_DEVICE *)calloc (sizeof (NS83902_END_DEVICE), 1);
  456.     if (pDrvCtrl == NULL)
  457. goto errorExit;
  458.     /* parse the init string, filling in the device structure */
  459.     if (ns83902InitParse (pDrvCtrl, initString) == ERROR)
  460. goto errorExit;
  461.     
  462.     /* Have the BSP hand us our address. */
  463.     ns83902EnetAddrGet (pDrvCtrl, (char*) &(pDrvCtrl->enetAddr));
  464.     DRV_LOG (NS83902_DEBUG_LOAD, "ENET Addr: %x:%x:%x:%x:%x:%x n",
  465.              pDrvCtrl->enetAddr[0], pDrvCtrl->enetAddr[1], 
  466.      pDrvCtrl->enetAddr[2], pDrvCtrl->enetAddr[3], 
  467.      pDrvCtrl->enetAddr[4], pDrvCtrl->enetAddr[5]);
  468.     /* initialize the END and MIB2 parts of the structure */
  469.     if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, NS83902_DEV_NAME,
  470.     pDrvCtrl->unit, &ns83902FuncTable,
  471.                       "ST-NIC Enhanced Network Driver") == ERROR
  472.      || END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
  473.                       &pDrvCtrl->enetAddr[0], NS83902_EADR_LEN, ETHERMTU,
  474.                       NS83902_SPEED)
  475.     == ERROR)
  476. goto errorExit;
  477.     /* set buffer address; reserve 8 pages for TX */
  478.     pDrvCtrl->txStartPage = 0;
  479.     pDrvCtrl->rxStartPage = pDrvCtrl->txStartPage + 8;
  480.     pDrvCtrl->nextPage    = pDrvCtrl->rxStartPage;
  481.     /* size of the whole ring */
  482.     pDrvCtrl->rringSize = pDrvCtrl->rxStopPage - pDrvCtrl->rxStartPage + 1;
  483.     /* Perform memory allocation */
  484.     if (ns83902InitMem (pDrvCtrl) == ERROR)
  485. {
  486. DRV_LOG (NS83902_DEBUG_LOAD, "Error in InitMem...n", 1, 2, 3, 4, 5, 6);
  487. goto errorExit;
  488. }
  489.     /* set the flags to indicate readiness */
  490.     END_OBJ_READY (&pDrvCtrl->endObj,
  491.                    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
  492.     
  493.     DRV_LOG (NS83902_DEBUG_LOAD, "Done loading ns83902End...n", 1, 2, 3, 4, 5, 6);
  494.     /* save the device address */
  495. #ifdef NS83902_DEBUG
  496.     ns83902EndDevice = pDrvCtrl;
  497.     ns83902DmaSemId  = pDrvCtrl->endObj.txSem;
  498. #endif
  499.     return (&pDrvCtrl->endObj);
  500. errorExit:
  501.     ns83902Unload (pDrvCtrl);
  502.     return NULL;
  503.     }
  504. /*******************************************************************************
  505. *
  506. * ns83902InitParse - parse the initialization string
  507. *
  508. * Parse the input string and fill in values in the driver control structure.
  509. *
  510. * RETURNS: OK, or ERROR if any arguments are invalid.
  511. */
  512. LOCAL STATUS ns83902InitParse
  513.     (
  514.     NS83902_END_DEVICE * pDrvCtrl,
  515.     char * initString
  516.     )
  517.     {
  518.     char * tok;
  519.     char * pHolder = NULL;
  520.     long address;
  521.     UINT8 options;
  522.     
  523.     /* Parse the initString */
  524.     /* Unit number. */
  525.     tok = strtok_r (initString, ":", &pHolder);
  526.     if (tok == NULL)
  527. return ERROR;
  528.     pDrvCtrl->unit = atoi (tok);
  529.     /* NIC address. */
  530.     
  531.     tok = strtok_r (NULL, ":", &pHolder);
  532.     if (tok == NULL)
  533. return ERROR;
  534.     address = strtoul (tok, NULL, 16);
  535.     pDrvCtrl->pNic = (char*) address;
  536.     /* Interrupt vector. */
  537.     tok = strtok_r (NULL, ":", &pHolder);
  538.     if (tok == NULL)
  539. return ERROR;
  540.     pDrvCtrl->ivec = atoi (tok);
  541.     /* Interrupt level. */
  542.     tok = strtok_r (NULL, ":", &pHolder);
  543.     if (tok == NULL)
  544. return ERROR;
  545.     pDrvCtrl->ilevel = atoi (tok);
  546.     /* Remote DMA I/O address. */
  547.     tok = strtok_r (NULL, ":", &pHolder);
  548.     if (tok == NULL)
  549. return ERROR;
  550.     pDrvCtrl->ioPort = (char *) strtoul (tok, NULL, 16);
  551.     /* Get ring buffer size in pages */
  552.     tok = strtok_r (NULL, ":", &pHolder);
  553.     if (tok == NULL)
  554. return ERROR;
  555.     pDrvCtrl->rxStopPage = strtoul (tok, NULL, 16) / NS83902_PAGE_SIZE;
  556.     /* Get target options */
  557.     tok = strtok_r (NULL, ":", &pHolder);
  558.     if (tok == NULL)
  559. return ERROR;
  560.     options = strtoul (tok, NULL, 16);
  561.     pDrvCtrl->wide = options & NS83902_WIDE_MASK;
  562.     pDrvCtrl->regInterval = 1 << ((options & NS83902_INTERVAL_MASK) >> 1);
  563.     DRV_LOG (NS83902_DEBUG_LOAD, "Processed all arugmentsn", 1, 2, 3, 4, 5, 6);
  564.     DRV_LOG (NS83902_DEBUG_LOAD, "Address %p Lvl %u Vec %d Port %p Ring %p n",
  565.                (int)pDrvCtrl->pNic, pDrvCtrl->ilevel, pDrvCtrl->ivec, 
  566.        (int)pDrvCtrl->ioPort, pDrvCtrl->rxStopPage, 6);    
  567.     DRV_LOG (NS83902_DEBUG_LOAD, "Transfer width: %s n", 
  568.                (int)(pDrvCtrl->wide ? "word":"byte"), 2, 3, 4, 5, 6);
  569.     DRV_LOG (NS83902_DEBUG_LOAD, "Register interval: %d n", 
  570.        pDrvCtrl->regInterval, 2, 3, 4, 5, 6);
  571.     return OK;
  572.     }
  573. /*******************************************************************************
  574. *
  575. * ns83902InitMem - initialize memory for NIC chip
  576. *
  577. * Using data in the control structure, setup and initialize the memory
  578. * areas needed.  If the memory address is not already specified, then allocate
  579. * cache safe memory.
  580. *
  581. * RETURNS: OK or ERROR.
  582. */
  583. LOCAL STATUS ns83902InitMem
  584.     (
  585.     NS83902_END_DEVICE * pDrvCtrl /* device to be initialized */
  586.     )
  587.     {
  588.     /* allocate netpool */
  589.     if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  590.         return (ERROR);
  591.     /* Set number of M-Blks and CL-Blks*/
  592.     ns83902MclBlkConfig.mBlkNum = pDrvCtrl->rringSize;
  593.     ns83902MclBlkConfig.clBlkNum= pDrvCtrl->rringSize / 2;
  594.     ns83902ClDescTbl[0].clNum = ns83902MclBlkConfig.clBlkNum;
  595.     /* Calculate the total memory for all the M-Blks and CL-Blks. */
  596.     ns83902MclBlkConfig.memSize = ns83902MclBlkConfig.mBlkNum * 
  597.    (MSIZE + sizeof (long)) +
  598.   ns83902MclBlkConfig.clBlkNum * 
  599.    (CL_BLK_SZ + sizeof(long));
  600.     /* allocate memory for M-Blks and CL-Blks */
  601.     ns83902MclBlkConfig.memArea = (char *) memalign (sizeof(long),
  602.    ns83902MclBlkConfig.memSize);
  603.     if (ns83902MclBlkConfig.memArea == NULL)
  604. return (ERROR);
  605.     
  606.     /* Calculate the memory size of all the clusters. */
  607.     ns83902ClDescTbl[0].clSize  = NS83902_RX_BUF_SZ;
  608.     ns83902ClDescTbl[0].memSize = sizeof(long) + ns83902ClDescTbl[0].clNum * 
  609.   (ns83902ClDescTbl[0].clSize + 8);
  610.     /* Allocate memory for clusters */
  611.     ns83902ClDescTbl[0].memArea = (char *) memalign (sizeof(long),
  612.    ns83902ClDescTbl[0].memSize);
  613.    
  614.     if (ns83902ClDescTbl[0].memArea == NULL)
  615. {
  616. DRV_LOG (NS83902_DEBUG_LOAD, "system memory unavailablen", 
  617.  1, 2, 3, 4, 5, 6);
  618. return (ERROR);
  619. }
  620.     /* Save clusters start address for later use */
  621.     pDrvCtrl->pCluster = (NS83902_CLUSTER) ns83902ClDescTbl[0].memArea;
  622.     /* Initialize the net buffer pool with buffers */
  623.     if (netPoolInit (pDrvCtrl->endObj.pNetPool, &ns83902MclBlkConfig, 
  624.      &ns83902ClDescTbl[0], ns83902ClDescTblNumEnt, NULL) == ERROR)
  625. {
  626. DRV_LOG (NS83902_DEBUG_LOAD, "Could not init bufferingn",
  627.  1, 2, 3, 4, 5, 6);
  628. return (ERROR);
  629. }
  630.     
  631.     /* Store the cluster pool id as others need it later. */
  632.     pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool, 
  633.   NS83902_RX_BUF_SZ, FALSE);
  634.     if (pDrvCtrl->pClPoolId  == NULL)
  635. return (ERROR);
  636. #ifdef NS83902_DEBUG
  637.     ns83902NetPool = *pDrvCtrl->endObj.pNetPool;
  638.     ns83902ClPoolId = pDrvCtrl->pClPoolId;
  639. #endif
  640.     return (OK);
  641.     }
  642. /*******************************************************************************
  643. *
  644. * ns83902Start - start the device
  645. *
  646. * This function calls BSP functions to connect interrupts and start the
  647. * device running in interrupt mode.
  648. *
  649. * RETURNS: OK or ERROR
  650. *
  651. */
  652. LOCAL STATUS ns83902Start
  653.     (
  654.     NS83902_END_DEVICE *pDrvCtrl
  655.     )
  656.     {
  657.     STATUS result;
  658.     /* Clear statuses */
  659.     pDrvCtrl->rxHandling = FALSE;
  660.     pDrvCtrl->txBlocked = FALSE;
  661.     pDrvCtrl->rxOvw = FALSE;
  662.     pDrvCtrl->txResend = FALSE;
  663.     
  664.     /* reset the device */
  665.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
  666.     /* connect interrupt handler */
  667.     SYS_INT_CONNECT (pDrvCtrl, ns83902Int, (int)pDrvCtrl, &result);
  668.     if (result == ERROR)
  669. return ERROR;
  670.     DRV_LOG (NS83902_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
  671.     /* device config */
  672.     ns83902Config (pDrvCtrl);
  673.     /* mark the interface -- up */
  674.     END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  675.     
  676.     SYS_INT_ENABLE (pDrvCtrl);
  677.     DRV_LOG (NS83902_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
  678.     return (OK);
  679.     }
  680. /*******************************************************************************
  681. *
  682. * ns83902Config - configure the NIC chip and program address
  683. *
  684. * This routine follows the algorythm in the ST-NIC manual for enabling
  685. * a NIC device on an active network.  Essentially, this routine initializes
  686. * the NIC device.
  687. *
  688. * RETURNS: N/A.
  689. */
  690. LOCAL void ns83902Config
  691.     (
  692.     NS83902_END_DEVICE * pDrvCtrl /* device to be configured */    
  693.     )
  694.     {
  695.     UCHAR* pEnetAddr = pDrvCtrl->enetAddr;
  696.     UCHAR dcr;
  697.     /* Page 0 */
  698.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
  699.     /* Enable broadcast, Endian, Word Size */
  700. #if (_BYTE_ORDER == _BIG_ENDIAN)
  701.     dcr = DCR_NOTLS | DCR_FIFO8 | DCR_BOS;
  702. #else
  703.     dcr = DCR_NOTLS | DCR_FIFO8;
  704. #endif
  705.     if (pDrvCtrl->wide == TRUE)  
  706. dcr |= DCR_WTS;
  707.     NS83902_REG_SET (pDrvCtrl, NS83902_DCR, dcr, CR_RPAGE0);
  708.     /* Clear the remote byte count reg. */
  709.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 0, CR_RPAGE0);
  710.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0);
  711.     /* Set to monitor and loopback mode */
  712.     NS83902_REG_SET (pDrvCtrl, NS83902_RCR, RCR_MON, CR_RPAGE0);
  713.     NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE1, CR_RPAGE0);
  714.     /* Accept Broadcast */
  715.     NS83902_REG_SET (pDrvCtrl, NS83902_RCR, (RCR_AB | RCR_AM), CR_RPAGE0);
  716.     /* Set the transmit page and receive page */
  717.     NS83902_REG_SET (pDrvCtrl, NS83902_PSTART, pDrvCtrl->rxStartPage, CR_RPAGE0);
  718.     NS83902_REG_SET (pDrvCtrl, NS83902_PSTOP, pDrvCtrl->rxStopPage, CR_RPAGE0);
  719.     NS83902_REG_SET (pDrvCtrl, NS83902_TPSR, pDrvCtrl->txStartPage, CR_RPAGE0);
  720.     NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, pDrvCtrl->rxStopPage - 1, CR_RPAGE0);
  721.     /* Clear the pending interrupts and mask. */
  722.     NS83902_REG_SET (pDrvCtrl, NS83902_ISR, 0xff, CR_RPAGE0);
  723.     NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);
  724.     /* set MAC Address */
  725.     NS83902_REG_SET (pDrvCtrl, NS83902_PAR0, pEnetAddr [0], CR_RPAGE1);
  726.     NS83902_REG_SET (pDrvCtrl, NS83902_PAR1, pEnetAddr [1], CR_RPAGE1);
  727.     NS83902_REG_SET (pDrvCtrl, NS83902_PAR2, pEnetAddr [2], CR_RPAGE1);
  728.     NS83902_REG_SET (pDrvCtrl, NS83902_PAR3, pEnetAddr [3], CR_RPAGE1);
  729.     NS83902_REG_SET (pDrvCtrl, NS83902_PAR4, pEnetAddr [4], CR_RPAGE1);
  730.     NS83902_REG_SET (pDrvCtrl, NS83902_PAR5, pEnetAddr [5], CR_RPAGE1);
  731.     /* Initialize the multicast list to accept all. */
  732.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR0, 0x00, CR_RPAGE1);
  733.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR1, 0x00, CR_RPAGE1);
  734.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR2, 0x00, CR_RPAGE1);
  735.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR3, 0x00, CR_RPAGE1);
  736.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR4, 0x00, CR_RPAGE1);
  737.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR5, 0x00, CR_RPAGE1);
  738.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR6, 0x00, CR_RPAGE1);
  739.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR7, 0x00, CR_RPAGE1);
  740.     NS83902_REG_SET (pDrvCtrl, NS83902_CURR, pDrvCtrl->rxStartPage, CR_RPAGE1);
  741.     /* Page 0 */
  742.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
  743.     /* set the interrupt mask */
  744.     NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_ENABLE, CR_RPAGE0);
  745.     /* Start */
  746.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_ABORT | CR_STA, CR_RPAGE0);
  747.     NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE0, CR_RPAGE0);
  748.     }
  749. /*******************************************************************************
  750. *
  751. * ns83902EnetAddrGet - get the Ethernet address.
  752. *
  753. * Get ethernet address from the BSP.
  754. *
  755. * RETURNS: N/A.
  756. */
  757. LOCAL void ns83902EnetAddrGet
  758.     (
  759.     NS83902_END_DEVICE* pDrvCtrl, 
  760.     char* addr
  761.     )
  762.     {
  763. #if _BYTE_ORDER == _BIG_ENDIAN
  764.     /* For big endian we need to swap byte order */
  765.     int i;
  766.     char  bytes[6];
  767.     SYS_ENET_ADDR_GET (pDrvCtrl, bytes);
  768.     for (i=0; i<6; i++)
  769. *addr++ = bytes[5-i];
  770. #else  /* _BYTE_ORDER == _LITTLE_ENDIAN  */
  771.     /* Little endian is in correct order */
  772.     SYS_ENET_ADDR_GET (pDrvCtrl, addr);
  773. #endif /* _BYTE_ORDER == _BIG_ENDIAN */
  774.     }
  775. /*******************************************************************************
  776. *
  777. * ns83902WritePort - write to the DMA port
  778. *
  779. * RETURNS: N/A.
  780. */
  781. LOCAL void ns83902WritePort
  782.     (
  783.     NS83902_END_DEVICE* pDrvCtrl,    
  784.     char * pBuf,
  785.     int len
  786.     )
  787.     {
  788.     int ix;
  789.     UINT16 *  pWide;
  790.     if (pDrvCtrl->wide == TRUE)
  791. {
  792. len = (++len) >> 1;
  793. pWide = (UINT16 *) pBuf;
  794. for (ix = 0 ; ix < len; ix++)
  795.     {
  796.     SYS_OUT_SHORT (pDrvCtrl, pDrvCtrl->ioPort, *pWide++);
  797.     SYS_NS83902_DELAY();
  798.     }
  799. }
  800.     else
  801. {
  802. for (ix = 0 ; ix < len; ix++)
  803.     {
  804.     SYS_OUT_BYTE (pDrvCtrl, pDrvCtrl->ioPort, *pBuf++);
  805.     SYS_NS83902_DELAY();
  806.     }
  807. }
  808.     }    
  809. /*******************************************************************************
  810. *
  811. * ns83902ReadPort - read the DMA port
  812. *
  813. * RETURNS: N/A.
  814. */
  815. LOCAL void ns83902ReadPort
  816.     (
  817.     NS83902_END_DEVICE* pDrvCtrl,    
  818.     char * pBuf,
  819.     int len
  820.     )
  821.     {
  822.     int  ix;
  823.     UINT16 *  pWide;
  824.     if (pDrvCtrl->wide == TRUE)
  825. {
  826. len = (++len) >> 1;
  827. pWide = (UINT16 *) pBuf;
  828. for (ix = 0 ; ix < len; ix++)
  829.     {
  830.     SYS_IN_SHORT (pDrvCtrl, pDrvCtrl->ioPort, *pWide++);
  831.     }
  832. }
  833.     else
  834. {
  835. for (ix = 0 ; ix < len; ix++)
  836.     {
  837.     SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, *pBuf++);
  838.     }
  839. }
  840.     }    
  841. /*******************************************************************************
  842. *
  843. * ns83902PktBufRead - read data from the NIC receive ring buffer
  844. *
  845. * This routine gets exclusive access to the remote DMA, and gets data from 
  846. * the NIC's receive ring buffer.
  847. *
  848. * RETURNS: OK, or ERROR if obtaining the requested bytes encountered an error.
  849. */
  850. LOCAL STATUS ns83902PktBufRead
  851.     (
  852.     NS83902_END_DEVICE* pDrvCtrl,
  853.     UINT32 ns83902BufAddr,
  854.     UINT32 len,
  855.     char* pData
  856.     )
  857.     {
  858.     /* Exclusive DMA access */
  859.     if (!NS83902_IS_IN_POLL_MODE())
  860. NS83902_SEM_TAKE (pDrvCtrl, WAIT_FOREVER);
  861.     DRV_LOG (NS83902_DEBUG_RX, 
  862.      "ns83902Receive: ns83902BufAddr:%u pData:%p len:%dn",
  863.              ns83902BufAddr, (int)pData, len, 4, 5, 6);        
  864.     
  865.     /* Set up remote read DMA transfer */
  866.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, LSB(len), CR_RPAGE0);
  867.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, MSB(len), CR_RPAGE0);
  868.     NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, LSB(ns83902BufAddr), CR_RPAGE0);
  869.     NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, MSB(ns83902BufAddr), CR_RPAGE0);
  870.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RREAD, CR_RPAGE0);
  871.     /* Get data through DMA port */
  872.     ns83902ReadPort (pDrvCtrl, pData, len);
  873.     if (!NS83902_IS_IN_POLL_MODE())
  874. NS83902_SEM_GIVE (pDrvCtrl);
  875.     return (OK);
  876.     }
  877. /*******************************************************************************
  878. *
  879. * ns83902ReadFrame - read a packet off the interface ring buffer into a cluster
  880. *
  881. * Allocates a new cluster from the cluster pool, and reads the frame from the
  882. * device into the cluster.
  883. *
  884. * RETURNS: a cluster or NULL if any error
  885. */
  886. LOCAL NS83902_CLUSTER ns83902ReadFrame
  887.     (
  888.     NS83902_END_DEVICE* pDrvCtrl
  889.     )
  890.     {
  891.     NS83902_RX_FRAME* pRx;
  892.     NS83902_CLUSTER pRetCluster = NULL;
  893.     UINT32 frameAddress;
  894.     UINT16 len; /* len of Rx pkt */
  895.     UINT8 bnry;
  896.     UINT8 rsr;
  897.     UINT8 cur;
  898.     /* Check receive status */
  899.     NS83902_REG_GET (pDrvCtrl, NS83902_RSR, rsr, CR_RPAGE0);
  900.     if ((rsr & RSR_PRX) != RSR_PRX)
  901.         return (pRetCluster);
  902.     NS83902_REG_GET (pDrvCtrl, NS83902_CURR, cur, CR_RPAGE1);
  903.     if (!(END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) ||
  904.         (pDrvCtrl->nextPage == cur))
  905.         return (pRetCluster);
  906.     DRV_LOG (NS83902_DEBUG_RX, "Start Read!n", 1, 2, 3, 4, 5, 6);
  907.     /*
  908.      * There is work to be done.
  909.      * First we copy the NIC receive status header from the NIC buffer
  910.      * into our local area. This is done so that we can obtain the length
  911.      * of the packet before copying out the rest of it. Note that the length
  912.      * field in the NIC header includes the Ethernet header, the data, and
  913.      * the 4 byte FCS field.
  914.      */
  915.     /* Get a cluster */
  916.     if ((pRx = (NS83902_RX_FRAME*) netClusterGet (pDrvCtrl->endObj.pNetPool,
  917.                                            pDrvCtrl->pClPoolId)) == NULL)
  918.         {
  919. pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  920. muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);
  921.         DRV_LOG (NS83902_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
  922.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  923.         return (pRetCluster);
  924.         }
  925.     
  926.     /* read header */
  927.     DRV_LOG (NS83902_DEBUG_RX, "ns83902PktBufRead : Reading Headern", 
  928.      1, 2, 3, 4, 5, 6);
  929.     if (ns83902PktBufRead (pDrvCtrl, pDrvCtrl->nextPage << 8,
  930.                           (NS83902_RX_HDR_SZ), (char *) &pRx->rxHdr) == ERROR)
  931.         {
  932.         DRV_LOG (NS83902_DEBUG_RX,
  933.                  "ns83902PktBufRead could not read packet headern",
  934.                  0, 0, 0, 0, 0, 0);
  935. netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
  936.         return (pRetCluster);
  937.         }
  938.     /* Calculate real length */
  939.     len = pRx->rxHdr.count;
  940. #if (_BYTE_ORDER == _BIG_ENDIAN)
  941.     len = ((len >> 8) & 0x00ff) + ((len << 8) & 0xff00) - NS83902_ETH_CRC_LEN;
  942. #else
  943.     len = len - NS83902_ETH_CRC_LEN;
  944. #endif
  945.     /* write back value to rxHdr */
  946.     pRx->rxHdr.count = len;
  947.     /* Current frame address and next page */
  948.     frameAddress = (pDrvCtrl->nextPage << 8) + NS83902_RX_HDR_SZ;
  949.     pDrvCtrl->nextPage = pRx->rxHdr.nextRxPage;
  950.    
  951.     /* valid frame checks */
  952. #ifdef NS83902_INSTRUMENT
  953.     ns83902Len = len;
  954.     ns83902HdrStat = pRx->rxHdr.status;
  955.     ns83902NextPage = pRx->rxHdr.nextRxPage;
  956.     ns83902CurrentPage = cur;
  957. #endif
  958.     /* check for critical error; should never happen */
  959.     if (pDrvCtrl->nextPage < pDrvCtrl->rxStartPage || 
  960. pDrvCtrl->nextPage >= pDrvCtrl->rxStopPage )
  961. {
  962. /* Can't recover, restart */
  963. #ifdef NS83902_INSTRUMENT
  964.      ns83902InitNb++;
  965. #endif
  966. ns83902Config (pDrvCtrl);
  967. pDrvCtrl->nextPage = pDrvCtrl->rxStartPage;
  968. /* mark the interface up */
  969. END_FLAGS_SET (&pDrvCtrl->endObj,
  970. (IFF_UP | IFF_RUNNING | IFF_MULTICAST | IFF_BROADCAST));
  971. netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
  972. return (pRetCluster);
  973. }
  974.     /*
  975.      * If the packet's receive status byte indicates an error the packet is 
  976.      * discarded and the receive page pointers are updated to point to the 
  977.      * next packet.
  978.      */
  979.     if ((len < 60) || (len > 1514) || 
  980. ((pRx->rxHdr.status & ~RSR_PHY) != RSR_PRX))
  981. {
  982.         DRV_LOG (NS83902_DEBUG_RX,
  983.                  "ns83902Rcv receive error: statusHeader=0x%x nextRxPage=%d 
  984.                            currentPage=%d len=%d IntNb=%dn",
  985.                  pRx->rxHdr.status, pRx->rxHdr.nextRxPage, cur, len,
  986.  ns83902IntNb, 0);
  987.         
  988.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  989. /* update boundary pointer */
  990. if (pDrvCtrl->nextPage == pDrvCtrl->rxStartPage)
  991.     bnry = pDrvCtrl->rxStopPage;
  992. else
  993.     bnry = pDrvCtrl->nextPage - 1;
  994. NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, bnry, CR_RPAGE0);
  995. netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
  996. return (pRetCluster);
  997. }
  998.     /* copy Ethernet packet section of the frame */
  999.     
  1000.     DRV_LOG (NS83902_DEBUG_RX, "ns83902PktBufRead : Reading Framen",
  1001.      1, 2, 3, 4, 5, 6);
  1002.     
  1003.     if (ns83902PktBufRead (pDrvCtrl, frameAddress, len,
  1004.    (char *) &pRx->enetHdr) == ERROR)
  1005. {
  1006. DRV_LOG (NS83902_DEBUG_RX, "ns83902Recv: Could not read packet datan",
  1007.  1, 2, 3, 4, 5, 6);
  1008. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1009. netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
  1010. }
  1011.     else
  1012. {
  1013. /* Successfully got a frame */
  1014. pRetCluster = (NS83902_CLUSTER) pRx;
  1015. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  1016. }
  1017.     /* update boundary pointer */
  1018.     if (pDrvCtrl->nextPage == pDrvCtrl->rxStartPage)
  1019. bnry = pDrvCtrl->rxStopPage;
  1020.     else
  1021. bnry = pDrvCtrl->nextPage - 1;
  1022.     NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, bnry, CR_RPAGE0);
  1023.     DRV_LOG (NS83902_DEBUG_RX, "End Read!n", 1, 2, 3, 4, 5, 6);
  1024.     return (pRetCluster);
  1025.     }
  1026. /*******************************************************************************
  1027. *
  1028. * ns83902Recv - read a packet off the interface ring buffer
  1029. *
  1030. * ns83902Recv copies packets from local memory into an mbuf and hands it to
  1031. * the next higher layer (IP or etherInputHook).
  1032. *
  1033. * RETURNS: TRUE, or FALSE if the packet reception encountered errors.
  1034. */
  1035. LOCAL void ns83902Recv
  1036.     (
  1037.     NS83902_END_DEVICE* pDrvCtrl,
  1038.     NS83902_CLUSTER pCluster
  1039.     )
  1040.     {
  1041.     NS83902_RX_FRAME* pRx = (NS83902_RX_FRAME*) pCluster;    
  1042.     CL_BLK_ID pClBlk;
  1043.     M_BLK_ID pMblk;
  1044.     UINT32 len = pRx->rxHdr.count;
  1045.     /* Process frame received */
  1046.     if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL)
  1047.         {
  1048. pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1049. muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);
  1050.         DRV_LOG (NS83902_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
  1051.         netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pCluster);        
  1052.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1053.         goto cleanRXD;
  1054.         }
  1055.     /*
  1056.      * OK we've got a spare, let's get an M_BLK_ID and marry it to the
  1057.      * one in the ring.
  1058.      */
  1059.     if ((pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)) ==
  1060.         NULL)
  1061.         {
  1062.         netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk);
  1063.         netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pCluster);
  1064.         DRV_LOG (NS83902_DEBUG_MB, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
  1065.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1066.         goto cleanRXD;
  1067.         }
  1068.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  1069.     /* Join the cluster to the MBlock */
  1070.     netClBlkJoin (pClBlk, (char*)pCluster, len, NULL, 0, 0, 0);
  1071.     netMblkClJoin (pMblk, pClBlk);
  1072.     pMblk->mBlkHdr.mData  = (char *)&pRx->enetHdr;
  1073.     pMblk->mBlkHdr.mFlags  |= M_PKTHDR; /* set the packet header */
  1074.     pMblk->mBlkHdr.mLen = len; /* set the data len */
  1075.     pMblk->mBlkPktHdr.len  = len; /* set the total len */
  1076.     /* Call the upper layer's receive routine. */
  1077.     END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);
  1078. cleanRXD:
  1079.     return;
  1080.     }
  1081. /*******************************************************************************
  1082. *
  1083. * ns83902Restart - restart chip after receive ring buffer overflow
  1084. *
  1085. * This routine is called from an isr handler that deals with a receive DMA
  1086. * overflow condition.  It gets access to the remote DMA, cleans up NIC
  1087. * registers and defers work to task context to empty the receive ring buffers.
  1088. *
  1089. * RETURNS: N/A.
  1090. */
  1091. LOCAL void ns83902Restart
  1092.     (
  1093.     NS83902_END_DEVICE* pDrvCtrl,
  1094.     UINT8 cr
  1095.     )
  1096.     {
  1097.     UINT8 isr;
  1098. #ifdef NS83902_INSTRUMENT
  1099.     ns83902RestartNb++;
  1100. #endif
  1101.     /* Buffer ring overflow algorithm */
  1102.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
  1103.     /* wait at least 1.6 mSec */
  1104.     SYS_MS_DELAY (2);
  1105.     /* Remove packets from buffer */
  1106.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 0, CR_RPAGE0);
  1107.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0);
  1108.     NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);
  1109.     if ((cr & CR_TXP) && (!(isr & (ISR_TXE | ISR_PTX))))
  1110.      pDrvCtrl->txResend = TRUE;
  1111.     NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE1, CR_RPAGE0);
  1112.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_ABORT | CR_STA, CR_RPAGE0);
  1113.     END_FLAGS_SET (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);
  1114.     pDrvCtrl->rxOvw = TRUE;
  1115.     if (pDrvCtrl->rxHandling == FALSE)
  1116. {
  1117. pDrvCtrl->rxHandling = TRUE;
  1118. netJobAdd ((FUNCPTR) ns83902HandleInt, (int) pDrvCtrl, 0, 0, 0, 0);
  1119. }
  1120.     }
  1121. /*******************************************************************************
  1122. *
  1123. * ns83902HandleInt - deferred receive interrupt handler
  1124. *
  1125. * This function handles the received frames from the device.  It runs in the
  1126. * context of the netTask, which was triggered by a received packet interrupt.
  1127. * It resends any packet that was in the midst of transmission when the overflow
  1128. * hit.
  1129. * Actual processing of the packet is done by calling ns83902Recv().
  1130. *
  1131. * RETURNS: N/A.
  1132. */
  1133. LOCAL void ns83902HandleInt
  1134.     (
  1135.     NS83902_END_DEVICE* pDrvCtrl    
  1136.     )
  1137.     {
  1138.     NS83902_CLUSTER pCluster;
  1139.     /* empties the receive ring buffer of its packets */
  1140.     pDrvCtrl->rxHandling = TRUE;
  1141.     while ((pCluster =  ns83902ReadFrame (pDrvCtrl)) != NULL)
  1142. ns83902Recv (pDrvCtrl, pCluster);
  1143.     pDrvCtrl->rxHandling = FALSE;
  1144.     if (pDrvCtrl->rxOvw == TRUE)
  1145. {
  1146. /* Reset overflow bit */
  1147. NS83902_REG_SET (pDrvCtrl, NS83902_ISR, ISR_OVW, CR_RPAGE0);
  1148. NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE0, CR_RPAGE0);
  1149. /* If resend needed, issue transmit command */
  1150. if (pDrvCtrl->txResend == TRUE)
  1151.     {
  1152.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STA | CR_TXP | CR_ABORT,
  1153.      CR_RPAGE0);
  1154.     pDrvCtrl->txResend = FALSE;
  1155.     }
  1156. pDrvCtrl->rxOvw = FALSE;
  1157. }
  1158.     /* Re-enable interrupts */
  1159.     NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_ENABLE, CR_RPAGE0);
  1160.     }
  1161. /*******************************************************************************
  1162. *
  1163. * ns83902Int - The driver's interrupt handler
  1164. *
  1165. * This function clears the cause of the device interrupt(s) and then acts
  1166. * on the individual possible causes.  The primary goal of this routine is to
  1167. * minimize the time spent in it.  This is accomplished by deferring processing
  1168. * to the netTask via the netJobAdd() function.
  1169. *
  1170. * Note that in case the receiver overruns, we promptly mark the interface as
  1171. * "down" and leave error handling to task-level.   This is in case netTask
  1172. * is in the midst of DMA activity, we must allow it to complete.  The receive
  1173. * handler will give up when it discovers the interface is down, which will
  1174. * then allow netTask to run our OVW handler.  This provides orderly error 
  1175. * recovery.
  1176. *
  1177. * RETURNS: N/A.
  1178. */
  1179. LOCAL void ns83902Int
  1180.     (
  1181.     NS83902_END_DEVICE* pDrvCtrl
  1182.     )
  1183.     {
  1184.     UINT8 isr; /* copy of NS83902_ISR */
  1185.     UINT8 cr; /* copy of NS83902_CR */
  1186.     /* Check if interface is up and running */
  1187.     if ((END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) !=
  1188.         (IFF_UP | IFF_RUNNING))
  1189. return;
  1190. #ifdef NS83902_INSTRUMENT
  1191.     ns83902IntNb++;
  1192. #endif
  1193.     DRV_LOG (NS83902_DEBUG_INT, "Inside INTn", 1, 2, 3, 4, 5, 6);
  1194.     /* Read and clear ISR */
  1195.     
  1196.     NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);
  1197.     NS83902_REG_SET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);
  1198.     /* handle transmit interrupts */
  1199.     if (isr & (ISR_PTX | ISR_TXE))
  1200. {
  1201. UINT8 tsr;
  1202. NS83902_REG_GET (pDrvCtrl, NS83902_TSR, tsr, CR_RPAGE0);
  1203. DRV_LOG (NS83902_DEBUG_TX, "ns83902Tx Interrupt TSR=%d n", tsr,
  1204.  2, 3, 4, 5, 6);
  1205. if ((tsr & TSR_PTX) == 0)
  1206.     {
  1207.     /* PTX zero, something went wrong */
  1208.     if (tsr & TSR_ABT)
  1209. {
  1210. #ifdef NS83902_INSTRUMENT
  1211. ns83902TxTimeout++;
  1212. #endif
  1213. DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Aborted n",
  1214.  1, 2, 3, 4, 5, 6);
  1215. }
  1216.     if (tsr & TSR_FU)
  1217. {
  1218. DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit FIFO Underrun n",
  1219.      1, 2, 3, 4, 5, 6);
  1220. }
  1221.     /* Notify upper layers about the error */
  1222.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1223.     pDrvCtrl->lastError.errCode = END_ERR_WARN;
  1224.     pDrvCtrl->lastError.pMesg = "Transmit error";
  1225.     netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
  1226.        (int) &pDrvCtrl->lastError, 0, 0, 0);
  1227.     DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Errorn", 0, 0, 0, 0, 0, 0);
  1228.     
  1229. #ifdef NS83902_INSTRUMENT
  1230.     ns83902TxError++;
  1231. #endif
  1232.     }
  1233. if (tsr & TSR_CRS)
  1234.     {
  1235.     DRV_LOG (NS83902_DEBUG_TX, "%s%d - no carriern", (int)NS83902_DEV_NAME,
  1236.      pDrvCtrl->unit, 3, 4, 5, 6);
  1237.     }
  1238. #if 0   /* no collision statistics for END drivers? */
  1239. if (tsr & TSR_COL)
  1240.     {
  1241.     UINT8 ncr;
  1242.     NS83902_REG_GET (pDrvCtrl, NS83902_NCR, ncr, CR_RPAGE0);
  1243.     END_ERR_ADD (pEndObj, MIB2_COLLISIONS, ncr);
  1244.     }
  1245. #endif
  1246. if (pDrvCtrl->txBlocked == TRUE)
  1247.     {
  1248.     pDrvCtrl->txBlocked = FALSE;
  1249.     netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj, 0, 0, 0, 0);
  1250.     }
  1251. }
  1252.     /* handle receiver overrun */
  1253.     if (isr & ISR_OVW)
  1254. {
  1255. /* disable interrupts */
  1256. NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);
  1257. NS83902_CR_GET (pDrvCtrl, cr);
  1258.         /* mark the interface down */
  1259.         END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING);
  1260.         
  1261. ns83902Restart (pDrvCtrl, cr);
  1262.         return;
  1263. }
  1264.     /* handle packet received */
  1265.     if (isr & ISR_PRX)
  1266.         if (pDrvCtrl->rxHandling == FALSE)
  1267.             {
  1268.             pDrvCtrl->rxHandling = TRUE;
  1269.     /* disable receive interrupts and defer work to task context */
  1270.     NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_RX_DISABLE, CR_RPAGE0);
  1271.     netJobAdd ((FUNCPTR) ns83902HandleInt, (int) pDrvCtrl, 0, 0, 0, 0);
  1272.             }
  1273.     }
  1274. /*******************************************************************************
  1275. *
  1276. * ns83902Send - the driver's actual output routine
  1277. *
  1278. * This routine accepts outgoing packets from the snd queue, and then 
  1279. * gains exclusive access to the DMA (through a mutex semaphore),
  1280. * then calls ns83902Transmit() to send the packet out onto the interface.
  1281. *
  1282. * RETURNS: OK, or ERROR if the packet could not be transmitted.
  1283. */
  1284. LOCAL STATUS ns83902Send
  1285.     (
  1286.     NS83902_END_DEVICE* pDrvCtrl,
  1287.     M_BLK* pMblk
  1288.     )
  1289.     {
  1290.     int status;
  1291.     DRV_LOG (NS83902_DEBUG_TX, "Begin ns83902Send pDrvCtrl %p pMblk %pn", 
  1292.      (int)pDrvCtrl, (int)pMblk, 3, 4, 5, 6);
  1293.     if ((END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) !=
  1294.         (IFF_UP | IFF_RUNNING))
  1295.         {
  1296.         DRV_LOG (NS83902_DEBUG_TX, "Device is NOT UP and RUNNINGn",
  1297.                  1, 2, 3, 4, 5, 6);
  1298.         return (ERROR);
  1299.         }
  1300.     /* send packet out over interface */
  1301.     if ((status = ns83902Transmit (pDrvCtrl, pMblk)) == OK)
  1302.         {
  1303. /* Success, free the Mblk chain */
  1304. if (!NS83902_IS_IN_POLL_MODE())
  1305.     netMblkClChainFree (pMblk);
  1306.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1307. }
  1308.     else
  1309.         {
  1310.         DRV_LOG (NS83902_DEBUG_TX, "FAILED ns83902Transmitn", 0, 0, 0, 0, 0, 0);
  1311.         
  1312.         /* update statistics */
  1313.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1314. #ifdef NS83902_INSTRUMENT
  1315. ns83902TxError++;
  1316. #endif
  1317.         }
  1318.     DRV_LOG (NS83902_DEBUG_TX, "End ns83902Send n", 0, 0, 0, 0, 0, 0);
  1319. #ifdef NS83902_INSTRUMENT
  1320.     ns83902TxNb++;
  1321. #endif
  1322.     return status;    
  1323.     }
  1324. /*******************************************************************************
  1325. *
  1326. * ns83902Transmit - send data over the NIC network interface
  1327. *
  1328. * This routine transfers data to the NIC device via the remote DMA, and
  1329. * then signal for a transmission.
  1330. *
  1331. * RETURNS: OK, or ERROR if the transmitter signalled an error.
  1332. */
  1333. LOCAL STATUS ns83902Transmit
  1334.     (
  1335.     NS83902_END_DEVICE* pDrvCtrl,    
  1336.     M_BLK* pMblk
  1337.     )
  1338.     {
  1339.     int status = OK;
  1340.     int txLen = 0;
  1341.     UINT8 cr;
  1342.     LOCAL UINT8 txData[ETHERMTU + ENET_HDR_REAL_SIZ];
  1343.     int cnt;
  1344.     USHORT dummyRead;
  1345.     /* Get exclusive access to DMA */
  1346.     if (!NS83902_IS_IN_POLL_MODE())
  1347. NS83902_SEM_TAKE (pDrvCtrl, WAIT_FOREVER);
  1348.     txLen = netMblkToBufCopy (pMblk, txData, NULL);
  1349.     txLen = max (txLen, ETHERSMALL);
  1350.     /* Check if we are ready to transmit */
  1351.     
  1352.     NS83902_CR_GET (pDrvCtrl, cr);
  1353.     if (cr & CR_TXP)
  1354. {
  1355. DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit: waiting for TX_IN_PROGRESSn",
  1356.  1, 2, 3, 4, 5, 6);
  1357. /* Wait for end of TX */
  1358. cnt = 100; /* timeout 100 mSec */
  1359. while ((cr & CR_TXP) && (cnt-- > 0))
  1360.     {
  1361.     SYS_MS_DELAY (1);
  1362.     NS83902_CR_GET (pDrvCtrl, cr);
  1363.     }
  1364. }
  1365.     /* If still not ready, bail */
  1366.     NS83902_CR_GET (pDrvCtrl, cr);
  1367.     if (cr & CR_TXP)
  1368. {
  1369.         DRV_LOG (NS83902_DEBUG_TX, "Not Ready to transmit!n", 1, 2, 3, 4, 5, 6);
  1370. pDrvCtrl->txBlocked = TRUE; /* transmitter not ready */
  1371. if (!NS83902_IS_IN_POLL_MODE())
  1372.     NS83902_SEM_GIVE (pDrvCtrl);
  1373.         return (END_ERR_BLOCK);
  1374. }
  1375.     /* Dummy read with RBCR > 1 before (see DP83902 manual) */
  1376.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 2, CR_RPAGE0);
  1377.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0);
  1378.     NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, 0, CR_RPAGE0);
  1379.     NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, LSB(pDrvCtrl->txStartPage),
  1380.      CR_RPAGE0);
  1381.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RREAD, CR_RPAGE0);
  1382.     if (pDrvCtrl->wide == TRUE)
  1383. {
  1384. SYS_IN_SHORT (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);
  1385. }
  1386.     else
  1387. {
  1388. SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);
  1389. SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);
  1390. }
  1391.     /* Set up remote DMA transfer */
  1392.     NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, 0, CR_RPAGE0);
  1393.     NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, LSB(pDrvCtrl->txStartPage), 
  1394.      CR_RPAGE0);
  1395.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, LSB(txLen), CR_RPAGE0);
  1396.     NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, MSB(txLen), CR_RPAGE0);
  1397.     /* Start remote DMA transfer */
  1398.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RWRITE, CR_RPAGE0);
  1399.     /* write data to the DMA port */
  1400.     ns83902WritePort (pDrvCtrl, txData, txLen);
  1401.     /* Se up local DMA */
  1402.     NS83902_REG_SET (pDrvCtrl, NS83902_TPSR, pDrvCtrl->txStartPage, CR_RPAGE0);
  1403.     NS83902_REG_SET (pDrvCtrl, NS83902_TBCR0, LSB(txLen), CR_RPAGE0);
  1404.     NS83902_REG_SET (pDrvCtrl, NS83902_TBCR1, MSB(txLen), CR_RPAGE0);
  1405.     DRV_LOG (NS83902_DEBUG_TX, "Sending %d bytes from %p n", txLen,
  1406.      (int)txData, 3, 4, 5, 6);   
  1407.     /* Start transmission while preserving DMA command bits */
  1408.     NS83902_CR_GET (pDrvCtrl, cr);
  1409.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, 
  1410.      CR_TXP | (cr & (CR_RWRITE | CR_RREAD | CR_ABORT)),
  1411.      CR_RPAGE0);
  1412.     /* Release Semaphore */
  1413.     
  1414.     if (!NS83902_IS_IN_POLL_MODE())
  1415. {
  1416. NS83902_SEM_GIVE (pDrvCtrl);
  1417. }
  1418.     else
  1419. {
  1420. UINT8 tsr;
  1421. UINT8 isr;
  1422. FOREVER
  1423.     {
  1424.     NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);
  1425.     if ((isr & (ISR_PTX | ISR_TXE)) != 0)
  1426. break;
  1427.          }
  1428. /* Check for errors */
  1429. NS83902_REG_GET (pDrvCtrl, NS83902_TSR, tsr, CR_RPAGE0);
  1430. if ((tsr & TSR_PTX) == 0)
  1431.     {
  1432.     /* PTX zero, something went wrong */
  1433.     status = ERROR;
  1434.     if (tsr & TSR_ABT)
  1435. {
  1436. #ifdef NS83902_INSTRUMENT
  1437. ns83902TxTimeout++;
  1438. #endif
  1439. DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Aborted n",
  1440.  1, 2, 3, 4, 5, 6);
  1441. }
  1442.     if (tsr & TSR_FU)
  1443. {
  1444. DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit FIFO Underrun n",
  1445.  1, 2, 3, 4, 5, 6);
  1446. }
  1447.     }
  1448. if (tsr & TSR_CRS)
  1449.     {
  1450.     logMsg ("%s%d - no carriern", (int)NS83902_DEV_NAME, pDrvCtrl->unit, 
  1451.     3, 4, 5, 6);
  1452.     }
  1453. #if 0   /* no collision statistics for END drivers? */
  1454. if (tsr & TSR_COL)
  1455.     {
  1456.     UINT8 ncr;
  1457.     NS83902_REG_GET (pDrvCtrl, NS83902_NCR, ncr, CR_RPAGE0);
  1458.     END_ERR_ADD (pEndObj, MIB2_COLLISIONS, ncr);
  1459.     }
  1460. #endif
  1461. /* Clear transmit flags in ISR */
  1462. NS83902_REG_SET (pDrvCtrl, NS83902_ISR, (ISR_PTX | ISR_TXE), CR_RPAGE0);
  1463. }
  1464.     return (status);
  1465.     }
  1466. /*******************************************************************************
  1467. *
  1468. * ns83902Ioctl - the driver's I/O control routine
  1469. *
  1470. * Perform device-specific commands.
  1471. *
  1472. * RETURNS: 0, or EINVAL if the command 'cmd' is not supported.
  1473. */
  1474. LOCAL int ns83902Ioctl
  1475.     (
  1476.     NS83902_END_DEVICE* pDrvCtrl,
  1477.     int cmd,
  1478.     caddr_t data    
  1479.     )
  1480.     {
  1481.     int  error = 0;
  1482.     long value;
  1483.     int saveFlags;
  1484.     DRV_LOG (NS83902_DEBUG_LOAD, "ns83902Ioctl Command %dn",
  1485.     cmd, 2, 3, 4, 5, 6);
  1486.     
  1487.     switch ((UINT)cmd)
  1488. {
  1489.         case EIOCSADDR:
  1490.     if (data == NULL)
  1491. return (EINVAL);
  1492.             bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),
  1493.    END_HADDR_LEN(&pDrvCtrl->endObj));
  1494.             ns83902Config (pDrvCtrl); /* HELP  Will it work? */
  1495.             break;
  1496.         case EIOCGADDR:
  1497.     if (data == NULL)
  1498. return (EINVAL);
  1499.             bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data,
  1500.     END_HADDR_LEN(&pDrvCtrl->endObj));
  1501.             break;
  1502.         case EIOCSFLAGS:
  1503.     value = (long) data;
  1504.     if( value < 0 )
  1505. {
  1506. value = -value;
  1507. value--;
  1508. END_FLAGS_CLR (&pDrvCtrl->endObj, value);
  1509. }
  1510.     else
  1511. {
  1512. END_FLAGS_SET (&pDrvCtrl->endObj, value);
  1513. }
  1514.     saveFlags = DRV_FLAGS_GET();
  1515.     if (DRV_FLAGS_GET() != saveFlags && 
  1516.            (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_UP))
  1517. {
  1518. END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING);
  1519. ns83902Config( pDrvCtrl );
  1520. }
  1521.             break;
  1522.         case EIOCGFLAGS:
  1523.     if (data == NULL)
  1524. error = EINVAL;
  1525.     else
  1526. *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj);
  1527.     break;
  1528.         case EIOCMULTIADD:                   /* move to mux */
  1529.             error = ns83902MCastAddrAdd (pDrvCtrl, (char *)data);
  1530.             break;
  1531.         case EIOCMULTIDEL:                   /* move to mux */
  1532.             error = ns83902MCastAddrDel (pDrvCtrl, (char *)data);
  1533.             break;
  1534.         case EIOCMULTIGET:                   /* move to mux */
  1535.             error = ns83902MCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data);
  1536.             break;
  1537.         case EIOCPOLLSTART:                  /* move to mux */
  1538.             error = ns83902PollStart (pDrvCtrl);
  1539.             break;
  1540.         case EIOCPOLLSTOP:                   /* move to mux */
  1541.             error = ns83902PollStop (pDrvCtrl);
  1542.             break;            
  1543.         case EIOCGMIB2:
  1544.             if (data == NULL)
  1545.                 return (EINVAL);
  1546.             bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
  1547.                   sizeof(pDrvCtrl->endObj.mib2Tbl));
  1548.             break;
  1549.         default:
  1550.             error = EINVAL;
  1551. }
  1552.     return (error);
  1553.     } 
  1554. /*******************************************************************************
  1555. *
  1556. * ns83902Stop - stop the device
  1557. *
  1558. * This function calls BSP functions to disconnect interrupts and stop
  1559. * the device from operating in interrupt mode.
  1560. *
  1561. * RETURNS: OK or ERROR
  1562. */
  1563. LOCAL STATUS ns83902Stop
  1564.     (
  1565.     NS83902_END_DEVICE* pDrvCtrl
  1566.     )
  1567.     {
  1568.     STATUS result = OK;
  1569.     END_FLAGS_CLR (&pDrvCtrl->endObj,IFF_UP | IFF_RUNNING );
  1570.     /* Stop the device. */
  1571.     NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
  1572.     /* disable all interrupts */
  1573.     NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);
  1574.     /* Disable LAN interrupts */
  1575.     SYS_INT_DISABLE (pDrvCtrl);
  1576.     /* disconnect interrupt */
  1577.     SYS_INT_DISCONNECT (pDrvCtrl, ns83902Int, (int)pDrvCtrl, &result);
  1578.     if (result == ERROR)
  1579. {
  1580. DRV_LOG (NS83902_DEBUG_TMP, "Could not diconnect interrupt!n",
  1581.                  1, 2, 3, 4, 5, 6);
  1582. }
  1583.     return (result);
  1584.     }
  1585. /******************************************************************************
  1586. *
  1587. * ns83902Unload - unload a driver from the system
  1588. *
  1589. * This function first brings down the device, and then frees any
  1590. * stuff that was allocated by the driver in the load function.
  1591. */
  1592. LOCAL STATUS ns83902Unload
  1593.     (
  1594.     NS83902_END_DEVICE* pDrvCtrl
  1595.     )
  1596.     {
  1597.     if (pDrvCtrl != NULL)
  1598.         {
  1599.         END_OBJECT_UNLOAD (&pDrvCtrl->endObj);
  1600.         /* free resources */
  1601.         if (pDrvCtrl->pCluster != NULL)
  1602.             free (pDrvCtrl->pCluster);
  1603.         }
  1604.     return (OK);
  1605.     }
  1606. /*******************************************************************************
  1607. *
  1608. * ns83902MCastAddrAdd - add a multicast address
  1609. *
  1610. *
  1611. * RETURNS: OK on success, ERROR otherwise.
  1612. */
  1613. LOCAL STATUS ns83902MCastAddrAdd
  1614.     (
  1615.     NS83902_END_DEVICE* pDrvCtrl,
  1616.     char * pAddr
  1617.     )
  1618.     {
  1619.     int retVal;
  1620.     DRV_LOG (NS83902_DEBUG_IOCTL, "MCastAddrAddn", 0, 0, 0, 0, 0, 0);
  1621.     retVal = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddr);
  1622.     if (retVal == ENETRESET)
  1623.         return ns83902AddrFilterSet (pDrvCtrl, pAddr, TRUE);
  1624.     return ((retVal == OK) ? OK : ERROR);
  1625.     }
  1626. /*******************************************************************************
  1627. *
  1628. * ns83902MCastAddrDel - remove a multicast address
  1629. *
  1630. *
  1631. * RETURNS: OK on success, ERROR otherwise.
  1632. */
  1633. LOCAL STATUS ns83902MCastAddrDel
  1634.     (
  1635.     NS83902_END_DEVICE* pDrvCtrl,
  1636.     char * pAddr
  1637.     )
  1638.     {
  1639.     int  retVal;
  1640.     DRV_LOG (NS83902_DEBUG_IOCTL, "MCastAddrDeln", 0, 0, 0, 0, 0, 0);
  1641.     retVal = etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr);
  1642.     if (retVal == ENETRESET)
  1643.         return ns83902AddrFilterSet (pDrvCtrl, pAddr, FALSE);
  1644.     return ((retVal == OK) ? OK : ERROR);
  1645.     }
  1646. /*******************************************************************************
  1647. *
  1648. * ns83902MCastAddrGet - retreive current multicast address list
  1649. *
  1650. *
  1651. * RETURNS: OK on success; otherwise ERROR.
  1652. */
  1653. LOCAL STATUS ns83902MCastAddrGet
  1654.     (
  1655.     NS83902_END_DEVICE* pDrvCtrl,
  1656.     MULTI_TABLE * pTable
  1657.     )
  1658.     {
  1659.     DRV_LOG (NS83902_DEBUG_IOCTL, "MCastAddrGetn", 0, 0, 0, 0, 0, 0);
  1660.     return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable));
  1661.     }
  1662. /*******************************************************************************
  1663. *
  1664. * ns83902PollStart - starting polling mode
  1665. *
  1666. * RETURNS: OK, always.
  1667. */
  1668. LOCAL STATUS ns83902PollStart
  1669.     (
  1670.     NS83902_END_DEVICE* pDrvCtrl
  1671.     )
  1672.     {
  1673.     int intLevel;
  1674.     DRV_LOG (NS83902_DEBUG_POLL, "S ", 0, 0, 0, 0, 0, 0);
  1675.     intLevel = intLock();
  1676.     /* disable all interrupts */
  1677.     NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);
  1678.     DRV_FLAGS_SET (NS83902_FLAG_POLL);
  1679.     intUnlock (intLevel);
  1680.     return (OK);    
  1681.     }
  1682. /*******************************************************************************
  1683. *
  1684. * ns83902PollStop - stop polling mode
  1685. *
  1686. * RETURNS: OK, always.
  1687. */
  1688. LOCAL STATUS ns83902PollStop
  1689.     (
  1690.     NS83902_END_DEVICE* pDrvCtrl
  1691.     )
  1692.     {
  1693.     int intLevel;
  1694.     intLevel = intLock();
  1695.     /* enable interrupts */
  1696.     NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_ENABLE, CR_RPAGE0);
  1697.     DRV_FLAGS_CLR(NS83902_FLAG_POLL);
  1698.     DRV_LOG (NS83902_DEBUG_POLL, "s", 0, 0, 0, 0, 0, 0);
  1699.     
  1700.     intUnlock (intLevel);
  1701.     return (OK);
  1702.     }
  1703. /*******************************************************************************
  1704. *
  1705. * ns83902PollSend - send a packet in polled mode
  1706. *
  1707. * RETURNS: OK on success, EAGAIN on failure
  1708. */
  1709. LOCAL STATUS ns83902PollSend
  1710.     (
  1711.     NS83902_END_DEVICE* pDrvCtrl,
  1712.     M_BLK* pMblk
  1713.     )
  1714.     {
  1715.     return (ns83902Send (pDrvCtrl, pMblk));
  1716.     }
  1717. /*******************************************************************************
  1718. *
  1719. * ns83902PollReceive - get a packet in polled mode
  1720. *
  1721. * RETURNS: OK on success, EAGAIN on failure.
  1722. */
  1723. LOCAL STATUS ns83902PollReceive
  1724.     (
  1725.     NS83902_END_DEVICE* pDrvCtrl,
  1726.     M_BLK* pMblk
  1727.     )
  1728.     {
  1729.     STATUS nRetValue = OK;
  1730.     NS83902_CLUSTER pCluster;
  1731.     int len;
  1732.     
  1733.     DRV_LOG (NS83902_DEBUG_POLL, "Start Poll Read!n", 1, 2, 3, 4, 5, 6);
  1734.     if ((pCluster = ns83902ReadFrame (pDrvCtrl)) == NULL)
  1735.         nRetValue = EAGAIN;
  1736.     else
  1737.         {
  1738.         NS83902_RX_FRAME* pRx = (NS83902_RX_FRAME*)pCluster;
  1739.         
  1740.         len = pRx->rxHdr.count;
  1741.     
  1742. pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */
  1743. pMblk->mBlkHdr.mLen = len;    /* set the data len */
  1744. pMblk->mBlkPktHdr.len = len;    /* set the total len */
  1745. pMblk->mBlkHdr.mData += 2;
  1746.         bcopy ((char *)&pRx->enetHdr, (char *)pMblk->mBlkHdr.mData, len);
  1747.         netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
  1748.         }
  1749.     
  1750.     DRV_LOG (NS83902_DEBUG_POLL, "End Poll Read!n", 1, 2, 3, 4, 5, 6);        
  1751.     return nRetValue;
  1752.     }
  1753. /*******************************************************************************
  1754. *
  1755. * ns83902HashIndex - compute the hash index for an ethernet address
  1756. *
  1757. * RETURNS: hash index for an ethernet address.
  1758. */
  1759. LOCAL int ns83902HashIndex
  1760.     (
  1761.     char * eAddr
  1762.     )
  1763.     {
  1764.     UINT8 eAddrByte;
  1765.     int index;                       /* hash index - return value */
  1766.     int byte;                        /* loop - counter */
  1767.     int bit;                         /* loop - counter */
  1768.     UINT crc = 0xffffffff;
  1769.     UINT8 msb;
  1770.     for (byte=0; byte<6; byte++)
  1771.         {
  1772.         eAddrByte = eAddr[byte];
  1773.         for (bit=0; bit<8; bit++)
  1774.             {
  1775.             msb = crc >> 31;
  1776.             crc <<= 1;
  1777.             if (msb ^ (eAddrByte & 0x1))
  1778.                 {
  1779.                 crc ^= NS83902_CRC_POLY;
  1780.                 crc |= 0x1;
  1781.                 }
  1782.             eAddrByte >>= 1;
  1783.             }
  1784.         }
  1785.     /* Just want the 6 most significant bits. */
  1786.     
  1787.     index = crc >> 26 ;
  1788.     return index;
  1789.     }
  1790. /******************************************************************************
  1791. *
  1792. * ns83902AddrFilterSet - set the address filter for multicast addresses
  1793. *
  1794. * This routine goes through all of the multicast addresses on the list
  1795. * of addresses (added with the MCastAddrAdd() routine) and sets the
  1796. * device's filter correctly.
  1797. *
  1798. * NOMANUAL
  1799. */
  1800. LOCAL STATUS ns83902AddrFilterSet
  1801.     (
  1802.     NS83902_END_DEVICE* pDrvCtrl,
  1803.     char* pAddr,
  1804.     BOOL bSet
  1805.     )
  1806.     {
  1807.     UINT8 nHashIndex;
  1808.     /* get hash index for the address */
  1809.     nHashIndex = ns83902HashIndex (pAddr);
  1810.     /* Turn on the corresponding bit in the filter. */
  1811.     ns83902MARSet (pDrvCtrl, nHashIndex, bSet);
  1812.     return OK;
  1813.     }
  1814. /*******************************************************************************
  1815. *
  1816. * ns83902MARSet - sets/resets the MAR for the specified hash index
  1817. *
  1818. * This routine sets/resets the MAR bit for the specified hash index
  1819. *
  1820. * RETURNS: OK or ERROR.
  1821. */
  1822. LOCAL void ns83902MARSet
  1823.     (
  1824.     NS83902_END_DEVICE* pDrvCtrl,    
  1825.     UINT8 index, /* hash index */
  1826.     BOOL bSet /* Set/Reset */
  1827.     )
  1828.     {
  1829.     UINT8 nRegOffset = index;
  1830.     UINT8 nBitPosition = index;
  1831.     UINT8 nBitMask = (UINT8)0x01;
  1832.     UINT8 nValue;
  1833.     
  1834.     /* Find register and bit position */
  1835.     nBitPosition = nBitPosition & 0x07; /* 3 LSB bits */
  1836.     nBitMask <<= nBitPosition;
  1837.     nRegOffset >>= 3;       /* next 3 bits */
  1838.     /* set the bit in bit array*/
  1839.     NS83902_REG_GET (pDrvCtrl, NS83902_MAR0 + nRegOffset, nValue, CR_RPAGE1);
  1840.     DRV_LOG (NS83902_DEBUG_LOAD, "Hash Index:%d MAR Offset:%d value:%dn",
  1841.              index, nRegOffset, nValue, 4, 5, 6);
  1842.     
  1843.     if (bSet)
  1844.         {
  1845.         nValue |= nBitMask; /* set */
  1846.         }
  1847.     else
  1848.         {
  1849.         nBitMask = ~nBitMask; /* reset */
  1850.         nValue &= nBitMask;        
  1851.         }
  1852.     
  1853.     NS83902_REG_SET (pDrvCtrl, NS83902_MAR0 + nRegOffset, nValue, CR_RPAGE1);
  1854.     
  1855.     DRV_LOG (NS83902_DEBUG_LOAD, "Hash Index:%d MAR Offset:%d value:%dn",
  1856.              index, nRegOffset, nValue, 4, 5, 6);
  1857.     }
  1858. /*******************************************************************************
  1859. *
  1860. * ns83902RegRead - read the current value of a NIC register
  1861. *
  1862. * This routine reads the register values of a NIC register
  1863. *
  1864. * RETURNS: register value.
  1865. */
  1866. LOCAL UINT8 ns83902RegRead
  1867.     (
  1868.     NS83902_END_DEVICE* pDrvCtrl,
  1869.     int  reg,
  1870.     int  page
  1871.     )
  1872.     {
  1873.     UINT8  value;
  1874.     int  oldLevel = intLock();
  1875.     if ((pDrvCtrl)->regPage != (page))
  1876. {
  1877. /* Set the register page */
  1878. UINT8 cr;
  1879. (pDrvCtrl)->regPage = (page);
  1880. NS83902_CR_GET ((pDrvCtrl), cr);
  1881. NS83902_CR_SET ((pDrvCtrl), (cr & !CR_PAGE_MASK) | (page));
  1882. }
  1883.     SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->pNic + reg * pDrvCtrl->regInterval,value);
  1884.     SYS_NS83902_DELAY();
  1885.     intUnlock (oldLevel);
  1886.     return (value);
  1887.     }
  1888.  
  1889. /*******************************************************************************
  1890. *
  1891. * ns83902RegSet - set a NIC register
  1892. *
  1893. * This routine reads and displays the register values of the NIC registers
  1894. *
  1895. * RETURNS: N/A.
  1896. */
  1897. LOCAL void ns83902RegSet
  1898.     (
  1899.     NS83902_END_DEVICE* pDrvCtrl,
  1900.     int reg,
  1901.     int value,
  1902.     int page
  1903.     )
  1904.     {
  1905.     int  oldLevel = intLock();
  1906.     if (pDrvCtrl->regPage != page)
  1907. {
  1908. /* Set the page */
  1909. UINT8 cr;
  1910. pDrvCtrl->regPage = page;
  1911. NS83902_CR_GET (pDrvCtrl, cr);
  1912. NS83902_CR_SET (pDrvCtrl, ((cr & !CR_PAGE_MASK) | page));
  1913. }
  1914.     SYS_OUT_BYTE (pDrvCtrl, pDrvCtrl->pNic + reg * pDrvCtrl->regInterval, value);
  1915.     SYS_NS83902_DELAY();
  1916.     intUnlock (oldLevel);
  1917.     }
  1918. #ifdef NS83902_DEBUG
  1919. /*******************************************************************************
  1920. *
  1921. * ns83902RegShow - prints the current value of the NIC registers
  1922. *
  1923. * This routine reads and displays the register values of the NIC registers
  1924. *
  1925. * RETURNS: N/A.
  1926. */
  1927. void ns83902RegShow 
  1928.     (
  1929.     NS83902_END_DEVICE* pDrvCtrl
  1930.     )
  1931.     {
  1932.     UINT8  value;
  1933.     NS83902_CR_GET (pDrvCtrl, value);
  1934.     printf ("CR:    0x%x n", value);
  1935.     NS83902_REG_GET (pDrvCtrl, NS83902_CLDA0, value, CR_RPAGE0);
  1936.     printf ("CLDA0: 0x%x n", value);
  1937.     NS83902_REG_GET (pDrvCtrl, NS83902_CLDA1, value, CR_RPAGE0);
  1938.     printf ("CLDA1: 0x%x n", value);
  1939.     NS83902_REG_GET (pDrvCtrl, NS83902_BNRY, value, CR_RPAGE0);
  1940.     printf ("BNRY:  0x%x n", value);
  1941.     NS83902_REG_GET (pDrvCtrl, NS83902_TSR, value, CR_RPAGE0);
  1942.     printf ("TSR:   0x%x n", value);
  1943.     NS83902_REG_GET (pDrvCtrl, NS83902_ISR, value, CR_RPAGE0);
  1944.     printf ("ISR:   0x%x n", value);
  1945.     NS83902_REG_GET (pDrvCtrl, NS83902_CRDA0, value, CR_RPAGE0);
  1946.     printf ("CRDA0: 0x%x n", value);
  1947.     NS83902_REG_GET (pDrvCtrl, NS83902_CRDA1, value, CR_RPAGE0);
  1948.     printf ("CRDA1: 0x%x n", value);
  1949.     NS83902_REG_GET (pDrvCtrl, NS83902_RSR, value, CR_RPAGE0);
  1950.     printf ("RSR:   0x%x n", value);
  1951.     }
  1952. #endif