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

VxWorks

开发平台:

C/C++

  1.  /* rtl81x9End.c - RealTek RTL81x9 Fast Ethernet interface header */
  2. /* Copyright 1984-2000 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01c,28jan00,dgy  Updated comments that refered to the wrong files.
  7. 01b,28jan00,dgy  Changed ryl81x9CsrReadByte to use the correct SYS_IN
  8.  macro.
  9. 01a,29oct99,dgy  created
  10. */
  11. /*
  12. Theory of Operation
  13. I. Board Compatibility
  14. This device driver is designed for the RealTek RTL81x9, the RealTek Fast
  15. Ethernet controllers for PCI.  This chip is used on a few clone boards.
  16. II. Board-specific settings
  17. PCI bus devices are configured by the system at boot time, so no jumpers
  18. need to be set on the board.  The system BIOS will assign the
  19. PCI INTA signal to a (preferably otherwise unused) system IRQ line.
  20. III. Driver operation
  21. IIIa. Rx Ring buffers
  22. The receive unit uses a single linear ring buffer rather than the more
  23.  common (and more efficient) descriptor-based architecture.  Incoming frames
  24. are sequentially stored into the Rx region, and the host copies them into
  25. mBlks.
  26. IIIb. Tx operation
  27. The RTL81x9 uses a fixed set of four Tx descriptors in register space.
  28. EXTERNAL INTERFACE
  29. The only external interface is the rtl81x9EndLoad() routine, which expects
  30. the <initString> parameter as input.  This parameter passes in a 
  31. colon-delimited string of the format:
  32. <unit>:<devMemAddr>:<devIoAddr>:<pciMemBase:<vecNum>:<intLvl>:<memAdrs>:
  33. <memSize>:<memWidth>:<flags>:<buffMultiplier>
  34. The el3c90xEndLoad() function uses strtok() to parse the string.
  35. TARGET-SPECIFIC PARAMETERS
  36. .IP <unit>
  37. A convenient holdover from the former model.  This parameter is used only
  38. in the string name for the driver.
  39. .IP <devMemAddr>
  40. This parameter in the memory base address of the device registers in the
  41. memory map of the CPU. It indicates to the driver where to find the
  42. register set. < This parameter should be equal to NONE if the device
  43. does not support memory mapped registers.
  44. .IP <devIoAddr>
  45. This parameter in the IO base address of the device registers in the
  46. IO map of some CPUs. It indicates to the driver where to find the RDP
  47. register. If both <devIoAddr> and <devMemAddr> are given then the device
  48. chooses <devMemAddr> which is a memory mapped register base address.
  49. This parameter should be equal to NONE if the device does not support 
  50. IO mapped registers.
  51. . <pciMemBase>
  52. This parameter is the base address of the CPU memory as seen from the
  53. PCI bus. This parameter is zero for most intel architectures.
  54. .IP <vecNum>
  55. This parameter is the vector associated with the device interrupt.
  56. This driver configures the LANCE device to generate hardware interrupts
  57. for various events within the device; thus it contains
  58. an interrupt handler routine.  The driver calls intConnect() to connect 
  59. its interrupt handler to the interrupt vector generated as a result of 
  60. the LANCE interrupt.
  61. .IP <intLvl>
  62. Some targets use additional interrupt controller devices to help organize
  63. and service the various interrupt sources.  This driver avoids all
  64. board-specific knowledge of such devices.  During the driver's
  65. initialization, the external routine sysRtl81x9IntEnable() is called to
  66. perform any board-specific operations required to allow the servicing of a
  67. NIC interrupt.  For a description of sysRtl81x9IntEnable(), see "External
  68. Support Requirements" below.
  69. .IP <memAdrs>
  70. This parameter gives the driver the memory address to carve out its
  71. buffers and data structures. If this parameter is specified to be
  72. NONE then the driver allocates cache coherent memory for buffers
  73. and descriptors from the system pool.
  74. The 3C90x NIC is a DMA type of device and typically shares access to
  75. some region of memory with the CPU.  This driver is designed for systems
  76. that directly share memory between the CPU and the NIC.  It
  77. assumes that this shared memory is directly available to it
  78. without any arbitration or timing concerns.
  79. .IP <memSize>
  80. This parameter can be used to explicitly limit the amount of shared
  81. memory (bytes) this driver will use.  The constant NONE can be used to
  82. indicate no specific size limitation.  This parameter is used only if
  83. a specific memory region is provided to the driver.
  84. .IP <memWidth>
  85. Some target hardware that restricts the shared memory region to a
  86. specific location also restricts the access width to this region by
  87. the CPU.  On these targets, performing an access of an invalid width
  88. will cause a bus error.
  89. This parameter can be used to specify the number of bytes of access
  90. width to be used by the driver during access to the shared memory.
  91. The constant NONE can be used to indicate no restrictions.
  92. Current internal support for this mechanism is not robust; implementation 
  93. may not work on all targets requiring these restrictions.
  94. .IP <flags>
  95. This is parameter is used for future use, currently its value should be
  96. zero.
  97. EXTERNAL SUPPORT REQUIREMENTS
  98. This driver requires several external support functions, defined as macros:
  99. .CS
  100.     SYS_INT_CONNECT(pDrvCtrl, routine, arg)
  101.     SYS_INT_DISCONNECT (pDrvCtrl, routine, arg)
  102.     SYS_INT_ENABLE(pDrvCtrl)
  103.     SYS_INT_DISABLE(pDrvCtrl)
  104.     SYS_OUT_BYTE(pDrvCtrl, reg, data)
  105.     SYS_IN_BYTE(pDrvCtrl, reg, data)
  106.     SYS_OUT_WORD(pDrvCtrl, reg, data)
  107.     SYS_IN_WORD(pDrvCtrl, reg, data)
  108.     SYS_OUT_LONG(pDrvCtrl, reg, data)
  109.     SYS_IN_LONG(pDrvCtrl, reg, data)
  110.     SYS_DELAY (delay)
  111.     sysEl3c90xIntEnable(pDrvCtrl->intLevel) 
  112.     sysEl3c90xIntDisable(pDrvCtrl->intLevel)
  113.     sysDelay (delay)
  114. .CE
  115. There are default values in the source code for these macros.  They presume
  116. memory mapped accesses to the device registers and the normal intConnect(),
  117. and intEnable() BSP functions.  The first argument to each is the device
  118. controller structure. Thus, each has access back to all the device-specific
  119. information.  Having the pointer in the macro facilitates the addition 
  120. of new features to this driver.
  121. The macros SYS_INT_CONNECT, SYS_INT_DISCONNECT, SYS_INT_ENABLE and
  122. SYS_INT_DISABLE allow the driver to be customized for BSPs that use special
  123. versions of these routines.
  124. The macro SYS_INT_CONNECT is used to connect the interrupt handler to
  125. the appropriate vector.  By default it is the routine intConnect().
  126. The macro SYS_INT_DISCONNECT is used to disconnect the interrupt handler prior
  127. to unloading the module.  By default this is a dummy routine that
  128. returns OK.
  129. The macro SYS_INT_ENABLE is used to enable the interrupt level for the
  130. end device.  It is called once during initialization.  It calls an
  131. external board level routine sysRtl81x9IntEnable(). 
  132. The macro SYS_INT_DISABLE is used to disable the interrupt level for the
  133. end device.  It is called during stop.  It calls an
  134. external board level routine sysRtl81x9IntDisable().
  135. The macro SYS_DELAY is used for a delay loop. It calls an external board
  136. level routine sysDelay(delay). The granularity of delay is one microsecond.
  137. SYSTEM RESOURCE USAGE
  138. When implemented, this driver requires the following system resources:
  139.     - one mutual exclusion semaphore
  140.     - one interrupt vector
  141.     - 24072 bytes in text for a I80486 target
  142.     - 112 bytes in the initialized data section (data)
  143.     - 0 bytes in the uninitialized data section (BSS)
  144. The driver allocates clusters of size 1536 bytes for receive frames and
  145. and transmit frames. There are 16 descriptors in the upload ring
  146. and 16 descriptors in the download ring. The buffer multiplier by default
  147. is 2, which means that the total number of clusters allocated by default
  148. are 64 ((upload descriptors + download descriptors)*2). There are as many
  149. clBlks as the number of clusters. The number of mBlks allocated are twice
  150. the number of clBlks. By default there are 64 clusters, 64 clBlks and 128
  151. mBlks allocated in the pool for the device. Depending on the load of the
  152. system increase the number of clusters allocated by incrementing the buffer
  153. multiplier.
  154. INCLUDES:
  155. end.h endLib.h etherMultiLib.h rtl81x9End.h
  156. SEE ALSO: muxLib, endLib, netBufLib
  157. .pG "Writing and Enhanced Network Driver"
  158. */
  159. #define END_MACROS
  160. #include "vxWorks.h"
  161. #include "arch/arm/archArm.h"
  162. #include "wdLib.h"
  163. #include "stdlib.h"
  164. #include "taskLib.h"
  165. #include "logLib.h"
  166. #include "intLib.h"
  167. #include "netLib.h"
  168. #include "stdio.h"
  169. #include "stdlib.h"
  170. #include "sysLib.h"
  171. #include "iv.h"
  172. #include "memLib.h"
  173. #include "semLib.h"
  174. #include "cacheLib.h"
  175. #include "sys/ioctl.h"
  176. #include "etherLib.h"
  177. #include "ioLib.h"
  178. #include "net/mbuf.h"
  179. #include "net/protosw.h"
  180. #include "sys/socket.h"
  181. #include "errno.h"
  182. #include "net/if.h"
  183. #include "net/route.h"
  184. #include "netinet/in.h"
  185. #include "netinet/in_systm.h"
  186. #include "netinet/in_var.h"
  187. #include "netinet/ip.h"
  188. #include "netinet/if_ether.h"
  189. #include "net/if_subr.h"
  190. #include "m2Lib.h"
  191. #include "etherMultiLib.h" /* multicast stuff. */
  192. #include "end.h" /* Common END structures. */
  193. #include "netBufLib.h"
  194. #include "muxLib.h"
  195. #include "endLib.h"
  196. #include "lstLib.h" /* Needed to maintain protocol list. */
  197. /***** LOCAL DEFINITIONS *****/
  198. #include "drv/end/rtl81x9.h"
  199. #define DRV_DEBUG
  200. #ifdef DRV_DEBUG
  201. int rtl81x9Debug = 0;
  202. /* int rtl81x9Debug = (DRV_DEBUG_ALL & (~DRV_DEBUG_POLL)); *//* Turn it off initially. */
  203. #define IXP1200_LED_ADDR   (0x38400000+0x10008)  /* Address of LED display */
  204. #define IXP1200_REG_WRITE(a,val) (*(volatile UINT32 *)(a) = (val))
  205. #define DEBUG_LED(val) IXP1200_REG_WRITE(IXP1200_LED_ADDR, (val))
  206. #endif /* DRV_DEBUG */
  207. /*Because MMU maps address 0 from the beginning of RESERVED_LOW_MEM, and PCI device only sees physical address*/
  208. /*that is why we should use MMU_OFFSET here*/
  209. #define MMU_OFFSET(addr) (0x1800000 + addr) 
  210. #define RTLPRINT 
  211. #define PRO_OFFSET 2
  212. /* used to avoid alignment error in protocol identification*/
  213. #define EEPROM_INIT_SIZE 24
  214. unsigned short EEPROM_Init[EEPROM_INIT_SIZE] = 
  215. {
  216. 0x8129,0x10ec,0x8139,0x10ec,0x8139,
  217. #ifdef EEHD_V1
  218. 0x4020,0x7512,0xe000,0x004c,0x0201,
  219. #else
  220. 0x4020,0x7512,0xe000,0x004c,0x0202,
  221. #endif
  222. 0x8c10,0x0000,0x8000,0x43b9,0xb0f2,
  223. 0x031a,0xdf43,0x8a36,0xdf43,0x8a36,
  224. 0x43b9,0xb0f2,0x1111,0x1111
  225. };
  226. unsigned char ownEnetAddr[6];
  227. /*
  228. unsigned char EEPROM_Init[EEPROM_INIT_SIZE] = 
  229. 0x29, 0x81, 0xec, 0x10, 0x39, 0x81, 0xec, 0x10, 0x39, 0x81,
  230. 0x20, 0x40, 0x12, 0x75, 0x00, 0xe0, 0x4c, 0x00, 0x01, 0x02,
  231. 0x10, 0x8c, 0x00, 0x00, 0x00, 0x80, 0xb9, 0x43, 0xf2, 0xb0, 
  232. 0x1a, 0x03, 0x43, 0xdf, 0x36, 0x8a, 0x43, 0xdf, 0x36, 0x8a,
  233. 0xb9, 0x43, 0xf2, 0xb0, 0x11, 0x11, 0x11, 0x11
  234. };
  235. */
  236. /* network buffers configuration */
  237. M_CL_CONFIG rtlMclConfig =  /* mBlk configuration table */
  238.     {
  239.     0, 0, NULL, 0
  240.     };
  241. CL_DESC rtlClDesc [] =  /* network cluster pool configuration table */
  242.     {
  243.     /* 
  244.     clusterSize num memArea memSize
  245.     ----------- ---- ------- -------
  246.     */
  247.     {RTL_BUFSIZ, 0, NULL, 0}
  248.     }; 
  249. int rtlClDescNumEnt = (NELEMENTS(rtlClDesc));
  250. #define END_FLAGS_ISSET(pEnd, setBits)                                  
  251.             ((pEnd)->flags & (setBits))
  252. #define END_HADDR(pEnd)                                                 
  253. ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  254. #define END_HADDR_LEN(pEnd)                                             
  255. ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  256. /*
  257.  * Default macro definitions for BSP interface.
  258.  * For X86 arch, the intConnect/Disconnect defaults are pciIntConnect and
  259.  * pciIntDisconnect.  For all others it is just intConnect and a dummy
  260.  * disconnect function.
  261.  * HELP: This needs to be fixed by porting pciIntLib to all architectures.
  262.  */
  263. #if CPU_FAMILY == I80X86
  264. #ifndef SYS_INT_CONNECT
  265. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)                       
  266.     {                                                                   
  267.     IMPORT STATUS pciIntConnect();                                      
  268.     *pResult = pciIntConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),
  269.      (rtn), (int)(arg));                        
  270.     }
  271. #endif /* SYS_INT_CONNECT */
  272. #ifndef SYS_INT_DISCONNECT
  273. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)                    
  274.     {                                                                   
  275.     IMPORT STATUS pciIntDisconnect();                                      
  276.     *pResult = pciIntDisconnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),
  277.      (rtn));                         
  278.     }
  279. #endif /* SYS_INT_DISCONNECT */
  280. #else /* CPU_FAMILY == I80X86 */
  281. #ifndef SYS_INT_CONNECT
  282. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)                       
  283.     {                                                                   
  284.     IMPORT STATUS intConnect();                                      
  285.     *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),
  286.      (rtn), (int)(arg));                        
  287.     }
  288. #endif /*SYS_INT_CONNECT*/
  289. #ifndef SYS_INT_DISCONNECT
  290. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)                    
  291.     {                                                                   
  292.     *pResult = OK;
  293.     }
  294. #endif /*SYS_INT_DISCONNECT*/
  295. #endif /* CPU_FAMILY == I80X86 */
  296. /* Macro to enable the appropriate interrupt level */
  297. #ifndef SYS_INT_ENABLE
  298. #define SYS_INT_ENABLE(pDrvCtrl) 
  299.     { 
  300.     IMPORT STATUS sysRtl81x9IntEnable(); 
  301.     sysRtl81x9IntEnable ((pDrvCtrl)->ilevel); 
  302.     }
  303. #endif /* SYS_INT_ENABLE*/
  304. /* Macro to disable the appropriate interrupt level */
  305. #ifndef SYS_INT_DISABLE
  306. #define SYS_INT_DISABLE(pDrvCtrl) 
  307.     { 
  308.     IMPORT void sysRtl81x9IntDisable (); 
  309.     sysRtl81x9IntDisable ((pDrvCtrl)->ilevel); 
  310.     }
  311. #endif
  312. #ifndef SYS_OUT_LONG
  313. #define SYS_OUT_LONG(pDrvCtrl,addr,value) 
  314.     { 
  315.     *((ULONG *)(addr)) = PCI_SWAP((value)); 
  316.     }
  317. #endif /* SYS_OUT_LONG */
  318. #ifndef SYS_IN_LONG
  319. #define SYS_IN_LONG(pDrvCtrl,addr,data) 
  320.     { 
  321.     ((data) = PCI_SWAP(*((ULONG *)(addr)))); 
  322.     }
  323. #endif /* SYS_IN_LONG */
  324. #ifndef SYS_OUT_SHORT
  325. #define SYS_OUT_SHORT(pDrvCtrl,addr,value) 
  326.     { 
  327.     *((USHORT *)(addr)) = PCI_WORD_SWAP((value)); 
  328.     }
  329. #endif /* SYS_OUT_SHORT*/
  330. #ifndef SYS_IN_SHORT
  331. #define SYS_IN_SHORT(pDrvCtrl,addr,data) 
  332.     { 
  333.     ((data) = PCI_WORD_SWAP(*((USHORT *)(addr)))); 
  334.     }      
  335. #endif /* SYS_IN_SHORT*/
  336. #ifndef SYS_OUT_BYTE
  337. #define SYS_OUT_BYTE(pDrvCtrl,addr,value) 
  338.     { 
  339.     *((UCHAR *)(addr)) = (value); 
  340.     }
  341. #endif /* SYS_OUT_BYTE */
  342. #ifndef SYS_IN_BYTE
  343. #define SYS_IN_BYTE(pDrvCtrl,addr,data) 
  344.     { 
  345.     ((data) = *((UCHAR *)(addr))); 
  346.     }
  347. #endif /* SYS_IN_BYTE */
  348. #ifndef SYS_OUT_SHORT_CSR
  349. #define SYS_OUT_SHORT_CSR(pDrvCtrl,addr,value) 
  350.     { 
  351.     *(USHORT *)addr = value; 
  352.     }
  353. #endif /*SYS_OUT_SHORT_CSR*/
  354. #ifndef SYS_IN_SHORT_CSR
  355. #define SYS_IN_SHORT_CSR(pDrvCtrl,addr,pData) 
  356.     (*(USHORT *)pData = *(USHORT *)addr)
  357. #endif /*SYS_IN_SHORT_CSR*/
  358. #define SYS_DELAY(count) {                                               
  359. volatile int cx = 0;                            
  360. for (cx = 0; cx < (count); cx++);               
  361. }
  362. #ifndef SYS_ENET_ADDR_GET
  363. #define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress) 
  364.     { 
  365.     IMPORT STATUS sysRtl81x9EnetAddrGet (RTL81X9END_DEVICE *pDrvCtrl, 
  366.                                      char * enetAdrs); 
  367.     sysRtl81x9EnetAddrGet (pDrvCtrl, pAddress); 
  368.     }
  369. #endif /* SYS_ENET_ADDR_GET */
  370. /* Cache macros */
  371. #define RTL_CACHE_INVALIDATE(address, len) 
  372.         CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
  373. #define RTL_CACHE_VIRT_TO_PHYS(address) 
  374.         CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
  375. /*
  376.  * MII access routines are provided for the 8129, which
  377.  * doesn't have a built-in PHY. For the 8139, we fake things
  378.  * up by diverting rl_phy_readreg()/rl_phy_writereg() to the
  379.  * direct access PHY registers.
  380.  */
  381. #define MII_SET(x)
  382. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_MII,
  383. rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_MII, RTL_WIN_0) | x, RTL_WIN_0 )
  384. #define MII_CLR(x)
  385. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_MII,
  386. rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_MII, RTL_WIN_0) & ~x, RTL_WIN_0 )
  387. /* EEPROM Macros */
  388. #define EE_SET(x)
  389. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346,
  390. rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_CFG_9346, RTL_WIN_0) | x, RTL_WIN_0)
  391. #define EE_CLR(x)
  392. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CFG_9346,
  393. rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_CFG_9346, RTL_WIN_0) & ~x, RTL_WIN_0)
  394. /***** LOCALS *****/
  395. LOCAL int rtlRsize = RTL_RMD_RLEN;    /* recv ring size */
  396. LOCAL int intCountNum = 0; /* added by shichao zhang */
  397. LOCAL int rxCountNum =0; /* added by shichao zhang */
  398. LOCAL unsigned char rtlDataToSend[RTL_NUM_TX_DESC * RTL81x9_BUFSIZE];
  399. /* forward static functions */
  400. LOCAL void      rtl81x9EEPROMInit (RTL81X9END_DEVICE *);
  401. LOCAL STATUS rtl81x9Reset ();
  402. LOCAL void     rtl81x9Int  (RTL81X9END_DEVICE *);
  403. LOCAL void rtl81x9HandleRecvInt(RTL81X9END_DEVICE *);
  404. LOCAL void rtl81x9HandleTxInt (RTL81X9END_DEVICE *);
  405. LOCAL void rtl81x9Restart  (RTL81X9END_DEVICE *);
  406. LOCAL STATUS  rtl81x9RestartSetup (RTL81X9END_DEVICE *);
  407. LOCAL void rtl81x9Config  (RTL81X9END_DEVICE *);
  408. LOCAL void rtl81x9AddrFilterSet(RTL81X9END_DEVICE *);
  409. /* END Specific interfaces. */
  410. /* This is the only externally visible interface. */
  411. END_OBJ * rtl81x9EndLoad (char *initString);
  412. LOCAL STATUS rtl81x9Start  (RTL81X9END_DEVICE *);
  413. LOCAL STATUS rtl81x9Stop  (RTL81X9END_DEVICE *);
  414. LOCAL STATUS rtl81x9Unload  (RTL81X9END_DEVICE *);
  415. LOCAL int rtl81x9Ioctl  (RTL81X9END_DEVICE *, int, caddr_t);
  416. STATUS rtl81x9Send  (RTL81X9END_DEVICE *, M_BLK *);
  417. STATUS  rtl81x9DirectSend   (RTL81X9END_DEVICE *, char*, int );
  418. LOCAL STATUS rtl81x9MCastAddrAdd (RTL81X9END_DEVICE *, char *);
  419. LOCAL STATUS rtl81x9MCastAddrDel (RTL81X9END_DEVICE *, char *);
  420. LOCAL STATUS rtl81x9MCastAddrGet (RTL81X9END_DEVICE *, MULTI_TABLE *);
  421. LOCAL STATUS rtl81x9PollSend  (RTL81X9END_DEVICE *, M_BLK *);
  422. LOCAL STATUS rtl81x9PollReceive  (RTL81X9END_DEVICE *, M_BLK *);
  423. LOCAL STATUS rtl81x9PollStart  (RTL81X9END_DEVICE *);
  424. LOCAL STATUS rtl81x9PollStop  (RTL81X9END_DEVICE *);
  425. LOCAL STATUS rtl81x9InitParse (RTL81X9END_DEVICE *, char *);
  426. LOCAL STATUS rtl81x9InitMem  (RTL81X9END_DEVICE *);
  427. LOCAL void rtl81x9LowPowerMode (RTL81X9END_DEVICE *);
  428. LOCAL UCHAR  rtl81x9CsrReadByte  (RTL81X9END_DEVICE *, USHORT, int);
  429. LOCAL USHORT rtl81x9CsrReadWord  (RTL81X9END_DEVICE *, USHORT, int);
  430. LOCAL ULONG rtl81x9CsrReadLong  (RTL81X9END_DEVICE *, USHORT, int);
  431. LOCAL void    rtl81x9CsrWriteByte (RTL81X9END_DEVICE *, USHORT, UCHAR, int);
  432. LOCAL void    rtl81x9CsrWriteWord (RTL81X9END_DEVICE *, USHORT, USHORT, int);
  433. LOCAL void    rtl81x9CsrWriteLong (RTL81X9END_DEVICE *, USHORT, ULONG, int);
  434. LOCAL void   rtl81x9ReadEEPROM  (RTL81X9END_DEVICE *, UCHAR *, ULONG, ULONG, ULONG);
  435. LOCAL void   rtl81x9EEPROMPutByte(RTL81X9END_DEVICE *, ULONG, USHORT);
  436. LOCAL void   rtl81x9EEPROMGetWord(RTL81X9END_DEVICE *, ULONG, USHORT*);
  437. LOCAL void      rtl81x9EEPROMInit (RTL81X9END_DEVICE *);/*by zhangming*/
  438. LOCAL void   rtl81x9EEPROMWriteWord(RTL81X9END_DEVICE *, ULONG, USHORT);/*by zhangming*/
  439. LOCAL void  rtl81x9Phy_writereg (RTL81X9END_DEVICE *, int, int);
  440. LOCAL USHORT  rtl81x9Phy_readreg  (RTL81X9END_DEVICE *, int);
  441. LOCAL int  rtl81x9MII_writereg (RTL81X9END_DEVICE *, RTL_MII_FRAME *);
  442. LOCAL void  rtl81x9MII_sync (RTL81X9END_DEVICE *);
  443. LOCAL void  rtl81x9MII_send (RTL81X9END_DEVICE *, ULONG, int);
  444. LOCAL int  rtl81x9MII_readreg  (RTL81X9END_DEVICE *, RTL_MII_FRAME *);
  445. LOCAL void  rtl81x9AutoNegTx  (RTL81X9END_DEVICE *);
  446. LOCAL int  rtl81x9MII_autoneg (RTL81X9END_DEVICE *);
  447. LOCAL int  rtl81x9MediaSet  (RTL81X9END_DEVICE *, int);
  448. LOCAL int  rtl81x9MediaConfig (RTL81X9END_DEVICE *);
  449. LOCAL void  rtlRegisterShow (RTL81X9END_DEVICE *);
  450. LOCAL void  rtlDrvCtrlShow (RTL81X9END_DEVICE *);
  451. /* 
  452.  * Define the device function table.  This is static across all driver
  453.  * instances.
  454.  */
  455. LOCAL NET_FUNCS rtlFuncTable = 
  456.   {
  457.   (FUNCPTR)rtl81x9Start, /* start func. */                 
  458.   (FUNCPTR)rtl81x9Stop, /* stop func. */
  459.   (FUNCPTR)rtl81x9Unload, /* unload func. */                
  460.   (FUNCPTR)rtl81x9Ioctl, /* ioctl func. */                 
  461.   (FUNCPTR)rtl81x9Send, /* send func. */                  
  462.   (FUNCPTR)rtl81x9MCastAddrAdd, /* multicast add func. */         
  463.   (FUNCPTR)rtl81x9MCastAddrDel, /* multicast delete func. */      
  464.   (FUNCPTR)rtl81x9MCastAddrGet, /* multicast get fun. */          
  465.   (FUNCPTR)rtl81x9PollSend, /* polling send func. */          
  466.   (FUNCPTR)rtl81x9PollReceive, /* polling receive func. */       
  467.   endEtherAddressForm, /* put address info into a NET_BUFFER */
  468.   endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
  469.   endEtherPacketAddrGet /* Get packet addresses. */
  470.   };
  471. extern STATUS pciConfigInLong (int busNo, int deviceNo, int funcNo, int address,
  472.  UINT32 * pData);
  473. /*******************************************************************************
  474. *
  475. * rtl81x9EndLoad - initialize the driver and device
  476. *
  477. * This routine initializes the driver and the device to the operational state.
  478. * All of the device-specific parameters are passed in <initString>, which
  479. * expects a string of the following format:
  480. *
  481. * <unit>:<CSR_reg_addr>:<RAP_reg_addr>:<int_vector>:<int_level>:<shmem_addr>:
  482. * <shmem_size>:<shmem_width>
  483. *
  484. * This routine can be called in two modes. If it is called with an empty but
  485. * allocated string, it places the name of this device (that is, "rtl") into 
  486. * the <initString> and returns 0.
  487. *
  488. * If the string is allocated and not empty, the routine attempts to load
  489. * the driver using the values specified in the string.
  490. *
  491. * RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
  492. * device if the <initString> was NULL.
  493. */
  494. END_OBJ* rtl81x9EndLoad
  495.     (
  496.     char* initString /* string to be parse by the driver */
  497.     )
  498.     {
  499.     RTL81X9END_DEVICE  *pDrvCtrl;
  500. USHORT rtl_dev_id = 0;
  501.     int speed;
  502. int i;
  503.     DRV_LOG (DRV_DEBUG_LOAD, "Loading rtl...n", 1, 2, 3, 4, 5, 6);
  504.     RTLPRINT("now in rtl81x9EndLoad()rn");
  505.     if (initString == NULL)
  506.         return (NULL);
  507.     
  508.     if (initString[0] == NULL)
  509.         {
  510.         bcopy((char *)RTL_DEV_NAME, initString, RTL_DEV_NAME_LEN);
  511.         return (0);
  512.         }
  513.     
  514.     /* allocate the device structure */
  515. RTLPRINT("initstring:%sn",initString);
  516.     pDrvCtrl = (RTL81X9END_DEVICE *)calloc (sizeof (RTL81X9END_DEVICE), 1);
  517.     if (pDrvCtrl == NULL)
  518. goto errorExit;
  519. RTLPRINT("in rtl81x9EndLoad(), begin to initParsern");
  520.     /* parse the init string, filling in the device structure */
  521.     if (rtl81x9InitParse (pDrvCtrl, initString) == ERROR)
  522. goto errorExit;
  523. RTLPRINT("in rtl81x9EndLoad(), end of initParsern");
  524. RTLPRINT("in rtl81x9EndLoad(),pDrvCtrl structure is:rn");
  525. RTLPRINT("devType:%xrn",pDrvCtrl->devType);
  526. RTLPRINT("unit:%drn",pDrvCtrl->unit);
  527. RTLPRINT("ivec:%xrn",pDrvCtrl->ivec);
  528. RTLPRINT("ilevel:%xrn",pDrvCtrl->ilevel);
  529. RTLPRINT("devAdrs:%xrn",pDrvCtrl->devAdrs);
  530. RTLPRINT("memBase:%xrn",pDrvCtrl->memBase);
  531. RTLPRINT("memAdrs:%xrn",pDrvCtrl->memAdrs);
  532. RTLPRINT("memSize:%xrn",pDrvCtrl->memSize);
  533. RTLPRINT("pciMemBase:%xrn",pDrvCtrl->pciMemBase);
  534. RTLPRINT("********************************************rn");
  535. /* Reset the adaptor */
  536. rtl81x9Reset (pDrvCtrl);
  537. RTLPRINT("in rtl81x9EndLoad(), end of rtl81x9Reset()rn");
  538. RTLPRINT("Enet address: ");
  539. /* Read the station address */
  540. for (i=0; i < 6; i++)
  541. {
  542. pDrvCtrl->enetAddr[i] = rtl81x9CsrReadByte (pDrvCtrl, RTL_REGS_IDR0 + i, RTL_WIN_0);
  543. ownEnetAddr[i] = pDrvCtrl->enetAddr[i];
  544. RTLPRINT("%x ", ownEnetAddr[i]);
  545. }
  546. RTLPRINT("rn");
  547. /*
  548.  * Now read the exact device type from the EEPROM to find
  549.  * out if it's an 8129 or 8139.
  550.  */
  551. rtl81x9ReadEEPROM (pDrvCtrl, (UCHAR *) &rtl_dev_id, RTL_EE_PCI_DID, 1, 0);
  552. RTLPRINT("in rtl81x9EndLoad(), rtl_dev_id is:0x%xrn",rtl_dev_id);
  553. /*
  554. pciConfigInWord(0, 8, 0, 0x02, &rtl_dev_id);
  555. */
  556. /*
  557. RTLPRINT("in rtl81x9EndLoad(), rtl_dev_id is:0x%xrn",rtl_dev_id);
  558.      */
  559.     /* Perform memory allocation */
  560.     RTLPRINT("in rtl81x9EndLoad(), begin to rtl81x9InitMem()rn");
  561.     if (rtl81x9InitMem (pDrvCtrl) == ERROR)
  562. goto errorExit;
  563. RTLPRINT("in rtl81x9EndLoad(), end of rtl81x9InitMem()rn");
  564. if (rtl_dev_id == RTL_DEVICEID_8139 || rtl_dev_id == ACCTON_DEVICEID_5030 ||
  565.     rtl_dev_id == DELTA_DEVICEID_8139 || rtl_dev_id == ADDTRON_DEVICEID_8139)
  566. {
  567.      if ((rtl81x9CsrReadLong (pDrvCtrl, RTL_REGS_TX_CONFIG, NONE) & RTL_TXCG_BLID))/*vicadd*/
  568. pDrvCtrl->devType = RTL_DEV_8139A;
  569. else
  570. pDrvCtrl->devType = RTL_DEV_8139B;
  571. }
  572. else if (rtl_dev_id == RTL_DEVICEID_8129)
  573. pDrvCtrl->devType = RTL_DEV_8129;
  574. else {
  575.      DRV_LOG (DRV_DEBUG_LOAD, "rtl: unknown device ID: %xn", rtl_dev_id, 2, 3, 4, 5, 6);
  576. goto errorExit;
  577. }
  578. RTLPRINT("in rtl81x9EndLoad(), begin to rtl81x9MediaConfig()rn");
  579.     speed =  rtl81x9MediaConfig (pDrvCtrl);
  580. pDrvCtrl->nextDesc = 0;
  581. pDrvCtrl->freeDesc = RTL_NUM_TX_DESC;
  582. for (i=0; i < RTL_NUM_TX_DESC; i++)
  583. pDrvCtrl->pDescMem[i] = NULL; 
  584.     /* Perform memory distribution and reset and reconfigure the device */
  585.     RTLPRINT("in rtl81x9EndLoad(), begin to rtl81x9RestartSetup()rn");
  586.     if (rtl81x9RestartSetup (pDrvCtrl) == ERROR)
  587.         goto errorExit;
  588.     /* initialize the END and MIB2 parts of the structure */
  589.     if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, RTL_DEV_NAME,
  590.     pDrvCtrl->unit, &rtlFuncTable,
  591.                       "RTL 81x9 Fast Ethernet Enhanced Network Driver") == ERROR
  592.      || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
  593.                       &pDrvCtrl->enetAddr[0], 6, ETHERMTU,
  594.                       speed)
  595.     == ERROR)
  596. goto errorExit;
  597.     /* set the flags to indicate readiness */
  598.     END_OBJ_READY (&pDrvCtrl->end,
  599.     IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
  600.     | IFF_MULTICAST | IFF_SIMPLEX);
  601.     /*V_LOG (DRV_DEBUG_LOAD, "Done loading rtl...n", 1, 2, 3, 4, 5, 6);*/
  602. /*    rtl81x9EEPROMInit(pDrvCtrl); */
  603.     return (&pDrvCtrl->end);
  604. errorExit:
  605.     if (pDrvCtrl != NULL)
  606. free ((char *)pDrvCtrl);
  607.     printf("****RtlEndLoad ErrorExit!!!****rn");
  608.     return NULL;
  609.     }
  610. /*******************************************************************************
  611. *
  612. * rtl81x9InitParse - parse parameter values from initString
  613. *
  614. * Parse the input string.  Fill in values in the driver control structure.
  615. *
  616. * The initialization string format is:
  617. * "<device addr>:<PCI addr>:<ivec>:<ilevel>:<mem base>:<mem size>:
  618. *  <user flags>:<offset>"
  619. *
  620. * .IP <device addr>
  621. * base address of hardware device registers
  622. * .IP <PCI addr>
  623. * main memory address over the PCI bus
  624. * .IP <ivec>
  625. * interrupt vector number
  626. * .IP <ilevel>
  627. * interrupt level
  628. * .IP <mem base>
  629. * base address of a DMA-able, cache free,pre-allocated  memory
  630. * .IP <mem size>
  631. * size of the pre-allocated memory
  632. * .IP <user flags>
  633. * User flags control the run-time characteristics of the chip
  634. * .IP <offset>
  635. * Memory offset for alignment
  636. * .LP
  637. *
  638. * RETURNS: OK or ERROR for invalid arguments.
  639. */
  640. LOCAL STATUS rtl81x9InitParse
  641.     (
  642.     RTL81X9END_DEVICE * pDrvCtrl,
  643.     char * initString
  644.     )
  645.     {
  646.     char * tok;
  647.     /*char**      holder = NULL;*/
  648.     char*      holder = NULL; /* vicadd*/
  649.     UINT32      devMemAddr;
  650.     UINT32      devIoAddr;
  651.     /* Parse the initString */
  652. /*    RTLPRINT("In rtl81x9InitParse(), initString is: %srn",initString); */
  653.     DRV_LOG (DRV_DEBUG_LOAD, "Parse starting ...n", 1, 2, 3, 4, 5, 6);
  654.     /* Unit number. */
  655.     tok = strtok_r (initString, ":", &holder);
  656.     if (tok == NULL)
  657.         return ERROR;
  658.     pDrvCtrl->unit = atoi (tok);
  659.     DRV_LOG (DRV_DEBUG_LOAD, "Unit : %d ...n", pDrvCtrl->unit, 2, 3, 4, 5, 6);
  660.     /* devAdrs address. */
  661.     tok = strtok_r (NULL, ":", &holder);
  662.     if (tok == NULL)
  663.         return ERROR;
  664.     devMemAddr = (UINT32) strtoul (tok, NULL, 16);
  665.     DRV_LOG (DRV_DEBUG_LOAD, "devMemAddr : 0x%X ...n", devMemAddr,
  666.              2, 3, 4, 5, 6);
  667.     /* devIoAddrs address */
  668.     tok = strtok_r (NULL, ":", &holder);
  669.     if (tok == NULL)
  670.         return ERROR;
  671.     devIoAddr = (UINT32) strtoul (tok, NULL, 16);
  672.     /* always use memory mapped IO if provided, else use io map */
  673.     
  674.     if ((devMemAddr == NONE) && (devIoAddr == NONE))
  675. {
  676.         DRV_LOG (DRV_DEBUG_LOAD, "No memory or IO base specified ...n",
  677.                  1, 2, 3, 4, 5, 6);
  678.         return (ERROR);
  679. }
  680.     else if (devMemAddr != NONE)
  681.         {
  682.         pDrvCtrl->devAdrs = devMemAddr;
  683.         pDrvCtrl->flags   |= RTL_FLG_MODE_MEM_IO_MAP;
  684.         DRV_LOG (DRV_DEBUG_LOAD, "devMemAddr specified for devAdrs ...n",
  685.                  1, 2, 3, 4, 5, 6);
  686.         }
  687.     else
  688. {
  689.         pDrvCtrl->devAdrs = devIoAddr;
  690.         DRV_LOG (DRV_DEBUG_LOAD, "devIoAddr specified for devAdrs - 0x%X ...n",
  691.                  devIoAddr, 2, 3, 4, 5, 6);
  692. }
  693.         
  694.     /* PCI memory base address as seen from the CPU */
  695.     
  696.     tok = strtok_r (NULL, ":", &holder);
  697.     if (tok == NULL)
  698.         return ERROR;
  699.     pDrvCtrl->pciMemBase = strtoul (tok, NULL, 16);
  700.     DRV_LOG (DRV_DEBUG_LOAD, "Pci : 0x%X ...n", pDrvCtrl->pciMemBase,
  701.              2, 3, 4, 5, 6);
  702.     /* Interrupt vector. */
  703.     tok = strtok_r (NULL, ":", &holder);
  704.     if (tok == NULL)
  705.         return ERROR;
  706.     pDrvCtrl->ivec = atoi (tok);
  707.     DRV_LOG (DRV_DEBUG_LOAD, "ivec : 0x%X ...n", pDrvCtrl->ivec,
  708.              2, 3, 4, 5, 6);
  709.     /* Interrupt level. */
  710.     tok = strtok_r (NULL, ":", &holder);
  711.     if (tok == NULL)
  712.         return ERROR;
  713.     pDrvCtrl->ilevel = atoi (tok);
  714.     DRV_LOG (DRV_DEBUG_LOAD, "ilevel : 0x%X ...n", pDrvCtrl->ilevel,
  715.              2, 3, 4, 5, 6);
  716.     /* Caller supplied memory address. */
  717.     tok = strtok_r (NULL, ":", &holder);
  718.     if (tok == NULL)
  719.         return ERROR;
  720.     pDrvCtrl->memAdrs = (char *)strtoul (tok, NULL, 16);
  721.     DRV_LOG (DRV_DEBUG_LOAD, "memAdrs : 0x%X ...n", (int)pDrvCtrl->memAdrs,
  722.              2, 3, 4, 5, 6);
  723.     /* Caller supplied memory size. */
  724.     tok = strtok_r (NULL, ":", &holder);
  725.     if (tok == NULL)
  726.         return ERROR;
  727.     pDrvCtrl->memSize = strtoul (tok, NULL, 16);
  728.     DRV_LOG (DRV_DEBUG_LOAD, "memSize : 0x%X ...n", pDrvCtrl->memSize,
  729.              2, 3, 4, 5, 6);
  730.     /* Caller supplied memory width. */
  731.     tok = strtok_r (NULL, ":", &holder);
  732.     if (tok == NULL)
  733.         return ERROR;
  734.     pDrvCtrl->memWidth = atoi (tok);
  735.     /*DRV_LOG (DRV_DEBUG_LOAD, "memWidth : 0x%X ...n", pDrvCtrl->memWidth,
  736.              2, 3, 4, 5, 6);*/
  737.     /* CSR3B value */
  738.     tok = strtok_r (NULL, ":", &holder);
  739.     if (tok == NULL)
  740.         return ERROR;
  741.     pDrvCtrl->csr3B = strtoul (tok, NULL, 16);
  742.     /*DRV_LOG (DRV_DEBUG_LOAD, "csr3b value : %d ...n", pDrvCtrl->csr3B,
  743.              2, 3, 4, 5, 6);*/
  744.     /* Caller supplied alignment offset. */
  745.     tok = strtok_r (NULL, ":", &holder);
  746.     if (tok == NULL)
  747. return ERROR;
  748.     pDrvCtrl->offset = atoi (tok);
  749.     /*DRV_LOG (DRV_DEBUG_LOAD, "offset value : %d ...n", pDrvCtrl->offset,
  750.              2, 3, 4, 5, 6);*/
  751.     /* caller supplied flags */
  752.     tok = strtok_r (NULL, ":", &holder);
  753.     if (tok == NULL)
  754.         return ERROR;
  755.     pDrvCtrl->flags |= strtoul (tok, NULL, 16);
  756.     /*DRV_LOG (DRV_DEBUG_LOAD, "flags : 0x%X ...n", pDrvCtrl->flags,
  757.              2, 3, 4, 5, 6);*/
  758.     return OK;
  759.     }
  760. /*******************************************************************************
  761. *
  762. * rtl81x9InitMem - initialize memory for the device
  763. *
  764. * Using data in the control structure, setup and initialize the memory
  765. * areas needed.  If the memory address is not already specified, then allocate
  766. * cache safe memory.
  767. *
  768. * RETURNS: OK or ERROR.
  769. *
  770. */
  771. LOCAL STATUS rtl81x9InitMem
  772.     (
  773.     RTL81X9END_DEVICE *  pDrvCtrl /* device to be initialized */
  774.     )
  775.     {
  776.     UINT sz = 0;            /* temporary size holder */
  777.     /***** Establish size of shared memory region we require *****/
  778. /*    RTLPRINT("in rtl81x9InitMemrn"); */
  779.     /*DRV_LOG (DRV_DEBUG_LOAD, "rtl81x9InitMemn", 0, 0, 0, 0, 0, 0);*/
  780.     if ((int) pDrvCtrl->memAdrs != NONE)  /* specified memory pool */
  781.         {
  782.         /*
  783.          * With a specified memory pool we want to maximize
  784.          * rtlRsize and rtlTsize
  785.          */
  786. DRV_LOG (DRV_DEBUG_LOAD, "No memAdrs suppliedn", 0, 0, 0, 0, 0, 0); 
  787.         sz = (pDrvCtrl->memSize - (RMD_SIZ + sizeof (rtl_ib)))
  788.                / ((2 * RTL_BUFSIZ) + RMD_SIZ);
  789.         sz >>= 1;               /* adjust for roundoff */
  790.         for (rtlRsize = 0; sz != 0; rtlRsize++, sz >>= 1)
  791.          ;
  792.         }
  793.     /* limit ring sizes to reasonable values */
  794.     rtlRsize = max (rtlRsize, 2); /* 4 Rx buffers is reasonable min */
  795.     rtlRsize = min (rtlRsize, 7); /* 128 Rx buffers is max for chip */
  796. /* RTLPRINT("in rtl81x9InitMem,rtl Rx buffers:rtlRsize=%drn",rtlRsize); */
  797.     /* Add it all up */
  798.     sz = (((1 << rtlRsize) + 1) * RMD_SIZ) + IB_SIZ + 24;
  799.     RTLPRINT("in rtl81x9InitMem,pDrvCtrl->memSize:%d, we need:%drn",pDrvCtrl->memSize,sz);
  800.     /*DRV_LOG (DRV_DEBUG_LOAD, "sx - %dn",sz, 0, 0, 0, 0, 0); */
  801.     /***** Establish a region of shared memory *****/
  802.     /* OK. We now know how much shared memory we need.  If the caller
  803.      * provides a specific memory region, we check to see if the provided
  804.      * region is large enough for our needs.  If the caller did not
  805.      * provide a specific region, then we attempt to allocate the memory
  806.      * from the system, using the cache aware allocation system call.
  807.      */
  808.     switch ((int) pDrvCtrl->memAdrs)
  809.         {
  810.         default :       /* caller provided memory */
  811. /*         RTLPRINT("in rtl81x9InitMem(), switch in defaultrn"); */
  812.             if (pDrvCtrl->memSize < sz)     /* not enough space */
  813.                 {
  814.      DRV_LOG (DRV_DEBUG_LOAD, "rtl81x9: not enough memory provided need %ul got %dn", 
  815.                           pDrvCtrl->memSize, sz, 0, 0, 0, 0);
  816.                 return (NULL);
  817.                 }
  818.      /* set the beginning of pool */
  819.             pDrvCtrl->pShMem = pDrvCtrl->memAdrs;
  820.             /* assume pool is cache coherent, copy null structure */
  821.             pDrvCtrl->cacheFuncs = cacheNullFuncs;
  822.      DRV_LOG (DRV_DEBUG_LOAD, "Memory checks outn",0, 0, 0, 0, 0, 0); 
  823.             break;
  824.         case NONE :     /* get our own memory */
  825.             /* Because the structures that are shared between the device
  826.              * and the driver may share cache lines, the possibility exists
  827.              * that the driver could flush a cache line for a structure and
  828.              * wipe out an asynchronous change by the device to a neighboring
  829.              * structure. Therefore, this driver cannot operate with memory
  830.              * that is not write coherent.  We check for the availability of
  831.              * such memory here, and abort if the system did not give us what
  832.              * we need.
  833.              */
  834.             if (!CACHE_DMA_IS_WRITE_COHERENT ())
  835.                 {
  836.                 DRV_LOG (DRV_DEBUG_LOAD, "rtl: device requires cache coherent memoryn", 0, 0, 0, 0, 0, 0);
  837.                 return (ERROR);
  838.                 }
  839. /* RTLPRINT("in rtl81x9InitMem(), CACHE_DMA_IS_WRITE_COHERENTrn"); */
  840.             pDrvCtrl->pShMem = (char *) cacheDmaMalloc (sz);
  841. RTLPRINT("in rtl81x9InitMem(), cacheDmaMalloc()rn");
  842.             if ((int)pDrvCtrl->pShMem == NULL)
  843.                 {
  844.                 DRV_LOG (DRV_DEBUG_LOAD, "rtl: system memory unavailablen", 0, 0, 0, 0, 0, 0);
  845.                 return (ERROR);
  846.                 }
  847.             /* copy the DMA structure */
  848. RTLPRINT("in rtl81x9InitMem(), cacheDmaMalloc() return OKrn");
  849.             RTLPRINT("pDrvCtrl->pShMem = 0x%xrn", pDrvCtrl->pShMem);
  850.             pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  851.             break;
  852.         }
  853.     /*                        Turkey Carving
  854.      *                        --------------
  855.      *
  856.      *                          LOW MEMORY
  857.      *
  858.      *             |----------------------------------------|
  859.      *             |       The initialization block         |
  860.      *             |         (sizeof (rtl_ib))              |
  861.      *             |----------------------------------------|
  862.      *             |         The Rx descriptors             |
  863.      *             | ((1 << rtlRsize) + 1)*sizeof (RTL_RMD) |
  864.      *             |----------------------------------------|
  865.      */
  866.     /* align */
  867.     pDrvCtrl->pShMem = (char *) ( ( (int)pDrvCtrl->pShMem + 3) & ~3);
  868.     /* Save some things */
  869.     pDrvCtrl->memBase  = (char *)((ULONG)pDrvCtrl->pShMem & 0xff000000);
  870.     if ((int) pDrvCtrl->memAdrs == NONE)
  871.         pDrvCtrl->flags |= RTL_FLG_MEM_ALLOC_FLAG;
  872.     /* first let's clear memory */
  873.     bzero ((char *) pDrvCtrl->pShMem, (int) sz); 
  874.     /* setup Rx memory pointers */
  875.     pDrvCtrl->pRring      = (RTL_RMD *) ((int)pDrvCtrl->pShMem + IB_SIZ);
  876.     pDrvCtrl->rringLen    = rtlRsize;
  877.     pDrvCtrl->rringSize   = 1 << rtlRsize;
  878.     /* Allocate a chunk of memory for the Chip to place the Rx Buffers in */
  879. pDrvCtrl->ptrRxBufSpace = cacheDmaMalloc(RTL_RXBUFLEN + 64); /* [02/01/2002]<sichao> avoid cache coherency problem */
  880. /*pDrvCtrl->ptrRxBufSpace = malloc (RTL_RXBUFLEN + 64);*/
  881. pDrvCtrl->ptrRxBufSpace += 4;
  882. if (pDrvCtrl->ptrRxBufSpace == NULL)
  883. {
  884. DRV_LOG (DRV_DEBUG_LOAD, "ptrRxBufSpace == NULLn", 0, 0, 0, 0, 0, 0);
  885. return (ERROR);
  886. }
  887.     RTLPRINT("pDrvCtrl->ptrRxBufSpace = 0x%xrn", pDrvCtrl->ptrRxBufSpace);
  888.     pDrvCtrl->rmdNext = 0;
  889.     /*
  890.      * Allocate receive buffers from our own private pool.
  891.      */
  892.     if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  893.         return (ERROR);
  894.     rtlMclConfig.mBlkNum = pDrvCtrl->rringSize * 2;
  895.     rtlClDesc[0].clNum = pDrvCtrl->rringSize *2;
  896.     rtlMclConfig.clBlkNum = rtlClDesc[0].clNum;
  897.     rtlMclConfig.memSize = (rtlMclConfig.mBlkNum * (MSIZE + sizeof (long))) +
  898.                           (rtlMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));
  899.     if ((rtlMclConfig.memArea = (char *) memalign (sizeof(long),
  900.                                                   rtlMclConfig.memSize))
  901.         == NULL)
  902.         return (ERROR);
  903.     rtlClDesc[0].clNum = pDrvCtrl->rringSize *2;
  904.     
  905.     rtlClDesc[0].memSize = (rtlClDesc[0].clNum * (RTL_BUFSIZ + 8))
  906.         + sizeof(int);
  907.     if ((int) pDrvCtrl->memAdrs != NONE) /* Do we hand over our own memory? */
  908.         {
  909.         rtlClDesc[0].memArea = 
  910.                 (char *)(pDrvCtrl->pRring + (((1 << rtlRsize) + 1) * RMD_SIZ));
  911.         }
  912.     else
  913.         {
  914.         rtlClDesc[0].memArea =
  915.             (char *) cacheDmaMalloc (rtlClDesc[0].memSize);
  916.         if ((int)rtlClDesc[0].memArea == NULL)
  917.             {
  918.             DRV_LOG(DRV_DEBUG_LOAD,
  919.                     "system memory unavailablen", 1, 2, 3, 4, 5, 6);
  920.             return (ERROR);
  921.             }
  922.         }
  923. /* RTLPRINT("in rtl81x9InitMem(), begin to netPoolInit()rn"); */
  924.     if (netPoolInit(pDrvCtrl->end.pNetPool, &rtlMclConfig,
  925.                     &rtlClDesc[0], rtlClDescNumEnt, NULL) == ERROR)
  926.         {
  927. /*        RTLPRINT("in rtl81x9InitMem(), netPoolInit error, errno=%xrn",errno); */
  928.      DRV_LOG (DRV_DEBUG_LOAD, "Could not init bufferingn",0, 0, 0, 0, 0, 0); 
  929.         return (ERROR);
  930.         }
  931.     /* Store the cluster pool id as others need it later. */
  932. /*    RTLPRINT("in rtl81x9InitMem(), end of netPoolInit()rn"); */
  933.     pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool,
  934.                                       RTL_BUFSIZ, FALSE);
  935.     return OK;
  936.     }
  937. /*******************************************************************************
  938. *
  939. * rtl81x9Start - start the device
  940. *
  941. * This function initializes the device and calls BSP functions to connect
  942. * interrupts and start the device running in interrupt mode.
  943. *
  944. * The complement of this routine is rtl81x9Stop.  Once a unit is reset by
  945. * rtl81x9Stop, it may be re-initialized to a running state by this routine.
  946. *
  947. * RETURNS: OK if successful, otherwise ERROR
  948. */
  949. LOCAL STATUS rtl81x9Start
  950.     (
  951.     RTL81X9END_DEVICE * pDrvCtrl
  952.     )
  953.     {
  954.     STATUS  result;
  955. int rxcfg;
  956. unsigned short data;
  957. int i;
  958.     pDrvCtrl->txBlocked = FALSE;
  959.     SYS_INT_CONNECT (pDrvCtrl, rtl81x9Int, (int)pDrvCtrl, &result);
  960.     if (result == ERROR)
  961. return ERROR;
  962.     SYS_INT_ENABLE (pDrvCtrl);
  963. /* Init the RX buffer pointer register. */
  964. /*convert to physical address*/
  965.     rtl81x9CsrWriteLong(pDrvCtrl, RTL_REGS_RX_BUF, MMU_OFFSET((ULONG)(pDrvCtrl->ptrRxBufSpace)), RTL_WIN_0);
  966.      /*DRV_LOG (DRV_DEBUG_ALL, "rxbuffer start- %x: n",(ULONG) pDrvCtrl->ptrRxBufSpace , 2, 3, 4, 5, 6);*/
  967. /* Enable Tx and RX */
  968.     rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RX_ENB + RTL_CMD_TX_ENB, RTL_WIN_0);
  969. /*
  970.  * Set the initial TX and RX configuration.
  971.  * Set the buffer size and set the wrap register
  972.  */
  973.     rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_CONFIG, RTL_TXCFG_CONFIG, RTL_WIN_0); 
  974.     /* DRV_LOG (DRV_DEBUG_ALL, "rtl81x9-TXCFG - %x: n",RTL_TXCFG_CONFIG , 2, 3, 4, 5, 6);*/
  975.     rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, RTL_RXCFG_CONFIG, RTL_WIN_0); 
  976. rxcfg = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_RX_CONFIG, RTL_WIN_0);
  977. /* Set the Early Threshold bits depending on flags read */  /*vicadd*/
  978. /* from initialisation string */
  979. rxcfg |= ((pDrvCtrl->flags >> 16) << 24);
  980. /* Set the individual bit to receive frames for this host only. */
  981. rxcfg |= RTL_RXCG_APM;
  982. /* If we want promiscuous mode, set the allframes bit. */
  983. if (pDrvCtrl->ib->rtlIBMode == 0x8000)
  984. rxcfg |= RTL_RXCG_AAP;
  985.      rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0); 
  986. else
  987. rxcfg &= ~RTL_RXCG_AAP;
  988.      rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0); 
  989. }
  990. /*
  991.  * Set capture broadcast bit to capture broadcast frames.
  992.  */
  993. /*vicadd*/
  994. rxcfg |= RTL_RXCG_AB|RTL_RXCG_AM;
  995.    /*  DRV_LOG (DRV_DEBUG_ALL, "rtl81x9-RCR - %x: n", rxcfg, 2, 3, 4, 5, 6);*/
  996.  
  997.  pDrvCtrl->reg_rcr =rxcfg;/* save it */
  998.     rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0); 
  999. /* We now need to update the Multicast Registers */
  1000. /* These values need to be finalised and written */
  1001.     rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_MAR0, 0xffff, RTL_WIN_0); 
  1002.     rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_MAR0 + 4, 0xffff, RTL_WIN_0); 
  1003. /* Enable Controller Interrupts */
  1004.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  1005.    /* DRV_LOG (DRV_DEBUG_ALL, "rtl81x9-IMR - %x: n",RTL_VALID_INTERRUPTS , 2, 3, 4, 5, 6);*/
  1006. data = rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_INTR_STATUS, NONE);
  1007.     DRV_LOG(DRV_DEBUG_ALL, "rtl81x9-INTR_STATUS - %x: n", data, 2, 3, 4, 5, 6);
  1008. rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_STATUS,  0xffff, NONE);
  1009. /* Start RX/TX process. */
  1010.     rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_MISSED, 0, RTL_WIN_0); 
  1011. /* Enable Tx and RX */
  1012.     rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RX_ENB + RTL_CMD_TX_ENB, RTL_WIN_0);
  1013. /*rtlRegisterShow(pDrvCtrl);*/
  1014. /*rtlDrvCtrlShow(pDrvCtrl); */
  1015. /*
  1016. for(i=0;i<256;i++)
  1017. rtlDataToSend[i]=i;
  1018. */
  1019.     return (OK);
  1020.     }
  1021. /*******************************************************************************
  1022. *
  1023. * rtl81x9Int - handle controller interrupt
  1024. *
  1025. * This routine is called at interrupt level in response to an interrupt from
  1026. * the controller.
  1027. *
  1028. * RETURNS: N/A.
  1029. */
  1030. LOCAL void rtl81x9Int
  1031.     (
  1032.     RTL81X9END_DEVICE  *pDrvCtrl
  1033.     )
  1034.     {
  1035.     u_short        stat;
  1036. DRV_LOG (DRV_DEBUG_INT, "Got a interrupt n", 0,0,0,0,0,0);
  1037. /* Disable controller interrupts. */
  1038.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);
  1039. for (;;)
  1040. {
  1041.     /* Read the interrupt status register */
  1042.      stat = rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_INTR_STATUS, NONE);
  1043. /* DRV_LOG (DRV_DEBUG_INT, "ISR status :%x ", stat,0,0,0,0,0); */
  1044.      /* clear interrupts, */
  1045. if (stat)
  1046.      rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_STATUS, stat, NONE);
  1047.      /* Check if a valid Interrupt has been set */
  1048. if ((stat & RTL_VALID_INTERRUPTS) == 0)
  1049. break;
  1050. if (stat & RTL_IPT_PCI_ERR)
  1051. {
  1052. DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_PCI_ERR - Reset and Re initialisen", 0,0,0,0,0,0);
  1053. rtl81x9Reset (pDrvCtrl);
  1054. rtl81x9Restart (pDrvCtrl);
  1055. }
  1056. if (stat & RTL_IPT_PCS_TIMEOUT)
  1057. {
  1058. DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_PCS_TIMEOUTn", 0, 0, 0, 0, 0, 0);
  1059. }
  1060. if (stat & RTL_IPT_CABLE_LEN_CHG)
  1061. {
  1062. DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_CABLE_LEN_CHGn", 0, 0, 0, 0, 0, 0);
  1063. }
  1064. if (stat & RTL_IPT_RX_FIFO_OVER)
  1065. {
  1066. DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_RX_FIFO_OVERn", 0, 0, 0, 0, 0, 0);
  1067. }
  1068. if (stat & RTL_IPT_RX_UNDERUN)
  1069. {
  1070. DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_RX_UNDERUNn", 0, 0, 0, 0, 0, 0);
  1071. /*vicadd*/    rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_STATUS,  RTL_IPT_RX_OK|RTL_IPT_RX_OVERFLOW|RTL_IPT_RX_FIFO_OVER, NONE);
  1072.     /*rxcfg=rtl81x9CsrReadLong (pDrvCtrl, RTL_REGS_RX_CONFIG,  RTL_WIN_0); 
  1073.      DRV_LOG (DRV_DEBUG_ALL, "rtl81x9-RCR - %x: n", rxcfg, 2, 3, 4, 5, 6);
  1074. */
  1075. }
  1076. if (stat & RTL_IPT_RX_OVERFLOW)
  1077. {
  1078. DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_RX_OVERFLOWn", 0, 0, 0, 0, 0, 0);
  1079. }
  1080. if (stat & RTL_IPT_TX_ERR)
  1081. {
  1082. DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_TX_ERRn", 0, 0, 0, 0, 0, 0);
  1083.          rtl81x9HandleTxInt (pDrvCtrl);
  1084. }
  1085. if (stat & RTL_IPT_RX_ERR)
  1086. {
  1087. DRV_LOG (DRV_DEBUG_INT, "RTL_IPT_RX_ERRn", 0, 0, 0, 0, 0, 0);
  1088.          if (netJobAdd ((FUNCPTR)rtl81x9HandleRecvInt, (int) pDrvCtrl,
  1089.                        0, 0, 0, 0) != OK)
  1090. DRV_LOG (DRV_DEBUG_INT, "xl: netJobAdd (rtl81x9HandleRecvInt) failedn", 0, 0, 0, 0, 0, 0);
  1091. }
  1092.      /* Check for transmit Interrupt */
  1093. if (stat & RTL_IPT_TX_OK)
  1094. {
  1095.          rtl81x9HandleTxInt (pDrvCtrl);
  1096. }
  1097. if (stat & RTL_IPT_RX_OK)
  1098. {
  1099.          if (netJobAdd ((FUNCPTR)rtl81x9HandleRecvInt, (int) pDrvCtrl,
  1100.                        0, 0, 0, 0) != OK)
  1101. DRV_LOG (DRV_DEBUG_INT, "xl: netJobAdd (rtl81x9HandleRecvInt) failedn", 0, 0, 0, 0, 0, 0);
  1102. }
  1103. }
  1104.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  1105. }
  1106. /*******************************************************************************
  1107. *
  1108. * rtl81x9HandleTxInt - task level interrupt service for tx packets
  1109. *
  1110. * This routine is called by the interrupt service routine to do any 
  1111. * message transmission processing.
  1112. *
  1113. * RETURNS: N/A.
  1114. */
  1115. LOCAL void rtl81x9HandleTxInt
  1116.     (
  1117.     RTL81X9END_DEVICE *pDrvCtrl
  1118.     )
  1119. {
  1120. int     txDesc;
  1121. int i;
  1122.  DRV_LOG (DRV_DEBUG_TX, "enter rtl81x9HandleTxIntrn", 0, 0, 0, 0, 0, 0);
  1123. for (txDesc=0; txDesc < RTL_NUM_TX_DESC; txDesc++) 
  1124. {
  1125. u_long txstatus;
  1126. u_long txAddress;
  1127.     
  1128.      txstatus = rtl81x9CsrReadLong (pDrvCtrl, 
  1129.      RTL_REGS_TX_STATUS0 + (txDesc*4), NONE);
  1130.      txAddress = rtl81x9CsrReadLong (pDrvCtrl, 
  1131.      RTL_REGS_TX_ADDR0 + (txDesc*4), NONE);
  1132.         DRV_LOG (DRV_DEBUG_TX, "********txstatus=0x%x*******rn", txstatus, 0, 0, 0, 0, 0);
  1133. if (txstatus & RTL_TX_STATUS_OK)
  1134. {
  1135. /* Has the packet been sent previously */
  1136. if ((txstatus & RTL_TX_HOST_OWNS) && (pDrvCtrl->pDescMem[txDesc] != NULL))
  1137. {
  1138. /* Clear the buffer that was registered to the Descriptor */
  1139. /* netClFree (pDrvCtrl->end.pNetPool, pDrvCtrl->pDescMem[txDesc]); */
  1140. pDrvCtrl->pDescMem[txDesc] = NULL;
  1141. pDrvCtrl->freeDesc++;
  1142. if (pDrvCtrl->freeDesc > RTL_NUM_TX_DESC)
  1143. pDrvCtrl->freeDesc = RTL_NUM_TX_DESC;
  1144. }
  1145. }
  1146. /* else if (txstatus & (RTL_TX_UNDERRUN | 
  1147. RTL_TX_OUT_OF_WINDOW | 
  1148. RTL_TX_ABORTED))*/
  1149. else if (txstatus & (RTL_TX_UNDERRUN | 
  1150. RTL_TX_OUT_OF_WINDOW | 
  1151. RTL_TX_ABORTED|
  1152. RTL_TX_CARRIER_LOST))
  1153. {
  1154. /* Clear the buffer that was registered to the Descriptor */
  1155. if (txstatus&RTL_TX_UNDERRUN) return;
  1156. /* netClFree (pDrvCtrl->end.pNetPool, pDrvCtrl->pDescMem[txDesc]); */
  1157. /* pDrvCtrl->pDescMem[txDesc] = NULL; */
  1158.      rtl81x9CsrWriteLong (pDrvCtrl, 
  1159. RTL_REGS_TX_STATUS0 + (txDesc*4), RTL_TX_HOST_OWNS, NONE);
  1160. }
  1161. }
  1162. }
  1163. /*******************************************************************************
  1164. *
  1165. * rtl81x9HandleRecvInt - task level interrupt service for input packets
  1166. *
  1167. * This routine is called by the interrupt service routine to do any 
  1168. * message received processing.
  1169. *
  1170. * RETURNS: N/A.
  1171. */
  1172. LOCAL void rtl81x9HandleRecvInt
  1173.     (
  1174.     RTL81X9END_DEVICE *pDrvCtrl
  1175.     )
  1176.     {
  1177.     int         len, wrapSize;
  1178.     M_BLK_ID  pMblk;
  1179.     char*       pNewCluster;
  1180.     CL_BLK_ID pClBlk;
  1181. RTL_RX_DATA *rxData;
  1182. USHORT cur_rx;
  1183. USHORT limit,max_bytes = 0;
  1184. USHORT  rx_bytes = 0;
  1185. int i;
  1186.         
  1187. char  *readPtr;
  1188. unsigned char * pkt;
  1189. unsigned char rxStatus;
  1190. /*    DRV_LOG (DRV_DEBUG_RX, "rtl81x9HandleRecvInt", 0, 0, 0, 0, 0, 0); */
  1191. /* Disable interrupts by clearing the interrupt mask. */
  1192. /*vicadd    rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE); */
  1193. cur_rx = ((rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_RX_BUF_PTR, NONE) 
  1194. + 16) % RTL_RXBUFLEN);
  1195. /* DRV_LOG (DRV_DEBUG_RX, "In rtl81x9HandleRecvInt, cur_rx=%drn", cur_rx, 0, 0, 0, 0, 0); */
  1196. /* Enable interrupts by setting the interrupt mask. */
  1197. /*vicadd    rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);*/
  1198. /* limit  = (rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_RX_BUF_ADDR, NONE) % RTL_RXBUFLEN);
  1199. if (limit < cur_rx)
  1200. max_bytes = (RTL_RXBUFLEN - cur_rx) + limit;
  1201. else
  1202. max_bytes = limit - cur_rx;
  1203. */
  1204.     while ((rtl81x9CsrReadByte (pDrvCtrl, RTL_REGS_CHIP_CMD, NONE) & 
  1205.         RTL_CMD_RX_BUF_EMPTY) == 0)
  1206.         {
  1207. readPtr = (pDrvCtrl->ptrRxBufSpace + cur_rx);
  1208.       rxData = (RTL_RX_DATA *) readPtr;
  1209.       rxData->rxStatusFlags = PCI_WORD_SWAP(rxData->rxStatusFlags);
  1210.       rxData->rxPktLen = PCI_WORD_SWAP(rxData->rxPktLen);
  1211. /* DRV_LOG (DRV_DEBUG_RX, "In rtl81x9HandleRecvInt, readPtr=0x%08xrn", readPtr, 0, 0, 0, 0, 0); */
  1212. DRV_LOG (DRV_DEBUG_ALL, "In rtl81x9HandleRecvInt, RTL recevie flag :0x%04xrn ", rxData->rxStatusFlags, 2, 3, 4, 5, 6);
  1213. DRV_LOG (DRV_DEBUG_ALL, "In rtl81x9HandleRecvInt, RTL recevie length :0x%04xrn ", rxData->rxPktLen, 2, 3, 4, 5, 6);
  1214. /* RTLPRINT("In rtl81x9HandleRecvInt, readPtr=0x%08xrn", readPtr);
  1215. RTLPRINT("In rtl81x9HandleRecvInt, RTL recevie flag :0x%04xrn ", rxData->rxStatusFlags);
  1216. RTLPRINT("In rtl81x9HandleRecvInt, RTL recevie length :0x%04xrn ", rxData->rxPktLen);
  1217. RTLPRINT("In rtl81x9HandleRecvInt, rxData->pktData=0x%08xrn", rxData->pktData);
  1218. rxStatus = rtl81x9CsrReadByte(pDrvCtrl, 0x36, 0);
  1219. RTLPRINT("In rtl81x9HandleRecvInt, realtek Rx Status Register:0x%02xrn",rxStatus);
  1220. */
  1221. pkt = (unsigned char*)rxData;
  1222. pkt = pkt + 4;
  1223. #if 0
  1224. {
  1225. unsigned long * p;
  1226. p = (unsigned long*)pkt+30;
  1227. /* printf("testn");*/
  1228. /* if((*p == 0xef)&&(*(p+1) == 0x0)&&(*(p+2) == 0x0)&&(*(p+3) == 0x1))
  1229. printf("in rtl81x9,got a packet from 0x%xn",*p); */
  1230. }
  1231. #endif
  1232. #if 0
  1233. /* printf("HandleRecvInt, packet length %d ,mac header:rn",rxData->rxPktLen); */
  1234. if((*pkt == 0x01) && (*(pkt+1) == 0x0)&&(*(pkt+2) == 0x5e))
  1235. {
  1236. for(i=0; i < 14; i++)
  1237. printf("%02x ", *(pkt+i));
  1238. printf("ndest ip:%02x.%02x.%02x.%02x ", *(pkt+30),*(pkt+31),*(pkt+32),*(pkt+33));
  1239. printf("rn***************************************rn");
  1240. }
  1241. /* DRV_LOG (DRV_DEBUG_RX, "HandleRecvInt, packet header:%02xrn", *(rxData->pktData+i), 2, 3, 4, 5, 6);*/
  1242. #endif
  1243. if ((rxData->rxPktLen >> 16) == RTL_RX_UNFINISHED)
  1244. {
  1245.   DRV_LOG (DRV_DEBUG_ALL, "RxHandError 0fff0: ", 1, 2, 3, 4, 5, 6);
  1246.                     break;
  1247. }
  1248. if (!(rxData->rxStatusFlags & RTL_RX_STATUS_OK)) 
  1249. {
  1250. /* DRV_LOG (DRV_DEBUG_ALL, "In rtl81x9HandleRecvInt, RTL recevie not OK!rn ", 1, 2, 3, 4, 5, 6);*/
  1251. /* if (rxData->rxStatusFlags & (RTL_RX_BAD_SYMBOL|
  1252.  RTL_RX_RUNT|
  1253.  RTL_RX_TOO_LONG|
  1254.  RTL_RX_CRC_ERROR|
  1255.  RTL_RX_BAD_ALIGN)) 
  1256. {*/
  1257. DRV_LOG (DRV_DEBUG_ALL, "In rtl81x9HandleRecvInt, RTL recevie not OK, some errorrn ", 1, 2, 3, 4, 5, 6);
  1258. /*rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB, RTL_WIN_0);
  1259. rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB|
  1260. RTL_CMD_RX_ENB, RTL_WIN_0);*/
  1261. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB, RTL_WIN_0);
  1262. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB|RTL_CMD_RX_ENB, RTL_WIN_0);
  1263. rtl81x9CsrWriteLong(pDrvCtrl, RTL_REGS_RX_BUF, MMU_OFFSET((ULONG)(pDrvCtrl->ptrRxBufSpace)), RTL_WIN_0);
  1264. /*rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_RX_BUF_PTR, cur_rx - 16, RTL_WIN_0);*/
  1265. cur_rx = 0;
  1266. /*DRV_LOG (DRV_DEBUG_ALL, "RxHandError:rxData->rxStatusFlags=%x ", rxData->rxStatusFlags, 2, 3, 4, 5, 6);
  1267. i = rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_INTR_STATUS, NONE);
  1268.                             DRV_LOG (DRV_DEBUG_INT, "ISR %x ", i,0,0,0,0,0);*/
  1269.  
  1270. rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, pDrvCtrl->reg_rcr, RTL_WIN_0); 
  1271. /* }*/
  1272. break;
  1273. }
  1274. /* DRV_LOG (DRV_DEBUG_RX, "HandleRecvInt, got a good packetrn", 1, 2, 3, 4, 5, 6);*/
  1275. /* No errors; receive the packet. */
  1276.      len = rxData->rxPktLen; /* get packet length */
  1277. /* DRV_LOG (DRV_DEBUG_RX, "HandleRecvInt, packet length:%drn", len, 2, 3, 4, 5, 6);*/
  1278. rx_bytes += len + 4;
  1279. /*
  1280.  * XXX The RealTek chip includes the CRC with every
  1281.  * received frame, and there's no way to turn this
  1282.  * behavior off (at least, I can't find anything in
  1283.    * the manual that explains how to do it) so we have
  1284.  * to trim off the CRC manually.
  1285.  */
  1286. len -= RTL_CRC_SIZE;
  1287. /*
  1288.  * Avoid trying to read more bytes than we know
  1289.  * the chip has prepared for us.
  1290.  */
  1291. /*if (rx_bytes > max_bytes)
  1292. {
  1293. DRV_LOG (DRV_DEBUG_ALL, "MAX bytes error rx_bytes=%x max_bytes=%xn", rx_bytes, max_bytes, 0, 0, 0, 0);
  1294. break; unknow what do
  1295. }*/
  1296. if(len>1518) {
  1297. /*rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB, RTL_WIN_0);
  1298. rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB|
  1299. RTL_CMD_RX_ENB, RTL_WIN_0);*/
  1300. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB, RTL_WIN_0);
  1301. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB|
  1302. RTL_CMD_RX_ENB, RTL_WIN_0);
  1303. rtl81x9CsrWriteLong(pDrvCtrl, RTL_REGS_RX_BUF, MMU_OFFSET((ULONG)(pDrvCtrl->ptrRxBufSpace)), RTL_WIN_0);
  1304. /*rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_RX_BUF_PTR, cur_rx - 16, RTL_WIN_0);*/
  1305. cur_rx = 0;
  1306. DRV_LOG (DRV_DEBUG_ALL, "RxHandError:rxData->rxStatusFlags=%x ", rxData->rxStatusFlags, 2, 3, 4, 5, 6);
  1307. /*i = rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_INTR_STATUS, NONE);*/
  1308.                                 /*DRV_LOG (DRV_DEBUG_INT, "ISR %x ", i,0,0,0,0,0);*/
  1309.  
  1310. rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, pDrvCtrl->reg_rcr, RTL_WIN_0); 
  1311.        DRV_LOG (DRV_DEBUG_ALL, "MAX bytes error rx_bytes>1518=%x n", len, 0, 0, 0, 0, 0);
  1312.                                break;
  1313. }
  1314. /* DRV_LOG (DRV_DEBUG_LOAD, "Rx_Bytes=%x len=%x max_byte=%xn", rx_bytes, len, max_bytes, 4, 5, 6);*/
  1315.      /* If we cannot get a buffer to loan then bail out. */
  1316.      pNewCluster = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
  1317. /*DRV_LOG (DRV_DEBUG_RX, "Cannot loan cluster!n", 0, 0, 0, 0, 0, 0);
  1318. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);*/
  1319.      if (pNewCluster == NULL)
  1320.          {
  1321.      DRV_LOG (DRV_DEBUG_RX, "Cannot loan cluster!n", 0, 0, 0, 0, 0, 0);
  1322. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1323. goto cleanRXD;
  1324.          }
  1325.      if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
  1326.        {
  1327.          netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
  1328.      DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!n", 0, 0, 0, 0, 0, 0);
  1329. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1330. goto cleanRXD;
  1331.          }
  1332.     
  1333.      /*
  1334.        * OK we've got a spare, let's get an M_BLK_ID and marry it to the
  1335.        * one in the ring.
  1336.        */
  1337.      if ((pMblk = mBlkGet(pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA))
  1338.          == NULL)
  1339.          {
  1340.          netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
  1341.          netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
  1342.          DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!n", 0, 0, 0, 0, 0, 0);
  1343.          END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1344.          goto cleanRXD;
  1345.          }
  1346. /* Copy the data found into the new cluster, we have (+4) to get us past the */
  1347. /* data that the rtl chip places at the start of the message and we remove   */
  1348. /* the CRC from the end of the message */
  1349. if ((readPtr + len) >= (pDrvCtrl->ptrRxBufSpace + RTL_RXBUFLEN))
  1350. {
  1351. wrapSize = (int) ((readPtr + len) - (pDrvCtrl->ptrRxBufSpace + RTL_RXBUFLEN));
  1352. /* Copy in first section of message as stored */
  1353. /* at the end of the ring buffer   */
  1354.   
  1355.      memcpy (pNewCluster+PRO_OFFSET, readPtr + 4, len - wrapSize);
  1356. /* Copy in end of message as stored */
  1357. /* at the start of the ring buffer  */
  1358. /*vicadd*/
  1359. #ifdef CPU_PENTIUM
  1360.      memcpy (pNewCluster +len - wrapSize -4, pDrvCtrl->ptrRxBufSpace, wrapSize+0x04);
  1361. /* there have some error compiler's bug in this line*/
  1362. /* If I just copy the correct bytes the last two bytes will*/
  1363. /* have some trouble, so I copy extra bytes to fix the CPU or*/
  1364. /* OS's bug vic */
  1365. #else
  1366. /* memcpy (pNewCluster+PRO_OFFSET , pDrvCtrl->ptrRxBufSpace, wrapSize); */
  1367. /* modified by zm*/
  1368. memcpy (pNewCluster+PRO_OFFSET + len - wrapSize -4, pDrvCtrl->ptrRxBufSpace, wrapSize + 0x04);
  1369. #endif
  1370. cur_rx = (wrapSize + RTL_CRC_SIZE + 4 + 3) & ~3;
  1371. /*DRV_LOG (DRV_DEBUG_ALL, "wrapsize=%x readptr=%x len=%x pNew=%x newwrapsize %xn",wrapSize,readPtr,len,pNewCluster,pNewCluster-wrapSize ,6);
  1372. DRV_LOG (DRV_DEBUG_ALL, "header=%02x %02x %02x %02x %02x %02x n",readPtr[4],readPtr[5],readPtr[6],readPtr[7],readPtr[8],readPtr[9]);
  1373. DRV_LOG (DRV_DEBUG_ALL, "newheader=%02x %02x %02x %02x %02x %02x n",pNewCluster[0],pNewCluster[1],pNewCluster[2],pNewCluster[3],pNewCluster[4],pNewCluster[5]);*/
  1374. /*DRV_LOG (DRV_DEBUG_ALL, "len=%02x n",len,2, 3, 4, 5, 6);*/
  1375. }
  1376. else
  1377. {
  1378.      memcpy (pNewCluster+PRO_OFFSET, readPtr + 4, len);
  1379. cur_rx = (cur_rx + len + RTL_CRC_SIZE + 4 + 3) & ~3;
  1380.     }
  1381.   /*DRV_LOG (DRV_DEBUG_ALL, "header=%02x %02x %02x %02x %02x %02x n",readPtr[0],readPtr[1],readPtr[2],readPtr[3],readPtr[4],readPtr[5]);
  1382. DRV_LOG (DRV_DEBUG_ALL, "len=%02x n",len,2, 3, 4, 5, 6);*/
  1383. /* Disable interrupts by clearing the interrupt mask. */
  1384. /*vicadd     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);*/
  1385. /* We then write the CAPR as the next ptr we will read minus 0x10 which  */
  1386. /* give us a little leeway to ensure that there is no overflow  */
  1387. rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_RX_BUF_PTR, (cur_rx - 16), RTL_WIN_0);
  1388.      /*DRV_LOG (DRV_DEBUG_ALL, "CAPR=%x len=%dn",(cur_rx - 16), len, 0, 0, 0, 0);*/
  1389. /* Enable interrupts by setting the interrupt mask. */
  1390. /*vicadd     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);*/
  1391.     
  1392.      /* Join the cluster to the MBlock */
  1393.      netClBlkJoin (pClBlk, pNewCluster, len, NULL, 0, 0, 0);
  1394.      netMblkClJoin (pMblk, pClBlk);
  1395.      /* make the packet data coherent */
  1396.      RTL_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len);
  1397.      pMblk->mBlkHdr.mLen   = len;
  1398.      pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1399.      pMblk->mBlkPktHdr.len = len;
  1400.      pMblk->mBlkHdr.mData  += PRO_OFFSET;
  1401.      /* Call the upper layer's receive routine. */
  1402.      rxCountNum++;
  1403.      DRV_LOG(DRV_DEBUG_ALL, "Rx have received %d pktrn", rxCountNum, 2, 3, 4, 5, 6);
  1404.      END_RCV_RTN_CALL (&pDrvCtrl->end, pMblk);
  1405. }
  1406. cleanRXD:
  1407.     }
  1408.   
  1409. /*******************************************************************************
  1410. *
  1411. * rtl81x9Ioctl - interface ioctl procedure
  1412. *
  1413. * Process an interface ioctl request.
  1414. *
  1415. * This routine implements the network interface control functions.
  1416. * It handles EIOCSADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS, EIOCMULTIADD,
  1417. * EIOCMULTIDRTL, EIOCMULTIGET, EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2 commands.
  1418. *
  1419. * RETURNS: OK if successful, otherwise EINVAL.
  1420. */
  1421. LOCAL int rtl81x9Ioctl
  1422.     (
  1423.     RTL81X9END_DEVICE * pDrvCtrl,
  1424.     int cmd,
  1425.     caddr_t data
  1426.     )
  1427.     {
  1428.     int error = 0;
  1429.     long value;
  1430.     switch (cmd)
  1431.         {
  1432.         case EIOCSADDR:
  1433.     if (data == NULL)
  1434. return (EINVAL);
  1435.             bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
  1436.    END_HADDR_LEN(&pDrvCtrl->end));
  1437.             break;
  1438.         case EIOCGADDR:
  1439.     if (data == NULL)
  1440. return (EINVAL);
  1441.             bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
  1442.     END_HADDR_LEN(&pDrvCtrl->end));
  1443.             break;
  1444.         case EIOCSFLAGS:
  1445.     value = (long)data;
  1446.     if (value < 0)
  1447. {
  1448. value = -value;
  1449. value--; /* HRTLP: WHY ??? */
  1450. END_FLAGS_CLR (&pDrvCtrl->end, value);
  1451. }
  1452.     else
  1453. {
  1454. END_FLAGS_SET (&pDrvCtrl->end, value);
  1455. }
  1456.     rtl81x9Config (pDrvCtrl);
  1457.             break;
  1458.         case EIOCGFLAGS:
  1459.     *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
  1460.             break;
  1461. case EIOCPOLLSTART:
  1462.     error = rtl81x9PollStart (pDrvCtrl);
  1463.     break;
  1464. case EIOCPOLLSTOP:
  1465.     error = rtl81x9PollStop (pDrvCtrl);
  1466.     break;
  1467.         case EIOCGMIB2:
  1468.             if (data == NULL)
  1469.                 return (EINVAL);
  1470.             bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
  1471.                   sizeof(pDrvCtrl->end.mib2Tbl));
  1472.             break;
  1473.         case EIOCGFBUF:
  1474.             if (data == NULL)
  1475.                 return (EINVAL);
  1476.             *(int *)data = RTL_MIN_FBUF;
  1477.             break;
  1478.         case EIOCGMWIDTH:
  1479.             if (data == NULL)
  1480.                 return (EINVAL);
  1481.             *(int *)data = pDrvCtrl->memWidth;
  1482.             break;
  1483.         case EIOCGHDRLEN:
  1484.             if (data == NULL)
  1485.                 return (EINVAL);
  1486.             *(int *)data = 14;
  1487.             break;
  1488.         default:
  1489.             error = EINVAL;
  1490.         }
  1491.     return (error);
  1492.     }
  1493. /*******************************************************************************
  1494. *
  1495. * rtl81x9Wait - wait for the command completion
  1496. *
  1497. * This function waits for the command completion
  1498. * It is possible the chip can wedge and the 'command in progress' bit may
  1499. * never clear. Hence, we wait only a finite amount of time to avoid getting
  1500. * caught in an infinite loop. Normally this delay routine would be a macro,
  1501. * but it isn't called during normal operation so we can afford to make it a
  1502. * function.
  1503. *
  1504. * RETURNS: N/A
  1505. */
  1506. LOCAL void rtl81x9Wait
  1507.     (
  1508.     RTL81X9END_DEVICE *  pDrvCtrl /* device control structure */
  1509.     )
  1510.     {
  1511.     register int ix;
  1512.     for (ix = 0; ix < RTL_TIMEOUT; ix++)
  1513.         {
  1514.         /*if ((rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_CHIP_CMD, NONE) & 0x10) == 0)*/
  1515. if ((rtl81x9CsrReadByte (pDrvCtrl, RTL_REGS_CHIP_CMD, NONE) & 0x10) == 0)
  1516.             break; /*vicadd*/
  1517. }
  1518.     if (ix == RTL_TIMEOUT)
  1519.         DRV_LOG (DRV_DEBUG_ALL, "rtl81x9Wait - rtlPci%d: command never completed!n",
  1520.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1521.     return;
  1522.     }
  1523. /*******************************************************************************
  1524. *
  1525. * rtl81x9Reset - Reset the chip
  1526. *
  1527. * This routine does a soft reset on the chip.
  1528. *
  1529. * RETURNS: OK, Always. 
  1530. */
  1531. LOCAL STATUS rtl81x9Reset
  1532.     (
  1533.     RTL81X9END_DEVICE * pDrvCtrl /* pointer to device control structure */
  1534.     )
  1535.     {
  1536.     /* issue the reset command */
  1537. /*DRV_LOG (DRV_DEBUG_LOAD, " rtl81x9Resetn",0,0,0,0,0,0);*/
  1538.     
  1539.     /*rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RESET, RTL_WIN_0);*/
  1540.     rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RESET, RTL_WIN_0);
  1541.     {
  1542. DEBUG_LED(0X2);
  1543. taskDelay (sysClkRateGet()/4);
  1544. }
  1545.     rtl81x9Wait(pDrvCtrl); /* wait for the command to complete */
  1546.     {
  1547. DEBUG_LED(0X7);
  1548. taskDelay (sysClkRateGet()/4);
  1549. }
  1550.     /* wait for a while */
  1551.     SYS_DELAY(10);/*vicadd*/
  1552.     return OK;
  1553.     }
  1554.    
  1555. /*******************************************************************************
  1556. *
  1557. * rtl81x9LowPowerMode - Enter low power mode
  1558. *
  1559. *
  1560. * RETURNS: N/A
  1561. *
  1562. * NOMANUAL
  1563. */
  1564. void rtl81x9LowPowerMode (RTL81X9END_DEVICE* pDrvCtrl)
  1565.     {
  1566. /*
  1567.     rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CFG_9346, 0xC0, RTL_WIN_0);
  1568.     rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CONFIG_1, 0x03, RTL_WIN_0);
  1569. */
  1570.     }
  1571. /*******************************************************************************
  1572. *
  1573. * rtl81x9NormalPowerMode - Come out of Low power mode
  1574. *
  1575. *
  1576. * RETURNS: N/A
  1577. *
  1578. * NOMANUAL
  1579. */
  1580. /*
  1581. void rtl81x9NormalPowerMode (RTL81X9END_DEVICE* pDrvCtrl)
  1582.     {
  1583.     rtl81x9CsrWrite(pDrvCtrl, RTL_REGS_CONFIG_1,  0x00,  RTL_WIN_0);
  1584.     }
  1585. */
  1586. /*******************************************************************************
  1587. *
  1588. * rtl81x9Stop - stop the device
  1589. *
  1590. * This routine marks the interface as down and resets the device.  This
  1591. * includes disabling interrupts, stopping the transmitter and receiver.
  1592. *
  1593. * The complement of this routine is rtl81x9Start.  Once a unit is
  1594. * stop in this routine, it may be re-initialized to a running state by
  1595. * rtl81x9Start.
  1596. *
  1597. * RETURNS: OK or ERROR
  1598. */
  1599. LOCAL STATUS rtl81x9Stop
  1600.     (
  1601.     RTL81X9END_DEVICE * pDrvCtrl
  1602.     )
  1603.     {
  1604.     STATUS result = OK;
  1605.     DRV_LOG (DRV_DEBUG_LOAD, "rtl81x9Stopn",0,0,0,0,0,0);
  1606. /* Disable interrupts by clearing the interrupt mask. */
  1607.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);
  1608. /* Stop the chip's Tx and Rx DMA processes. */
  1609.     rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CHIP_CMD, 0x00, NONE);
  1610. /* Green! Put the chip in low-power mode. */
  1611. rtl81x9LowPowerMode (pDrvCtrl);
  1612.     SYS_INT_DISCONNECT (pDrvCtrl, rtl81x9Int, (int)pDrvCtrl, &result);
  1613.     if (result == ERROR)
  1614.      DRV_LOG (DRV_DEBUG_LOAD, "rtl81x9Stop - Could not disconnect interrupt!n"
  1615.      ,0,0,0,0,0,0);
  1616. return result;
  1617.     }
  1618. /******************************************************************************
  1619. *
  1620. * rtl81x9AddrFilterSet - set the address filter for multicast addresses
  1621. *
  1622. * This routine goes through all of the multicast addresses on the list
  1623. * of addresses (added with the rtl81x9AddrAdd() routine) and sets the
  1624. * device's filter correctly.
  1625. *
  1626. * NOMANUAL
  1627. */
  1628. LOCAL void rtl81x9AddrFilterSet
  1629.     (
  1630.     RTL81X9END_DEVICE *pDrvCtrl
  1631.     )
  1632.     {
  1633.     ETHER_MULTI*  pCurr;
  1634.     rtl_ib* pIb;
  1635.     u_char* pCp;
  1636.     u_char  c;
  1637.     u_long  crc;
  1638.     u_long  carry;
  1639. int i, j;
  1640.     pIb = pDrvCtrl->ib;
  1641.     RTL_ADDRF_CLEAR (pIb);
  1642.     pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
  1643.     while (pCurr != NULL)
  1644. {
  1645. pCp = (unsigned char *)&pCurr->addr;
  1646. crc = 0xFFFFFFFF; /* initial value */
  1647. for (i = 0; i < 6; i++) 
  1648. {
  1649. c = *(pCp + i);
  1650. for (j = 0; j < 8; j++) 
  1651. {
  1652. carry = ((crc & 0x80000000) ? 1 : 0) ^ (c & 0x01);
  1653. crc <<= 1;
  1654. c >>= 1;
  1655. if (carry)
  1656. crc = (crc ^ 0x04c11db6) | carry;
  1657. }
  1658. }
  1659. /* Just want the 6 most significant bits. */
  1660. crc = crc >> 26;
  1661. /* Turn on the corresponding bit in the filter. */
  1662. RTL_ADDRF_SET (pIb, crc);
  1663. pCurr = END_MULTI_LST_NEXT(pCurr);
  1664. }
  1665.     }
  1666. /*******************************************************************************
  1667. *
  1668. * rtl81x9PollReceive - routine to receive a packet in polled mode.
  1669. *
  1670. * This routine is called by a user to try and get a packet from the
  1671. * device.
  1672. */
  1673. LOCAL STATUS rtl81x9PollReceive
  1674.     (
  1675.     RTL81X9END_DEVICE *pDrvCtrl,
  1676.     M_BLK_ID pMblk
  1677.     )
  1678.     {
  1679.     int         len, wrapSize;
  1680.     char*       pNewCluster;
  1681.     CL_BLK_ID pClBlk;
  1682. RTL_RX_DATA *rxData;
  1683. USHORT cur_rx;
  1684. USHORT limit;
  1685. USHORT max_bytes = 0, rx_bytes = 0;
  1686. char  *readPtr;
  1687.     DRV_LOG (DRV_DEBUG_POLL_RX, "rtl81x9PollReceiven",0,0,0,0,0,0);
  1688. /* Disable interrupts by clearing the interrupt mask. */
  1689.    /*vicadd  rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);*/
  1690. cur_rx = ((rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_RX_BUF_PTR, NONE) 
  1691. + 16) % RTL_RXBUFLEN);
  1692. /* Enable interrupts by setting the interrupt mask. */
  1693. /*vicadd    rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);*/
  1694. limit  = (rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_RX_BUF_ADDR, NONE) % RTL_RXBUFLEN);
  1695. if (limit < cur_rx)
  1696. max_bytes = (RTL_RXBUFLEN - cur_rx) + limit;
  1697. else
  1698. max_bytes = limit - cur_rx;
  1699.     while ((rtl81x9CsrReadByte (pDrvCtrl, RTL_REGS_CHIP_CMD, NONE) & 
  1700.         RTL_CMD_RX_BUF_EMPTY) == 0)
  1701.         {
  1702. readPtr = (pDrvCtrl->ptrRxBufSpace + cur_rx);
  1703.       rxData = (RTL_RX_DATA *) readPtr;
  1704. /*
  1705.  * Here's a totally undocumented fact for you. When the
  1706.  * RealTek chip is in the process of copying a packet into
  1707.  * RAM for you, the length will be 0xfff0. If you spot a
  1708.  * packet header with this value, you need to stop. The
  1709.  * datasheet makes absolutely no mention of this and
  1710.  * RealTek should be shot for this.
  1711.  */
  1712. if ((rxData->rxPktLen >> 16) == RTL_RX_UNFINISHED)
  1713. break;
  1714. if (!(rxData->rxStatusFlags & RTL_RX_STATUS_OK)) 
  1715. {
  1716. if (rxData->rxStatusFlags & (RTL_RX_BAD_SYMBOL|
  1717.  RTL_RX_RUNT|
  1718.  RTL_RX_TOO_LONG|
  1719.  RTL_RX_CRC_ERROR|
  1720.  RTL_RX_BAD_ALIGN)) 
  1721. {
  1722. /*rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB, RTL_WIN_0);*/
  1723. /*rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB|
  1724. RTL_CMD_RX_ENB, RTL_WIN_0);*/
  1725. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB, RTL_WIN_0);
  1726. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_TX_ENB|
  1727. RTL_CMD_RX_ENB, RTL_WIN_0);
  1728. rtl81x9CsrWriteLong(pDrvCtrl, RTL_REGS_RX_BUF, (ULONG) pDrvCtrl->ptrRxBufSpace, RTL_WIN_0);
  1729. rtl81x9CsrWriteWord(pDrvCtrl, RTL_REGS_RX_BUF_PTR, cur_rx - 16, RTL_WIN_0);
  1730. cur_rx = 0;
  1731. }
  1732. break;
  1733. }
  1734. /* No errors; receive the packet. */
  1735.      len = rxData->rxPktLen; /* get packet length */
  1736. rx_bytes += len + 4;
  1737. /*
  1738.  * XXX The RealTek chip includes the CRC with every
  1739.  * received frame, and there's no way to turn this
  1740.  * behavior off (at least, I can't find anything in
  1741.    * the manual that explains how to do it) so we have
  1742.  * to trim off the CRC manually.
  1743.  */
  1744. len -= RTL_CRC_SIZE;
  1745. /*
  1746.  * Avoid trying to read more bytes than we know
  1747.  * the chip has prepared for us.
  1748.  */
  1749. if (rx_bytes > max_bytes)
  1750. break;
  1751.      /* If we cannot get a buffer to loan then bail out. */
  1752.      pNewCluster = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
  1753.      if (pNewCluster == NULL)
  1754.          {
  1755.          DRV_LOG (DRV_DEBUG_POLL_RX, "Cannot loan cluster!n", 0, 0, 0, 0, 0, 0);
  1756. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1757. goto cleanRXD;
  1758.          }
  1759.      if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
  1760.        {
  1761.          netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
  1762.          DRV_LOG (DRV_DEBUG_POLL_RX, "Out of Cluster Blocks!n", 0, 0, 0, 0, 0, 0);
  1763. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1764. goto cleanRXD;
  1765.          }
  1766.     
  1767. /* Copy the data found into the new cluster, we have (+4) to get us past the */
  1768. /* data that the rtl chip places at the start of the message and we remove   */
  1769. /* the CRC from the end of the message */
  1770. if ((readPtr + len) >= (pDrvCtrl->ptrRxBufSpace + RTL_RXBUFLEN))
  1771. {
  1772. wrapSize = (int) ((readPtr + len) - (pDrvCtrl->ptrRxBufSpace + RTL_RXBUFLEN));
  1773. /* Copy in first section of message as stored */
  1774. /* at the end of the ring buffer   */
  1775.      memcpy (pNewCluster, readPtr + 4, len - wrapSize);
  1776. /* Copy in end of message as stored */
  1777. /* at the start of the ring buffer  */
  1778.      memcpy (pNewCluster, pDrvCtrl->ptrRxBufSpace, wrapSize);
  1779. cur_rx = (wrapSize + RTL_CRC_SIZE + 4 + 3) & ~3;
  1780. }
  1781. else
  1782. {
  1783.      memcpy (pNewCluster, readPtr + 4, len);
  1784. cur_rx = (cur_rx + len + RTL_CRC_SIZE + 4 + 3) & ~3;
  1785. }
  1786. /* Disable interrupts by clearing the interrupt mask. */
  1787. /*vicadd     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);*/
  1788. /* We then write the CAPR as the next ptr we will read minus 0x10 which  */
  1789. /* give us a little leeway to ensure that there is no overflow  */
  1790. rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_RX_BUF_PTR, (cur_rx - 16), RTL_WIN_0);
  1791.        /*RV_LOG (DRV_DEBUG_ALL,"Capr=%Xn",(cur_rx - 16) , 0, 0, 0, 0, 0);*/
  1792. /* Enable interrupts by setting the interrupt mask. */
  1793. /*vicadd     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);*/
  1794.     
  1795.      /* Join the cluster to the MBlock */
  1796.      netClBlkJoin (pClBlk, pNewCluster, len, NULL, 0, 0, 0);
  1797.      netMblkClJoin (pMblk, pClBlk);
  1798.      /* make the packet data coherent */
  1799.      RTL_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len);
  1800.      pMblk->mBlkHdr.mLen   = len;
  1801.      pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1802.      pMblk->mBlkPktHdr.len = len;
  1803.      /* Call the upper layer's receive routine. */
  1804.      END_RCV_RTN_CALL (&pDrvCtrl->end, pMblk);
  1805. return OK;
  1806. }
  1807. cleanRXD:
  1808. return ERROR;
  1809.     }
  1810. /*******************************************************************************
  1811. *
  1812. * rtl81x9PollSend - routine to send a packet in polled mode.
  1813. *
  1814. * This routine is called by a user to try and send a packet on the
  1815. * device.
  1816. */
  1817. LOCAL STATUS rtl81x9PollSend
  1818.     (
  1819.     RTL81X9END_DEVICE* pDrvCtrl,
  1820.     M_BLK_ID pMblk
  1821.     )
  1822.     {
  1823. int     txDesc;
  1824.     DRV_LOG (DRV_DEBUG_ALL, "rtl81x9PollSendn",0,0,0,0,0,0);
  1825. for (txDesc=0; txDesc < RTL_NUM_TX_DESC; txDesc++) 
  1826. {
  1827. u_long txstatus;
  1828.     
  1829.      txstatus = rtl81x9CsrReadLong (pDrvCtrl, 
  1830.      RTL_REGS_TX_STATUS0 + (txDesc*4), NONE);
  1831. if (txstatus & RTL_TX_STATUS_OK)
  1832. {
  1833. /* Has the packet been sent previously */
  1834. if ((txstatus & RTL_TX_HOST_OWNS) && (pDrvCtrl->pDescMem[txDesc] != NULL))
  1835. {
  1836. /* Clear the buffer that was registered to the Descriptor */
  1837. netClFree (pDrvCtrl->end.pNetPool, pDrvCtrl->pDescMem[txDesc]);
  1838. pDrvCtrl->pDescMem[txDesc] = NULL;
  1839. pDrvCtrl->freeDesc++;
  1840. if (pDrvCtrl->freeDesc > RTL_NUM_TX_DESC)
  1841. pDrvCtrl->freeDesc = RTL_NUM_TX_DESC;
  1842. }
  1843. }
  1844. else if (txstatus & (RTL_TX_UNDERRUN | 
  1845. RTL_TX_OUT_OF_WINDOW | 
  1846. RTL_TX_ABORTED ))
  1847. {
  1848. /* Clear the buffer that was registered to the Descriptor */
  1849. netClFree (pDrvCtrl->end.pNetPool, pDrvCtrl->pDescMem[txDesc]);
  1850. pDrvCtrl->pDescMem[txDesc] = NULL;
  1851.      rtl81x9CsrWriteLong (pDrvCtrl, 
  1852. RTL_REGS_TX_STATUS0 + (txDesc*4), RTL_TX_HOST_OWNS, NONE);
  1853. }
  1854. }
  1855.     return (OK);
  1856.     }
  1857. /*****************************************************************************
  1858. *
  1859. * rtl81x9MCastAddrAdd - add a multicast address for the device
  1860. *
  1861. * This routine adds a multicast address to whatever the driver
  1862. * is already listening for.  It then resets the address filter.
  1863. */
  1864. LOCAL STATUS rtl81x9MCastAddrAdd
  1865.     (
  1866.     RTL81X9END_DEVICE *pDrvCtrl,
  1867.     char* pAddress
  1868.     )
  1869.     {
  1870.     int error;
  1871.     if ((error = etherMultiAdd (&pDrvCtrl->end.multiList,
  1872. pAddress)) == ENETRESET)
  1873.     rtl81x9Config (pDrvCtrl);
  1874.     return (OK);
  1875.     }
  1876. /*****************************************************************************
  1877. *
  1878. * rtl81x9MCastAddrDel - delete a multicast address for the device
  1879. *
  1880. * This routine removes a multicast address from whatever the driver
  1881. * is listening for.  It then resets the address filter.
  1882. */
  1883. LOCAL STATUS rtl81x9MCastAddrDel
  1884.     (
  1885.     RTL81X9END_DEVICE* pDrvCtrl,
  1886.     char* pAddress
  1887.     )
  1888.     {
  1889.     int error;
  1890.     if ((error = etherMultiDel (&pDrvCtrl->end.multiList,
  1891.      (char *)pAddress)) == ENETRESET)
  1892.     rtl81x9Config (pDrvCtrl);
  1893.     return (OK);
  1894.     }
  1895. /*****************************************************************************
  1896. *
  1897. * rtl81x9MCastAddrGet - get the multicast address list for the device
  1898. *
  1899. * This routine gets the multicast list of whatever the driver
  1900. * is already listening for.
  1901. */
  1902. LOCAL STATUS rtl81x9MCastAddrGet
  1903.     (
  1904.     RTL81X9END_DEVICE* pDrvCtrl,
  1905.     MULTI_TABLE* pTable
  1906.     )
  1907.     {
  1908.     int error;
  1909.     error = etherMultiGet (&pDrvCtrl->end.multiList, pTable);
  1910.     return (error);
  1911.     }
  1912. /*******************************************************************************
  1913. *
  1914. * rtl81x9Send - the driver send routine
  1915. *
  1916. * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
  1917. * The buffer must already have the addressing information properly installed
  1918. * in it.  This is done by a higher layer.  
  1919. *
  1920. * RETURNS: OK or ERROR.
  1921. */
  1922. STATUS rtl81x9Send
  1923.     (
  1924.     RTL81X9END_DEVICE  *pDrvCtrl, /* device ptr */
  1925.     M_BLK_ID  pMblk /* data to send */
  1926.     )
  1927.     {
  1928.     int         len = 0;
  1929.     char*       pBuf;
  1930. ULONG tx_val;
  1931. int i;
  1932. DRV_LOG (DRV_DEBUG_ALL, "Enter driver sendn", 0, 0, 0, 0, 0, 0);
  1933.     /*
  1934.      * Obtain exclusive access to transmitter.  This is necessary because
  1935.      * we might have more than one stack transmitting at once.
  1936.      */   
  1937.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);
  1938.     if (!(pDrvCtrl->flags & RTL_FLG_POLLING))
  1939. END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
  1940.     /* find Tx Descriptor */
  1941. if (pDrvCtrl->freeDesc != 0)
  1942. {
  1943. if (pDrvCtrl->pDescMem[pDrvCtrl->nextDesc] == NULL) 
  1944. {
  1945.      pBuf = (pDrvCtrl->txmemspace + (pDrvCtrl->nextDesc * RTL81x9_BUFSIZE));
  1946.      pBuf += pDrvCtrl->offset; /* take care of the alignment */
  1947.      len = netMblkToBufCopy (pMblk, pBuf, NULL);
  1948. cacheFlush(_DATA_CACHE, (void*)pBuf, len);
  1949. #if 0
  1950. printf("pDrvCtrl->txmemspace address:0x%08xrn",pDrvCtrl->txmemspace);
  1951. printf("In driver send, pBuf length:%d, address:0x%08x, content:rn",len,pBuf);
  1952. for(i=0; i < pMblk->mBlkHdr.mLen; i++)
  1953. printf("%02x ", *(pBuf+i));
  1954. printf("rn############################rn");
  1955. #endif
  1956. /*     DRV_LOG (DRV_DEBUG_ALL, "In driver send, length:%drn", len, 0, 0, 0, 0, 0);*/
  1957.     netMblkClChainFree(pMblk);
  1958.      len = max (len, ETHERSMALL);
  1959. tx_val = len + (3 << 16);
  1960.             rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_ADDR0 + (pDrvCtrl->nextDesc * 4), MMU_OFFSET((unsigned int)pBuf), RTL_WIN_0); 
  1961.      rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_STATUS0 + (pDrvCtrl->nextDesc * 4), tx_val, RTL_WIN_0);
  1962. /*     rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_ADDR0 + (pDrvCtrl->nextDesc * 4), (int) K0_TO_PHYS(pMblk->mBlkHdr.mData), RTL_WIN_0); 
  1963.      rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_STATUS0 + (pDrvCtrl->nextDesc * 4), tx_val, RTL_WIN_0);
  1964. */
  1965. DRV_LOG (DRV_DEBUG_ALL, "No=%x txstatus=%xn", pDrvCtrl->nextDesc, tx_val, 0, 0, 0, 0);
  1966. pDrvCtrl->pDescMem[pDrvCtrl->nextDesc] = pBuf;
  1967. pDrvCtrl->nextDesc++;
  1968. if (pDrvCtrl->nextDesc == RTL_NUM_TX_DESC)
  1969. pDrvCtrl->nextDesc = 0;
  1970. if (pDrvCtrl->freeDesc != 0)
  1971. pDrvCtrl->freeDesc--;
  1972. }
  1973. else
  1974. {
  1975.      DRV_LOG (DRV_DEBUG_TX, "Next Desc %d is not free yetn", pDrvCtrl->nextDesc, 0, 0, 0, 0, 0);
  1976.      rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  1977.      /* added by zhangshichao */
  1978.          netMblkClChainFree(pMblk);
  1979.     if (!(pDrvCtrl->flags & RTL_FLG_POLLING))
  1980.          END_TX_SEM_GIVE (&pDrvCtrl->end);
  1981.     
  1982.          return (ERROR);
  1983.          } 
  1984. }
  1985. else
  1986. {
  1987.      DRV_LOG (DRV_DEBUG_TX, "No free Descriptorsn", 0, 0, 0, 0, 0, 0);
  1988.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  1989.     /* added by zhangshichao */
  1990.     
  1991.         netMblkClChainFree(pMblk);
  1992.     if (!(pDrvCtrl->flags & RTL_FLG_POLLING))
  1993.          END_TX_SEM_GIVE (&pDrvCtrl->end);
  1994.    
  1995.         return (ERROR);
  1996.         }
  1997.     /* Flush the write pipe */
  1998.     CACHE_PIPE_FLUSH ();
  1999.     if (!(pDrvCtrl->flags & RTL_FLG_POLLING))
  2000.         END_TX_SEM_GIVE (&pDrvCtrl->end);
  2001.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  2002.     return (OK);
  2003. }
  2004. /*******************************************************************************
  2005. *
  2006. * rtl81x9DirectSend - the driver send routine without additional copy
  2007. *
  2008. * This routine simply sends off the data pointed by pBuf.
  2009. *
  2010. * RETURNS: OK or ERROR.
  2011. */
  2012. STATUS rtl81x9DirectSend
  2013.     (
  2014.     RTL81X9END_DEVICE  *pDrvCtrl, /* device ptr */
  2015.     char* pBuf, /* data to send */
  2016.     int len /* data length to be sent */
  2017.     )
  2018.     {
  2019. ULONG tx_val;
  2020.     /*
  2021.      * Obtain exclusive access to transmitter.  This is necessary because
  2022.      * we might have more than one stack transmitting at once.
  2023.      */   
  2024.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);
  2025.     if (!(pDrvCtrl->flags & RTL_FLG_POLLING))
  2026. END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
  2027.     /* find Tx Descriptor */
  2028. if (pDrvCtrl->freeDesc != 0)
  2029. {
  2030. if (pDrvCtrl->pDescMem[pDrvCtrl->nextDesc] == NULL) 
  2031. {
  2032.      len = max (len, ETHERSMALL);
  2033. tx_val = len + (3 << 16);
  2034.      rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_ADDR0 + (pDrvCtrl->nextDesc * 4), (int)(pBuf), RTL_WIN_0); 
  2035.      rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_STATUS0 + (pDrvCtrl->nextDesc * 4), tx_val, RTL_WIN_0);
  2036. /*DRV_LOG (DRV_DEBUG_ALL, "No=%x txstatus=%xn", pDrvCtrl->nextDesc, tx_val, 0, 0, 0, 0); */
  2037. pDrvCtrl->pDescMem[pDrvCtrl->nextDesc] = pBuf;
  2038. pDrvCtrl->nextDesc++;
  2039. if (pDrvCtrl->nextDesc == 4)
  2040. pDrvCtrl->nextDesc = 0;
  2041. if (pDrvCtrl->freeDesc != 0)
  2042. pDrvCtrl->freeDesc--;
  2043. }
  2044. else
  2045. {
  2046.      DRV_LOG (DRV_DEBUG_TX, "Next Desc %d is not free yetn", pDrvCtrl->nextDesc, 0, 0, 0, 0, 0);
  2047.       rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  2048. /* add by zhangming */
  2049.      if (!(pDrvCtrl->flags & RTL_FLG_POLLING))
  2050.          END_TX_SEM_GIVE (&pDrvCtrl->end);
  2051.          return (ERROR);
  2052.          }
  2053. }
  2054. else
  2055. {
  2056.      DRV_LOG (DRV_DEBUG_TX, "No free Descriptorsn", 0, 0, 0, 0, 0, 0);
  2057.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  2058. /* add by zhangming */
  2059.      if (!(pDrvCtrl->flags & RTL_FLG_POLLING))
  2060.          END_TX_SEM_GIVE (&pDrvCtrl->end);
  2061.         return (ERROR);
  2062.         }
  2063.     /* Flush the write pipe */
  2064.     CACHE_PIPE_FLUSH ();
  2065.     if (!(pDrvCtrl->flags & RTL_FLG_POLLING))
  2066.         END_TX_SEM_GIVE (&pDrvCtrl->end);
  2067.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  2068.     return (OK);
  2069.     }
  2070. /*******************************************************************************
  2071. *
  2072. * rtl81x9RestartSetup - setup memory descriptors and turn on chip
  2073. *
  2074. * Initializes all the shared memory structures and turns on the chip.
  2075. */
  2076. LOCAL STATUS rtl81x9RestartSetup
  2077.     (
  2078.     RTL81X9END_DEVICE *pDrvCtrl
  2079.     )
  2080.     {
  2081.     int  rsize;
  2082.     void *  pTemp;
  2083.     /* reset the device */
  2084.     rtl81x9Reset (pDrvCtrl);
  2085.     /* setup Rx buffer descriptors  - align on 000 boundary */
  2086.     rsize = pDrvCtrl->rringLen;
  2087.     pDrvCtrl->pRring = (RTL_RMD *) ( ( (int)pDrvCtrl->pRring + 7) & ~7);    
  2088.     /* setup the initialization block */
  2089.     pDrvCtrl->ib = (rtl_ib *)pDrvCtrl->pShMem;
  2090.     /* HRTLP */
  2091.     swab ((char *) END_HADDR(&pDrvCtrl->end), pDrvCtrl->ib->rtlIBPadr, 6);
  2092.     CACHE_PIPE_FLUSH ();
  2093.     pTemp = RTL_CACHE_VIRT_TO_PHYS (pDrvCtrl->pRring);   /* point to Rx ring */
  2094.     RTL_ADDR_TO_IB_RMD (pTemp, pDrvCtrl->ib, rsize);
  2095.     /* reconfigure the device */
  2096.     rtl81x9Config (pDrvCtrl);
  2097.     return (OK); 
  2098.     }
  2099.      
  2100. /*******************************************************************************
  2101. *
  2102. * rtl81x9Restart - restart the device after a fatal error
  2103. *
  2104. * This routine takes care of all the messy details of a restart.  The device
  2105. * is reset and re-initialized.  The driver state is re-synchronized.
  2106. */
  2107. LOCAL void rtl81x9Restart
  2108.     (
  2109.     RTL81X9END_DEVICE *pDrvCtrl
  2110.     )
  2111.     {
  2112.     rtl81x9Reset (pDrvCtrl);
  2113.     rtl81x9RestartSetup (pDrvCtrl);
  2114.     /* set the flags to indicate readiness */
  2115.     END_OBJ_READY (&pDrvCtrl->end,
  2116.                     IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
  2117.                     | IFF_MULTICAST);
  2118.     }
  2119. /******************************************************************************
  2120. *
  2121. * rtl81x9Config - reconfigure the interface under us.
  2122. *
  2123. * Reconfigure the interface setting promiscuous mode, and changing the
  2124. * multicast interface list.
  2125. *
  2126. * NOMANUAL
  2127. */
  2128. LOCAL void rtl81x9Config
  2129.     (
  2130.     RTL81X9END_DEVICE *pDrvCtrl
  2131.     )
  2132.     {
  2133.     /* Set promiscuous mode if it's asked for. */
  2134.     if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
  2135.         {
  2136.      DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode on!n", 0, 0, 0, 0, 0, 0);
  2137.         
  2138.         /* chip will be in promiscuous mode */
  2139.         
  2140.         pDrvCtrl->ib->rtlIBMode = 0x8000;
  2141.         }
  2142.     else
  2143.         {
  2144.      /*vicadd DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!n", 0, 0, 0, 0, 0, 0);*/
  2145.         pDrvCtrl->ib->rtlIBMode = 0;
  2146.         }
  2147.     
  2148.     CACHE_PIPE_FLUSH ();
  2149.     /* Set up address filter for multicasting. */
  2150.     if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0)
  2151. {
  2152. rtl81x9AddrFilterSet (pDrvCtrl);
  2153. }
  2154.     }
  2155. /*******************************************************************************
  2156. *
  2157. * rtl81x9Unload - unload a driver from the system
  2158. *
  2159. * This routine deallocates lists, and free allocated memory.
  2160. *
  2161. * RETURNS: OK, always.
  2162. */
  2163. LOCAL STATUS rtl81x9Unload
  2164.     (
  2165.     RTL81X9END_DEVICE * pDrvCtrl
  2166.     )
  2167.     {
  2168.     END_OBJECT_UNLOAD (&pDrvCtrl->end);
  2169.     /* Free the shared DMA memory. */
  2170.     if (pDrvCtrl->flags & RTL_FLG_MEM_ALLOC_FLAG)
  2171. cacheDmaFree (pDrvCtrl->pShMem);
  2172.     return (OK);
  2173.     }
  2174. /*******************************************************************************
  2175. *
  2176. * rtl81x9PollStart - start polled mode operations
  2177. *
  2178. * This function starts polled mode operation.
  2179. *
  2180. * The device interrupts are disabled, the current mode flag is switched
  2181. * to indicate Polled mode and the device is reconfigured.
  2182. *
  2183. * RETURNS: OK or ERROR.
  2184. */
  2185. LOCAL STATUS rtl81x9PollStart
  2186.     (
  2187.     RTL81X9END_DEVICE * pDrvCtrl /* device to be polled */
  2188.     )
  2189.     {
  2190.     int         oldLevel;
  2191.     oldLevel = intLock ();          /* disable ints during update */
  2192.     /* Turn off interrupts */
  2193.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);
  2194.     pDrvCtrl->flags |= RTL_FLG_POLLING;
  2195.     intUnlock (oldLevel);   /* now rtl81x9Int won't get confused */
  2196.     rtl81x9Config (pDrvCtrl); /* reconfigure device */ 
  2197.     return (OK);
  2198.     }
  2199. /*******************************************************************************
  2200. *
  2201. * rtl81x9PollStop - stop polled mode operations
  2202. *
  2203. * This function terminates polled mode operation.  The device returns to
  2204. * interrupt mode.
  2205. *
  2206. * The device interrupts are enabled, the current mode flag is switched
  2207. * to indicate interrupt mode and the device is then reconfigured for
  2208. * interrupt operation.
  2209. *
  2210. * RETURNS: OK or ERROR.
  2211. */
  2212. LOCAL STATUS rtl81x9PollStop
  2213.     (
  2214.     RTL81X9END_DEVICE * pDrvCtrl /* device structure */
  2215.     )
  2216.     {
  2217.     int         oldLevel;
  2218.     oldLevel = intLock ();          /* disable ints during update */
  2219.     rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
  2220.     pDrvCtrl->flags &= ~RTL_FLG_POLLING;
  2221.     intUnlock (oldLevel);   /* now rtl81x981x9Int won't get confused */
  2222.     rtl81x9Config (pDrvCtrl); /* reconfigure device */
  2223.     
  2224.     return (OK);
  2225.     }
  2226. /*******************************************************************************
  2227. *
  2228. * rtl81x9CsrReadByte - read a byte from a given window and register
  2229. *
  2230. * This function reads a byte from a given window and register
  2231. *
  2232. * RETURNS: UCHAR
  2233. */
  2234. LOCAL UCHAR rtl81x9CsrReadByte
  2235.     (
  2236.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2237.     USHORT reg, /* register offset */
  2238.     int window /* window number */
  2239.     )
  2240.     {
  2241.     UCHAR inWord;
  2242.     int  level;
  2243.         /* disable all controller interrupts to prevent race conditions */
  2244.      level = intLock ();
  2245.         /* set the register */
  2246.         SYS_IN_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inWord);
  2247.         /* reenable controller interrupts */
  2248.      intUnlock (level);
  2249.     return (inWord);
  2250.     }
  2251. /*******************************************************************************
  2252. *
  2253. * rtl81x9CsrReadWord - read a word from a given window and register
  2254. *
  2255. * This function reads a word from a given window and register
  2256. *
  2257. * RETURNS: USHORT
  2258. */
  2259. LOCAL USHORT rtl81x9CsrReadWord
  2260.     (
  2261.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2262.     USHORT reg, /* register offset */
  2263.     int window /* window number */
  2264.     )
  2265.     {
  2266.     USHORT inWord;
  2267.     int  level;
  2268.         /* disable all controller interrupts to prevent race conditions */
  2269.      level = intLock ();
  2270.         /* set the register */
  2271.         SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inWord);
  2272.         /* reenable controller interrupts */
  2273.      intUnlock (level);
  2274.     return (inWord);
  2275.     }
  2276. /*******************************************************************************
  2277. *
  2278. * rtl81x9CsrReadLong - read a long from a given window and register
  2279. *
  2280. * This function reads a long from a given window and register
  2281. *
  2282. * RETURNS: USHORT
  2283. */
  2284. LOCAL ULONG rtl81x9CsrReadLong
  2285.     (
  2286.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2287.     USHORT reg, /* register offset */
  2288.     int window /* window number */
  2289.     )
  2290.     {
  2291.     ULONG inWord;
  2292.     int  level;
  2293.         /* disable all controller interrupts to prevent race conditions */
  2294.      level = intLock ();
  2295.         /* set the register */
  2296.         SYS_IN_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inWord);
  2297.         /* reenable controller interrupts */
  2298.      intUnlock (level);
  2299.     return (inWord);
  2300.     }
  2301. /*******************************************************************************
  2302. *
  2303. * rtl81x9CsrWriteByte - write a byte to a given window and register
  2304. *
  2305. * This function writes a byte to a given window and register
  2306. *
  2307. * RETURNS: N/A
  2308. */
  2309. LOCAL void rtl81x9CsrWriteByte
  2310.     (
  2311.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2312.     USHORT reg, /* register offset */
  2313.     UCHAR outByte, /* byte to be written */
  2314.     int window /* window number */
  2315.     )
  2316.     {
  2317.     int  level;
  2318.      level = intLock ();
  2319.  
  2320.         /* set the register */
  2321.         SYS_OUT_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outByte);
  2322.         /* reenable interrupts */
  2323.      intUnlock (level);
  2324.     }
  2325. /*******************************************************************************
  2326. *
  2327. * rtl81x9CsrWriteWord - write a word to a given window and register
  2328. *
  2329. * This function writes a word to a given window and register
  2330. *
  2331. * RETURNS: N/A
  2332. */
  2333. LOCAL void rtl81x9CsrWriteWord
  2334.     (
  2335.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2336.     USHORT reg, /* register offset */
  2337.     USHORT outWord, /* word to be written */
  2338.     int window /* window number */
  2339.     )
  2340.     {
  2341.     int  level;
  2342.         /* disable interrupts to prevent race conditions */
  2343.      level = intLock ();
  2344.         /* set the register */
  2345.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outWord);
  2346.         /* reenable interrupts */
  2347.      intUnlock (level);
  2348. }
  2349. /*******************************************************************************
  2350. *
  2351. * rtl81x9CsrWriteLong - write a long to a given window and register
  2352. *
  2353. * This function writes a long to a given window and register
  2354. *
  2355. * RETURNS: N/A
  2356. */
  2357. LOCAL void rtl81x9CsrWriteLong
  2358.     (
  2359.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2360.     USHORT reg, /* register offset */
  2361.     ULONG outLong, /* long word to be written */
  2362.     int window /* window number */
  2363.     )
  2364.     {
  2365.     int  level;
  2366.     /* disable interrupts to prevent race conditions */
  2367.     level = intLock ();
  2368.     /* set the register */
  2369.     SYS_OUT_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32) reg), outLong);
  2370.     /* reenable interrupts */
  2371.     intUnlock (level);
  2372.     }
  2373. #if 0
  2374. /*******************************************************************************
  2375. *
  2376. * rtl81x9ReadEEPROM - read a value from the EEPROM
  2377. *
  2378. * This function reads a sequence of words from the EEPROM at the address passed in the params
  2379. *
  2380. * RETURNS: N/A
  2381. */
  2382. LOCAL void rtl81x9ReadEEPROM
  2383.     (
  2384.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2385.     UCHAR *dest,
  2386.     ULONG off,
  2387.     ULONG cnt,
  2388.     ULONG swap
  2389.     )
  2390. {
  2391. int i;
  2392. USHORT word = 0, *ptr;
  2393. for (i = 0; i < cnt; i++) 
  2394. {
  2395. rtl81x9EEPROMGetWord(pDrvCtrl, off + i, &word);
  2396. ptr = (USHORT *)(dest + (i * 2));
  2397. if (swap)
  2398. *ptr = ntohs(word);
  2399. else
  2400. *ptr = word;
  2401. }
  2402. return;
  2403. }
  2404. /*******************************************************************************
  2405. *
  2406. * rtl81x9EEPROMGetWord - read a value from the EEPROM
  2407. *
  2408. * Read a word of data stored in the EEPROM at address 'addr.'
  2409. *
  2410. * RETURNS: N/A
  2411. */
  2412. LOCAL void rtl81x9EEPROMGetWord
  2413.     (
  2414.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2415. ULONG addr,
  2416. USHORT *dest
  2417.     )
  2418. {
  2419. register int i;
  2420. USHORT word = 0;
  2421. /* Enter EEPROM access mode. */
  2422. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_PROGRAM|RTL_EE_SEL, RTL_WIN_0);
  2423. /*
  2424.  * Send address of word we want to read.
  2425.  */
  2426. rtl81x9EEPROMPutByte (pDrvCtrl, addr);
  2427. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_PROGRAM|RTL_EE_SEL, RTL_WIN_0);
  2428. /*
  2429.  * Start reading bits from EEPROM.
  2430.  */
  2431. for (i = 0x8000; i; i >>= 1) {
  2432. EE_SET(RTL_EE_CLK);
  2433. SYS_DELAY(100);
  2434. if (rtl81x9CsrReadByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_WIN_0) & RTL_EE_DATAOUT)
  2435. word |= i;
  2436. EE_CLR(RTL_EE_CLK);
  2437. SYS_DELAY(100);
  2438. }
  2439. /* Turn off EEPROM access mode. */
  2440. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_OFF, RTL_WIN_0);
  2441. *dest = word;
  2442. return;
  2443. }
  2444. /*******************************************************************************
  2445. *
  2446. * rtl81x9EEPROMPutByte - read a value from the EEPROM
  2447. *
  2448. * Send a read command and address to the EEPROM, check for ACK
  2449. *
  2450. * RETURNS: N/A
  2451. */
  2452. LOCAL void rtl81x9EEPROMPutByte
  2453.     (
  2454.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2455. ULONG addr
  2456.     )
  2457. {
  2458. register int d, i;
  2459. d = addr | RTL_EECMD_READ;
  2460. /*
  2461.  * Feed in each bit and stobe the clock.
  2462.  */
  2463. for (i = 0x400; i; i >>= 1) {
  2464. if (d & i) {
  2465. EE_SET(RTL_EE_DATAIN);
  2466. } else {
  2467. EE_CLR(RTL_EE_DATAIN);
  2468. }
  2469. SYS_DELAY(100);
  2470. EE_SET(RTL_EE_CLK);
  2471. SYS_DELAY(150);
  2472. EE_CLR(RTL_EE_CLK);
  2473. SYS_DELAY(100);
  2474. }
  2475. return;
  2476. }
  2477. #endif
  2478. /*******************************************************************************
  2479. *
  2480. * rtl81x9MII_sync - Sync the PHY's
  2481. *
  2482.  * Sync the PHYs by setting data bit and strobing the clock 32 times.
  2483. *
  2484. * RETURNS: N/A
  2485. */
  2486. LOCAL void rtl81x9MII_sync
  2487.     (
  2488.     RTL81X9END_DEVICE *  pDrvCtrl /* device control structure */
  2489.     )
  2490. {
  2491. register int i;
  2492. MII_SET(RTL_MII_DIR|RTL_MII_DATAOUT);
  2493. for (i = 0; i < 32; i++) {
  2494. MII_SET(RTL_MII_CLK);
  2495. SYS_DELAY(100);
  2496. MII_CLR(RTL_MII_CLK);
  2497. SYS_DELAY(100);
  2498. }
  2499. return;
  2500. }
  2501. /*******************************************************************************
  2502. *
  2503. * rtl81x9MII_send
  2504. *
  2505. * Clock a series of bits through the MII.
  2506. *
  2507. * RETURNS: N/A
  2508. */
  2509. LOCAL void rtl81x9MII_send
  2510.     (
  2511.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2512. ULONG bits,
  2513. int cnt
  2514.     )
  2515. {
  2516. int i;
  2517. MII_CLR(RTL_MII_CLK);
  2518. for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
  2519.                 if (bits & i) {
  2520. MII_SET(RTL_MII_DATAOUT);
  2521.                 } else {
  2522. MII_CLR(RTL_MII_DATAOUT);
  2523.                 }
  2524. SYS_DELAY(100);
  2525. MII_CLR(RTL_MII_CLK);
  2526. SYS_DELAY(100);
  2527. MII_SET(RTL_MII_CLK);
  2528. }
  2529. }
  2530. /*******************************************************************************
  2531. *
  2532. * rtl81x9MII_readreg
  2533. *
  2534. * Read an PHY register through the MII.
  2535. *
  2536. * RETURNS: N/A
  2537. */
  2538. LOCAL int rtl81x9MII_readreg 
  2539. (
  2540.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2541. RTL_MII_FRAME * frame
  2542. )
  2543. {
  2544. int i, ack, s;
  2545. s = splimp();
  2546. /*
  2547.  * Set up frame for RX.
  2548.  */
  2549. frame->mii_stdelim = RTL_MII_STARTDELIM;
  2550. frame->mii_opcode = RTL_MII_READOP;
  2551. frame->mii_turnaround = 0;
  2552. frame->mii_data = 0;
  2553. rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_MII, 0, RTL_WIN_0);
  2554. /*
  2555.    * Turn on data xmit.
  2556.  */
  2557. MII_SET(RTL_MII_DIR);
  2558. rtl81x9MII_sync(pDrvCtrl);
  2559. /*
  2560.  * Send command/address info.
  2561.  */
  2562. rtl81x9MII_send(pDrvCtrl, frame->mii_stdelim, 2);
  2563. rtl81x9MII_send(pDrvCtrl, frame->mii_opcode,  2);
  2564. rtl81x9MII_send(pDrvCtrl, frame->mii_phyaddr, 5);
  2565. rtl81x9MII_send(pDrvCtrl, frame->mii_regaddr, 5);
  2566. /* Idle bit */
  2567. MII_CLR((RTL_MII_CLK|RTL_MII_DATAOUT));
  2568. SYS_DELAY(100);
  2569. MII_SET(RTL_MII_CLK);
  2570. SYS_DELAY(100);
  2571. /* Turn off xmit. */
  2572. MII_CLR(RTL_MII_DIR);
  2573. /* Check for ack */
  2574. MII_CLR(RTL_MII_CLK);
  2575. SYS_DELAY(100);
  2576. MII_SET(RTL_MII_CLK);
  2577. SYS_DELAY(100);
  2578. ack = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_MII, RTL_WIN_0) & RTL_MII_DATAIN;
  2579. /*
  2580.  * Now try reading data bits. If the ack failed, we still
  2581.  * need to clock through 16 cycles to keep the PHY(s) in sync.
  2582.  */
  2583. if (ack) {
  2584. for(i = 0; i < 16; i++) {
  2585. MII_CLR(RTL_MII_CLK);
  2586. SYS_DELAY(100);
  2587. MII_SET(RTL_MII_CLK);
  2588. SYS_DELAY(100);
  2589. }
  2590. goto fail;
  2591. }
  2592. for (i = 0x8000; i; i >>= 1) {
  2593. MII_CLR(RTL_MII_CLK);
  2594. SYS_DELAY(100);
  2595. if (!ack) {
  2596. if (rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_MII, RTL_WIN_0) & RTL_MII_DATAIN)
  2597. frame->mii_data |= i;
  2598. SYS_DELAY(100);
  2599. }
  2600. MII_SET(RTL_MII_CLK);
  2601. SYS_DELAY(100);
  2602. }
  2603. fail:
  2604. MII_CLR(RTL_MII_CLK);
  2605. SYS_DELAY(100);
  2606. MII_SET(RTL_MII_CLK);
  2607. SYS_DELAY(100);
  2608. splx(s);
  2609. if (ack)
  2610. return(1);
  2611. return(0);
  2612. }
  2613. /*******************************************************************************
  2614. *
  2615. * rtl81x9MII_writereg
  2616. *
  2617. * Write an PHY register through the MII.
  2618. *
  2619. * RETURNS: N/A
  2620. */
  2621. LOCAL int rtl81x9MII_writereg 
  2622. (
  2623.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2624. RTL_MII_FRAME * frame
  2625. )
  2626. {
  2627. int s;
  2628. s = splimp();
  2629. /*
  2630.  * Set up frame for TX.
  2631.  */
  2632. frame->mii_stdelim = RTL_MII_STARTDELIM;
  2633. frame->mii_opcode = RTL_MII_WRITEOP;
  2634. frame->mii_turnaround = RTL_MII_TURNAROUND;
  2635. /*
  2636.    * Turn on data output.
  2637.  */
  2638. MII_SET(RTL_MII_DIR);
  2639. rtl81x9MII_sync(pDrvCtrl);
  2640. rtl81x9MII_send(pDrvCtrl, frame->mii_stdelim, 2);
  2641. rtl81x9MII_send(pDrvCtrl, frame->mii_opcode, 2);
  2642. rtl81x9MII_send(pDrvCtrl, frame->mii_phyaddr, 5);
  2643. rtl81x9MII_send(pDrvCtrl, frame->mii_regaddr, 5);
  2644. rtl81x9MII_send(pDrvCtrl, frame->mii_turnaround, 2);
  2645. rtl81x9MII_send(pDrvCtrl, frame->mii_data, 16);
  2646. /* Idle bit. */
  2647. MII_SET(RTL_MII_CLK);
  2648. SYS_DELAY(100);
  2649. MII_CLR(RTL_MII_CLK);
  2650. SYS_DELAY(100);
  2651. /*
  2652.  * Turn off xmit.
  2653.  */
  2654. MII_CLR(RTL_MII_DIR);
  2655. splx(s);
  2656. return(0);
  2657. }
  2658. /*******************************************************************************
  2659. *
  2660. * rtl81x9Phy_readreg
  2661. *
  2662. * Read an PHY register.
  2663. *
  2664. * RETURNS: N/A
  2665. */
  2666. LOCAL USHORT rtl81x9Phy_readreg 
  2667. (
  2668.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2669. int reg
  2670. )
  2671. {
  2672. RTL_MII_FRAME frame;
  2673. USHORT rval = 0;
  2674. USHORT rtl8139_reg = 0;
  2675. if ((pDrvCtrl->devType == RTL_DEV_8139A) || (pDrvCtrl->devType == RTL_DEV_8139B)) 
  2676. {
  2677. switch(reg) {
  2678. case RTL_PHY_BMCR:
  2679. rtl8139_reg = RTL_REGS_MII_BMCR;
  2680. break;
  2681. case RTL_PHY_BMSR:
  2682. rtl8139_reg = RTL_REGS_MII_BMSR;
  2683. break;
  2684. case RTL_PHY_ANAR:
  2685. rtl8139_reg = RTL_REGS_NWAY_ADVERT;
  2686. break;
  2687. case RTL_PHY_LPAR:
  2688. rtl8139_reg = RTL_REGS_NWAY_LPAR;
  2689. break;
  2690. default:
  2691. DRV_LOG (DRV_DEBUG_LOAD, "rl%d: bad phy registern", pDrvCtrl->unit, 0, 0, 0, 0, 0);
  2692. return(0);
  2693. }
  2694. rval = rtl81x9CsrReadWord(pDrvCtrl, rtl8139_reg, RTL_WIN_0);
  2695. return (rval);
  2696. }
  2697. bzero((char *)&frame, sizeof(frame));
  2698. frame.mii_phyaddr = pDrvCtrl->phy_addr;
  2699. frame.mii_regaddr = reg;
  2700. rtl81x9MII_readreg(pDrvCtrl, &frame);
  2701. return(frame.mii_data);
  2702. }
  2703. /*******************************************************************************
  2704. *
  2705. * rtl81x9Phy_writereg
  2706. *
  2707. * Read an PHY register.
  2708. *
  2709. * RETURNS: N/A
  2710. */
  2711. LOCAL void rtl81x9Phy_writereg 
  2712. (
  2713.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2714. int reg,
  2715. int data
  2716. )
  2717. {
  2718. RTL_MII_FRAME frame;
  2719. USHORT rtl8139_reg = 0;
  2720. if ((pDrvCtrl->devType == RTL_DEV_8139A) || (pDrvCtrl->devType == RTL_DEV_8139B)) 
  2721. {
  2722. switch(reg) {
  2723. case RTL_PHY_BMCR:
  2724. rtl8139_reg = RTL_REGS_MII_BMCR;
  2725. break;
  2726. case RTL_PHY_BMSR:
  2727. rtl8139_reg = RTL_REGS_MII_BMSR;
  2728. break;
  2729. case RTL_PHY_ANAR:
  2730. rtl8139_reg = RTL_REGS_NWAY_ADVERT;
  2731. break;
  2732. case RTL_PHY_LPAR:
  2733. rtl8139_reg = RTL_REGS_NWAY_LPAR;
  2734. break;
  2735. default:
  2736. DRV_LOG (DRV_DEBUG_LOAD, "rtl%d: bad phy registern", pDrvCtrl->devType, 0, 0, 0, 0, 0);
  2737. return;
  2738. }
  2739.   rtl81x9CsrWriteWord (pDrvCtrl, rtl8139_reg, data, RTL_WIN_0);
  2740. return;
  2741. }
  2742. bzero((char *)&frame, sizeof(frame));
  2743. frame.mii_phyaddr = pDrvCtrl->phy_addr;
  2744. frame.mii_regaddr = reg;
  2745. frame.mii_data = data;
  2746. rtl81x9MII_writereg(pDrvCtrl, &frame);
  2747. return;
  2748. }
  2749. /*******************************************************************************
  2750. *
  2751. * rtl81x9AutoNegTx
  2752. *
  2753. * Initiate an autonegotiation session.
  2754. *
  2755. * RETURNS: N/A
  2756. */
  2757. LOCAL void rtl81x9AutoNegTx 
  2758. (
  2759.     RTL81X9END_DEVICE *  pDrvCtrl /* device control structure */
  2760. )
  2761. {
  2762. USHORT phy_sts;
  2763. rtl81x9Phy_writereg (pDrvCtrl, RTL_PHY_BMCR, RTL_PHY_BMCR_RESET);
  2764. SYS_DELAY(50000);
  2765. while(rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_BMCR)
  2766. & RTL_PHY_BMCR_RESET);
  2767. phy_sts = rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_BMCR);
  2768. phy_sts |= RTL_PHY_BMCR_AUTONEGENBL|RTL_PHY_BMCR_AUTONEGRSTR;
  2769. rtl81x9Phy_writereg(pDrvCtrl, RTL_PHY_BMCR, phy_sts);
  2770. SYS_DELAY(50000);
  2771. return;
  2772. }
  2773. /*******************************************************************************
  2774. *
  2775. * rtl81x9MII_autoneg
  2776. *
  2777. * Invoke autonegotiation on a PHY. Also used with the 8139 internal
  2778. * transceiver.
  2779. *
  2780. * RETURNS: N/A
  2781. */
  2782. LOCAL int rtl81x9MII_autoneg 
  2783. (
  2784.     RTL81X9END_DEVICE *  pDrvCtrl /* device control structure */
  2785. )
  2786. {
  2787.     UINT16 phyStatus = 0;
  2788.     UINT16 media;
  2789.     UINT16 advert;
  2790.     UINT16 ability;
  2791. int speed = 10000000;
  2792. /*
  2793.  * The 100baseT4 PHY sometimes has the 'autoneg supported'
  2794.  * bit cleared in the status register, but has the 'autoneg enabled'
  2795.  * bit set in the control register. This is a contradiction, and
  2796.  * I'm not sure how to handle it. If you want to force an attempt
  2797.  * to autoneg for 100baseT4 PHYs, #define FORCE_AUTONEG_TFOUR
  2798.  * and see what happens.
  2799.  */
  2800. #ifndef FORCE_AUTONEG_TFOUR
  2801. /*
  2802.  * First, see if autoneg is supported. If not, there's
  2803.  * no point in continuing.
  2804.  */
  2805. phyStatus = rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_BMSR);
  2806. if (!(phyStatus & RTL_PHY_BMSR_CANAUTONEG)) {
  2807.         DRV_LOG (DRV_DEBUG_LOAD,"rtl%d: autonegotiation not supportedn",
  2808.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  2809.         media = rtl81x9Phy_readreg (pDrvCtrl, RTL_PHY_BMCR);
  2810.         media &= ~RTL_PHY_BMCR_SPEEDSEL;
  2811.         media &= ~RTL_PHY_BMCR_DUPLEX;
  2812.         rtl81x9Phy_writereg (pDrvCtrl, RTL_PHY_BMCR, media);
  2813. return speed;
  2814. }
  2815. #endif
  2816. rtl81x9AutoNegTx (pDrvCtrl);
  2817. SYS_DELAY (50000000);
  2818. if (rtl81x9Phy_readreg (pDrvCtrl, RTL_PHY_BMSR) & RTL_PHY_BMSR_AUTONEGCOMP) 
  2819. {
  2820. DRV_LOG (DRV_DEBUG_LOAD, "rtl%d: autoneg complete, n", pDrvCtrl->unit, 0, 0, 0, 0, 0);
  2821. phyStatus = rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_BMSR);
  2822. else 
  2823. {
  2824. DRV_LOG (DRV_DEBUG_LOAD, "rtl%d: autoneg not complete, n", pDrvCtrl->unit, 0, 0, 0, 0, 0);
  2825. }
  2826. media = rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_BMCR);
  2827. /* Link is good. Report modes and set duplex mode. */
  2828. if (rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_BMSR) & RTL_PHY_BMSR_LINKSTAT) 
  2829. {
  2830. DRV_LOG (DRV_DEBUG_LOAD, "link status good ", 0, 0, 0, 0, 0, 0);
  2831. advert = rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_ANAR);
  2832. ability = rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_LPAR);
  2833. if (advert & RTL_PHY_ANAR_100BT4 && ability & RTL_PHY_ANAR_100BT4) 
  2834. {
  2835. media |= RTL_PHY_BMCR_SPEEDSEL;
  2836. media &= ~RTL_PHY_BMCR_DUPLEX;
  2837. DRV_LOG (DRV_DEBUG_LOAD, "(100baseT4)n", 0, 0, 0, 0, 0, 0);
  2838. speed = 100000000;
  2839. else if (advert & RTL_PHY_ANAR_100BTXFULL &&
  2840. ability & RTL_PHY_ANAR_100BTXFULL) 
  2841. {
  2842. media |= RTL_PHY_BMCR_SPEEDSEL;
  2843. media |= RTL_PHY_BMCR_DUPLEX;
  2844. DRV_LOG (DRV_DEBUG_LOAD, "(full-duplex, 100Mbps)n", 0, 0, 0, 0, 0, 0);
  2845. speed = 100000000;
  2846. else if (advert & RTL_PHY_ANAR_100BTXHALF &&
  2847. ability & RTL_PHY_ANAR_100BTXHALF) 
  2848. {
  2849. media |= RTL_PHY_BMCR_SPEEDSEL;
  2850. media &= ~RTL_PHY_BMCR_DUPLEX;
  2851. DRV_LOG (DRV_DEBUG_LOAD, "(half-duplex, 100Mbps)n", 0, 0, 0, 0, 0, 0);
  2852. speed = 100000000;
  2853. else if (advert & RTL_PHY_ANAR_10BTFULL &&
  2854. ability & RTL_PHY_ANAR_10BTFULL) 
  2855. {
  2856. media &= ~RTL_PHY_BMCR_SPEEDSEL;
  2857. media |= RTL_PHY_BMCR_DUPLEX;
  2858. DRV_LOG (DRV_DEBUG_LOAD, "(full-duplex, 10Mbps)n", 0, 0, 0, 0, 0, 0);
  2859. speed = 10000000;
  2860. else 
  2861. {
  2862. media &= ~RTL_PHY_BMCR_SPEEDSEL;
  2863. media &= ~RTL_PHY_BMCR_DUPLEX;
  2864. DRV_LOG (DRV_DEBUG_LOAD, "(half-duplex, 10Mbps)n", 0, 0, 0, 0, 0, 0);
  2865. speed = 10000000;
  2866. }
  2867. /* Set ASIC's duplex mode to match the PHY. */
  2868. rtl81x9Phy_writereg(pDrvCtrl, RTL_PHY_BMCR, media);
  2869. else 
  2870. {
  2871. DRV_LOG (DRV_DEBUG_LOAD, "no carriern", 0, 0, 0, 0, 0, 0);
  2872.         media &= ~RTL_PHY_BMCR_SPEEDSEL;
  2873.         media &= ~RTL_PHY_BMCR_DUPLEX;
  2874.         rtl81x9Phy_writereg (pDrvCtrl, RTL_PHY_BMCR, media);
  2875. }
  2876. return speed;
  2877. }
  2878. /*******************************************************************************
  2879. *
  2880. * rtl81x9MediaSet
  2881. *
  2882. * Set speed and duplex mode.
  2883. *
  2884. * RETURNS: N/A
  2885. */
  2886. LOCAL int rtl81x9MediaSet 
  2887. (
  2888.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  2889. int media
  2890. )
  2891. {
  2892. USHORT bmcr;
  2893. USHORT bmsr;
  2894.     int speed = 10000000;
  2895. /*DRV_LOG (DRV_DEBUG_LOAD, "rl%d: selecting MII, ", pDrvCtrl->unit, 0, 0, 0, 0, 0);*/
  2896. bmsr = rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_BMSR);
  2897. bmcr = rtl81x9Phy_readreg(pDrvCtrl, RTL_PHY_BMCR);
  2898. bmcr &= ~(RTL_PHY_BMCR_AUTONEGENBL|RTL_PHY_BMCR_SPEEDSEL|
  2899. RTL_PHY_BMCR_DUPLEX|RTL_PHY_BMCR_LOOPBK);
  2900.   /*  DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: PHY status word: %xn", pDrvCtrl->unit,
  2901.              bmsr, 3, 4, 5, 6);*/
  2902.     if (bmsr & RTL_PHY_BMSR_CANAUTONEG)
  2903.         {
  2904.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autoneg supportedn",
  2905.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  2906.         speed = 0;
  2907. return TRUE;
  2908. }
  2909.     if (bmsr & RTL_PHY_BMSR_10BTHALF)
  2910.         {
  2911.         DRV_LOG (DRV_DEBUG_LOAD,"rtl81x9%d: 10Mbps half-duplex mode supportedn",
  2912.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  2913. if (IFM_SUBTYPE(media) == IFM_10_T) 
  2914. {
  2915. DRV_LOG (DRV_DEBUG_LOAD, "10Mbps, ", 0, 0, 0, 0, 0, 0);
  2916. bmcr &= ~RTL_PHY_BMCR_SPEEDSEL;
  2917. }
  2918. }
  2919.     if (bmsr & RTL_PHY_BMSR_10BTFULL)
  2920.         {
  2921.         DRV_LOG (DRV_DEBUG_LOAD,"rtl81x9%d: 10Mbps full-duplex mode supportedn",
  2922.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  2923. if (IFM_SUBTYPE(media) == IFM_10_T) 
  2924. {
  2925. DRV_LOG (DRV_DEBUG_LOAD, "10Mbps, ", 0, 0, 0, 0, 0, 0);
  2926. bmcr &= ~RTL_PHY_BMCR_SPEEDSEL;
  2927. }
  2928. }
  2929.     if (bmsr & RTL_PHY_BMSR_100BTXHALF)
  2930.         {
  2931.         DRV_LOG (DRV_DEBUG_LOAD,"rtl81x9%d:100Mbps half-duplex mode supportedn",
  2932.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  2933.         speed = 100000000;
  2934. if (IFM_SUBTYPE(media) == IFM_100_TX) 
  2935. {
  2936. DRV_LOG (DRV_DEBUG_LOAD, "100Mbps, ", 0, 0, 0, 0, 0, 0);
  2937. bmcr |= RTL_PHY_BMCR_SPEEDSEL;
  2938. }
  2939. }
  2940.     if (bmsr & RTL_PHY_BMSR_100BTXFULL)
  2941.         {
  2942.         DRV_LOG (DRV_DEBUG_LOAD,"rtl81x9%d:100Mbps full-duplex mode supportedn",
  2943.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  2944.         speed = 100000000;
  2945. if (IFM_SUBTYPE(media) == IFM_100_TX) 
  2946. {
  2947. DRV_LOG (DRV_DEBUG_LOAD, "100Mbps, ", 0, 0, 0, 0, 0, 0);
  2948. bmcr |= RTL_PHY_BMCR_SPEEDSEL;
  2949. }
  2950. }
  2951.     /* Some also support 100BaseT4 */
  2952.     if (bmsr & RTL_PHY_BMSR_100BT4)
  2953.         {
  2954.         DRV_LOG (DRV_DEBUG_LOAD,"rtl81x9%d:100baseT4 mode supportedn",
  2955.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  2956.         speed = 100000000;
  2957. #ifdef FORCE_AUTONEG_TFOUR
  2958.         DRV_LOG (DRV_DEBUG_LOAD,"rtl81x9%d:force on autoneg support for BT4n",
  2959.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  2960. #endif
  2961. if (IFM_SUBTYPE(media) == IFM_100_T4) 
  2962. {
  2963. DRV_LOG (DRV_DEBUG_LOAD, "100Mbps/T4, half-duplexn", 0, 0, 0, 0, 0, 0);
  2964. bmcr |= RTL_PHY_BMCR_SPEEDSEL;
  2965. bmcr &= ~RTL_PHY_BMCR_DUPLEX;
  2966. }
  2967. }
  2968. if ((media & IFM_GMASK) == IFM_FDX) 
  2969. {
  2970. DRV_LOG (DRV_DEBUG_LOAD, "full duplexn", 0, 0, 0, 0, 0, 0);
  2971. bmcr |= RTL_PHY_BMCR_DUPLEX;
  2972. else 
  2973. {
  2974. DRV_LOG (DRV_DEBUG_LOAD, "half duplexn", 0, 0, 0, 0, 0, 0);
  2975. bmcr &= ~RTL_PHY_BMCR_DUPLEX;
  2976. }
  2977. rtl81x9Phy_writereg(pDrvCtrl, RTL_PHY_BMCR, bmcr);
  2978. return speed;
  2979. }
  2980. /*******************************************************************************
  2981. *
  2982. * rtl81x9MediaConfig - configure the media and do auto negotiation
  2983. *
  2984. * This function configures the media and does the auto negotioation.
  2985. *
  2986. * RETURNS: speed or 0
  2987. *
  2988. */
  2989. LOCAL int rtl81x9MediaConfig
  2990.     (
  2991.     RTL81X9END_DEVICE *  pDrvCtrl /* device control structure */
  2992.     )
  2993.     {
  2994. int speed;
  2995. if ((speed = rtl81x9MediaSet (pDrvCtrl, IFM_10_T)) == 0)
  2996. rtl81x9MII_autoneg (pDrvCtrl);
  2997.     return (speed);
  2998.     }
  2999. /*******************************************************************************
  3000. *
  3001. * rtl81x9EEPROMInit - Initialize EEPROM values
  3002. *
  3003. * RETURNS: N/A
  3004. *
  3005. * Added by ZhangShichao
  3006. */
  3007. LOCAL void rtl81x9EEPROMInit
  3008.     (
  3009.     RTL81X9END_DEVICE *  pDrvCtrl /* device control structure */
  3010.     )
  3011. {
  3012. register int i;
  3013. USHORT *initTable;
  3014. USHORT readout;
  3015. char *tempStr="";
  3016. #if 1
  3017. /* Enter EEPROM access mode. */
  3018. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_PROGRAM|RTL_EE_SEL, RTL_WIN_0);
  3019. /*Enable write/erase of EEPROM*/
  3020. rtl81x9EEPROMPutByte(pDrvCtrl, 0, RTL_EECMD_EWEN);
  3021. /* Turn off EEPROM access mode. */
  3022. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_OFF, RTL_WIN_0);
  3023. /*the EEPROM is organized in x16 mode, so we manipulate in USHORT*/
  3024. initTable = (USHORT*) EEPROM_Init;
  3025. for(i=0; i<EEPROM_INIT_SIZE; i++)
  3026. {
  3027. printf("Writing a word...");
  3028. rtl81x9EEPROMWriteWord(pDrvCtrl, i, *(initTable++));
  3029. /*Wait 10ms for EEPROM programming to be finished*/
  3030. SYS_DELAY(100000);
  3031. printf("done.rn");
  3032. }
  3033. #endif
  3034. printf("rnEEPROM contents: rn");
  3035. for(i=0; i<64; i++)
  3036. {
  3037. rtl81x9EEPROMGetWord(pDrvCtrl, i, &readout);
  3038. printf("%04x ", readout);
  3039. }
  3040. #if 1
  3041. /* Enter EEPROM access mode. */
  3042. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_PROGRAM|RTL_EE_SEL, RTL_WIN_0);
  3043. /*Disable write/erase of EEPROM*/
  3044. rtl81x9EEPROMPutByte(pDrvCtrl, 0, RTL_EECMD_EWDS);
  3045. /* Turn off EEPROM access mode. */
  3046. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_AUTOLOAD, RTL_WIN_0);
  3047. #endif
  3048. return;
  3049. }
  3050. /*******************************************************************************
  3051. *
  3052. * rtl81x9ReadEEPROM - read a value from the EEPROM
  3053. *
  3054. * This function reads a sequence of words from the EEPROM at the address passed in the params
  3055. *
  3056. * RETURNS: N/A
  3057. */
  3058. LOCAL void rtl81x9ReadEEPROM
  3059.     (
  3060.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  3061.     UCHAR *dest,
  3062.     ULONG off,
  3063.     ULONG cnt,
  3064.     ULONG swap
  3065.     )
  3066. {
  3067. ULONG i;
  3068. USHORT word = 0, *ptr;
  3069. for (i = 0; i < cnt; i++) 
  3070. {
  3071. rtl81x9EEPROMGetWord(pDrvCtrl, off + i, &word);
  3072. ptr = (USHORT *)(dest + (i * 2));
  3073. if (swap)
  3074. *ptr = ntohs(word);
  3075. else
  3076. *ptr = word;
  3077. }
  3078. return;
  3079. }
  3080. /*******************************************************************************
  3081. *
  3082. * rtl81x9EEPROMWriteWord - write a value to the EEPROM
  3083. *
  3084. * Store a word of data in the EEPROM at address 'addr.'
  3085. *
  3086. * RETURNS: N/A
  3087. *
  3088. * Added by zhangming
  3089. */
  3090. LOCAL void rtl81x9EEPROMWriteWord
  3091.     (
  3092.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  3093. ULONG addr,
  3094. USHORT data
  3095.     )
  3096. {
  3097. register int i;
  3098. /* Enter EEPROM access mode. */
  3099. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_PROGRAM|RTL_EE_SEL, RTL_WIN_0);
  3100. /*
  3101.  * Send address of word we want to write.
  3102.  */
  3103. rtl81x9EEPROMPutByte (pDrvCtrl, addr, RTL_EECMD_WRITE);
  3104. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_PROGRAM|RTL_EE_SEL, RTL_WIN_0);
  3105. /*
  3106.  * Start reading bits from EEPROM.
  3107.  */
  3108. for (i = 0x8000; i; i >>= 1)
  3109. {
  3110. if (data & i) {
  3111. EE_SET(RTL_EE_DATAIN);
  3112. } else {
  3113. EE_CLR(RTL_EE_DATAIN);
  3114. }
  3115. SYS_DELAY(100);
  3116. EE_SET(RTL_EE_CLK);
  3117. SYS_DELAY(150);
  3118. EE_CLR(RTL_EE_CLK);
  3119. SYS_DELAY(100);
  3120. }
  3121. /* Turn off EEPROM access mode. */
  3122. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_OFF, RTL_WIN_0);
  3123. return;
  3124. }
  3125. /*******************************************************************************
  3126. *
  3127. * rtl81x9EEPROMGetWord - read a value from the EEPROM
  3128. *
  3129. * Read a word of data stored in the EEPROM at address 'addr.'
  3130. *
  3131. * RETURNS: N/A
  3132. */
  3133. LOCAL void rtl81x9EEPROMGetWord
  3134.     (
  3135.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  3136. ULONG addr,
  3137. USHORT *dest
  3138.     )
  3139. {
  3140. register int i;
  3141. USHORT word = 0;
  3142. /* Enter EEPROM access mode. */
  3143. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_PROGRAM|RTL_EE_SEL, RTL_WIN_0);
  3144. /*
  3145.  * Send address of word we want to read.
  3146.  */
  3147. /* rtl81x9EEPROMPutByte (pDrvCtrl, addr); */
  3148. /*  by zhangming */
  3149. rtl81x9EEPROMPutByte (pDrvCtrl, addr, RTL_EECMD_READ);
  3150. rtl81x9CsrWriteByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_PROGRAM|RTL_EE_SEL, RTL_WIN_0);
  3151. /*
  3152.  * Start reading bits from EEPROM.
  3153.  */
  3154. for (i = 0x8000; i; i >>= 1) {
  3155. EE_SET(RTL_EE_CLK);
  3156. SYS_DELAY(100);
  3157. if (rtl81x9CsrReadByte (pDrvCtrl, RTL_REGS_CFG_9346, RTL_WIN_0) & RTL_EE_DATAOUT)
  3158. word |= i;
  3159. EE_CLR(RTL_EE_CLK);
  3160. SYS_DELAY(100);
  3161. }
  3162. /* Turn off EEPROM access mode. */
  3163. rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CFG_9346, RTL_EEMODE_OFF, RTL_WIN_0);
  3164. *dest = word;
  3165. return;
  3166. }
  3167. /*******************************************************************************
  3168. *
  3169. * rtl81x9EEPROMPutByte - read a value from the EEPROM
  3170. *
  3171. * Send a read command and address to the EEPROM, check for ACK
  3172. *
  3173. * RETURNS: N/A
  3174. */
  3175. LOCAL void rtl81x9EEPROMPutByte
  3176.     (
  3177.     RTL81X9END_DEVICE *  pDrvCtrl, /* device control structure */
  3178. ULONG addr,
  3179. USHORT cmd /*added by zhangming */
  3180.     )
  3181. {
  3182. register int d, i;
  3183. /* d = addr | RTL_EECMD_READ; */
  3184. d = addr | cmd;
  3185. /*
  3186.  * Feed in each bit and stobe the clock.
  3187.  */
  3188. for (i = 0x400; i; i >>= 1) {
  3189. if (d & i) {
  3190. EE_SET(RTL_EE_DATAIN);
  3191. } else {
  3192. EE_CLR(RTL_EE_DATAIN);
  3193. }
  3194. SYS_DELAY(100);
  3195. EE_SET(RTL_EE_CLK);
  3196. SYS_DELAY(150);
  3197. EE_CLR(RTL_EE_CLK);
  3198. SYS_DELAY(100);
  3199. }
  3200. return;
  3201. }
  3202. void rtlEnetAddrGet(unsigned char *enetAddr)
  3203. {
  3204. int i;
  3205. for(i=0; i<6; i++)
  3206. *(enetAddr+i) = ownEnetAddr[i];
  3207. return;
  3208. }
  3209. void rtlRegisterShow
  3210.     (
  3211.     RTL81X9END_DEVICE *  pDrvCtrl /* device control structure */
  3212.     )
  3213. {
  3214. int regRead, i;
  3215. printf("rn+++++++++++++Rtl81x9 Register show+++++++++++++++++rn");
  3216. for(i=0;i<6;i++)
  3217. {
  3218. regRead = rtl81x9CsrReadByte(pDrvCtrl, i, 0);
  3219. printf("RTL_REGS_IDR%d: %02xrn",i,regRead);
  3220. }
  3221. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_MAR0, 0);
  3222. printf("RTL_REGS_MAR0-3: %08xrn",regRead);
  3223. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_MAR0+4, 0);
  3224. printf("RTL_REGS_MAR4-7: %08xrn",regRead);
  3225. for(i=0;i<4;i++)
  3226. {
  3227. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_TX_STATUS0+i*4, 0);
  3228. printf("RTL_REGS_TX_STATUS%d: %08xrn",i,regRead);
  3229. }
  3230. for(i=0;i<4;i++)
  3231. {
  3232. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_TX_ADDR0+i*4, 0);
  3233. printf("RTL_REGS_TX_ADDR%d: %08xrn",i,regRead);
  3234. }
  3235. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_RX_BUF, 0);
  3236. printf("RTL_REGS_RX_BUF: %08x rn", regRead);
  3237. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_RX_EARLY_CNT, 0);
  3238. printf("RTL_REGS_RX_EARLY_CNT: %04x rn", regRead);
  3239. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_RX_EARLY_STATUS, 0);
  3240. printf("RTL_REGS_RX_EARLY_STATUS: %02x rn", regRead);
  3241. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_CHIP_CMD, 0);
  3242. printf("RTL_REGS_CHIP_CMD: %02x rn", regRead);
  3243. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_RX_BUF_PTR, 0);
  3244. printf("RTL_REGS_RX_BUF_PTR: %04x rn", regRead);
  3245. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_RX_BUF_ADDR, 0);
  3246. printf("RTL_REGS_RX_BUF_ADDR: %04x rn", regRead);
  3247. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_INTR_MASK, 0);
  3248. printf("RTL_REGS_INTR_MASK: %04x rn", regRead);
  3249. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_INTR_STATUS, 0);
  3250. printf("RTL_REGS_INTR_STATUS: %04x rn", regRead);
  3251. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_TX_CONFIG, 0);
  3252. printf("RTL_REGS_TX_CONFIG: %08x rn",regRead);
  3253. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_RX_CONFIG, 0);
  3254. printf("RTL_REGS_RX_CONFIG: %08x rn",regRead);
  3255. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_TIMER, 0);
  3256. printf("RTL_REGS_TIMER: %08x rn",regRead);
  3257. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_RX_MISSED, 0);
  3258. printf("RTL_REGS_RX_MISSED: %08x rn",regRead);
  3259. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_CONFIG_0, 0);
  3260. printf("RTL_REGS_CONFIG_0: %02x rn", regRead);
  3261. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_CONFIG_1, 0);
  3262. printf("RTL_REGS_CONFIG_1: %02x rn", regRead);
  3263. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_TIMERINT, 0);
  3264. printf("RTL_REGS_TIMERINT: %08x rn",regRead);
  3265. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_MSR, 0);
  3266. printf("RTL_REGS_MSR: %02x rn", regRead);
  3267. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_CONFIG3, 0);
  3268. printf("RTL_REGS_CONFIG3: %02x rn", regRead);
  3269. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_MII, 0);
  3270. printf("RTL_REGS_MII: %02x rn", regRead);
  3271. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_MULTI_INTR, 0);
  3272. printf("RTL_REGS_MULTI_INTR: %04x rn", regRead);
  3273. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_PCI_RERID, 0);
  3274. printf("RTL_REGS_PCI_RERID: %02x rn", regRead);
  3275. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_TX_SUMMARY, 0);
  3276. printf("RTL_REGS_TX_SUMMARY: %04x rn", regRead);
  3277. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_MII_BMCR, 0);
  3278. printf("RTL_REGS_MII_BMCR: %04x rn", regRead);
  3279. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_MII_BMSR, 0);
  3280. printf("RTL_REGS_MII_BMSR: %04x rn", regRead);
  3281. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_NWAY_ADVERT, 0);
  3282. printf("RTL_REGS_NWAY_ADVERT: %04x rn", regRead);
  3283. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_NWAY_LPAR, 0);
  3284. printf("RTL_REGS_NWAY_LPAR: %04x rn", regRead);
  3285. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_NWAY_EXPANSION, 0);
  3286. printf("RTL_REGS_NWAY_EXPANSION: %04x rn", regRead);
  3287. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_DIS, 0);
  3288. printf("RTL_REGS_DIS: %04x rn", regRead);
  3289. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_FCSC, 0);
  3290. printf("RTL_REGS_FCSC: %04x rn", regRead);
  3291. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_NWAYTR, 0);
  3292. printf("RTL_REGS_NWAYTR: %04x rn", regRead);
  3293. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_NWAYTR+2, 0);
  3294. printf("RTL_REGS_REC: %04x rn", regRead);
  3295. regRead = rtl81x9CsrReadWord(pDrvCtrl, RTL_REGS_CSCR, 0);
  3296. printf("RTL_REGS_CSCR: %04x rn", regRead);
  3297. regRead = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_PARA_78, 0);
  3298. printf("RTL_REGS_PARA_PHY1_TW: %08x rn", regRead);
  3299. regRead = rtl81x9CsrReadByte(pDrvCtrl, RTL_REGS_PARA_78+4, 0);
  3300. printf("RTL_REGS_PARA_PHY2: %02x rn", regRead);
  3301. regRead = rtl81x9CsrReadByte(pDrvCtrl, 0xd8, 0);
  3302. printf("RTL_REGS_CONFIG5: %02x rn", regRead);
  3303. printf("++++++++++++++++++++++++++++++++++++++++++++++rn");
  3304. }
  3305. void rtlDrvCtrlShow(RTL81X9END_DEVICE * pDrvCtrl)
  3306. {
  3307. int i;
  3308. printf("rn*************Rrl DrvCtrl Sturcture Show*************rn");
  3309. printf("devType:0x%02xrn",pDrvCtrl->devType);
  3310. printf("unit:%drn",pDrvCtrl->unit);
  3311. printf("phy_addr:%drn",pDrvCtrl->phy_addr);
  3312. printf("nextDesc:%drn",pDrvCtrl->nextDesc);
  3313. printf("freeDesc:%drn",pDrvCtrl->freeDesc);
  3314. for(i=0;i<RTL_NUM_TX_DESC;i++)
  3315. printf("pDescMem[%d] address:0x%08xrn",i,pDrvCtrl->pDescMem[i]);
  3316. printf("ptrRxBufSpace:0x%08xrn",pDrvCtrl->ptrRxBufSpace);
  3317. printf("offset:%drn",pDrvCtrl->offset);
  3318. printf("ivec:%xrn",pDrvCtrl->ivec);
  3319. printf("ilevel:%xrn",pDrvCtrl->ilevel);
  3320. printf("devAdrs:%xrn",pDrvCtrl->devAdrs);
  3321. printf("memBase:%xrn",pDrvCtrl->memBase);
  3322. printf("memAdrs:%xrn",pDrvCtrl->memAdrs);
  3323. printf("memSize:%xrn",pDrvCtrl->memSize);
  3324. printf("pciMemBase:%xrn",pDrvCtrl->pciMemBase);
  3325. printf("ehternet address:%02x%02x%02x%02x%02x%02xrn",
  3326. pDrvCtrl->enetAddr[0],
  3327. pDrvCtrl->enetAddr[1],
  3328. pDrvCtrl->enetAddr[2],
  3329. pDrvCtrl->enetAddr[3],
  3330. pDrvCtrl->enetAddr[4],
  3331. pDrvCtrl->enetAddr[5]);
  3332. printf("CL_POOL_ID:%08xrn",pDrvCtrl->pClPoolId);
  3333. printf("errorStatus:%04xrn",pDrvCtrl->errorStat);
  3334. printf("rn**************************************************rn");
  3335. }