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

VxWorks

开发平台:

C/C++

  1. /* fei82557End.c - END style Intel 82557 Ethernet network interface driver */
  2. /* Copyright 1989-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02u,07may02,pmr SPR 72378: initializing pNewRFD to NULL in fei82557Receive().
  8. 02t,22apr02,rcs removed taskDelay() from fei82557PollSend() SPR# 76102
  9. 02s,18apr02,rcs set mBlk to total clusters ratio to 5 SPR# 75667
  10. 02r,22jan02,rcs facilitated common source base with either RFC 1213 or
  11.                 RFC 2233 depending on INCLUDE_RFC_1213 macro.
  12. 02q,16oct01,rcs added muxError() call to fei82557Receive() to alert the mux
  13.                 that the driver has exhausted its clusters.
  14.                 SPR# 70545 and  SPR# 70259
  15. 02p,16oct01,rcs modified fei82557Int() and fei82557HandleRecvInt() to fix 
  16.                 SPR# 69298
  17. 02o,02oct01,rcs added a CSR_BYTE_RD after writing the interupt ack to ensure
  18.                 the interrupt is actually acknowledged before the interrupts
  19.                 are re-enabled. (SPR# 69298) 
  20. 02n,28aug01,ann adding the code that copies the pMib2Tbl contents into
  21.                 mib2Tbl for backward compatibility - SPR 69697 & 69758
  22. 02m,16aug01,ann we now set the RFC2233 flag in the END_OBJ_READY macro.
  23.                 fix for SPR 69673
  24. 02l,31jul01,rcs adjusted cluster pool allocation to accomodate CL_BUF_IDs
  25.                 (SPR# 69385)
  26. 02k,31jul01,rcs set number of clusters passed to netPoolInit() to correct
  27.                 value. (SPR# 69383)
  28. 02j,31jul01,rcs moved netJobAdd of muxTxRestart if pDrvCtrl->txStall out of 
  29.                 FOREVER loop. (SPR# 31636)
  30. 02i,31jul01,rcs set taskDelay()s to reference sysClkRateGet() (SPR# 63430)
  31. 02h,31jul01,rcs removed suspended state test from fei82557Send() (SPR# 63483) 
  32. 02g,31jul01,rcs set cluster size passed to netPoolInit() correctly (SPR# 67237) 
  33. 02f,27jul01,jpf Removed mux mode function call
  34. 02e,13jul01,ann eliminating the mibStyle variable and accomodated the
  35.                 END_MIB_2233 flag in the END flags field
  36. 02d,20jun01,rcs modified fei82557PhyInit to handle disconnected phys (SPR#28941)
  37. 02c,29mar01,spm merged changes from version 01n of tor2_0.open_stack 
  38.                 branch (wpwr VOB, base 01k) for unified code base
  39. 02b,09mar01,jpd fixed alignment issue in PollReceive() (SPR #64573).
  40. 02a,13dec00,rcs removed (UINT32) cast from RFD_LONG_RD value arg (SPR# 62996) 
  41. 01z,05dec00,dat merge from sustaining to tor2_0_x branch
  42. 01x,28sep00,jgn remove physical to virtual translations (SPR #34891)
  43. 01w,02aug00,stv removed netMblkClChainFree() in Pollsend routine (SPR# 32885).
  44. 01v,19jun00,jgn SPR 32016, improve interrupt handling + add multiplier to
  45. increase number of rx buffers available for loaning
  46. 01u,11jun00,ham removed reference to etherLib.
  47. 01t,06jun00,jgn fixed CPU to PCI trans. for base address regs (SPR 31811)
  48. 01s,02jun00,jgn fixed initialisation for cases where CPU adrs != PCI adrs
  49. 01r,11apr00,jgn added support for aligning packet data (offset parameter)
  50. 01q,29feb00,stv Fixed the bug which stalls transmission under heavy
  51. load (SPR# 30361).  (merge from T2)
  52. 01p,27jan00,dat fixed use of NULL, removed warnings
  53. 01o,05jan00,stv removed private/funcBindP.h (SPR# 29875). 
  54. 01n,01dec99,stv freed mBlk chain before returning ERROR (SPR #28492).
  55. 01m,14oct99,stv Fixed the bug of failing to release the transmit
  56.                 semaphore (SPR #29094).
  57. 01l,08sep99,jmb avoid virtual address translations of *_NOT_USED.
  58. 01k,11mar99,cn  added support for shared PCI interrupts (SPR# 24379).
  59. Also corrected a potential memory leak in xxxRecv.
  60. 01j,09mar99,cn  moved callout to adapter init routine before xxxMemInit(),
  61. and corrected usage of xxxSCBCommand() (SPR# 25242).
  62. 01i,22sep98,dat  removed lint warnings.
  63. 01h,21jul98,cn  added support for multi-device configuration. Also made
  64. chip-access macros redefineable and moved them to the header
  65. file.
  66. 01g,16apr98,cn  added globals feiEndIntConnect and feiEndIntDisconnect and 
  67. modified SYS_INT_CONNECT and SYS_INT_DISCONNECT accordingly.
  68. Changed state to scbStatus in fei82557Action().
  69. 01f,23mar98,cn  fixed compiling problem when building for big-endian machines
  70. 01e,11mar98,cn  checked-in 
  71. 01d,05mar98,cn  more code clean-up after code review, added support for
  72. MULTIALL
  73. 01c,23feb98,cn  code clean-up
  74. 01b,18feb98,cn  changed all the once called LINK macros to normal
  75. 01a,07nov97,cn  created from ../netif/if_fei.c, version 01k
  76. */
  77. /*
  78. DESCRIPTION
  79. This module implements an Intel 82557 Ethernet network interface driver.
  80. This is a fast Ethernet PCI bus controller, IEEE 802.3 10Base-T and 
  81. 100Base-T compatible. It also features a glueless 32-bit PCI bus master 
  82. interface, fully compliant with PCI Spec version 2.1. An interface to 
  83. MII compliant physical layer devices is built-in to the card. The 82557
  84. Ethernet PCI bus controller also includes Flash support up to 1 MByte
  85. and EEPROM support, altough these features are not dealt with in this 
  86. driver.
  87. The 82557 establishes a shared memory communication system with the CPU,
  88. which is divided into three parts: the Control/Status Registers (CSR),
  89. the Command Block List (CBL) and the Receive Frame Area (RFA). The CSR
  90. is on chip and is either accessible with I/O or memory cycles, whereas the
  91. other structures reside on the host.
  92. The CSR is the main means of communication between the device and the
  93. host, meaning that the host issues commands through these registers
  94. while the chip posts status changes in it, occurred as a result of those
  95. commands. Pointers to both the CBL and RFA are also stored in the CSR.
  96. The CBL consists of a linked list of frame descriptors through which 
  97. individual action commands can be performed. These may be transmit 
  98. commands as well as non-transmit commands, e.g. Configure or Multicast
  99. setup commands. While the CBL list may function in two different modes,
  100. only the simplified memory mode is implemented in the driver.
  101. The RFA is a linked list of receive frame descriptors. Only support for
  102. the simplified memory mode is granted. In this model, the data buffer 
  103. immediately follows the related frame descriptor.
  104. The driver is designed to be moderately generic, operating unmodified
  105. across the range of architectures and targets supported by VxWorks.  
  106. To achieve this, this driver must be given several target-specific 
  107. parameters, and some external support routines must be provided.  These 
  108. parameters, and the mechanisms used to communicate them to the driver, 
  109. are detailed below.
  110. BOARD LAYOUT
  111. This device is on-board.  No jumpering diagram is necessary.
  112. EXTERNAL INTERFACE
  113. The driver provides the standard external interface, fei82557EndLoad(), which
  114. takes a string of colon separated parameters. The parameters should be
  115. specified in hexadecimal, optionally preceeded by "0x" or a minus sign "-".
  116. The parameter string is parsed using strtok_r() and each parameter is
  117. converted from a string representation to binary by a call to
  118. strtoul(parameter, NULL, 16).
  119. The format of the parameter string is:
  120.  "<memBase>:<memSize>:<nTfds>:<nRfds>:<flags>:<offset>"
  121. In addition, the two global variables 'feiEndIntConnect' and 
  122. 'feiEndIntDisconnect' specify respectively the interrupt connect routine 
  123. and the interrupt disconnect routine to be used depending on the BSP. 
  124. The former defaults to intConnect() and the user can override this to use 
  125. any other interrupt connect routine (say pciIntConnect()) in sysHwInit() 
  126. or any device specific initialization routine called in sysHwInit(). 
  127. Likewise, the latter is set by default to NULL, but it may be overridden 
  128. in the BSP in the same way.
  129.  
  130. TARGET-SPECIFIC PARAMETERS
  131. .IP <memBase>
  132. This parameter is passed to the driver via fei82557EndLoad().
  133. The Intel 82557 device is a DMA-type device and typically shares
  134. access to some region of memory with the CPU.  This driver is designed
  135. for systems that directly share memory between the CPU and the 82557.
  136. This parameter can be used to specify an explicit memory region for use
  137. by the 82557.  This should be done on targets that restrict the 82557
  138. to a particular memory region.  The constant `NONE' can be used to 
  139. indicate that there are no memory limitations, in which case the driver 
  140. will allocate cache safe memory for its use using cacheDmaAlloc().
  141. .IP <memSize>
  142. The memory size parameter specifies the size of the pre-allocated memory
  143. region. If memory base is specified as NONE (-1), the driver ignores this
  144. parameter. Otherwise, the driver checks the size of the provoded memory 
  145. region is adequate with respect to the given number of Command Frame
  146. Descriptor and Receive Frame Descriptor.
  147. .IP <nTfds>
  148. This parameter specifies the number of transmit descriptor/buffers to be
  149. allocated. If this parameter is less than two, a default of 32 is used.
  150. .IP <nRfds>
  151. This parameter specifies the number of receive descriptor/buffers to be
  152. allocated. If this parameter is less than two, a default of 32 is used.
  153. In addition, four times as many loaning buffers are created.  These buffers
  154. are loaned up to the network stack.  When loaning buffers are exhausted,
  155. the system begins discarding incoming packets.  Specifying 32 buffers results
  156. in 32 frame descriptors, 32 reserved buffers and 128 loaning buffers being
  157. created from the system heap.
  158. .IP <flags>
  159. User flags may control the run-time characteristics of the Ethernet
  160. chip. Not implemented.
  161. .IP <offset>
  162. Offset used to align IP header on word boundary for CPUs that need long word
  163. aligned access to the IP packet (this will normally be zero or two). This field is
  164. optional, the default value is zero.
  165. .LP
  166.  
  167. EXTERNAL SUPPORT REQUIREMENTS
  168. This driver requires one external support function:
  169. .CS
  170. STATUS sys557Init (int unit, FEI_BOARD_INFO *pBoard)
  171. .CE
  172. This routine performs any target-specific initialization
  173. required before the 82557 device is initialized by the driver.
  174. The driver calls this routine every time it wants to [re]initialize
  175. the device.  This routine returns OK, or ERROR if it fails.
  176. .LP
  177. SYSTEM RESOURCE USAGE
  178. The driver uses cacheDmaMalloc() to allocate memory to share with the 82557.
  179. The size of this area is affected by the configuration parameters specified
  180. in the fei82557EndLoad() call. 
  181. Either the shared memory region must be non-cacheable, or else
  182. the hardware must implement bus snooping.  The driver cannot maintain
  183. cache coherency for the device because fields within the command
  184. structures are asynchronously modified by both the driver and the device,
  185. and these fields may share the same cache line.
  186. TUNING HINTS
  187. The only adjustable parameters are the number of TFDs and RFDs that will be
  188. created at run-time.  These parameters are given to the driver when 
  189. fei82557EndLoad() is called.  There is one TFD and one RFD associated with 
  190. each transmitted frame and each received frame respectively.  For 
  191. memory-limited applications, decreasing the number of TFDs and RFDs may be 
  192. desirable.  Increasing the number of TFDs will provide no performance 
  193. benefit after a certain point. Increasing the number of RFDs will provide 
  194. more buffering before packets are dropped.  This can be useful if there are 
  195. tasks running at a higher priority than the net task.
  196. ALIGNMENT
  197. Some architectures do not support unaligned access to 32-bit data items. On
  198. these architectures (eg PowerPC and ARM), it will be necessary to adjust the
  199. offset parameter in the load string to realign the packet. Failure to do so
  200. will result in received packets being absorbed by the network stack, although
  201. transmit functions should work OK.
  202. SEE ALSO: ifLib,
  203. .I "Intel 82557 User's Manual,"
  204. .I "Intel 32-bit Local Area Network (LAN) Component User's Manual"
  205. */
  206. #include "vxWorks.h"
  207. #include "wdLib.h"
  208. #include "iv.h"
  209. #include "vme.h"
  210. #include "net/mbuf.h"
  211. #include "net/unixLib.h"
  212. #include "net/protosw.h"
  213. #include "sys/socket.h"
  214. #include "sys/ioctl.h"
  215. #include "errno.h"
  216. #include "memLib.h"
  217. #include "intLib.h"
  218. #include "net/route.h"
  219. #include "iosLib.h"
  220. #include "errnoLib.h"
  221. #include "vxLib.h"    /* from if_fei.c */
  222. #include "private/funcBindP.h"
  223. #include "cacheLib.h"
  224. #include "logLib.h"
  225. #include "netLib.h"
  226. #include "stdio.h"
  227. #include "stdlib.h"
  228. #include "sysLib.h"
  229. #include "taskLib.h"
  230. #include "net/systm.h"
  231. #include "sys/times.h"
  232. #include "net/if_subr.h"
  233. #include "drv/end/fei82557End.h"
  234. #include "drv/pci/pciIntLib.h"
  235. #undef ETHER_MAP_IP_MULTICAST
  236. #include "etherMultiLib.h"
  237. #include "end.h"
  238. #include "semLib.h"
  239. #define    END_MACROS
  240. #include "endLib.h"
  241. #include "lstLib.h"
  242. /* defines */
  243. /* Driver debug control */
  244. #undef DRV_DEBUG557
  245. /* Driver debug control */
  246. #ifdef DRV_DEBUG557
  247. #define DRV_DEBUG_OFF 0x0000
  248. #define DRV_DEBUG_RX 0x0001
  249. #define DRV_DEBUG_TX 0x0002
  250. #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
  251. #define DRV_DEBUG_POLL_RX     0x0004
  252. #define DRV_DEBUG_POLL_TX     0x0008
  253. #define DRV_DEBUG_LOAD 0x0010
  254. #define DRV_DEBUG_IOCTL 0x0020
  255. #define DRV_DEBUG_INT 0x0040
  256. #define DRV_DEBUG_START     0x0080
  257. #define DRV_DEBUG_DUMP     0x0100
  258. #define DRV_DEBUG_ALL     0xffff
  259. int fei82557Debug = DRV_DEBUG_LOAD;
  260. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  261.     do {
  262.     if (fei82557Debug & FLG)
  263. if (_func_logMsg != NULL)
  264.     _func_logMsg (X0, (int)X1, (int)X2, (int)X3, (int)X4,
  265.     (int)X5, (int)X6);
  266.     } while (0)
  267. #define DRV_PRINT(FLG, X)
  268.     do {
  269.     if (fei82557Debug & FLG)
  270. printf X;
  271.     } while (0)
  272. #else /* DRV_DEBUG557 */
  273. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  274. #define DRV_PRINT(FLG, X)
  275. #endif /* DRV_DEBUG557 */
  276. /* general macros for reading/writing from/to specified locations */
  277. #if (_BYTE_ORDER == _BIG_ENDIAN)
  278.  
  279. #define FEI_SWAP_LONG(x)        LONGSWAP(x)
  280. #define FEI_SWAP_WORD(x)        (MSB(x) | LSB(x) << 8)
  281.  
  282. #else
  283.  
  284. #define FEI_SWAP_LONG(x)        (x)
  285. #define FEI_SWAP_WORD(x)        (x)
  286.  
  287. #endif /* _BYTE_ORDER == _BIG_ENDIAN */
  288. /* Cache and PCI-bus related macros */
  289. #define FEI_VIRT_TO_SYS(virtAddr)     
  290. (FEI_LOCAL_TO_SYS (((UINT32) FEI_VIRT_TO_PHYS (virtAddr))))
  291. #define FEI_VIRT_TO_PHYS(virtAddr)     
  292. CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (char *)(virtAddr))
  293. #define FEI_LOCAL_TO_SYS(physAddr)     
  294. LOCAL_TO_SYS_ADDR (pDrvCtrl->unit, (physAddr))
  295. #define FEI_CACHE_INVALIDATE(address, len)     
  296.         CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
  297. /* driver flags */
  298. #define FEI_OWN_MEM 0x01 /* internally provided memory */
  299. #define FEI_INV_NCFD    0x02 /* invalid nCFDs provided */
  300. #define FEI_INV_NRFD    0x04 /* invalid nRFDs provided */
  301. #define FEI_POLLING 0x08 /* polling mode */
  302. #define FEI_PROMISC 0x20     /* promiscuous mode */
  303. #define FEI_MCAST 0x40     /* multicast addressing mode */
  304. #define FEI_MCASTALL 0x80     /* all multicast addressing mode */
  305. #define FEI_MEMOWN 0x10     /* device mem allocated by driver */
  306.  
  307. #define FEI_FLAG_CLEAR(clearBits)
  308.     (pDrvCtrl->flags &= ~(clearBits))
  309. #define FEI_FLAG_SET(setBits)
  310.     (pDrvCtrl->flags |= (setBits))
  311. #define FEI_FLAG_GET()
  312.     (pDrvCtrl->flags)
  313. #define FEI_FLAG_ISSET(setBits)
  314.     (pDrvCtrl->flags & (setBits))
  315. /* shortcuts */
  316. #define END_FLAGS_ISSET(setBits)
  317.     ((&pDrvCtrl->endObj)->flags & (setBits))
  318. #define FEI_VECTOR(pDrvCtrl)
  319.     ((pDrvCtrl)->board.vector)
  320. #define FEI_INT_ENABLE(pDrvCtrl)
  321.     ((int)(pDrvCtrl)->board.intEnable)
  322. #define FEI_INT_DISABLE(pDrvCtrl)
  323.     ((int)(pDrvCtrl)->board.intDisable)
  324. #define FEI_INT_ACK(pDrvCtrl)
  325.     ((int)(pDrvCtrl)->board.intAck)
  326. #define CL_OVERHEAD 4 /* prepended cluster header */
  327. #define CL_RFD_SIZE (RFD_SIZE + CL_OVERHEAD)
  328. #define FEI_SAFE_MEM(pDrvCtrl)
  329.     ((pDrvCtrl)->memSize)
  330. #define FEI_RFD_MEM(pDrvCtrl)
  331.     (CL_RFD_SIZE * (pDrvCtrl)->nRFDs)
  332. #define FEI_CFD_MEM(pDrvCtrl)
  333.     (CFD_SIZE * (pDrvCtrl)->nCFDs)
  334. #ifdef INCLUDE_RFC_1213
  335. /* Old RFC 1213 mib2 interface */
  336. #define FEI_HADDR(pEnd)                                                 
  337.         ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  338. #define FEI_HADDR_LEN(pEnd)                                             
  339.         ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  340. #else 
  341. /* New RFC 2233 mib2 interface */
  342. #define FEI_HADDR(pEnd)                                                 
  343.                 ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.phyAddress)
  344. #define FEI_HADDR_LEN(pEnd)                                             
  345.                 ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.addrLength)
  346. #endif
  347. /* Control Status Register definitions, some of them came from if_fei.h */
  348. #define CSR_STAT_OFFSET SCB_STATUS /* CSR status byte */
  349. #define CSR_ACK_OFFSET 0x01 /* CSR acknowledge byte */
  350. #define CSR_COMM_OFFSET SCB_CMD /* CSR command byte */
  351. #define CSR_INT_OFFSET 0x03 /* CSR Interrupt byte */
  352. #define CSR_GP_OFFSET SCB_POINTER /* CSR General Pointer */
  353. #define CSR_PORT_OFFSET SCB_PORT /* CSR PORT Register */
  354. #define CSR_FLASH_OFFSET SCB_FLASH /* CSR FLASH Register */
  355. #define CSR_EEPROM_OFFSET SCB_EEPROM /* CSR EEPROM Register */
  356. #define CSR_MDI_OFFSET SCB_MDI /* CSR MDI Register */
  357. #define CSR_RXBC_OFFSET SCB_EARLYRX /* CSR early RCV Byte Count */
  358. /* Control Status Registers read/write macros */
  359. /* Control Status Registers write macros */
  360. /*
  361.  * CSR_BYTE_WR, CSR_WORD_WR, and CSR_LONG_WR have a CACHE_PIPE_FLUSH() 
  362.  * and CSR_BYTE_RD (CSR_INT_OFFSET, (UINT8) tmp) embedded in them.
  363.  * The CSR_BYTE_RD is to force the write data through any write posting queues
  364.  * it may be stuck while crossing the pci. The CACHE_PIPE_FLUSH() is necessary
  365.  * to ensure the proper order of execution. The choice of reading the interrupt
  366.  * mask register is not significant except that it is a convient location 
  367.  * which has no side effects when read.
  368.  */  
  369. #define CSR_BYTE_WR(offset, value)
  370.     {
  371.     UINT8 tmp;  
  372.     FEI_BYTE_WR (((UINT32) (pDrvCtrl->pCSR) + (offset)), (value));      
  373.     CACHE_PIPE_FLUSH();
  374.     CSR_BYTE_RD (CSR_INT_OFFSET, (UINT8) tmp);                          
  375.     }
  376. #define CSR_WORD_WR(offset, value)
  377.     {
  378.     UINT8 tmp; 
  379.     FEI_WORD_WR (((UINT32) (pDrvCtrl->pCSR) + (offset)), (value));
  380.     CACHE_PIPE_FLUSH();
  381.     CSR_BYTE_RD (CSR_INT_OFFSET, (UINT8) tmp);                          
  382.     } 
  383. #define CSR_LONG_WR(offset, value)
  384.     {
  385.     UINT8 tmp; 
  386.     FEI_LONG_WR (((UINT32) (pDrvCtrl->pCSR) + (offset)), (value));
  387.     CACHE_PIPE_FLUSH();
  388.     CSR_BYTE_RD (CSR_INT_OFFSET, (UINT8) tmp);                          
  389.     } 
  390. /* this is a special case, as the device will read it as an address */
  391. #define CSR_GP_WR(value)
  392.     do {
  393.     volatile UINT32 temp = FEI_VIRT_TO_SYS (value);
  394.     
  395.     CSR_LONG_WR (CSR_GP_OFFSET, (temp));
  396.     } while (0)
  397. /* Control Status Registers read macros */
  398. #define CSR_BYTE_RD(offset, value)
  399.     FEI_BYTE_RD ((UINT32 *) ((UINT32) (pDrvCtrl->pCSR) + (offset)),
  400.      (value))
  401. #define CSR_WORD_RD(offset, value)
  402.     FEI_WORD_RD ((UINT32 *) ((UINT32) (pDrvCtrl->pCSR) + (offset)),
  403.      (value))
  404. #define CSR_LONG_RD(offset, value)
  405.     FEI_LONG_RD ((UINT32 *) ((UINT32) (pDrvCtrl->pCSR) + (offset)),
  406.      (value))
  407. /* FD rings available */
  408.  
  409. #define CFD_FREE                0x01            /* CFD free ring */
  410. #define CFD_USED                0x02            /* CFD used ring */
  411. #define RFD_FREE                0x04            /* RFD free ring */
  412.  
  413. #define CFD_COMM_WORD           0x01            /* CFD command word */
  414. #define CFD_STAT_WORD           0x02            /* CFD status word */
  415. #define RFD_COMM_WORD           0x04            /* RFD command word */
  416. #define RFD_STAT_WORD           0x08            /* RFD status word */
  417.  
  418. #define CFD_ACTION              0x01            /* generic action command */
  419. #define CFD_TX                  0x02            /* transmit command */
  420. /* frame descriptors macros: these are generic among RFDs and CFDs */
  421. #define FD_FLAG_ISSET(fdStat, bits)                                     
  422.     (((UINT16) (fdStat)) & ((UINT16) (bits)))
  423. /* get the pointer to the appropriate frame descriptor ring */
  424. #define FREE_CFD_GET(pCurrFD)
  425.     ((pCurrFD) = pDrvCtrl->pFreeCFD)
  426. #define USED_CFD_GET(pCurrFD)
  427.     ((pCurrFD) = pDrvCtrl->pUsedCFD)
  428. #define RFD_GET(pCurrFD)
  429.     ((pCurrFD) = pDrvCtrl->pRFD)
  430. /* command frame descriptors write macros */
  431. #define CFD_BYTE_WR(base, offset, value)
  432.     FEI_BYTE_WR ((UINT32 *) ((UINT32) (base) + (offset)), 
  433.      (value))
  434. #define CFD_WORD_WR(base, offset, value)
  435.     FEI_WORD_WR ((UINT32 *) ((UINT32) (base) + (offset)), 
  436.      (value))
  437. #define CFD_LONG_WR(base, offset, value)
  438.     FEI_LONG_WR ((UINT32 *) ((UINT32) (base) + (offset)), 
  439.      (value))
  440. /* this is a special case, as the device will read as an address */
  441. #define CFD_NEXT_WR(base, value)
  442.     do {
  443.     volatile UINT32 temp = (UINT32) FEI_VIRT_TO_SYS (value);
  444.     
  445.     CFD_LONG_WR ((UINT32) (base), CFD_NEXT_OFFSET, (temp));
  446.     } while (0)
  447. /* this is a special case, as the device will read as an address */
  448. #define CFD_TBD_WR(base, value)
  449.     do {
  450.     volatile UINT32 temp;                                               
  451.     temp = (value == TBD_NOT_USED) ? value :                            
  452.                    ((UINT32) FEI_VIRT_TO_SYS ((UINT32) (value)));       
  453.     CFD_LONG_WR ((UINT32) (base), CFD_TBD_OFFSET, (temp));
  454.     } while (0)
  455. /* receive frame descriptors write macros */
  456. #define RFD_BYTE_WR(base, offset, value)
  457.     FEI_BYTE_WR ((UINT32 *) ((UINT32) (base) + (offset)), 
  458.      (value))
  459. #define RFD_WORD_WR(base, offset, value)
  460.     FEI_WORD_WR ((UINT32 *) ((UINT32) (base) + (offset)), 
  461.      (value))
  462. #define RFD_LONG_WR(base, offset, value)
  463.     FEI_LONG_WR ((UINT32 *) ((UINT32) (base) + (offset)), 
  464.      (value))
  465. /* this is a special case, as the device will read as an address */
  466. #define RFD_NEXT_WR(base, value)
  467.     do {
  468.     volatile UINT32 temp = (UINT32) FEI_VIRT_TO_SYS ((UINT32) (value));
  469.     
  470.     RFD_LONG_WR ((UINT32) (base), RFD_NEXT_OFFSET, (temp));
  471.     } while (0)
  472. /* this is a special case, as the device will read as an address */
  473. #define RFD_RBD_WR(base, value)
  474.     do {
  475.     volatile UINT32 temp;                                               
  476.     temp = (value == RBD_NOT_USED) ? value :                            
  477.                   ((UINT32) FEI_VIRT_TO_SYS ((UINT32) (value)));        
  478.     RFD_LONG_WR ((UINT32) (base), RFD_RBD_OFFSET, (temp));
  479.     } while (0)
  480. /* command frame descriptors read macros */
  481. #define CFD_BYTE_RD(base, offset, value)
  482.     FEI_BYTE_RD ((UINT32 *) ((UINT32) (base) + (offset)), (value))
  483. #define CFD_WORD_RD(base, offset, value)
  484.     FEI_WORD_RD ((UINT32 *) ((UINT32) (base) + (offset)), (value))
  485. #define CFD_LONG_RD(base, offset, value)
  486.     FEI_LONG_RD ((UINT32 *) ((UINT32) (base) + (offset)), (UINT32)(value))
  487. /* this is a special case, as the device will read as an address */
  488. #define CFD_NEXT_RD(base, value)
  489.     CFD_LONG_RD ((UINT32) (base), CFD_SW_NEXT_OFFSET, (value))
  490. /* receive frame descriptors read macros */
  491. #define RFD_BYTE_RD(base, offset, value)
  492.     FEI_BYTE_RD ((UINT32 *) ((UINT32) (base) + (offset)), (value))
  493. #define RFD_WORD_RD(base, offset, value)
  494.     FEI_WORD_RD ((UINT32 *) ((UINT32) (base) + (offset)), (value))
  495. #define RFD_LONG_RD(base, offset, value)
  496.     FEI_LONG_RD ((UINT32 *) ((UINT32) (base) + (offset)), (value))
  497. /* this is a special case, as the device will read as an address */
  498. #define RFD_NEXT_RD(base, value)
  499.     RFD_LONG_RD ((UINT32) (base), RFD_SW_NEXT_OFFSET, (value))
  500. /* various command frame descriptors macros */
  501. #define CFD_PKT_ADDR(cfdBase)
  502.     ((UINT32 *) ((UINT32) cfdBase + CFD_PKT_OFFSET))
  503. #define RFD_PKT_ADDR(cfdBase)
  504.     ((UINT32 *) ((UINT32) cfdBase + RFD_PKT_OFFSET))
  505. #define CFD_IA_ADDR(cfdBase)
  506.     ((UINT32 *) ((UINT32) (cfdBase) + CFD_IA_OFFSET))
  507. #define CFD_MC_ADDR(cfdBase)
  508.     ((UINT32 *) ((UINT32) (cfdBase) + CFD_MC_OFFSET))
  509. #define CFD_CONFIG_WR(address, value)
  510.     FEI_BYTE_WR ((UINT32 *) ((UINT32) (address)),          
  511.      (value))
  512. #define I82557_INT_ENABLE(value)
  513.     {
  514.     UINT8 temp;
  515.     CACHE_PIPE_FLUSH();                                                 
  516.     CSR_BYTE_RD (CSR_INT_OFFSET, (UINT8) temp);
  517.     CSR_BYTE_WR (CSR_INT_OFFSET, (UINT8) (temp & !value));
  518.     }
  519. #define I82557_INT_DISABLE(value)
  520.     {
  521.     UINT8 temp;
  522.     CACHE_PIPE_FLUSH();                                                 
  523.     CSR_BYTE_RD (CSR_INT_OFFSET, (UINT8) temp);
  524.     CSR_BYTE_WR (CSR_INT_OFFSET, (UINT8) (temp | value));
  525.     }
  526. /*
  527.  * This is the multiplier that is applied to the number of RFDs requested
  528.  * to determine the number of "spares" available for loaning to the network
  529.  * stack.
  530.  */
  531. #define FEI_RFD_LOAN_MULTIPLIER 4
  532. /* globals */
  533. FUNCPTR feiEndIntConnect = (FUNCPTR) intConnect;
  534. FUNCPTR feiEndIntDisconnect = (FUNCPTR) NULL;
  535. /* locals */
  536. /* The definition of the driver control structure */
  537. typedef struct drv_ctrl
  538.     {
  539.     END_OBJ         endObj; /* base class */
  540.     int     unit; /* unit number */
  541.     char * pMemBase; /* 82557 memory pool base */
  542.     ULONG memSize; /* 82557 memory pool size */
  543.     char * pMemArea;  /* cluster block pointer */
  544.     int      nCFDs; /* how many CFDs to create */
  545.     int      nRFDs; /* how many RFDs to create */
  546.     volatile CSR_ID pCSR; /* pointer to CSR base */
  547.     volatile CFD_ID pFreeCFD; /* current free CFD */
  548.     volatile CFD_ID pUsedCFD; /* first used CFD */
  549.     volatile RFD_ID pRFD; /* current Receive Frame Descriptor */
  550.     INT8 flags; /* driver state */
  551.     BOOL attached; /* interface has been attached */
  552.     volatile BOOL rxHandle; /* rx handler scheduled */
  553.     BOOL txHandle; /* tx handler scheduled */
  554.     BOOL txStall; /* tx handler stalled - no CFDs */
  555.     CACHE_FUNCS cacheFuncs; /* cache descriptor */
  556.     FEI_BOARD_INFO   board; /* board specific info */
  557.     CL_POOL_ID   pClPoolId; /* cluster pool identifier */
  558.     int offset; /* Alignment offset */
  559.     UINT                deviceId; /* PCI device ID */
  560.     END_ERR             lastError;      /* Last error passed to muxError */
  561.     UINT                errorNoBufs;    /* cluster exhaustion */
  562.     } DRV_CTRL;
  563. #ifdef DRV_DEBUG557
  564. void feiPoolShow
  565.     (
  566.     int unit
  567.     )
  568.     {
  569.     DRV_CTRL *pDrvCtrl = (DRV_CTRL *)endFindByName ("fei", unit);
  570.     netPoolShow (pDrvCtrl->endObj.pNetPool);
  571.     }
  572. #endif /* DRV_DEBUG557 */
  573. /* Function declarations not in any header files */
  574. IMPORT STATUS    sys557Init (int unit, FEI_BOARD_INFO *pBoard);
  575. /* forward function declarations */
  576. LOCAL int fei82557ClkRate = 0;
  577. LOCAL STATUS    fei82557InitParse (DRV_CTRL *pDrvCtrl, char *initString);
  578. LOCAL STATUS    fei82557InitMem (DRV_CTRL *pDrvCtrl);
  579. LOCAL STATUS    fei82557Send (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  580. LOCAL UINT16 fei82557Action (DRV_CTRL *pDrvCtrl, UINT16 action);
  581. LOCAL STATUS    fei82557PhyInit (DRV_CTRL *pDrvCtrl);
  582. LOCAL STATUS fei82557Stop (DRV_CTRL *pDrvCtrl);
  583. LOCAL STATUS  fei82557Reset (DRV_CTRL *pDrvCtrl);
  584. LOCAL STATUS    fei82557SCBCommand (DRV_CTRL *pDrvCtrl, UINT8 cmd, 
  585.        BOOL addrValid, UINT32 *addr);
  586. LOCAL STATUS    fei82557Diag (DRV_CTRL *pDrvCtrl);
  587. LOCAL STATUS    fei82557IASetup (DRV_CTRL *pDrvCtrl);
  588. LOCAL STATUS    fei82557Config (DRV_CTRL *pDrvCtrl);
  589. LOCAL void fei82557MCastListForm (DRV_CTRL *pDrvCtrl, CFD_ID pCFD);
  590. LOCAL void fei82557ConfigForm (DRV_CTRL *pDrvCtrl, CFD_ID pCFD);
  591. LOCAL int fei82557MDIPhyLinkSet (DRV_CTRL *pDrvCtrl, int phyAddr);
  592. LOCAL STATUS    fei82557NOP (DRV_CTRL *pDrvCtrl);
  593. LOCAL void fei82557CFDFree (DRV_CTRL *pDrvCtrl);
  594. LOCAL void fei82557FDUpdate (DRV_CTRL *pDrvCtrl, UINT8 fdList);
  595. LOCAL void fei82557RFDReturn (DRV_CTRL *pDrvCtrl, volatile RFD_ID pRFDNew);
  596. LOCAL STATUS fei82557MDIPhyConfig (DRV_CTRL *pDrvCtrl, int phyAddr);
  597. LOCAL void fei82557Int (DRV_CTRL *pDrvCtrl);
  598. LOCAL void      fei82557HandleRecvInt (DRV_CTRL *pDrvCtrl);
  599. LOCAL void fei82557Receive (DRV_CTRL *pDrvCtrl, RFD_ID pRfd);
  600. LOCAL int fei82557MDIRead (DRV_CTRL *pDrvCtrl, int regAddr,
  601.     int phyAddr, UINT16 *retVal);
  602. LOCAL int fei82557MDIWrite (DRV_CTRL *pDrvCtrl, int regAddr,
  603.     int phyAddr, UINT16 writeData);
  604. /* debug routines, not normally compiled */
  605.       STATUS    fei82557ErrCounterDump (DRV_CTRL *pDrvCtrl, UINT32 *memAddr);
  606.       STATUS    fei82557DumpPrint (DRV_CTRL *pDrvCtrl);
  607. /* END Specific interfaces. */
  608. END_OBJ * fei82557EndLoad (char *initString);    
  609. LOCAL STATUS    fei82557Start (DRV_CTRL *pDrvCtrl);
  610. LOCAL STATUS fei82557Unload (DRV_CTRL *pDrvCtrl);
  611. LOCAL STATUS    fei82557Stop (DRV_CTRL *pDrvCtrl);
  612. LOCAL int       fei82557Ioctl (DRV_CTRL *pDrvCtrl, int cmd, caddr_t data);
  613. LOCAL STATUS    fei82557Send (DRV_CTRL *pDrvCtrl, M_BLK_ID pMblk);
  614. LOCAL STATUS    fei82557MCastAddrAdd (DRV_CTRL *pDrvCtrl, char* pAddress);
  615. LOCAL STATUS    fei82557MCastAddrDel (DRV_CTRL *pDrvCtrl, char* pAddress);
  616. LOCAL STATUS    fei82557MCastAddrGet (DRV_CTRL *pDrvCtrl,
  617.                                         MULTI_TABLE *pTable);
  618. LOCAL STATUS    fei82557PollSend (DRV_CTRL *pDrvCtrl, M_BLK_ID pMblk);
  619. LOCAL STATUS    fei82557PollReceive (DRV_CTRL *pDrvCtrl, M_BLK_ID pMblk);
  620. LOCAL STATUS    fei82557PollStart (DRV_CTRL *pDrvCtrl);
  621. LOCAL STATUS    fei82557PollStop (DRV_CTRL *pDrvCtrl);
  622. /* 
  623.  * Define the device function table.  This is static across all driver
  624.  * instances.
  625.  */
  626. LOCAL NET_FUNCS netFuncs = 
  627.     {
  628.     (FUNCPTR)fei82557Start, /* start func. */  
  629.     (FUNCPTR)fei82557Stop, /* stop func. */
  630.     (FUNCPTR)fei82557Unload, /* unload func. */
  631.     (FUNCPTR)fei82557Ioctl, /* ioctl func. */  
  632.     (FUNCPTR)fei82557Send, /* send func. */   
  633.     (FUNCPTR)fei82557MCastAddrAdd,     /* multicast add func. */  
  634.     (FUNCPTR)fei82557MCastAddrDel,     /* multicast delete func. */      
  635.     (FUNCPTR)fei82557MCastAddrGet,     /* multicast get fun. */   
  636.     (FUNCPTR)fei82557PollSend,     /* polling send func. */   
  637.     (FUNCPTR)fei82557PollReceive,     /* polling receive func. */
  638.     endEtherAddressForm,    /* put address info into a NET_BUFFER. */
  639.     endEtherPacketDataGet,  /* get pointer to data in NET_BUFFER. */
  640.     endEtherPacketAddrGet   /* Get packet addresses. */
  641.     };
  642. /*******************************************************************************
  643. *
  644. * fei82557EndLoad - initialize the driver and device
  645. *
  646. * This routine initializes both, driver and device to an operational state
  647. * using device specific parameters specified by <initString>.
  648. *
  649. * The parameter string, <initString>, is an ordered list of parameters each
  650. * separated by a colon. The format of <initString> is,
  651. * "<unit>:<memBase>:<memSize>:<nCFDs>:<nRFDs>:<flags>:<deviceId>"
  652. *
  653. * The 82557 shares a region of memory with the driver.  The caller of this
  654. * routine can specify the address of this memory region, or can specify that
  655. * the driver must obtain this memory region from the system resources.
  656. *
  657. * A default number of transmit/receive frames of 32 can be selected by
  658. * passing zero in the parameters <nTfds> and <nRfds>. In other cases, the
  659. * number of frames selected should be greater than two.
  660. *
  661. * The <memBase> parameter is used to inform the driver about the shared
  662. * memory region.  If this parameter is set to the constant "NONE," then this
  663. * routine will attempt to allocate the shared memory from the system.  Any
  664. * other value for this parameter is interpreted by this routine as the address
  665. * of the shared memory region to be used. The <memSize> parameter is used
  666. * to check that this region is large enough with respect to the provided
  667. * values of both transmit/receive frames.
  668. *
  669. * If the caller provides the shared memory region, then the driver assumes
  670. * that this region does not require cache coherency operations, nor does it
  671. * require conversions between virtual and physical addresses.
  672. *
  673. * If the caller indicates that this routine must allocate the shared memory
  674. * region, then this routine will use cacheDmaMalloc() to obtain
  675. * some  non-cacheable memory.  The attributes of this memory will be checked,
  676. * and if the memory is not write coherent, this routine will abort and
  677. * return ERROR.
  678. *
  679. * RETURNS: an END object pointer, or NULL on error.
  680. *
  681. * SEE ALSO: ifLib,
  682. * .I "Intel 82557 User's Manual"
  683. */
  684. END_OBJ* fei82557EndLoad
  685.     (
  686.     char *initString      /* parameter string */
  687.     )
  688.     {
  689.     DRV_CTRL * pDrvCtrl;       /* pointer to DRV_CTRL structure */
  690.     UCHAR    enetAddr[6]; /* ethernet address */
  691.     UINT32 speed;
  692.     UINT32 scbStatus;
  693.     char        bucket[2];
  694.     DRV_LOG (DRV_DEBUG_LOAD, ("Loading endn"), 1, 2, 3, 4, 5, 6);
  695.     if (initString == NULL)
  696. return (NULL);
  697.     if (initString[0] == 0)
  698. {
  699. bcopy ((char *)DEV_NAME, (void *)initString, DEV_NAME_LEN);
  700. return (0);
  701. }
  702.     /* allocate the device structure */
  703.     pDrvCtrl = (DRV_CTRL *) calloc (sizeof (DRV_CTRL), 1);
  704.     if (pDrvCtrl == NULL)
  705. return (NULL);
  706.     /* Parse InitString */
  707.     if (fei82557InitParse (pDrvCtrl, initString) == ERROR)
  708. goto errorExit;
  709.     /* sanity check the unit number */
  710.     if (pDrvCtrl->unit < 0 )
  711. goto errorExit;    
  712.     /* 
  713.      * initialize the default parameter for the Physical medium 
  714.      * layer control user has his chance to override in the BSP, 
  715.      * just be CAREFUL 
  716.      */
  717.     pDrvCtrl->board.phyAddr  = 1;
  718.     pDrvCtrl->board.phySpeed = PHY_AUTO_SPEED;
  719.     pDrvCtrl->board.phyDpx   = PHY_AUTO_DPX;
  720.     pDrvCtrl->board.others   = 0;
  721.     pDrvCtrl->board.tcbTxThresh = FEI_TCB_TX_THRESH;
  722.     /* callout to perform adapter init */
  723.     if (sys557Init (pDrvCtrl->unit, &pDrvCtrl->board) == ERROR)
  724. goto errorExit;
  725.     /* get CSR address from the FEI_BOARD_INFO structure */
  726.     if ((pDrvCtrl->pCSR = (CSR_ID) pDrvCtrl->board.baseAddr) == NULL)
  727. goto errorExit;
  728.     /* probe for memory-mapped CSR */
  729.     CACHE_PIPE_FLUSH();
  730.     CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus);
  731.     if (vxMemProbe ((char *) &scbStatus, VX_READ, 2,
  732.     &bucket[0]) != OK)
  733. {
  734. DRV_LOG (DRV_DEBUG_LOAD,
  735.    (": need MMU mapping for address 0x%xn"),
  736.    (UINT32) pDrvCtrl->pCSR, 2, 3, 4, 5, 6);
  737. goto errorExit;
  738. }
  739.     /* memory initialization */
  740.     if (fei82557InitMem (pDrvCtrl) == ERROR)
  741. goto errorExit;
  742.     I82557_INT_DISABLE(SCB_C_M);
  743.     /* initialize the Physical medium layer */
  744.     if (fei82557PhyInit (pDrvCtrl) != OK)
  745. {
  746. DRV_PRINT (DRV_DEBUG_LOAD,
  747.    ("LINK FAILS, Check line connectionn"));
  748. }
  749.     speed = ((((int) pDrvCtrl->board.phySpeed) == PHY_100MBS) ?
  750. FEI_100MBS : FEI_10MBS);
  751.     if (fei82557ClkRate == 0)
  752. fei82557ClkRate = sysClkRateGet ();
  753.     /* 
  754.      * reset the chip: this should be replaced by a true 
  755.      * adapter reset routine, once the init code is here.
  756.      */
  757.     if (fei82557Reset (pDrvCtrl) != OK)
  758. goto errorExit;
  759.     /* CU and RU should be idle following fei82557Reset() */
  760.     if (fei82557SCBCommand (pDrvCtrl, SCB_C_CULDBASE, TRUE, 0x0) == ERROR)
  761. goto errorExit;
  762.     if (fei82557SCBCommand (pDrvCtrl, SCB_C_RULDBASE, TRUE, 0x0) == ERROR)
  763. goto errorExit;
  764.     pDrvCtrl->attached = TRUE;
  765.     /* get our ethernet hardware address */
  766.     bcopy ((char *)&pDrvCtrl->board.enetAddr,
  767.    (char *)&enetAddr[0],
  768.    FEI_ADDR_LEN);
  769.     DRV_LOG (DRV_DEBUG_LOAD, ("fei82557Load...n
  770.  ADRR: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x n "), 
  771. enetAddr[0],
  772. enetAddr[1],
  773. enetAddr[2],
  774. enetAddr[3],
  775. enetAddr[4],
  776. enetAddr[5]);
  777.     /* endObj initializations */
  778.     if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ*) pDrvCtrl,
  779.       DEV_NAME, pDrvCtrl->unit, &netFuncs,
  780.       "Intel 82557 Ethernet Enhanced Network Driver") == ERROR)
  781. goto errorExit;
  782. #ifdef INCLUDE_RFC_1213
  783.     /* Old RFC 1213 mib2 interface */
  784.     if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
  785.                       (u_char *) &enetAddr[0], FEI_ADDR_LEN,
  786.                       ETHERMTU, speed) == ERROR)
  787.         goto errorExit;
  788.     /* Mark the device ready */
  789.     END_OBJ_READY (&pDrvCtrl->endObj,
  790.                    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
  791. #else
  792.     /* New RFC 2233 mib2 interface */
  793.     /* Initialize MIB-II entries (for RFC 2233 ifXTable) */
  794.     pDrvCtrl->endObj.pMib2Tbl = m2IfAlloc(M2_ifType_ethernet_csmacd,
  795.                                           (UINT8*) enetAddr, 6,
  796.                                           ETHERMTU, speed,
  797.                                           DEV_NAME, pDrvCtrl->unit);
  798.     if (pDrvCtrl->endObj.pMib2Tbl == NULL)
  799.         {
  800.         printf ("%s%d - MIB-II initializations failedn",
  801.                 DEV_NAME, pDrvCtrl->unit);
  802.         goto errorExit;
  803.         }
  804.         
  805.     /* 
  806.      * Set the RFC2233 flag bit in the END object flags field and
  807.      * install the counter update routines.
  808.      */
  809.     m2IfPktCountRtnInstall(pDrvCtrl->endObj.pMib2Tbl, m2If8023PacketCount);
  810.     /*
  811.      * Make a copy of the data in mib2Tbl struct as well. We do this
  812.      * mainly for backward compatibility issues. There might be some
  813.      * code that might be referencing the END pointer and might
  814.      * possibly do lookups on the mib2Tbl, which will cause all sorts
  815.      * of problems.
  816.      */
  817.     bcopy ((char *)&pDrvCtrl->endObj.pMib2Tbl->m2Data.mibIfTbl,
  818.                    (char *)&pDrvCtrl->endObj.mib2Tbl, sizeof (M2_INTERFACETBL));
  819.     /* Mark the device ready */
  820.     END_OBJ_READY (&pDrvCtrl->endObj,
  821.                    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST |
  822.                    END_MIB_2233);
  823. #endif /* INCLUDE_RFC_1213 */
  824.     DRV_LOG (DRV_DEBUG_LOAD, ("fei82557Load... Done n"), 1, 2, 3, 4, 5, 6);
  825.     return (&pDrvCtrl->endObj);
  826. errorExit:
  827.     DRV_LOG (DRV_DEBUG_LOAD, "fei82557Load failedn", 0,0,0,0,0,0);
  828.     fei82557Unload (pDrvCtrl);
  829.     free ((char *) pDrvCtrl);
  830.     return NULL;
  831.     }
  832. /*******************************************************************************
  833. *
  834. * fei82557Unload - unload a driver from the system
  835. *
  836. * RETURNS: N/A
  837. */
  838. LOCAL STATUS fei82557Unload
  839.     (
  840.     DRV_CTRL *pDrvCtrl       /* pointer to DRV_CTRL structure */
  841.     )
  842.     {
  843.     
  844.     DRV_LOG (DRV_DEBUG_LOAD, ("Unloading end..."), 1, 2, 3, 4, 5, 6);
  845. #ifndef INCLUDE_RFC_1213
  846.     /* New RFC 2233 mib2 interface */
  847.     /* Free MIB-II entries */
  848.     m2IfFree(pDrvCtrl->endObj.pMib2Tbl);
  849.     pDrvCtrl->endObj.pMib2Tbl = NULL;
  850. #endif /* INCLUDE_RFC_1213 */
  851.     pDrvCtrl->attached = FALSE;
  852.     /* free lists */
  853.     END_OBJECT_UNLOAD (&pDrvCtrl->endObj);
  854.     /* free allocated memory if necessary */
  855.     if ((FEI_FLAG_ISSET (FEI_OWN_MEM)) && 
  856. (pDrvCtrl->pMemBase != NULL))
  857. cacheDmaFree (pDrvCtrl->pMemBase);
  858.     /* free allocated memory if necessary */
  859.     cfree (pDrvCtrl->pMemArea);
  860.     DRV_LOG (DRV_DEBUG_LOAD, ("fei82557Unload... Donen"), 1, 2, 3, 4, 5, 6);
  861.     return (OK);
  862.     }
  863. /*******************************************************************************
  864. *
  865. * fei82557InitParse - parse parameter values from initString
  866. *
  867. * RETURNS: OK or ERROR
  868. */
  869. LOCAL STATUS fei82557InitParse
  870.     (
  871.     DRV_CTRL * pDrvCtrl,       /* pointer to DRV_CTRL structure */
  872.     char * initString /* parameter string */
  873.     )
  874.     {
  875.     char *  tok; /* an initString token */
  876.     char *  holder = NULL; /* points to initString fragment beyond tok */
  877.     tok = strtok_r (initString, ":", &holder);
  878.     if (tok == NULL)
  879. return ERROR;
  880.     pDrvCtrl->unit = atoi (tok);
  881.     tok = strtok_r (NULL, ":", &holder);
  882.     if (tok == NULL)
  883. return ERROR;
  884.     pDrvCtrl->pMemBase = (char *) strtoul (tok, NULL, 16);
  885.     tok = strtok_r (NULL, ":", &holder);
  886.     if (tok == NULL)
  887. return ERROR;
  888.     pDrvCtrl->memSize = strtoul (tok, NULL, 16);
  889.     tok = strtok_r (NULL, ":", &holder);
  890.     if (tok == NULL)
  891. return ERROR;
  892.     pDrvCtrl->nCFDs = strtoul (tok, NULL, 16);
  893.     tok = strtok_r (NULL, ":", &holder);
  894.     if (tok == NULL)
  895. return ERROR;
  896.     pDrvCtrl->nRFDs = strtoul (tok, NULL, 16);
  897.     tok = strtok_r (NULL, ":", &holder);
  898.     if (tok == NULL)
  899. return ERROR;
  900.     pDrvCtrl->flags = atoi (tok);
  901.     /* offset value is optional, default is zero */
  902.     pDrvCtrl->offset = 0;
  903.     tok = strtok_r (NULL, ":", &holder);
  904.     if (tok != NULL)
  905. pDrvCtrl->offset = atoi (tok);
  906.     /* device ID is optional, default is zero */
  907.     pDrvCtrl->deviceId = 0;
  908.     tok = strtok_r (NULL, ":", &holder);
  909.     if (tok != NULL)
  910. pDrvCtrl->deviceId = atoi (tok);
  911.     if (!pDrvCtrl->nCFDs || pDrvCtrl->nCFDs <= 2)
  912. {
  913. FEI_FLAG_SET (FEI_INV_NCFD);
  914. pDrvCtrl->nCFDs = DEF_NUM_CFDS;
  915. }
  916.     if (!pDrvCtrl->nRFDs || pDrvCtrl->nRFDs <= 2)
  917. {
  918. FEI_FLAG_SET (FEI_INV_NRFD);
  919. pDrvCtrl->nRFDs = DEF_NUM_RFDS;
  920. }
  921.     DRV_LOG (DRV_DEBUG_LOAD,
  922.     "fei82557EndLoad: unit=%d pMemBase=0x%x memSize=0x%xn",
  923.     pDrvCtrl->unit, (int) pDrvCtrl->pMemBase,
  924.     (int) pDrvCtrl->memSize, 0,0,0);
  925.     DRV_LOG (DRV_DEBUG_LOAD,
  926.     "fei82557EndLoad: nCFDs=%d nRFDs=%d flags=%d offset=%dn",
  927.     pDrvCtrl->nCFDs, pDrvCtrl->nRFDs, pDrvCtrl->flags,
  928.     pDrvCtrl->offset, 0, 0);
  929.     return (OK);
  930.     }
  931. /*******************************************************************************
  932. *
  933. * fei82557InitMem - initialize memory
  934. *
  935. * RETURNS: OK or ERROR
  936. */
  937. LOCAL STATUS fei82557InitMem
  938.     (
  939.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  940.     )
  941.     {
  942.     volatile CFD_ID pCFD;     /* pointer to CFDs */
  943.     volatile RFD_ID pRFD;     /* pointer to RFDs */
  944.     UINT32 size;     /* temporary size holder */
  945.     int ix; /* a counter */
  946.     int nRFDLoan; /* number of loaning RFDs */
  947.     BOOL firstCFD = TRUE;/* is this the first CFD? */
  948.     BOOL firstRFD = TRUE;/* is this the first RFD? */
  949.     M_CL_CONFIG  fei82557MclBlkConfig =
  950.     {
  951. /*
  952.  *  mBlkNum   clBlkNum      memArea     memSize
  953.  *  -----------   ---- -------     -------
  954.  */
  955.     0, 0,  NULL,      0
  956.     };
  957.     CL_DESC  fei82557ClDescTbl [] =
  958.     {
  959. /*
  960.  *  clusterSize   num     memArea     memSize
  961.  *  -----------   ---- -------     -------
  962.  */
  963. {RFD_SIZE, 0,   NULL,       0}    
  964.     };
  965.     int fei82557ClDescTblNumEnt = (NELEMENTS (fei82557ClDescTbl));
  966.     /* initialize the netPool */
  967.     if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof (NET_POOL))) == NULL)
  968. return (ERROR);
  969.     /* it looks sensible */
  970.     nRFDLoan = (pDrvCtrl->nRFDs * FEI_RFD_LOAN_MULTIPLIER);
  971.     /* 
  972.      * the final 4 is to allow for alignment 
  973.      */
  974.     size = (((pDrvCtrl->nRFDs) * (CL_RFD_SIZE)) +
  975.     (nRFDLoan * (CL_RFD_SIZE)) +
  976.     ((pDrvCtrl->nCFDs) * (CFD_SIZE + sizeof(long))) + 
  977.     4);
  978.     /* 
  979.      * Establish the memory area that we will share with the device.  If
  980.      * the caller has provided an area, then we assume it is non-cacheable
  981.      * and will not require the use of the special cache routines.
  982.      * If the caller did not provide an area, then we must obtain it from
  983.      * the system, using the cache savvy allocation routine.
  984.      */
  985.     switch ((int) pDrvCtrl->pMemBase)
  986. {
  987. case NONE :      /* we must obtain it */
  988.     /* this driver can't handle write incoherent caches */
  989.     if (!CACHE_DMA_IS_WRITE_COHERENT ()) 
  990. {
  991. DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: shared 
  992.     memory not cache coherentn"),
  993.     1, 2, 3, 4, 5, 6);
  994. return (ERROR);
  995. }
  996.     pDrvCtrl->pMemBase = cacheDmaMalloc (size);
  997.     if (pDrvCtrl->pMemBase == NULL)      /* no memory available */
  998. {
  999. DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: could not 
  1000.     obtain memoryn"),
  1001.     1, 2, 3, 4, 5, 6);
  1002. return (ERROR);
  1003. }
  1004.     pDrvCtrl->memSize = size;
  1005.     FEI_FLAG_SET (FEI_OWN_MEM);
  1006.     pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  1007.     break;
  1008. default :        /* the user provided an area */
  1009.     if (pDrvCtrl->memSize == 0) 
  1010. {
  1011. DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: not enough 
  1012.    memoryn"),
  1013.    1, 2, 3, 4, 5, 6);
  1014. return (ERROR);
  1015. }
  1016.     /* 
  1017.      * check the user provided enough memory with reference
  1018.      * to the given number of receive/transmit frames, if any.
  1019.      */
  1020.     if (FEI_FLAG_ISSET (FEI_INV_NCFD) && 
  1021. FEI_FLAG_ISSET (FEI_INV_NRFD))
  1022. {
  1023. pDrvCtrl->nCFDs = pDrvCtrl->nRFDs = 
  1024. (FEI_SAFE_MEM (pDrvCtrl) / 
  1025.  ((2 * CL_RFD_SIZE) + CFD_SIZE));
  1026. }
  1027.     else if (FEI_FLAG_ISSET (FEI_INV_NCFD))
  1028. {
  1029. pDrvCtrl->nCFDs = 
  1030. ((FEI_SAFE_MEM (pDrvCtrl) - 
  1031.  (2 * FEI_RFD_MEM (pDrvCtrl))) /
  1032.  (CFD_SIZE));
  1033. }
  1034.     else if (FEI_FLAG_ISSET (FEI_INV_NRFD))
  1035. {
  1036. pDrvCtrl->nRFDs = 
  1037. ((FEI_SAFE_MEM (pDrvCtrl) - 
  1038.  FEI_CFD_MEM (pDrvCtrl)) /
  1039.  (2 * CL_RFD_SIZE));
  1040. }
  1041.     else
  1042. {
  1043. if (pDrvCtrl->memSize < size) 
  1044.     {
  1045.     DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: not enough 
  1046.       memoryn"),
  1047.       1, 2, 3, 4, 5, 6);
  1048.     return (ERROR);
  1049.     }
  1050. }
  1051.     if ((pDrvCtrl->nCFDs <= 2) || (pDrvCtrl->nRFDs <= 2))
  1052. {
  1053. DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: not enough 
  1054.   memoryn"),
  1055.   1, 2, 3, 4, 5, 6);
  1056. return (ERROR);
  1057. }
  1058.     FEI_FLAG_CLEAR (FEI_OWN_MEM);
  1059.     pDrvCtrl->cacheFuncs = cacheNullFuncs;
  1060.     break;
  1061. }
  1062.     /* zero the shared memory */
  1063.     memset (pDrvCtrl->pMemBase, 0, (int) pDrvCtrl->memSize);
  1064.     /* pool of mblks */
  1065.     if (fei82557MclBlkConfig.mBlkNum == 0)
  1066.         fei82557MclBlkConfig.mBlkNum = ((pDrvCtrl->nRFDs) *
  1067.                                         FEI_RFD_LOAN_MULTIPLIER + 1 ) * 5;
  1068.     /* pool of clusters, including loaning buffers */
  1069.     if (fei82557ClDescTbl[0].clNum == 0)
  1070. {
  1071. fei82557ClDescTbl[0].clNum = ((pDrvCtrl->nRFDs) * 
  1072.                                        (FEI_RFD_LOAN_MULTIPLIER + 1));
  1073. fei82557ClDescTbl[0].clSize = RFD_SIZE;
  1074. }
  1075.     fei82557ClDescTbl[0].memSize = (fei82557ClDescTbl[0].clNum * 
  1076.   (fei82557ClDescTbl[0].clSize + CL_OVERHEAD));
  1077.     fei82557ClDescTbl[0].memArea = pDrvCtrl->pMemBase + 
  1078.   (pDrvCtrl->nCFDs * CFD_SIZE);
  1079.     /* align the shared memory */
  1080.     fei82557ClDescTbl[0].memArea = (char *) 
  1081.    (((u_long) fei82557ClDescTbl[0].memArea + 0x3)
  1082.    & ~0x3);
  1083.     /* pool of cluster blocks */
  1084.     if (fei82557MclBlkConfig.clBlkNum == 0)
  1085. fei82557MclBlkConfig.clBlkNum = fei82557ClDescTbl[0].clNum;
  1086.     /* get memory for mblks */
  1087.     if (fei82557MclBlkConfig.memArea == NULL)
  1088. {
  1089. /* memory size adjusted to hold the netPool pointer at the head */
  1090. fei82557MclBlkConfig.memSize = ((fei82557MclBlkConfig.mBlkNum *
  1091.        (M_BLK_SZ + sizeof(long)))  +
  1092.        (fei82557MclBlkConfig.clBlkNum * 
  1093. CL_BLK_SZ + sizeof(long)));
  1094. if ((fei82557MclBlkConfig.memArea = (char *) memalign
  1095.     (4, fei82557MclBlkConfig.memSize))
  1096.     == NULL)
  1097.     return (ERROR);
  1098. /* store the pointer to the cluster area */
  1099. pDrvCtrl->pMemArea = fei82557MclBlkConfig.memArea;
  1100. }
  1101.     /* init the mem pool */
  1102.     if (netPoolInit (pDrvCtrl->endObj.pNetPool, &fei82557MclBlkConfig, 
  1103.      &fei82557ClDescTbl[0], fei82557ClDescTblNumEnt, NULL) 
  1104.      == ERROR)
  1105. return (ERROR);
  1106.     if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool,
  1107.        RFD_SIZE, FALSE)) == NULL)
  1108. return (ERROR);
  1109.     /* carve up the shared-memory region */
  1110.     /*
  1111.      * N.B.
  1112.      * We are setting up the CFD ring as a ring of TxCBs, tied off with a
  1113.      * CFD_C_SUSP as frames are copied into the data buffers.  The
  1114.      * susp/resume model is used because the links to the next CFDs do
  1115.      * not change -- it is a fixed ring.  Also note that if a CFD is needed
  1116.      * for anything else (e.g., DIAG, NOP, DUMP, CONFIG, or IASETUP comands),
  1117.      * then the commands will use the current CFD in the ring.  After the
  1118.      * command is complete, it will be set back to a TxCB by fei82557Action().
  1119.      */
  1120.     /* First ready CFD pointer */
  1121.     pCFD = pDrvCtrl->pFreeCFD = (CFD_ID) pDrvCtrl->pMemBase;
  1122.     /* initialize the CFD ring */
  1123.     for (ix = 0; ix < pDrvCtrl->nCFDs; ix++)
  1124. {
  1125. CFD_WORD_WR (pCFD, CFD_STAT_OFFSET,
  1126.      (CFD_S_COMPLETE | CFD_S_OK));
  1127.     
  1128. /* tie the current CFD to the next one */
  1129. CFD_NEXT_WR (pCFD, ((UINT32) pCFD + CFD_SIZE));
  1130. CFD_LONG_WR (pCFD, CFD_SW_NEXT_OFFSET, ((UINT32) pCFD + CFD_SIZE));
  1131.     
  1132. if (!firstCFD)
  1133.     {
  1134.     /* Previous CFD pointer */
  1135.     CFD_LONG_WR (pCFD, CFD_PREV_OFFSET,
  1136.  ((UINT32) pCFD - CFD_SIZE));
  1137.     }
  1138. else
  1139.     {
  1140.     /* remember this CFD */
  1141.     pDrvCtrl->pFreeCFD = pCFD;
  1142.     /* tie the first CFD to the last one */
  1143.     CFD_LONG_WR (pCFD, CFD_PREV_OFFSET,
  1144.  ((UINT32) pCFD + (CFD_SIZE * (pDrvCtrl->nCFDs - 1))));
  1145.     firstCFD = FALSE;
  1146.     }
  1147. /* no TBDs used */
  1148. CFD_TBD_WR (pCFD, (UINT32) TBD_NOT_USED);
  1149. CFD_BYTE_WR (pCFD, CFD_NUM_OFFSET, 0);
  1150. /* set the thresh value */
  1151. CFD_BYTE_WR (pCFD, CFD_THRESH_OFFSET, 
  1152.      pDrvCtrl->board.tcbTxThresh);
  1153. /* bump to the next CFD */
  1154. pCFD = (CFD_ID) ((UINT32) pCFD + CFD_SIZE);
  1155. }
  1156.     pCFD = (CFD_ID) ((UINT32) pCFD - CFD_SIZE);
  1157.     /* tie the last CFD to the first one */
  1158.     CFD_NEXT_WR (pCFD, ((UINT32) pDrvCtrl->pFreeCFD));
  1159.     CFD_LONG_WR (pCFD, CFD_SW_NEXT_OFFSET, ((UINT32) pDrvCtrl->pFreeCFD));
  1160.     /* set the used CFDs ring to the free one */
  1161.     pDrvCtrl->pUsedCFD = pDrvCtrl->pFreeCFD;
  1162.     /*
  1163.      * N.B.
  1164.      * Use RFD_C_EL to tie the end of the RBD ring, and not RFD_C_SUSP
  1165.      * This is because we want the option of inserting a new RFD into
  1166.      * the ring on the fly (i.e., via an SCB_RUSTART command).  Why would
  1167.      * we do this?  Buffer loaning....  A suspend/resume reception model
  1168.      * will not allow us to do this, so we must use an idle/start model.
  1169.      */
  1170.     /* initialize the RFD ring, some of the fields will be done 
  1171.      * in fei82557Start 
  1172.      */
  1173.     for (ix = 0; ix < pDrvCtrl->nRFDs; ix++)
  1174. {
  1175. volatile RFD_ID    pRFDOld;
  1176. if ((pRFD = (RFD_ID) netClusterGet (pDrvCtrl->endObj.pNetPool,
  1177.    pDrvCtrl->pClPoolId)) == NULL)
  1178.     return (ERROR);
  1179. if (firstRFD)
  1180.     {
  1181.     /* first ready RFD pointer */
  1182.     pDrvCtrl->pRFD = pRFD;
  1183.     firstRFD = FALSE;
  1184.     }
  1185. else
  1186.     {
  1187.     /* tie the previous RFD to the current one */
  1188.     RFD_NEXT_WR (pRFDOld, (UINT32) pRFD);
  1189.     RFD_LONG_WR (pRFDOld, RFD_SW_NEXT_OFFSET, (UINT32) pRFD);
  1190.     RFD_LONG_WR (pRFD, RFD_PREV_OFFSET, (UINT32) pRFDOld);
  1191.     }
  1192. /* no RBDs used */
  1193.         RFD_RBD_WR (pRFD, (UINT32) RBD_NOT_USED);
  1194. /* set the actual count field to zero */
  1195.         RFD_WORD_WR (pRFD, RFD_COUNT_OFFSET, 0);
  1196. /* set the size field for Ethernet packets */
  1197.         RFD_WORD_WR (pRFD, RFD_SIZE_OFFSET,
  1198.      (UINT32) (ETHERMTU + EH_SIZE));
  1199. /* remember this RFD */
  1200. pRFDOld = pRFD;
  1201. }
  1202.     /* tie the last RFD to the first one */
  1203.     RFD_NEXT_WR ((UINT32) pRFD, (UINT32) pDrvCtrl->pRFD);
  1204.     RFD_LONG_WR (pRFD, RFD_SW_NEXT_OFFSET, (UINT32) pDrvCtrl->pRFD);
  1205.     /* link the first RFD to the last one */
  1206.     RFD_LONG_WR (pDrvCtrl->pRFD, RFD_PREV_OFFSET, (UINT32) pRFD);
  1207.     /* Flush the write pipe */
  1208.     CACHE_PIPE_FLUSH ();
  1209.     DRV_LOG (DRV_DEBUG_LOAD, ("fei82557InitMem... Donen"),
  1210. 0, 0, 0, 0, 0, 0);
  1211.     return OK;
  1212.     }
  1213. /**************************************************************************
  1214. *
  1215. * fei82557Start - start the device
  1216. *
  1217. * This routine starts the 82557 device and brings it up to an operational
  1218. * state.  The driver must have already been attached with the fei82557Load()
  1219. * routine.
  1220. *
  1221. * RETURNS: OK, or ERROR if the device could not be initialized.
  1222. */
  1223. LOCAL STATUS fei82557Start
  1224.     (
  1225.     DRV_CTRL *pDrvCtrl       /* pointer to DRV_CTRL structure */
  1226.     )
  1227.     {
  1228.     RFD_ID       pRFD;
  1229.     UINT32       tempVar;
  1230.     int retVal;
  1231.     DRV_LOG (DRV_DEBUG_START, ("Starting end...n"), 1, 2, 3, 4, 5, 6);
  1232.     /* must have been attached */
  1233.     if (!pDrvCtrl->attached)
  1234. return (ERROR);
  1235.     /* reset the chip */
  1236.     if (fei82557Reset (pDrvCtrl) == ERROR)
  1237. return (ERROR);
  1238.     /* connect the int handler */
  1239.     SYS_INT_CONNECT (pDrvCtrl, fei82557Int, (int) pDrvCtrl, &retVal);
  1240.     if (retVal == ERROR)
  1241. return (ERROR);
  1242.     /* acknowledge interrupts */
  1243.     SYS_INT_ACK (pDrvCtrl);
  1244.     /* enable chip interrupts after fei82557Reset disabled them */
  1245.     I82557_INT_ENABLE(SCB_C_M);
  1246.     /* enable system interrupts after fei82557Reset disabled them */
  1247.     SYS_INT_ENABLE (pDrvCtrl);
  1248.     /* run diagnostics */
  1249.     if (fei82557Diag (pDrvCtrl) == ERROR)    
  1250. return (ERROR);
  1251.     /* setup address */
  1252.     if (fei82557IASetup (pDrvCtrl) == ERROR)
  1253. return (ERROR);
  1254.     if (END_FLAGS_ISSET (IFF_MULTICAST))
  1255.         FEI_FLAG_SET (FEI_MCAST);
  1256.  
  1257.     /* configure chip */
  1258.     if (fei82557Config (pDrvCtrl) == ERROR)
  1259. return (ERROR);
  1260.     /* set some flags to default values */
  1261.     pDrvCtrl->rxHandle = FALSE;
  1262.     pDrvCtrl->txHandle = FALSE;
  1263.     pDrvCtrl->txStall = FALSE;
  1264.     /* get the current free RFD */
  1265.     RFD_GET (pRFD);
  1266.     /* initiailize RFD ring */
  1267.     do 
  1268. {
  1269. /* set state and command for this RFD */
  1270. RFD_WORD_WR (pRFD, RFD_STAT_OFFSET, (UINT32) 0);
  1271. RFD_WORD_WR (pRFD, RFD_COMM_OFFSET, (UINT32) 0);
  1272. /* bump to the next RFD */
  1273. RFD_LONG_RD (pRFD, RFD_SW_NEXT_OFFSET, tempVar);
  1274. pRFD = (RFD_ID) tempVar;
  1275. } while (pRFD != pDrvCtrl->pRFD);
  1276.     /* mark the last RFD for the chip to became idle */
  1277.     RFD_LONG_RD (pRFD, RFD_PREV_OFFSET, tempVar);
  1278.     RFD_WORD_WR (tempVar, RFD_COMM_OFFSET, (UINT32) RFD_C_EL);
  1279.     /* Flush the write pipe */
  1280.     CACHE_PIPE_FLUSH ();
  1281.     /* put CU into suspended state */
  1282.     if (fei82557NOP (pDrvCtrl) == ERROR)
  1283. return (ERROR);
  1284.     /* mark the interface as up */
  1285.     END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  1286.     /* startup the receiver */
  1287.     if (fei82557SCBCommand (pDrvCtrl, SCB_C_RUSTART, TRUE, pRFD)
  1288. == ERROR)
  1289. return (ERROR);
  1290.     DRV_LOG (DRV_DEBUG_START, ("Starting end... Donen"), 1, 2, 3, 4, 5, 6);
  1291.     return (OK);
  1292.     }
  1293. /*******************************************************************************
  1294. * fei82557Send - send an Ethernet packet
  1295. *
  1296. * This routine() takes a M_BLK_ID and sends off the data in the M_BLK_ID.
  1297. * The buffer must already have the addressing information properly installed
  1298. * in it. This is done by a higher layer.
  1299. *
  1300. * muxSend() calls this routine each time it wants to send a packet.
  1301. *
  1302. * RETURNS: N/A
  1303. */
  1304. LOCAL STATUS fei82557Send
  1305.     (
  1306.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1307.     M_BLK *  pMblk           /* pointer to the mBlk/cluster pair */
  1308.     )
  1309.     {
  1310.     volatile CFD_ID  pCFD;
  1311.     volatile CFD_ID  pPrevCFD;
  1312.     int len = 0;
  1313.     volatile UINT16 command;
  1314.     volatile UINT16 status;
  1315.     char * pEnetHdr;
  1316.     volatile UINT16 scbStatus;
  1317.     DRV_LOG (DRV_DEBUG_TX, ("fei82557Send...n"), 1, 2, 3, 4, 5, 6);
  1318.     /* check device mode */
  1319.     if (FEI_FLAG_ISSET (FEI_POLLING))
  1320.         {
  1321.         netMblkClChainFree (pMblk); /* free the given mBlk chain */
  1322.         errno = EINVAL;
  1323.         return (ERROR);
  1324.         }
  1325.     /* interlock with fei82557CFDFree */
  1326.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  1327.     /* check for CFDs availability */
  1328.     /* get the current free CFD */
  1329.     FREE_CFD_GET (pCFD);
  1330.  
  1331.     /* Make cache consistent with memory */
  1332.     FEI_CACHE_INVALIDATE (pCFD, 4);
  1333.  
  1334.     /* read the CFD status word */
  1335.     CFD_WORD_RD (pCFD, CFD_STAT_OFFSET, status);
  1336.  
  1337.     if (!(FD_FLAG_ISSET (status, (CFD_S_COMPLETE | CFD_S_OK))))
  1338. {
  1339. DRV_LOG (DRV_DEBUG_TX, ("fei82557Send...NO CFDS n"), 1, 2, 3, 4, 5, 6);
  1340. /* set to stall condition */
  1341. pDrvCtrl->txStall = TRUE;
  1342.        
  1343.         CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus);
  1344.         if ((scbStatus & SCB_S_CUMASK) == SCB_S_CUSUSP)
  1345.     {
  1346.     if (fei82557SCBCommand (pDrvCtrl, SCB_C_CUSTART, TRUE, pCFD) 
  1347.              == ERROR)
  1348. {
  1349. DRV_LOG (DRV_DEBUG_TX,("CU Start failed n"), 0, 0, 0, 0, 0, 0);
  1350.     }
  1351. END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1352. return (END_ERR_BLOCK);
  1353. }
  1354.     pEnetHdr = (char *) (CFD_PKT_ADDR (pCFD));
  1355.     len = netMblkToBufCopy (pMblk, (char *) pEnetHdr, NULL);
  1356.     netMblkClChainFree (pMblk);
  1357.     len = max (ETHERSMALL, len); 
  1358. #ifndef INCLUDE_RFC_1213
  1359.     /* New RFC 2233 mib2 interface */
  1360.     /* RFC 2233 mib2 counter update for outgoing packet */
  1361.     if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  1362.         {
  1363.         pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,
  1364.                                                  M2_PACKET_OUT, pEnetHdr, len);
  1365.         }
  1366. #endif /* INCLUDE_RFC_1213 */
  1367.     /* set up the current CFD */
  1368.     CFD_WORD_WR (pCFD, CFD_COUNT_OFFSET, ((len & 0x3fff) | TCB_CNT_EOF));
  1369.     CFD_WORD_WR (pCFD, CFD_COMM_OFFSET, (CFD_C_XMIT | CFD_C_SUSP));
  1370.     CFD_WORD_WR (pCFD, CFD_STAT_OFFSET, 0);
  1371.     /* set the thresh value */
  1372.     CFD_BYTE_WR (pCFD, CFD_THRESH_OFFSET, 
  1373.  pDrvCtrl->board.tcbTxThresh);
  1374.     /* no TBDs used */
  1375.     CFD_BYTE_WR (pCFD, CFD_NUM_OFFSET, 0);
  1376.     /* this is a transmit command */
  1377.     CFD_BYTE_WR (pCFD, CFD_ACTION_OFFSET, CFD_TX);
  1378.     /* tie to the previous CFD */
  1379.     CFD_LONG_RD (pCFD, CFD_PREV_OFFSET, pPrevCFD);
  1380.     CFD_WORD_RD (pPrevCFD, CFD_COMM_OFFSET, command);
  1381.     CFD_WORD_WR (pPrevCFD, CFD_COMM_OFFSET, (command & (~CFD_C_SUSP)));
  1382.     /* Flush the write pipe */
  1383.     CACHE_PIPE_FLUSH ();
  1384.     /* advance the current free CFD pointer */
  1385.     fei82557FDUpdate (pDrvCtrl, CFD_FREE);
  1386. #ifdef INCLUDE_RFC_1213
  1387.     /* Old RFC 1213 mib2 interface */
  1388.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1389.  
  1390. #endif /* INCLUDE_RFC_1213 */ 
  1391.     /* kick the CU if needed */
  1392.     if (fei82557SCBCommand (pDrvCtrl, SCB_C_CURESUME, FALSE,(UINT32) 0) 
  1393.         == ERROR)
  1394.         {
  1395.         DRV_LOG (DRV_DEBUG_TX, ("Could not send packetn"), 
  1396.           1, 2, 3, 4, 5, 6);
  1397.         END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1398.         return (ERROR);
  1399.         }
  1400.     /* interlock with fei82557CFDFree */
  1401.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1402.     DRV_LOG (DRV_DEBUG_TX, ("fei82557Send...Donen"), 1, 2, 3, 4, 5, 6);
  1403.     return (OK);
  1404.     }
  1405. /*******************************************************************************
  1406. *
  1407. * fei82557Int - entry point for handling interrupts from the 82557
  1408. *
  1409. * The interrupting events are acknowledged to the device, so that the device
  1410. * will de-assert its interrupt signal.  The amount of work done here is kept
  1411. * to a minimum; the bulk of the work is deferred to the netTask.
  1412. *
  1413. * RETURNS: N/A
  1414. */
  1415. LOCAL void fei82557Int
  1416.     (
  1417.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1418.     )
  1419.     {
  1420.     UINT16  event;
  1421.     /* read and save CSR status word */
  1422.     CACHE_PIPE_FLUSH(); 
  1423.     CSR_WORD_RD (CSR_STAT_OFFSET, event);
  1424.     if ((event & SCB_S_STATMASK) == 0)
  1425. {
  1426. /* This device was not the cause of the shared int */
  1427. return;  
  1428. }
  1429.     /* clear chip level interrupt pending, use byte access */
  1430.     CSR_BYTE_WR (CSR_ACK_OFFSET, ((event & SCB_S_STATMASK) >> 8));
  1431.     /* board level interrupt acknowledge */
  1432.     SYS_INT_ACK (pDrvCtrl);
  1433.     /* handle transmit interrupts */
  1434.     if ((event & SCB_S_CNA) && (pDrvCtrl->txHandle == FALSE))
  1435. {
  1436. pDrvCtrl->txHandle = TRUE;
  1437. netJobAdd ((FUNCPTR) fei82557CFDFree, (int) pDrvCtrl, 0, 0, 0, 0);
  1438. }
  1439.     /* handle receive interrupts only if fei82557Receive is not running */
  1440.     if (event & (SCB_S_FR | SCB_S_RNR))
  1441. {
  1442.         /* Disable receive interrupts in the device for now */
  1443.         if (pDrvCtrl->deviceId == 0 || pDrvCtrl->deviceId == FEI82557_DEVICE_ID)
  1444.             {
  1445.             /* This is an 82557 mask all interrupts */
  1446.             I82557_INT_DISABLE(SCB_C_M);
  1447.             }
  1448.         else
  1449.             {
  1450.             /* This is not an 82557 mask only read and no resource interrupts */
  1451.             I82557_INT_DISABLE(SCB_C_FR | SCB_C_RNR);
  1452.             }
  1453. netJobAdd ((FUNCPTR) fei82557HandleRecvInt, (int) pDrvCtrl,
  1454.     0, 0, 0, 0);
  1455. }
  1456.     }
  1457. /******************************************************************************
  1458. *
  1459. * fei82557HandleRecvInt - service task-level interrupts for receive frames
  1460. *
  1461. * This routine is run in netTask's context.  The ISR scheduled
  1462. * this routine so that it could handle receive packets at task level.
  1463. *
  1464. * RETURNS: N/A
  1465. */
  1466. LOCAL void fei82557HandleRecvInt
  1467.     (
  1468.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1469.     )
  1470.     {
  1471.     volatile RFD_ID pRFD;
  1472.     UINT16   status = 0;
  1473.     UINT16 scbStatus;
  1474.     UINT16 scbCommand;
  1475.     int ix;
  1476.     DRV_LOG (DRV_DEBUG_RX, "fei82557HandleRecvIntn", 0, 0, 0, 0, 0, 0);
  1477.     /* while RFDs to be processed */
  1478.     FOREVER
  1479. {
  1480. /* check for RFDs availability */
  1481. /* get the first used RFD */
  1482. RFD_GET (pRFD);
  1483. /* Make cache consistent with memory */
  1484. FEI_CACHE_INVALIDATE (pRFD, RFD_SIZE);
  1485.     
  1486. /* read the RFD status word */
  1487. RFD_WORD_RD (pRFD, RFD_STAT_OFFSET, status);
  1488. DRV_LOG (DRV_DEBUG_RX, "Checking RFD @ %#x status = %#xn",
  1489. (int) pRFD, (int) status ,0,0,0,0);
  1490. if (!(FD_FLAG_ISSET (status, RFD_S_COMPLETE)))
  1491.     {
  1492.     /* No more RFDs, so break out of the inner loop */
  1493.     break;
  1494.     }
  1495. fei82557Receive (pDrvCtrl, pRFD);
  1496. }
  1497.     /* Flush the write pipe */
  1498.     CACHE_PIPE_FLUSH ();
  1499.     /* kick receiver (if needed) */
  1500.     CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus);
  1501.     if ((scbStatus & SCB_S_RUMASK) != SCB_S_RURDY)
  1502.         {
  1503.         DRV_LOG (DRV_DEBUG_RX, ("HandleRecvInt: ********* RU NOT READYn"),
  1504.                                 0, 0, 0, 0, 0, 0);
  1505. /* get the first used RFD */
  1506. RFD_GET (pRFD);
  1507.         if (fei82557SCBCommand (pDrvCtrl, SCB_C_RUSTART, TRUE, pRFD)
  1508.             == ERROR)
  1509.             {
  1510.             DRV_LOG (DRV_DEBUG_RX,
  1511.      "fei82557HandleRecvInt: command %d failedn",
  1512.      SCB_C_RUSTART, 0, 0, 0, 0, 0);
  1513.     }
  1514.         else
  1515.     {
  1516.     /* read CSR command word */
  1517.     CSR_WORD_RD (CSR_COMM_OFFSET, scbCommand);
  1518.     DRV_LOG (DRV_DEBUG_RX,
  1519.      "fei82557HandleRecvInt: CSR command word 0x%xn",
  1520.              (int) scbCommand, 0, 0, 0, 0, 0);
  1521.             /* wait for RUSTART accept */
  1522.     for (ix = (FEI_INIT_TMO * fei82557ClkRate); --ix;)
  1523. {
  1524. /* read CSR command word */
  1525. CSR_WORD_RD (CSR_COMM_OFFSET, scbCommand);
  1526. if (!(scbCommand & SCB_C_RUMASK))
  1527.     {
  1528.     DRV_LOG (DRV_DEBUG_RX,
  1529.      "fei82557HandleRecvInt: RUSTART acceptedn",
  1530.      0, 0, 0, 0, 0, 0);
  1531.     break;
  1532.     }
  1533. taskDelay (max (1, sysClkRateGet()/60));
  1534. }
  1535.     if (!ix)
  1536. {
  1537. DRV_LOG (DRV_DEBUG_RX,
  1538.  "fei82557HandleRecvInt: RUSTART FAILED #######n",
  1539.  0, 0, 0, 0, 0, 0);
  1540. }
  1541.     }
  1542.         }
  1543.     if (pDrvCtrl->deviceId == 0 || pDrvCtrl->deviceId == FEI82557_DEVICE_ID)
  1544.         {
  1545.         /* This is an 82557 mask all interrupts */
  1546.         I82557_INT_ENABLE(SCB_C_M);
  1547.         }
  1548.     else
  1549.         {
  1550.         /* This is not an 82557 mask only read and no resource interrupts */
  1551.         I82557_INT_ENABLE ((SCB_C_FR | SCB_C_RNR));
  1552.         }
  1553.     DRV_LOG (DRV_DEBUG_RX, ("fei82557HandleRecvInt... Done, n"),
  1554.                              0, 0, 0, 0, 0, 0);
  1555.     }
  1556. /******************************************************************************
  1557. *
  1558. * fei82557Receive - pass a received frame to the next layer up
  1559. *
  1560. * RETURNS: N/A
  1561. */
  1562. LOCAL void fei82557Receive
  1563.     (
  1564.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1565.     RFD_ID      pRFD         /* pointer to a RFD */
  1566.     )
  1567.     {
  1568.     volatile RFD_ID     pNewRFD         = NULL;
  1569.     M_BLK_ID            pMblk           = NULL;
  1570.     CL_BLK_ID           pClBlk          = NULL;
  1571.     volatile UINT16     status;
  1572.     volatile UINT16     count;
  1573.     char * pData;
  1574.     static UINT         noClusters = 0;
  1575.     RFD_WORD_RD (pRFD, RFD_STAT_OFFSET, status);
  1576.     if (!(FD_FLAG_ISSET (status, RFD_S_OK)))
  1577. {
  1578.         DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: NOT OKn", 0,0,0,0,0,0);
  1579.         goto fei82557RecvError;
  1580.         }
  1581.     if ((pMblk = netMblkGet (pDrvCtrl->endObj.pNetPool,
  1582.                             M_DONTWAIT, MT_DATA)) == NULL)
  1583. {
  1584. DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netMblkGet failedn",
  1585.  0,0,0,0,0,0);
  1586.         goto fei82557RecvError;
  1587. }
  1588.     if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool,
  1589.                                M_DONTWAIT)) == NULL)
  1590. {
  1591. DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netClBlkGet failedn",
  1592.  0,0,0,0,0,0);
  1593.         goto fei82557RecvError;
  1594. }
  1595.     if ((pNewRFD = (RFD_ID) netClusterGet (pDrvCtrl->endObj.pNetPool,
  1596.                                           pDrvCtrl->pClPoolId)) == NULL)
  1597. {
  1598. DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netClusterGet failedn",
  1599.  0,0,0,0,0,0);
  1600.         /* Tell the mux to give back some clusters */
  1601.        
  1602.         pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1603.         muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError);
  1604. logMsg ("fei82557Receive: netClusterGet failedn",noClusters,0,0,0,0,0);
  1605.         goto fei82557RecvError;
  1606. }
  1607.     /* is the RFD to be given back?? */
  1608.     if (netClBlkJoin (pClBlk, (char *) pRFD, RFD_SIZE,
  1609.                       NULL, 0, 0, 0) == NULL)
  1610. {
  1611. DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netClBlkJoin failedn",
  1612.  0,0,0,0,0,0);
  1613.         goto fei82557RecvError;
  1614. }
  1615.     if (netMblkClJoin (pMblk, pClBlk) == NULL)
  1616. {
  1617. DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netMblkClJoin failedn",
  1618.  0,0,0,0,0,0);
  1619.         goto fei82557RecvError;
  1620. }
  1621. #ifdef INCLUDE_RFC_1213
  1622.  
  1623.     /* Old RFC 1213 mib2 interface */
  1624.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  1625. #endif /* INCLUDE_RFC_1213 */ 
  1626.     /* get the actual received bytes number */
  1627.     DRV_LOG (DRV_DEBUG_RX, "pRFD = %pn", pRFD, 0,0,0,0,0);
  1628.     RFD_WORD_RD (pRFD, RFD_COUNT_OFFSET, count);
  1629.     pData = (char *) (RFD_PKT_ADDR (pRFD));
  1630.     if (pDrvCtrl->offset > 0)
  1631. {
  1632. bcopy (pData, pData+pDrvCtrl->offset, count & ~0xc000);
  1633. pData += pDrvCtrl->offset;
  1634. }
  1635.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1636.     pMblk->mBlkHdr.mData = pData;
  1637.     pMblk->mBlkHdr.mLen = count & ~0xc000;    
  1638.     pMblk->mBlkPktHdr.len = pMblk->mBlkHdr.mLen;
  1639. #ifndef INCLUDE_RFC_1213
  1640.     /* New RFC 2233 mib2 interface */
  1641.     /* RFC 2233 mib2 counter update for incoming packet */
  1642.     if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  1643.         {
  1644.         pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,
  1645.                                                  M2_PACKET_IN,
  1646.                                                  pMblk->mBlkHdr.mData,
  1647.                                                  pMblk->mBlkHdr.mLen);
  1648.         }
  1649. #endif /* INCLUDE_RFC_1213 */
  1650.     /* put the new RFD on the RFD queue */
  1651.     fei82557RFDReturn(pDrvCtrl, pNewRFD);
  1652.     DRV_LOG (DRV_DEBUG_RX, "length %dn", pMblk->mBlkHdr.mLen, 0,0,0,0,0);
  1653.     if (memcmp (pData, &pDrvCtrl->board.enetAddr, 6) == 0)
  1654. {
  1655. DRV_LOG (DRV_DEBUG_RX, ("fei82557Receive... Done - data @ %pn"),
  1656.  pData, 0, 0, 0, 0, 0);
  1657. DRV_LOG (DRV_DEBUG_RX, ("Sender IP %#x Receiver IP %#xn"),
  1658.  *((int *)(pData+26)),
  1659.  *((int *)(pData+30)), 0, 0, 0, 0);
  1660. }
  1661.     END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);
  1662.     return;
  1663. fei82557RecvError:
  1664.     if (pMblk != NULL)
  1665.         netMblkFree (pDrvCtrl->endObj.pNetPool, pMblk);
  1666.     if (pClBlk != NULL)
  1667.         netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk);
  1668.     if (pNewRFD != NULL)
  1669. netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *) pNewRFD);
  1670. #ifdef INCLUDE_RFC_1213
  1671.     /* Old RFC 1213 mib2 interface */
  1672.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1673. #else
  1674.     /* New RFC 2233 mib2 interface */
  1675.     if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  1676.             {
  1677.             pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
  1678.                                                                 pMib2Tbl,
  1679.                                                       M2_ctrId_ifInErrors,
  1680.                                                       1);
  1681.             }
  1682. #endif /* INCLUDE_RFC_1213 */
  1683.       
  1684.     /* put the errored RFD on the RFD queue */
  1685.     fei82557RFDReturn(pDrvCtrl, pRFD);
  1686.     }
  1687. /**************************************************************************
  1688. *
  1689. * fei82557RFDReturn - put a Receive Frame on the Receive Queue
  1690. *
  1691. * This routine puts a Receive Frame on the Receive Queue.
  1692. *
  1693. * RETURNS: N/A
  1694. *
  1695. */
  1696. LOCAL void fei82557RFDReturn
  1697.     (
  1698.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1699.     RFD_ID pNewRFD /* pointer to a RFD */
  1700.     )
  1701.     {
  1702.     volatile UINT32   tempVar;
  1703.     volatile RFD_ID   pRFD;  
  1704.     volatile UINT16   command;
  1705.     /* get the last used RFD */
  1706.     RFD_GET (pRFD);
  1707.     /* link it to the RFD chain */
  1708.     /* link the new RFD to the next one */
  1709.     RFD_LONG_RD (pRFD, RFD_SW_NEXT_OFFSET, tempVar); 
  1710.     RFD_LONG_WR (tempVar, RFD_PREV_OFFSET, (UINT32) pNewRFD);
  1711.     RFD_NEXT_WR (pNewRFD, tempVar);
  1712.     RFD_LONG_WR (pNewRFD, RFD_SW_NEXT_OFFSET, tempVar);
  1713.     /* link the new RFD to the previous one */
  1714.     RFD_LONG_RD (pRFD, RFD_PREV_OFFSET, tempVar);
  1715.     RFD_NEXT_WR (tempVar, pNewRFD);
  1716.     RFD_LONG_WR (tempVar, RFD_SW_NEXT_OFFSET, (UINT32) pNewRFD);
  1717.     RFD_LONG_WR (pNewRFD, RFD_PREV_OFFSET, tempVar);
  1718.     /* init the new RFD, mirrors fei82557Start */
  1719.     /* set state and command for this RFD */
  1720.     RFD_WORD_WR (pNewRFD, RFD_STAT_OFFSET, (UINT32) 0);
  1721.     RFD_WORD_WR (pNewRFD, RFD_COMM_OFFSET, (UINT32) RFD_C_EL);
  1722.     /* no RBDs used */
  1723.     RFD_RBD_WR (pNewRFD, (UINT32) RBD_NOT_USED);
  1724.     /* set the actual count field to zero */
  1725.     RFD_WORD_WR (pNewRFD, RFD_COUNT_OFFSET, 0);
  1726.     /* set the size field for Ethernet packets */
  1727.     RFD_WORD_WR (pNewRFD, RFD_SIZE_OFFSET, 
  1728.  (UINT32) (ETHERMTU + EH_SIZE));
  1729.     /* chain the previous RFD */
  1730.     RFD_LONG_RD (pNewRFD, RFD_PREV_OFFSET, tempVar);
  1731.     RFD_WORD_RD (tempVar, RFD_COMM_OFFSET, command);
  1732.     RFD_WORD_WR (tempVar, RFD_COMM_OFFSET, (command & (~RFD_C_EL)));
  1733.     /* bump to the next free RFD */
  1734.     fei82557FDUpdate (pDrvCtrl, RFD_FREE);
  1735.     }
  1736. /**************************************************************************
  1737. *
  1738. * fei82557CFDFree - free all used command frames
  1739. *
  1740. * This routine frees all used command frames and notifies upper protocols
  1741. * that new resources are available.
  1742. *
  1743. * RETURNS: N/A
  1744. *
  1745. */
  1746. LOCAL void     fei82557CFDFree
  1747.     (
  1748.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1749.     )
  1750.     {
  1751.     volatile CFD_ID     pUsedCFD = NULL;
  1752.     volatile UINT16 status;
  1753.     volatile UINT16 scbStatus;
  1754.     UINT8 action;
  1755.     if (!(FEI_FLAG_ISSET (FEI_POLLING)))
  1756. {
  1757. /* interlock with fei82557Send */
  1758. END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  1759. /* read CSR status word */
  1760. CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus);
  1761. /* if CU is active, do not go on */
  1762. if ((scbStatus & SCB_S_CUMASK) != SCB_S_CUSUSP)
  1763.     {
  1764.     pDrvCtrl->txHandle = FALSE;
  1765.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1766.     return;
  1767.     }
  1768. }
  1769.     /* process all the used CFDs until we find either:
  1770.      * a. a non-complete frame;
  1771.      * b. a frame with the SUSPEND bit set
  1772.      */
  1773.     FOREVER
  1774.         {
  1775.         USED_CFD_GET (pUsedCFD);
  1776.  
  1777.         /* Make cache consistent with memory */
  1778.         FEI_CACHE_INVALIDATE (pUsedCFD, 4);
  1779.  
  1780.         /* read the CFD status word */
  1781.         CFD_WORD_RD (pUsedCFD, CFD_STAT_OFFSET, status);
  1782.  
  1783.         /* if it's not ready, don't touch it! */
  1784.         if (!(FD_FLAG_ISSET (status, (CFD_S_COMPLETE | CFD_S_OK))))
  1785.             {
  1786.             break;
  1787.             }
  1788. /* put CFD back to a TxCB - mirrors fei82557InitMem() */
  1789. /* no TBDs used */
  1790. CFD_TBD_WR (pUsedCFD, (UINT32) TBD_NOT_USED);
  1791. CFD_BYTE_WR (pUsedCFD, CFD_NUM_OFFSET, 0);
  1792. /* set the thresh value */
  1793. CFD_BYTE_WR (pUsedCFD, CFD_THRESH_OFFSET, 
  1794.      pDrvCtrl->board.tcbTxThresh);
  1795.         /* correct statistic only in case of non-action command */
  1796. CFD_BYTE_RD (pUsedCFD, CFD_ACTION_OFFSET, action);
  1797.         if ((action == CFD_TX) &&
  1798.             !(FD_FLAG_ISSET (status, (CFD_S_COMPLETE | CFD_S_OK))))
  1799.             {
  1800.     if (!(FEI_FLAG_ISSET (FEI_POLLING)))
  1801. {
  1802. DRV_LOG (DRV_DEBUG_INT, ("fei82557CFDFree: Errored Frame n"), 
  1803.  0, 0, 0, 0, 0, 0);
  1804. }
  1805. #ifdef INCLUDE_RFC_1213
  1806.             /* Old RFC 1213 mib2 interface */
  1807.             END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1808.             END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
  1809.             
  1810. #else
  1811.             /* New RFC 2233 mib2 interface */
  1812.             if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  1813.                 {
  1814.                 pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
  1815.                                                                     pMib2Tbl,
  1816.                                                           M2_ctrId_ifOutErrors,
  1817.                                                           1);
  1818.                 }
  1819. #endif /* INCLUDE_RFC_1213 */
  1820.             /* make the errored CFD available */
  1821.     CFD_WORD_WR (pUsedCFD, CFD_STAT_OFFSET, 
  1822.  (CFD_S_OK | CFD_S_COMPLETE));
  1823.             }
  1824. if (!(FEI_FLAG_ISSET (FEI_POLLING)))
  1825.     {
  1826.     /* soon notify upper protocols CFDs are available */
  1827.     if (pDrvCtrl->txStall)
  1828.         {
  1829.         DRV_LOG (DRV_DEBUG_INT, ("fei82557CFDFree: Restart mux n"), 
  1830.                              0, 0, 0, 0, 0, 0);
  1831.         netJobAdd ((FUNCPTR) muxTxRestart, (int) &pDrvCtrl->endObj,
  1832.           0, 0, 0, 0);
  1833.         pDrvCtrl->txStall = FALSE;
  1834.         }
  1835.     }
  1836.         /* we have finished our work if this is a suspend CFD */
  1837.         CFD_WORD_RD (pUsedCFD, CFD_COMM_OFFSET, status);
  1838.         /* advance pointer to the used CFDs (even if we are exiting) */
  1839. fei82557FDUpdate (pDrvCtrl, CFD_USED);
  1840.         if (FD_FLAG_ISSET (status, CFD_C_SUSP))
  1841.             {
  1842.             break;
  1843.             }
  1844.         }
  1845.     if (!(FEI_FLAG_ISSET (FEI_POLLING)))
  1846. {
  1847.         pDrvCtrl->txHandle = FALSE;
  1848. END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1849. DRV_LOG (DRV_DEBUG_INT, ("fei82557CFDFree: Done n"),
  1850.  0, 0, 0, 0, 0, 0);
  1851. }
  1852.     /* Flush the write pipe */
  1853.     CACHE_PIPE_FLUSH ();
  1854.     }
  1855. /**************************************************************************
  1856. *
  1857. * fei82557FDUpdate - update the current frame descriptor
  1858. *
  1859. * This routine updates the pointer to the appropriate frame descriptor 
  1860. * ring with the value stored in the link field of the current frame 
  1861. * descriptor. Frame descriptor here can be either an RFD or a CFD in the
  1862. * free CFDs ring as well as in the used CFDs ring.
  1863. *
  1864. * RETURNS: N/A
  1865. *
  1866. */
  1867. LOCAL void     fei82557FDUpdate
  1868.     (
  1869.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1870.     UINT8 fdList /* FD list selector */
  1871.     )
  1872.     {
  1873.     volatile UINT32 fdAddr;
  1874.     volatile FD_ID pFD;
  1875.     switch (fdList)
  1876.         {
  1877.         case CFD_FREE:
  1878.             /* CFDs ready to be processed */
  1879.     FREE_CFD_GET (pFD);
  1880.             /* get the next free CFD address */
  1881.     CFD_NEXT_RD (pFD, fdAddr);
  1882.             /* bump to the next free CFD */
  1883.             pDrvCtrl->pFreeCFD = (FD_ID) fdAddr;
  1884.             break;
  1885.         case CFD_USED:
  1886.             /* CFDs already processed */
  1887.     USED_CFD_GET (pFD);
  1888.             /* get the next free CFD address */
  1889.     CFD_NEXT_RD (pFD, fdAddr);
  1890.             /* bump to the next used CFD */
  1891.             pDrvCtrl->pUsedCFD = (FD_ID) fdAddr;
  1892.             break;
  1893.         case RFD_FREE:
  1894.             /* RFDs ready to be processed */
  1895.     RFD_GET (pFD);
  1896.             /* get the next free RFD address */
  1897.     RFD_NEXT_RD (pFD, fdAddr);
  1898.             /* bump to the next free RFD */
  1899.             pDrvCtrl->pRFD = (FD_ID) fdAddr;
  1900.             break;
  1901.         default:
  1902.             break;
  1903.         }
  1904.     }
  1905. /**************************************************************************
  1906. *
  1907. * fei82557Stop - stop the fei82557 interface
  1908. *
  1909. * This routine marks the interface as inactive, disables interrupts and 
  1910. * resets the chip. It brings down the interface to a non-operational state. 
  1911. * To bring the interface back up, fei82557Start() must be called.
  1912. *
  1913. * RETURNS: OK, always.
  1914. */
  1915. LOCAL STATUS fei82557Stop
  1916.     (
  1917.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1918.     )
  1919.     {
  1920.     int retVal;
  1921.     /* disable system interrupt */
  1922.     SYS_INT_DISABLE (pDrvCtrl);     
  1923.     /* disable chip interrupt   */
  1924.     I82557_INT_DISABLE(SCB_C_M);
  1925.     /* mark the interface as down */
  1926.     END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  1927.     /* reset the chip */
  1928.     fei82557Reset (pDrvCtrl);
  1929.     /* disconnect the interrupt handler */
  1930.     SYS_INT_DISCONNECT (pDrvCtrl, fei82557Int, (int)pDrvCtrl, &retVal);
  1931.     if (retVal == ERROR)
  1932. return (ERROR);
  1933.     /* wait for the reset... */
  1934.     taskDelay (max (2, sysClkRateGet()/30));   
  1935.     return OK;
  1936.     } 
  1937. /**************************************************************************
  1938. *
  1939. * fei82557Reset - reset the `fei82557' interface
  1940. *
  1941. * This routine resets the chip by issuing a Port Selective Reset Command
  1942. * to the chip. The Receiver And the Transmit Unit are in idle state after
  1943. * this command is performed.
  1944. *
  1945. * RETURNS: OK or ERROR, if the command was not successful.
  1946. */
  1947. LOCAL STATUS fei82557Reset
  1948.     (
  1949.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1950.     )
  1951.     {
  1952.     int ix;
  1953.     /* issue a selective reset to the 82557 chip */
  1954.     CSR_LONG_WR (CSR_PORT_OFFSET, FEI_PORT_SELRESET);
  1955.     /* wait for the receive handler to catch up to the [reset] 557 */
  1956.     for (ix = (FEI_INIT_TMO * fei82557ClkRate); --ix;)
  1957. {
  1958. if (!pDrvCtrl->rxHandle)
  1959.     break;
  1960. taskDelay (max(1, sysClkRateGet()/60));
  1961. }
  1962.     if (!ix)
  1963. return (ERROR);
  1964.     return (OK);
  1965.     }
  1966. /**************************************************************************
  1967. *
  1968. * fei82557SCBCommand - deliver a command to the 82557 via the SCB
  1969. *
  1970. * This function causes the device to execute a command. An error status is
  1971. * returned if the command field does not return to zero, from a previous
  1972. * command, in a reasonable amount of time.
  1973. *
  1974. * RETURNS: OK, or ERROR if the command field appears to be frozen.
  1975. */
  1976. LOCAL STATUS fei82557SCBCommand
  1977.     (
  1978.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1979.     UINT8    cmd, /* command identifier */
  1980.     BOOL     addrValid, /* optionally fill the GP */
  1981.     UINT32 * pAddr /* Frame Descriptor address */
  1982.     )
  1983.     {
  1984.     volatile UINT16     scbCommand;
  1985.     int     ix;
  1986.     CACHE_PIPE_FLUSH();
  1987.     for (ix = 0x8000; --ix;)
  1988. {
  1989. /* read CSR command word */
  1990. CSR_WORD_RD (CSR_COMM_OFFSET, scbCommand);
  1991. if ((scbCommand & SCB_CR_MASK) == 0)
  1992.     {
  1993.     break;
  1994.     }
  1995. }
  1996.     if (!ix)
  1997. {
  1998. DRV_LOG (DRV_DEBUG_START,
  1999.  ("fei82557SCBCommand: command 0x%x failed, scb 0x%xn"),
  2000.  cmd, scbCommand, 0, 0, 0, 0);
  2001. return (ERROR);
  2002. }
  2003.     /* 
  2004.      * writing the GP and SCB Command should be protected from preemption 
  2005.      * we attain this by disabling task context switch before we write 
  2006.      * to the general pointer and re-enabling it after we write the
  2007.      * command word. We also flush the write pipe in-between. 
  2008.      */
  2009.     /* optionally fill the GP */
  2010.     if (addrValid)
  2011. {
  2012. if (taskLock() == ERROR)
  2013.     {
  2014.     DRV_LOG (DRV_DEBUG_ALL, "fei82557SCBCommand: task lock failedn",
  2015.      0, 0, 0, 0, 0, 0);
  2016.     return (ERROR);
  2017.     }
  2018. /* Do not do CPU to PCI translation for the base address registers. */
  2019. if ((cmd == SCB_C_CULDBASE) || (cmd == SCB_C_RULDBASE))
  2020.     {
  2021.     CSR_LONG_WR (CSR_GP_OFFSET, (UINT32) (pAddr));
  2022.     }
  2023. else
  2024.     {
  2025.     CSR_GP_WR ((UINT32) pAddr);
  2026.     }
  2027. }
  2028.     /* read CSR command byte */
  2029.     CSR_WORD_RD (CSR_COMM_OFFSET, scbCommand);
  2030.     /* write CSR command byte */
  2031.     CSR_BYTE_WR (CSR_COMM_OFFSET, (UINT8) (scbCommand | cmd));
  2032.     /* Flush the write pipe */
  2033.     CACHE_PIPE_FLUSH ();
  2034.     if (addrValid)
  2035. {
  2036. if (taskUnlock() == ERROR)
  2037.     DRV_LOG (DRV_DEBUG_ALL, ("fei82557SCBCommand: task unlock failedn"),
  2038.     0, 0, 0, 0, 0, 0);
  2039. }
  2040.     return (OK);
  2041.     } 
  2042. /*******************************************************************************
  2043. * fei82557Action - execute the specified action command
  2044. *
  2045. * This routine executes the specified action
  2046. *
  2047. * We do the command contained in the CFD synchronously, so that we know
  2048. * it's complete upon return.
  2049. *
  2050. * RETURNS: The status return of the action command, or 0 on failure.
  2051. */
  2052. LOCAL UINT16 fei82557Action
  2053.     (
  2054.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2055.     UINT16 action /* action command identifier */
  2056.     )
  2057.     {
  2058.     volatile CFD_ID  pCFD;
  2059.     volatile CFD_ID  pPrevCFD;
  2060.     int ix;
  2061.     volatile UINT16 command = 0;
  2062.     volatile UINT16 status;
  2063.     volatile UINT16     scbStatus;
  2064.     /* interlock with fei82557Send */
  2065.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  2066.     /* check for CFDs availability */
  2067.  
  2068.     FREE_CFD_GET (pCFD);
  2069.  
  2070.     /* Make cache consistent with memory */
  2071.     FEI_CACHE_INVALIDATE (pCFD, 4);
  2072.  
  2073.     /* read the CFD status word */
  2074.     CFD_WORD_RD (pCFD, CFD_STAT_OFFSET, status);
  2075.  
  2076.     if (!(FD_FLAG_ISSET (status, (CFD_S_COMPLETE | CFD_S_OK))))
  2077.         {
  2078. /* interlock with fei82557CFDFree */
  2079. END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  2080.         return (0);
  2081.         }
  2082.     /* set up the current CFD */
  2083.     CFD_WORD_WR (pCFD, CFD_COMM_OFFSET, (action | CFD_C_SUSP));
  2084.     CFD_WORD_WR (pCFD, CFD_STAT_OFFSET, 0);
  2085.     CFD_BYTE_WR (pCFD, CFD_ACTION_OFFSET, CFD_ACTION);
  2086.     /* for some actions we need to do additional work */
  2087.     switch (action)
  2088. {
  2089. case CFD_C_MASETUP:
  2090.     /* form the multicast address list */
  2091.     fei82557MCastListForm (pDrvCtrl, pCFD);
  2092.     break;
  2093. case CFD_C_CONFIG:
  2094.     /* fill the CFD with config bytes */
  2095.     fei82557ConfigForm (pDrvCtrl, pCFD);
  2096.     break;
  2097. case CFD_C_IASETUP:
  2098.     /* fill the CFD with our Ethernet address */
  2099.     bcopy ((char *) FEI_HADDR (&pDrvCtrl->endObj),
  2100.    (char *) CFD_IA_ADDR (pCFD),
  2101.    FEI_HADDR_LEN (&pDrvCtrl->endObj));
  2102.     break;
  2103. default:
  2104.     break;
  2105. }
  2106.     /* tie to the previous CFD */
  2107.     CFD_LONG_RD (pCFD, CFD_PREV_OFFSET, pPrevCFD);
  2108.     CFD_WORD_RD (pPrevCFD, CFD_COMM_OFFSET, command);
  2109.     CFD_WORD_WR (pPrevCFD, CFD_COMM_OFFSET, (command & (~CFD_C_SUSP)));
  2110.     /* Flush the write pipe */
  2111.     CACHE_PIPE_FLUSH ();
  2112.     /* advance the current free CFD pointer */
  2113.     fei82557FDUpdate (pDrvCtrl, CFD_FREE);
  2114. #ifdef INCLUDE_RFC_1213
  2115.     /* Old RFC 1213 mib2 interface */
  2116.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  2117. #endif /* INCLUDE_RFC_1213 */
  2118.     /* check CU operation -- kick if needed */
  2119.     CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus);
  2120.     if ((scbStatus & SCB_S_CUMASK) != SCB_S_CUACTIVE)
  2121.         {
  2122.         if (scbStatus == SCB_S_CUIDLE)
  2123.             {
  2124.             if (fei82557SCBCommand (pDrvCtrl, SCB_C_CUSTART, TRUE, pCFD)
  2125. == ERROR)
  2126.                 {
  2127. DRV_LOG (DRV_DEBUG_START,
  2128.  ("fei82557SCBCommand: command failedn"),
  2129.  0, 0, 0, 0, 0, 0);
  2130.                 }
  2131.             }
  2132.         else
  2133.             {
  2134.             if (fei82557SCBCommand (pDrvCtrl, SCB_C_CURESUME, FALSE, 0x0) 
  2135. == ERROR)
  2136.                 {
  2137. DRV_LOG (DRV_DEBUG_START,
  2138.  ("fei82557SCBCommand: command failedn"),
  2139.  0, 0, 0, 0, 0, 0);
  2140.                 }
  2141.             }
  2142.         }
  2143.     /* wait for command to complete */
  2144.     for (ix = (FEI_ACTION_TMO * fei82557ClkRate); --ix;)
  2145. {
  2146. CFD_WORD_RD (pCFD, CFD_STAT_OFFSET, status);
  2147. if (status & CFD_S_COMPLETE)
  2148.     break;
  2149. taskDelay (max(1, sysClkRateGet()/60));
  2150. }
  2151.     if (!ix)
  2152. {
  2153. CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus);
  2154. DRV_LOG (DRV_DEBUG_START,
  2155.  "fei82557Action: Command %#x Status %#x CSR Status %#xn",
  2156.     action, status, scbStatus, 0, 0, 0);
  2157. }
  2158.     /* interlock with fei82557CFDFree */
  2159.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  2160.     return (status);
  2161.     }
  2162. /**************************************************************************
  2163. *
  2164. * fei82557MCastListForm - set up the multicast address list
  2165. *
  2166. * This routine populates the given CFD with the address list found in
  2167. * the apposite structure provided by the upper layers.
  2168. *
  2169. * RETURNS: N/A
  2170. */
  2171. LOCAL void fei82557MCastListForm
  2172.     (
  2173.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2174.     CFD_ID pCFD /* pointer to a CFD */
  2175.     )
  2176.     {
  2177.     UINT32 mCastAddr;
  2178.     ETHER_MULTI * mCastNode;
  2179.     UINT16 count = 0;
  2180.     /* get the starting address for the multicast list */
  2181.     mCastAddr = (UINT32) CFD_MC_ADDR (pCFD);
  2182.     /* copy the multicast address list */
  2183.     for (mCastNode = (ETHER_MULTI *) lstFirst (&pDrvCtrl->endObj.multiList);
  2184.  mCastNode != NULL; 
  2185.  mCastNode = (ETHER_MULTI *) lstNext (&mCastNode->node))
  2186. {
  2187. bcopy ((char *) mCastNode->addr, (char *) mCastAddr, FEI_ADDR_LEN);
  2188. mCastAddr += FEI_ADDR_LEN;
  2189. count += FEI_ADDR_LEN;
  2190. }
  2191.     /* set the byte counter for the list */
  2192.     CFD_WORD_WR (pCFD, CFD_MCOUNT_OFFSET, (count & ~0xc000));
  2193.     }
  2194. /**************************************************************************
  2195. *
  2196. * fei82557ConfigForm - fill the config CFD with proper values
  2197. *
  2198. * RETURNS: N/A
  2199. */
  2200. LOCAL void fei82557ConfigForm
  2201.     (
  2202.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2203.     CFD_ID pCFD /* pointer to a CFD */
  2204.     )
  2205.     {
  2206.     UINT32 addr; 
  2207.     /* get to the starting address for config data */
  2208.     addr = (UINT32) pCFD + CFD_SIZE_HDR;
  2209.     /* set to config values recommeded by the i82557 User's Manual */
  2210.     CFD_CONFIG_WR (addr + 0, 0x16);
  2211.     CFD_CONFIG_WR (addr + 1, 0x88);
  2212.     CFD_CONFIG_WR (addr + 2, 0x00);
  2213.     CFD_CONFIG_WR (addr + 3, 0x00);
  2214.     CFD_CONFIG_WR (addr + 4, 0x00);
  2215.     CFD_CONFIG_WR (addr + 5, 0x00);
  2216.     /* it was 0x38, now 0x30 to generate CNA interrupts */
  2217.     CFD_CONFIG_WR (addr + 6, 0x30); /* save bad frame, no TNO 0x3a; */
  2218.     CFD_CONFIG_WR (addr + 7, 0x03);
  2219.     CFD_CONFIG_WR (addr + 8, 0x01); /* MII operation */
  2220.     CFD_CONFIG_WR (addr + 9, 0x00);
  2221.     CFD_CONFIG_WR (addr + 10, 0x2e);
  2222.     CFD_CONFIG_WR (addr + 11, 0x00);
  2223.     CFD_CONFIG_WR (addr + 12, 0x60);
  2224.     CFD_CONFIG_WR (addr + 13, 0x00);
  2225.     CFD_CONFIG_WR (addr + 14, 0xf2);
  2226.     if (FEI_FLAG_ISSET (FEI_PROMISC))
  2227. {
  2228. CFD_CONFIG_WR (addr + 15, 0x49);
  2229. DRV_LOG (DRV_DEBUG_START, ("fei82557ConfigForm: PROMISC!!!!!!! n"),
  2230.     0, 0, 0, 0, 0, 0);
  2231. }
  2232.     else
  2233. CFD_CONFIG_WR (addr + 15, 0x48);      /* 0x49 in the old driver */
  2234.     CFD_CONFIG_WR (addr + 16, 0x00);
  2235.     CFD_CONFIG_WR (addr + 17, 0x40);
  2236.     CFD_CONFIG_WR (addr + 18, 0xf2);
  2237.     if (pDrvCtrl->board.phyDpx != PHY_HALF_DPX)
  2238. CFD_CONFIG_WR (addr + 19, 0x80);
  2239.     else
  2240. CFD_CONFIG_WR (addr + 19, 0x00); /* c0 force full duplex 0x80 */
  2241.  
  2242.     CFD_CONFIG_WR (addr + 20, 0x3f);
  2243.     if (FEI_FLAG_ISSET (FEI_MCASTALL))
  2244. {
  2245. CFD_CONFIG_WR (addr + 21, 0x0d);
  2246. DRV_LOG (DRV_DEBUG_START, ("fei82557ConfigForm: MULTIALL n"),
  2247.     0, 0, 0, 0, 0, 0);
  2248. }
  2249.     else
  2250. CFD_CONFIG_WR (addr + 21, 0x05);      /* 0x05 in the old driver */
  2251.     }
  2252. /**************************************************************************
  2253. *
  2254. * fei82557Diag - format and issue a diagnostic command
  2255. *
  2256. * RETURNS: OK, or ERROR if the diagnostic command failed.
  2257. */
  2258. LOCAL STATUS fei82557Diag
  2259.     (
  2260.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  2261.     )
  2262.     {
  2263.     UINT16  stat;
  2264.     if (((stat = fei82557Action (pDrvCtrl, CFD_C_DIAG)) &
  2265. (CFD_S_OK | CFD_S_DIAG_F)) != CFD_S_OK)
  2266. {
  2267. DRV_LOG (DRV_DEBUG_START,
  2268.  "82557 diagnostics failed, cfdStatus 0x%xn",
  2269.  stat, 0, 0, 0, 0, 0);
  2270. return (ERROR);
  2271. }
  2272.      return (OK);
  2273.     } 
  2274. /**************************************************************************
  2275. *
  2276. * fei82557IASetup - issue an individual address command
  2277. *
  2278. * RETURNS: OK, or ERROR if the individual address command failed.
  2279. */
  2280. LOCAL STATUS fei82557IASetup
  2281.     (
  2282.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  2283.     )
  2284.     {
  2285.     if (!(fei82557Action (pDrvCtrl, CFD_C_IASETUP) & CFD_S_OK))
  2286. return (ERROR);
  2287.     return (OK);
  2288.     } 
  2289. /**************************************************************************
  2290. *
  2291. * fei82557Config - issue a config command
  2292. *
  2293. * RETURNS: OK, or ERROR if the config command failed.
  2294. */
  2295. LOCAL STATUS fei82557Config
  2296.     (
  2297.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  2298.     )
  2299.     {
  2300.     if (!(fei82557Action (pDrvCtrl, CFD_C_CONFIG) & CFD_S_OK))
  2301. return (ERROR);
  2302.     return (OK);
  2303.     } 
  2304. /*******************************************************************************
  2305. * fei82557Ioctl - interface ioctl procedure
  2306. *
  2307. * Process an interface ioctl request.
  2308. *
  2309. * RETURNS: OK, or ERROR if the config command failed.
  2310. */
  2311. LOCAL int fei82557Ioctl
  2312.     (
  2313.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2314.     int         cmd, /* command to process */
  2315.     caddr_t     data            /* pointer to data */
  2316.     )
  2317.     {
  2318.     int         error = OK;
  2319.     INT8        savedFlags;
  2320.     long        value;
  2321.     END_OBJ *   pEndObj=&pDrvCtrl->endObj;
  2322.     DRV_LOG (DRV_DEBUG_IOCTL,
  2323.              "Ioctl unit=0x%x cmd=%d data=0x%xn",
  2324.              pDrvCtrl->unit, cmd, (int)data, 0, 0, 0);
  2325.     switch (cmd)
  2326.         {
  2327.         case EIOCSADDR:
  2328.             if (data == NULL)
  2329.                 error = EINVAL;
  2330.             else
  2331.                 {
  2332.                 /* Copy and install the new address */
  2333. bcopy ((char *) data,
  2334.        (char *) FEI_HADDR (&pDrvCtrl->endObj),
  2335.        FEI_HADDR_LEN (&pDrvCtrl->endObj));
  2336. error = fei82557IASetup (pDrvCtrl);
  2337.                 }
  2338.             break;
  2339.         case EIOCGADDR:                      
  2340.             if (data == NULL)
  2341.                 error = EINVAL;
  2342.             else
  2343. bcopy ((char *) FEI_HADDR (&pDrvCtrl->endObj),
  2344.        (char *) data,
  2345.        FEI_HADDR_LEN (&pDrvCtrl->endObj));
  2346.             break;
  2347.         case EIOCSFLAGS:
  2348.             value = (long) data;
  2349.             if (value < 0)
  2350.                 {
  2351.                 value = -value;
  2352.                 value--;
  2353.                 END_FLAGS_CLR (pEndObj, value);
  2354.                 }
  2355.             else
  2356.                 END_FLAGS_SET (pEndObj, value);
  2357.             DRV_LOG (DRV_DEBUG_IOCTL, ("endFlags=0x%x n"),
  2358. END_FLAGS_GET(pEndObj), 
  2359. 0, 0, 0, 0, 0);
  2360.             /* handle IFF_PROMISC */
  2361.             savedFlags = FEI_FLAG_GET();
  2362.             if (END_FLAGS_ISSET (IFF_PROMISC))
  2363.                 FEI_FLAG_SET (FEI_PROMISC);
  2364.             else
  2365.                 FEI_FLAG_CLEAR (FEI_PROMISC);
  2366.  
  2367.             /* handle IFF_MULTICAST */
  2368.             if (END_FLAGS_GET(pEndObj) & (IFF_MULTICAST))
  2369.                 FEI_FLAG_SET (FEI_MCAST);
  2370.             else
  2371.                 FEI_FLAG_CLEAR (FEI_MCAST);
  2372.             /* handle IFF_ALLMULTI */
  2373.             if (END_FLAGS_GET(pEndObj) & (IFF_ALLMULTI))
  2374.                 FEI_FLAG_SET (FEI_MCASTALL);
  2375.             else
  2376.                 FEI_FLAG_CLEAR (FEI_MCASTALL);
  2377.             DRV_LOG (DRV_DEBUG_IOCTL, "EIOCSFLAGS: 0x%x: 0x%xn",
  2378.                     pEndObj->flags, savedFlags, 0, 0, 0, 0);
  2379.             if ((FEI_FLAG_GET () != savedFlags) &&
  2380.                 (END_FLAGS_GET (pEndObj) & IFF_UP))
  2381.                 {
  2382. /* config down */
  2383.                 END_FLAGS_CLR (pEndObj, IFF_UP | IFF_RUNNING); 
  2384.                 error = fei82557Config (pDrvCtrl);
  2385.                 END_FLAGS_SET (pEndObj, IFF_UP | IFF_RUNNING); /* config up */
  2386.                 }
  2387.             break;
  2388.         case EIOCGFLAGS:
  2389.             DRV_LOG (DRV_DEBUG_IOCTL, "EIOCGFLAGS: 0x%x: 0x%xn",
  2390.                     pEndObj->flags, *(long *)data, 0, 0, 0, 0);
  2391.             if (data == NULL)
  2392.                 error = EINVAL;
  2393.             else
  2394.                 *(long *)data = END_FLAGS_GET(pEndObj);
  2395.             break;
  2396.         case EIOCMULTIADD:
  2397.             error = fei82557MCastAddrAdd (pDrvCtrl, (char *) data);
  2398.             break;
  2399.         case EIOCMULTIDEL:
  2400.             error = fei82557MCastAddrDel (pDrvCtrl, (char *) data);
  2401.             break;
  2402.         case EIOCMULTIGET:
  2403.             error = fei82557MCastAddrGet (pDrvCtrl, (MULTI_TABLE *) data);
  2404.             break;
  2405.         case EIOCPOLLSTART:
  2406.             fei82557PollStart (pDrvCtrl);
  2407.             break;
  2408.         case EIOCPOLLSTOP:
  2409.     DRV_LOG (DRV_DEBUG_POLL, ("IOCTL about to call fei82557PollStopn"), 
  2410. 0, 0, 0, 0, 0, 0);
  2411.             fei82557PollStop (pDrvCtrl);
  2412.             break;
  2413.         case EIOCGMIB2:  
  2414.             if (data == NULL)
  2415.                 error=EINVAL;
  2416.             else
  2417. bcopy ((char *) &pEndObj->mib2Tbl, (char *) data,
  2418. sizeof (pEndObj->mib2Tbl));
  2419.             break;
  2420. #ifndef INCLUDE_RFC_1213
  2421.         /* New RFC 2233 mib2 interface */
  2422.         case EIOCGMIB2233:
  2423.             if ((data == NULL) || (pEndObj->pMib2Tbl == NULL))
  2424.                 error = EINVAL;
  2425.             else
  2426.                 *((M2_ID **)data) = pEndObj->pMib2Tbl;
  2427.             break;
  2428. #endif /* INCLUDE_RFC_1213 */
  2429.         default:
  2430.             DRV_LOG (DRV_DEBUG_IOCTL, ("INVALID IO COMMAND!! n"),
  2431. 0, 0, 0, 0, 0, 0);
  2432.             error = EINVAL;
  2433.         }
  2434.     return (error);
  2435.     }
  2436. /*******************************************************************************
  2437. * fei82557MCastAddrAdd - add a multicast address for the device
  2438. *
  2439. * This routine adds a multicast address to whatever the driver
  2440. * is already listening for.
  2441. *
  2442. * RETURNS: OK or ERROR.
  2443. */
  2444. LOCAL STATUS fei82557MCastAddrAdd
  2445.     (
  2446.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2447.     char *      pAddr /* address to be added */
  2448.     )
  2449.     {
  2450.     int retVal;
  2451.     DRV_LOG (DRV_DEBUG_IOCTL, ("MCastAddrAddn"), 0, 0, 0, 0, 0, 0);
  2452.     retVal = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddr);
  2453.     if (retVal == ENETRESET)
  2454. {
  2455.         pDrvCtrl->endObj.nMulti++;
  2456.  
  2457.         if (pDrvCtrl->endObj.nMulti > N_MCAST)
  2458.             {
  2459.             etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr);
  2460.             pDrvCtrl->endObj.nMulti--;
  2461.             }
  2462.         else
  2463.     if (!(fei82557Action (pDrvCtrl, CFD_C_MASETUP) & CFD_S_OK))
  2464. return (ERROR);
  2465.     else
  2466. return (OK);
  2467. }
  2468.     return ((retVal == OK) ? OK : ERROR);
  2469.     }
  2470. /*******************************************************************************
  2471. *
  2472. * fei82557MCastAddrDel - delete a multicast address for the device
  2473. *
  2474. * This routine deletes a multicast address from the current list of
  2475. * multicast addresses.
  2476. *
  2477. * RETURNS: OK or ERROR.
  2478. */
  2479. LOCAL STATUS fei82557MCastAddrDel
  2480.     (
  2481.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2482.     char *      pAddr /* address to be deleted */
  2483.     )
  2484.     {
  2485.     int retVal;
  2486.     DRV_LOG (DRV_DEBUG_IOCTL, ("fei82557MCastAddrDeln"), 0, 0, 0, 0, 0, 0);
  2487.     retVal = etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr);
  2488.     if (retVal == ENETRESET)
  2489. {
  2490. if (!(fei82557Action (pDrvCtrl, CFD_C_MASETUP) & CFD_S_OK))
  2491.     return (ERROR);
  2492. pDrvCtrl->endObj.nMulti--;
  2493. }
  2494.     return ((retVal == OK) ? OK : ERROR);
  2495.     }
  2496. /*******************************************************************************
  2497. * fei82557MCastAddrGet - get the current multicast address list
  2498. *
  2499. * This routine returns the current multicast address list in <pTable>
  2500. *
  2501. * RETURNS: OK or ERROR.
  2502. */
  2503. LOCAL STATUS fei82557MCastAddrGet
  2504.     (
  2505.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2506.     MULTI_TABLE *pTable /* table into which to copy addresses */
  2507.     )
  2508.     {
  2509.     DRV_LOG (DRV_DEBUG_IOCTL, ("fei82557MCastAddrGetn"), 0, 0, 0, 0, 0, 0);
  2510.     return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable));
  2511.     }
  2512. /*******************************************************************************
  2513. * fei82557PollSend - transmit a packet in polled mode
  2514. *
  2515. * This routine is called by a user to try and send a packet on the
  2516. * device. It sends a packet directly on the network, without having to
  2517. * go through the normal process of queuing a packet on an output queue
  2518. * and the waiting for the device to decide to transmit it.
  2519. *
  2520. * These routine should not call any kernel functions.
  2521. *
  2522. * RETURNS: OK or EAGAIN.
  2523. */
  2524. LOCAL STATUS fei82557PollSend
  2525.     (
  2526.     DRV_CTRL    *pDrvCtrl, /* pointer to DRV_CTRL structure */
  2527.     M_BLK_ID    pMblk /* pointer to the mBlk/cluster pair */
  2528.     )
  2529.     {
  2530.     volatile CFD_ID  pCFD;
  2531.     volatile CFD_ID  pPrevCFD;
  2532.     int len = 0;
  2533.     UINT16 command;
  2534.     volatile UINT16 status;
  2535.     char * pEnetHdr;
  2536.     volatile UINT16 scbStatus;
  2537.     BOOL complete = FALSE;
  2538.     /* check if the command unit is active */
  2539.     CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus);
  2540.     if ((scbStatus & SCB_S_CUMASK) != SCB_S_CUSUSP)
  2541. {
  2542. DRV_LOG (DRV_DEBUG_POLL_TX, ("fei82557PollSend: CU Activen"), 
  2543.      0, 0, 0, 0, 0, 0);
  2544. return (EAGAIN);
  2545. }
  2546.     /* check for CFDs availability */
  2547.     FREE_CFD_GET (pCFD);
  2548.  
  2549.     /* Make cache consistent with memory */
  2550.     FEI_CACHE_INVALIDATE (pCFD, 4);
  2551.  
  2552.     /* read the CFD status word */
  2553.     CFD_WORD_RD (pCFD, CFD_STAT_OFFSET, status);
  2554.  
  2555.     if (!(FD_FLAG_ISSET (status, (CFD_S_COMPLETE | CFD_S_OK))))
  2556. {
  2557. DRV_LOG (DRV_DEBUG_POLL_TX, ("fei82557PollSend: No CFDsn"), 
  2558.      0, 0, 0, 0, 0, 0);
  2559. return (EAGAIN);
  2560. }
  2561.     pEnetHdr = (char *) (CFD_PKT_ADDR (pCFD));
  2562.     len = netMblkToBufCopy (pMblk, (char *) pEnetHdr, NULL);
  2563.     len = max (ETHERSMALL, len);
  2564. #ifndef INCLUDE_RFC_1213
  2565.     /* New RFC 2233 mib2 interface */
  2566.     /* RFC 2233 mib2 counter update for outgoing packet */
  2567.     if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  2568.         {
  2569.         pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,
  2570.                                                  M2_PACKET_OUT, pEnetHdr, len);
  2571.         }
  2572. #endif /* INCLUDE_RFC_1213 */
  2573.     /* set up the current CFD */
  2574.     CFD_WORD_WR (pCFD, CFD_COUNT_OFFSET, ((len & 0x3fff) | TCB_CNT_EOF));
  2575.     CFD_WORD_WR (pCFD, CFD_COMM_OFFSET, (CFD_C_XMIT | CFD_C_SUSP));
  2576.     CFD_WORD_WR (pCFD, CFD_STAT_OFFSET, 0);
  2577.     /* set the thresh value */
  2578.     CFD_BYTE_WR (pCFD, CFD_THRESH_OFFSET, 
  2579.  pDrvCtrl->board.tcbTxThresh);
  2580.     /* no TBDs used */
  2581.     CFD_BYTE_WR (pCFD, CFD_NUM_OFFSET, 0);
  2582.     /* this is a transmit command */
  2583.     CFD_BYTE_WR (pCFD, CFD_ACTION_OFFSET, CFD_TX);
  2584.     /* tie to the previous CFD */
  2585.     CFD_LONG_RD (pCFD, CFD_PREV_OFFSET, pPrevCFD);
  2586.     CFD_WORD_RD (pPrevCFD, CFD_COMM_OFFSET, command);
  2587.     CFD_WORD_WR (pPrevCFD, CFD_COMM_OFFSET, (command & (~CFD_C_SUSP)));
  2588.     /* Flush the write pipe */
  2589.     CACHE_PIPE_FLUSH ();
  2590.     /* advance the current free CFD pointer */
  2591.     fei82557FDUpdate (pDrvCtrl, CFD_FREE);
  2592. #ifdef INCLUDE_RFC_1213
  2593.     /* Old RFC 1213 mib2 interface */
  2594.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  2595. #endif /* INCLUDE_RFC_1213 */
  2596.     /* kick the CU */
  2597.     if (fei82557SCBCommand (pDrvCtrl, SCB_C_CURESUME, FALSE,(UINT32) 0) 
  2598.     == ERROR)
  2599.     {
  2600.     DRV_LOG (DRV_DEBUG_POLL_TX, ("fei82557PollSend: Send Errorn"), 
  2601.  0, 0, 0, 0, 0, 0);
  2602.     return (EAGAIN);
  2603.     }
  2604. else
  2605.     {
  2606.     /* in the old driver ther was a second attempt 
  2607.      * at transimitting the packet, but is it sensible?
  2608.      */
  2609.     }
  2610.     /* wait for command to complete */
  2611.     while (!complete)
  2612. {
  2613. CFD_WORD_RD (pCFD, CFD_STAT_OFFSET, status);
  2614. if (status & CFD_S_COMPLETE)
  2615.     complete = TRUE;
  2616.         }
  2617.     complete = FALSE;
  2618.     /* wait for command to complete */
  2619.     while (!complete)
  2620. {
  2621. CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus);
  2622.         if ((scbStatus & SCB_S_CUMASK) == SCB_S_CUSUSP)
  2623.     complete = TRUE;
  2624.         }
  2625.     /* free this CFD */
  2626.     fei82557CFDFree (pDrvCtrl);
  2627.     DRV_LOG (DRV_DEBUG_POLL_TX, ("fei82557PollSendn"), 0, 0, 0, 0, 0, 0);
  2628.     return (OK);
  2629.     }
  2630. /*******************************************************************************
  2631. * fei82557PollReceive - receive a packet in polled mode
  2632. *
  2633. * This routine is called by a user to try and get a packet from the
  2634. * device. It returns EAGAIN if no packet is available. The caller must
  2635. * supply a M_BLK_ID with enough space to contain the received packet. If
  2636. * enough buffer is not available then EAGAIN is returned.
  2637. *
  2638. * These routine should not call any kernel functions.
  2639. *
  2640. * RETURNS: OK or EAGAIN.
  2641. */
  2642. LOCAL STATUS fei82557PollReceive
  2643.     (
  2644.     DRV_CTRL    *pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2645.     M_BLK_ID    pMblk            /* pointer to the mBlk/cluster pair */
  2646.     )
  2647.     {
  2648.     volatile UINT16 status;
  2649.     UINT16 retVal = OK;
  2650.     volatile RFD_ID    pRFD;  
  2651.     volatile UINT16     count;
  2652.     DRV_LOG (DRV_DEBUG_POLL_RX, ("fei82557PollReceiven"), 0, 0, 0, 0, 0, 0);
  2653.     if ((pMblk->mBlkHdr.mFlags & M_EXT) != M_EXT)
  2654.         return (EAGAIN);
  2655.     /* get the first free RFD */
  2656.     RFD_GET (pRFD);
  2657.     /* Make cache consistent with memory */
  2658.     FEI_CACHE_INVALIDATE (pRFD, RFD_SIZE);
  2659.     /* read the RFD status word */
  2660.     RFD_WORD_RD (pRFD, RFD_STAT_OFFSET, status);
  2661.     /* check for RFDs completion */
  2662.     if (!(FD_FLAG_ISSET (status, RFD_S_COMPLETE)))
  2663. {
  2664. return (EAGAIN);
  2665. }
  2666.     /* check for RFDs correctness */
  2667.     if (!(FD_FLAG_ISSET (status, RFD_S_OK)))
  2668. {
  2669. #ifdef INCLUDE_RFC_1213
  2670.         /* Old RFC 1213 mib2 interface */
  2671.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  2672. #else
  2673.         /* New RFC 2233 mib2 interface */
  2674.         if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  2675.                 {
  2676.                 pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
  2677.                                                                     pMib2Tbl,
  2678.                                                           M2_ctrId_ifInErrors,
  2679.                                                           1);
  2680.                 }
  2681. #endif /* INCLUDE_RFC_1213 */
  2682. retVal = EAGAIN;
  2683. goto fei82557PollReceiveEnd;    
  2684. }
  2685. #ifdef INCLUDE_RFC_1213
  2686.     /* Old RFC 1213 mib2 interface */
  2687.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  2688.    
  2689. #endif /* INCLUDE_RFC_1213 */ 
  2690.     /* get the actual received bytes number */
  2691.     RFD_WORD_RD (pRFD, RFD_COUNT_OFFSET, count);
  2692.     /*
  2693.      * Upper layer provides the buffer. If buffer is not large enough, 
  2694.      * we do not copy the received buffer.
  2695.      */
  2696.     if (pMblk->mBlkHdr.mLen < (count & ~0xc000))
  2697. {
  2698. retVal = EAGAIN;
  2699. goto fei82557PollReceiveEnd;    
  2700. }
  2701.     pMblk->mBlkHdr.mFlags   |= M_PKTHDR;
  2702.     pMblk->mBlkHdr.mLen = count & ~0xc000;    
  2703.     pMblk->mBlkPktHdr.len   = pMblk->mBlkHdr.mLen;
  2704.     if (pDrvCtrl->offset > 0)
  2705. pMblk->mBlkHdr.mData += pDrvCtrl->offset;
  2706.     bcopy ((char *) (RFD_PKT_ADDR (pRFD)),
  2707.    (char *) pMblk->mBlkHdr.mData, 
  2708.    (count & ~0xc000));
  2709. #ifndef INCLUDE_RFC_1213
  2710.     /* New RFC 2233 mib2 interface */
  2711.     /* RFC 2233 mib2 counter update for incoming packet */
  2712.     if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  2713.         {
  2714.         pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,
  2715.                                                  M2_PACKET_IN,
  2716.                                                  pMblk->mBlkHdr.mData,
  2717.                                                  pMblk->mBlkHdr.mLen);
  2718.         }
  2719. #endif /* INCLUDE_RFC_1213 */
  2720. fei82557PollReceiveEnd:
  2721.     /* put the used RFD on the RFD queue */
  2722.     fei82557RFDReturn(pDrvCtrl, pRFD);
  2723.     DRV_LOG (DRV_DEBUG_POLL_RX, ("fei82557PollReceive... return n"), 
  2724.  0, 0, 0, 0, 0, 0);
  2725.     return (retVal);
  2726.     }
  2727. /*******************************************************************************
  2728. * fei82557PollStart - start polling mode
  2729. *
  2730. * This routine starts polling mode by disabling ethernet interrupts and
  2731. * setting the polling flag in the END_CTRL stucture.
  2732. *
  2733. * RETURNS: OK, always.
  2734. */
  2735. LOCAL STATUS fei82557PollStart
  2736.     (
  2737.     DRV_CTRL    *pDrvCtrl       /* pointer to DRV_CTRL structure */
  2738.     )
  2739.     {
  2740.     int         intLevel;
  2741.     DRV_LOG (DRV_DEBUG_POLL, ("fei82557PollStartn"), 0, 0, 0, 0, 0, 0);
  2742.     intLevel = intLock();
  2743.     /* disable system interrupt */
  2744.     SYS_INT_DISABLE (pDrvCtrl);     
  2745.     /* disable chip interrupt   */
  2746.     I82557_INT_DISABLE(SCB_C_M);
  2747.     FEI_FLAG_SET (FEI_POLLING);
  2748.     intUnlock (intLevel);
  2749.     return (OK);
  2750.     }
  2751. /*******************************************************************************
  2752. * fei82557PollStop - stop polling mode
  2753. *
  2754. * This routine stops polling mode by enabling ethernet interrupts and
  2755. * resetting the polling flag in the END_CTRL structure.
  2756. *
  2757. * RETURNS: OK, always.
  2758. */
  2759. LOCAL STATUS fei82557PollStop
  2760.     (
  2761.     DRV_CTRL    *pDrvCtrl       /* pointer to DRV_CTRL structure */
  2762.     )
  2763.     {
  2764.     int         intLevel;
  2765.     intLevel = intLock();
  2766.     /* enable system interrupt */
  2767.     SYS_INT_ENABLE (pDrvCtrl);     
  2768.     /* enable chip interrupt   */
  2769.     I82557_INT_ENABLE(SCB_C_M);
  2770.     /* set flags */
  2771.     FEI_FLAG_CLEAR (FEI_POLLING);
  2772.     intUnlock (intLevel);
  2773.     DRV_LOG (DRV_DEBUG_POLL, ("fei82557PollStop... endn"), 0, 0, 0, 0, 0, 0);
  2774.     return (OK);
  2775.     }
  2776. /**************************************************************************
  2777. *
  2778. * fei82557PhyInit - initialize and configure the PHY device if there is one
  2779. *
  2780. * This routine initialize and configure the PHY device if there is one.
  2781. *
  2782. * RETURNS: OK or ERROR.
  2783. *
  2784. */
  2785. LOCAL STATUS fei82557PhyInit
  2786.     (
  2787.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  2788.     )
  2789.     {
  2790.     int status;
  2791.     int phyDevice;
  2792.     /* not a MII interface, no need to initialize PHY */
  2793.     if (pDrvCtrl->board.phyAddr > 31)
  2794. return (OK);  
  2795.     /* configure the Physical layer medium if it's MII interface */
  2796.     /* starts with logical PHY 1 */
  2797.     phyDevice = (pDrvCtrl->board.phyAddr) ? pDrvCtrl->board.phyAddr : 1;
  2798.     status = fei82557MDIPhyLinkSet (pDrvCtrl, phyDevice);
  2799.     /*  Try a few more times to get a valid link */
  2800.     if (status != OK)
  2801. {
  2802.         /* try getting a valid link with the fallback phy device value */
  2803.         phyDevice = 0;
  2804.         status = fei82557MDIPhyLinkSet (pDrvCtrl, phyDevice);
  2805.         if (status != OK)
  2806.             {
  2807.             /* 
  2808.              * Don't leave the fallback phy value configured 
  2809.              * restore the phy device value, reconfigure phy with it.
  2810.              */
  2811.             phyDevice = (pDrvCtrl->board.phyAddr) ? pDrvCtrl->board.phyAddr : 1;
  2812.             status = fei82557MDIPhyLinkSet (pDrvCtrl, phyDevice);
  2813.             if (status != OK)
  2814.                 {
  2815.         DRV_LOG (DRV_DEBUG_LOAD,
  2816.                ("LINK_FAIL error, check the line connection !!!n"),
  2817.        0, 0, 0, 0, 0, 0);
  2818.         return (status);
  2819.         }
  2820.             }
  2821.         }
  2822.     /* we are here if a valid link is established */
  2823.     status = fei82557MDIPhyConfig (pDrvCtrl, phyDevice); 
  2824.     if (status == PHY_AUTO_FAIL)
  2825. {
  2826. /* force default speed and duplex */
  2827. pDrvCtrl->board.phySpeed = PHY_10MBS;
  2828. pDrvCtrl->board.phyDpx = PHY_HALF_DPX; 
  2829. pDrvCtrl->board.others = 0;
  2830. /* and configure it again */
  2831. status = fei82557MDIPhyConfig (pDrvCtrl, phyDevice);  
  2832. }
  2833.     return (status);
  2834.     } 
  2835. /**************************************************************************
  2836. *
  2837. * fei82557MDIPhyLinkSet - detect and set the link for the PHY device
  2838. *
  2839. * This routine first checks if the link has been established.  If not, it
  2840. * isolates the other one, and tries to establish the link.  PHY device 0 is
  2841. * always at PHY address 0.  PHY 1 can be at 1-31 PHY addresses.
  2842. *
  2843. * RETURNS: OK or ERROR.
  2844. *
  2845. */
  2846. LOCAL STATUS fei82557MDIPhyLinkSet
  2847.     (
  2848.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2849.     int phyAddr /* physical address */
  2850.     )
  2851.     {
  2852.     UINT16 ctlReg;
  2853.     UINT16 statusReg;
  2854.     int isoDev, i;
  2855.     /* read control register */
  2856.     fei82557MDIRead (pDrvCtrl, MDI_CTRL_REG, phyAddr, &ctlReg);
  2857.     /* read again */
  2858.     fei82557MDIRead (pDrvCtrl, MDI_CTRL_REG, phyAddr, &ctlReg);
  2859.     /* check if the PHY is there */
  2860.     if (ctlReg == (UINT16)0xffff)
  2861. return (ERROR);   /* no PHY present */
  2862.     /* The PHY is there, read status register  */
  2863.     fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2864.     /* in case the status bit is the latched bit */
  2865.     if ( !(statusReg & MDI_SR_LINK_STATUS))
  2866. fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2867.     if (statusReg & MDI_SR_LINK_STATUS)
  2868. return (OK);  /* Device found and link OK */
  2869.     /* no link is established, let's configure it */
  2870.     /* isolates the other PHY */
  2871.     isoDev = (phyAddr) ? 0 : 1;
  2872.     fei82557MDIWrite (pDrvCtrl, MDI_CTRL_REG, isoDev, MDI_CR_ISOLATE);
  2873.     /* wait for a while */
  2874.     taskDelay (max (2, sysClkRateGet()/30));
  2875.     /* enable the PHY device we try to configure */
  2876.     fei82557MDIWrite (pDrvCtrl, MDI_CTRL_REG, phyAddr, MDI_CR_SELECT);
  2877.     /* wait for a while for command take effect */
  2878.     taskDelay (max (2, sysClkRateGet()/30)); 
  2879.     /* restart the auto negotiation process, execute anyways even if
  2880.      * it has no such capability.
  2881.      */
  2882.     fei82557MDIWrite (pDrvCtrl, MDI_CTRL_REG, phyAddr, 
  2883.      MDI_CR_RESTART | MDI_CR_SELECT);
  2884.     /* wait for auto-negotiation to complete */
  2885.     for (i = 0; i < 80; i++)
  2886. {
  2887. /* read the status register */
  2888. fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2889. fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2890. if (statusReg & (MDI_SR_AUTO_NEG | MDI_SR_REMOTE_FAULT) )
  2891.     break;
  2892. taskDelay (max (2, sysClkRateGet()/30));
  2893. if (!(statusReg & MDI_SR_AUTO_SELECT))
  2894.     break;  /* no such capability */
  2895. }
  2896.     /* Read the status register */
  2897.     fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2898.     /* some of the status bits require to clear a latch */
  2899.     if (!(statusReg & MDI_SR_LINK_STATUS))
  2900. fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2901.     if (statusReg & MDI_SR_LINK_STATUS)
  2902. return (OK);  /* Link configure done and successful */
  2903.     /* device is there, cann't establish link */
  2904.     return (PHY_LINK_ERROR);   
  2905.      return (OK);
  2906.     } 
  2907. /**************************************************************************
  2908. *
  2909. * fei82557MDIPhyConfig - configure the PHY device
  2910. *
  2911. * This routine configures the PHY device according to the parameters
  2912. * specified by users or the default value.
  2913. *
  2914. * RETURNS: OK or ERROR.
  2915. *
  2916. */
  2917. LOCAL STATUS fei82557MDIPhyConfig
  2918.     (
  2919.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2920.     int phyAddr
  2921.     )
  2922.     {
  2923.     UINT16 ctlReg = 0;
  2924.     int fullDpx=FALSE;
  2925.     int autoSelect =FALSE;
  2926.     UINT16 statusReg;
  2927.     int status, i;
  2928.     /* find out what capabilities the device has */
  2929.     /*  read status register  */
  2930.     fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2931.     /* some of the status bits require to read twice */
  2932.     fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2933.     /* The device at least has to have the half duplex and 10mb speed */
  2934.     if (statusReg & (MDI_SR_10T_FULL_DPX | MDI_SR_TX_FULL_DPX))
  2935. fullDpx = TRUE;
  2936.     if (statusReg & MDI_SR_AUTO_SELECT)
  2937. autoSelect = TRUE;
  2938.     DRV_LOG (DRV_DEBUG_LOAD, ("status REG = %x !!!! n"),
  2939. statusReg, 0, 0, 0, 0, 0);
  2940.     if (pDrvCtrl->board.phyDpx == PHY_FULL_DPX && fullDpx == TRUE)
  2941. ctlReg |= MDI_CR_FDX;
  2942.     if (pDrvCtrl->board.phySpeed == PHY_100MBS)
  2943. ctlReg |= MDI_CR_100;
  2944.     if (pDrvCtrl->board.phySpeed == PHY_AUTO_SPEED || 
  2945. pDrvCtrl->board.phyDpx == PHY_AUTO_DPX )
  2946. {
  2947. if (autoSelect != TRUE)
  2948.     {
  2949.     /* set back to default */
  2950.     pDrvCtrl->board.phySpeed = PHY_10MBS;
  2951.     pDrvCtrl->board.phyDpx = PHY_HALF_DPX;
  2952.     ctlReg |= (PHY_10MBS | PHY_HALF_DPX);
  2953.     }
  2954. else
  2955.     {
  2956.     ctlReg |= (MDI_CR_SELECT | MDI_CR_RESTART);
  2957.     }
  2958.  }
  2959.     /* or other possible board level selection */
  2960.     ctlReg |= pDrvCtrl->board.others;
  2961.     /* configure the PHY */
  2962.     fei82557MDIWrite (pDrvCtrl, MDI_CTRL_REG, phyAddr, ctlReg);
  2963.    
  2964.     /* wait for a while */
  2965.     taskDelay (max (2, sysClkRateGet()/30));   
  2966.     if (!(ctlReg & MDI_CR_RESTART))
  2967. return (OK);
  2968.     /* we are here if the restart auto negotiation is selected */
  2969.     DRV_LOG (DRV_DEBUG_LOAD, ("auto NEGOTIATION STARTS !!!! n"),
  2970.       0, 0, 0, 0, 0, 0);
  2971.     /* wait for it done */
  2972.     for (status = PHY_AUTO_FAIL, i = 0; i < 80; i++)
  2973. {
  2974. /* read status register, first read clears */
  2975. fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2976. fei82557MDIRead (pDrvCtrl, MDI_STATUS_REG, phyAddr, &statusReg);
  2977. if (statusReg & MDI_SR_AUTO_NEG)
  2978.     {
  2979.     status = OK;  /* auto negotiation completed */
  2980.     break;
  2981.     }
  2982. if (statusReg & MDI_SR_REMOTE_FAULT)
  2983.     {
  2984.     status = PHY_AUTO_FAIL;  /* auto negotiation fails */
  2985.     break;
  2986.     }
  2987. }
  2988.       
  2989. return (status);
  2990. /**************************************************************************
  2991. *
  2992. * fei82557MDIRead - read the MDI register
  2993. *
  2994. * This routine reads the specific register in the PHY device
  2995. * Valid PHY address is 0-31
  2996. *
  2997. * RETURNS: OK or ERROR.
  2998. *
  2999. */
  3000. static int fei82557MDIRead
  3001.     (
  3002.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  3003.     int regAddr,
  3004.     int phyAddr,
  3005.     UINT16 *retVal
  3006.     )
  3007.     {
  3008.     int i;
  3009.     volatile UINT32 mdrValue;
  3010.     mdrValue = ((regAddr << 16) | (phyAddr << 21) | (MDI_READ << 26));
  3011.     /* write to MDI it was done differently!! */
  3012.     CSR_LONG_WR (CSR_MDI_OFFSET, mdrValue);
  3013.     /* wait for a while */
  3014.     taskDelay (max (2, sysClkRateGet()/30));    
  3015.     /* check if it's done */
  3016.     for (i = 0; i < 40; i++)
  3017. {
  3018. CSR_LONG_RD (CSR_MDI_OFFSET, mdrValue);
  3019. /* check for correct completion */
  3020. if (mdrValue & (1 << 28))
  3021.     {
  3022.     break;
  3023.     }
  3024. taskDelay (max (1, sysClkRateGet()/60));
  3025. }
  3026.      if (i==40)
  3027.  return (ERROR);
  3028.      *retVal = (UINT16) (mdrValue & 0xffff);
  3029.      return (OK);
  3030.      }
  3031. /**************************************************************************
  3032. *
  3033. * fei82557MDIWrite - write to the MDI register
  3034. *
  3035. * This routine writes the specific register in the PHY device
  3036. * Valid PHY address is 0-31
  3037. *
  3038. * RETURNS: OK or ERROR.
  3039. */
  3040. static int fei82557MDIWrite
  3041.     (
  3042.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  3043.     int regAddr,
  3044.     int phyAddr,
  3045.     UINT16 writeData
  3046.     )
  3047.     {
  3048.     int i;
  3049.     volatile UINT32 mdrValue;
  3050.     mdrValue = ((regAddr << 16) | (phyAddr << 21) | 
  3051. (MDI_WRITE << 26) | writeData);
  3052.     /* write to MDI it was done differently!! */
  3053.     CSR_LONG_WR (CSR_MDI_OFFSET, mdrValue);
  3054.     /* wait for a while */
  3055.     taskDelay (max (2, sysClkRateGet()/30));    
  3056.     /* check if it's done */
  3057.     for (i = 0; i < 40; i++)
  3058. {
  3059. CSR_LONG_RD (CSR_MDI_OFFSET, mdrValue);
  3060. /* check for correct completion */
  3061. if (mdrValue & (1 << 28))
  3062.     {
  3063.     break;
  3064.     }
  3065. taskDelay (max (1, sysClkRateGet()/60));
  3066. }
  3067.      if (i==40)
  3068.  return (ERROR);
  3069.      return (OK);
  3070.      }
  3071. /**************************************************************************
  3072. *
  3073. * fei82557NOP - format and issue a NOP command
  3074. *
  3075. * RETURNS: OK, or ERROR if the NOP command failed.
  3076. *
  3077. */
  3078. LOCAL STATUS fei82557NOP
  3079.     (
  3080.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  3081.     )
  3082.     {
  3083.     if (!(fei82557Action (pDrvCtrl, CFD_C_NOP) & CFD_S_OK))
  3084. return (ERROR);
  3085.     return (OK);
  3086.     } 
  3087. #ifdef DRV_DEBUG557
  3088. /******************************************************************************
  3089. *
  3090. * fei82557DumpPrint - Display statistical counters
  3091. *
  3092. * This routine displays i82557 statistical counters
  3093. *
  3094. * RETURNS: OK, or ERROR if the DUMP command failed.
  3095. */
  3096. STATUS fei82557DumpPrint
  3097.     (
  3098.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  3099.     )
  3100.     {
  3101.     UINT32      dumpArray [18];
  3102.     UINT32 *    pDump;
  3103.     STATUS status = OK;
  3104.     /* dump area must be long-word allign */
  3105.     pDump = (UINT32 *) (((UINT32) dumpArray + 4) & 0xfffffffc);
  3106.     status = fei82557ErrCounterDump (pDrvCtrl, pDump);
  3107.     DRV_LOG (DRV_DEBUG_DUMP, ("n"), 0, 0, 0, 0, 0, 0);
  3108.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx good frames:      %dn"),
  3109.       *pDump++, 0, 0, 0, 0, 0);
  3110.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx MAXCOL errors:    %dn"),
  3111.       *pDump++, 0, 0, 0, 0, 0);
  3112.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx LATECOL errors:   %dn"),
  3113.       *pDump++, 0, 0, 0, 0, 0);
  3114.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx underrun errors:  %dn"),
  3115.       *pDump++, 0, 0, 0, 0, 0);
  3116.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx lost CRS errors:  %dn"),
  3117.       *pDump++, 0, 0, 0, 0, 0);
  3118.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx deferred: %dn"),
  3119.       *pDump++, 0, 0, 0, 0, 0);
  3120.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx single collisions:       %dn"),
  3121.       *pDump++, 0, 0, 0, 0, 0);
  3122.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx multiple collisions:     %dn"),
  3123.       *pDump++, 0, 0, 0, 0, 0);
  3124.     DRV_LOG (DRV_DEBUG_DUMP, ("Tx total collisions: %dn"),
  3125.       *pDump++, 0, 0, 0, 0, 0);
  3126.     DRV_LOG (DRV_DEBUG_DUMP, ("Rx good frames:      %dn"),
  3127.       *pDump++, 0, 0, 0, 0, 0);
  3128.     DRV_LOG (DRV_DEBUG_DUMP, ("Rx CRC errors:       %dn"),
  3129.       *pDump++, 0, 0, 0, 0, 0);
  3130.     DRV_LOG (DRV_DEBUG_DUMP, ("Rx allignment errors:       %dn"),
  3131.       *pDump++, 0, 0, 0, 0, 0);
  3132.     DRV_LOG (DRV_DEBUG_DUMP, ("Rx resource errors:  %dn"),
  3133.       *pDump++, 0, 0, 0, 0, 0);
  3134.     DRV_LOG (DRV_DEBUG_DUMP, ("Rx overrun errors:   %dn"),
  3135.       *pDump++, 0, 0, 0, 0, 0);
  3136.     DRV_LOG (DRV_DEBUG_DUMP, ("Rx collision detect errors: %dn"),
  3137.       *pDump++, 0, 0, 0, 0, 0);
  3138.     DRV_LOG (DRV_DEBUG_DUMP, ("Rx short frame errors:      %dn"),
  3139.       *pDump++, 0, 0, 0, 0, 0);
  3140.     return (status);
  3141.     }
  3142. /*****************************************************************************
  3143. *
  3144. * fei82557ErrCounterDump - dump statistical counters
  3145. *
  3146. * This routine dumps statistical counters for the purpose of debugging and
  3147. * tuning the 82557.
  3148. *
  3149. * The <memAddr> parameter is the pointer to an array of 68 bytes in the
  3150. * local memory.  This memory region must be allocated before this routine is
  3151. * called.  The memory space must also be DWORD (4 bytes) aligned.  When the
  3152. * last DWORD (4 bytes) is written to a value, 0xa007, it indicates the dump
  3153. * command has completed.  To determine the meaning of each statistical
  3154. * counter, see the Intel 82557 manual.
  3155. *
  3156. * RETURNS: OK or ERROR.
  3157. */
  3158. STATUS fei82557ErrCounterDump
  3159.     (
  3160.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  3161.     UINT32 * memAddr
  3162.     )
  3163.     {
  3164.     STATUS status = OK;
  3165.     int i;
  3166.     memAddr[16]=0;    /* make sure the last DWORD is 0 */
  3167.     /* tells the 82557 where to write dump data */
  3168.     if (fei82557SCBCommand (pDrvCtrl, SCB_C_CULDDUMP, TRUE, memAddr)
  3169. == ERROR)
  3170. status = ERROR;
  3171.     /* issue the dump and reset counter command */
  3172.     if (fei82557SCBCommand (pDrvCtrl, SCB_C_CUDUMPRST, 
  3173.    FALSE, (UINT32) 0) 
  3174. == ERROR)
  3175. status = ERROR;
  3176.     /* waits for it done */
  3177.     for (i = 0; i < 60; i++)
  3178.     {
  3179.     if (memAddr[16] == (UINT32) 0xa007)
  3180. break;
  3181. taskDelay (max (2, sysClkRateGet()/30));
  3182.     }
  3183.     if (i==60)
  3184. status = ERROR;
  3185.     return (status);
  3186.     }
  3187. #endif /* End of Debug code */