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

VxWorks

开发平台:

C/C++

  1. /* ln7990End.c - END style AMD 7990 LANCE Ethernet network interface driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02x,16jul02,rcs  aligned pRing and pTring before initializing fields. SPR#77322
  8. 02w,14jan02,dat  Removing warnings from Diab compiler
  9. 02v,11jun00,ham  removed reference to etherLib.
  10. 02u,27jan00,dat  fixed use of NULL
  11. 02t,04mar99,jkf  removed "+ 2" when setting pTring. added "+ 1" and 
  12.                  "* TMD_SIZ" to lnClDescTbl[0].memArea, ln7990InitMem(),
  13.                  for boards that hand over a memory pool SPR#22628.  
  14.                  changed ln7990ScrubTRing() to handle a receive packet.
  15.                  fixed the endMultiLstCnt implicit declaration warning.
  16. 02s,06oct98,n_s  correct error codes in ln7990Int.
  17. 02r,30sep98,n_s  removed check for RINT in PollReceive.
  18. 02q,23sep98,n_s  fixed ln7990Int to limit netJobAdd calls and handle overload
  19.                  cases.  spr # 22381.
  20. 02p,22sep98,n_s  fixed ln7990Int to call Restart from task level.
  21. 02o,21sep98,n_s  corrected handling of txSem in ln7990Send ().
  22. 02n,22sep98,dat  SPR 22325, System mode transition.
  23. 02m,17jul98,db   changed "holder" in ln7990InitParse from char ** to char *.
  24.  fixed references to "holder" in ln7990InitParse(spr #21464).
  25. 02l,12dec97,kbw  made man page edits
  26. 02k,11dec97,gnn  removed IFF_SCAT and IFF_LOAN.
  27. 02j,08dec97,gnn  END code review fixes
  28. 02i,25nov97,gnn  fixed spr#9620 polled mode receive
  29. 02h,27oct97,vin  fixed the offset problem in xxRecv() call.
  30. 02g,19oct97,vin  moved swapping of loaned buffer before END_RCV_RTN_CALL
  31. 02f,17oct97,vin  removed extra free.
  32. 02e,07oct97,vin  MIB MTU size to ETHER_MTU
  33. 02d,03oct97,gnn  added example error upcall code
  34. 02c,25sep97,gnn  fixed SPARC issues and cleaned up memory problems.
  35. 02b,03sep97,gnn  fixed a crashing bug under heavy load
  36. 02a,31aug97,vin  reimplemented txBlocked logic, moved the txBlocked variable 
  37.  into the drvCtrl structure.
  38. 01z,25aug97,gnn  changes due to new netPoolInit routine.
  39. 01y,22aug97,gnn  rewrote and fixed polled mode
  40. 01x,19aug97,gnn  changes due to new buffering scheme.
  41. 01w,12aug97,gnn  changes necessitated by MUX/END update.
  42. 01v,02jun97,gnn  implemented new Memory Width ioctl.
  43. 01u,20may97,spm  corrected memory alignment, added a real lnRestart function 
  44. 01t,17apr97,gnn  added offset load parameter.
  45. 01s,24feb97,gnn  Removed an unecessary step in the interrupt routine.
  46.                  Added code to properly pass back NET_BUFFER fields.
  47. 01r,05jan97,gnn  Turned IFF_SCAT off by default.
  48. 01q,03feb97,gnn  Changed the way in which muxBufAlloc is used.
  49.                  Added speed as an argument to MIB stuff.
  50. 01p,22jan97,gnn  Turned IFF_SCAT off by default.
  51. 01o,22jan97,gnn  Changed code to get the enet address from the BSP.
  52. 01n,21jan97,gnn  Added code to handle send side free routines.
  53.                  Added code to handle scatter/gather interface.
  54.                  Added code to better handle polled mode.
  55.                  Removed code that is common to all ENDs into endLib.c.
  56. 01m,06jan97,gnn  Fixed compilation errors and removed more non-driver stuff.
  57. 01l,23dec96,dat  added macros, added csr3B, enetAddr to init string,
  58. 01k,02dec96,gnn  forgot a break in the Ioctl.
  59. 01j,27nov96,gnn  added MIB 2 Ioctl.
  60. 01i,19nov96,gnn  Added IFF_BROADCAST to the flags.
  61. 01h,13nov96,dat  Restructured to isolate end/mib routines
  62. 01g,22oct96,gnn  Name changes to follow coding standards.
  63.                  static functions changed to LOCAL.
  64. 01f,22oct96,gnn  Removed all netVectors and replaced them with netBuffers.
  65.                  Did a significant code cleanup in preparation for going to
  66.                  a 32bit world with a 24 bit driver.
  67. 01e,23sep96,gnn  Cleanup of code.  Changed pointers to look like WRS
  68.  pointers and the like.
  69.  Made is so that the ln7990Config routine works
  70.  correctly to fill in the transmit and receive
  71.  descriptors' memory fields.
  72.  This version works with system level debugging or
  73.  buffer loaning but not with both.
  74. 01d,28aug96,gnn  Fixed argument parsing for pre-allocated memory.
  75.  Added more log messages to the load sequence.
  76. 01c,15aug96,gnn  Name changes to follow our coding standard.
  77. 01b,14aug96,gnn  Worked the documentation and other stuff over to
  78.  integrate into the new scheme of network drivers.
  79. 01a,22apr96,gnn  Copied if_ln driver and worked into the END scheme.
  80. */
  81. /*
  82. This module implements the Advanced Micro Devices Am7990 LANCE Ethernet network
  83. interface driver.  The driver can be configured to support big-endian or
  84. little-endian architectures, and it contains error recovery code to handle 
  85. known device errata related to DMA activity.
  86. This driver is designed to be moderately generic.  Thus, it operates 
  87. unmodified across the range of architectures and targets supported by 
  88. VxWorks.  To achieve this, the driver load routine requires an input 
  89. string consisting of several target-specific values.  The driver also 
  90. requires some external support routines.  These target-specific values 
  91. and the external support routines are described below.  If any of the 
  92. assumptions stated below are not true for your particular hardware, this 
  93. driver might not function correctly with that hardware.
  94. BOARD LAYOUT
  95. This device is on-board.  No jumpering diagram is necessary.
  96. EXTERNAL INTERFACE
  97. The only external interface is the ln7990EndLoad() routine, which expects
  98. the <initString> parameter as input.  This parameter passes in a 
  99. colon-delimited string of the format:
  100. <unit>:<CSR_reg_addr>:<RAP_reg_addr>:<int_vector>:<int_level>:<shmem_addr>:<shmem_size>:<shmem_width>:<offset>:<csr3B>
  101. The ln7990EndLoad() function uses strtok() to parse the string.
  102. TARGET-SPECIFIC PARAMETERS
  103. .IP <unit>
  104. A convenient holdover from the former model.  This parameter is used only
  105. in the string name for the driver.
  106. .IP <CSR_register_addr>
  107. Tells the driver where to find the CSR register.
  108. .IP <RAP_register_addr>
  109. Tells the driver where to find the RAP register.
  110. .IP <int_vector>
  111. Configures the LANCE device to generate hardware interrupts
  112. for various events within the device. Thus, it contains
  113. an interrupt handler routine.  The driver calls sysIntConnect() to connect
  114. its interrupt handler to the interrupt vector generated as a result of
  115. the LANCE interrupt.
  116. .IP <int_level>
  117. This parameter is passed to an external support routine, sysLanIntEnable(),
  118. which is described below in "External Support Requirements." This routine 
  119. is called during as part of driver's initialization.  It handles any 
  120. board-specific operations required to allow the servicing of a LANCE 
  121. interrupt on targets that use additional interrupt controller devices to 
  122. help organize and service the various interrupt sources.  This parameter 
  123. makes it possible for this driver to avoid all board-specific knowledge of 
  124. such devices.  
  125. .IP <shmem_addr>
  126. The LANCE device is a DMA type of device and typically shares access to
  127. some region of memory with the CPU.  This driver is designed for systems
  128. that directly share memory between the CPU and the LANCE.  It
  129. assumes that this shared memory is directly available to it
  130. without any arbitration or timing concerns.
  131. This parameter can be used to specify an explicit memory region for use
  132. by the LANCE.  This should be done on hardware that restricts the LANCE
  133. to a particular memory region.  The constant NONE can be used to indicate
  134. that there are no memory limitations, in which case, the driver
  135. attempts to allocate the shared memory from the system space.
  136. .IP <shmem_size>
  137. Use this parameter to explicitly limit the amount of shared memory (bytes) 
  138. that this driver uses.  Use "NONE" to indicate that there is no specific 
  139. size limitation.  This parameter is used only if a specific memory region 
  140. is provided to the driver.
  141. .IP <shmem_width>
  142. Some target hardware that restricts the shared memory region to a
  143. specific location also restricts the access width to this region by
  144. the CPU.  On such targets, performing an access of an invalid width
  145. causes a bus error.  Use this parameter to specify the number of bytes 
  146. on which data must be aligned if it is to be used by the driver during 
  147. access to the shared memory.  Use "NONE" to indicate that there are no 
  148. restrictions.  The support for this mechanism is not robust. Thus, its 
  149. current implementation might not work on all targets requiring these 
  150. restrictions.
  151. .IP <offset>
  152. Specifies the memory alignment offset.
  153. .IP <csr3B>
  154. Specifies the value that is placed into LANCE control register #3. This
  155. value determines the bus mode of the device and thus allows the support of
  156. big-endian and little-endian architectures.  The default value supports
  157. Motorola-type buses.  Normally this value is 0x4.  For SPARC CPUs, it is
  158. normally set to 0x7 to add the ACON and BCON control bits.  For more
  159. information on this register and the bus mode of the LANCE controller, see
  160. .I "Advanced Micro Devices Local Area Network Controller Am7990 (LANCE)."
  161. .LP
  162. EXTERNAL SUPPORT REQUIREMENTS
  163. This driver requires several external support functions, defined as macros:
  164. .CS
  165.     SYS_INT_CONNECT(pDrvCtrl, routine, arg)
  166.     SYS_INT_DISCONNECT (pDrvCtrl, routine, arg)
  167.     SYS_INT_ENABLE(pDrvCtrl)
  168.     SYS_OUT_SHORT(pDrvCtrl, reg, data)
  169.     SYS_IN_SHORT(pDrvCtrl, reg, pData)
  170. .CE
  171. There are default values in the source code for these macros.  They presume
  172. memory-mapped accesses to the device registers and the normal intConnect(),
  173. and intEnable() BSP functions.  The first argument to each is the device
  174. controller structure. Thus, each has access back to all the device-specific
  175. information.  Having the pointer in the macro facilitates the addition 
  176. of new features to this driver.
  177. SYSTEM RESOURCE USAGE
  178. When implemented, this driver requires the following system resources:
  179.     - one interrupt vector
  180.     - 68 bytes in the initialized data section (data) /@HELP@/
  181.     - 0 bytes of bss /@HELP@/
  182. The above data and BSS requirements are for the MC68020 architecture
  183. and can vary for other architectures.  Code size (text) varies greatly 
  184. between architectures and is therefore not quoted here.
  185. If the driver is not given a specific region of memory using the ln7990EndLoad()
  186. routine, then it calls cacheDmaMalloc() to allocate the memory to be shared
  187. with the LANCE.  The size requested is 80,542 bytes.  If a memory region
  188. is provided to the driver, the size of this region is adjustable to suit
  189. user needs.
  190. The LANCE can only be operated if the shared memory region is write-coherent
  191. with the data cache.  The driver cannot maintain cache coherency for data 
  192. that is written by the driver. That is because members within the shared 
  193. structures are asynchronously modified by both the driver and the device, 
  194. and these members might share the same cache line.
  195. SEE ALSO: muxLib,
  196. .I "Advanced Micro Devices Local Area Network Controller Am7990 (LANCE)"
  197. */
  198. #include "vxWorks.h"
  199. #include "wdLib.h"
  200. #include "stdlib.h"
  201. #include "taskLib.h"
  202. #include "logLib.h"
  203. #include "intLib.h"
  204. #include "netLib.h"
  205. #include "stdio.h"
  206. #include "stdlib.h"
  207. #include "sysLib.h"
  208. #include "iv.h"
  209. #include "memLib.h"
  210. #include "semLib.h"
  211. #include "cacheLib.h"
  212. #include "sys/ioctl.h"
  213. #ifndef DOC             /* don't include when building documentation */
  214. #include "net/mbuf.h"
  215. #endif  /* DOC */
  216. #include "net/protosw.h"
  217. #include "sys/socket.h"
  218. #include "errno.h"
  219. #include "net/if.h"
  220. #include "net/route.h"
  221. #include "netinet/in.h"
  222. #include "netinet/in_systm.h"
  223. #include "netinet/in_var.h"
  224. #include "netinet/ip.h"
  225. #include "netinet/if_ether.h"
  226. #include "net/if_subr.h"
  227. #include "m2Lib.h"
  228. #include "drv/end/ln7990EndCommon.h" /* Common defines. */
  229. #include "drv/end/ln7990End.h" /* device description header */
  230. #include "etherMultiLib.h" /* multicast stuff. */
  231. #include "end.h" /* Common END structures. */
  232. #include "netBufLib.h"
  233. #include "muxLib.h"
  234. #undef END_MACROS
  235. #include "endLib.h"
  236. #include "lstLib.h" /* Needed to maintain protocol list. */
  237. /***** LOCAL DEFINITIONS *****/
  238. #define DELAY(count) {                                               
  239. volatile int cx = 0;                            
  240. for (cx = 0; cx < (count); cx++);               
  241. }
  242. /* Configuration items */
  243. #define LN_BUFSIZ      (ETHERMTU + SIZEOF_ETHERHEADER + 6)
  244. #define LN_RMD_RLEN     5       /* ring size as a power of 2 -- 32 RMD's */
  245. #define LN_TMD_TLEN     5       /* same for transmit ring    -- 32 TMD's */
  246. #define LN_SPEED        10000000
  247. /* Naming items */
  248. #define LN_DEV_NAME "ln"
  249. #define LN_DEV_NAME_LEN 3
  250. /*
  251.  * If LN_KICKSTART_TX is TRUE the transmitter is kick-started to force a
  252.  * read of the transmit descriptors, otherwise the internal polling (1.6msec)
  253.  * will initiate a read of the descriptors.  This should be FALSE is there
  254.  * is any chance of memory latency or chip accesses detaining the LANCE DMA,
  255.  * which results in a transmitter UFLO error.  This can be changed with the
  256.  * global lnKickStartTx below.
  257.  */
  258. #define LN_KICKSTART_TX TRUE
  259. /* Cache macros */
  260. #define LN_CACHE_INVALIDATE(address, len) 
  261.         CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
  262. #define LN_CACHE_PHYS_TO_VIRT(address) 
  263.         CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
  264. #define LN_CACHE_VIRT_TO_PHYS(address) 
  265.         CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
  266. /*
  267.  * Default macro definitions for BSP interface.
  268.  * These macros can be redefined in a wrapper file, to generate
  269.  * a new module with an optimized interface.
  270.  */
  271. #ifndef SYS_INT_CONNECT
  272. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) 
  273.     { 
  274.     IMPORT STATUS sysIntConnect(); 
  275.     *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), 
  276.      rtn, (int)arg); 
  277.     }
  278. #endif /*SYS_INT_CONNECT*/
  279. #ifndef SYS_INT_DISCONNECT
  280. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) 
  281.     { 
  282.     *pResult = OK; /* HELP: need a real routine */ 
  283.     }
  284. #endif /*SYS_INT_DISCONNECT*/
  285. #ifndef SYS_INT_ENABLE
  286. #define SYS_INT_ENABLE(pDrvCtrl) 
  287.     { 
  288.     IMPORT void sysLanIntEnable(); 
  289.     sysLanIntEnable (pDrvCtrl->ilevel); 
  290.     }
  291. #endif /*SYS_INT_ENABLE*/
  292. #ifndef SYS_OUT_SHORT
  293. #define SYS_OUT_SHORT(pDrvCtrl,addr,value) 
  294.     { 
  295.     *(USHORT *)addr = value; 
  296.     }
  297. #endif /*SYS_OUT_SHORT*/
  298. #ifndef SYS_IN_SHORT
  299. #define SYS_IN_SHORT(pDrvCtrl,addr,pData) 
  300.     (*(USHORT *)pData = *(USHORT *)addr)
  301. #endif /*SYS_IN_SHORT*/
  302. #ifndef SYS_ENET_ADDR_GET
  303. #define SYS_ENET_ADDR_GET(pAddress) 
  304.     { 
  305.     IMPORT unsigned char lnEnetAddr[]; 
  306.     bcopy ((char *)lnEnetAddr, (char *)(pAddress), 6); 
  307.     }
  308. #endif /* SYS_ENET_ADDR_GET */
  309. /* A shortcut for getting the hardware address from the MIB II stuff. */
  310. #define END_HADDR(pEnd)
  311. ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  312. #define END_HADDR_LEN(pEnd) 
  313. ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  314. #define END_FLAGS_ISSET(pEnd, setBits)                                  
  315.             ((pEnd)->flags & (setBits))
  316. typedef struct free_args
  317.     {
  318.     void* arg1;
  319.     void* arg2;
  320.     } FREE_ARGS;
  321.         
  322. /* The definition of the driver control structure */
  323. typedef struct ln_device
  324.     {
  325.     END_OBJ     end; /* The class we inherit from. */
  326.     ln_ib       *ib; /* ptr to Initialization Block */
  327.     int unit; /* unit number */
  328.     int rmdIndex; /* current RMD index */
  329.     int rringSize; /* RMD ring size */
  330.     int  rringLen;  /* RMD ring length (bytes) */
  331.     ln_rmd* pRring; /* RMD ring start */
  332.     int tmdIndex; /* current TMD index */
  333.     int tmdIndexC; /* current TMD index */
  334.     int tringSize; /* TMD ring size */
  335.     int  tringLen;               /* TMD ring length (bytes) */
  336.     ln_tmd* pTring; /* TMD ring start */
  337.     int         ivec;                   /* interrupt vector */
  338.     int         ilevel;                 /* interrupt level */
  339.     u_short* pCsr;               /* device register CSR */
  340.     u_short* pRap;               /* device register RAP */
  341.     char*       pShMem;                 /* real ptr to shared memory */
  342.     char*       memBase;                /* LANCE memory pool base */
  343.     char*       memAdrs;                /* LANCE memory pool base */
  344.     int         memSize;                /* LANCE memory pool size */
  345.     int         memWidth;               /* width of data port */
  346.     int         offset;
  347.     int         csr0Errs;               /* count of csr0 errors */
  348.     long flags; /* Our local flags. */
  349.     UCHAR enetAddr[6]; /* ethernet address */
  350.     USHORT csr3B;
  351.     CACHE_FUNCS cacheFuncs;             /* cache function pointers */
  352.     BOOL txBlocked;  /* transmit flow control */
  353.     BOOL        txCleaning;
  354.     FUNCPTR     freeRtn[128];           /* Array of free routines. */
  355.     struct free_args    freeData[128];          /* Array of free arguments */
  356.                                         /* the free routines. */
  357.     CL_POOL_ID  pClPoolId;
  358.     END_ERR     lastError;              /* Last error passed to muxError */
  359.     BOOL        errorHandling;          /* task level error handling */
  360.     u_short     errorStat;              /* error status */
  361.     } LN7990END_DEVICE;
  362. /* Definitions for the flags field */
  363. #define LS_PROMISCUOUS_FLAG     0x1
  364. #define LS_MEM_ALLOC_FLAG       0x2
  365. #define LS_PAD_USED_FLAG        0x4
  366. #define LS_RCV_HANDLING_FLAG    0x8
  367. #define LS_POLLING 0x20
  368. /* network buffers configuration */
  369. M_CL_CONFIG lnMclConfig =  /* mBlk configuration table */
  370.     {
  371.     0, 0, NULL, 0
  372.     };
  373. CL_DESC lnClDescTbl [] =  /* network cluster pool configuration table */
  374.     {
  375.     /* 
  376.     clusterSize num memArea memSize
  377.     ----------- ---- ------- -------
  378.     */
  379.     {LN_BUFSIZ, 0, NULL, 0}
  380.     }; 
  381. int lnClDescTblNumEnt = (NELEMENTS(lnClDescTbl));
  382. /***** DEBUG MACROS *****/
  383. #undef DRV_DEBUG
  384. #ifdef DRV_DEBUG
  385. #define DRV_DEBUG_OFF 0x0000
  386. #define DRV_DEBUG_RX 0x0001
  387. #define DRV_DEBUG_TX 0x0002
  388. #define DRV_DEBUG_INT 0x0004
  389. #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
  390. #define DRV_DEBUG_POLL_RX 0x0008
  391. #define DRV_DEBUG_POLL_TX 0x0010
  392. #define DRV_DEBUG_LOAD 0x0020
  393. #define DRV_DEBUG_IOCTL 0x0040
  394. #define DRV_DEBUG_POLL_REDIR 0x10000
  395. #define DRV_DEBUG_LOG_NVRAM 0x20000
  396. #ifdef LOCAL
  397. #undef LOCAL
  398. #endif /* LOCAL */
  399. #define LOCAL ;
  400. int ln7990Debug = DRV_DEBUG_OFF; /* Turn it off initially. */
  401. #include "nvLogLib.h"
  402. NET_POOL ln7990NetPool;
  403. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)                        
  404. if ((ln7990Debug & FLG)&&(FLG & DRV_DEBUG_POLL))                
  405.             nvLogMsg(X0, X1, X2, X3, X4, X5, X6);                       
  406.         else if (ln7990Debug & FLG)                                     
  407.             logMsg(X0, X1, X2, X3, X4, X5, X6);
  408. #define DRV_PRINT(FLG,X)                                                
  409. if (ln7990Debug & FLG) printf X;
  410. #else /*DRV_DEBUG*/
  411. #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
  412. #define DRV_PRINT(DBG_SW,X)
  413. #endif /*DRV_DEBUG*/
  414. /***** LOCALS *****/
  415. LOCAL int lnTsize = LN_TMD_TLEN;    /* deflt xmit ring size as power of 2 */
  416. LOCAL int lnRsize = LN_RMD_RLEN;    /* deflt recv ring size as power of 2 */
  417. LOCAL BOOL lnKickStartTx = LN_KICKSTART_TX;
  418. /* forward static functions */
  419. LOCAL void ln7990Reset (LN7990END_DEVICE *pDrvCtrl);
  420. LOCAL void ln7990Int (LN7990END_DEVICE *pDrvCtrl);
  421. LOCAL void ln7990HandleRecvInt (LN7990END_DEVICE *pDrvCtrl);
  422. LOCAL STATUS ln7990Recv (LN7990END_DEVICE *pDrvCtrl, ln_rmd *rmd);
  423. LOCAL ln_rmd * ln7990FullRMDGet (LN7990END_DEVICE *pDrvCtrl);
  424. LOCAL u_short ln7990Csr0Read (LN7990END_DEVICE * pDrvCtrl);
  425. LOCAL void ln7990CsrWrite (LN7990END_DEVICE * pDrvCtrl, int reg,
  426. u_short value);
  427. LOCAL void ln7990Restart (LN7990END_DEVICE *pDrvCtrl);
  428. LOCAL STATUS  ln7990RestartSetup (LN7990END_DEVICE *pDrvCtrl);
  429. LOCAL void ln7990Config (LN7990END_DEVICE *pDrvCtrl);
  430. LOCAL void ln7990AddrFilterSet (LN7990END_DEVICE *pDrvCtrl);
  431. LOCAL void ln7990ScrubTRing (LN7990END_DEVICE* pDrvCtrl);
  432. LOCAL void      ln7990HandleError (LN7990END_DEVICE  *pDrvCtrl);
  433. /* END Specific interfaces. */
  434. /* This is the only externally visible interface. */
  435. END_OBJ*  ln7990EndLoad (char* initString);
  436. LOCAL STATUS ln7990Start (LN7990END_DEVICE* pDrvCtrl);
  437. LOCAL STATUS ln7990Stop (LN7990END_DEVICE* pDrvCtrl);
  438. LOCAL STATUS ln7990Unload (LN7990END_DEVICE* pDrvCtrl);
  439. LOCAL int ln7990Ioctl (LN7990END_DEVICE* pDrvCtrl, int cmd, caddr_t data);
  440. LOCAL STATUS ln7990Send (LN7990END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
  441.   
  442. LOCAL STATUS ln7990MCastAddrAdd (LN7990END_DEVICE* pDrvCtrl, char* pAddress);
  443. LOCAL STATUS ln7990MCastAddrDel (LN7990END_DEVICE* pDrvCtrl, char* pAddress);
  444. LOCAL STATUS ln7990MCastAddrGet (LN7990END_DEVICE* pDrvCtrl,
  445.     MULTI_TABLE* pTable);
  446. LOCAL STATUS ln7990PollSend (LN7990END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
  447. LOCAL STATUS ln7990PollReceive (LN7990END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
  448. LOCAL STATUS ln7990PollStart (LN7990END_DEVICE* pDrvCtrl);
  449. LOCAL STATUS ln7990PollStop (LN7990END_DEVICE* pDrvCtrl);
  450. LOCAL STATUS ln7990InitParse ();
  451. LOCAL STATUS ln7990InitMem ();
  452. /*
  453.  * Declare our function table.  This is static across all driver
  454.  * instances.
  455.  */
  456. LOCAL NET_FUNCS lnFuncTable =
  457.     {
  458.     (FUNCPTR)ln7990Start, /* Function to start the device. */
  459.     (FUNCPTR)ln7990Stop, /* Function to stop the device. */
  460.     (FUNCPTR)ln7990Unload, /* Unloading function for the driver. */
  461.     (FUNCPTR)ln7990Ioctl, /* Ioctl function for the driver. */
  462.     (FUNCPTR)ln7990Send, /* Send function for the driver. */
  463.     (FUNCPTR)ln7990MCastAddrAdd,/* Multicast address add */
  464.     (FUNCPTR)ln7990MCastAddrDel,/* Multicast address delete */
  465.     (FUNCPTR)ln7990MCastAddrGet,/* Multicast table retrieve */
  466.     (FUNCPTR)ln7990PollSend, /* Polling send function for the driver. */
  467.     (FUNCPTR)ln7990PollReceive, /* Polling receive function for the driver. */
  468.     endEtherAddressForm,        /* Put address info into a packet.  */
  469.     endEtherPacketDataGet,      /* Get a pointer to packet data. */
  470.     endEtherPacketAddrGet       /* Get packet addresses. */
  471.     };
  472. /* external IMPORT's */
  473. #ifndef END_MACROS
  474. IMPORT int endMultiLstCnt (END_OBJ *);
  475. #endif
  476. /******************************************************************************
  477. *
  478. * ln7990EndLoad - initialize the driver and device
  479. *
  480. * This routine initializes the driver and the device to the operational state.
  481. * All of the device-specific parameters are passed in <initString>, which
  482. * expects a string of the following format:
  483. *
  484. * <unit>:<CSR_reg_addr>:<RAP_reg_addr>:<int_vector>:<int_level>:<shmem_addr>:
  485. * <shmem_size>:<shmem_width>
  486. *
  487. * This routine can be called in two modes. If it is called with an empty but
  488. * allocated string, it places the name of this device (that is, "ln") into 
  489. * the <initString> and returns 0.
  490. *
  491. * If the string is allocated and not empty, the routine attempts to load
  492. * the driver using the values specified in the string.
  493. *
  494. * RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
  495. * device if the <initString> was NULL.
  496. */
  497. END_OBJ* ln7990EndLoad
  498.     (
  499.     char* initString /* string to be parse by the driver */
  500.     )
  501.     {
  502.     LN7990END_DEVICE  *pDrvCtrl;
  503.     DRV_LOG (DRV_DEBUG_LOAD, "Loading ln...n", 1, 2, 3, 4, 5, 6);
  504.     if (initString == NULL)
  505.         return (NULL);
  506.     
  507.     if (initString[0] == 0)
  508.         {
  509.         bcopy((char *)LN_DEV_NAME, initString, LN_DEV_NAME_LEN);
  510.         return (0);
  511.         }
  512.     
  513.     /* allocate the device structure */
  514.     pDrvCtrl = (LN7990END_DEVICE *)calloc (sizeof (LN7990END_DEVICE), 1);
  515.     if (pDrvCtrl == NULL)
  516. goto errorExit;
  517.     /* parse the init string, filling in the device structure */
  518.     if (ln7990InitParse (pDrvCtrl, initString) == ERROR)
  519. goto errorExit;
  520.     /* Have the BSP hand us our address. */
  521.     SYS_ENET_ADDR_GET(&(pDrvCtrl->enetAddr));
  522.     /* initialize the END and MIB2 parts of the structure */
  523.     if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, LN_DEV_NAME,
  524.     pDrvCtrl->unit, &lnFuncTable,
  525.                       "AMD 7990 Lance Enhanced Network Driver") == ERROR
  526.      || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
  527.                       &pDrvCtrl->enetAddr[0], 6, ETHERMTU,
  528.                       LN_SPEED)
  529.     == ERROR)
  530. goto errorExit;
  531.     /* Perform memory allocation */
  532.     if (ln7990InitMem (pDrvCtrl) == ERROR)
  533. goto errorExit;
  534.     /* Perform memory distribution and reset and reconfigure the device */
  535.     if (ln7990RestartSetup (pDrvCtrl) == ERROR)
  536.         goto errorExit;
  537.     /* set the flags to indicate readiness */
  538.     END_OBJ_READY (&pDrvCtrl->end,
  539.     IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
  540.     | IFF_MULTICAST | IFF_SIMPLEX);
  541.     
  542.     DRV_LOG (DRV_DEBUG_LOAD, "Done loading ln7990...n", 1, 2, 3, 4, 5, 6);
  543.     return (&pDrvCtrl->end);
  544. errorExit:
  545.     if (pDrvCtrl != NULL)
  546. free ((char *)pDrvCtrl);
  547.     return NULL;
  548.     }
  549. /*******************************************************************************
  550. *
  551. * ln7990InitParse - parse the initialization string
  552. *
  553. * Parse the input string.  Fill in values in the driver control structure.
  554. * The initialization string format is:
  555. * <unit>:<csrAdr>:<rapAdr>:<vecnum>:<intLvl>:<memAdrs>:<memSize>:<memWidth>:
  556. * <offset>:<csr3B>
  557. *
  558. * .IP <unit>
  559. * Device unit number, a small integer.
  560. * .IP <csrAdr>
  561. * Address of CSR0 register.
  562. * .IP <rapAdr>
  563. * Address of RAP register.
  564. * .IP <vecNum>
  565. * Interrupt vector number (used with sysIntConnect() ).
  566. * .IP <intLvl>
  567. * Interrupt level.
  568. * .IP <memAdrs>
  569. * Memory pool address or NONE.
  570. * .IP <memSize>
  571. * Memory pool size or zero.
  572. * .IP <memWidth>
  573. * Memory system size, 1, 2, or 4 bytes (optional).
  574. * .IP <offset>
  575. * Memory offset for alignment.
  576. * .IP <csr3B>
  577. * CSR register 3B control value, normally 0x4 or 0x7.
  578. *
  579. * RETURNS: OK, or ERROR if any arguments are invalid.
  580. */
  581. LOCAL STATUS ln7990InitParse
  582.     (
  583.     LN7990END_DEVICE * pDrvCtrl,
  584.     char * initString
  585.     )
  586.     {
  587.     char * tok;
  588.     char * pHolder = NULL;
  589.     long address;
  590.     
  591.     /* Parse the initString */
  592.     /* Unit number. */
  593.     tok = strtok_r (initString, ":", &pHolder);
  594.     if (tok == NULL)
  595. return ERROR;
  596.     pDrvCtrl->unit = atoi (tok);
  597.     /* CSR address. */
  598.     
  599.     tok = strtok_r (NULL, ":", &pHolder);
  600.     if (tok == NULL)
  601. return ERROR;
  602.     address = strtoul (tok, NULL, 16);
  603.     pDrvCtrl->pCsr = (UINT16 *)address;
  604.     /* RAP address. */
  605.     tok = strtok_r (NULL, ":", &pHolder);
  606.     if (tok == NULL)
  607. return ERROR;
  608.     address = strtoul (tok, NULL, 16);
  609.     pDrvCtrl->pRap = (UINT16 *)address;
  610.     /* Interrupt vector. */
  611.     tok = strtok_r (NULL, ":", &pHolder);
  612.     if (tok == NULL)
  613. return ERROR;
  614.     pDrvCtrl->ivec = atoi (tok);
  615.     /* Interrupt level. */
  616.     tok = strtok_r (NULL, ":", &pHolder);
  617.     if (tok == NULL)
  618. return ERROR;
  619.     pDrvCtrl->ilevel = atoi (tok);
  620.     /* Caller supplied memory address. */
  621.     tok = strtok_r (NULL, ":", &pHolder);
  622.     if (tok == NULL)
  623. return ERROR;
  624.     pDrvCtrl->memAdrs = (char *)strtoul (tok, NULL, 16);
  625.     /* Caller supplied memory size. */
  626.     tok = strtok_r (NULL, ":", &pHolder);
  627.     if (tok == NULL)
  628. return ERROR;
  629.     pDrvCtrl->memSize = strtoul (tok, NULL, 16);
  630.     /* Caller supplied memory width. */
  631.     tok = strtok_r (NULL, ":", &pHolder);
  632.     if (tok == NULL)
  633. return ERROR;
  634.     pDrvCtrl->memWidth = atoi (tok);
  635.     /* Caller supplied alignment offset. */
  636.     tok = strtok_r (NULL, ":", &pHolder);
  637.     if (tok == NULL)
  638. return ERROR;
  639.     pDrvCtrl->offset = atoi (tok);
  640.     /* Do we use csr3B? */
  641.     tok = strtok_r (NULL, ":", &pHolder);
  642.     if (tok == NULL)
  643. return ERROR;
  644.     pDrvCtrl->csr3B = atoi (tok);
  645.     DRV_LOG (DRV_DEBUG_LOAD, "Processed all arugmentsn", 1, 2, 3, 4, 5, 6);
  646.     return OK;
  647.     }
  648. /*******************************************************************************
  649. *
  650. * ln7990InitMem - initialize memory for Lance chip
  651. *
  652. * Using data in the control structure, setup and initialize the memory
  653. * areas needed.  If the memory address is not already specified, then allocate
  654. * cache safe memory.
  655. *
  656. * RETURNS: OK or ERROR.
  657. */
  658. LOCAL STATUS ln7990InitMem
  659.     (
  660.     LN7990END_DEVICE * pDrvCtrl /* device to be initialized */
  661.     )
  662.     {
  663.     UINT sz;            /* temporary size holder */
  664.     int  ix;
  665.     ln_rmd *  pRmd;
  666.     void *  pTemp;
  667.     char*  pTempBuf;
  668.     /***** Establish size of shared memory region we require *****/
  669.     if ((int) pDrvCtrl->memAdrs != NONE)  /* specified memory pool */
  670.         {
  671.         /*
  672.          * With a specified memory pool we want to maximize
  673.          * lnRsize and lnTsize
  674.          */
  675.         sz = (pDrvCtrl->memSize - (RMD_SIZ + TMD_SIZ + sizeof (ln_ib)))
  676.                / ((2 * LN_BUFSIZ) + RMD_SIZ + TMD_SIZ);
  677.         sz >>= 1;               /* adjust for roundoff */
  678.         for (lnRsize = 0; sz != 0; lnRsize++, sz >>= 1)
  679.             ;
  680.         lnTsize = lnRsize;      /* lnTsize = lnRsize for convenience */
  681.         }
  682.     /* limit ring sizes to reasonable values */
  683.     lnRsize = max (lnRsize, 2); /* 4 Rx buffers is reasonable min */
  684.     lnRsize = min (lnRsize, 7); /* 128 Rx buffers is max for chip */
  685.     lnTsize = max (lnTsize, 2); /* 4 Tx buffers is reasonable min */
  686.     lnTsize = min (lnTsize, 7); /* 128 Tx buffers is max for chip */
  687.     /* Add it all up */
  688.     sz = (((1 << lnRsize) + 1) * RMD_SIZ) +
  689.         (((1 << lnTsize) + 1) * TMD_SIZ) +  IB_SIZ + 28;
  690.     /***** Establish a region of shared memory *****/
  691.     /* OK. We now know how much shared memory we need.  If the caller
  692.      * provides a specific memory region, we check to see if the provided
  693.      * region is large enough for our needs.  If the caller did not
  694.      * provide a specific region, then we attempt to allocate the memory
  695.      * from the system, using the cache aware allocation system call.
  696.      */
  697.     switch ((int) pDrvCtrl->memAdrs)
  698.         {
  699.         default :       /* caller provided memory */
  700.             if (pDrvCtrl->memSize < sz)     /* not enough space */
  701.                 {
  702. DRV_LOG (DRV_DEBUG_LOAD, "ln7990: not enough memory providedn"
  703.                          "ln7990: need %ul got %dn",
  704.                          pDrvCtrl->memSize, sz, 3, 4, 5, 6);
  705.                 return (ERROR);
  706.                 }
  707.     /* set the beginning of pool */
  708.             pDrvCtrl->pShMem = pDrvCtrl->memAdrs;
  709.             /* assume pool is cache coherent, copy null structure */
  710.             pDrvCtrl->cacheFuncs = cacheNullFuncs;
  711.     DRV_LOG (DRV_DEBUG_LOAD, "Memory checks outn", 1, 2, 3, 4, 5, 6);
  712.             break;
  713.         case NONE :     /* get our own memory */
  714.             /* Because the structures that are shared between the device
  715.              * and the driver may share cache lines, the possibility exists
  716.              * that the driver could flush a cache line for a structure and
  717.              * wipe out an asynchronous change by the device to a neighboring
  718.              * structure. Therefore, this driver cannot operate with memory
  719.              * that is not write coherent.  We check for the availability of
  720.              * such memory here, and abort if the system did not give us what
  721.              * we need.
  722.              */
  723.             if (!CACHE_DMA_IS_WRITE_COHERENT ())
  724.                 {
  725.                 printf ("ln: device requires cache coherent memoryn");
  726.                 return (ERROR);
  727.                 }
  728.             pDrvCtrl->pShMem = (char *) cacheDmaMalloc (sz);
  729.             if (pDrvCtrl->pShMem == NULL)
  730.                 {
  731.                 printf ("ln: system memory unavailablen");
  732.                 return (ERROR);
  733.                 }
  734.             /* copy the DMA structure */
  735.             pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  736.             break;
  737.         }
  738.     /*                        Turkey Carving
  739.      *                        --------------
  740.      *
  741.      *                          LOW MEMORY
  742.      *
  743.      *             |-------------------------------------|
  744.      *             |       The initialization block      |
  745.      *             |         (sizeof (ln_ib))            |
  746.      *             |-------------------------------------|
  747.      *             |         The Rx descriptors          |
  748.      *             | ((1 << lnRsize) + 1)*sizeof (ln_rmd)|
  749.      *             |-------------------------------------|
  750.      *             |         The Tx descriptors          |
  751.      *             | ((1 << lnTsize) + 1)*sizeof (ln_tmd)|
  752.      *             |-------------------------------------|
  753.      */
  754.     /* align */
  755.     pDrvCtrl->pShMem = (char *) ( ( (int)pDrvCtrl->pShMem + 3) & ~3);
  756.     /* Save some things */
  757.     pDrvCtrl->memBase  = (char *)((ULONG)pDrvCtrl->pShMem & 0xff000000);
  758.     if ((int) pDrvCtrl->memAdrs == NONE)
  759.         pDrvCtrl->flags |= LS_MEM_ALLOC_FLAG;
  760.     /* first let's clear memory */
  761.     bzero ((char *) pDrvCtrl->pShMem, (int) sz); /* HELP: deal with memWidth */
  762.     /* setup Rx memory pointers */
  763.     pDrvCtrl->pRring = (ln_rmd *) ((((int)pDrvCtrl->pShMem + IB_SIZ) + 7) &~7);
  764.     pDrvCtrl->rringLen  = lnRsize;
  765.     pDrvCtrl->rringSize = 1 << lnRsize;
  766.     pDrvCtrl->rmdIndex = 0;
  767.     /* setup Tx memory pointers. */
  768.     pDrvCtrl->pTring = (ln_tmd *) ((int)pDrvCtrl->pRring +
  769. ((1 << lnRsize) + 1) * RMD_SIZ);
  770.     pDrvCtrl->tringSize = 1 << lnTsize;
  771.     pDrvCtrl->tringLen  = lnTsize;
  772.     pDrvCtrl->tmdIndex = 0;
  773.     pDrvCtrl->tmdIndexC = 0;
  774.     /* Set up the structures to allow us to free data after sending it. */
  775.     
  776.     for (ix = 0; ix < pDrvCtrl->rringSize; ix++)
  777.         {
  778.         pDrvCtrl->freeRtn[ix] = NULL;
  779.         pDrvCtrl->freeData[ix].arg1 = NULL;
  780.         pDrvCtrl->freeData[ix].arg2 = NULL;
  781.         }
  782.     /*
  783.      * Allocate receive buffers from our own private pool.
  784.      */
  785.     if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  786.         return (ERROR);
  787.     lnMclConfig.mBlkNum = pDrvCtrl->rringSize * 2;
  788.     lnClDescTbl[0].clNum = pDrvCtrl->rringSize *2;
  789.     lnMclConfig.clBlkNum = lnClDescTbl[0].clNum;
  790.     lnMclConfig.memSize = (lnMclConfig.mBlkNum * (MSIZE + sizeof (long))) +
  791.                           (lnMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));
  792.     if ((lnMclConfig.memArea = (char *) memalign (sizeof(long),
  793.                                                   lnMclConfig.memSize))
  794.         == NULL)
  795.         return (ERROR);
  796.     
  797.     lnClDescTbl[0].clNum = pDrvCtrl->rringSize *2;
  798.     
  799.     lnClDescTbl[0].memSize = (lnClDescTbl[0].clNum * (LN_BUFSIZ + 8))
  800.         + sizeof(int);
  801.     if ((int) pDrvCtrl->memAdrs != NONE) /* Do we hand over our own memory? */
  802.         {
  803.         lnClDescTbl[0].memArea = 
  804.                 (char *)(pDrvCtrl->pTring + (((1 << lnTsize) + 1) * TMD_SIZ));
  805.         }
  806.     else
  807.         {
  808.         lnClDescTbl[0].memArea =
  809.             (char *) cacheDmaMalloc (lnClDescTbl[0].memSize);
  810.         if (lnClDescTbl[0].memArea == NULL)
  811.             {
  812.             DRV_LOG(DRV_DEBUG_LOAD,
  813.                     "system memory unavailablen", 1, 2, 3, 4, 5, 6);
  814.             return (ERROR);
  815.             }
  816.         }
  817.     
  818.     if (netPoolInit(pDrvCtrl->end.pNetPool, &lnMclConfig,
  819.                     &lnClDescTbl[0], lnClDescTblNumEnt, NULL) == ERROR)
  820.         {
  821.         DRV_LOG (DRV_DEBUG_LOAD, "Could not init bufferingn",
  822.                  1, 2, 3, 4, 5, 6);
  823.         return (ERROR);
  824.         }
  825. #ifdef DRV_DEBUG
  826.     ln7990NetPool = *pDrvCtrl->end.pNetPool;
  827. #endif
  828.     /* Store the cluster pool id as others need it later. */
  829.     pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool,
  830.                                       LN_BUFSIZ, FALSE);
  831.     pRmd = pDrvCtrl->pRring;
  832.     for (ix = 0; ix < pDrvCtrl->rringSize; ix++, pRmd++)
  833.         {
  834.         if ((pTempBuf = (char *)netClusterGet(pDrvCtrl->end.pNetPool,
  835.                                               pDrvCtrl->pClPoolId))
  836.             == NULL)
  837.             {
  838.             DRV_LOG (DRV_DEBUG_LOAD, "Could not get a buffern",
  839.                      1, 2, 3, 4, 5, 6);
  840.             return (ERROR);
  841.             }
  842.         pTempBuf += pDrvCtrl->offset;
  843.         LN_RMD_BUF_TO_ADDR (pRmd, pTemp, pTempBuf);
  844.         }
  845.     return OK;
  846.     }
  847. /*******************************************************************************
  848. *
  849. * ln7990Start - start the device
  850. *
  851. * This function calls BSP functions to connect interrupts and start the
  852. * device running in interrupt mode.
  853. *
  854. * RETURNS: OK or ERROR
  855. *
  856. */
  857. LOCAL STATUS ln7990Start
  858.     (
  859.     LN7990END_DEVICE *pDrvCtrl
  860.     )
  861.     {
  862.     STATUS result;
  863.     pDrvCtrl->txCleaning = FALSE;
  864.     pDrvCtrl->txBlocked = FALSE;
  865.     SYS_INT_CONNECT (pDrvCtrl, ln7990Int, (int)pDrvCtrl, &result);
  866.     if (result == ERROR)
  867. return ERROR;
  868.     DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
  869.     SYS_INT_ENABLE (pDrvCtrl);
  870.     DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
  871.     return (OK);
  872.     }
  873. /*******************************************************************************
  874. *
  875. * ln7990HandleError - handle controller interrupt errors
  876. *
  877. * This routine is called to process controller errors at a task level that 
  878. * were detecected in interrupt context.
  879. *
  880. * RETURNS: N/A.
  881. */
  882. LOCAL void ln7990HandleError
  883.     (
  884.     LN7990END_DEVICE  *pDrvCtrl
  885.     )
  886.     {
  887.     u_short stat;
  888.     pDrvCtrl->errorHandling = FALSE;
  889.     stat = pDrvCtrl->errorStat;
  890.     pDrvCtrl->errorStat &= ~stat;
  891.     
  892.     if (stat & lncsr_MERR)
  893. {
  894. pDrvCtrl->lastError.errCode = END_ERR_RESET;
  895. pDrvCtrl->lastError.pMesg = "Memory error.";
  896. muxError (&pDrvCtrl->end, &pDrvCtrl->lastError);
  897. }
  898.     if (stat & lncsr_BABL)
  899. {
  900. pDrvCtrl->lastError.errCode = END_ERR_WARN;
  901. pDrvCtrl->lastError.pMesg = "Babbling";
  902. muxError (&pDrvCtrl->end, &pDrvCtrl->lastError);
  903. }
  904.     if (stat & lncsr_MISS)
  905. {
  906. pDrvCtrl->lastError.errCode = END_ERR_WARN;
  907. pDrvCtrl->lastError.pMesg = "Missing";
  908. muxError (&pDrvCtrl->end, &pDrvCtrl->lastError);
  909. }
  910.     
  911.     return;
  912.     }
  913.     
  914. /*******************************************************************************
  915. *
  916. * ln7990Int - handle controller interrupt
  917. *
  918. * This routine is called at interrupt level in response to an interrupt from
  919. * the controller.
  920. *
  921. * RETURNS: N/A.
  922. */
  923. LOCAL void ln7990Int
  924.     (
  925.     LN7990END_DEVICE  *pDrvCtrl
  926.     )
  927.     {
  928.     u_short        stat;
  929.     ln_rmd         *pRmd;
  930.    /* Read the device status register */
  931.     stat = ln7990Csr0Read (pDrvCtrl);
  932.     DRV_LOG (DRV_DEBUG_INT, "i=0x%x:n", stat, 2, 3, 4, 5, 6);
  933.     /* If false interrupt, return. */
  934.     if (!(stat & lncsr_INTR))
  935. {
  936. DRV_LOG (DRV_DEBUG_INT, "False interrupt.n", 1, 2, 3, 4, 5, 6);
  937.         return;
  938. }
  939.     /*
  940.      * enable interrupts, clear receive and/or transmit interrupts,
  941.      * and clear any errors that may be set.
  942.      */
  943.     ln7990CsrWrite (pDrvCtrl, 0, ((stat &
  944.     (lncsr_BABL|lncsr_CERR|lncsr_MISS|lncsr_MERR|
  945.      lncsr_RINT|lncsr_TINT|lncsr_IDON)) | lncsr_INEA));
  946.     /* Check for errors */
  947.     if (stat & (lncsr_BABL | lncsr_MISS | lncsr_MERR))
  948.         {
  949.         ++pDrvCtrl->csr0Errs;
  950. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  951. if (stat & lncsr_BABL)
  952.     {
  953.     pDrvCtrl->errorStat |= lncsr_BABL;
  954.     if (!pDrvCtrl->errorHandling)
  955. {
  956. if (netJobAdd ((FUNCPTR) ln7990HandleError, (int) pDrvCtrl
  957.        , 2, 3, 4, 5) == OK)
  958.     {
  959.     pDrvCtrl->errorHandling = TRUE;
  960.     }
  961. }
  962.     DRV_LOG (DRV_DEBUG_INT, "Babblingn", 1, 2, 3, 4, 5, 6);
  963.     }
  964. if (stat & lncsr_MISS)
  965.     {
  966.     pDrvCtrl->errorStat |= lncsr_MISS;
  967.     if (!pDrvCtrl->errorHandling)
  968. {
  969. if (netJobAdd ((FUNCPTR) ln7990HandleError, (int) pDrvCtrl
  970.        , 2, 3, 4, 5) == OK)
  971.     {
  972.     pDrvCtrl->errorHandling = TRUE;
  973.     }
  974. }
  975.     DRV_LOG (DRV_DEBUG_INT, "Missingn", 1, 2, 3, 4, 5, 6);
  976.     }
  977.         
  978. /* restart chip on fatal error */
  979.         if (stat & lncsr_MERR)        /* memory error */
  980.             {
  981.     pDrvCtrl->errorStat |= lncsr_MERR;
  982.     if (!pDrvCtrl->errorHandling)
  983. {
  984. if (netJobAdd ((FUNCPTR) ln7990HandleError, (int) pDrvCtrl
  985.        , 2, 3, 4, 5) == OK)
  986.     {
  987.     pDrvCtrl->errorHandling = TRUE;
  988.     }
  989. }
  990.     DRV_LOG (DRV_DEBUG_INT, "Memory error, restarting.n",
  991.                      1, 2, 3, 4, 5, 6);
  992.             END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
  993.     /* Only reset device if Restart will occur */
  994.     if (netJobAdd ((FUNCPTR) ln7990Restart
  995.    , (int) pDrvCtrl, 2, 3, 4, 5) == OK)
  996. {
  997. ln7990Reset (pDrvCtrl);
  998. }
  999.     return;
  1000.     }
  1001.         }
  1002.     /* Have netTask handle any input packets */
  1003.     pRmd =  pDrvCtrl->pRring + pDrvCtrl->rmdIndex;
  1004.     LN_CACHE_INVALIDATE (pRmd, RMD_SIZ);
  1005.     if (((stat & lncsr_RINT) && (stat & lncsr_RXON)) ||
  1006. LN_RMD_OWNED (pRmd) == 0)
  1007.         {
  1008.         DRV_LOG (DRV_DEBUG_INT, "r ", 1, 2, 3, 4, 5, 6);
  1009.         if (!(pDrvCtrl->flags & LS_RCV_HANDLING_FLAG))
  1010.             {
  1011.             if (netJobAdd ((FUNCPTR)ln7990HandleRecvInt, (int)pDrvCtrl,
  1012.                               0,0,0,0) == OK)
  1013. {
  1014. pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;
  1015. }
  1016.     }
  1017.         }
  1018.     /*
  1019.      * Did LANCE update any of the TMD's?
  1020.      * If not then don't bother continuing with transmitter stuff
  1021.      */
  1022.     if (!(stat & lncsr_TINT))
  1023. {
  1024.         return;
  1025. }
  1026.     DRV_LOG (DRV_DEBUG_INT, "t ", 1, 2, 3, 4, 5, 6);
  1027.     
  1028.     if (!pDrvCtrl->txCleaning)
  1029.         {
  1030.         pDrvCtrl->txCleaning = TRUE;
  1031.         netJobAdd ((FUNCPTR)ln7990ScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0);
  1032.         }
  1033.     if (pDrvCtrl->txBlocked) /* cause a restart */
  1034.         {
  1035.         netJobAdd ((FUNCPTR)muxTxRestart, (int) &pDrvCtrl->end, 0, 0, 0, 0);
  1036.         pDrvCtrl->txBlocked = FALSE;
  1037.         }
  1038.     /* Flush the write pipe */
  1039.     CACHE_PIPE_FLUSH ();
  1040.     }
  1041. /*******************************************************************************
  1042. *
  1043. * ln7990HandleRecvInt - task level interrupt service for input packets
  1044. *
  1045. * This routine is called at task level indirectly by the interrupt
  1046. * service routine to do any message received processing.
  1047. *
  1048. * RETURNS: N/A.
  1049. */
  1050. LOCAL void ln7990HandleRecvInt
  1051.     (
  1052.     LN7990END_DEVICE *pDrvCtrl
  1053.     )
  1054.     {
  1055.     ln_rmd *pRmd;
  1056.     do
  1057.         {
  1058.         pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;
  1059.         while ((pRmd = ln7990FullRMDGet (pDrvCtrl)) != NULL)
  1060.             ln7990Recv (pDrvCtrl, pRmd);
  1061.         /*
  1062.          * There is a RACE right here.  The ISR could add a receive packet
  1063.          * and check the boolean below, and decide to exit.  Thus the
  1064.          * packet could be dropped if we don't double check before we
  1065.          * return.
  1066.          */
  1067.         pDrvCtrl->flags &= ~LS_RCV_HANDLING_FLAG;
  1068.         }
  1069.     while (ln7990FullRMDGet (pDrvCtrl) != NULL);
  1070.     /* this double check solves the RACE */
  1071.     }
  1072. /*******************************************************************************
  1073. *
  1074. * ln7990FullRMDGet - get next received message RMD
  1075. *
  1076. * Get next recevied message descriptor.  Returns NULL if none are
  1077. * ready.
  1078. *
  1079. * RETURNS: ptr to next Rx desc to process, or NULL if none ready.
  1080. */
  1081. LOCAL ln_rmd *ln7990FullRMDGet
  1082.     (
  1083.     LN7990END_DEVICE  *pDrvCtrl
  1084.     )
  1085.     {
  1086.     ln_rmd   *pRmd;
  1087.     pRmd = pDrvCtrl->pRring + pDrvCtrl->rmdIndex;  /* form ptr to Rx desc */
  1088.     LN_CACHE_INVALIDATE (pRmd, RMD_SIZ);
  1089.     if (LN_RMD_OWNED (pRmd) == 0)
  1090.         return (pRmd);
  1091.     else
  1092.         return ((ln_rmd *) NULL);
  1093.     }
  1094. /*******************************************************************************
  1095. *
  1096. * ln7990Recv - process the next incoming packet
  1097. *
  1098. * Handle one incoming packet.  The packet is checked for errors.
  1099. *
  1100. * RETURNS: N/A.
  1101. */
  1102. LOCAL STATUS ln7990Recv
  1103.     (
  1104.     LN7990END_DEVICE *pDrvCtrl,
  1105.     ln_rmd   *pRmd
  1106.     )
  1107.     {
  1108.     int         len;
  1109.     u_long phys;
  1110.     M_BLK_ID  pMblk;
  1111.     char*       pCluster;
  1112.     char*       pNewCluster;
  1113.     char*       pTemp;
  1114.     CL_BLK_ID pClBlk;
  1115.     /* Packet must be checked for errors. */
  1116.     /* If error flag */
  1117.     /* OR if packet is not completely in one buffer */
  1118.     if  (LN_RMD_ERR (pRmd))
  1119.         {
  1120. DRV_LOG (DRV_DEBUG_RX, "RMD error!n", 1, 2, 3, 4, 5, 6);
  1121. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1122. goto cleanRXD;
  1123.         }
  1124.     /* If we cannot get a buffer to loan then bail out. */
  1125.     pNewCluster = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
  1126.     if (pNewCluster == NULL)
  1127.         {
  1128. DRV_LOG (DRV_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
  1129. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1130. goto cleanRXD;
  1131.         }
  1132.     if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
  1133.         {
  1134.         netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
  1135. DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
  1136. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1137. goto cleanRXD;
  1138.         }
  1139.     
  1140.     /*
  1141.      * OK we've got a spare, let's get an M_BLK_ID and marry it to the
  1142.      * one in the ring.
  1143.      */
  1144.     if ((pMblk = mBlkGet(pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
  1145.         {
  1146.         netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); 
  1147.         netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
  1148. DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
  1149. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1150. goto cleanRXD;
  1151.         }
  1152.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  1153.     len = LN_PKT_LEN_GET (pRmd);            /* get packet length */
  1154.     /* Get pointer to packet */
  1155.     LN_RMD_TO_ADDR (pDrvCtrl->memBase , pRmd, phys);
  1156.     pCluster = LN_CACHE_PHYS_TO_VIRT (phys);
  1157.     pCluster -= pDrvCtrl->offset;
  1158.     
  1159.     /* Join the cluster to the MBlock */
  1160.     netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0);
  1161.     netMblkClJoin (pMblk, pClBlk);
  1162.     /* make the packet data coherent */
  1163.     LN_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len);
  1164.     pMblk->mBlkHdr.mData += pDrvCtrl->offset;
  1165.     pMblk->mBlkHdr.mLen = len;
  1166.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1167.     pMblk->mBlkPktHdr.len = len;
  1168.     DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!n", 1, 2, 3, 4, 5, 6);
  1169.     /* Deal with memory alignment. */
  1170.     pNewCluster += pDrvCtrl->offset;
  1171.     LN_RMD_BUF_TO_ADDR (pRmd, pTemp, pNewCluster);
  1172.     LN_CLEAN_RXD (pRmd);
  1173.     /* Flush the write pipe */
  1174.     CACHE_PIPE_FLUSH ();
  1175.     /* Advance our management index */
  1176.     pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
  1177.     /* Call the upper layer's receive routine. */
  1178.     END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
  1179.     return (OK);
  1180. cleanRXD:
  1181.     LN_CLEAN_RXD (pRmd);
  1182.     /* Flush the write pipe */
  1183.     CACHE_PIPE_FLUSH ();
  1184.     /* Advance our management index */
  1185.     pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
  1186.     return (OK);
  1187.     }
  1188. /*******************************************************************************
  1189. *
  1190. * ln7990Send - the driver send routine
  1191. *
  1192. * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
  1193. * The buffer must already have the addressing information properly installed
  1194. * in it.  This is done by a higher layer.  The last arguments are a free
  1195. * routine to be called when the device is done with the buffer and a pointer
  1196. * to the argument to pass to the free routine.  
  1197. *
  1198. * RETURNS: OK or ERROR.
  1199. */
  1200. LOCAL STATUS ln7990Send
  1201.     (
  1202.     LN7990END_DEVICE *pDrvCtrl, /* device ptr */
  1203.     M_BLK_ID pMblk /* data to send */
  1204.     )
  1205.     {
  1206.     ln_tmd* pTmd;
  1207.     int         len = 0;
  1208.     void*       pTemp;
  1209.     char*       pBuf;
  1210.     char*       pOrig;
  1211.     int         s;
  1212.     /*
  1213.      * Obtain exclusive access to transmitter.  This is necessary because
  1214.      * we might have more than one stack transmitting at once.
  1215.      */
  1216.     if (!(pDrvCtrl->flags & LS_POLLING))
  1217. END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
  1218.     /*
  1219.      * Here we handle both simple and vector transmit in the same place.
  1220.      *
  1221.      */
  1222. #if 0
  1223.     {
  1224.     M_BLK_ID    pChunk;
  1225.     int         count;
  1226.     pChunk = pMblk;
  1227.     for (count = 0; pChunk != NULL && (pChunk->mBlkHdr.mData != 0);
  1228.          pChunk = pChunk->m_next, count++)
  1229.         {
  1230.         if (pChunk->mBlkHdr.mLen <= 0)
  1231.             {
  1232.             netMblkClFree(pChunk);
  1233.             continue;
  1234.             }
  1235.         pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex;
  1236.         
  1237.         LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);
  1238.         
  1239.         if ((pTmd->tbuf_stat & lntmd1_OWN) ||
  1240.             (((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1))
  1241.              == pDrvCtrl->tmdIndexC))
  1242.             {
  1243.             if (!(pDrvCtrl->flags & LS_POLLING))
  1244.                 END_TX_SEM_GIVE (&pDrvCtrl->end);
  1245.             /* Are we still on the first chunk? */
  1246.             if (count == 0)
  1247.                 netMblkClChainFree(pMblk);
  1248.             else /* Have to iteratively clean up. */
  1249.                 {
  1250.                 
  1251.                 }
  1252.             DRV_LOG (DRV_DEBUG_TX, "Out of TMDs!n", 1, 2, 3, 4, 5, 6);
  1253.             return (END_ERR_BLOCK);
  1254.             }
  1255.         len = pChunk->mBlkHdr.mLen;
  1256.         LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pChunk->mBlkHdr.mData);
  1257.         pTmd->tbuf_err = 0;         /* clear buffer error status */
  1258.         pTmd->tbuf_bcnt = -len;     /* negative message byte count */
  1259.         
  1260.         if (count == 0)
  1261.             pTmd->tbuf_stat |=  lntmd1_STP;
  1262.         
  1263.         pTmd->tbuf_stat |= lntmd1_OWN;
  1264.         pDrvCtrl->freeRtn[pDrvCtrl->tmdIndex] = (FUNCPTR)netMblkClFree;
  1265.         pDrvCtrl->freeData[pDrvCtrl->tmdIndex].arg1 = pChunk;
  1266.         pDrvCtrl->freeData[pDrvCtrl->tmdIndex].arg2 = NULL;
  1267.         /* Advance our management index */
  1268.         pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
  1269.         
  1270.         }
  1271.     
  1272.     /* On the final tmd we set the END bit as well as OWN. */
  1273.     pTmd->tbuf_stat |= lntmd1_OWN | lntmd1_ENP;
  1274.     /* If we only have one TMD for the packet then make sure of size. */
  1275.     if (count == 1)
  1276.         {
  1277.         len = max (len, ETHERSMALL);
  1278.         pTmd->tbuf_bcnt = -len;
  1279.         }
  1280.     
  1281.     }
  1282. #else
  1283.     pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex;
  1284.     
  1285.     LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);
  1286.     
  1287.     if ((pTmd->tbuf_stat & lntmd1_OWN) ||
  1288.         (((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1))
  1289.          == pDrvCtrl->tmdIndexC))
  1290.         {
  1291.         if (!(pDrvCtrl->flags & LS_POLLING))
  1292.             END_TX_SEM_GIVE (&pDrvCtrl->end);
  1293.         /* Are we still on the first chunk? */
  1294.         DRV_LOG (DRV_DEBUG_TX, "Out of TMDs!n", 1, 2, 3, 4, 5, 6);
  1295.         s = intLock();
  1296. pDrvCtrl->txBlocked = TRUE;
  1297.         intUnlock(s);
  1298.         return (END_ERR_BLOCK);
  1299.         }
  1300.     DRV_LOG (DRV_DEBUG_TX, "before cluster get %d %dn",
  1301.              (int) pDrvCtrl->end.pNetPool,
  1302.              (int) pDrvCtrl->pClPoolId, 3, 4, 5, 6);
  1303.     pOrig = pBuf = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
  1304.     DRV_LOG (DRV_DEBUG_TX, "after cluster getn", 1, 2, 3, 4, 5, 6);
  1305.     if (pBuf == NULL)
  1306.         {
  1307. if (!(pDrvCtrl->flags & LS_POLLING))
  1308.     END_TX_SEM_GIVE (&pDrvCtrl->end);
  1309.         netMblkClChainFree(pMblk);
  1310.         return (ERROR);
  1311.         }
  1312.     pBuf += pDrvCtrl->offset;
  1313.     
  1314.     len = netMblkToBufCopy (pMblk, pBuf, NULL);
  1315.     netMblkClChainFree(pMblk); 
  1316.     LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pBuf);
  1317.     len = max (len, ETHERSMALL);
  1318.     pTmd->tbuf_err = 0;         /* clear buffer error status */
  1319.     pTmd->tbuf_bcnt = -len;     /* negative message byte count */
  1320.         
  1321.     pTmd->tbuf_stat |=  lntmd1_STP | lntmd1_OWN | lntmd1_ENP;
  1322.     
  1323.     pDrvCtrl->freeRtn[pDrvCtrl->tmdIndex] = (FUNCPTR)netClFree;
  1324.     pDrvCtrl->freeData[pDrvCtrl->tmdIndex].arg1 = pDrvCtrl->end.pNetPool;
  1325.     pDrvCtrl->freeData[pDrvCtrl->tmdIndex].arg2 = pOrig;
  1326.     /* Advance our management index */
  1327.     pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
  1328. #endif
  1329.     /* Flush the write pipe */
  1330.     
  1331.     CACHE_PIPE_FLUSH ();
  1332.     
  1333.     if (lnKickStartTx)
  1334.         {
  1335.         if (!(pDrvCtrl->flags & LS_POLLING))
  1336.     ln7990CsrWrite (pDrvCtrl, 0, (lncsr_INEA | lncsr_TDMD));
  1337. else
  1338.     ln7990CsrWrite (pDrvCtrl, 0, lncsr_TDMD);
  1339. }
  1340.     
  1341.     if (!(pDrvCtrl->flags & LS_POLLING))
  1342. END_TX_SEM_GIVE (&pDrvCtrl->end);
  1343.     
  1344.     /* Bump the statistic counter. */
  1345.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
  1346.     return (OK);
  1347.     }
  1348. /*******************************************************************************
  1349. *
  1350. * ln7990Ioctl - the driver I/O control routine
  1351. *
  1352. * Process an ioctl request.
  1353. */
  1354. LOCAL int ln7990Ioctl
  1355.     (
  1356.     LN7990END_DEVICE *pDrvCtrl,
  1357.     int cmd,
  1358.     caddr_t data
  1359.     )
  1360.     {
  1361.     int error = 0;
  1362.     long value;
  1363.     switch ((UINT)cmd)
  1364.         {
  1365.         case EIOCSADDR:
  1366.     if (data == NULL)
  1367. return (EINVAL);
  1368.             bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
  1369.    END_HADDR_LEN(&pDrvCtrl->end));
  1370.             break;
  1371.         case EIOCGADDR:
  1372.     if (data == NULL)
  1373. return (EINVAL);
  1374.             bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
  1375.     END_HADDR_LEN(&pDrvCtrl->end));
  1376.             break;
  1377.         case EIOCSFLAGS:
  1378.     value = (long)data;
  1379.     if (value < 0)
  1380. {
  1381. value = -value;
  1382. value--; /* HELP: WHY ??? */
  1383. END_FLAGS_CLR (&pDrvCtrl->end, value);
  1384. }
  1385.     else
  1386. {
  1387. END_FLAGS_SET (&pDrvCtrl->end, value);
  1388. }
  1389.     ln7990Config (pDrvCtrl);
  1390.             break;
  1391.         case EIOCGFLAGS:
  1392.     *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
  1393.             break;
  1394. case EIOCPOLLSTART:
  1395.     error = ln7990PollStart (pDrvCtrl);
  1396.     break;
  1397. case EIOCPOLLSTOP:
  1398.     error = ln7990PollStop (pDrvCtrl);
  1399.     break;
  1400.         case EIOCGMIB2:
  1401.             if (data == NULL)
  1402.                 return (EINVAL);
  1403.             bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
  1404.                   sizeof(pDrvCtrl->end.mib2Tbl));
  1405.             break;
  1406.         case EIOCGFBUF:
  1407.             if (data == NULL)
  1408.                 return (EINVAL);
  1409.             *(int *)data = LN_MIN_FBUF;
  1410.             break;
  1411.         case EIOCGMWIDTH:
  1412.             if (data == NULL)
  1413.                 return (EINVAL);
  1414.             *(int *)data = pDrvCtrl->memWidth;
  1415.             break;
  1416.         case EIOCGHDRLEN:
  1417.             if (data == NULL)
  1418.                 return (EINVAL);
  1419.             *(int *)data = 14;
  1420.             break;
  1421.         default:
  1422.             error = EINVAL;
  1423.         }
  1424.     return (error);
  1425.     }
  1426. /*******************************************************************************
  1427. *
  1428. * ln7990Reset - hardware reset of chip (stop it)
  1429. */
  1430. LOCAL void ln7990Reset
  1431.     (
  1432.     LN7990END_DEVICE  *pDrvCtrl
  1433.     )
  1434.     {
  1435.     ln7990CsrWrite (pDrvCtrl, 0, lncsr_STOP);
  1436.     }
  1437. /*******************************************************************************
  1438. *
  1439. * ln7990Csr0Read - read CSR 0 register
  1440. *
  1441. * Assumes normal operation, where the RAP register has been left selecting
  1442. * CSR0.
  1443. */
  1444. LOCAL u_short ln7990Csr0Read
  1445.     (
  1446.     LN7990END_DEVICE * pDrvCtrl /* driver control */
  1447.     )
  1448.     {
  1449.     USHORT result;
  1450.     SYS_IN_SHORT (pDrvCtrl, pDrvCtrl->pCsr, &result);
  1451.     return (result); /* get contents of CSR */
  1452.     }
  1453. /*******************************************************************************
  1454. *
  1455. * ln7990CsrWrite - select and write a CSR register
  1456. *
  1457. */
  1458. LOCAL void ln7990CsrWrite
  1459.     (
  1460.     LN7990END_DEVICE * pDrvCtrl, /* driver control */
  1461.     int reg, /* register to select */
  1462.     u_short value /* value to write */
  1463.     )
  1464.     {
  1465.     int level;
  1466.     level = intLock ();
  1467.     SYS_OUT_SHORT (pDrvCtrl, pDrvCtrl->pRap, (u_short)reg);
  1468.     SYS_OUT_SHORT (pDrvCtrl, pDrvCtrl->pCsr, value);
  1469.     intUnlock (level);
  1470.     }
  1471. /*******************************************************************************
  1472. *
  1473. * ln7990RestartSetup - setup memory descriptors and turn on chip
  1474. *
  1475. * Initializes all the shared memory structures and turns on the chip.
  1476. */
  1477. LOCAL STATUS ln7990RestartSetup
  1478.     (
  1479.     LN7990END_DEVICE *pDrvCtrl
  1480.     )
  1481.     {
  1482.     int  rsize;
  1483.     int  tsize;
  1484.     void *  pTemp;
  1485.     /* reset the device */
  1486.     ln7990Reset (pDrvCtrl);
  1487.     /* setup Rx buffer descriptors  */
  1488.     rsize = pDrvCtrl->rringLen;
  1489.     /* 
  1490.      * setup Tx buffer descriptors  - 
  1491.      */
  1492.     tsize = pDrvCtrl->tringLen;
  1493.     /* setup the initialization block */
  1494.     pDrvCtrl->ib = (ln_ib *)pDrvCtrl->pShMem;
  1495.     /* HELP */
  1496.     swab ((char *) END_HADDR(&pDrvCtrl->end), pDrvCtrl->ib->lnIBPadr, 6);
  1497.     CACHE_PIPE_FLUSH ();
  1498.     pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->pRring);   /* point to Rx ring */
  1499.     LN_ADDR_TO_IB_RMD (pTemp, pDrvCtrl->ib, rsize);
  1500.     pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->pTring);   /* point to Tx ring */
  1501.     LN_ADDR_TO_IB_TMD (pTemp, pDrvCtrl->ib, tsize);
  1502.     DRV_LOG (DRV_DEBUG_LOAD, "Memory setup completen", 1, 2, 3, 4, 5, 6);
  1503.     /* reconfigure the device */
  1504.     ln7990Config (pDrvCtrl);
  1505.     return (OK); 
  1506.     }
  1507.      
  1508. /*******************************************************************************
  1509. *
  1510. * ln7990Restart - restart the device after a fatal error
  1511. *
  1512. * This routine takes care of all the messy details of a restart.  The device
  1513. * is reset and re-initialized.  The driver state is re-synchronized.
  1514. */
  1515. LOCAL void ln7990Restart
  1516.     (
  1517.     LN7990END_DEVICE *pDrvCtrl
  1518.     )
  1519.     {
  1520.     ln7990Reset (pDrvCtrl);
  1521.     ln7990RestartSetup (pDrvCtrl);
  1522.     /* set the flags to indicate readiness */
  1523.     END_OBJ_READY (&pDrvCtrl->end,
  1524.                     IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
  1525.                     | IFF_MULTICAST);
  1526.     }
  1527. /******************************************************************************
  1528. *
  1529. * ln7990Config - reconfigure the interface under us.
  1530. *
  1531. * Reconfigure the interface setting promiscuous mode, and changing the
  1532. * multicast interface list.
  1533. *
  1534. * NOMANUAL
  1535. */
  1536. LOCAL void ln7990Config
  1537.     (
  1538.     LN7990END_DEVICE *pDrvCtrl
  1539.     )
  1540.     {
  1541.     u_short stat;
  1542.     void* pTemp;
  1543.     int timeoutCount = 0;
  1544.     ln_rmd *pRmd;
  1545.     ln_tmd *pTmd;
  1546.     int ix;
  1547.     /* Set promiscuous mode if it's asked for. */
  1548.     if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
  1549.         {
  1550.         DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode on!n",
  1551.                  1, 2, 3, 4, 5, 6);
  1552.         
  1553.         /* chip will be in promiscuous mode */
  1554.         
  1555.         pDrvCtrl->ib->lnIBMode = 0x8000;
  1556.         }
  1557.     else
  1558.         {
  1559.         DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!n",
  1560.                  1, 2, 3, 4, 5, 6);
  1561.         pDrvCtrl->ib->lnIBMode = 0; /* chip will be in normal receive mode */
  1562.         }
  1563.     
  1564.     CACHE_PIPE_FLUSH ();
  1565.     ln7990CsrWrite (pDrvCtrl, 0, lncsr_STOP);     /* set the stop bit */
  1566.     /* Set up address filter for multicasting. */
  1567.     if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0)
  1568. {
  1569. ln7990AddrFilterSet (pDrvCtrl);
  1570. }
  1571.     ln7990CsrWrite (pDrvCtrl, 3, pDrvCtrl->csr3B);
  1572.     pRmd = pDrvCtrl->pRring;
  1573.     for (ix = 0; ix < pDrvCtrl->rringSize; ix++, pRmd++)
  1574.         {
  1575.         pRmd->rbuf_bcnt = -(LN_BUFSIZ); /* neg of buffer byte count */
  1576.         LN_CLEAN_RXD (pRmd);
  1577.         }
  1578.     pDrvCtrl->rmdIndex = 0;
  1579.     
  1580.     pTmd = pDrvCtrl->pTring;
  1581.     for (ix = 0; ix < pDrvCtrl->tringSize; ix++, pTmd++)
  1582.         {
  1583.         pTmd->tbuf_bcnt = 0; /* no message byte count yet */
  1584.         pTmd->tbuf_err = 0; /* no error status yet */
  1585.         LN_TMD_CLR_ERR (pTmd);
  1586.         }
  1587.     
  1588.     pDrvCtrl->tmdIndex = 0;
  1589.     pDrvCtrl->tmdIndexC = 0;
  1590.     
  1591.     /* Point the device to the initialization block */
  1592.     pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->ib);
  1593.     ln7990CsrWrite (pDrvCtrl, 2,
  1594.        (u_short)(((u_long)pTemp >> 16) & 0x000000ff));
  1595.     ln7990CsrWrite (pDrvCtrl, 1, (u_long) pTemp);
  1596.     ln7990CsrWrite (pDrvCtrl, 0, lncsr_INIT);    /* init chip (read IB) */
  1597.     /* hang until Initialization DONe, ERRor, or timeout */
  1598.     while (((stat = ln7990Csr0Read (pDrvCtrl)) &
  1599.     (lncsr_IDON | lncsr_ERR)) == 0)
  1600.         {
  1601.         if (timeoutCount++ > 0x10000)
  1602.     break;
  1603. DELAY (1000 * timeoutCount);
  1604.         }
  1605.     DRV_LOG (DRV_DEBUG_LOAD, "Timeoutcount %dn", timeoutCount,
  1606.              2, 3, 4, 5, 6);
  1607.     /* log chip initialization failure */
  1608.     if ((stat & lncsr_ERR) || (timeoutCount >= 0x10000))
  1609.         {
  1610. DRV_LOG (DRV_DEBUG_LOAD, "%s: Device initialization failedn",
  1611.                  (int)END_DEV_NAME(&pDrvCtrl->end), 0,0,0,0,0);
  1612.         return;
  1613.         }
  1614.     if (!(pDrvCtrl->flags & LS_POLLING))
  1615. {
  1616. ln7990CsrWrite (pDrvCtrl, 0, lncsr_INEA | lncsr_STRT);
  1617. }
  1618.     else
  1619. {
  1620. ln7990CsrWrite (pDrvCtrl, 0, lncsr_STRT);
  1621. }
  1622.     }
  1623. /******************************************************************************
  1624. *
  1625. * ln7990AddrFilterSet - set the address filter for multicast addresses
  1626. *
  1627. * This routine goes through all of the multicast addresses on the list
  1628. * of addresses (added with the ln7990AddrAdd() routine) and sets the
  1629. * device's filter correctly.
  1630. *
  1631. * NOMANUAL
  1632. */
  1633. LOCAL void ln7990AddrFilterSet
  1634.     (
  1635.     LN7990END_DEVICE *pDrvCtrl
  1636.     )
  1637.     {
  1638.     ETHER_MULTI* pCurr;
  1639.     ln_ib *pIb;
  1640.     u_char *pCp;
  1641.     u_char c;
  1642.     u_long crc;
  1643.     int len;
  1644.     int count;
  1645.     pIb = pDrvCtrl->ib;
  1646.     LN_ADDRF_CLEAR (pIb);
  1647.     pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
  1648.     while (pCurr != NULL)
  1649. {
  1650. /*
  1651.  * One would think, given the AM7990 document's polynomial
  1652.  * of 0x04c11db6, that this should be 0x6db88320 (the bit
  1653.  * reversal of the AMD value), but that is not right.  See
  1654.  * the BASIC listing: bit 0 (our bit 31) must then be set.
  1655.  */
  1656. pCp = (unsigned char *)&pCurr->addr;
  1657. crc = 0xffffffff;
  1658. for (len = 6; --len >= 0;)
  1659.     {
  1660.     c = *pCp++;
  1661.     for (count = 0; count < 8; count++)
  1662. {
  1663. if ((c & 0x01) ^ (crc & 0x01))
  1664.     {
  1665.     crc >>= 1;
  1666.     crc = crc ^ 0xedb88320;
  1667.     }
  1668. else
  1669.     {
  1670.     crc >>= 1;
  1671.     }
  1672. c >>= 1;
  1673. }
  1674.     }
  1675. /* Just want the 6 most significant bits. */
  1676. crc = crc >> 26;
  1677. /* Turn on the corresponding bit in the filter. */
  1678. LN_ADDRF_SET (pIb, crc);
  1679. pCurr = END_MULTI_LST_NEXT(pCurr);
  1680. }
  1681.     }
  1682. /*******************************************************************************
  1683. *
  1684. * ln7990PollReceive - routine to receive a packet in polled mode.
  1685. *
  1686. * This routine is called by a user to try and get a packet from the
  1687. * device.
  1688. */
  1689. LOCAL STATUS ln7990PollReceive
  1690.     (
  1691.     LN7990END_DEVICE *pDrvCtrl,
  1692.     M_BLK_ID pMblk
  1693.     )
  1694.     {
  1695.     ln_rmd *pRmd;
  1696.     u_short stat;
  1697.     u_long phys;
  1698.     char* pPacket;
  1699.     int len;
  1700.     DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bn", 1, 2, 3, 4, 5, 6);
  1701.     /* Read the device status register */
  1702.     stat = ln7990Csr0Read (pDrvCtrl);
  1703.     /* Check for errors */
  1704.     if (stat & (lncsr_BABL | lncsr_MISS | lncsr_MERR))
  1705.         {
  1706.         ++pDrvCtrl->csr0Errs;
  1707.         DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad errorn", 1, 2, 3, 4, 5, 6);
  1708. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1709.         /* restart chip on fatal error */
  1710.         if (stat & lncsr_MERR)        /* memory error */
  1711.             {
  1712.     END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
  1713.             DRV_LOG (DRV_DEBUG_POLL_RX, "PRX restartn", 1, 2, 3, 4, 5, 6);
  1714.             ln7990Restart (pDrvCtrl);
  1715.     return (EAGAIN);
  1716.             }
  1717.         }
  1718.     /*
  1719.      * clear receive interrupts, and clear any errors that may be set.
  1720.      */
  1721.     ln7990CsrWrite (pDrvCtrl, 0, ((stat &
  1722.             (lncsr_BABL|lncsr_CERR|lncsr_MISS|lncsr_MERR|
  1723.              lncsr_RINT))));
  1724.     /* Packet must be checked for errors. */
  1725.     pRmd = ln7990FullRMDGet (pDrvCtrl);
  1726.     if (pRmd == NULL)
  1727. {
  1728.         DRV_LOG (DRV_DEBUG_POLL_RX, "PRX no rmdn", 1, 2, 3, 4, 5, 6);
  1729. return (EAGAIN);
  1730. }
  1731.     if  (LN_RMD_ERR (pRmd))
  1732. {
  1733. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1734.         DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad rmdn", 1, 2, 3, 4, 5, 6);
  1735. goto cleanRXD;
  1736. }
  1737.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  1738.     len = LN_PKT_LEN_GET (pRmd); /* get packet length */
  1739.     /* Get pointer to packet */
  1740.     LN_RMD_TO_ADDR (pDrvCtrl->memBase, pRmd, phys);
  1741.     pPacket = (char *) LN_CACHE_PHYS_TO_VIRT (phys);
  1742.     LN_CACHE_INVALIDATE (pPacket, len);   /* make the packet coherent */
  1743.     /* Upper layer provides the buffer. */
  1744.     if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
  1745. {
  1746.         DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad mblk len:%d flags:%dn",
  1747.                  pMblk->mBlkHdr.mLen, pMblk->mBlkHdr.mFlags, 3, 4, 5, 6);
  1748. return (EAGAIN);
  1749. }
  1750.     pMblk->mBlkHdr.mData += pDrvCtrl->offset;
  1751.     bcopy (pPacket, pMblk->mBlkHdr.mData, len);
  1752.     pMblk->mBlkHdr.mLen = len;
  1753.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1754.     pMblk->mBlkPktHdr.len = len;
  1755.     /* Done with descriptor, clean up and give it to the device. */
  1756.     cleanRXD:
  1757.     LN_CLEAN_RXD (pRmd);
  1758.     /* Flush the write pipe */
  1759.     CACHE_PIPE_FLUSH ();
  1760.     /* Advance our management index */
  1761.     pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
  1762.     DRV_LOG (DRV_DEBUG_POLL_RX, "PRX okn", 1, 2, 3, 4, 5, 6);
  1763.     return (OK);
  1764.     }
  1765. /*******************************************************************************
  1766. *
  1767. * ln7990PollSend - routine to send a packet in polled mode.
  1768. *
  1769. * This routine is called by a user to try and send a packet on the
  1770. * device.
  1771. */
  1772. LOCAL STATUS ln7990PollSend
  1773.     (
  1774.     LN7990END_DEVICE* pDrvCtrl,
  1775.     M_BLK_ID pMblk
  1776.     )
  1777.     {
  1778.     ln_tmd* pTmd;
  1779.     void*       pTemp;
  1780.     int         len;
  1781.     int         oldLevel;
  1782.     u_short stat;
  1783.     char*       pBuf = NULL;
  1784.     char*       pOrig = NULL;
  1785.     
  1786.     DRV_LOG (DRV_DEBUG_POLL_TX, "PTX bn", 1, 2, 3, 4, 5, 6);
  1787.     /* See if next TXD is available */
  1788.     pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex;
  1789.     LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);
  1790.     if ((pTmd->tbuf_stat & lntmd1_OWN) || (((pDrvCtrl->tmdIndex + 1) &
  1791.         (pDrvCtrl->tringSize - 1)) == pDrvCtrl->tmdIndexC))
  1792.         {
  1793.         DRV_LOG (DRV_DEBUG_POLL_TX, "Out of tmds.n", 1, 2, 3, 4, 5, 6);
  1794.         if (!pDrvCtrl->txCleaning)
  1795.             netJobAdd ((FUNCPTR)ln7990ScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0);
  1796.        return (EAGAIN);
  1797.         }
  1798.     /*
  1799.      * If we don't have alignment issues then we can transmit
  1800.      * directly from the M_BLK otherwise we have to copy.
  1801.      */
  1802.     
  1803.     if ((pDrvCtrl->offset == 0) && (pMblk->mBlkHdr.mNext == NULL))
  1804.         {
  1805.         len = max (ETHERSMALL, pMblk->m_len);
  1806.         LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pMblk->m_data);
  1807.         DRV_LOG (DRV_DEBUG_POLL_TX, "offset == 0.n", 1, 2, 3, 4, 5, 6);
  1808.         }
  1809.     else
  1810.         {
  1811.         DRV_LOG (DRV_DEBUG_POLL_TX, "offset != 0.n", 1, 2, 3, 4, 5, 6);
  1812.         pOrig = pBuf = netClusterGet(pDrvCtrl->end.pNetPool,
  1813.                                      pDrvCtrl->pClPoolId);
  1814.         if (pBuf == NULL)
  1815.             {
  1816.             return (EAGAIN);
  1817.             }
  1818.         
  1819.         pBuf += pDrvCtrl->offset;
  1820.         
  1821.         len = netMblkToBufCopy (pMblk, pBuf, NULL);
  1822.         LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pBuf);
  1823.         }
  1824.     len = max (len, ETHERSMALL);
  1825.     /* place a transmit request */
  1826.     oldLevel = intLock ();          /* disable ints during update */
  1827.     pTmd->tbuf_err = 0;                     /* clear buffer error status */
  1828.     pTmd->tbuf_bcnt = -len;                  /* negative message byte count */
  1829.     pTmd->tbuf_stat |= lntmd1_OWN | lntmd1_STP | lntmd1_ENP;
  1830.     /* Flush the write pipe */
  1831.     CACHE_PIPE_FLUSH ();
  1832.     intUnlock (oldLevel);   /* now ln7990Int won't get confused */
  1833.     /* Advance our management index */
  1834.     pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
  1835.     /* kick start the transmitter, if selected */
  1836.     if (lnKickStartTx)
  1837. ln7990CsrWrite (pDrvCtrl, 0, lncsr_TDMD);
  1838.     /* Bump the statistic counter. */
  1839.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
  1840.     /* Flush the write pipe */
  1841.     CACHE_PIPE_FLUSH ();
  1842.     /* Read the device status register */
  1843.     stat = ln7990Csr0Read (pDrvCtrl);
  1844.     /*
  1845.      * Spin until we think we've sent it.  SInce we're single threaded
  1846.      * now it must be us who talked.
  1847.      */
  1848.     while (!(stat & lncsr_TINT))
  1849.         {
  1850.         stat = ln7990Csr0Read (pDrvCtrl);
  1851.         }
  1852.     /*
  1853.      * We now believe taht this frame has been transmitted.  SInce we
  1854.      * may have allocated/copied it we need to free it an then shout
  1855.      * hey nonny hey.
  1856.      */
  1857.     if (pOrig != NULL)
  1858.         {
  1859.         DRV_LOG (DRV_DEBUG_POLL_TX, "pOrig != NULLn", 1, 2, 3, 4, 5, 6);
  1860.         netClFree(pDrvCtrl->end.pNetPool, pOrig);
  1861.         }
  1862.     
  1863.     if (!pDrvCtrl->txCleaning)
  1864.         {
  1865.         pDrvCtrl->txCleaning = TRUE;
  1866.         ln7990ScrubTRing (pDrvCtrl);
  1867.         }
  1868.     
  1869.     DRV_LOG (DRV_DEBUG_POLL_TX, "PTX en", 1, 2, 3, 4, 5, 6);
  1870.     return (OK);
  1871.     }
  1872. /*****************************************************************************
  1873. *
  1874. * ln7990MCastAddrAdd - add a multicast address for the device
  1875. *
  1876. * This routine adds a multicast address to whatever the driver
  1877. * is already listening for.  It then resets the address filter.
  1878. */
  1879. LOCAL STATUS ln7990MCastAddrAdd
  1880.     (
  1881.     LN7990END_DEVICE *pDrvCtrl,
  1882.     char* pAddress
  1883.     )
  1884.     {
  1885.     int error;
  1886.     if ((error = etherMultiAdd (&pDrvCtrl->end.multiList,
  1887. pAddress)) == ENETRESET)
  1888.     ln7990Config (pDrvCtrl);
  1889.     return (OK);
  1890.     }
  1891. /*****************************************************************************
  1892. *
  1893. * ln7990MCastAddrDel - delete a multicast address for the device
  1894. *
  1895. * This routine removes a multicast address from whatever the driver
  1896. * is listening for.  It then resets the address filter.
  1897. */
  1898. LOCAL STATUS ln7990MCastAddrDel
  1899.     (
  1900.     LN7990END_DEVICE* pDrvCtrl,
  1901.     char* pAddress
  1902.     )
  1903.     {
  1904.     int error;
  1905.     if ((error = etherMultiDel (&pDrvCtrl->end.multiList,
  1906.      (char *)pAddress)) == ENETRESET)
  1907.     ln7990Config (pDrvCtrl);
  1908.     return (OK);
  1909.     }
  1910. /*****************************************************************************
  1911. *
  1912. * ln7990MCastAddrGet - get the multicast address list for the device
  1913. *
  1914. * This routine gets the multicast list of whatever the driver
  1915. * is already listening for.
  1916. */
  1917. LOCAL STATUS ln7990MCastAddrGet
  1918.     (
  1919.     LN7990END_DEVICE* pDrvCtrl,
  1920.     MULTI_TABLE* pTable
  1921.     )
  1922.     {
  1923.     int error;
  1924.     error = etherMultiGet (&pDrvCtrl->end.multiList, pTable);
  1925.     return (error);
  1926.     }
  1927. /*******************************************************************************
  1928. *
  1929. * ln7990Stop - stop the device
  1930. *
  1931. * This function calls BSP functions to disconnect interrupts and stop
  1932. * the device from operating in interrupt mode.
  1933. *
  1934. * RETURNS: OK or ERROR
  1935. */
  1936. LOCAL STATUS ln7990Stop
  1937.     (
  1938.     LN7990END_DEVICE *pDrvCtrl
  1939.     )
  1940.     {
  1941.     STATUS result = OK;
  1942.     /* Stop the device. */
  1943.     ln7990CsrWrite (pDrvCtrl, 0, lncsr_STOP);      /* set the stop bit */
  1944.     SYS_INT_DISCONNECT (pDrvCtrl, ln7990Int, (int)pDrvCtrl, &result);
  1945.     if (result == ERROR)
  1946. {
  1947. DRV_LOG (DRV_DEBUG_LOAD, "Could not diconnect interrupt!n",
  1948.                  1, 2, 3, 4, 5, 6);
  1949. }
  1950.     return (result);
  1951.     }
  1952. /******************************************************************************
  1953. *
  1954. * ln7990Unload - unload a driver from the system
  1955. *
  1956. * This function first brings down the device, and then frees any
  1957. * stuff that was allocated by the driver in the load function.
  1958. */
  1959. LOCAL STATUS ln7990Unload
  1960.     (
  1961.     LN7990END_DEVICE* pDrvCtrl
  1962.     )
  1963.     {
  1964.     END_OBJECT_UNLOAD (&pDrvCtrl->end);
  1965.     /* Free the shared DMA memory. */
  1966.     if (pDrvCtrl->flags & LS_MEM_ALLOC_FLAG)
  1967. cacheDmaFree (pDrvCtrl->pShMem);
  1968.     return (OK);
  1969.     }
  1970. /*******************************************************************************
  1971. *
  1972. * ln7990PollStart - start polled mode operations
  1973. *
  1974. * RETURNS: OK or ERROR.
  1975. */
  1976. LOCAL STATUS ln7990PollStart
  1977.     (
  1978.     LN7990END_DEVICE* pDrvCtrl
  1979.     )
  1980.     {
  1981.     u_short        stat;
  1982.     int         oldLevel;
  1983.     /* Read the device status register */
  1984.     oldLevel = intLock ();          /* disable ints during update */
  1985.     stat = ln7990Csr0Read (pDrvCtrl);
  1986.     /* Rewrite the register minus the INEA bit to turn off interrupts */
  1987.     ln7990CsrWrite (pDrvCtrl, 0, ((stat &
  1988.     (lncsr_BABL|lncsr_CERR|lncsr_MISS|lncsr_MERR|
  1989.     lncsr_RINT|lncsr_TINT))));
  1990.     pDrvCtrl->flags |= LS_POLLING;
  1991.     intUnlock (oldLevel);   /* now ln7990Int won't get confused */
  1992.     DRV_LOG (DRV_DEBUG_POLL, "STARTEDn", 1, 2, 3, 4, 5, 6);
  1993.     ln7990Config (pDrvCtrl); /* reconfigure device */ 
  1994.     return (OK);
  1995.     }
  1996. /*******************************************************************************
  1997. *
  1998. * ln7990PollStop - stop polled mode operations
  1999. *
  2000. * RETURNS: OK or ERROR.
  2001. */
  2002. LOCAL STATUS ln7990PollStop
  2003.     (
  2004.     LN7990END_DEVICE* pDrvCtrl
  2005.     )
  2006.     {
  2007.     u_short        stat;
  2008.     int         oldLevel;
  2009.     oldLevel = intLock ();          /* disable ints during update */
  2010.     stat = ln7990Csr0Read (pDrvCtrl);
  2011.     /* Rewrite the register minus the INEA bit to turn off interrupts */
  2012.     ln7990CsrWrite (pDrvCtrl, 0, ((stat &
  2013.             (lncsr_BABL|lncsr_CERR|lncsr_MISS|lncsr_MERR|
  2014. lncsr_RINT|lncsr_TINT)) | lncsr_INEA));
  2015.     pDrvCtrl->flags &= ~LS_POLLING;
  2016.     intUnlock (oldLevel);   /* now ln7990Int won't get confused */
  2017.     DRV_LOG (DRV_DEBUG_POLL, "STOPPEDn", 1, 2, 3, 4, 5, 6);
  2018.     ln7990Config (pDrvCtrl); /* reconfigure device */
  2019.     
  2020.     return (OK);
  2021.     }
  2022. /******************************************************************************
  2023. *
  2024. * ln7990ScrubTRing - clean the transmit ring
  2025. *
  2026. * RETURNS: N/A
  2027. *
  2028. */
  2029. LOCAL void ln7990ScrubTRing
  2030.     (
  2031.     LN7990END_DEVICE* pDrvCtrl
  2032.     )
  2033.     {
  2034.     int         oldLevel;
  2035.     ln_tmd* pTmd;
  2036.     ln_rmd* pRmd;
  2037.     
  2038.     pDrvCtrl->txCleaning = TRUE;
  2039.     while (pDrvCtrl->tmdIndexC != pDrvCtrl->tmdIndex)
  2040.         {
  2041.         /* Handle one recv packet if exists */
  2042. if ((pRmd = ln7990FullRMDGet (pDrvCtrl)) != NULL)
  2043.     {
  2044.             LN_CACHE_INVALIDATE (pRmd, RMD_SIZ);
  2045.             ln7990Recv (pDrvCtrl, pRmd);
  2046.             }
  2047.         /* disposal has not caught up */
  2048.         pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndexC;
  2049.         /* if the buffer is still owned by LANCE, don't touch it */
  2050.         LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);
  2051.         if (SHMEM_RD (&pTmd->tbuf_stat) & TMD_OWN)
  2052.             break;
  2053.         oldLevel = intLock();
  2054.         if (pDrvCtrl->freeRtn[pDrvCtrl->tmdIndexC] != NULL)
  2055.             {
  2056.             pDrvCtrl->freeRtn[pDrvCtrl->tmdIndexC]
  2057.                 (pDrvCtrl->freeData[pDrvCtrl->tmdIndexC].arg1,
  2058.                  pDrvCtrl->freeData[pDrvCtrl->tmdIndexC].arg2); 
  2059.             pDrvCtrl->freeRtn[pDrvCtrl->tmdIndexC] = NULL;
  2060.             pDrvCtrl->freeData[pDrvCtrl->tmdIndexC].arg1 = NULL; 
  2061.             pDrvCtrl->freeData[pDrvCtrl->tmdIndexC].arg2 = NULL; 
  2062.             }
  2063.         intUnlock(oldLevel);
  2064.         
  2065.         /* now bump the tmd disposal index pointer around the ring */
  2066.         pDrvCtrl->tmdIndexC = (pDrvCtrl->tmdIndexC + 1) &
  2067.       (pDrvCtrl->tringSize - 1);
  2068.         /*
  2069.          * lntmd1_ERR is an "OR" of LCOL, LCAR, UFLO or RTRY.
  2070.          * Note that BUFF is not indicated in lntmd1_ERR.
  2071.          * We should therefore check both lntmd1_ERR and lntmd3_BUFF
  2072.          * here for error conditions.
  2073.          */
  2074.         if ((SHMEM_RD (&pTmd->tbuf_stat) & lntmd1_ERR) ||
  2075.     (SHMEM_RD (&pTmd->tbuf_err) & lntmd3_BUFF))
  2076.             {
  2077.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1);
  2078.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, -1);
  2079.             /*
  2080.      * If error was due to excess collisions, bump the collision
  2081.              * counter.  The LANCE does not keep an individual counter of
  2082.              * collisions, so in this driver, the collision statistic is not
  2083.              * an accurate count of total collisions.
  2084.              */
  2085.     /* assume DRTY bit not set */
  2086.             if (SHMEM_RD (&pTmd->tbuf_err) & lntmd3_RTRY)
  2087. END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1);
  2088.             /* check for no carrier */
  2089.             if (SHMEM_RD (&pTmd->tbuf_err) & TMD_LCAR)
  2090. {
  2091. DRV_LOG (DRV_DEBUG_TX, "%s: no carriern",
  2092.                          (int)END_DEV_NAME(&pDrvCtrl->end), 0,0,0,0,0);
  2093. }
  2094.             /*
  2095.      * Restart chip on fatal errors.
  2096.              * The following code handles the situation where the transmitter
  2097.              * shuts down due to an underflow error.  This is a situation that
  2098.              * will occur if the DMA cannot keep up with the transmitter.
  2099.              * It will occur if the LANCE is being held off from DMA access
  2100.              * for too long or due to significant memory latency.  DRAM
  2101.              * refresh or slow memory could influence this.  Many
  2102.              * implementations use a dedicated LANCE buffer.  This can be
  2103.              * static RAM to eliminate refresh conflicts; or dual-port RAM
  2104.              * so that the LANCE can have free run of this memory during its
  2105.              * DMA transfers.
  2106.              */
  2107.             if ((SHMEM_RD (&pTmd->tbuf_err) & lntmd3_BUFF) ||
  2108. (SHMEM_RD (&pTmd->tbuf_err) & TMD_UFLO))
  2109.                 {
  2110.                 pDrvCtrl->end.flags &= ~(IFF_UP | IFF_RUNNING);
  2111. ln7990Restart (pDrvCtrl);
  2112.                 }
  2113.             }
  2114. LN_TMD_CLR_ERR (pTmd);
  2115.         }
  2116.     pDrvCtrl->txCleaning = FALSE;
  2117.     }