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

VxWorks

开发平台:

C/C++

  1. /* motFecEnd.c - END style Motorola FEC Ethernet network interface driver */
  2. /* Copyright 1989-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02c,02may02,pmr  SPR 75008: only set txStall flag if motFecTbdClean() fails to 
  8.  free any Tx BDs in motFecSend().
  9. 02b,30apr02,rcs  SPR 76102: polling mode fix
  10. 02a,28jan02,rcs  changed motRevNumGet() to call vxImmrDevGet() SPR# 7120
  11. 01z,06dec01,rcs  changed REV_D_4 back to REV_D_3 SPR# 71420 
  12. 01y,04dec01,kab  Removed decl for vxImmrGet(), get from vxPpcLib.h
  13. 01x,26oct01,crg  fixed a possible cause of transmitter underruns by preventing
  14.                  generation of TBDs with no data (SPR 29513)
  15.                  added support for proper setting of MII management interface
  16.                  speed (SPR 33812)
  17.  corrected clearing of receive events in motFecHandleRecvInt()
  18.  (SPR 69440)
  19. 01w,21sep01,dat  Removing ANSI errors for diab compiler (needs more work)
  20. 01v,15sep01,dat  Removed special definition of CACHE_PIPE_FLUSH
  21. 01u,01feb01,rcs  added motRevNumGet() using vxImmrGet()
  22. 01t,01feb01,rcs  merged in Motorola's modifications.
  23. 01s,29jan01,rcs  in motFecRxCtrlRegValGet initialized *rxCtrlVal (SPR# 63479)
  24. 01r,29jan01,rcs  in motFecTxCtrlRegValGet initialized *txCtrlVal (SPR# 63479)
  25. 01q,05dec00,dat  merge from sustaining branch to tor2_0_x
  26. 01p,21nov00,rhk  changes to initialization of FEC in order to support
  27.                  rev. D.4 and newer 860T processors.
  28. 01o,05jul00,stv  fixed the coding error in motFecHashTblPopulate (SPR #31622).
  29. 01n,07jul00,stv  fixed the coding error in motFecHashTblPopulate (SPR# 31283).
  30. 01m,11jun00,ham  removed reference to etherLib.
  31. 01l,22may00,pai  Repaired (SPR #30673) by adding Keith Wiles' corrections to
  32.                  hash register bit settings and his table driven CRC funtion.
  33.                  Updated comments in motFecHashRegValGet().  Corrected the
  34.                  coding error in motFecHashTblPopulate() (SPR #31283).
  35.                  Released transmit semaphore and incremented MIB-II counter
  36.                  in motFecSend() when returning ERROR as a result of being
  37.                  called in polled mode.
  38. 01k,29mar00,pai  allocated memory for PHY_INFO struct in motFecEndLoad() (SPR
  39.                  #30085).
  40. 01j,01feb00,pai  set driver control TX stall flag in motFecSend() if clean
  41.                  TBD count becomes 0 (SPR #30135).
  42. 01i,27jan00,dat  fixed use of NULL
  43. 01h,05jan00,stv  removed private/funcBindP.h (SPR# 29875).
  44. 01g,06dec99,stv  corrected return error code and freed mBlk chain (SPR #28492).
  45. 01f,11nov99,cn   removed unnecessary freeing of pDrvCtrl in motFecUnload
  46.  (SPR# 28772).
  47. 01e,09sep99,rhk  added a check to make sure driver is operational before
  48.                  shutting down in motFecStop.
  49. 01d,31aug99,rhk  disabled the MOT_FEC_DBG switch, pointed to the local
  50.                  copy of ppc860Intr.h.
  51. 01c,19feb99,cn   corrected a bug in motFecMiiDiag ().
  52. 01b,09feb99,cn   changes required by performance improvement (SPR# 24883).
  53.  Also up-dated documentation, added probing of the device
  54.  in the motFecStart () routine.
  55. 01a,09nov98,cn   written.
  56. */
  57. /*
  58. DESCRIPTION
  59. This module implements a Motorola Fast Ethernet Controller (FEC) network
  60. interface driver. The FEC is fully compliant with the IEEE 802.3
  61. 10Base-T and 100Base-T specifications. Hardware support of
  62. the Media Independent Interface (MII) is built-in in the chip.
  63. The FEC establishes a shared memory communication system with the CPU,
  64. which is divided into two parts: the Control/Status Registers (CSR),
  65. and the buffer descriptors (BD).
  66. The CSRs reside in the MPC860T Communication Controller's internal RAM.
  67. They are used for mode control and to extract status information
  68. of a global nature. For instance, the types of events that should
  69. generate an interrupt, or features like the promiscous mode or the
  70. max receive frame length may be set programming some of the CSRs properly.
  71. Pointers to both the Transmit Buffer Descriptors ring (TBD) and the
  72. Receive Buffer Descriptors ring (RBD) are also stored in the CSRs.
  73. The CSRs are located in on-chip RAM and must be accessed using the
  74. big-endian mode.
  75. The BDs are used to pass data buffers and related buffer information
  76. between the hardware and the software. They reside in the host main
  77. memory and basically include local status information and a pointer
  78. to the actual buffer, again in external memory.
  79. This driver must be given several target-specific parameters, and
  80. some external support routines must be provided.  These parameters,
  81. and the mechanisms used to communicate them to the driver, are
  82. detailed below.
  83. For versions of the MPC860T starting with revision D.4 and beyond
  84. the functioning of the FEC changes slightly.  An additional bit has
  85. been added to the Ethernet Control Register (ECNTRL), the FEC PIN
  86. MUX bit.  This bit must be set prior to issuing commands involving
  87. the other two bits in the register (ETHER_EN, RESET).  The bit must
  88. also be set when either of the other two bits are being utilized.
  89. For versions of the 860T prior to revision D.4, this bit should not
  90. be set.
  91. BOARD LAYOUT
  92. This device is on-board.  No jumpering diagram is necessary.
  93. EXTERNAL INTERFACE
  94. The driver provides the standard external interface, motFecEndLoad(), which
  95. takes a string of colon-separated parameters. The parameters should be
  96. specified in hexadecimal, optionally preceeded by "0x" or a minus sign "-".
  97. The parameter string is parsed using strtok_r() and each parameter is
  98. converted from a string representation to binary by a call to
  99. strtoul(parameter, NULL, 16).
  100. The format of the parameter string is:
  101. "<motCpmAddr>:<ivec>:<bufBase>:<bufSize>:<fifoTxBase>:<fifoRxBase>
  102. :<tbdNum>:<rbdNum>:<phyAddr>:<isoPhyAddr>:<phyDefMode>:<userFlags>
  103. :<clockSpeed>"
  104. TARGET-SPECIFIC PARAMETERS
  105. .IP <motCpmAddr>
  106. Indicates the address at which the host processor presents its internal
  107. memory (also known as the dual ported RAM base address). With this address,
  108. the driver is able to compute the location of the FEC parameter RAM, and,
  109. ultimately, to program the FEC for proper operations.
  110. .IP <ivec>
  111. This driver configures the host processor to generate hardware interrupts
  112. for various events within the device. The interrupt-vector offset
  113. parameter is used to connect the driver's ISR to the interrupt through
  114. a call to the VxWorks system function intConnect(). It is also used to
  115. compute the interrupt level (0-7) associated with the FEC interrupt (one
  116. of the MPC860T SIU internal interrupt sources). The latter is given as
  117. a parameter to intEnable(), in order to enable this level interrupt to
  118. the PPC core.
  119. .IP <bufBase>
  120. The Motorola Fast Ethernet Controller is a DMA-type device and typically
  121. shares access to some region of memory with the CPU. This driver is designed
  122. for systems that directly share memory between the CPU and the FEC.
  123. This parameter tells the driver that space for the both the TBDs and the
  124. RBDs needs not be allocated but should be taken from a cache-coherent
  125. private memory space provided by the user at the given address. The user
  126. should be aware that memory used for buffers descriptors must be 8-byte
  127. aligned and non-cacheable. All the buffer descriptors should fit
  128. in the given memory space.
  129. If this parameter is "NONE", space for buffer descriptors is obtained
  130. by calling cacheDmaMalloc() in motFecEndLoad().
  131. .IP <bufSize>
  132. The memory size parameter specifies the size of the pre-allocated memory
  133. region. If <bufBase> is specified as NONE (-1), the driver ignores this
  134. parameter. Otherwise, the driver checks the size of the provided memory
  135. region is adequate with respect to the given number of Transmit Buffer
  136. Descriptors and Receive Buffer Descriptors.
  137. .IP <fifoTxBase>
  138. Indicate the base location of the transmit FIFO, in internal memory.
  139. The user does not need to initialize this parameter, as the related
  140. FEC register defaults to a proper value after reset. The specific
  141. reset value is microcode dependent. However, if the user wishes to
  142. reserve some RAM for other purposes, he may set this parameter to a
  143. different value. This should not be less than the default.
  144. If <fifoTxBase> is specified as NONE (-1), the driver ignores it.
  145. .IP <fifoRxBase>
  146. Indicate the base location of the receive FIFO, in internal memory.
  147. The user does not need to initialize this parameter, as the related
  148. FEC register defaults to a proper value after reset. The specific
  149. reset value is microcode dependent. However, if the user wishes to
  150. reserve some RAM for other purposes, he may set this parameter to a
  151. different value. This should not be less than the default.
  152. If <fifoRxBase> is specified as NONE (-1), the driver ignores it.
  153. .IP <tbdNum>
  154. This parameter specifies the number of transmit buffer descriptors (TBDs).
  155. Each buffer descriptor resides in 8 bytes of the processor's external
  156. RAM space, and each one points to a 1536-byte buffer again in external
  157. RAM. If this parameter is less than a minimum number specified in the
  158. macro MOT_FEC_TBD_MIN, or if it is "NULL", a default value of 64 is used.
  159. This default number is kept deliberately hugh, since each packet the driver
  160. sends may consume more than a single TBD. This parameter should always
  161. equal a even number.
  162. .IP  <rbdNum>
  163. This parameter specifies the number of receive buffer descriptors (RBDs).
  164. Each buffer descriptor resides in 8 bytes of the processor's external
  165. RAM space, and each one points to a 1536-byte buffer again in external
  166. RAM. If this parameter is less than a minimum number specified in the
  167. macro MOT_FEC_RBD_MIN, or if it is "NULL", a default value of 48 is used.
  168. This parameter should always equal a even number.
  169. .IP  <phyAddr>
  170. This parameter specifies the logical address of a MII-compliant physical
  171. device (PHY) that is to be used as a physical media on the network.
  172. Valid addresses are in the range 0-31. There may be more than one device
  173. under the control of the same management interface. If this parameter is
  174. "NULL", the default physical layer initialization routine will find out the
  175. PHY actual address by scanning the whole range. The one with the lowest
  176. address will be chosen.
  177. .IP  <isoPhyAddr>
  178. This parameter specifies the logical address of a MII-compliant physical
  179. device (PHY) that is to be electrically isolated by the management
  180. interface. Valid addresses are in the range 0-31. If this parameter
  181. equals 0xff, the default physical layer initialization routine will
  182. assume there is no need to isolate any device. However, this parameter
  183. will be ignored unless the MOT_FEC_USR_PHY_ISO bit in the <userFlags>
  184. is set to one.
  185. .IP  <phyDefMode>
  186. This parameter specifies the operating mode that will be set up
  187. by the default physical layer initialization routine in case all
  188. the attempts made to establish a valid link failed. If that happens,
  189. the first PHY that matches the specified abilities will be chosen to
  190. work in that mode, and the physical link will not be tested.
  191. .IP  <userFlags>
  192. This field enables the user to give some degree of customization to the
  193. driver, especially as regards the physical layer interface.
  194. .IP  <clockSpeed>
  195. This field enables the user to define the speed of the clock being used
  196. to drive the interface.  The clock speed is used to derive the MII
  197. management interface clock, which cannot exceed 2.5 MHz.  <clockSpeed>
  198. is optional in BSPs using clocks that are 50 MHz or less, but it is
  199. required in faster designs to ensure proper MII interface operation.
  200. MOT_FEC_USR_PHY_NO_AN: the default physical layer initialization
  201. routine will exploit the auto-negotiation mechanism as described in
  202. the IEEE Std 802.3, to bring a valid link up. According to it, all
  203. the link partners on the media will take part to the negotiation
  204. process, and the highest priority common denominator technology ability
  205. will be chosen. It the user wishes to prevent auto-negotiation from
  206. occurring, he may set this bit in the user flags.
  207. MOT_FEC_USR_PHY_TBL: in the auto-negotiation process, PHYs
  208. advertise all their technology abilities at the same time,
  209. and the result is that the maximum common denominator is used. However,
  210. this behaviour may be changed, and the user may affect the order how
  211. each subset of PHY's abilities is negotiated. Hence, when the
  212. MOT_FEC_USR_PHY_TBL bit is set, the default physical layer
  213. initialization routine will look at the motFecPhyAnOrderTbl[] table and
  214. auto-negotiate a subset of abilities at a time, as suggested by the
  215. table itself. It is worth noticing here, however, that if the
  216. MOT_FEC_USR_PHY_NO_AN bit is on, the above table will be ignored.
  217. MOT_FEC_USR_PHY_NO_FD: the PHY may be set to operate in full duplex mode,
  218. provided it has this ability, as a result of the negotiation with other
  219. link partners. However, in this operating mode, the FEC will ignore the
  220. collision detect and carrier sense signals. If the user wishes not to
  221. negotiate full duplex mode, he should set the MOT_FEC_USR_PHY_NO_FD bit
  222. in the user flags.
  223. MOT_FEC_USR_PHY_NO_HD: the PHY may be set to operate in half duplex mode,
  224. provided it has this ability, as a result of the negotiation with other link
  225. partners. If the user wishes not to negotiate half duplex mode, he should
  226. set the MOT_FEC_USR_PHY_NO_HD bit in the user flags.
  227. MOT_FEC_USR_PHY_NO_100: the PHY may be set to operate at 100Mbit/s speed,
  228. provided it has this ability, as a result of the negotiation with
  229. other link partners. If the user wishes not to negotiate 100Mbit/s speed,
  230. he should set the MOT_FEC_USR_PHY_NO_100 bit in the user flags.
  231. MOT_FEC_USR_PHY_NO_10: the PHY may be set to operate at 10Mbit/s speed,
  232. provided it has this ability, as a result of the negotiation with
  233. other link partners. If the user wishes not to negotiate 10Mbit/s speed,
  234. he should set the MOT_FEC_USR_PHY_NO_10 bit in the user flags.
  235. MOT_FEC_USR_PHY_ISO: some boards may have different PHYs controlled by the
  236. same management interface. In some cases, there may be the need of
  237. electrically isolating some of them from the interface itself, in order
  238. to guarantee a proper behaviour on the medium layer. If the user wishes to
  239. electrically isolate one PHY from the MII interface, he should set the
  240. MOT_FEC_USR_PHY_ISO bit and provide its logical address in the <isoPhyAddr>
  241. field of the load string. The default behaviour is to not isolate any
  242. PHY on the board.
  243. MOT_FEC_USR_SER: the user may set the MOT_FEC_USR_SER bit to enable
  244. the 7-wire interface instead of the MII which is the default.
  245. MOT_FEC_USR_LOOP: when the MOT_FEC_USR_LOOP bit is set, the driver will
  246. configure the FEC to work in loopback mode, with the TX signal directly
  247. connected to the RX. This mode should only be used for testing.
  248. MOT_FEC_USR_HBC: if the MOT_FEC_USR_HBC bit is set, the driver will
  249. configure the FEC to perform heartbeat check following end of transmisson
  250. and the HB bit in the status field of the TBD will be set if the collision
  251. input does not assert within the heartbeat window (also see _func_motFecHbFail,
  252. below). The user does not normally need to set this bit.
  253. .LP
  254. EXTERNAL SUPPORT REQUIREMENTS
  255. This driver requires three external support functions:
  256. .IP sysFecEnetEnable()
  257. .CS
  258.     STATUS sysFecEnetEnable (UINT32 motCpmAddr);
  259. .CE
  260. This routine is expected to handle any target-specific functions needed
  261. to enable the FEC. These functions typically include setting the Port D
  262. on the 860T-based board so that the MII interface may be used, and also
  263. disabling the IRQ7 signal. This routine is expected to return OK on
  264. success, or ERROR. The driver calls this routine, once per device, from the
  265. motFecEndLoad() routine.
  266. .IP sysFecEnetDisable()
  267. .CS
  268.     STATUS sysFecEnetDisable (UINT32 motCpmAddr);
  269. .CE
  270. This routine is expected to perform any target specific functions required
  271. to disable the MII interface to the FEC.  This involves restoring the
  272. default values for all the Port D signals. This routine is expected to
  273. return OK on success, or ERROR. The driver calls this routine from the
  274. motFecEndStop() routine each time a device is disabled.
  275. .IP sysFecEnetAddrGet()
  276. .CS
  277. STATUS sysFecEnetAddrGet (UINT32 motCpmAddr, UCHAR * enetAddr);
  278. .CE
  279. The driver expects this routine to provide the six-byte Ethernet hardware
  280. address that is used by this device.  This routine must copy the six-byte
  281. address to the space provided by <enetAddr>.  This routine is expected to
  282. return OK on success, or ERROR.  The driver calls this routine, once per
  283. device, from the motFecEndLoad() routine.
  284. .IP `_func_motFecPhyInit'
  285. .CS
  286.     FUNCPTR _func_motFecPhyInit
  287. .CE
  288. This driver sets the global variable `_func_motFecPhyInit' to the
  289. MII-compliant media initialization routine motFecPhyInit(). If the user
  290. wishes to exploit a different way to configure the PHY, he may set
  291. this variable to his own media initialization routine, tipically
  292. in sysHwInit().
  293. .IP `_func_motFecHbFail'
  294. .CS
  295.     FUNCPTR _func_motFecPhyInit
  296. .CE
  297. The FEC may be configured to perform heartbeat check following end
  298. of transmission, and to generate an interrupt, when this event occurs.
  299. If this is the case, and if the global variable `_func_motFecHbFail'
  300. is not NULL, the routine referenced to by `_func_motFecHbFail' is called,
  301. with a pointer to the driver control structure as parameter. Hence,
  302. the user may set this variable to his own heart beat check fail routine,
  303. where he can take any action he sees appropriate.
  304. The default value for the global variable `_func_motFecHbFail' is NULL.
  305. .LP
  306. SYSTEM RESOURCE USAGE
  307. If the driver allocates the memory to share with the Ethernet device,
  308. it does so by calling the cacheDmaMalloc() routine.  For the default case
  309. of 64 transmit buffers and 48 receive buffers, the total size requested
  310. is 912 bytes, and this includes the 16-byte alignment requirement of the
  311. device.  If a non-cacheable memory region is provided by the user, the
  312. size of this region should be this amount, unless the user has specified
  313. a different number of transmit or receive BDs.
  314. This driver can operate only if this memory region is non-cacheable
  315. or if the hardware implements bus snooping.  The driver cannot maintain
  316. cache coherency for the device because the BDs are asynchronously
  317. modified by both the driver and the device, and these fields might share
  318. the same cache line.
  319. Data buffers are instead allocated in the external memory through the
  320. regular memory allocation routine (memalign), and the related cache lines
  321. are then flushed or invalidated as appropriate. The user should not allocate
  322. memory for them.
  323. TUNING HINTS
  324. The only adjustable parameters are the number of TBDs and RBDs that will be
  325. created at run-time.  These parameters are given to the driver when
  326. motFecEndLoad() is called.  There is one RBD associated with each received
  327. frame whereas a single transmit packet normally uses more than one TBD.  For
  328. memory-limited applications, decreasing the number of RBDs may be
  329. desirable.  Decreasing the number of TBDs below a certain point will
  330. provide substantial performance degradation, and is not reccomended. An
  331. adequate number of loaning buffers are also pre-allocated to provide more
  332. buffering before packets are dropped, but this is not configurable.
  333. The relative priority of the netTask and of the other tasks in the system
  334. may heavily affect performance of this driver. Usually the best performance
  335. is achieved when the netTask priority equals that of the other
  336. applications using the driver.
  337. SPECIAL CONSIDERATIONS
  338. Due to the FEC8 errata in the document: "MPC860 Family Device Errata Reference"
  339. available at the Motorola web site, the number of receive buffer
  340. descriptors (RBD) for the FEC (see configNet.h) is kept deliberately high.
  341. According to Motorola, this problem was fixed in Rev. B3 of the silicon.
  342. In memory-bound applications, when using the above mentioned revision of
  343. the MPC860T processor, the user may decrease the number of RBDs
  344. to fit his needs.
  345. SEE ALSO: ifLib,
  346. .I "MPC860T Fast Ethernet Controller (Supplement to the MPC860 User's Manual)"
  347. .I "Motorola MPC860 User's Manual",
  348. INTERNAL
  349. This driver contains conditional compilation switch MOT_FEC_END_DEBUG.
  350. If defined, adds debug output routines.  Output is further
  351. selectable at run-time via the motFecEndDbg global variable.
  352. */
  353. #include "vxWorks.h"
  354. #include "wdLib.h"
  355. #include "iv.h"
  356. #include "vme.h"
  357. #include "net/mbuf.h"
  358. #include "net/unixLib.h"
  359. #include "net/protosw.h"
  360. #include "sys/socket.h"
  361. #include "sys/ioctl.h"
  362. #include "errno.h"
  363. #include "memLib.h"
  364. #include "intLib.h"
  365. #include "net/route.h"
  366. #include "iosLib.h"
  367. #include "errnoLib.h"
  368. #include "vxLib.h" 
  369. #include "cacheLib.h"
  370. #include "logLib.h"
  371. #include "netLib.h"
  372. #include "stdio.h"
  373. #include "stdlib.h"
  374. #include "sysLib.h"
  375. #include "taskLib.h"
  376. #include "net/systm.h"
  377. #include "sys/times.h"
  378. #include "net/if_subr.h"
  379. #undef ETHER_MAP_IP_MULTICAST
  380. #include "etherMultiLib.h"
  381. #include "end.h"
  382. #include "semLib.h"
  383. #define    END_MACROS
  384. #include "endLib.h"
  385. #include "lstLib.h"
  386. #include "drv/intrCtl/ppc860Intr.h"
  387. #include "drv/end/motFecEnd.h"
  388. /* defines */
  389. /* initial divisor and final XOR value for reflected CRC */
  390. #define INIT_REFLECTED  0xFFFFFFFF
  391. #define XOROT           INIT_REFLECTED
  392. /* Driver debug control */
  393. #define MOT_FEC_DBG
  394. /* Driver debug control */
  395. #ifdef MOT_FEC_DBG
  396. #define MOT_FEC_DBG_OFF 0x0000
  397. #define MOT_FEC_DBG_RX 0x0001
  398. #define MOT_FEC_DBG_TX 0x0002
  399. #define MOT_FEC_DBG_POLL 0x0004
  400. #define MOT_FEC_DBG_MII 0x0008
  401. #define MOT_FEC_DBG_LOAD 0x0010
  402. #define MOT_FEC_DBG_IOCTL 0x0020
  403. #define MOT_FEC_DBG_INT 0x0040
  404. #define MOT_FEC_DBG_START     0x0080
  405. #define MOT_FEC_DBG_ANY     0xffff
  406. UINT32 motFecEndDbg = 0x0;
  407. UINT32 motFecBabRxErr = 0x0;
  408. UINT32 motFecBabTxErr = 0x0;
  409. UINT32 motFecHbFailErr = 0x0;
  410. UINT32 motFecTxLcErr = 0x0;
  411. UINT32 motFecTxUrErr = 0x0;
  412. UINT32 motFecTxCslErr = 0x0;
  413. UINT32 motFecTxRlErr = 0x0;
  414. UINT32 motFecRxLgErr = 0x0;
  415. UINT32 motFecRxNoErr = 0x0;
  416. UINT32 motFecRxCrcErr = 0x0;
  417. UINT32 motFecRxOvErr = 0x0;
  418. UINT32 motFecRxTrErr = 0x0;
  419. UINT32  motFecRxLsErr = 0x0;
  420. UINT32  motFecRxMemErr = 0x0;
  421. DRV_CTRL *  pDrvCtrlDbg = NULL;
  422. #define MOT_FEC_BAB_RX_ADD
  423.     motFecBabRxErr++;
  424. #define MOT_FEC_BAB_TX_ADD
  425.     motFecBabTxErr++;
  426. #define MOT_FEC_HB_FAIL_ADD
  427.     motFecHbFailErr++;
  428. #define MOT_FEC_TX_LC_ADD
  429.     motFecTxLcErr++;
  430. #define MOT_FEC_TX_UR_ADD
  431.     motFecTxUrErr++;
  432. #define MOT_FEC_TX_CSL_ADD
  433.     motFecTxCslErr++;
  434. #define MOT_FEC_TX_RL_ADD
  435.     motFecTxRlErr++;
  436. #define MOT_FEC_RX_LG_ADD
  437.     motFecRxLgErr++;
  438. #define MOT_FEC_RX_NO_ADD
  439.     motFecRxNoErr++;
  440. #define MOT_FEC_RX_CRC_ADD
  441.     motFecRxCrcErr++;
  442. #define MOT_FEC_RX_OV_ADD
  443.     motFecRxOvErr++;
  444. #define MOT_FEC_RX_TR_ADD
  445.     motFecRxTrErr++;
  446. #define MOT_FEC_RX_MEM_ADD
  447.     motFecRxMemErr++;
  448. #define MOT_FEC_RX_LS_ADD
  449.     motFecRxLsErr++;
  450. #define MOT_FEC_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)                    
  451.     {                                                                   
  452.     if (motFecEndDbg & FLG)                                             
  453.         logMsg (X0, X1, X2, X3, X4, X5, X6);                            
  454.     }
  455. #else /* MOT_FEC_DBG */
  456. #define MOT_FEC_BAB_RX_ADD
  457. #define MOT_FEC_BAB_TX_ADD
  458. #define MOT_FEC_HB_FAIL_ADD
  459. #define MOT_FEC_TX_LC_ADD
  460. #define MOT_FEC_TX_UR_ADD
  461. #define MOT_FEC_TX_CSL_ADD
  462. #define MOT_FEC_TX_RL_ADD
  463. #define MOT_FEC_RX_MEM_ADD
  464. #define MOT_FEC_RX_LS_ADD
  465. #define MOT_FEC_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  466. #endif /* MOT_FEC_DBG */
  467. /* general macros for reading/writing from/to specified locations */
  468. /* Cache and virtual/physical memory related macros */
  469. #define MOT_FEC_PHYS_TO_VIRT(physAddr)     
  470. CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->bdCacheFuncs, (char *)(physAddr))
  471. #define MOT_FEC_VIRT_TO_PHYS(virtAddr)     
  472. CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->bdCacheFuncs, (char *)(virtAddr))
  473. #define MOT_FEC_BD_CACHE_INVAL(address, len)          
  474.         CACHE_DRV_INVALIDATE (&pDrvCtrl->bdCacheFuncs, (address), (len))
  475. #define MOT_FEC_CACHE_INVAL(address, len)                                   
  476. CACHE_DRV_INVALIDATE (&pDrvCtrl->bufCacheFuncs, (address), (len))
  477. #define MOT_FEC_CACHE_FLUSH(address, len)                                   
  478. CACHE_DRV_FLUSH (&pDrvCtrl->bufCacheFuncs, (address), (len))
  479. /* driver flags */
  480. #define MOT_FEC_OWN_MEM 0x01 /* internally provided memory */
  481. #define MOT_FEC_INV_TBD_NUM 0x02 /* invalid tbdNum provided */
  482. #define MOT_FEC_INV_RBD_NUM 0x04 /* invalid rbdNum provided */
  483. #define MOT_FEC_POLLING 0x08 /* polling mode */
  484. #define MOT_FEC_PROM 0x20    /* promiscuous mode */
  485. #define MOT_FEC_MCAST 0x40    /* multicast addressing mode */
  486. #define MOT_FEC_FD 0x80    /* full duplex mode */
  487. /* shortcuts */
  488. #define MOT_FEC_FLAG_CLEAR(clearBits)
  489.     (pDrvCtrl->flags &= ~(clearBits))
  490. #define MOT_FEC_FLAG_SET(setBits)
  491.     (pDrvCtrl->flags |= (setBits))
  492. #define MOT_FEC_FLAG_GET()
  493.     (pDrvCtrl->flags)
  494. #define MOT_FEC_FLAG_ISSET(setBits)
  495.     (pDrvCtrl->flags & (setBits))
  496. #define MOT_FEC_PHY_FLAGS_SET(setBits)
  497.     (pDrvCtrl->phyInfo->phyFlags |= (setBits))
  498. #define MOT_FEC_PHY_FLAGS_ISSET(setBits)
  499.     (pDrvCtrl->phyInfo->phyFlags & (setBits))
  500. #define MOT_FEC_PHY_FLAGS_GET(setBits)
  501.     (pDrvCtrl->phyInfo->phyFlags)
  502. #define MOT_FEC_PHY_FLAGS_CLEAR(clearBits)
  503.     (pDrvCtrl->phyInfo->phyFlags &= ~(clearBits))
  504. #define MOT_FEC_USR_FLAG_ISSET(setBits)
  505.     (pDrvCtrl->userFlags & (setBits))
  506. #define END_FLAGS_ISSET(setBits)
  507.     ((&pDrvCtrl->endObj)->flags & (setBits))
  508. #define MOT_FEC_ADDR_GET(pEnd)                                          
  509.     ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  510. #define MOT_FEC_ADDR_LEN_GET(pEnd)                                      
  511.     ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  512. /* some BDs definitions */
  513. /*
  514.  * the total is 0x600 and it accounts for the required alignment
  515.  * of receive data buffers, and the cluster overhead.
  516.  */
  517. #define MOT_FEC_MAX_CL_LEN      ((MOT_FEC_MAX_PCK_SZ
  518.  + (MOT_FEC_BD_ALIGN - 1)
  519.  + (CL_OVERHEAD - 1))
  520.  & (~ (CL_OVERHEAD - 1)))
  521. #define MOT_FEC_MAX_RX_BUF ((MOT_FEC_MAX_PCK_SZ + MOT_FEC_BD_ALIGN - 1) 
  522. & (~(MOT_FEC_BD_ALIGN - 1)))
  523. #define MOT_FEC_BUF_V_LEN (MOT_FEC_MAX_RX_BUF + 16)
  524. #define MOT_FEC_RX_BUF_SZ       (MOT_FEC_MAX_CL_LEN)
  525. #define MOT_FEC_TX_BUF_SZ       (MOT_FEC_MAX_CL_LEN)
  526. #define MOT_FEC_MEM_SZ(pDrvCtrl)
  527.     ((pDrvCtrl)->bufSize)
  528. #define MOT_FEC_LOAN_SZ
  529.     (MOT_FEC_RX_BUF_SZ * MOT_FEC_BD_LOAN_NUM)
  530. #define MOT_FEC_RX_MEM(pDrvCtrl)
  531.     (MOT_FEC_RX_BUF_SZ * ((pDrvCtrl)->rbdNum + MOT_FEC_BD_LOAN_NUM))
  532. #define MOT_FEC_TX_MEM(pDrvCtrl)
  533.     (MOT_FEC_TX_BUF_SZ * (MOT_FEC_TBD_POLL_NUM + MOT_FEC_TX_CL_NUM))
  534. #define MOT_FEC_TBD_MEM(pDrvCtrl)
  535.     (MOT_FEC_TBD_SZ * (pDrvCtrl)->tbdNum)
  536. #define MOT_FEC_RBD_MEM(pDrvCtrl)
  537.     (MOT_FEC_RBD_SZ * (pDrvCtrl)->rbdNum)
  538. #define MOT_FEC_BD_MEM(pDrvCtrl)
  539.     (MOT_FEC_TBD_MEM (pDrvCtrl) + MOT_FEC_RBD_MEM (pDrvCtrl))
  540. /* Control/Status Registers (CSR) definitions */
  541. #define MOT_FEC_CSR_WR(csrOff, csrVal)
  542.     {
  543.     UINT32 temp = 0;
  544.     temp = (UINT32) MOT_FEC_VIRT_TO_PHYS ((pDrvCtrl->motCpmAddr) 
  545.   + (csrOff));
  546.     MOT_FEC_LONG_WR ((UINT32 *) (temp), (csrVal));
  547.     }
  548. #define MOT_FEC_CSR_RD(csrOff, csrVal)
  549.     {
  550.     UINT32 temp = 0;
  551.     temp = (UINT32) MOT_FEC_VIRT_TO_PHYS ((pDrvCtrl->motCpmAddr) 
  552.   + (csrOff));
  553.     MOT_FEC_LONG_RD ((UINT32 *) (temp), (csrVal));
  554.     }
  555. /* macros to read/write tx/rx buffer descriptors */
  556. #define MOT_FEC_BD_WORD_WR(bdAddr, bdOff, bdVal)
  557.     {
  558.     UINT32 temp = 0;
  559.     temp = (UINT32) MOT_FEC_VIRT_TO_PHYS ((bdAddr) + (bdOff));
  560.     MOT_FEC_WORD_WR ((UINT16 *) (temp), (bdVal));
  561.     }
  562. /* here we're writing the data pointer, so it's a physical address */
  563. #define MOT_FEC_BD_LONG_WR(bdAddr, bdOff, bdVal)
  564.     {
  565.     UINT32 temp1 = 0;
  566.     UINT32 temp2 = 0;
  567.     temp1 = (UINT32) MOT_FEC_VIRT_TO_PHYS ((bdAddr) + (bdOff));
  568.     temp2 = (UINT32) MOT_FEC_VIRT_TO_PHYS (bdVal);
  569.     MOT_FEC_LONG_WR ((UINT32 *) (temp1), (temp2));
  570.     }
  571. #define MOT_FEC_BD_WORD_RD(bdAddr, bdOff, bdVal)
  572.     {
  573.     UINT32 temp = 0;
  574.     temp = (UINT32) MOT_FEC_VIRT_TO_PHYS ((bdAddr) + (bdOff));
  575.     MOT_FEC_WORD_RD ((UINT16 *) (temp), (bdVal));
  576.     }
  577. #define MOT_FEC_BD_LONG_RD(bdAddr, bdOff, bdVal)
  578.     {
  579.     UINT32 temp1 = 0;
  580.     UINT32 temp2 = 0;
  581.     temp1 = (UINT32) MOT_FEC_VIRT_TO_PHYS ((bdAddr) + (bdOff));
  582.     MOT_FEC_LONG_RD ((UINT32 *) (temp1), (temp2));
  583.     bdVal = (char *) MOT_FEC_PHYS_TO_VIRT (temp2);
  584.     }
  585. #define MOT_FEC_NEXT_TBD(pDrvCtrl, pTbd)
  586.     (pTbd) = (MOT_FEC_TBD_ID) ((pDrvCtrl)->tbdBase +   
  587.        ((pDrvCtrl)->tbdIndex * MOT_FEC_TBD_SZ))
  588. #define MOT_FEC_USED_TBD(pDrvCtrl, pTbd)    
  589.     (pTbd) = (MOT_FEC_TBD_ID) ((pDrvCtrl)->tbdBase +     
  590.        ((pDrvCtrl)->usedTbdIndex * MOT_FEC_TBD_SZ))
  591. #define MOT_FEC_NEXT_RBD(pDrvCtrl, pRbd)    
  592.     (pRbd) = (MOT_FEC_RBD_ID) ((pDrvCtrl)->rbdBase +     
  593.        (((pDrvCtrl)->rbdIndex) * MOT_FEC_RBD_SZ))
  594. #define MOT_FEC_ETH_SET                                                 
  595.     MOT_FEC_CSR_WR (MOT_FEC_CTRL_OFF, pinMux);
  596. #define MOT_FEC_ETH_ENABLE
  597.     MOT_FEC_CSR_WR (MOT_FEC_CTRL_OFF, (MOT_FEC_ETH_EN | pinMux));
  598. #define MOT_FEC_ETH_DISABLE
  599.     MOT_FEC_CSR_WR (MOT_FEC_CTRL_OFF, (MOT_FEC_ETH_DIS | pinMux));
  600. #define MOT_FEC_RX_ACTIVATE
  601.     MOT_FEC_CSR_WR (MOT_FEC_RX_ACT_OFF, MOT_FEC_RX_ACT);
  602. #define MOT_FEC_TX_ACTIVATE
  603.     MOT_FEC_CSR_WR (MOT_FEC_TX_ACT_OFF, MOT_FEC_TX_ACT);
  604. #define MOT_FEC_INT_DISABLE
  605.     MOT_FEC_CSR_WR (MOT_FEC_MASK_OFF, 0);
  606. #define MOT_FEC_INT_ENABLE
  607.     MOT_FEC_CSR_WR (MOT_FEC_MASK_OFF, (pDrvCtrl->intMask));
  608. #define MOT_FEC_VECTOR(pDrvCtrl)
  609.     ((pDrvCtrl)->ivec)
  610. /* more shortcuts */
  611. #define MOT_FEC_GRA_SEM_CREATE
  612.     if ((pDrvCtrl->graSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY)) 
  613. == NULL)
  614. goto errorExit
  615. #define MOT_FEC_GRA_SEM_DELETE
  616.     if ((pDrvCtrl->graSem) != NULL) 
  617. semDelete (pDrvCtrl->graSem)
  618. #define MOT_FEC_GRA_SEM_GIVE
  619.     (semGive (pDrvCtrl->graSem))
  620. #define MOT_FEC_GRA_SEM_TAKE
  621.     (semTake (pDrvCtrl->graSem, WAIT_FOREVER))
  622. #define MOT_FEC_MII_SEM_CREATE
  623.     if ((pDrvCtrl->miiSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY)) 
  624. == NULL)
  625. goto errorExit
  626. #define MOT_FEC_MII_SEM_DELETE
  627.     if ((pDrvCtrl->miiSem) != NULL) 
  628. semDelete (pDrvCtrl->miiSem)
  629. #define MOT_FEC_MII_SEM_GIVE
  630.     (semGive (pDrvCtrl->miiSem))
  631. #define MOT_FEC_MII_SEM_TAKE
  632.     (semTake (pDrvCtrl->miiSem, WAIT_FOREVER))
  633. #define NET_BUF_ALLOC()                                                 
  634.     netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)
  635. #define NET_TO_MOT_FEC_BUF(netBuf)                              
  636.     (((UINT32) (netBuf) + MOT_FEC_BD_ALIGN - 1) 
  637.       & ~(MOT_FEC_BD_ALIGN - 1))
  638. #define NET_BUF_FREE(pBuffer)                                           
  639.     netClFree (pDrvCtrl->endObj.pNetPool, (pBuffer))
  640. #define NET_MBLK_ALLOC()                                                
  641.     netMblkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)
  642. #define NET_MBLK_FREE(pMblock)                                          
  643.     netMblkFree (pDrvCtrl->endObj.pNetPool, (M_BLK_ID) (pMblock))
  644. #define NET_CL_BLK_ALLOC()                                              
  645.     netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)
  646. #define NET_CL_BLK_FREE(pClBlock)                                       
  647.     netClBlkFree (pDrvCtrl->endObj.pNetPool, (CL_BLK_ID) (pClBlock))
  648. #define NET_MBLK_BUF_FREE(pMblock)                                      
  649.     netMblkClFree ((M_BLK_ID) (pMblock))
  650. #define NET_MBLK_CL_JOIN(pMblock, pClBlock, ret)                        
  651.     ret = netMblkClJoin ((pMblock), (pClBlock))
  652. #define NET_CL_BLK_JOIN(pClBlock, pBuffer, length, ret)                 
  653.     ret = netClBlkJoin ((pClBlock), (pBuffer), (length), NULL, 0, 0, 0)
  654. /* globals */
  655. /* external */
  656. IMPORT UINT32 vxImmrGet(void);
  657. /* locals */
  658. LOCAL int pinMux;
  659. /* intermediate remainders for table-driven CRC calculations */
  660. LOCAL UINT32  crctable[256] =
  661. {
  662.  0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
  663.  0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
  664.  0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
  665.  0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
  666.  0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
  667.  0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
  668.  0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
  669.  0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
  670.  0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
  671.  0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
  672.  0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
  673.  0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
  674.  0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
  675.  0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
  676.  0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
  677.  0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
  678.  0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
  679.  0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
  680.  0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
  681.  0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
  682.  0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
  683.  0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
  684.  0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
  685.  0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
  686.  0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
  687.  0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
  688.  0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
  689.  0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
  690.  0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
  691.  0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
  692.  0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
  693.  0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
  694.  0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
  695.  0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
  696.  0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
  697.  0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
  698.  0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
  699.  0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
  700.  0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
  701.  0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
  702.  0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
  703.  0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
  704.  0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
  705.  0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
  706.  0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
  707.  0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
  708.  0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
  709.  0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
  710.  0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
  711.  0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
  712.  0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
  713.  0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
  714.  0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
  715.  0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
  716.  0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
  717.  0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
  718.  0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
  719.  0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
  720.  0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
  721.  0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
  722.  0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
  723.  0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
  724.  0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
  725.  0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
  726. };
  727. /* Function declarations not in any header files */
  728. /* forward function declarations */
  729. LOCAL STATUS    motFecInitParse (DRV_CTRL *pDrvCtrl, char *initString);
  730. LOCAL STATUS    motFecInitMem (DRV_CTRL *pDrvCtrl);
  731. LOCAL STATUS    motFecSend (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  732. LOCAL STATUS    motFecPhyInit (DRV_CTRL *pDrvCtrl);
  733. LOCAL STATUS    motFecPhyPreInit (DRV_CTRL *pDrvCtrl);
  734. LOCAL STATUS  motFecReset (DRV_CTRL *pDrvCtrl);
  735. LOCAL STATUS    motFecBdFree (DRV_CTRL *pDrvCtrl);
  736. LOCAL STATUS    motFecRbdInit (DRV_CTRL *pDrvCtrl);
  737. LOCAL STATUS motFecTbdInit (DRV_CTRL *pDrvCtrl);
  738. LOCAL STATUS motFecRxCtrlRegValGet (DRV_CTRL *pDrvCtrl, UINT32 * rxCtrlVal);
  739. LOCAL STATUS motFecTxCtrlRegValGet (DRV_CTRL *pDrvCtrl, UINT32 * txCtrlVal);
  740. LOCAL STATUS motFecHashRegValGet (DRV_CTRL *pDrvCtrl, UINT32  crcVal,
  741.      UINT32 * csrVal, UINT16 * offset);
  742. LOCAL STATUS motFecAddrRegValGet (DRV_CTRL *pDrvCtrl, UINT32  * csr0Val,
  743.      UINT32 * csr1Val);
  744. LOCAL UINT32 motFecCrcGet (char * pAddr);
  745. LOCAL STATUS motFecHashTblPopulate (DRV_CTRL * pDrvCtrl);
  746. LOCAL STATUS motFecHashTblAdd (DRV_CTRL * pDrvCtrl, char * pAddr);
  747. LOCAL STATUS motFecPrePhyConfig (DRV_CTRL *pDrvCtrl);
  748. LOCAL STATUS motFecPostPhyConfig (DRV_CTRL *pDrvCtrl);
  749. LOCAL STATUS motFecMblkWalk (M_BLK * pMblk, UINT8 * pFragNum,
  750. UINT16 *    pPktType);
  751. LOCAL STATUS motFecPktTransmit (DRV_CTRL *pDrvCtrl, M_BLK * pMblk,
  752.    UINT8  fragNum, UINT16     pktType);
  753. LOCAL STATUS motFecPktCopyTransmit (DRV_CTRL *pDrvCtrl, M_BLK * pMblk,
  754.    UINT8  fragNum, UINT16     pktType);
  755. LOCAL void motFecTbdClean (DRV_CTRL *pDrvCtrl);
  756. LOCAL UINT32 motFecTbdCheck (DRV_CTRL *pDrvCtrl, MOT_FEC_TBD_ID pUsedTbd);
  757. LOCAL MOT_FEC_TBD_LIST_ID motFecTbdListSet (DRV_CTRL *pDrvCtrl, UINT8 tbdNum);
  758. LOCAL MOT_FEC_TBD_ID motFecTbdGet (DRV_CTRL *pDrvCtrl);
  759. LOCAL void motFecInt (DRV_CTRL *pDrvCtrl);
  760. LOCAL void      motFecRxTxHandle (DRV_CTRL *pDrvCtrl);
  761. LOCAL void      motFecHandleRecvInt (DRV_CTRL *pDrvCtrl);
  762. LOCAL void motFecReceive (DRV_CTRL *pDrvCtrl, MOT_FEC_RBD_ID pRfd);
  763. LOCAL STATUS motFecMiiRead (DRV_CTRL *pDrvCtrl, UINT8 phyAddr,
  764.        UINT8 regAddr, UINT16 *retVal);
  765. LOCAL STATUS motFecMiiWrite (DRV_CTRL *pDrvCtrl, UINT8 phyAddr,
  766. UINT8 regAddr, UINT16 writeData);
  767. LOCAL STATUS motFecMiiDiag (DRV_CTRL *pDrvCtrl, UINT8 phyAddr);
  768. LOCAL STATUS motFecMiiIsolate (DRV_CTRL *pDrvCtrl, UINT8 isoPhyAddr);
  769. LOCAL STATUS motFecMiiAnRun (DRV_CTRL *pDrvCtrl, UINT8 phyAddr);
  770. LOCAL STATUS motFecMiiAnStart (DRV_CTRL *pDrvCtrl, UINT8 phyAddr);
  771. LOCAL STATUS motFecMiiModeForce (DRV_CTRL *pDrvCtrl, UINT8 phyAddr);
  772. LOCAL STATUS motFecMiiDefForce (DRV_CTRL *pDrvCtrl, UINT8 phyAddr);
  773. LOCAL STATUS motFecMiiAnCheck (DRV_CTRL *pDrvCtrl, UINT8 phyAddr);
  774. LOCAL STATUS motFecMiiProbe (DRV_CTRL *pDrvCtrl, UINT8 phyAddr);
  775. LOCAL void motFecRbdClean (DRV_CTRL *pDrvCtrl,
  776. volatile MOT_FEC_RBD_ID pRBDNew);
  777. LOCAL int       motRevNumGet (void);
  778. /* END Specific interfaces. */
  779. END_OBJ * motFecEndLoad (char *initString);
  780. LOCAL STATUS    motFecStart (DRV_CTRL *pDrvCtrl);
  781. LOCAL STATUS motFecUnload (DRV_CTRL *pDrvCtrl);
  782. LOCAL STATUS    motFecStop (DRV_CTRL *pDrvCtrl);
  783. LOCAL int       motFecIoctl (DRV_CTRL *pDrvCtrl, int cmd, caddr_t data);
  784. LOCAL STATUS    motFecSend (DRV_CTRL *pDrvCtrl, M_BLK_ID pMblk);
  785. LOCAL STATUS    motFecMCastAddrAdd (DRV_CTRL *pDrvCtrl, char* pAddress);
  786. LOCAL STATUS    motFecMCastAddrDel (DRV_CTRL *pDrvCtrl, char* pAddress);
  787. LOCAL STATUS    motFecMCastAddrGet (DRV_CTRL *pDrvCtrl,
  788.                                         MULTI_TABLE *pTable);
  789. LOCAL STATUS    motFecPollSend (DRV_CTRL *pDrvCtrl, M_BLK_ID pMblk);
  790. LOCAL STATUS    motFecPollReceive (DRV_CTRL *pDrvCtrl, M_BLK_ID pMblk);
  791. LOCAL STATUS    motFecPollStart (DRV_CTRL *pDrvCtrl);
  792. LOCAL STATUS    motFecPollStop (DRV_CTRL *pDrvCtrl);
  793. /* globals */
  794. FUNCPTR _func_motFecPhyInit = (FUNCPTR) motFecPhyInit;
  795. FUNCPTR _func_motFecHbFail = (FUNCPTR) NULL;
  796. #ifdef MOT_FEC_DBG
  797. void motFecCsrShow (void);
  798. void motFecRbdShow (int);
  799. void motFecTbdShow (int);
  800. void motFecErrorShow (void);
  801. void motFecDrvShow (void);
  802. void motFecMiiShow (void);
  803. void motFecMibShow (void);
  804. #endif /* MOT_FEC_DBG */
  805. /*
  806.  * Define the device function table.  This is static across all driver
  807.  * instances.
  808.  */
  809. LOCAL NET_FUNCS netFuncs =
  810.     {
  811.     (FUNCPTR) motFecStart, /* start func. */
  812.     (FUNCPTR) motFecStop, /* stop func. */
  813.     (FUNCPTR) motFecUnload, /* unload func. */
  814.     (FUNCPTR) motFecIoctl, /* ioctl func. */
  815.     (FUNCPTR) motFecSend, /* send func. */
  816.     (FUNCPTR) motFecMCastAddrAdd,     /* multicast add func. */
  817.     (FUNCPTR) motFecMCastAddrDel,     /* multicast delete func. */
  818.     (FUNCPTR) motFecMCastAddrGet,     /* multicast get fun. */
  819.     (FUNCPTR) motFecPollSend,     /* polling send func. */
  820.     (FUNCPTR) motFecPollReceive,     /* polling receive func. */
  821.     endEtherAddressForm,    /* put address info into a NET_BUFFER */
  822.     (FUNCPTR) endEtherPacketDataGet,  /* get pointer to data in NET_BUFFER */
  823.     (FUNCPTR) endEtherPacketAddrGet   /* Get packet addresses */
  824.     };
  825. /*******************************************************************************
  826. *
  827. * motFecEndLoad - initialize the driver and device
  828. *
  829. * This routine initializes both driver and device to an operational state
  830. * using device specific parameters specified by <initString>.
  831. *
  832. * The parameter string, <initString>, is an ordered list of parameters each
  833. * separated by a colon. The format of <initString> is:
  834. *
  835. * "<motCpmAddr>:<ivec>:<bufBase>:<bufSize>:<fifoTxBase>:<fifoRxBase>
  836. * :<tbdNum>:<rbdNum>:<phyAddr>:<isoPhyAddr>:<phyDefMode>:<userFlags>
  837. * :<clockSpeed>"
  838. *
  839. * The FEC shares a region of memory with the driver.  The caller of this
  840. * routine can specify the address of this memory region, or can specify that
  841. * the driver must obtain this memory region from the system resources.
  842. *
  843. * A default number of transmit/receive buffer descriptors of 32 can be
  844. * selected by passing zero in the parameters <tbdNum> and <rbdNum>.
  845. * In other cases, the number of buffers selected should be greater than two.
  846. *
  847. * The <bufBase> parameter is used to inform the driver about the shared
  848. * memory region.  If this parameter is set to the constant "NONE," then this
  849. * routine will attempt to allocate the shared memory from the system.  Any
  850. * other value for this parameter is interpreted by this routine as the address
  851. * of the shared memory region to be used. The <bufSize> parameter is used
  852. * to check that this region is large enough with respect to the provided
  853. * values of both transmit/receive buffer descriptors.
  854. *
  855. * If the caller provides the shared memory region, then the driver assumes
  856. * that this region does not require cache coherency operations, nor does it
  857. * require conversions between virtual and physical addresses.
  858. *
  859. * If the caller indicates that this routine must allocate the shared memory
  860. * region, then this routine will use cacheDmaMalloc() to obtain
  861. * some  cache-safe memory.  The attributes of this memory will be checked,
  862. * and if the memory is not write coherent, this routine will abort and
  863. * return NULL.
  864. *
  865. * RETURNS: an END object pointer, or NULL on error.
  866. *
  867. * SEE ALSO: ifLib,
  868. * .I "MPC860T Fast Ethernet Controller (Supplement to MPC860 User's Manual)"
  869. */
  870. END_OBJ* motFecEndLoad
  871.     (
  872.     char *initString      /* parameter string */
  873.     )
  874.     {
  875.     DRV_CTRL * pDrvCtrl = NULL; /* pointer to DRV_CTRL structure */
  876.     UCHAR    enetAddr[6]; /* ethernet address */
  877.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("Loading end...n"), 1, 2, 3, 4, 5, 6);
  878.     if (initString == NULL)
  879. return (NULL);
  880.     if (initString[0] == 0)
  881. {
  882. bcopy ((char *)MOT_FEC_DEV_NAME, (void *)initString,
  883. MOT_FEC_DEV_NAME_LEN);
  884. return (NULL);
  885. }
  886.     /* allocate the device structure */
  887.     pDrvCtrl = (DRV_CTRL *) calloc (sizeof (DRV_CTRL), 1);
  888.     if (pDrvCtrl == NULL)
  889. return (NULL);
  890.     pDrvCtrl->phyInfo = (PHY_INFO *) calloc (sizeof (PHY_INFO), 1);
  891.     if (pDrvCtrl->phyInfo == NULL)
  892. {
  893. free ((char *)pDrvCtrl);
  894. return (NULL);
  895. }
  896. #ifdef MOT_FEC_DBG
  897.     pDrvCtrlDbg = pDrvCtrl;
  898. #endif /* MOT_FEC_DBG */
  899.     /* Parse InitString */
  900.     if (motFecInitParse (pDrvCtrl, initString) == ERROR)
  901. goto errorExit;
  902.     pDrvCtrl->ilevel = (int) IVEC_TO_ILEVEL (pDrvCtrl->ivec);
  903.     /* sanity check the unit number */
  904.     if (pDrvCtrl->unit < 0 )
  905. goto errorExit;
  906.     /* memory initialization */
  907.     if (motFecInitMem (pDrvCtrl) == ERROR)
  908. goto errorExit;
  909.     /* get our ethernet hardware address */
  910.     SYS_FEC_ENET_ADDR_GET (enetAddr);
  911.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecEndLoad: enetAddr= n
  912.     0x%x 0x%x 0x%x 0x%x 0x%x 0x%x n "),
  913.     enetAddr[0],
  914.     enetAddr[1],
  915.     enetAddr[2],
  916.     enetAddr[3],
  917.     enetAddr[4],
  918.     enetAddr[5]);
  919.     /* initialize some flags */
  920.     pDrvCtrl->loaded = TRUE;
  921.     pDrvCtrl->intrConnect = FALSE;
  922.     /*
  923.      * create the synchronization semaphores for mii intr handling
  924.      * and for graceful transmit command interrupts.
  925.      */
  926.     MOT_FEC_MII_SEM_CREATE;
  927.     MOT_FEC_GRA_SEM_CREATE;
  928.     /* endObj initializations */
  929.     if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ*) pDrvCtrl,
  930.       MOT_FEC_DEV_NAME, pDrvCtrl->unit, &netFuncs,
  931.       "Motorola FEC Ethernet Enhanced Network Driver")
  932. == ERROR)
  933. goto errorExit;
  934.     pDrvCtrl->phyInfo->phySpeed = MOT_FEC_10MBS;
  935.     if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
  936.       (u_char *) &enetAddr[0], MOT_FEC_ADDR_LEN,
  937.       ETHERMTU, pDrvCtrl->phyInfo->phySpeed) == ERROR)
  938. goto errorExit;
  939.     /* Mark the device ready */
  940.     END_OBJ_READY (&pDrvCtrl->endObj,
  941.                    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
  942.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecEndLoad... Done n"),
  943.     1, 2, 3, 4, 5, 6);
  944.     /*
  945.      * determine the revision number of the processor, and set pinMux
  946.      * bit accordingly
  947.      */
  948.     if (motRevNumGet () >= REV_D_3)
  949.         pinMux = MOT_FEC_ETH_PINMUX;
  950.     else
  951.         pinMux = 0;
  952.     return (&pDrvCtrl->endObj);
  953. errorExit:
  954.     motFecUnload (pDrvCtrl);
  955.     free ((char *) pDrvCtrl);
  956.     return NULL;
  957.     }
  958. /*******************************************************************************
  959. *
  960. * motFecUnload - unload a driver from the system
  961. *
  962. * This routine unloads the driver pointed to by <pDrvCtrl> from the system.
  963. *
  964. * RETURNS: OK, always.
  965. *
  966. * SEE ALSO: motFecLoad()
  967. */
  968. LOCAL STATUS motFecUnload
  969.     (
  970.     DRV_CTRL *pDrvCtrl       /* pointer to DRV_CTRL structure */
  971.     )
  972.     {
  973.     int ix = 0; /* a counter */
  974.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("Unloading end..."), 1, 2, 3, 4, 5, 6);
  975.     if (pDrvCtrl == NULL)
  976. return (ERROR);
  977.     pDrvCtrl->loaded = FALSE;
  978.     /* free lists */
  979.     for (ix = 0; ix < pDrvCtrl->tbdNum; ix++)
  980. {
  981. cfree ((char *) pDrvCtrl->pTbdList [ix]);
  982. }
  983.     END_OBJECT_UNLOAD (&pDrvCtrl->endObj);
  984.     /* free allocated memory if necessary */
  985.     if ((MOT_FEC_FLAG_ISSET (MOT_FEC_OWN_MEM)) &&
  986. (pDrvCtrl->pBufBase != NULL))
  987. cacheDmaFree (pDrvCtrl->pBufBase);
  988.     /* free allocated memory if necessary */
  989.     if ((pDrvCtrl->pMBlkArea) != NULL)
  990. free (pDrvCtrl->pMBlkArea);
  991.     /* free the semaphores if necessary */
  992.     MOT_FEC_MII_SEM_DELETE;
  993.     MOT_FEC_GRA_SEM_DELETE;
  994.     free (pDrvCtrl->phyInfo);
  995.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecUnload... Donen"),
  996.     1, 2, 3, 4, 5, 6);
  997.     return (OK);
  998.     }
  999. /*******************************************************************************
  1000. *
  1001. * motFecInitParse - parse parameter values from initString
  1002. *
  1003. * This routine parses parameter values from initString and stores them in
  1004. * the related fiels of the driver control structure.
  1005. *
  1006. * RETURNS: OK or ERROR
  1007. */
  1008. LOCAL STATUS motFecInitParse
  1009.     (
  1010.     DRV_CTRL * pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1011.     char * initString /* parameter string */
  1012.     )
  1013.     {
  1014.     char *  tok; /* an initString token */
  1015.     char *  holder = NULL; /* points to initString fragment beyond tok */
  1016.     tok = strtok_r (initString, ":", &holder);
  1017.     if (tok == NULL)
  1018. return ERROR;
  1019.     pDrvCtrl->unit = atoi (tok);
  1020.     tok = strtok_r (NULL, ":", &holder);
  1021.     if (tok == NULL)
  1022. return ERROR;
  1023.     pDrvCtrl->motCpmAddr = (UINT32) strtoul (tok, NULL, 16);
  1024.     tok = strtok_r (NULL, ":", &holder);
  1025.     if (tok == NULL)
  1026. return ERROR;
  1027.     pDrvCtrl->ivec = (int) strtoul (tok, NULL, 16);
  1028.     tok = strtok_r (NULL, ":", &holder);
  1029.     if (tok == NULL)
  1030. return ERROR;
  1031.     pDrvCtrl->pBufBase = (char *) strtoul (tok, NULL, 16);
  1032.     tok = strtok_r (NULL, ":", &holder);
  1033.     if (tok == NULL)
  1034. return ERROR;
  1035.     pDrvCtrl->bufSize = strtoul (tok, NULL, 16);
  1036.     tok = strtok_r (NULL, ":", &holder);
  1037.     if (tok == NULL)
  1038. return ERROR;
  1039.     pDrvCtrl->fifoTxBase = (UINT32) strtoul (tok, NULL, 16);
  1040.     tok = strtok_r (NULL, ":", &holder);
  1041.     if (tok == NULL)
  1042. return ERROR;
  1043.     pDrvCtrl->fifoRxBase = (UINT32) strtoul (tok, NULL, 16);
  1044.     tok = strtok_r (NULL, ":", &holder);
  1045.     if (tok == NULL)
  1046. return ERROR;
  1047.     pDrvCtrl->tbdNum = (UINT16) strtoul (tok, NULL, 16);
  1048.     tok = strtok_r (NULL, ":", &holder);
  1049.     if (tok == NULL)
  1050. return ERROR;
  1051.     pDrvCtrl->rbdNum = (UINT16) strtoul (tok, NULL, 16);
  1052.     tok = strtok_r (NULL, ":", &holder);
  1053.     if (tok == NULL)
  1054. return ERROR;
  1055.     pDrvCtrl->phyInfo->phyAddr = (UINT8) strtoul (tok, NULL, 16);
  1056.     tok = strtok_r (NULL, ":", &holder);
  1057.     if (tok == NULL)
  1058. return ERROR;
  1059.     pDrvCtrl->phyInfo->isoPhyAddr = (UINT8) strtoul (tok, NULL, 16);
  1060.     tok = strtok_r (NULL, ":", &holder);
  1061.     if (tok == NULL)
  1062.         return ERROR;
  1063.     pDrvCtrl->phyInfo->phyDefMode = (UINT8) strtoul (tok, NULL, 16);
  1064.     tok = strtok_r (NULL, ":", &holder);
  1065.     if (tok == NULL)
  1066. return ERROR;
  1067.     pDrvCtrl->userFlags = strtoul (tok, NULL, 16);
  1068.     /* start of optional parameters */
  1069.     tok = strtok_r (NULL, ":", &holder);
  1070.     if (tok != NULL)
  1071. pDrvCtrl->clockSpeed = atoi (tok);
  1072.     if (!pDrvCtrl->tbdNum || pDrvCtrl->tbdNum <= 2)
  1073. {
  1074. MOT_FEC_FLAG_SET (MOT_FEC_INV_TBD_NUM);
  1075. pDrvCtrl->tbdNum = MOT_FEC_TBD_DEF_NUM;
  1076. }
  1077.     if (!pDrvCtrl->rbdNum || pDrvCtrl->rbdNum <= 2)
  1078. {
  1079. MOT_FEC_FLAG_SET (MOT_FEC_INV_RBD_NUM);
  1080. pDrvCtrl->rbdNum = MOT_FEC_RBD_DEF_NUM;
  1081. }
  1082.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD,
  1083.  ("motFecEndParse: unit=%d motCpmAddr=0x%x ivec=0x%xn
  1084.  bufBase=0x%x bufSize=0x%x n"),
  1085.  pDrvCtrl->unit,
  1086.  (int) pDrvCtrl->motCpmAddr,
  1087.  (int) pDrvCtrl->ivec,
  1088.  (int) pDrvCtrl->pBufBase,
  1089.  pDrvCtrl->bufSize,
  1090.  0);
  1091.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD,
  1092.  ("motFecEndParse: fifoTxBase=0x%x fifoRxBase=0x%xn
  1093.  tbdNum=%d rbdNum=%d flags=0x%xn"),
  1094.  pDrvCtrl->fifoTxBase,
  1095.  pDrvCtrl->fifoRxBase,
  1096.  pDrvCtrl->tbdNum,
  1097.  pDrvCtrl->rbdNum,
  1098.  pDrvCtrl->userFlags,
  1099.  0);
  1100.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD,
  1101.                  ("motFecEndParse: phyAddr=0x%x isoPhyAddr=0x%xn
  1102.                   phyDefMode=0x%x n"),
  1103.                  pDrvCtrl->phyInfo->phyAddr,
  1104.                  pDrvCtrl->phyInfo->isoPhyAddr,
  1105.                  pDrvCtrl->phyInfo->phyDefMode,
  1106.                  0, 0, 0);
  1107.     return (OK);
  1108.     }
  1109. /*******************************************************************************
  1110. *
  1111. * motFecInitMem - initialize memory
  1112. *
  1113. * This routine initializes all the memory needed by the driver whose control
  1114. * structure is passed in <pDrvCtrl>.
  1115. *
  1116. * RETURNS: OK or ERROR
  1117. */
  1118. LOCAL STATUS motFecInitMem
  1119.     (
  1120.     DRV_CTRL *  pDrvCtrl        /* pointer to DRV_CTRL structure */
  1121.     )
  1122.     {
  1123.     UINT32 bdSize;     /* temporary size holder */
  1124.     UINT32 clSize;     /* temporary size holder */
  1125.     UINT16 clNum; /* a buffer number holder */
  1126.     M_CL_CONFIG   mclBlkConfig = {0, 0, NULL, 0};
  1127. /* cluster blocks configuration */
  1128.     CL_DESC   clDescTbl [] = { {MOT_FEC_MAX_CL_LEN, 0, NULL, 0} };
  1129. /* cluster blocks config table */
  1130.     int clDescTblNumEnt = (NELEMENTS (clDescTbl));
  1131. /* number of different clusters */
  1132.     /* initialize the netPool */
  1133.     if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof (NET_POOL))) == NULL)
  1134. return (ERROR);
  1135.     /*
  1136.      * we include here room for both TBDs and RBDs,
  1137.      * and the alignment factor.
  1138.      */
  1139.     bdSize = (MOT_FEC_BD_MEM (pDrvCtrl) + MOT_FEC_BD_ALIGN);
  1140.     /*
  1141.      * Establish the memory area that we will share with the device.  If
  1142.      * the caller has provided an area, then we assume it is non-cacheable
  1143.      * and will not require the use of the special cache routines.
  1144.      * If the caller did provide an area, then we must obtain it from
  1145.      * the system, using the cache savvy allocation routine.
  1146.      */
  1147.     switch ((int) pDrvCtrl->pBufBase)
  1148. {
  1149. case NONE :      /* we must obtain it */
  1150.     /* this driver can't handle write incoherent caches */
  1151.     if (!CACHE_DMA_IS_WRITE_COHERENT ())
  1152. {
  1153. MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecInitMem: shared n
  1154.         memory not cache coherentn"),
  1155.         1, 2, 3, 4, 5, 6);
  1156. return (ERROR);
  1157. }
  1158.     pDrvCtrl->pBufBase = cacheDmaMalloc (bdSize);
  1159.     if (pDrvCtrl->pBufBase == NULL)      /* no memory available */
  1160. {
  1161. MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecInitMem: could not n
  1162.         obtain memoryn"),
  1163.         1, 2, 3, 4, 5, 6);
  1164. return (ERROR);
  1165. }
  1166.             pDrvCtrl->pBufBase = (char *) (((UINT32) (pDrvCtrl->pBufBase) +
  1167.                                   MOT_FEC_BD_ALIGN - 1) &
  1168.                                   ~(MOT_FEC_BD_ALIGN -1));
  1169.     pDrvCtrl->bufSize = bdSize;
  1170.     MOT_FEC_FLAG_SET (MOT_FEC_OWN_MEM);
  1171.     pDrvCtrl->bdCacheFuncs = cacheDmaFuncs;
  1172.     break;
  1173. default :        /* the user provided an area */
  1174.     if (pDrvCtrl->bufSize == 0)
  1175. {
  1176. MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecInitMem: not enough n
  1177.         memoryn"),
  1178.         1, 2, 3, 4, 5, 6);
  1179. return (ERROR);
  1180. }
  1181.     /*
  1182.      * check the user provided enough memory with reference
  1183.      * to the given number of receive/transmit frames, if any.
  1184.      */
  1185.     if (MOT_FEC_FLAG_ISSET (MOT_FEC_INV_TBD_NUM) &&
  1186. MOT_FEC_FLAG_ISSET (MOT_FEC_INV_RBD_NUM))
  1187. {
  1188. pDrvCtrl->tbdNum = (MOT_FEC_MEM_SZ (pDrvCtrl) /
  1189.     (MOT_FEC_TBD_SZ + MOT_FEC_RBD_SZ));
  1190. pDrvCtrl->rbdNum = pDrvCtrl->tbdNum;
  1191. }
  1192.     else if (MOT_FEC_FLAG_ISSET (MOT_FEC_INV_TBD_NUM))
  1193. {
  1194. pDrvCtrl->tbdNum = ((MOT_FEC_MEM_SZ (pDrvCtrl)
  1195.     - MOT_FEC_RBD_MEM (pDrvCtrl))
  1196.     / MOT_FEC_TBD_SZ);
  1197. }
  1198.     else if (MOT_FEC_FLAG_ISSET (MOT_FEC_INV_RBD_NUM))
  1199. {
  1200. pDrvCtrl->rbdNum = ((MOT_FEC_MEM_SZ (pDrvCtrl)
  1201.     - MOT_FEC_TBD_MEM (pDrvCtrl))
  1202.     / MOT_FEC_RBD_SZ);
  1203. }
  1204.     else
  1205. {
  1206. if (MOT_FEC_MEM_SZ (pDrvCtrl) < bdSize)
  1207.     {
  1208.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecInitMem: not enough n
  1209.    memoryn"),
  1210.    1, 2, 3, 4, 5, 6);
  1211.     return (ERROR);
  1212.     }
  1213. }
  1214.     if ((pDrvCtrl->tbdNum <= MOT_FEC_TBD_MIN)
  1215. || (pDrvCtrl->rbdNum <= MOT_FEC_RBD_MIN))
  1216. {
  1217. MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecInitMem: not enough n
  1218.        memoryn"),
  1219.        1, 2, 3, 4, 5, 6);
  1220. return (ERROR);
  1221. }
  1222.     MOT_FEC_FLAG_CLEAR (MOT_FEC_OWN_MEM);
  1223.     pDrvCtrl->bdCacheFuncs = cacheNullFuncs;
  1224.     break;
  1225. }
  1226.     /* cache functions descriptor for data buffers */
  1227.     motFecBufCacheFuncs.flushRtn = motFecBufFlushRtn;
  1228.     motFecBufCacheFuncs.invalidateRtn = motFecBufInvRtn;
  1229.     motFecBufCacheFuncs.virtToPhysRtn = NULL;
  1230.     motFecBufCacheFuncs.physToVirtRtn = NULL;
  1231.     pDrvCtrl->bufCacheFuncs = motFecBufCacheFuncs;
  1232.     /* zero the shared memory */
  1233.     memset (pDrvCtrl->pBufBase, 0, (int) pDrvCtrl->bufSize);
  1234.     /*
  1235.      * number of clusters, including loaning buffers, a min number
  1236.      * of transmit clusters for copy-mode transmit, and one transmit
  1237.      * cluster for polling operation.
  1238.      */
  1239.     clNum = pDrvCtrl->rbdNum + MOT_FEC_BD_LOAN_NUM
  1240.     + 1 + MOT_FEC_TX_CL_NUM;
  1241.     clSize = (MOT_FEC_TX_MEM (pDrvCtrl) + MOT_FEC_RX_MEM (pDrvCtrl)
  1242.     + (CL_OVERHEAD * clNum)
  1243.     + MOT_FEC_BD_ALIGN);
  1244.     /* pool of mblks */
  1245.     if (mclBlkConfig.mBlkNum == 0)
  1246. mclBlkConfig.mBlkNum = clNum * 2;
  1247.     /* pool of clusters, including loaning buffers */
  1248.     if (clDescTbl[0].clNum == 0)
  1249. {
  1250. clDescTbl[0].clNum = clNum;
  1251. clDescTbl[0].clSize = MOT_FEC_MAX_CL_LEN;
  1252. }
  1253.     /* there's a cluster overhead and an alignment issue */
  1254.     clDescTbl[0].memSize = (clDescTbl[0].clNum *
  1255.     (clDescTbl[0].clSize + CL_OVERHEAD));
  1256.     clDescTbl[0].memArea = (char *) (memalign (CL_ALIGNMENT, clSize));
  1257.     if (clDescTbl[0].memArea == NULL)
  1258. {
  1259. return (ERROR);
  1260. }
  1261.     /* store the pointer to the clBlock area */
  1262.     pDrvCtrl->pClBlkArea = clDescTbl[0].memArea;
  1263.     pDrvCtrl->clBlkSize = clDescTbl[0].memSize;
  1264.     /* pool of cluster blocks */
  1265.     if (mclBlkConfig.clBlkNum == 0)
  1266. mclBlkConfig.clBlkNum = clDescTbl[0].clNum;
  1267.     /* get memory for mblks */
  1268.     if (mclBlkConfig.memArea == NULL)
  1269. {
  1270. /* memory size adjusted to hold the netPool pointer at the head */
  1271. mclBlkConfig.memSize = ((mclBlkConfig.mBlkNum
  1272. * (M_BLK_SZ + MBLK_ALIGNMENT))
  1273. + (mclBlkConfig.clBlkNum
  1274. * (CL_BLK_SZ + CL_ALIGNMENT)));
  1275. mclBlkConfig.memArea = (char *) memalign (MBLK_ALIGNMENT,
  1276.   mclBlkConfig.memSize);
  1277. if (mclBlkConfig.memArea == NULL)
  1278.     {
  1279.     return (ERROR);
  1280.     }
  1281. /* store the pointer to the mBlock area */
  1282. pDrvCtrl->pMBlkArea = mclBlkConfig.memArea;
  1283. pDrvCtrl->mBlkSize = mclBlkConfig.memSize;
  1284. }
  1285.     /* init the mem pool */
  1286.     if (netPoolInit (pDrvCtrl->endObj.pNetPool, &mclBlkConfig,
  1287.      &clDescTbl[0], clDescTblNumEnt, NULL)
  1288. == ERROR)
  1289. {
  1290. return (ERROR);
  1291. }
  1292.     if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool,
  1293.        MOT_FEC_MAX_CL_LEN, FALSE))
  1294.         == NULL)
  1295. {
  1296. return (ERROR);
  1297. }
  1298.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecInitMem... Donen"),
  1299.     0, 0, 0, 0, 0, 0);
  1300.     return OK;
  1301.     }
  1302. /**************************************************************************
  1303. *
  1304. * motFecStart - start the device
  1305. *
  1306. * This routine starts the FEC device and brings it up to an operational
  1307. * state.  The driver must have already been loaded with the motFecEndLoad()
  1308. * routine.
  1309. *
  1310. * RETURNS: OK, or ERROR if the device could not be initialized.
  1311. *
  1312. * INTERNAL
  1313. * The speed field inthe phyInfo structure is only set after the call
  1314. * to the physical layer init routine. On the other hand, the mib2
  1315. * interface is initialized in the motFecEndLoad() routine, and the default
  1316. * value of 10Mbit assumed there is not always correct. We need to
  1317. * correct it here.
  1318. *
  1319. */
  1320. LOCAL STATUS motFecStart
  1321.     (
  1322.     DRV_CTRL *pDrvCtrl       /* pointer to DRV_CTRL structure */
  1323.     )
  1324.     {
  1325.     int retVal; /* convenient holder for return value */
  1326.     char        bucket[4];
  1327.     MOT_FEC_LOG (MOT_FEC_DBG_START, ("Starting end...n"), 1, 2, 3, 4, 5, 6);
  1328.     /* must have been loaded */
  1329.     if (!pDrvCtrl->loaded)
  1330. return (ERROR);
  1331.     if (vxMemProbe ((char *) (pDrvCtrl->motCpmAddr + MOT_FEC_CSR_OFF),
  1332.     VX_READ, 4, &bucket[0]) != OK)
  1333.         {
  1334.         MOT_FEC_LOG (MOT_FEC_DBG_START,
  1335.                    (": need MMU mapping for address 0x%xn"),
  1336.                    (UINT32) pDrvCtrl->motCpmAddr, 2, 3, 4, 5, 6);
  1337. return (ERROR);
  1338.         }
  1339.     /* reset the chip */
  1340.     MOT_FEC_ETH_SET;
  1341.     if (motFecReset (pDrvCtrl) != OK)
  1342. return (ERROR);
  1343.     if (motFecTbdInit (pDrvCtrl) == ERROR)
  1344. return (ERROR);
  1345.     if (motFecRbdInit (pDrvCtrl) == ERROR)
  1346. return (ERROR);
  1347.     /* set some flags to default values */
  1348.     pDrvCtrl->txStall = FALSE;
  1349.     pDrvCtrl->tbdIndex = 0;
  1350.     pDrvCtrl->usedTbdIndex = 0;
  1351.     pDrvCtrl->cleanTbdNum = pDrvCtrl->tbdNum;
  1352.     pDrvCtrl->rbdIndex = 0;
  1353.     /* connect the interrupt handler */
  1354.     SYS_FEC_INT_CONNECT (pDrvCtrl, motFecInt, (int) pDrvCtrl, retVal);
  1355.     if (retVal == ERROR)
  1356. return (ERROR);
  1357.     /* enable system interrupt: set relevant bit in SIMASK */
  1358.     SYS_FEC_INT_ENABLE (pDrvCtrl, retVal);
  1359.     if (retVal == ERROR)
  1360. return (ERROR);
  1361.     /* call the BSP to do any other initialization (port D) */
  1362.     SYS_FEC_ENET_ENABLE;
  1363.     /* configure some chip's registers */
  1364.     if (motFecPrePhyConfig (pDrvCtrl) == ERROR)
  1365. return (ERROR);
  1366.     /* initialize some fields in the PHY info structure */
  1367.     if (motFecPhyPreInit (pDrvCtrl) != OK)
  1368. {
  1369. MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("Failed to pre-initialize the PHYn"),
  1370. 0, 0, 0, 0, 0, 0);
  1371. return (ERROR);
  1372. }
  1373.     /* initialize the Physical medium layer */
  1374.     if (_func_motFecPhyInit == NULL)
  1375. return (ERROR);
  1376.     if (((* _func_motFecPhyInit) (pDrvCtrl)) != OK)
  1377. {
  1378. MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("Failed to initialize the PHYn"),
  1379. 0, 0, 0, 0, 0, 0);
  1380. return (ERROR);
  1381. }
  1382.     /* configure other chip's registers */
  1383.     if (motFecPostPhyConfig (pDrvCtrl) == ERROR)
  1384. return (ERROR);
  1385.     /* correct the speed for the mib2 stuff */
  1386.     pDrvCtrl->endObj.mib2Tbl.ifSpeed = pDrvCtrl->phyInfo->phySpeed;
  1387.     if (END_FLAGS_ISSET (IFF_MULTICAST))
  1388.         MOT_FEC_FLAG_SET (MOT_FEC_MCAST);
  1389.     /* enable the Ethernet Controller */
  1390.     MOT_FEC_ETH_ENABLE;
  1391.     /* mark the interface as up */
  1392.     END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  1393.     /* startup the receiver */
  1394.     MOT_FEC_RX_ACTIVATE;
  1395.     /* Flush the write pipe */
  1396.     CACHE_PIPE_FLUSH ();
  1397.     MOT_FEC_LOG (MOT_FEC_DBG_START, ("Starting end... Donen"),
  1398.      1, 2, 3, 4, 5, 6);
  1399.     return (OK);
  1400.     }
  1401. /**************************************************************************
  1402. *
  1403. * motFecStop - stop the 'motfec' interface
  1404. *
  1405. * This routine marks the interface as inactive, disables interrupts and
  1406. * the Ethernet Controller. As a result, reception is stopped immediately,
  1407. * and transmission is stopped after a bad CRC is appended to any frame
  1408. * currently being transmitted. The reception/transmission control logic
  1409. * (FIFO pointers, buffer descriptors, etc.) is reset. To bring the
  1410. * interface back up, motFecStart() must be called.
  1411. *
  1412. * RETURNS: OK, always.
  1413. */
  1414. LOCAL STATUS motFecStop
  1415.     (
  1416.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1417.     )
  1418.     {
  1419.     int retVal; /* convenient holder for return value */
  1420.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecStop...n"), 1, 2, 3, 4, 5, 6);
  1421.     /* make sure driver is operational before stopping it */
  1422.     if (END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING))
  1423.         {
  1424.         /* mark the interface as down */
  1425.         END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  1426.         /* issue a graceful transmit command */
  1427.         MOT_FEC_CSR_WR (MOT_FEC_TX_CTRL_OFF, MOT_FEC_TX_CTRL_GRA);
  1428.         /* wait for the related interrupt */
  1429.         MOT_FEC_GRA_SEM_TAKE;
  1430.         /* mask chip interrupts */
  1431.         MOT_FEC_INT_DISABLE;
  1432.         /* disable the Ethernet Controller */
  1433.         MOT_FEC_ETH_DISABLE;
  1434.         /* disable system interrupt: reset relevant bit in SIMASK */
  1435.         SYS_FEC_INT_DISABLE (pDrvCtrl, retVal);
  1436.         if (retVal == ERROR)
  1437.     return (ERROR);
  1438.         /* disconnect the interrupt handler */
  1439.         SYS_FEC_INT_DISCONNECT (pDrvCtrl, motFecInt, (int)pDrvCtrl, retVal);
  1440.         if (retVal == ERROR)
  1441.     return (ERROR);
  1442.         /* call the BSP to disable the Port D */
  1443.         SYS_FEC_ENET_DISABLE;
  1444.         if (motFecBdFree (pDrvCtrl) != OK)
  1445.     return (ERROR);
  1446.         }
  1447.     MOT_FEC_LOG (MOT_FEC_DBG_LOAD, ("motFecStop... Done n"),
  1448.     1, 2, 3, 4, 5, 6);
  1449.     return OK;
  1450.     }
  1451. /**************************************************************************
  1452. *
  1453. * motFecReset - reset the `motFec' interface
  1454. *
  1455. * This routine resets the chip by setting the Reset bit in the Ethernet
  1456. * Control Register. The ETHER_EN bit is cleared, and all the FEC registers
  1457. * take their default values. In addition, any transmission/reception
  1458. * currently in progress is abruptly aborted.
  1459. *
  1460. * RETURNS: OK, always.
  1461. */
  1462. LOCAL STATUS motFecReset
  1463.     (
  1464.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1465.     )
  1466.     {
  1467.     /* issue a reset command to the FEC chip */
  1468.     MOT_FEC_CSR_WR (MOT_FEC_CTRL_OFF, (MOT_FEC_ETH_RES | pinMux));
  1469.     /* wait at least 16 clock cycles */
  1470.     taskDelay (1);
  1471.     /* enable the FEC PIN MUX bit if necessary */
  1472.     MOT_FEC_CSR_WR (MOT_FEC_CTRL_OFF, pinMux);
  1473.     /* wait at least 16 clock cycles */
  1474.     taskDelay (1);
  1475.     return (OK);
  1476.     }
  1477. /*******************************************************************************
  1478. *
  1479. * motFecInt - entry point for handling interrupts from the FEC
  1480. *
  1481. * The interrupting events are acknowledged to the device, so that the device
  1482. * will de-assert its interrupt signal.  The amount of work done here is kept
  1483. * to a minimum; the bulk of the work is deferred to the netTask.
  1484. *
  1485. * RETURNS: N/A
  1486. */
  1487. LOCAL void motFecInt
  1488.     (
  1489.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1490.     )
  1491.     {
  1492.     UINT32 event = 0; /* event intr register */
  1493.     UINT32 mask = 0; /* holder for the mask intr register */
  1494.     UINT32 status; /* status word */
  1495.     CACHE_PIPE_FLUSH ();
  1496.     /* read and save the interrupt event register */
  1497.     MOT_FEC_CSR_RD (MOT_FEC_EVENT_OFF, event);
  1498.     /* clear all interrupts */
  1499.     MOT_FEC_CSR_WR (MOT_FEC_EVENT_OFF, (event & MOT_FEC_EVENT_MSK));
  1500.     CACHE_PIPE_FLUSH ();
  1501.     /* read the interrupt mask register */
  1502.     MOT_FEC_CSR_RD (MOT_FEC_MASK_OFF, mask);
  1503.     /* read CSR status word again */
  1504.     MOT_FEC_CSR_RD (MOT_FEC_EVENT_OFF, status);
  1505.     MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: event 0x%x, status 0x%xn"),
  1506.    (event & MOT_FEC_EVENT_MSK), status,
  1507.    0, 0, 0, 0);
  1508.     /* handle bus error interrupts */
  1509.     if ((event & MOT_FEC_EVENT_BERR) == MOT_FEC_EVENT_BERR)
  1510. {
  1511. MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: bus error, restart chipn"),
  1512.        0, 0, 0, 0, 0, 0);
  1513. /* stop and restart the device */
  1514. (void) netJobAdd ((FUNCPTR) motFecStop, (int) pDrvCtrl,
  1515.   event, 0, 0, 0);
  1516. (void) netJobAdd ((FUNCPTR) motFecStart, (int) pDrvCtrl,
  1517.   event, 0, 0, 0);
  1518. }
  1519.     /* handle babbling transmit error interrupts */
  1520.     if ((event & MOT_FEC_EVENT_BABT) == MOT_FEC_EVENT_BABT)
  1521. {
  1522. MOT_FEC_BAB_TX_ADD;
  1523. MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: babbling tx errorn"),
  1524.        0, 0, 0, 0, 0, 0);
  1525. }
  1526.     /* handle babbling receive error interrupts */
  1527.     if ((event & MOT_FEC_EVENT_BABR) == MOT_FEC_EVENT_BABR)
  1528. {
  1529. MOT_FEC_BAB_RX_ADD;
  1530. MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: babbling rx errorn"),
  1531.        0, 0, 0, 0, 0, 0);
  1532. }
  1533.     /* handle transmit and receive interrupts */
  1534.     if ((((event & MOT_FEC_EVENT_TXF) == MOT_FEC_EVENT_TXF)
  1535. && ((mask & MOT_FEC_EVENT_TXF) == MOT_FEC_EVENT_TXF)) ||
  1536. (((event & MOT_FEC_EVENT_RXF) == MOT_FEC_EVENT_RXF)
  1537. && ((mask & MOT_FEC_EVENT_RXF) == MOT_FEC_EVENT_RXF)))
  1538. {
  1539.         /* disable tx/rx interrupts */
  1540.         MOT_FEC_CSR_WR (MOT_FEC_MASK_OFF, (mask & (~(MOT_FEC_EVENT_TXF
  1541.      | MOT_FEC_EVENT_RXF))));
  1542. MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: tx/rx intrn"),
  1543.        0, 0, 0, 0, 0, 0);
  1544. (void) netJobAdd ((FUNCPTR) motFecRxTxHandle, (int) pDrvCtrl,
  1545.   0, 0, 0, 0);
  1546. }
  1547.     /* handle heartbeat check fail interrupts */
  1548.     if ((event & MOT_FEC_EVENT_HB) == MOT_FEC_EVENT_HB)
  1549. {
  1550. MOT_FEC_HB_FAIL_ADD;
  1551. if (_func_motFecHbFail != NULL)
  1552.     (* _func_motFecHbFail) (pDrvCtrl);
  1553. MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: heartbeat check failn"),
  1554.        0, 0, 0, 0, 0, 0);
  1555. }
  1556.     /* handle mii frame completion interrupts */
  1557.     if ((event & MOT_FEC_EVENT_MII) == MOT_FEC_EVENT_MII)
  1558. {
  1559. MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: mii transfern"),
  1560.        0, 0, 0, 0, 0, 0);
  1561. /* let the PHY configuration task finish off its job */
  1562. MOT_FEC_MII_SEM_GIVE;
  1563. }
  1564.     /* handle graceful transmit interrupts */
  1565.     if ((event & MOT_FEC_EVENT_GRA) == MOT_FEC_EVENT_GRA)
  1566. {
  1567. MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: graceful transmitn"),
  1568.        0, 0, 0, 0, 0, 0);
  1569. /* let the Stop task finish off its job */
  1570. MOT_FEC_GRA_SEM_GIVE;
  1571. }
  1572.     }
  1573. /*******************************************************************************
  1574. *
  1575. * motFecSend - send an Ethernet packet
  1576. *
  1577. * This routine() takes a M_BLK_ID and sends off the data in the M_BLK_ID.
  1578. * The buffer must already have the addressing information properly installed
  1579. * in it. This is done by a higher layer.
  1580. *
  1581. * muxSend() calls this routine each time it wants to send a packet.
  1582. *
  1583. * RETURNS: OK, or END_ERR_BLOCK, if no resources are available, or ERROR,
  1584. * if the device is currently working in polling mode.
  1585. */
  1586. LOCAL STATUS motFecSend
  1587.     (
  1588.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1589.     M_BLK *  pMblk           /* pointer to the mBlk/cluster pair */
  1590.     )
  1591.     {
  1592.     UINT8 fragNum = 0; /* number of fragments in this mBlk */
  1593.     UINT16 pktType = 0; /* packet type (unicast or multicast) */
  1594.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...n"), 1, 2, 3, 4, 5, 6);
  1595.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  1596.     /* check device mode */
  1597.     if (MOT_FEC_FLAG_ISSET (MOT_FEC_POLLING))
  1598.         {
  1599.         netMblkClChainFree (pMblk); /* free the given mBlk chain */
  1600.         errno = EINVAL;
  1601.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1602.         END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1603.         return (ERROR);
  1604.         }
  1605.     /* walk the mBlk */
  1606.     if (motFecMblkWalk (pMblk, &fragNum, &pktType) == ERROR)
  1607. {
  1608.         goto motFecSendError;
  1609. }
  1610.     /* check we have enough resources */
  1611.     if ((pDrvCtrl->cleanTbdNum) == 0)
  1612. {
  1613.         /*
  1614.          * SPR 75008 - first run the clean routine and then if there still
  1615.          * are not any free Tx buffer descriptors, set the stall flag and
  1616.          * the stall condition will be handled in motFecTbdClean()
  1617.          */
  1618.         motFecTbdClean (pDrvCtrl);
  1619.         if (pDrvCtrl->cleanTbdNum == 0)
  1620.             {
  1621.             /* SPR 30135 - make sure muxTxRestart() will be called later */
  1622.             pDrvCtrl->txStall = TRUE;
  1623.             motFecTbdClean (pDrvCtrl);
  1624.             goto motFecSendError;
  1625.             }
  1626. }
  1627.     if ((pDrvCtrl->cleanTbdNum) >= fragNum)
  1628. {
  1629. /* transmit the packet in zero-copy mode */
  1630. if (motFecPktTransmit (pDrvCtrl, pMblk, fragNum, pktType) == ERROR)
  1631.     {
  1632.     goto motFecSendError;
  1633.     }
  1634. }
  1635.     else
  1636. {
  1637. /* transmit the packet in copy mode */
  1638. fragNum = 1;
  1639. if (motFecPktCopyTransmit (pDrvCtrl, pMblk, fragNum, pktType) == ERROR)
  1640.     {
  1641.     goto motFecSendError;
  1642.     }
  1643. }
  1644.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1645.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...Donen"), 1, 2, 3, 4, 5, 6);
  1646.     return (OK);
  1647. motFecSendError:
  1648.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1649.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1650.     return (END_ERR_BLOCK);
  1651.     }
  1652. /******************************************************************************
  1653. *
  1654. * motFecPktTransmit - transmit a packet
  1655. *
  1656. * This routine transmits the packet described by the given parameters
  1657. * over the network, without copying the mBlk to the driver's buffer.
  1658. * It also updates statistics.
  1659. *
  1660. * RETURNS: OK, or ERROR if no resources were available.
  1661. */
  1662. LOCAL STATUS motFecPktTransmit
  1663.     (
  1664.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1665.     M_BLK *  pMblk,          /* pointer to the mBlk */
  1666.     UINT8  fragNum, /* number of fragments */
  1667.     UINT16  pktType /* packet type */
  1668.     )
  1669.     {
  1670.     int bufLen = 0; /* length of this fragment */
  1671.     int pktLen = 0; /* length of this packet */
  1672.     int totLen = 0; /* length of data to be sent */
  1673.     char * pBuf = NULL; /* pointer to data to be sent */
  1674.     MOT_FEC_TBD_ID pTbd = NULL; /* pointer to the current ready TBD */
  1675.     MOT_FEC_TBD_LIST_ID pTbdList = NULL;/* pointer to the TBD list*/
  1676.     UINT16 tbdStatus; /* holder for the TBD status */
  1677.     M_BLK * pCurr = pMblk; /* holder for the current mBlk */
  1678.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...n"), 1, 2, 3, 4, 5, 6);
  1679.     /* get the current free TBD */
  1680.     pTbdList = motFecTbdListSet (pDrvCtrl, fragNum);
  1681.     if (pTbdList == (MOT_FEC_TBD_LIST_ID) NULL)
  1682. {
  1683. /* set to stall condition */
  1684. pDrvCtrl->txStall = TRUE;
  1685. return (ERROR);
  1686. }
  1687.     /* store the Mblk pointer */
  1688.     pTbdList->pBuf = (UCHAR *) pMblk;
  1689.     pTbdList->bufType = BUF_TYPE_MBLK;
  1690.     /* store the packet type */
  1691.     pTbdList->pktType = pktType;
  1692.     pCurr = pMblk;
  1693.     /* get the total packet length */
  1694.     pktLen = pMblk->mBlkPktHdr.len;
  1695.     /* for each mBlk fragment, set up the related TBD */
  1696.     while (fragNum > 0)
  1697. {
  1698. pBuf = pCurr->mBlkHdr.mData;
  1699. bufLen = pCurr->mBlkHdr.mLen;
  1700. pCurr = ((M_BLK *) pCurr->mBlkHdr.mNext);
  1701. /*
  1702.  * skip fragments that contain no data (SPR 29513).
  1703.  * fragments without data were not counted in motFecMblkWalk()
  1704.  */
  1705. if (bufLen == 0)
  1706.     continue;
  1707. /* just in case we have to pad it */
  1708. totLen += bufLen;
  1709. /* flush the cache, if necessary */
  1710. MOT_FEC_CACHE_FLUSH (pBuf, bufLen);
  1711. /* get and set up the current TBD */
  1712. pTbd = pTbdList->pTbd;
  1713. MOT_FEC_BD_LONG_WR (pTbd, MOT_FEC_BD_ADDR_OFF, (UINT32) pBuf);
  1714. MOT_FEC_BD_WORD_RD (pTbd, MOT_FEC_BD_STAT_OFF, tbdStatus);
  1715. /*
  1716.  * complete TBD construction based on whether or not this is the last
  1717.  * fragment
  1718.  */
  1719. if (--fragNum > 0)
  1720.     {
  1721.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend more mblks n"),
  1722.   1, 2, 3, 4, 5, 6);
  1723.     MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_LEN_OFF, (UINT32) bufLen);
  1724.     MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF,
  1725. (tbdStatus | MOT_FEC_TBD_RDY));
  1726.     }
  1727. else
  1728.     {
  1729.     if (totLen < ETHERSMALL)
  1730. bufLen = max (bufLen, (ETHERSMALL - totLen + bufLen));
  1731.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend last len=0x%xn"),
  1732.   bufLen, 2, 3, 4, 5, 6);
  1733.     MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_LEN_OFF, (UINT32) bufLen);
  1734.     MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF,
  1735. (MOT_FEC_TBD_LAST | MOT_FEC_TBD_CRC
  1736. | MOT_FEC_TBD_RDY | tbdStatus));
  1737.     }
  1738. /* move on to the next element */
  1739. pTbdList = pTbdList->pNext;
  1740. }
  1741.     /* kick the transmitter */
  1742.     MOT_FEC_TX_ACTIVATE;
  1743.     /* Flush the write pipe */
  1744.     CACHE_PIPE_FLUSH ();
  1745.     /* up-date statistics */
  1746.     if (pktType == PKT_TYPE_MULTI)
  1747. {
  1748. pDrvCtrl->endObj.mib2Tbl.ifOutNUcastPkts += 1;
  1749. }
  1750.     else
  1751. {
  1752. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1753. }
  1754.     return (OK);
  1755.     }
  1756. /******************************************************************************
  1757. *
  1758. * motFecPktCopyTransmit - copy and transmit a packet
  1759. *
  1760. * This routine transmits the packet described by the given parameters
  1761. * over the network, after copying the mBlk to the driver's buffer.
  1762. * It also updates statistics.
  1763. *
  1764. * RETURNS: OK, or ERROR if no resources were available.
  1765. */
  1766. LOCAL STATUS motFecPktCopyTransmit
  1767.     (
  1768.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1769.     M_BLK *  pMblk,          /* pointer to the mBlk */
  1770.     UINT8  fragNum, /* number of fragments */
  1771.     UINT16  pktType /* packet type */
  1772.     )
  1773.     {
  1774.     int len = 0; /* length of data to be sent */
  1775.     char * pBuf = NULL; /* pointer to data to be sent */
  1776.     MOT_FEC_TBD_ID pTbd = NULL; /* pointer to the current ready TBD */
  1777.     MOT_FEC_TBD_LIST_ID pTbdList = NULL;/* pointer to the TBD list*/
  1778.     UINT16 tbdStatus; /* holder for the TBD status */
  1779.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...n"), 1, 2, 3, 4, 5, 6);
  1780.     /* get a cluster buffer from the pool */
  1781.     pBuf = NET_BUF_ALLOC();
  1782.     if (pBuf == NULL)
  1783. {
  1784. /* set to stall condition */
  1785. pDrvCtrl->txStall = TRUE;
  1786. return (ERROR);
  1787. }
  1788.     /* get the current free TBD list */
  1789.     pTbdList = motFecTbdListSet (pDrvCtrl, fragNum);
  1790.     if (pTbdList == (MOT_FEC_TBD_LIST_ID) NULL)
  1791. {
  1792. /* set to stall condition */
  1793.         NET_BUF_FREE ((UCHAR *) pBuf);
  1794. pDrvCtrl->txStall = TRUE;
  1795. return (ERROR);
  1796. }
  1797.     /* store the packet type */
  1798.     pTbdList->pktType = pktType;
  1799.     /* store the buffer pointer and its type */
  1800.     pTbdList->bufType = BUF_TYPE_CL;
  1801.     pTbdList->pBuf = (UINT8 *)pBuf;
  1802.     /* copy data and free the Mblk */
  1803.     len = netMblkToBufCopy (pMblk, (char *) pBuf, NULL);
  1804.     netMblkClChainFree (pMblk);
  1805.     len = max (ETHERSMALL, len);
  1806.     /* flush the cache, if necessary */
  1807.     MOT_FEC_CACHE_FLUSH (pBuf, len);
  1808.     /* get and set up the current TBD */
  1809.     pTbd = pTbdList->pTbd;
  1810.     MOT_FEC_BD_LONG_WR (pTbd, MOT_FEC_BD_ADDR_OFF, (UINT32) pBuf);
  1811.     MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_LEN_OFF, (UINT32) len);
  1812.     MOT_FEC_BD_WORD_RD (pTbd, MOT_FEC_BD_STAT_OFF, tbdStatus);
  1813.     MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF,
  1814. (MOT_FEC_TBD_LAST | MOT_FEC_TBD_CRC
  1815. | MOT_FEC_TBD_RDY | tbdStatus));
  1816.     /* kick the transmitter */
  1817.     MOT_FEC_TX_ACTIVATE;
  1818.     /* Flush the write pipe */
  1819.     CACHE_PIPE_FLUSH ();
  1820.     /* up-date statistics */
  1821.     if (pktType == PKT_TYPE_MULTI)
  1822. {
  1823. pDrvCtrl->endObj.mib2Tbl.ifOutNUcastPkts += 1;
  1824. }
  1825.     else
  1826. {
  1827. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1828. }
  1829.     return (OK);
  1830.     }
  1831. /******************************************************************************
  1832. *
  1833. * motFecMblkWalk - walk the mBlk
  1834. *
  1835. * This routine walks the mBlk whose address is in <pMblk>, computes
  1836. * the number of fragments it is made of, and returns it in the parameter
  1837. * <pFragNum>. In addition, it finds out whether the specified packet
  1838. * is unicast or multicast, and sets <pPktType> accordingly.
  1839. *
  1840. * RETURNS: OK, or ERROR in case of invalid mBlk.
  1841. */
  1842. LOCAL STATUS motFecMblkWalk
  1843.     (
  1844.     M_BLK *  pMblk,          /* pointer to the mBlk */
  1845.     UINT8 * pFragNum, /* number of fragments */
  1846.     UINT16 * pPktType /* packet type */
  1847.     )
  1848.     {
  1849.     M_BLK * pCurr = pMblk; /* the current mBlk */
  1850.     if (pMblk == NULL)
  1851.         {
  1852.         MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend: invalid pMblkn"),
  1853.                                       0, 0, 0, 0, 0, 0);
  1854. return (ERROR);
  1855.         }
  1856.     /* walk this mBlk */
  1857.     while (pCurr != NULL)
  1858. {
  1859. /*
  1860.  * keep track of the number of fragments in this mBlk.
  1861.  * Do not count fragments with no data (SPR 29513)
  1862.  */
  1863. if (pCurr->mBlkHdr.mLen != 0)
  1864.     (*pFragNum)++;
  1865. pCurr = ((M_BLK *) pCurr->mBlkHdr.mNext);
  1866. }
  1867.     /* set the packet type to multicast or unicast */
  1868.     if (pMblk->mBlkHdr.mData[0] & (UINT8) 0x01)
  1869. {
  1870. (*pPktType) = PKT_TYPE_MULTI;
  1871. }
  1872.     else
  1873. {
  1874. (*pPktType) = PKT_TYPE_UNI;
  1875. }
  1876.     return (OK);
  1877.     }
  1878. /******************************************************************************
  1879. *
  1880. * motFecTbdListSet - set up a list of available transmit descriptors
  1881. *
  1882. * This routine sets up a list of available buffer descriptors for use by
  1883. * the send routine.
  1884. *
  1885. * RETURNS: a pointer to a transmit descriptors list, or NULL.
  1886. */
  1887. LOCAL MOT_FEC_TBD_LIST_ID motFecTbdListSet
  1888.     (
  1889.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1890.     UINT8 tbdNum  /* number of tbd */
  1891.     )
  1892.     {
  1893.     MOT_FEC_TBD_ID pTbd = NULL; /* pointer to the current TBD */
  1894.     UINT16 tbdIndex = pDrvCtrl->tbdIndex; /* TBD index */
  1895.     UINT16 nextIndex = 0; /* index to the next TBD */
  1896.     UINT16 currIndex = 0; /* index to the current TBD */
  1897.     UINT16 i = 0; /* an index */
  1898.     MOT_FEC_TBD_LIST_ID pTbdList = NULL;
  1899.     /* set the number of TBDs in this list */
  1900.     pDrvCtrl->pTbdList [tbdIndex]->fragNum = tbdNum;
  1901.     /* initialize the list */
  1902.     for (i = 0; i < tbdNum; i++)
  1903. {
  1904. /* get the current free TBD */
  1905. if ((pTbd = motFecTbdGet (pDrvCtrl)) == NULL)
  1906.     {
  1907.     return (NULL);
  1908.     }
  1909. currIndex = pDrvCtrl->tbdIndex;
  1910. nextIndex = (currIndex + 1) % (pDrvCtrl->tbdNum);
  1911. pTbdList = pDrvCtrl->pTbdList [currIndex];
  1912. pTbdList->pTbd = pTbd;
  1913. pTbdList->pBuf = NULL;
  1914. pTbdList->pNext = pDrvCtrl->pTbdList [nextIndex];
  1915. /* update some indeces for a correct handling of the TBD ring */
  1916. pDrvCtrl->tbdIndex = (pDrvCtrl->tbdIndex + 1) % pDrvCtrl->tbdNum;
  1917. }
  1918. /* terminate the list properly */
  1919. pTbdList->pNext = NULL;
  1920. /* keep track of the clean TBDs */
  1921. pDrvCtrl->cleanTbdNum -= tbdNum;
  1922.     return (pDrvCtrl->pTbdList [tbdIndex]);
  1923.     }
  1924. /******************************************************************************
  1925. *
  1926. * motFecTbdGet - get the first available transmit descriptor
  1927. *
  1928. * This routine gets the first available buffer descriptor in the transmit
  1929. * ring. It checks the descriptor is owned by the host and it has been
  1930. * cleaned by the motFecTbdClean() routine.
  1931. *
  1932. * RETURNS: an available transmit descriptor, otherwise NULL.
  1933. */
  1934. LOCAL MOT_FEC_TBD_ID motFecTbdGet
  1935.     (
  1936.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1937.     )
  1938.     {
  1939.     MOT_FEC_TBD_ID nextTbd = NULL; /* holder for the next TBD */
  1940.     UINT16 tbdStatus; /* holder for the TBD status */
  1941.     MOT_FEC_NEXT_TBD (pDrvCtrl, nextTbd);
  1942.     /* Make cache consistent with memory */
  1943.     MOT_FEC_BD_CACHE_INVAL (nextTbd, MOT_FEC_TBD_SZ);
  1944.     MOT_FEC_BD_WORD_RD ((char *) nextTbd, MOT_FEC_BD_STAT_OFF, tbdStatus);
  1945.     if ((tbdStatus & MOT_FEC_TBD_RDY) == MOT_FEC_TBD_RDY)
  1946. {
  1947. MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend... not our Tbd n"),
  1948.       1, 2, 3, 4, 5, 6);
  1949. return (NULL);
  1950. }
  1951.     return ((MOT_FEC_TBD_ID) nextTbd);
  1952.     }
  1953. /******************************************************************************
  1954. *
  1955. * motFecTbdClean - clean the transmit buffer descriptors ring
  1956. *
  1957. * This routine is run in netTask's context. It cleans the transmit
  1958. * buffer descriptors ring. It also calls motFecTbdCheck() to check
  1959. * for any transmit errors, and possibly up-dates statistics.
  1960. *
  1961. * SEE ALSO: motFecTbdCheck()
  1962. *
  1963. * RETURNS: N/A.
  1964. */
  1965. LOCAL void motFecTbdClean
  1966.     (
  1967.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1968.     )
  1969.     {
  1970.     MOT_FEC_TBD_ID pUsedTbd; /* first used TBD */
  1971.     BOOL tbdError = FALSE; /* no error reported */
  1972.     UINT32  retVal = 0; /* return value */
  1973.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecTbdCleann"), 1, 2, 3, 4, 5, 6);
  1974.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  1975.     /* process all the consumed TBDs */
  1976.     while (pDrvCtrl->cleanTbdNum < pDrvCtrl->tbdNum)
  1977. {
  1978. MOT_FEC_TBD_LIST_ID pTbdList;
  1979. MOT_FEC_TBD_LIST_ID pTempList;
  1980. pTbdList = pDrvCtrl->pTbdList [pDrvCtrl->usedTbdIndex];
  1981. pTempList = pTbdList;
  1982. /* first, we detect abnormal events */
  1983. while (pTempList != NULL)
  1984.     {
  1985.     pUsedTbd = pTempList->pTbd;
  1986.     /* check on this TBD */
  1987.     retVal = motFecTbdCheck (pDrvCtrl, pUsedTbd);
  1988.     if (retVal == MOT_FEC_TBD_BUSY)
  1989. {
  1990. END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1991. return;
  1992. }
  1993.     if (retVal == MOT_FEC_TBD_ERROR)
  1994. {
  1995. tbdError = TRUE;
  1996. break;
  1997. }
  1998.     /* move on to the next element in the list */
  1999.     pTempList = pTempList->pNext;
  2000.     }
  2001.         /* free the Mblk or the cluster, whichever is appropriate */
  2002.         if ((pTbdList->bufType == ((UINT16) BUF_TYPE_MBLK))
  2003.     && (pTbdList->pBuf != NULL))
  2004.     {
  2005.     netMblkClChainFree ((M_BLK *) pTbdList->pBuf);
  2006.     pTbdList->pBuf = NULL;
  2007.     }
  2008. else
  2009.     {
  2010.     if ((pTbdList->bufType == ((UINT16) BUF_TYPE_CL))
  2011. && (pTbdList->pBuf != NULL))
  2012. {
  2013. /* it's a cluster */
  2014. NET_BUF_FREE (pTbdList->pBuf);
  2015. pTbdList->pBuf = NULL;
  2016. }
  2017.     }
  2018. /* correct statistics, if necessary */
  2019. if (tbdError == TRUE)
  2020.     {
  2021.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  2022.     if (pTbdList->pktType == PKT_TYPE_MULTI)
  2023. {
  2024. pDrvCtrl->endObj.mib2Tbl.ifOutNUcastPkts -= 1;
  2025. }
  2026.     else
  2027. {
  2028. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
  2029. }
  2030.     tbdError = FALSE;
  2031.     }
  2032. pTempList = pTbdList;
  2033. /* finally, we clean this TBD list */
  2034. while (pTempList != NULL)
  2035.     {
  2036.     pUsedTbd = pTempList->pTbd;
  2037.     /* clean this buffer descriptor, mirror motFecTbdInit() */
  2038.     if (pDrvCtrl->usedTbdIndex == (pDrvCtrl->tbdNum - 1))
  2039. {
  2040. MOT_FEC_BD_WORD_WR (pUsedTbd, MOT_FEC_BD_STAT_OFF,
  2041.     MOT_FEC_TBD_WRAP);
  2042. }
  2043.     else
  2044. {
  2045. MOT_FEC_BD_WORD_WR (pUsedTbd, MOT_FEC_BD_STAT_OFF, 0);
  2046. }
  2047.     /* update some indeces for a correct handling of the TBD ring */
  2048.     pDrvCtrl->cleanTbdNum++;
  2049.     pDrvCtrl->usedTbdIndex = (pDrvCtrl->usedTbdIndex + 1)
  2050.       % (pDrvCtrl->tbdNum);
  2051.     /* move on to the next element in the list */
  2052.     pTempList = pTempList->pNext;
  2053.     }
  2054. /* soon notify upper protocols TBDs are available */
  2055. if (pDrvCtrl->txStall)
  2056.     {
  2057.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("Restart mux n"),
  2058.   0, 0, 0, 0, 0, 0);
  2059.     (void) netJobAdd ((FUNCPTR) muxTxRestart,
  2060.       (int) &pDrvCtrl->endObj,
  2061.       0, 0, 0, 0);
  2062.     pDrvCtrl->txStall = FALSE;
  2063.     }
  2064. }
  2065.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  2066.     MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecTbdClean...Donen"),
  2067.   1, 2, 3, 4, 5, 6);
  2068.     }
  2069. /******************************************************************************
  2070. *
  2071. * motFecTbdCheck - check the transmit buffer descriptor
  2072. *
  2073. * This routine checks for any transmit errors by looking at the
  2074. * descriptor status.
  2075. *
  2076. * SEE ALSO: motFecTbdClean()
  2077. *
  2078. * RETURNS: MOT_FEC_TBD_OK, or MOT_FEC_TBD_BUSY if the specified TBD is
  2079. * not ready, or MOT_FEC_TBD_ERROR in case of errored TBD.
  2080. */
  2081. LOCAL UINT32 motFecTbdCheck
  2082.     (
  2083.     DRV_CTRL *   pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2084.     MOT_FEC_TBD_ID pUsedTbd /* holder for the first used TBD */
  2085.     )
  2086.     {
  2087.     UINT16 tbdStatus; /* holder for the TBD status */
  2088.     /* Make cache consistent with memory */
  2089.     MOT_FEC_BD_CACHE_INVAL (pUsedTbd, MOT_FEC_TBD_SZ);
  2090.     MOT_FEC_BD_WORD_RD ((char *) pUsedTbd, MOT_FEC_BD_STAT_OFF, tbdStatus);
  2091.     /* if it's not ready, don't touch it! */
  2092.     if ((tbdStatus & MOT_FEC_TBD_RDY) == MOT_FEC_TBD_RDY)
  2093. {
  2094. return (MOT_FEC_TBD_BUSY);
  2095. }
  2096. #ifdef MOT_FEC_DBG
  2097.     if ((tbdStatus & MOT_FEC_TBD_LC) == MOT_FEC_TBD_LC)
  2098. {
  2099. MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecTbdCheck: late collisionn"),
  2100.       1, 2, 3, 4, 5, 6);
  2101. MOT_FEC_TX_LC_ADD;
  2102. }
  2103.     if ((tbdStatus & MOT_FEC_TBD_RL) == MOT_FEC_TBD_RL)
  2104. {
  2105. MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecTbdCheck: retransmit limit"),
  2106.       1, 2, 3, 4, 5, 6);
  2107. MOT_FEC_TX_RL_ADD;
  2108. }
  2109.     if ((tbdStatus & MOT_FEC_TBD_UN) == MOT_FEC_TBD_UN)
  2110. {
  2111. MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecTbdCheck: tx underrunn"),
  2112.       1, 2, 3, 4, 5, 6);
  2113. MOT_FEC_TX_UR_ADD;
  2114. }
  2115.     if ((tbdStatus & MOT_FEC_TBD_CSL) == MOT_FEC_TBD_CSL)
  2116. {
  2117. MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecTbdCheck: carrier sense n"),
  2118.       1, 2, 3, 4, 5, 6);
  2119. MOT_FEC_TX_CSL_ADD;
  2120. }
  2121. #endif /* MOT_FEC_DBG */
  2122.     /* in case of errors, report it to the calling routine */
  2123.     if (tbdStatus & (MOT_FEC_TBD_LC |
  2124.      MOT_FEC_TBD_RL |
  2125.      MOT_FEC_TBD_UN |
  2126.      MOT_FEC_TBD_CSL))
  2127. {
  2128. return (MOT_FEC_TBD_ERROR);
  2129. }
  2130.     return (MOT_FEC_TBD_OK);
  2131.     }
  2132. /**************************************************************************
  2133. *
  2134. * motFecTbdInit - initialize the transmit buffer ring
  2135. *
  2136. * This routine initializes the transmit buffer descriptors ring.
  2137. *
  2138. * SEE ALSO: motFecRbdInit()
  2139. *
  2140. * RETURNS: OK, always.
  2141. */
  2142. LOCAL STATUS motFecTbdInit
  2143.     (
  2144.     DRV_CTRL *  pDrvCtrl        /* pointer to DRV_CTRL structure */
  2145.     )
  2146.     {
  2147.     UINT16 ix; /* a counter */
  2148.     MOT_FEC_TBD_ID pTbd; /* generic TBD pointer */
  2149.     /* carve up the shared-memory region */
  2150.     pDrvCtrl->tbdBase = pTbd = (MOT_FEC_TBD_ID) pDrvCtrl->pBufBase;
  2151.     for (ix = 0; ix < pDrvCtrl->tbdNum; ix++)
  2152. {
  2153. /*
  2154.  * put a fragment of each frame in a single buffer and
  2155.  * generate the 4-byte CRC at the end of each frame.
  2156.  * Do not make it ready for transmission yet.
  2157.  */
  2158. MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF, 0);
  2159. pTbd += MOT_FEC_TBD_SZ;
  2160. /* get memory for the TBD list */
  2161. pDrvCtrl->pTbdList [ix] = (MOT_FEC_TBD_LIST_ID)
  2162.    calloc (sizeof (MOT_FEC_TBD_LIST), 1);
  2163. }
  2164.     /* have the last TBD to close the ring */
  2165.     pTbd -= MOT_FEC_TBD_SZ;
  2166.     MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF,
  2167. (MOT_FEC_TBD_WRAP | 0));
  2168.     /* get a cluster buffer from the pool */
  2169.     pDrvCtrl->pTxPollBuf = (UINT8 *)NET_BUF_ALLOC();
  2170.     return (OK);
  2171.     }
  2172. /******************************************************************************
  2173. *
  2174. * motFecRxTxHandle - service task-level interrupts for rx and tx frames
  2175. *
  2176. * This routine is run in netTask's context.  The ISR scheduled
  2177. * this routine so that it could handle receive and transmit packets
  2178. * at task level.
  2179. *
  2180. * RETURNS: N/A
  2181. */
  2182. LOCAL void motFecRxTxHandle
  2183.     (
  2184.     DRV_CTRL *  pDrvCtrl /* pointer to DRV_CTRL structure */
  2185.     )
  2186.     {
  2187.     int         intLevel; /* current intr level */
  2188.     UINT32 event = 0; /* event intr register */
  2189.     UINT32 mask = 0; /* holder for the mask intr register */
  2190.     MOT_FEC_LOG (MOT_FEC_DBG_RX, ("motFecRxTxHandle: n"),
  2191.   0, 0, 0, 0, 0, 0);
  2192.     /* while tx/rx interrupts to be processed */
  2193. motFecRxTxProcess:
  2194.     motFecHandleRecvInt (pDrvCtrl);
  2195.     motFecTbdClean (pDrvCtrl);
  2196.     intLevel = intLock();
  2197.     /* 
  2198.      * This piece of code is to deal with any events that have occurred 
  2199.      * since the events were masked off in the ISR. These events will 
  2200.      * have occurred but no interrupt would have been generated. 
  2201.      */
  2202.     MOT_FEC_CSR_RD (MOT_FEC_EVENT_OFF, event);
  2203.     /* clear all interrupts */
  2204.     MOT_FEC_CSR_WR (MOT_FEC_EVENT_OFF, (event & MOT_FEC_EVENT_MSK));
  2205.     if (((event & MOT_FEC_EVENT_TXF) == MOT_FEC_EVENT_TXF) ||
  2206. ((event & MOT_FEC_EVENT_RXF) == MOT_FEC_EVENT_RXF))
  2207. {
  2208. intUnlock (intLevel);
  2209. goto motFecRxTxProcess;
  2210. }
  2211.     else
  2212. {
  2213. /* re-enable receive and transmit interrupts */
  2214. MOT_FEC_CSR_RD (MOT_FEC_MASK_OFF, mask);
  2215. MOT_FEC_CSR_WR (MOT_FEC_MASK_OFF, (mask | MOT_FEC_EVENT_TXF
  2216.    | MOT_FEC_EVENT_RXF));
  2217. /* Flush the write pipe */
  2218. CACHE_PIPE_FLUSH ();
  2219. intUnlock (intLevel);
  2220. }
  2221.     }
  2222. /******************************************************************************
  2223. *
  2224. * motFecHandleRecvInt - service task-level interrupts for receive frames
  2225. *
  2226. * This routine is run in netTask's context. It is called by motFecRxTxHandle()
  2227. * so that it could handle receive packets at task level.
  2228. *
  2229. * RETURNS: N/A
  2230. */
  2231. LOCAL void motFecHandleRecvInt
  2232.     (
  2233.     DRV_CTRL *  pDrvCtrl /* pointer to DRV_CTRL structure */
  2234.     )
  2235.     {
  2236.     MOT_FEC_RBD_ID pUsedRbd; /* a used rbd pointer */
  2237.     UINT16 rbdStatus = 0; /* holder for the status of this rbd */
  2238.     UINT32 rxStatus = 0; /* holder for the receiver status */
  2239.     UINT32 event = 0; /* event intr register */
  2240.     int          intLevel; /* current intr level */
  2241.     MOT_FEC_LOG (MOT_FEC_DBG_RX, ("motFecHandleRecvInt: n"),
  2242.   0, 0, 0, 0, 0, 0);
  2243.     /* while RBDs to be processed */
  2244.     do
  2245.         {
  2246. /* get the first used RBD */
  2247. MOT_FEC_NEXT_RBD (pDrvCtrl, pUsedRbd);
  2248. /* Make cache consistent with memory */
  2249. MOT_FEC_BD_CACHE_INVAL (pUsedRbd, MOT_FEC_RBD_SZ);
  2250. /* read the RBD status word */
  2251. MOT_FEC_BD_WORD_RD (pUsedRbd, MOT_FEC_BD_STAT_OFF,
  2252.     rbdStatus);
  2253.         /* if it's not ready, don't touch it! */
  2254. if ((rbdStatus & MOT_FEC_RBD_EMPTY) == MOT_FEC_RBD_EMPTY)
  2255.     {
  2256.     break;
  2257.     }
  2258. /* process this RBD */
  2259. motFecReceive (pDrvCtrl, pUsedRbd);
  2260. } while (TRUE);
  2261.     /* kick receiver (if needed) */
  2262.     MOT_FEC_CSR_RD (MOT_FEC_RX_ACT_OFF, rxStatus);
  2263.     if (!(rxStatus & MOT_FEC_RX_ACT))
  2264. {
  2265.         MOT_FEC_LOG (MOT_FEC_DBG_RX, ("motFecHandleRecvInt: RU NOT READYn"),
  2266.       0, 0, 0, 0, 0, 0);
  2267. MOT_FEC_RX_ACTIVATE;
  2268. }
  2269.     /* Flush the write pipe */
  2270.     CACHE_PIPE_FLUSH ();
  2271.     MOT_FEC_LOG (MOT_FEC_DBG_RX, ("motFecHandleRecvInt... Done, n"),
  2272.   0, 0, 0, 0, 0, 0);
  2273.     }
  2274. /******************************************************************************
  2275. *
  2276. * motFecReceive - pass a received frame to the next layer up
  2277. *
  2278. * This routine hands the packet off to the upper layer after cleaning the
  2279. * RBD that was used for its reception.
  2280. *
  2281. * RETURNS: N/A
  2282. */
  2283. LOCAL void motFecReceive
  2284.     (
  2285.     DRV_CTRL *   pDrvCtrl,       /* pointer to DRV_CTRL structure */
  2286.     MOT_FEC_RBD_ID      pUsedRbd        /* pointer to a RBD */
  2287.     )
  2288.     {
  2289.     char * pData = NULL; /* a rx data pointer */
  2290.     char * pBuf = NULL; /* a rx data pointer */
  2291.     M_BLK_ID pMblk  = NULL; /* mBlock pointer */
  2292.     CL_BLK_ID pClBlk = NULL; /* cluster block pointer */
  2293.     UINT16 rbdStatus = 0; /* holder for the status of this RBD */
  2294.     UINT16 rbdLen = 0; /* number of bytes received by this RBD */
  2295.     void * retVal = NULL; /* convenient holder for return value */
  2296.     MOT_FEC_LOG (MOT_FEC_DBG_RX, ("motFecReceive rbdIndex=%dn"),
  2297.   pDrvCtrl->rbdIndex, 0, 0, 0, 0, 0);
  2298.     /* pass the packet up only if reception was Ok */
  2299.     MOT_FEC_BD_WORD_RD (pUsedRbd, MOT_FEC_BD_STAT_OFF,
  2300. rbdStatus);
  2301.     if (rbdStatus & MOT_FEC_RBD_ERR)
  2302. {