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

VxWorks

开发平台:

C/C++

  1. /* motFccEnd.c - END style Motorola FCC Ethernet network interface driver */
  2. /* Copyright 1989-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01n,07dec01,rcs  added muxError() call to alert the mux that the driver has 
  8.                  exhausted its clusters.  SPR# 70254 and  SPR# 30004
  9. 01m,30nov01,rcs  replaced motFccEnd.c with m8260FccEnd.c and added 
  10.                  motFccJobQInit(), motFccJobQAdd(), and motFccJobQueue() 
  11. 01l,26nov01,rcs  created _func_m82xxDpramLib.c from target/src/mem  
  12. 01k,09nov01,rcs  made load string parameters mblkMult and clMult optional  
  13. 01j,07nov01,rcs  formatted code to conform to WRS coding conventions.
  14. 01i,30oct01,g_h  Removing in-line assembly.
  15. 01h,12oct01,g_h  Change inline assembly macro
  16. 01g,17sep01,g_h  add support to use without DPRAM lib
  17. 01f,13sep01,gev  fix SPR 70254
  18. 01e,17jul01,g_h  change to use the DPRAM lib.
  19. 01d,10may01,g_h  rename to m8260FccEnd.c
  20. 01c,17apr01,g_h  in motFccInitMem() change the memory allocation from memalign() to
  21.                  cacheDmaMalloc() 
  22. 01b,08mar01,g_h  modified to run from ROM
  23. 01a,18jan01,g_h  written from motFecEnd.c, 01c.
  24. */
  25. /*
  26. DESCRIPTION
  27. This module implements a Motorola Fast Communication Controller (FCC) 
  28. Ethernet network interface driver. The FCC supports several communication
  29. protocols, and when progammed to operate in Ethernet mode, it is fully 
  30. compliant with the IEEE 802.3u 10Base-T and 100Base-T specifications. 
  31. The FCC establishes a shared memory communication system with the CPU,
  32. which may be divided into three parts: a set of Control/Status Registers (CSR)
  33. and FCC-specific parameters, the buffer descriptors (BD), and the data buffers. 
  34. Both the CSRs and the internal parameters reside in the MPC8260's internal 
  35. RAM. They are used for mode control and to extract status information 
  36. of a global nature. For instance, the types of events that should 
  37. generate an interrupt, or features like the promiscous mode or the 
  38. hearthbeat control may be set programming some of the CSRs properly. 
  39. Pointers to both the Transmit Buffer Descriptors ring (TBD) and the
  40. Receive Buffer Descriptors ring (RBD) are stored in the internal parameter 
  41. RAM. The latter also includes protocol-specific parameters, like the 
  42. individual physical address of this station or the max receive frame length.
  43. The BDs are used to pass data buffers and related buffer information
  44. between the hardware and the software. They may reside either on the 60x
  45. bus, or on the CPM local bus They include local status information and a 
  46. pointer to the incoming or outgoing data buffers. These are located again 
  47. in external memory, and the user may chose whether this is on the 60x bus, 
  48. or the CPM local bus (see below).
  49. This driver is designed to be moderately generic. Without modification, it can
  50. operate across all the FCCs in the MPC8260, regardless of where the internal 
  51. memory base address is located. To achieve this goal, this driver must be 
  52. given several target-specific parameters, and some external support routines 
  53. must be provided.  These parameters, and the mechanisms used to communicate 
  54. them to the driver, are detailed below.
  55. This network interface driver does not include support for trailer protocols
  56. or data chaining.  However, buffer loaning has been implemented in an effort
  57. to boost performance. In addition, no copy is performed of the outgoing packet
  58. before it is sent.
  59.  
  60. BOARD LAYOUT
  61. This device is on-board.  No jumpering diagram is necessary.
  62. EXTERNAL INTERFACE
  63. The driver provides the standard external interface, motFccEndLoad(), which
  64. takes a string of colon-separated parameters. The parameters should be
  65. specified in hexadecimal, optionally preceeded by "0x" or a minus sign "-".
  66. The parameter string is parsed using strtok_r() and each parameter is
  67. converted from a string representation to binary by a call to
  68. strtoul(parameter, NULL, 16).
  69. The format of the parameter string is:
  70. "<immrVal>:<fccNum>:<bdBase>:<bdSize>:<bufBase>:<bufSize>:<fifoTxBase>:
  71. <fifoRxBase> :<tbdNum>:<rbdNum>:<phyAddr>:<phyDefMode>:<userFlags>:
  72. <mblkMult>:<clMult>:<txJobMsgQLen>"
  73. TARGET-SPECIFIC PARAMETERS
  74. .IP <immrVal>
  75. Indicates the address at which the host processor presents its internal 
  76. memory (also known as the internal RAM base address). With this address, 
  77. and the fccNum (see below), the driver is able to compute the location of 
  78. the FCC parameter RAM, and, ultimately, to program the FCC for proper 
  79. operations. 
  80. .IP <fccNum>
  81. This driver is written to support multiple individual device units.
  82. This parameter is used to explicitly state which FCC is being used (on the
  83. vads8260 board, FCC2 is wired to the Fast Ethernet tranceiver, thus this 
  84. parameter equals "2").
  85. .IP <bdBase>
  86. The Motorola Fast Communication Controller is a DMA-type device and typically 
  87. shares access to some region of memory with the CPU. This driver is designed
  88. for systems that directly share memory between the CPU and the FCC.
  89. This parameter tells the driver that space for both the TBDs and the 
  90. RBDs needs not be allocated but should be taken from a cache-coherent 
  91. private memory space provided by the user at the given address. The user 
  92. should be aware that memory used for buffers descriptors must be 8-byte 
  93. aligned and non-cacheable. Therefore, the given memory space should allow
  94. for all the buffer descriptors and the 8-byte alignment factor.
  95. If this parameter is "NONE", space for buffer descriptors is obtained 
  96. by calling cacheDmaMalloc() in motFccEndLoad().
  97. .IP <bdSize>
  98. The memory size parameter specifies the size of the pre-allocated memory
  99. region for the BDs. If <bdBase> is specified as NONE (-1), the driver ignores 
  100. this parameter. Otherwise, the driver checks the size of the provided memory 
  101. region is adequate with respect to the given number of Transmit Buffer
  102. Descriptors and Receive Buffer Descriptors.
  103. .IP <bufBase>
  104. This parameter tells the driver that space for data buffers
  105. needs not be allocated but should be taken from a cache-coherent 
  106. private memory space provided by the user at the given address. The user 
  107. should be aware that memory used for buffers must be 32-byte 
  108. aligned and non-cacheable. The FCC poses one more constraint in that DMA
  109. cycles may initiate even when all the incoming data have already been 
  110. transferred to memory. This means that at most 32 bytes of memory at the end of
  111. each receive data buffer, may be overwritten during reception. The driver
  112. pads that area out, thus consuming some additional memory.
  113. If this parameter is "NONE", space for buffer descriptors is obtained 
  114. by calling memalign() in motFccEndLoad().
  115. .IP <bufSize>
  116. The memory size parameter specifies the size of the pre-allocated memory
  117. region for data buffers. If <bufBase> is specified as NONE (-1), the driver 
  118. ignores this parameter. Otherwise, the driver checks the size of the provided 
  119. memory region is adequate with respect to the given number of Receive Buffer 
  120. Descriptors and a non-user-configurable number of trasmit buffers 
  121. (MOT_FCC_TX_CL_NUM).  All the above should fit in the given memory space. 
  122. This area should also include room for buffer management structures.
  123. .IP <fifoTxBase>
  124. Indicate the base location of the transmit FIFO, in internal memory.
  125. The user does not need to initialize this parameter, as the default
  126. value (see MOT_FCC_FIFO_TX_BASE) is highly optimized for best performance.
  127. However, if the user wishes to reserve that very area in internal RAM for 
  128. other purposes, he may set this parameter to a different value. 
  129. If <fifoTxBase> is specified as NONE (-1), the driver uses the default
  130. value.
  131. .IP <fifoRxBase>
  132. Indicate the base location of the receive FIFO, in internal memory.
  133. The user does not need to initialize this parameter, as the default
  134. value (see MOT_FCC_FIFO_TX_BASE) is highly optimized for best performance.
  135. However, if the user wishes to reserve that very area in internal RAM for 
  136. other purposes, he may set this parameter to a different value. 
  137. If <fifoRxBase> is specified as NONE (-1), the driver uses the default
  138. value.
  139. .IP <tbdNum>
  140. This parameter specifies the number of transmit buffer descriptors (TBDs). 
  141. Each buffer descriptor resides in 8 bytes of the processor's external
  142. RAM space, If this parameter is less than a minimum number specified in the 
  143. macro MOT_FCC_TBD_MIN, or if it is "NULL", a default value of 64 (see
  144. MOT_FCC_TBD_DEF_NUM) is used. This number is kept deliberately high, since 
  145. each packet the driver sends may consume more than a single TBD. This 
  146. parameter should always equal a even number.
  147. .IP  <rbdNum>
  148. This parameter specifies the number of receive buffer descriptors (RBDs). 
  149. Each buffer descriptor resides in 8 bytes of the processor's external
  150. RAM space, and each one points to a 1584-byte buffer again in external 
  151. RAM. If this parameter is less than a minimum number specified in the 
  152. macro MOT_FCC_RBD_MIN, or if it is "NULL", a default value of 32 (see
  153. MOT_FCC_RBD_DEF_NUM) is used. This parameter should always equal a even number.
  154. .IP  <phyAddr>
  155. This parameter specifies the logical address of a MII-compliant physical
  156. device (PHY) that is to be used as a physical media on the network.
  157. Valid addresses are in the range 0-31. There may be more than one device
  158. under the control of the same management interface. The default physical 
  159. layer initialization routine will scan the whole range of PHY devices 
  160. starting from the one in <phyAddr>. If this parameter is 
  161. "MII_PHY_NULL", the default physical layer initialization routine will find 
  162. out the PHY actual address by scanning the whole range. The one with the lowest
  163. address will be chosen.
  164. .IP  <phyDefMode>
  165. This parameter specifies the operating mode that will be set up
  166. by the default physical layer initialization routine in case all
  167. the attempts made to establish a valid link failed. If that happens,
  168. the first PHY that matches the specified abilities will be chosen to
  169. work in that mode, and the physical link will not be tested.
  170.  
  171. .IP  <pAnOrderTbl>
  172. This parameter may be set to the address of a table that specifies the 
  173. order how different subsets of technology abilities should be advertised by
  174. the auto-negotiation process, if enabled. Unless the flag <MOT_FCC_USR_PHY_TBL>
  175. is set in the userFlags field of the load string, the driver ignores this
  176. parameter.
  177. The user does not normally need to specify this parameter, since the default
  178. behaviour enables auto-negotiation process as described in IEEE 802.3u.
  179. .IP  <userFlags>
  180. This field enables the user to give some degree of customization to the
  181. driver.
  182. .IP <mblkMult>
  183. Ratio between mBlk's and Rx BD's
  184. .IP <clMult>
  185. Ratio between Clusters and Rx BD's
  186. .IP <txJobMsgQLen>
  187. Length of the message queue from the ISR to motFccJobQueue()
  188. MOT_FCC_USR_DPRAM_ALOC: This option allows multiple FCCs operating in the same 
  189. system to share the Dual Ported RAM. It enables Dual Ported RAM allocation and 
  190. freeing using the  utilities m82xxDpramFccMalloc, m82xxDpramFree, and 
  191. m82xxDpramFccFree via the function pointers _func_m82xxDpramFccMalloc, 
  192. _func_m82xxDpramFree, and _func_m82xxDpramFccFree which must be loaded by the 
  193. BSP if this option is used.
  194.  
  195. MOT_FCC_USR_PHY_NO_AN: the default physical layer initialization
  196. routine will exploit the auto-negotiation mechanism as described in
  197. the IEEE Std 802.3u, to bring a valid link up. According to it, all
  198. the link partners on the media will take part to the negotiation
  199. process, and the highest priority common denominator technology ability
  200. will be chosen. If the user wishes to prevent auto-negotiation from
  201. occurring, he may set this bit in the user flags.
  202.  
  203. MOT_FCC_USR_PHY_TBL: in the auto-negotiation process, PHYs
  204. advertise all their technology abilities at the same time,
  205. and the result is that the maximum common denominator is used. However,
  206. this behaviour may be changed, and the user may affect the order how
  207. each subset of PHY's abilities is negotiated. Hence, when the
  208. MOT_FCC_USR_PHY_TBL bit is set, the default physical layer
  209. initialization routine will look at the motFccAnOrderTbl[] table and
  210. auto-negotiate a subset of abilities at a time, as suggested by the
  211. table itself. It is worth noticing here, however, that if the
  212. MOT_FCC_USR_PHY_NO_AN bit is on, the above table will be ignored.
  213.  
  214. MOT_FCC_USR_PHY_NO_FD: the PHY may be set to operate in full duplex mode,
  215. provided it has this ability, as a result of the negotiation with other
  216. link partners. However, in this operating mode, the FCC will ignore the
  217. collision detect and carrier sense signals. If the user wishes not to
  218. negotiate full duplex mode, he should set the MOT_FCC_USR_PHY_NO_FD bit
  219. in the user flags.
  220.  
  221. MOT_FCC_USR_PHY_NO_HD: the PHY may be set to operate in half duplex mode,
  222. provided it has this ability, as a result of the negotiation with other link
  223. partners. If the user wishes not to negotiate half duplex mode, he should
  224. set the MOT_FCC_USR_PHY_NO_HD bit in the user flags.
  225.  
  226. MOT_FCC_USR_PHY_NO_100: the PHY may be set to operate at 100Mbit/s speed,
  227. provided it has this ability, as a result of the negotiation with
  228. other link partners. If the user wishes not to negotiate 100Mbit/s speed,
  229. he should set the MOT_FCC_USR_PHY_NO_100 bit in the user flags.
  230.  
  231. MOT_FCC_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_FCC_USR_PHY_NO_10 bit in the user flags.
  235.  
  236. MOT_FCC_USR_PHY_ISO: some boards may have different PHYs controlled by the
  237. same management interface. In some cases, there may be the need of
  238. electrically isolating some of them from the interface itself, in order
  239. to guarantee a proper behaviour on the medium layer. If the user wishes to
  240. electrically isolate all PHYs from the MII interface, he should set the
  241. MOT_FCC_USR_PHY_ISO bit. The default behaviour is to not isolate any
  242. PHY on the board.
  243.  
  244. MOT_FCC_USR_LOOP: when the MOT_FCC_USR_LOOP bit is set, the driver will
  245. configure the FCC to work in internal loopback mode, with the TX signal 
  246. directly connected to the RX. This mode should only be used for testing.
  247.  
  248. MOT_FCC_USR_RMON: when the MOT_FCC_USR_RMON bit is set, the driver will
  249. configure the FCC to work in RMON mode, thus collecting network statistics
  250. required for RMON support without the need to receive all packets as in
  251. promiscous mode.
  252.  
  253. MOT_FCC_USR_BUF_LBUS: when the MOT_FCC_USR_BUF_LBUS bit is set, the driver will
  254. configure the FCC to work as though the data buffers were located in the 
  255. CPM local bus.
  256. MOT_FCC_USR_BD_LBUS: when the MOT_FCC_USR_BD_LBUS bit is set, the driver will
  257. configure the FCC to work as though the buffer descriptors were located in the 
  258. CPM local bus.
  259. MOT_FCC_USR_HBC: if the MOT_FCC_USR_HBC bit is set, the driver will
  260. configure the FCC to perform heartbeat check following end of transmisson
  261. and the HB bit in the status field of the TBD will be set if the collision
  262. input does not assert within the heartbeat window (also see _func_motFccHbFail,
  263. below). The user does not normally need to set this bit.
  264.  
  265. .LP
  266. EXTERNAL SUPPORT REQUIREMENTS
  267. This driver requires several external support functions:
  268. .IP sysFccEnetEnable()
  269. .CS
  270.     STATUS sysFccEnetEnable (UINT32 immrVal, UINT8 fccNum);
  271. .CE
  272. This routine is expected to handle any target-specific functions needed 
  273. to enable the FCC. These functions typically include setting the Port B and C
  274. on the MPC8260 so that the MII interface may be used. This routine is 
  275. expected to return OK on success, or ERROR. The driver calls this routine, 
  276. once per device, from the motFccStart () routine.
  277. .IP sysFccEnetDisable()
  278. .CS
  279.     STATUS sysFccEnetDisable (UINT32 immrVal, UINT8 fccNum);
  280. .CE
  281. This routine is expected to perform any target specific functions required
  282. to disable the MII interface to the FCC.  This involves restoring the 
  283. default values for all the Port B and C signals. This routine is expected to 
  284. return OK on success, or ERROR. The driver calls this routine from the 
  285. motFccStop() routine each time a device is disabled.
  286. .IP sysFccEnetAddrGet()
  287. .CS
  288.     STATUS sysFccEnetAddrGet (int unit,UCHAR *address);
  289. .CE
  290. The driver expects this routine to provide the six-byte Ethernet hardware 
  291. address that is used by this device.  This routine must copy the six-byte 
  292. address to the space provided by <enetAddr>.  This routine is expected to 
  293. return OK on success, or ERROR.  The driver calls this routine, once per 
  294. device, from the motFccEndLoad() routine.
  295. .CS
  296.     STATUS sysFccMiiBitWr (UINT32 immrVal, UINT8 fccNum, INT32 bitVal);
  297. .CE
  298. This routine is expected to perform any target specific functions required
  299. to write a single bit value to the MII management interface of a MII-compliant
  300. PHY device. The MII management interface is made up of two lines: management 
  301. data clock (MDC) and management data input/output (MDIO). The former provides
  302. the timing reference for transfer of information on the MDIO signal.
  303. The latter is used to transfer control and status information between the
  304. PHY and the FCC. For this transfer to be successful, the information itself 
  305. has to be encoded into a frame format, and both the MDIO and MDC signals have
  306. to comply with certain requirements as described in the 802.3u IEEE Standard.
  307. There is not buil-in support in the FCC for the MII management interface.
  308. This means that the clocking on the MDC line and the framing of the information
  309. on the MDIO signal have to be done in software. Hence, this routine is 
  310. expected to write the value in <bitVal> to the MDIO line while properly 
  311. sourcing the MDC clock to a PHY, for one bit time.
  312. .CS
  313.     STATUS sysFccMiiBitRd (UINT32 immrVal, UINT8 fccNum, INT8 * bitVal);
  314. .CE
  315. This routine is expected to perform any target specific functions required
  316. to read a single bit value from the MII management interface of a MII-compliant
  317. PHY device. The MII management interface is made up of two lines: management 
  318. data clock (MDC) and management data input/output (MDIO). The former provides
  319. the timing reference for transfer of information on the MDIO signal.
  320. The latter is used to transfer control and status information between the
  321. PHY and the FCC. For this transfer to be successful, the information itself 
  322. has to be encoded into a frame format, and both the MDIO and MDC signals have
  323. to comply with certain requirements as described in the 802.3u IEEE Standard.
  324. There is not buil-in support in the FCC for the MII management interface.
  325. This means that the clocking on the MDC line and the framing of the information
  326. on the MDIO signal have to be done in software. Hence, this routine is 
  327. expected to read the value from the MDIO line in <bitVal>, while properly 
  328. sourcing the MDC clock to a PHY, for one bit time.
  329. .IP `_func_motFccPhyInit'
  330. .CS
  331.     FUNCPTR _func_motFccPhyInit
  332. .CE
  333. This driver sets the global variable `_func_motFccPhyInit' to the 
  334. MII-compliant media initialization routine miiPhyInit(). If the user 
  335. wishes to exploit a different way to configure the PHY, he may set
  336. this variable to his own media initialization routine, tipically
  337. in sysHwInit().
  338. .IP `_func_motFccHbFail'
  339. .CS
  340.     FUNCPTR _func_motFccHbFail
  341. .CE
  342. The FCC may be configured to perform heartbeat check following end 
  343. of transmission, and to report any failure in the relevant TBD status field. 
  344. If this is the case, and if the global variable `_func_motFccHbFail'
  345. is not NULL, the routine referenced to by `_func_motFccHbFail' is called,
  346. with a pointer to the driver control structure as parameter. Hence,
  347. the user may set this variable to his own heart beat check fail routine,
  348. where he can take any action he sees appropriate.
  349. The default value for the global variable `_func_motFccHbFail' is NULL.
  350. .IP `_func_m82xxDpramFccMalloc'
  351. .CS
  352.     FUNCPTR _func_m82xxDpramFccMalloc
  353. .CE
  354. .IP `_func_m82xxDpramFree'
  355. .CS
  356.     FUNCPTR _func_m82xxDpramFree
  357. .CE
  358. .IP `_func_m82xxDpramFccFree'
  359. .CS
  360.     FUNCPTR _func_m82xxDpramFccFree
  361. .CE
  362. The FCC can be configured to utilize the dual ported ram located in
  363. the MPPC8260 CMP. In this case the user flag MOT_FCC_USR_DPRAM_ALOC is set 
  364. and the global variables _func_m82xxDpramFccMalloc, _func_m82xxDpramFree, and 
  365. _func_m82xxDpramFccFree must be populated by the BSP with the FUNCPTRs to 
  366. m82xxDpramFccMalloc(),  m82xxDpramFree(), and m82xxDpramFccFree() (respectively)
  367. from m82xxDpramLib.h. These functions are then used by the motFccEnd driver to 
  368. allocate and free memory in the dual ported ram. If any of these FUNCPTRs 
  369. are left NULL the motFccPramInit() will return an ERROR and the motFccEnd
  370. driver will not initialize.     
  371. .LP
  372. SYSTEM RESOURCE USAGE
  373. If the driver allocates the memory for the BDs to share with the FCC,
  374. it does so by calling the cacheDmaMalloc() routine.  For the default case
  375. of 64 transmit buffers and 32 receive buffers, the total size requested 
  376. is 776 bytes, and this includes the 8-byte alignment requirement of the 
  377. device.  If a non-cacheable memory region is provided by the user, the 
  378. size of this region should be this amount, unless the user has specified 
  379. a different number of transmit or receive BDs. 
  380. This driver can operate only if this memory region is non-cacheable
  381. or if the hardware implements bus snooping.  The driver cannot maintain
  382. cache coherency for the device because the BDs are asynchronously
  383. modified by both the driver and the device, and these fields share 
  384. the same cache line.
  385. If the driver allocates the memory for the data buffers to share with the FCC,
  386. it does so by calling the memalign () routine.  The driver does not need to
  387. use cache-safe memory for data buffers, since the host CPU and the device are
  388. not allowed to modify buffers asynchronously. The related cache lines
  389. are flushed or invalidated as appropriate. For the default case
  390. of 7 transmit clusters and 32 receive clusters, the total size requested 
  391. for this memory region is 112751 bytes, and this includes the 32-byte 
  392. alignment and the 32-byte pad-out area per buffer of the device.  If a 
  393. non-cacheable memory region is provided by the user, the size of this region 
  394. should be this amount, unless the user has specified a different number 
  395. of transmit or receive BDs. 
  396. TUNING HINTS
  397. The only adjustable parameters are the number of TBDs and RBDs that will be
  398. created at run-time.  These parameters are given to the driver when 
  399. motFccEndLoad() is called.  There is one RBD associated with each received 
  400. frame whereas a single transmit packet normally uses more than one TBD.  For 
  401. memory-limited applications, decreasing the number of RBDs may be 
  402. desirable.  Decreasing the number of TBDs below a certain point will 
  403. provide substantial performance degradation, and is not reccomended. An 
  404. adequate number of loaning buffers are also pre-allocated to provide more 
  405. buffering before packets are dropped, but this is not configurable.
  406. The relative priority of the netTask and of the other tasks in the system
  407. may heavily affect performance of this driver. Usually the best performance 
  408. is achieved when the netTask priority equals that of the other 
  409. applications using the driver.
  410. SPECIAL CONSIDERATIONS
  411. SEE ALSO: ifLib,
  412. .I "MPC8260 Fast Ethernet Controller (Supplement to the MPC860 User's Manual)"
  413. .I "Motorola MPC860 User's Manual",
  414. INTERNAL
  415. This driver contains conditional compilation switch MOT_FCC_DBG.
  416. If defined, adds debug output routines.  Output is further
  417. selectable at run-time via the motFccEndDbg global variable.
  418. */
  419. #include "vxWorks.h"
  420. #include "wdLib.h"
  421. #include "iv.h"
  422. #include "vme.h"
  423. #include "net/mbuf.h"
  424. #include "net/unixLib.h"
  425. #include "net/protosw.h"
  426. #include "sys/socket.h"
  427. #include "sys/ioctl.h"
  428. #include "errnoLib.h"
  429. #include "errno.h"
  430. #include "memLib.h"
  431. #include "intLib.h"
  432. #include "net/route.h"
  433. #include "iosLib.h"
  434. #include "errnoLib.h"
  435. #include "vxLib.h"
  436. #include "cacheLib.h"
  437. #include "logLib.h"
  438. #include "netLib.h"
  439. #include "stdio.h"
  440. #include "stdlib.h"
  441. #include "sysLib.h"
  442. #include "taskLib.h"
  443. #include "net/systm.h"
  444. #include "sys/times.h"
  445. #include "net/if_subr.h"
  446. #undef ETHER_MAP_IP_MULTICAST
  447. #include "etherMultiLib.h"
  448. #include "end.h"
  449. #include "semLib.h"
  450. #define    END_MACROS
  451. #include "endLib.h"
  452. #include "lstLib.h"
  453. #include "miiLib.h"
  454. #include "drv/intrCtl/m8260IntrCtl.h"
  455. #include "drv/sio/m8260Cp.h"
  456. #include "drv/sio/m8260CpmMux.h"
  457. #include "drv/end/motFccEnd.h"
  458. /* defines */
  459. /* Driver debug control */
  460. /* for debugging */
  461. #ifdef MOT_FCC_DBG 
  462. #undef MOT_FCC_DBG 
  463. #endif
  464. /* Driver debug control */
  465. #ifdef MOT_FCC_DBG
  466. #define MOT_FCC_DBG_OFF 0x0000
  467. #define MOT_FCC_DBG_RX 0x0001
  468. #define MOT_FCC_DBG_TX 0x0002
  469. #define MOT_FCC_DBG_POLL 0x0004
  470. #define MOT_FCC_DBG_MII 0x0008
  471. #define MOT_FCC_DBG_LOAD 0x0010
  472. #define MOT_FCC_DBG_IOCTL 0x0020
  473. #define MOT_FCC_DBG_INT 0x0040
  474. #define MOT_FCC_DBG_START 0x0080
  475. #define MOT_FCC_DBG_INT_RX_ERR 0x0100
  476. #define MOT_FCC_DBG_INT_TX_ERR 0x0200
  477. #define MOT_FCC_DBG_ANY 0xffff
  478. UINT32 motFccEndDbg = MOT_FCC_DBG_INT_RX_ERR|MOT_FCC_DBG_INT_TX_ERR;
  479. UINT32 motFccRxBsyErr = 0x0;
  480. UINT32 motFccTxErr = 0x0;
  481. UINT32 motFccHbFailErr = 0x0;
  482. UINT32 motFccTxLcErr = 0x0;
  483. UINT32 motFccTxUrErr = 0x0;
  484. UINT32 motFccTxCslErr = 0x0;
  485. UINT32 motFccTxRlErr = 0x0;
  486. UINT32 motFccRxLgErr = 0x0;
  487. UINT32 motFccRxNoErr = 0x0;
  488. UINT32 motFccRxCrcErr = 0x0;
  489. UINT32 motFccRxOvErr = 0x0;
  490. UINT32  motFccRxShErr = 0x0;
  491. UINT32  motFccRxLcErr = 0x0;
  492. UINT32  motFccRxMemErr = 0x0;
  493. DRV_CTRL *  pDrvCtrlDbg = NULL;
  494. #define MOT_FCC_HB_FAIL_ADD motFccHbFailErr++;
  495. #define MOT_FCC_RX_LG_ADD motFccRxLgErr++;
  496. #define MOT_FCC_RX_NO_ADD motFccRxNoErr++;
  497. #define MOT_FCC_RX_CRC_ADD motFccRxCrcErr++;
  498. #define MOT_FCC_RX_OV_ADD motFccRxOvErr++;
  499. #define MOT_FCC_RX_LC_ADD motFccRxLcErr++;
  500. #define MOT_FCC_RX_SH_ADD motFccRxShErr++;
  501. #define MOT_FCC_RX_MEM_ADD(p) (p)->Stats->motFccRxMemErr++;
  502. #define MOT_FCC_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  503.     {
  504.     if (motFccEndDbg & FLG)
  505.         logMsg (X0, X1, X2, X3, X4, X5, X6);         
  506.     }
  507. #else /* MOT_FCC_DBG */
  508. #define MOT_FCC_HB_FAIL_ADD
  509. #define MOT_FCC_RX_MEM_ADD(p)
  510. #define MOT_FCC_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  511. #endif /* MOT_FCC_DBG */
  512. /* general macros for reading/writing from/to specified locations */
  513. /* Cache and virtual/physical memory related macros */
  514. #define MOT_FCC_PHYS_TO_VIRT(physAddr)     
  515. CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->bdCacheFuncs, (char *)(physAddr))
  516. #define MOT_FCC_VIRT_TO_PHYS(virtAddr)     
  517. CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->bdCacheFuncs, (char *)(virtAddr))
  518. #define MOT_FCC_BD_CACHE_INVAL(address, len)          
  519.         CACHE_DRV_INVALIDATE (&pDrvCtrl->bdCacheFuncs, (address), (len))
  520. #define MOT_FCC_CACHE_INVAL(address, len)                                   
  521. CACHE_DRV_INVALIDATE (&pDrvCtrl->bufCacheFuncs, (address), (len))
  522. #define MOT_FCC_CACHE_FLUSH(address, len)                                   
  523. CACHE_DRV_FLUSH (&pDrvCtrl->bufCacheFuncs, (address), (len))
  524. /* driver flags */
  525. #define MOT_FCC_OWN_BUF_MEM 0x01 /* internally provided memory for data*/
  526. #define MOT_FCC_INV_TBD_NUM 0x02 /* invalid tbdNum provided */
  527. #define MOT_FCC_INV_RBD_NUM 0x04 /* invalid rbdNum provided */
  528. #define MOT_FCC_POLLING 0x08 /* polling mode */
  529. #define MOT_FCC_PROM 0x20    /* promiscuous mode */
  530. #define MOT_FCC_MCAST 0x40    /* multicast addressing mode */
  531. #define MOT_FCC_FD 0x80    /* full duplex mode */
  532. #define MOT_FCC_OWN_BD_MEM 0x10 /* internally provided memory for BDs */
  533. /* shortcuts */
  534. #define MOT_FCC_FLAG_CLEAR(clearBits)
  535.     (pDrvCtrl->flags &= ~(clearBits))
  536. #define MOT_FCC_FLAG_SET(setBits)
  537.     (pDrvCtrl->flags |= (setBits))
  538. #define MOT_FCC_FLAG_GET()
  539.     (pDrvCtrl->flags)
  540. #define MOT_FCC_FLAG_ISSET(setBits)
  541.     (pDrvCtrl->flags & (setBits))
  542. #define MOT_FCC_PHY_FLAGS_SET(setBits)
  543.     (pDrvCtrl->phyInfo->phyFlags |= (setBits))
  544. #define MOT_FCC_PHY_FLAGS_ISSET(setBits)
  545.     (pDrvCtrl->phyInfo->phyFlags & (setBits))
  546. #define MOT_FCC_PHY_FLAGS_GET(setBits)
  547.     (pDrvCtrl->phyInfo->phyFlags)
  548. #define MOT_FCC_PHY_FLAGS_CLEAR(clearBits)
  549.     (pDrvCtrl->phyInfo->phyFlags &= ~(clearBits))
  550. #define MOT_FCC_USR_FLAG_ISSET(setBits)
  551.     (pDrvCtrl->userFlags & (setBits))
  552. #define END_FLAGS_ISSET(setBits)
  553.     ((&pDrvCtrl->endObj)->flags & (setBits))
  554. #define MOT_FCC_ADDR_GET(pEnd)                                          
  555.     ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  556. #define MOT_FCC_ADDR_LEN_GET(pEnd)                                      
  557.     ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  558. /* some BDs definitions */
  559. /* 
  560.  * the total is 0x630 and it accounts for the required alignment
  561.  * of receive data buffers, and the cluster overhead.
  562.  */
  563. #define XXX_FCC_MAX_CL_LEN      ((MII_ETH_MAX_PCK_SZ
  564.  + (MOT_FCC_BUF_ALIGN - 1)
  565.  + MOT_FCC_BUF_ALIGN
  566.  + (CL_OVERHEAD - 1))
  567.  & (~ (CL_OVERHEAD - 1)))
  568. #define MOT_FCC_MAX_CL_LEN      ROUND_UP(XXX_FCC_MAX_CL_LEN,MOT_FCC_BUF_ALIGN)
  569. #define MOT_FCC_RX_CL_SZ       (MOT_FCC_MAX_CL_LEN)
  570. #define MOT_FCC_TX_CL_SZ       (MOT_FCC_MAX_CL_LEN)
  571. /* read/write macros to access internal memory */
  572. #define MOT_FCC_REG_LONG_WR(regAddr, regVal)
  573.     {
  574.     UINT32 temp = 0;
  575.     temp = (UINT32) MOT_FCC_VIRT_TO_PHYS (regAddr);
  576.     MOT_FCC_LONG_WR ((UINT32 *) (temp), (regVal));
  577.     }
  578. #define MOT_FCC_REG_LONG_RD(regAddr, regVal)
  579.     {
  580.     UINT32 temp = 0;
  581.     temp = (UINT32) MOT_FCC_VIRT_TO_PHYS (regAddr);
  582.     MOT_FCC_LONG_RD ((UINT32 *) (temp), (regVal));
  583.     }
  584. #define MOT_FCC_REG_WORD_WR(regAddr, regVal)
  585.     {
  586.     UINT32 temp = 0;
  587.     temp = (UINT32) MOT_FCC_VIRT_TO_PHYS (regAddr);
  588.     MOT_FCC_WORD_WR ((UINT16 *) (temp), (regVal));
  589.     }
  590. #define MOT_FCC_REG_WORD_RD(regAddr, regVal)
  591.     {
  592.     UINT32 temp = 0;
  593.     temp = (UINT32) MOT_FCC_VIRT_TO_PHYS (regAddr);
  594.     MOT_FCC_WORD_RD ((UINT16 *) (temp), (regVal));
  595.     }
  596. /* macros to read/write tx/rx buffer descriptors */
  597. #define MOT_FCC_BD_WORD_WR(bdAddr, bdOff, bdVal)
  598.     {
  599.     UINT32 temp = 0;
  600.     temp = (UINT32) MOT_FCC_VIRT_TO_PHYS ((bdAddr) + (bdOff));
  601.     MOT_FCC_WORD_WR ((UINT16 *) (temp), (bdVal));
  602.     }
  603. /* here we're writing the data pointer, so it's a physical address */
  604. #define MOT_FCC_BD_LONG_WR(bdAddr, bdOff, bdVal)
  605.     {
  606.     UINT32 temp1 = 0;
  607.     UINT32 temp2 = 0;
  608.     temp1 = (UINT32) MOT_FCC_VIRT_TO_PHYS ((bdAddr) + (bdOff));
  609.     temp2 = (UINT32) MOT_FCC_VIRT_TO_PHYS (bdVal);
  610.     MOT_FCC_LONG_WR ((UINT32 *) (temp1), (temp2));
  611.     }
  612. #define MOT_FCC_BD_WORD_RD(bdAddr, bdOff, bdVal)
  613.     {
  614.     UINT32 temp = 0;
  615.     temp = (UINT32) MOT_FCC_VIRT_TO_PHYS ((bdAddr) + (bdOff));
  616.     MOT_FCC_WORD_RD ((UINT16 *) (temp), (bdVal));
  617.     }
  618. #define MOT_FCC_BD_LONG_RD(bdAddr, bdOff, bdVal)
  619.     {
  620.     UINT32 temp1 = 0;
  621.     UINT32 temp2 = 0;
  622.     temp1 = (UINT32) MOT_FCC_VIRT_TO_PHYS ((bdAddr) + (bdOff));
  623.     MOT_FCC_LONG_RD ((UINT32 *) (temp1), (temp2));
  624.     bdVal = (char *) MOT_FCC_PHYS_TO_VIRT (temp2);
  625.     }
  626. #define MOT_FCC_NEXT_TBD(pDrvCtrl, pTbd)
  627.     (pTbd) = (MOT_FCC_TBD_ID) ((pDrvCtrl)->tbdBase +   
  628.       ((pDrvCtrl)->tbdIndex * MOT_FCC_TBD_SZ))
  629. #define MOT_FCC_USED_TBD(pDrvCtrl, pTbd)
  630.     (pTbd) = (MOT_FCC_TBD_ID) ((pDrvCtrl)->tbdBase +     
  631.               ((pDrvCtrl)->usedTbdIndex * MOT_FCC_TBD_SZ))
  632. #define MOT_FCC_RX_ACTIVATE
  633.     {
  634.     UINT32 tmp = 0;
  635.     MOT_FCC_REG_LONG_RD (pDrvCtrl->fccIramAddr, tmp);
  636.     MOT_FCC_REG_LONG_WR (pDrvCtrl->fccIramAddr,
  637. (tmp | M8260_GFMR_ENR));
  638.     }
  639. #define MOT_FCC_INT_DISABLE
  640.     {
  641.     MOT_FCC_REG_WORD_WR ((UINT32) M8260_FGMR1 (pDrvCtrl->immrVal) +
  642.  ((pDrvCtrl->fccNum - 1) * M8260_FCC_IRAM_GAP),
  643.  MOT_FCC_CLEAR_VAL);
  644.     }
  645. #define MOT_FCC_INT_ENABLE
  646.     {
  647.     MOT_FCC_REG_WORD_WR ((UINT32) M8260_FGMR1 (pDrvCtrl->immrVal) +
  648.  ((pDrvCtrl->fccNum - 1) * M8260_FCC_IRAM_GAP),
  649.  (pDrvCtrl->intMask));
  650.     }
  651. /* more shortcuts */
  652. #define MOT_FCC_GRA_SEM_CREATE
  653.     if ((pDrvCtrl->graSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY)) 
  654. == NULL)
  655. goto errorExit
  656. #define MOT_FCC_GRA_SEM_DELETE
  657.     if ((pDrvCtrl->graSem) != NULL) 
  658. semDelete (pDrvCtrl->graSem)
  659. #define MOT_FCC_GRA_SEM_GIVE
  660.     (semGive (pDrvCtrl->graSem))
  661. #define MOT_FCC_GRA_SEM_TAKE
  662.     (semTake (pDrvCtrl->graSem, WAIT_FOREVER))
  663. #define NET_BUF_ALLOC()                                                 
  664.     netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)
  665. #define NET_TO_MOT_FCC_BUF(netBuf)                              
  666.     (((UINT32) (netBuf) + MOT_FCC_BUF_ALIGN - 1) 
  667.       & ~(MOT_FCC_BUF_ALIGN - 1))
  668. #define NET_BUF_FREE(pBuffer)                                           
  669.     netClFree (pDrvCtrl->endObj.pNetPool, (pBuffer))
  670.  
  671. #define NET_MBLK_ALLOC()                                                
  672.     netMblkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)
  673.  
  674. #define NET_MBLK_FREE(pMblock)                                          
  675.     netMblkFree (pDrvCtrl->endObj.pNetPool, (M_BLK_ID) (pMblock))
  676.  
  677. #define NET_CL_BLK_ALLOC()                                              
  678.     netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)
  679.  
  680. #define NET_CL_BLK_FREE(pClBlock)                                       
  681.     netClBlkFree (pDrvCtrl->endObj.pNetPool, (CL_BLK_ID) (pClBlock))
  682.  
  683. #define NET_MBLK_BUF_FREE(pMblock)                                      
  684.     netMblkClFree ((M_BLK_ID) (pMblock))
  685.  
  686. #define NET_MBLK_CL_JOIN(pMblock, pClBlock, ret)                        
  687.     ret = netMblkClJoin ((pMblock), (pClBlock))
  688.  
  689. #define NET_CL_BLK_JOIN(pClBlock, pBuffer, length, ret)                 
  690.     (ret) = netClBlkJoin ((pClBlock), (pBuffer), (length), NULL, 0, 0, 0)
  691.  
  692. /* locals */
  693. /* Function declarations not in any header files */
  694. /* forward function declarations */
  695. LOCAL STATUS    motFccInitParse (DRV_CTRL * pDrvCtrl, char *initString);
  696. LOCAL STATUS    motFccInitMem (DRV_CTRL *pDrvCtrl);
  697. LOCAL STATUS    motFccSend (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  698. LOCAL STATUS    motFccPhyPreInit (DRV_CTRL * pDrvCtrl);
  699. LOCAL STATUS    motFccBdFree (DRV_CTRL * pDrvCtrl);
  700. LOCAL STATUS    motFccRbdInit (DRV_CTRL * pDrvCtrl);
  701. LOCAL STATUS motFccTbdInit (DRV_CTRL * pDrvCtrl);
  702. LOCAL STATUS motFccFpsmrValSet (DRV_CTRL * pDrvCtrl);
  703. LOCAL STATUS motFccHashTblPopulate (DRV_CTRL * pDrvCtrl);
  704. LOCAL STATUS motFccHashTblAdd (DRV_CTRL * pDrvCtrl, UCHAR * pAddr);
  705. LOCAL STATUS motFccInit (DRV_CTRL * pDrvCtrl);
  706. LOCAL STATUS motFccPramInit (DRV_CTRL * pDrvCtrl);
  707. LOCAL STATUS motFccIramInit (DRV_CTRL * pDrvCtrl);
  708. LOCAL STATUS motFccCpcrCommand (DRV_CTRL * pDrvCtrl, UINT8 command);
  709. LOCAL void motFccInt (DRV_CTRL * pDrvCtrl);
  710. LOCAL void motFccHandleRXFrames(DRV_CTRL *pDrvCtrl);
  711. LOCAL STATUS motFccMiiRead (DRV_CTRL * pDrvCtrl, UINT8 phyAddr,
  712.                UINT8 regAddr, UINT16 *retVal);
  713. LOCAL STATUS motFccMiiWrite (DRV_CTRL * pDrvCtrl, UINT8 phyAddr,
  714. UINT8 regAddr, UINT16 writeData);
  715. LOCAL STATUS motFccAddrSet (DRV_CTRL * pDrvCtrl, UCHAR * pAddr,
  716.                    UINT32 offset);
  717. LOCAL void motFccPhyLSCInt(DRV_CTRL *pDrvCtrl);
  718. LOCAL STATUS    motFccJobQInit (DRV_CTRL *pDrvCtrl); 
  719. LOCAL void      motFccJobQAdd (DRV_CTRL * pDrvCtrl, FUNCPTR routine, int param1,
  720.                                int param2, int param3, int param4, int param5);
  721. LOCAL STATUS    motFccJobQueue (DRV_CTRL * pDrvCtrl);
  722. /* END Specific interfaces. */
  723. END_OBJ * motFccEndLoad (char *initString);    
  724. LOCAL STATUS    motFccStart (DRV_CTRL * pDrvCtrl);
  725. LOCAL STATUS motFccUnload (DRV_CTRL * pDrvCtrl);
  726. LOCAL STATUS    motFccStop (DRV_CTRL * pDrvCtrl);
  727. LOCAL int       motFccIoctl (DRV_CTRL * pDrvCtrl, int cmd, caddr_t data);
  728. LOCAL STATUS    motFccSend (DRV_CTRL * pDrvCtrl, M_BLK_ID pMblk);
  729. LOCAL STATUS    motFccMCastAddrAdd (DRV_CTRL * pDrvCtrl, UCHAR * pAddress);
  730. LOCAL STATUS    motFccMCastAddrDel (DRV_CTRL * pDrvCtrl, UCHAR * pAddress);
  731. LOCAL STATUS    motFccMCastAddrGet (DRV_CTRL * pDrvCtrl,
  732.                                     MULTI_TABLE *pTable);
  733. LOCAL STATUS    motFccPollSend (DRV_CTRL * pDrvCtrl, M_BLK_ID pMblk);
  734. LOCAL STATUS    motFccPollReceive (DRV_CTRL * pDrvCtrl, M_BLK_ID pMblk);
  735. LOCAL STATUS    motFccPollStart (DRV_CTRL * pDrvCtrl);
  736. LOCAL STATUS    motFccPollStop (DRV_CTRL * pDrvCtrl);
  737. /* globals */
  738. FUNCPTR _func_motFccPhyInit = (FUNCPTR) miiPhyInit;
  739. FUNCPTR _func_motFccPhyLSCInt = (FUNCPTR) motFccPhyLSCInt;
  740. FUNCPTR _func_motFccHbFail = (FUNCPTR) NULL;
  741. FUNCPTR _func_motFccPhyDuplex = (FUNCPTR) NULL;
  742. FUNCPTR  _func_m82xxDpramFree = (FUNCPTR)NULL;
  743. FUNCPTR  _func_m82xxDpramFccMalloc = (FUNCPTR)NULL;
  744. FUNCPTR  _func_m82xxDpramFccFree = (FUNCPTR)NULL;
  745. DRV_CTRL *global_pDrvCtrl;
  746. #ifdef MOT_FCC_DBG
  747. void motFccIramShow (void);
  748. void motFccPramShow (void);
  749. void motFccRbdShow (int);
  750. void motFccTbdShow (int);
  751. void motFccErrorShow (void);
  752. void motFccDrvShow (void);
  753. void motFccMiiShow (void);
  754. void motFccMibShow (void);
  755. UINT16 motFccMiiRegRead(UINT8 regAddr);
  756. #endif /* MOT_FCC_DBG */
  757. /* 
  758.  * Define the device function table.  This is static across all driver
  759.  * instances.
  760.  */
  761. LOCAL NET_FUNCS netFccFuncs = 
  762.     {
  763.     (FUNCPTR) motFccStart, /* start func. */  
  764.     (FUNCPTR) motFccStop, /* stop func. */
  765.     (FUNCPTR) motFccUnload, /* unload func. */
  766.     (FUNCPTR) motFccIoctl, /* ioctl func. */  
  767.     (FUNCPTR) motFccSend, /* send func. */   
  768.     (FUNCPTR) motFccMCastAddrAdd,     /* multicast add func. */  
  769.     (FUNCPTR) motFccMCastAddrDel,     /* multicast delete func. */      
  770.     (FUNCPTR) motFccMCastAddrGet,     /* multicast get fun. */   
  771.     (FUNCPTR) motFccPollSend,     /* polling send func. */   
  772.     (FUNCPTR) motFccPollReceive,     /* polling receive func. */
  773.     endEtherAddressForm,    /* put address info into a NET_BUFFER */
  774.     (FUNCPTR) endEtherPacketDataGet,  /* get pointer to data in NET_BUFFER */
  775.     (FUNCPTR) endEtherPacketAddrGet   /* Get packet addresses */
  776.     };
  777. /*******************************************************************************
  778. *
  779. * motFccEndLoad - initialize the driver and device
  780. *
  781. * This routine initializes both driver and device to an operational state
  782. * using device specific parameters specified by <initString>.
  783. *
  784. * The parameter string, <initString>, is an ordered list of parameters each
  785. * separated by a colon. The format of <initString> is:
  786. *
  787. * "<immrVal>:<ivec>:<bufBase>:<bufSize>:<fifoTxBase>:<fifoRxBase>
  788. * :<tbdNum>:<rbdNum>:<phyAddr>:<phyDefMode>:<pAnOrderTbl>:<userFlags>"
  789. *
  790. * The FCC shares a region of memory with the driver.  The caller of this
  791. * routine can specify the address of this memory region, or can specify that
  792. * the driver must obtain this memory region from the system resources.
  793. *
  794. * A default number of transmit/receive buffer descriptors of 32 can be 
  795. * selected by passing zero in the parameters <tbdNum> and <rbdNum>. 
  796. * In other cases, the number of buffers selected should be greater than two.
  797. *
  798. * The <bufBase> parameter is used to inform the driver about the shared
  799. * memory region.  If this parameter is set to the constant "NONE," then this
  800. * routine will attempt to allocate the shared memory from the system.  Any
  801. * other value for this parameter is interpreted by this routine as the address
  802. * of the shared memory region to be used. The <bufSize> parameter is used
  803. * to check that this region is large enough with respect to the provided
  804. * values of both transmit/receive buffer descriptors.
  805. *
  806. * If the caller provides the shared memory region, then the driver assumes
  807. * that this region does not require cache coherency operations, nor does it
  808. * require conversions between virtual and physical addresses.
  809. *
  810. * If the caller indicates that this routine must allocate the shared memory
  811. * region, then this routine will use cacheDmaMalloc() to obtain
  812. * some  cache-safe memory.  The attributes of this memory will be checked,
  813. * and if the memory is not write coherent, this routine will abort and
  814. * return NULL.
  815. *
  816. * RETURNS: an END object pointer, or NULL on error.
  817. *
  818. * SEE ALSO: ifLib,
  819. * .I "MPC8260 Power QUICC II User's Manual"
  820. */
  821. END_OBJ* motFccEndLoad
  822.     (
  823.     char *initString
  824.     )
  825.     {
  826.     DRV_CTRL *pDrvCtrl = NULL;      /* pointer to DRV_CTRL structure */
  827.     UCHAR    enetAddr[MOT_FCC_ADDR_LEN];  /* ethernet address */
  828.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("Loading end...n"), 1, 2, 3, 4, 5, 6);
  829.     if (initString == NULL)
  830. return NULL;
  831.     if (initString[0] == 0)
  832.         {
  833. bcopy ((char *)MOT_FCC_DEV_NAME, (void *)initString,
  834.                MOT_FCC_DEV_NAME_LEN);
  835. return NULL;
  836.         }
  837.     /* allocate the device structure */
  838.     pDrvCtrl = (DRV_CTRL *) calloc (sizeof (DRV_CTRL), 1);
  839.     if (pDrvCtrl == NULL)
  840. return NULL;
  841.     global_pDrvCtrl = pDrvCtrl;
  842.     /* get memory for the phyInfo structure */
  843.     if ((pDrvCtrl->phyInfo = calloc (sizeof (PHY_INFO), 1)) == NULL)
  844. return NULL;
  845.     /* get memory for the drivers stats structure */
  846.     if ((pDrvCtrl->Stats = calloc (sizeof (FCC_DRIVER_STATS), 1)) == NULL)
  847. return NULL;
  848. #ifdef MOT_FCC_DBG 
  849.     pDrvCtrlDbg = pDrvCtrl;
  850. #endif /* MOT_FCC_DBG */
  851.     /* Parse InitString */
  852.     if (motFccInitParse (pDrvCtrl, initString) == ERROR)
  853.         {
  854. goto errorExit;
  855.         }
  856.     /* sanity check the unit number */
  857.     if (pDrvCtrl->unit < 0 )
  858. goto errorExit;    
  859.     /* memory initialization */
  860.     if (motFccInitMem (pDrvCtrl) == ERROR)
  861. goto errorExit;
  862.     /* get our ethernet hardware address */
  863.     SYS_FCC_ENET_ADDR_GET (enetAddr);
  864.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("motFccEndLoad: enetAddr= 
  865.     0x%x 0x%x 0x%x 0x%x 0x%x 0x%x n "), 
  866.     enetAddr[0],
  867.     enetAddr[1],
  868.     enetAddr[2],
  869.     enetAddr[3],
  870.     enetAddr[4],
  871.     enetAddr[5]);
  872.     /* initialize some flags */
  873.     pDrvCtrl->loaded = TRUE;
  874.     pDrvCtrl->intrConnect = FALSE;
  875.     /* Set zeroBufFlag */
  876.     if (pDrvCtrl->userFlags & MOT_FCC_USR_BUF_LBUS || 
  877.         pDrvCtrl->userFlags & MOT_FCC_USR_NO_ZCOPY)
  878.         {
  879. pDrvCtrl->zeroBufFlag = FALSE;
  880.         }
  881.     else
  882.         {
  883. pDrvCtrl->zeroBufFlag = TRUE;
  884.         }
  885.     /* store the internal ram base address */
  886.     pDrvCtrl->fccIramAddr = (UINT32) M8260_FGMR1 (pDrvCtrl->immrVal) +
  887.     ((pDrvCtrl->fccNum - 1) * M8260_FCC_IRAM_GAP);
  888.     pDrvCtrl->fccReg = (FCC_REG_T *)pDrvCtrl->fccIramAddr;
  889.     /* store the parameter ram base address */
  890.     pDrvCtrl->fccPramAddr = (UINT32) M8260_FCC1_BASE (pDrvCtrl->immrVal) +
  891.     ((pDrvCtrl->fccNum - 1) * M8260_FCC_DPRAM_GAP);
  892.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("motFccEndLoad: pram=0x%x iram=0x%x n "), 
  893.     pDrvCtrl->fccPramAddr,
  894.     pDrvCtrl->fccIramAddr,
  895.     0, 0, 0, 0);
  896.     pDrvCtrl->fccPar = (FCC_PARAM_T *)pDrvCtrl->fccPramAddr;
  897.     pDrvCtrl->fccEthPar = &pDrvCtrl->fccPar->prot.e;
  898.     /* 
  899.      * create the synchronization semaphore for graceful transmit 
  900.      * command interrupts. 
  901.      */
  902.     MOT_FCC_GRA_SEM_CREATE;
  903.     
  904. /*
  905.  * Because we create EMPTY semaphore we need to give it here
  906.  * other wise the only time that it's given back is in the
  907.  * motFccInt() and if we have two NI in the bootrom like SCC
  908.  * and FCC the motFccStop() will be spin forever when it will
  909.  * try to do MOT_FCC_GRA_SEM_TAKE.                            
  910.  */
  911. MOT_FCC_GRA_SEM_GIVE;
  912.     /* endObj initializations */
  913.     if (END_OBJ_INIT (&pDrvCtrl->endObj, 
  914.                       (DEV_OBJ*) pDrvCtrl,
  915.       MOT_FCC_DEV_NAME, 
  916.                       pDrvCtrl->unit, &netFccFuncs,
  917.       "Motorola FCC Ethernet Enhanced Network Driver") == ERROR)
  918.         {
  919. goto errorExit;
  920.         }
  921.     pDrvCtrl->phyInfo->phySpeed = MOT_FCC_100MBS;
  922.     if (END_MIB_INIT (&pDrvCtrl->endObj, 
  923.                       M2_ifType_ethernet_csmacd, 
  924.       (u_char *) &enetAddr[0], 
  925.                       MOT_FCC_ADDR_LEN,
  926.       ETHERMTU, 
  927.                       pDrvCtrl->phyInfo->phySpeed) == ERROR)
  928.         {
  929. goto errorExit;
  930.         }
  931.     /* Mark the device ready */
  932.     END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST | 
  933.                    IFF_BROADCAST);
  934.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("motFccEndLoad... Done n"), 
  935.     1, 2, 3, 4, 5, 6);
  936.     return (&pDrvCtrl->endObj);
  937. errorExit:
  938.     motFccUnload (pDrvCtrl);
  939.     return NULL;
  940.     }
  941. /*******************************************************************************
  942. *
  943. * motFccUnload - unload a driver from the system
  944. *
  945. * This routine unloads the driver pointed to by <pDrvCtrl> from the system.
  946. *
  947. * RETURNS: OK, always.
  948. *
  949. * SEE ALSO: motFccLoad()
  950. */
  951. LOCAL STATUS motFccUnload
  952.     (
  953.     DRV_CTRL *pDrvCtrl       /* pointer to DRV_CTRL structure */
  954.     )
  955.     {
  956.     FCC_PARAM_T *pParam;
  957.     /* get to the beginning of the parameter area */
  958.     pParam = pDrvCtrl->fccPar;
  959.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("Unloading end..."), 1, 2, 3, 4, 5, 6);
  960.     if (pDrvCtrl == NULL)
  961. return (ERROR);
  962.     pDrvCtrl->loaded = FALSE;
  963.     /* free allocated memory if necessary */
  964.     if ((MOT_FCC_FLAG_ISSET (MOT_FCC_OWN_BUF_MEM)) && 
  965.         (pDrvCtrl->pBufBase != NULL))
  966.         {
  967. free (pDrvCtrl->pBufBase);
  968.         }
  969.     if ((MOT_FCC_FLAG_ISSET (MOT_FCC_OWN_BD_MEM)) && 
  970.         (pDrvCtrl->pBdBase != NULL))
  971.         {
  972. cacheDmaFree (pDrvCtrl->pBdBase);
  973.         }
  974.     else if ((MOT_FCC_USR_FLAG_ISSET(MOT_FCC_USR_DPRAM_ALOC)) && 
  975.              (pDrvCtrl->pBdBase != NULL))
  976. {
  977. /* 
  978.          * If pBdBase is not equal to NULL then it was allocated from the 
  979.          * DPRAM pool 
  980.          */
  981. _func_m82xxDpramFree((void*)pDrvCtrl->pBdBase);
  982. pDrvCtrl->pBdBase = NULL;
  983. }
  984.     /* free allocated memory if necessary */
  985.     if ((pDrvCtrl->pMBlkArea) != NULL)
  986. free (pDrvCtrl->pMBlkArea);
  987.     END_OBJECT_UNLOAD (&pDrvCtrl->endObj);
  988.     /* free the semaphores if necessary */
  989.     MOT_FCC_GRA_SEM_DELETE;
  990.     if ((char *) pDrvCtrl->phyInfo != NULL)
  991. cfree ((char *) pDrvCtrl->phyInfo);
  992.     /* free allocated DPRAM memory if necessary */
  993.     if ((MOT_FCC_USR_FLAG_ISSET(MOT_FCC_USR_DPRAM_ALOC)) && 
  994.         (pParam->riptr != 0))
  995.         {
  996.         _func_m82xxDpramFccFree((void*)((ULONG)pParam->riptr));
  997.         pParam->riptr = 0;
  998.         }
  999.     if ((MOT_FCC_USR_FLAG_ISSET(MOT_FCC_USR_DPRAM_ALOC)) && 
  1000.         (pParam->tiptr != 0))
  1001. {
  1002.         _func_m82xxDpramFccFree((void*)((ULONG)pParam->tiptr));
  1003.         pParam->tiptr = 0;
  1004. }
  1005.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("motFccUnload... Donen"), 
  1006.     1, 2, 3, 4, 5, 6);
  1007.     return (OK);
  1008.     }
  1009. /*******************************************************************************
  1010. *
  1011. * motFccInitParse - parse parameter values from initString
  1012. *
  1013. * This routine parses parameter values from initString and stores them in
  1014. * the related fiels of the driver control structure.
  1015. *
  1016. * RETURNS: OK or ERROR
  1017. */
  1018. LOCAL STATUS motFccInitParse
  1019.     (
  1020.     DRV_CTRL *pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1021.     char     *initString /* parameter string */
  1022.     )
  1023.     {
  1024.     char *  tok; /* an initString token */
  1025.     char *  holder = NULL; /* points to initString fragment beyond tok */
  1026.     tok = strtok_r (initString, ":", &holder);
  1027.     if (tok == NULL)
  1028.         {
  1029. return ERROR;
  1030.         }
  1031.     pDrvCtrl->unit = (int) strtoul (tok, NULL, 16);
  1032.     tok = strtok_r (NULL, ":", &holder);
  1033.     if (tok == NULL)
  1034.         {
  1035.         return ERROR;
  1036.         }
  1037.     pDrvCtrl->immrVal = (UINT32) strtoul (tok, NULL, 16);
  1038.     tok = strtok_r (NULL, ":", &holder);
  1039.     if (tok == NULL)
  1040.         {
  1041.         return ERROR;
  1042.         }
  1043.     pDrvCtrl->fccNum = (UINT32) strtoul (tok, NULL, 16);
  1044.     tok = strtok_r (NULL, ":", &holder);
  1045.     if (tok == NULL)
  1046.         {
  1047.         return ERROR;
  1048.         }
  1049.     pDrvCtrl->pBdBase = (char *) strtoul (tok, NULL, 16);
  1050.     tok = strtok_r (NULL, ":", &holder);
  1051.     if (tok == NULL)
  1052.         {
  1053.         return ERROR;
  1054.         }
  1055.     pDrvCtrl->bdSize = strtoul (tok, NULL, 16);
  1056.     tok = strtok_r (NULL, ":", &holder);
  1057.     if (tok == NULL)
  1058.         {
  1059.         return ERROR;
  1060.         }
  1061.     pDrvCtrl->pBufBase = (char *) strtoul (tok, NULL, 16);
  1062.     tok = strtok_r (NULL, ":", &holder);
  1063.     if (tok == NULL)
  1064.         {
  1065.         return ERROR;
  1066.         }
  1067.     pDrvCtrl->bufSize = strtoul (tok, NULL, 16);
  1068.     tok = strtok_r (NULL, ":", &holder);
  1069.     if (tok == NULL)
  1070.         {
  1071.         return ERROR;
  1072.         }
  1073.     pDrvCtrl->fifoTxBase = (UINT32) strtoul (tok, NULL, 16);
  1074.     tok = strtok_r (NULL, ":", &holder);
  1075.     if (tok == NULL)
  1076.         {
  1077.         return ERROR;
  1078.         }
  1079.     pDrvCtrl->fifoRxBase = (UINT32) strtoul (tok, NULL, 16);
  1080.     tok = strtok_r (NULL, ":", &holder);
  1081.     if (tok == NULL)
  1082.         {
  1083.         return ERROR;
  1084.         }
  1085.     pDrvCtrl->tbdNum = (UINT16) strtoul (tok, NULL, 16);
  1086.     tok = strtok_r (NULL, ":", &holder);
  1087.     if (tok == NULL)
  1088.         {
  1089.         return ERROR;
  1090.         }
  1091.     pDrvCtrl->rbdNum = (UINT16) strtoul (tok, NULL, 16);
  1092.     tok = strtok_r (NULL, ":", &holder);
  1093.     if (tok == NULL)
  1094.         {
  1095.         return ERROR;
  1096.         }
  1097.     pDrvCtrl->phyInfo->phyAddr = (UINT8) strtoul (tok, NULL, 16);
  1098.     tok = strtok_r (NULL, ":", &holder);
  1099.     if (tok == NULL)
  1100.         {
  1101.         return ERROR;
  1102.         }
  1103.     pDrvCtrl->phyInfo->phyDefMode = (UINT8) strtoul (tok, NULL, 16);
  1104.     tok = strtok_r (NULL, ":", &holder);
  1105.     if (tok == NULL)
  1106.         {
  1107.         return ERROR;
  1108.         }
  1109.     pDrvCtrl->phyInfo->phyAnOrderTbl = (MII_AN_ORDER_TBL *) 
  1110. strtoul (tok, NULL, 16);
  1111.     tok = strtok_r (NULL, ":", &holder);
  1112.     if (tok == NULL)
  1113.         {
  1114.         return ERROR;
  1115.         }
  1116.     pDrvCtrl->userFlags = strtoul (tok, NULL, 16);
  1117.     /* mblkMult is optional */
  1118.     pDrvCtrl->mblkMult = 5;
  1119.     tok = strtok_r (NULL, ":", &holder);
  1120.     if (tok  != NULL)
  1121.         pDrvCtrl->mblkMult = strtoul (tok, NULL, 16);
  1122.     /* clMult is optional */
  1123.     pDrvCtrl->clMult =  6;
  1124.     tok = strtok_r (NULL, ":", &holder);
  1125.     if (tok != NULL)
  1126.         pDrvCtrl->clMult = strtoul (tok, NULL, 16);
  1127.     /* txJobMsgQLen is optional */
  1128.     pDrvCtrl->txJobMsgQLen = 128;
  1129.     tok = strtok_r (NULL, ":", &holder);
  1130.     if (tok != NULL)
  1131.         pDrvCtrl->txJobMsgQLen = strtoul (tok, NULL, 16);
  1132.     if (!pDrvCtrl->tbdNum || pDrvCtrl->tbdNum <= 2)
  1133. {
  1134. MOT_FCC_FLAG_SET (MOT_FCC_INV_TBD_NUM);
  1135. pDrvCtrl->tbdNum = MOT_FCC_TBD_DEF_NUM;
  1136. }
  1137.     if (!pDrvCtrl->rbdNum || pDrvCtrl->rbdNum <= 2)
  1138. {
  1139. MOT_FCC_FLAG_SET (MOT_FCC_INV_RBD_NUM);
  1140. pDrvCtrl->rbdNum = MOT_FCC_RBD_DEF_NUM; 
  1141. }
  1142.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD,
  1143.  ("motFccEndParse: unit=%d immrVal=0x%x 
  1144.  bufBase=0x%x bufSize=0x%x,
  1145.  bdBase=0x%x bdSize=0x%x n"),
  1146.  pDrvCtrl->unit, 
  1147.  (int) pDrvCtrl->immrVal,
  1148.  (int) pDrvCtrl->pBufBase,
  1149.  pDrvCtrl->bufSize,
  1150.  (int) pDrvCtrl->pBdBase,
  1151.  pDrvCtrl->bdSize);
  1152.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD,
  1153.  ("motFccEndParse: fifoTxBase=0x%x fifoRxBase=0x%x
  1154.  tbdNum=%d rbdNum=%d flags=0x%x fccNum=%dn"),
  1155.  pDrvCtrl->fifoTxBase,
  1156.  pDrvCtrl->fifoRxBase,
  1157.  pDrvCtrl->tbdNum,
  1158.  pDrvCtrl->rbdNum,
  1159.  pDrvCtrl->userFlags,
  1160.  pDrvCtrl->fccNum);
  1161.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD,
  1162.                  ("motFccEndParse: phyAddr=0x%x 
  1163.                   phyDefMode=0x%x orderTbl=0x%x n"),
  1164.                  pDrvCtrl->phyInfo->phyAddr,
  1165.                  pDrvCtrl->phyInfo->phyDefMode,
  1166.                  (int) pDrvCtrl->phyInfo->phyAnOrderTbl,
  1167.                  0, 0, 0);
  1168.     return (OK);
  1169.     }
  1170. /*******************************************************************************
  1171. * motFccInitMem - initialize memory
  1172. *
  1173. * This routine initializes all the memory needed by the driver whose control
  1174. * structure is passed in <pDrvCtrl>.
  1175. *
  1176. * RETURNS: OK or ERROR
  1177. */
  1178. LOCAL STATUS motFccInitMem 
  1179.     (
  1180.     DRV_CTRL *pDrvCtrl
  1181.     )
  1182.     {
  1183.     UINT32 bdMemSize,rbdMemSize,tbdMemSize;
  1184.     UINT16 clNum; /* a buffer number holder */
  1185.     /* cluster blocks configuration */
  1186.     M_CL_CONFIG mclBlkConfig = {0, 0, NULL, 0};
  1187.     /* cluster blocks config table */
  1188.     CL_DESC clDescTbl [] = { {MOT_FCC_MAX_CL_LEN, 0, NULL, 0} };
  1189.     /* number of different clusters sizes in pool -- only 1 */
  1190.     int clDescTblNumEnt = 1;
  1191.     /* initialize the netPool */
  1192.     if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof (NET_POOL))) == NULL)
  1193.         {
  1194. return ERROR;
  1195.         }
  1196.     /* 
  1197.      * Establish the memory area that we will share with the device.  This
  1198.      * area may be thought of as being divided into two parts: one is the 
  1199.      * buffer descriptors (BD) and the second one is for the data buffers. 
  1200.      * Since they have different requirements as far as cache are concerned,
  1201.      * they may be addressed separately.
  1202.      * We'll deal with the BDs area first.  If the caller has provided 
  1203.      * an area, then we assume it is non-cacheable and will not require 
  1204.      * the use of the special cache routines. If the caller has not provided 
  1205.      * an area, then we must obtain it from the system, using the cache 
  1206.      * savvy allocation routine.
  1207.      */
  1208.     switch ((int) pDrvCtrl->pBdBase) 
  1209.         {
  1210.         case NONE :      /* we must obtain it */
  1211. /* this driver can't handle write incoherent caches */
  1212.     if (!CACHE_DMA_IS_WRITE_COHERENT ()) 
  1213.                 {
  1214.         MOT_FCC_LOG (MOT_FCC_DBG_LOAD, 
  1215.                             "motFccInitMem: shared memory not cache coherentn",
  1216.                             0,0,0,0,0,0);
  1217.         return ERROR;
  1218.         }
  1219.     rbdMemSize = MOT_FCC_RBD_SZ * pDrvCtrl->rbdNum;
  1220.     tbdMemSize = MOT_FCC_TBD_SZ * pDrvCtrl->tbdNum;
  1221.     bdMemSize = rbdMemSize + tbdMemSize + MOT_FCC_BD_ALIGN;
  1222.     pDrvCtrl->pBdBase = cacheDmaMalloc(bdMemSize);
  1223.     if (pDrvCtrl->pBdBase == NULL)
  1224.                 {     
  1225.                 /* no memory available */
  1226.         MOT_FCC_LOG (MOT_FCC_DBG_LOAD, 
  1227.                              "motFccInitMem: could not obtain memoryn",
  1228.                              0,0,0,0,0,0);
  1229.         return ERROR;
  1230.         }
  1231.     pDrvCtrl->bdSize = bdMemSize;
  1232.     MOT_FCC_FLAG_SET (MOT_FCC_OWN_BD_MEM);
  1233.     pDrvCtrl->bdCacheFuncs = cacheDmaFuncs;
  1234.     break;
  1235.         default :        /* the user provided an area */
  1236.             if (!pDrvCtrl->bdSize)
  1237.                 {
  1238.         MOT_FCC_LOG (MOT_FCC_DBG_LOAD, 
  1239.                              "motFccInitMem: not enough memoryn",0,0,0,0,0,0);
  1240.         return ERROR;
  1241.         }
  1242.     /* 
  1243.      * check whether user provided a number for Rx and Tx BDs
  1244.      * fill in the blanks if we can.
  1245.      * check whether enough memory was provided, etc.
  1246.      */
  1247.         
  1248.     if (MOT_FCC_FLAG_ISSET (MOT_FCC_INV_TBD_NUM) && 
  1249.                 MOT_FCC_FLAG_ISSET (MOT_FCC_INV_RBD_NUM)) 
  1250.                 {
  1251.         pDrvCtrl->tbdNum = pDrvCtrl->bdSize / 
  1252.                                    (MOT_FCC_TBD_SZ + MOT_FCC_RBD_SZ);
  1253.         pDrvCtrl->rbdNum = pDrvCtrl->tbdNum;
  1254.         } 
  1255.             else if (MOT_FCC_FLAG_ISSET (MOT_FCC_INV_TBD_NUM)) 
  1256.                 {
  1257.         rbdMemSize = MOT_FCC_RBD_SZ * pDrvCtrl->rbdNum;
  1258.         pDrvCtrl->tbdNum = (pDrvCtrl->bdSize - rbdMemSize) / 
  1259.                                    MOT_FCC_TBD_SZ;
  1260.         } 
  1261.             else if (MOT_FCC_FLAG_ISSET (MOT_FCC_INV_RBD_NUM)) 
  1262.                 {
  1263.         tbdMemSize = MOT_FCC_TBD_SZ * pDrvCtrl->tbdNum;
  1264.         pDrvCtrl->rbdNum = (pDrvCtrl->bdSize - tbdMemSize) / 
  1265.                                    MOT_FCC_RBD_SZ;
  1266.         } 
  1267.             else 
  1268.                 {
  1269.         rbdMemSize = MOT_FCC_RBD_SZ * pDrvCtrl->rbdNum;
  1270.         tbdMemSize = MOT_FCC_TBD_SZ * pDrvCtrl->tbdNum;
  1271.         bdMemSize = rbdMemSize + tbdMemSize + MOT_FCC_BD_ALIGN;
  1272.         if (pDrvCtrl->bdSize < bdMemSize) 
  1273.                     {
  1274.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, 
  1275.                                  "motFccInitMem: not enough memoryn",
  1276.                                  0,0,0,0,0,0);
  1277.     return ERROR;
  1278.             }
  1279.         }
  1280.             if ((pDrvCtrl->tbdNum < MOT_FCC_TBD_MIN) || 
  1281.                 (pDrvCtrl->rbdNum < MOT_FCC_RBD_MIN)) 
  1282.                 {
  1283.         MOT_FCC_LOG (MOT_FCC_DBG_LOAD, 
  1284.                              "motFccInitMem: not enough BDsn",0,0,0,0,0,0);
  1285.         return ERROR;
  1286.         }
  1287.     MOT_FCC_FLAG_CLEAR (MOT_FCC_OWN_BD_MEM);
  1288.     pDrvCtrl->bdCacheFuncs = cacheNullFuncs;
  1289.     break;
  1290.         }
  1291.     /* zero the shared memory */
  1292.     memset (pDrvCtrl->pBdBase, 0, (int) pDrvCtrl->bdSize);
  1293.     /* align the shared memory */
  1294.     pDrvCtrl->pBdBase = (char *) ROUND_UP((UINT32)pDrvCtrl->pBdBase,
  1295.                                           MOT_FCC_BD_ALIGN);
  1296.     /* 
  1297.      * number of clusters, including loaning buffers, a min number
  1298.      * of transmit clusters for copy-mode transmit, and one transmit
  1299.      * cluster for polling operation.
  1300.      */
  1301.     clNum = pDrvCtrl->rbdNum + MOT_FCC_BD_LOAN_NUM + MOT_FCC_TX_POLL_NUM + 
  1302.             MOT_FCC_TX_CL_NUM;
  1303.     /* pool of mblks */
  1304.     if (mclBlkConfig.mBlkNum == 0)
  1305.         {
  1306. mclBlkConfig.mBlkNum = clNum * pDrvCtrl->mblkMult;
  1307.         }
  1308.     /* pool of clusters, including loaning buffers */
  1309.     if (clDescTbl[0].clNum == 0) 
  1310.         {
  1311. clDescTbl[0].clNum = clNum * pDrvCtrl->clMult;
  1312. clDescTbl[0].clSize = MOT_FCC_MAX_CL_LEN;
  1313.         } 
  1314.     /* there's a cluster overhead and an alignment issue */
  1315.     clDescTbl[0].memSize = clDescTbl[0].clNum * 
  1316.                            (clDescTbl[0].clSize + CL_OVERHEAD) + 
  1317.                            CL_ALIGNMENT - 1;
  1318.     /*
  1319.      * Now we'll deal with the data buffers.  If the caller has provided 
  1320.      * an area, then we assume it is non-cacheable and will not require 
  1321.      * the use of the special cache routines. If the caller has not provided 
  1322.      * an area, then we must obtain it from the system, but we will not be
  1323.      * using the cache savvy allocation routine, since we will flushing or
  1324.      * invalidate the data cache itself as appropriate. This speeds up
  1325.      * driver operation, as the network stack will be able to process data
  1326.      * in a cacheable area.
  1327.      */
  1328.     switch ((int) pDrvCtrl->pBufBase) 
  1329.         {
  1330.         case NONE :      /* we must obtain it */
  1331.     clDescTbl[0].memArea = (char *) memalign(CL_ALIGNMENT, 
  1332.                                clDescTbl[0].memSize);
  1333.     if (clDescTbl[0].memArea == NULL)
  1334.                 {
  1335.         MOT_FCC_LOG (MOT_FCC_DBG_LOAD, 
  1336.                              ("motFccInitMem: could not obtain memoryn"),
  1337.                              0,0,0,0,0,0);
  1338.         return ERROR;
  1339.         }
  1340.     /* store the pointer to the clBlock area and its size */
  1341.     pDrvCtrl->pBufBase = clDescTbl[0].memArea;
  1342.     pDrvCtrl->bufSize = clDescTbl[0].memSize;
  1343.     MOT_FCC_FLAG_SET (MOT_FCC_OWN_BUF_MEM);
  1344.     /* cache functions descriptor for data buffers */
  1345.     motFccBufCacheFuncs.flushRtn = cacheArchFlush;
  1346.     motFccBufCacheFuncs.invalidateRtn = cacheArchInvalidate;
  1347.     motFccBufCacheFuncs.virtToPhysRtn = NULL;
  1348.     motFccBufCacheFuncs.physToVirtRtn = NULL;
  1349.     pDrvCtrl->bufCacheFuncs = motFccBufCacheFuncs;
  1350.     break;
  1351.         default :        /* the user provided an area */
  1352.     if (pDrvCtrl->bufSize == 0) 
  1353.                 {
  1354.         MOT_FCC_LOG (MOT_FCC_DBG_LOAD, 
  1355.                             ("motFccInitMem: not enough memoryn"),0,0,0,0,0,0);
  1356.         return ERROR;
  1357.         }
  1358.     /* 
  1359.      * check the user provided enough memory with reference
  1360.      * to the given number of receive/transmit frames, if any.
  1361.      */
  1362.     if (pDrvCtrl->bufSize < clDescTbl[0].memSize) 
  1363.                 {
  1364.         MOT_FCC_LOG (MOT_FCC_DBG_LOAD, 
  1365.                             ("motFccInitMem: not enough memoryn"),0,0,0,0,0,0);
  1366.         return ERROR;
  1367.         }
  1368.     /* Set memArea to the buffer base */
  1369.     clDescTbl[0].memArea = pDrvCtrl->pBufBase;
  1370.     MOT_FCC_FLAG_CLEAR (MOT_FCC_OWN_BUF_MEM);
  1371.     pDrvCtrl->bufCacheFuncs = cacheNullFuncs;
  1372.     break;
  1373.         }
  1374.     /* zero and align the shared memory */
  1375.     memset (pDrvCtrl->pBufBase, 0, (int) pDrvCtrl->bufSize);
  1376.     pDrvCtrl->pBufBase = (char *) ROUND_UP((UINT32)pDrvCtrl->pBufBase,
  1377.                                            CL_ALIGNMENT);
  1378.  
  1379.     /* pool of cluster blocks */
  1380.     if (mclBlkConfig.clBlkNum == 0)
  1381.         {
  1382. mclBlkConfig.clBlkNum = clDescTbl[0].clNum;
  1383.         }
  1384.     /* get memory for mblks */
  1385.     if (mclBlkConfig.memArea == NULL) 
  1386.         {
  1387. /* memory size adjusted to hold the netPool pointer at the head */
  1388. mclBlkConfig.memSize = ((mclBlkConfig.mBlkNum * 
  1389.                                 (M_BLK_SZ + MBLK_ALIGNMENT)) + 
  1390.                                 (mclBlkConfig.clBlkNum * 
  1391.                                 (CL_BLK_SZ + CL_ALIGNMENT)));
  1392. mclBlkConfig.memArea = (char *) memalign (MBLK_ALIGNMENT, 
  1393.                                                   mclBlkConfig.memSize);
  1394.     if (mclBlkConfig.memArea == NULL) 
  1395.                 {
  1396.         return ERROR;
  1397.         }
  1398.             else
  1399.                 {
  1400.                 memset (mclBlkConfig.memArea, 0, (int)mclBlkConfig.memSize);  
  1401.                 }
  1402. /* store the pointer to the mBlock area */
  1403. pDrvCtrl->pMBlkArea = mclBlkConfig.memArea;
  1404. pDrvCtrl->mBlkSize = mclBlkConfig.memSize;
  1405.         }
  1406.     /* init the mem pool */
  1407.     if (netPoolInit (pDrvCtrl->endObj.pNetPool, 
  1408.                      &mclBlkConfig, &clDescTbl[0], clDescTblNumEnt, 
  1409.                      NULL) == ERROR) 
  1410.         {
  1411. return ERROR;
  1412.         }
  1413.     if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool, 
  1414.                                             MOT_FCC_MAX_CL_LEN, FALSE)) == NULL)       
  1415.         {
  1416. return ERROR;
  1417.         }
  1418.     /* wait for 25% available before restart MUX */
  1419.     pDrvCtrl->unStallThresh = (pDrvCtrl->tbdNum >> 2);
  1420.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("motFccInitMem... Donen"), 
  1421.                  0, 0, 0, 0, 0, 0);
  1422.     return OK;
  1423.     }
  1424. /**************************************************************************
  1425. *
  1426. * motFccStart - start the device
  1427. *
  1428. * This routine starts the FCC device and brings it up to an operational
  1429. * state.  The driver must have already been loaded with the motFccEndLoad()
  1430. * routine.
  1431. *
  1432. * INTERNAL
  1433. * The speed field inthe phyInfo structure is only set after the call
  1434. * to the physical layer init routine. On the other hand, the mib2 
  1435. * interface is initialized in the motFccEndLoad() routine, and the default
  1436. * value of 10Mbit assumed there is not always correct. We need to
  1437. * correct it here.
  1438. *
  1439. * RETURNS: OK, or ERROR if the device could not be started.
  1440. *
  1441. */
  1442. LOCAL STATUS motFccStart
  1443.     (
  1444.     DRV_CTRL *pDrvCtrl
  1445.     )
  1446.     {
  1447.     int         retVal; /* convenient holder for return value */
  1448.     char bucket[4]; /* holder for vxMemProbe */
  1449.     MOT_FCC_LOG (MOT_FCC_DBG_START, "Starting end...n", 1, 2, 3, 4, 5, 6);
  1450.     /* must have been loaded */
  1451.     if (!pDrvCtrl->loaded)
  1452. return ERROR;
  1453.     if (vxMemProbe ((char *) (pDrvCtrl->fccIramAddr), 
  1454.         VX_READ, 4, &bucket[0]) != OK) 
  1455.         {
  1456.         MOT_FCC_LOG (MOT_FCC_DBG_START, ": need MMU mapping for address 0x%xn",
  1457.                    (UINT32) pDrvCtrl->fccIramAddr, 2, 3, 4, 5, 6);
  1458. return ERROR;
  1459.         }
  1460.     if (motFccTbdInit(pDrvCtrl) == ERROR || motFccRbdInit(pDrvCtrl) == ERROR)
  1461. return ERROR;
  1462.     /* set some flags to default values */
  1463.     pDrvCtrl->txStall = FALSE;
  1464.     pDrvCtrl->tbdIndex = 0;
  1465.     pDrvCtrl->usedTbdIndex = 0;
  1466.     pDrvCtrl->cleanTbdNum = pDrvCtrl->tbdNum;
  1467.     pDrvCtrl->rbdIndex = 0;
  1468.     /* acknowledge system interrupt */
  1469.     SYS_FCC_INT_ACK (pDrvCtrl, retVal);
  1470.     if (retVal == ERROR)
  1471. return ERROR;
  1472.     /* connect the interrupt handler */
  1473.     SYS_FCC_INT_CONNECT (pDrvCtrl, motFccInt, (int) pDrvCtrl, retVal);
  1474.     if (retVal == ERROR)
  1475. return ERROR;
  1476.     /* enable system interrupt: set relevant bit in SIMNR_L */
  1477.     SYS_FCC_INT_ENABLE (pDrvCtrl, retVal);
  1478.     if (retVal == ERROR)
  1479. return ERROR;
  1480.     /* call the BSP to do any other initialization (MII interface) */
  1481.     SYS_FCC_ENET_ENABLE;
  1482.     /* initialize some fields in the PHY info structure */
  1483.     if (motFccPhyPreInit (pDrvCtrl) != OK) 
  1484.         {
  1485. MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("Failed to pre-initialize the PHYn"), 
  1486.                      0, 0, 0, 0, 0, 0);
  1487. return ERROR;
  1488.         }
  1489.     /* initialize the Physical medium layer */
  1490.     if (_func_motFccPhyInit == NULL)
  1491. return ERROR;
  1492.     if (((* _func_motFccPhyInit) (pDrvCtrl->phyInfo)) != OK) 
  1493.         {
  1494. MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("Failed to initialize the PHYn"), 
  1495.                      0, 0, 0, 0, 0, 0);
  1496. return ERROR;
  1497.         }
  1498.     /* initialize the chip */
  1499.     if (motFccInit (pDrvCtrl) == ERROR)
  1500. return ERROR;
  1501.     if (motFccJobQInit(pDrvCtrl) == ERROR)
  1502.         return ERROR; 
  1503.     /* correct the speed for the mib2 stuff */
  1504.     pDrvCtrl->endObj.mib2Tbl.ifSpeed = pDrvCtrl->phyInfo->phySpeed;
  1505.     /* startup the transmitter */
  1506.     pDrvCtrl->fccReg->fcc_gmr |= M8260_GFMR_ENT;
  1507.     /* mark the interface as up */
  1508.     END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  1509.     /* startup the receiver */
  1510.     MOT_FCC_RX_ACTIVATE;
  1511.     /* Flush the write pipe */
  1512.     CACHE_PIPE_FLUSH ();
  1513.     MOT_FCC_LOG (MOT_FCC_DBG_START, ("Starting end... Donen"), 
  1514.                  1, 2, 3, 4, 5, 6);
  1515.     return OK;
  1516.     }
  1517. /**************************************************************************
  1518. *
  1519. * motFccStop - stop the 'motfcc' interface
  1520. *
  1521. * This routine marks the interface as inactive, disables interrupts and 
  1522. * the Ethernet Controller. As a result, reception is stopped immediately,
  1523. * and transmission is stopped after a bad CRC is appended to any frame
  1524. * currently being transmitted. The reception/transmission control logic
  1525. * (FIFO pointers, buffer descriptors, etc.) is reset. To bring the 
  1526. * interface back up, motFccStart() must be called.
  1527. *
  1528. * RETURNS: OK, always.
  1529. */
  1530. LOCAL STATUS motFccStop
  1531.     (
  1532.     DRV_CTRL *pDrvCtrl
  1533.     )
  1534.     {
  1535.     int retVal; /* convenient holder for return value */
  1536.     UINT8 command = 0; /* command to issue to the CP */
  1537.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("motFccStop...n"), 1, 2, 3, 4, 5, 6);
  1538.     /* mark the interface as down */
  1539.     END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  1540.     /* issue a graceful stop transmit command to the CP */
  1541.     command = M8260_CPCR_TX_GRSTOP;
  1542.     if (motFccCpcrCommand (pDrvCtrl, command) == ERROR)
  1543. return ERROR;
  1544.     /* wait for the related interrupt */
  1545.     MOT_FCC_GRA_SEM_TAKE;
  1546.     /* mask chip interrupts */
  1547.     MOT_FCC_INT_DISABLE;   
  1548.     /* disable system interrupt: reset relevant bit in SIMNR_L */
  1549.     SYS_FCC_INT_DISABLE (pDrvCtrl, retVal);
  1550.     if (retVal == ERROR)
  1551. return ERROR;
  1552.     /* disconnect the interrupt handler */
  1553.     SYS_FCC_INT_DISCONNECT (pDrvCtrl, motFccInt, (int)pDrvCtrl, retVal);
  1554.     if (retVal == ERROR)
  1555. return ERROR;
  1556.     /* call the BSP to disable the MII interface */
  1557.     SYS_FCC_ENET_DISABLE;
  1558.     /* free buffer descriptors */
  1559.     if (motFccBdFree (pDrvCtrl) != OK)
  1560. return ERROR;
  1561.     MOT_FCC_LOG (MOT_FCC_DBG_LOAD, ("motFccStop... Done n"), 1, 2, 3, 4, 5, 6);
  1562.     return OK;
  1563.     }
  1564. /*******************************************************************************
  1565. *
  1566. * motFccSendDummyFrame - send a dummy ethernet packet out for ARP
  1567. *
  1568. * This routine is run in netTask's context.
  1569. *
  1570. * RETURNS: N/A
  1571. */
  1572. LOCAL void motFccSendDummyFrame
  1573.     (
  1574.     DRV_CTRL *pDrvCtrl
  1575.     )
  1576.     {
  1577.     int          intLevel;    /* current intr level */
  1578.     int          len;       /* length of data to be sent */
  1579.     char         *pBuf;       /* pointer to data to be sent */
  1580.     FCC_BD       *pTbd;       /* pointer to the current ready TBD */
  1581.     FCC_TBD_LIST *pTbdList;   /* pointer to the TBD list*/
  1582. END_TX_SEM_TAKE(&pDrvCtrl->endObj, WAIT_FOREVER);
  1583. pTbd = &pDrvCtrl->tbdBase[pDrvCtrl->tbdIndex];
  1584. pTbdList = &pDrvCtrl->pTbdList[pDrvCtrl->tbdIndex];
  1585. pBuf = pDrvCtrl->pTxPollBuf;
  1586. memset(pBuf,0xff,6);
  1587. bcopy((char *)MOT_FCC_ADDR_GET(&pDrvCtrl->endObj),pBuf+6,6);
  1588. len = 100;
  1589. MOT_FCC_CACHE_FLUSH(pBuf,len); /* flush the cache, if necessary */
  1590. pTbd->bdLen = len;
  1591. pTbd->bdAddr = (unsigned long)pBuf;
  1592. pTbdList->pBuf = NULL;         /* not a Cluster pointer */
  1593. pTbdList->info = 0; /* so we know NOT to free in ISR */
  1594. intLevel = intLock();
  1595. pDrvCtrl->cleanTbdNum -= 1; /* keep accurate count of clean BDs */
  1596. if (pDrvCtrl->tbdIndex == (pDrvCtrl->tbdNum - 1))
  1597.     {
  1598.     pTbd->word1 =
  1599.          ( M8260_FETH_TBD_R
  1600.                 | M8260_FETH_TBD_L
  1601.         | M8260_FETH_TBD_TC
  1602.         | M8260_FETH_TBD_I
  1603.         | M8260_FETH_TBD_W
  1604.         | M8260_FETH_TBD_PAD
  1605.         );
  1606.     }
  1607. else
  1608.     {
  1609.     pTbd->word1 =
  1610.         ( M8260_FETH_TBD_R
  1611.         | M8260_FETH_TBD_L
  1612.         | M8260_FETH_TBD_TC
  1613.         | M8260_FETH_TBD_I
  1614.         | M8260_FETH_TBD_PAD
  1615.         );
  1616.     }
  1617. /* move on to the next element */
  1618. pDrvCtrl->tbdIndex = (pDrvCtrl->tbdIndex + 1) % pDrvCtrl->tbdNum;
  1619. intUnlock (intLevel);
  1620. END_TX_SEM_GIVE(&pDrvCtrl->endObj);
  1621.     }
  1622. /*******************************************************************************
  1623. *
  1624. * motFccHandleLSCJob - task-level link status event processor
  1625. *
  1626. * This routine is run in netTask's context.
  1627. *
  1628. * RETURNS: N/A
  1629. */
  1630. LOCAL void motFccHandleLSCJob
  1631.     (
  1632.     DRV_CTRL *pDrvCtrl
  1633.     )
  1634.     {
  1635.     int         intLevel; /* current intr level */
  1636.     UINT16 miiStat;
  1637.     int         retVal;
  1638.     int         duplex;
  1639.     UINT32 fccIramAddr;
  1640.     UINT32      fpsmrVal;
  1641.     fccIramAddr = pDrvCtrl->fccIramAddr;
  1642.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, "motFccHandleLSCJob: n", 0, 0, 0, 0, 0, 0);
  1643.     ++pDrvCtrl->Stats->numLSCHandlerEntries;
  1644.     /* read MII status register once to unlatch link status bit */
  1645.     
  1646.     retVal = motFccMiiRead(pDrvCtrl,pDrvCtrl->phyInfo->phyAddr,1,&miiStat);
  1647.     /* read again to know it's current value */
  1648.     
  1649.     retVal = motFccMiiRead(pDrvCtrl,pDrvCtrl->phyInfo->phyAddr,1,&miiStat);
  1650.     if(miiStat & 4) /* if link is now up */
  1651. {
  1652. if(_func_motFccPhyDuplex)
  1653.     {
  1654.     /* get duplex mode from BSP */
  1655.     retVal = (* _func_motFccPhyDuplex)(pDrvCtrl->phyInfo, &duplex);
  1656.     
  1657.     if(retVal == OK)
  1658.         {
  1659.         intLevel = intLock();
  1660.         MOT_FCC_REG_LONG_RD (fccIramAddr + M8260_FCC_FPSMR_OFF, 
  1661.                                      fpsmrVal);
  1662.         if(duplex) /* TRUE when full duplex mode is active */
  1663.             { 
  1664.             fpsmrVal |= (M8260_FPSMR_ETH_LPB | M8260_FPSMR_ETH_FDE);
  1665.             MOT_FCC_LOG(MOT_FCC_DBG_ANY, 
  1666.                                 "motFccHandleLSCJob: enable full duplexn", 
  1667.                                  0, 0, 0, 0, 0, 0);
  1668.             }
  1669.         else
  1670.             {
  1671.             fpsmrVal &= ~(M8260_FPSMR_ETH_LPB | M8260_FPSMR_ETH_FDE);
  1672.             MOT_FCC_LOG(MOT_FCC_DBG_ANY, 
  1673.                                 "motFccHandleLSCJob: disable full duplexn", 
  1674.                                 0, 0, 0, 0, 0, 0);
  1675.     }
  1676.     MOT_FCC_REG_LONG_WR (fccIramAddr + M8260_FCC_FPSMR_OFF, fpsmrVal);
  1677.     intUnlock (intLevel);
  1678.     /* check device mode */
  1679.     if(!MOT_FCC_FLAG_ISSET(MOT_FCC_POLLING))
  1680.         {
  1681.         /* check if any transmits are currently pending */
  1682.         if(pDrvCtrl->cleanTbdNum == pDrvCtrl->tbdNum)
  1683.             {
  1684.             netJobAdd((FUNCPTR)motFccSendDummyFrame,(int)pDrvCtrl,
  1685.                               0,0,0,0);
  1686.             netJobAdd((FUNCPTR)motFccSendDummyFrame,(int)pDrvCtrl,
  1687.                               0,0,0,0);
  1688.             netJobAdd((FUNCPTR)motFccSendDummyFrame,(int)pDrvCtrl,
  1689.                               0,0,0,0);
  1690.             }
  1691.         }
  1692.     }
  1693. }
  1694.     }
  1695.     intLevel = intLock();
  1696.     pDrvCtrl->lscHandling = 0;
  1697.     intUnlock (intLevel);
  1698.     ++pDrvCtrl->Stats->numLSCHandlerExits;
  1699.     }
  1700. /*******************************************************************************
  1701. *
  1702. * motFccJobQInit - Create a msgQueue for motFccJobQueue() 
  1703. *  
  1704. * This routine creates the msgQueue to be used buy motFccJobQueue(). 
  1705. *
  1706. * RETURNS: OK, or ERROR
  1707. */
  1708. LOCAL STATUS motFccJobQInit
  1709.     (
  1710.     DRV_CTRL * pDrvCtrl
  1711.     )
  1712.     {
  1713.   
  1714.     if (!(pDrvCtrl->txJobMsgQId = msgQCreate(pDrvCtrl->txJobMsgQLen, 
  1715.                                      sizeof(TODO_NODE), MSG_Q_FIFO)))
  1716.         {
  1717.         logMsg("ERROR - motFccjobQueInit: unable to create msgQueue.n",
  1718.                 0,0,0,0,0,0);
  1719.         return(ERROR);
  1720.         }
  1721.  
  1722.     return (OK);
  1723.     }
  1724. /*******************************************************************************
  1725. *
  1726. * motFccJobQAdd - Add a job to the txJobMsgQueue
  1727. *
  1728. * This routine passes a motFccTxFreeJob to motFccJobQueue() with msgQSend(). 
  1729. * If msgQSend() returns an ERROR it then sends the motFccTxFreeJob to 
  1730. * the netJobRing with netJobAdd(). 
  1731. *
  1732. * RETURNS: N/A
  1733. */
  1734. LOCAL void motFccJobQAdd
  1735.     (
  1736.     DRV_CTRL * pDrvCtrl,
  1737.     FUNCPTR    routine,
  1738.     int        param1,
  1739.     int        param2,
  1740.     int        param3,
  1741.     int        param4,
  1742.     int        param5
  1743.     )
  1744.     { 
  1745.     TODO_NODE  pJobNode; 
  1746.      
  1747.     pJobNode.routine = routine;
  1748.     pJobNode.param1 = param1;
  1749.     pJobNode.param2 = param2;
  1750.     pJobNode.param3 = param3;
  1751.     pJobNode.param4 = param4;
  1752.     pJobNode.param5 = param5;
  1753.     if ((msgQSend (pDrvCtrl->txJobMsgQId, (char *)&pJobNode, 
  1754.                    sizeof(TODO_NODE), NO_WAIT, 0)) == ERROR)
  1755.         {      
  1756.         netJobAdd((FUNCPTR)routine, param1, param2, param3, param4, param5);
  1757.         }
  1758.     }
  1759. /*******************************************************************************
  1760. *
  1761. * motFccJobQueue - Empties the txJobMsgQueue
  1762. *
  1763. * This routine is added by the ISR to the netJobRing with netJobAdd(). 
  1764. * It de-queues and executes the motFccTxFreeJob s then passed to it by 
  1765. * motFccJobQAdd() in the ISR. Its purpose is to reduce the number of jobs 
  1766. * added to the netJobRing to prevent "netTask: netJobRing overflow!" panics  
  1767. *
  1768. * RETURNS: OK, or ERROR
  1769. */
  1770. LOCAL STATUS  motFccJobQueue
  1771.     (
  1772.     DRV_CTRL * pDrvCtrl
  1773.     )
  1774.     {
  1775.     TODO_NODE     jobNode;
  1776.     int           msgQRxStatus;
  1777.     int           intLockKey;
  1778.     int   localError = 0;
  1779.  
  1780.     while (msgQNumMsgs(pDrvCtrl->txJobMsgQId) > 0)
  1781.         {
  1782.         msgQRxStatus = msgQReceive(pDrvCtrl->txJobMsgQId, (char *)&jobNode,
  1783.                                    sizeof(TODO_NODE), NO_WAIT);
  1784.         if (msgQRxStatus == ERROR)
  1785.             {
  1786.             localError = errnoGet();
  1787.             if (localError != S_objLib_OBJ_TIMEOUT)
  1788.                 {
  1789.                  MOT_FCC_LOG(MOT_FCC_DBG_INT_TX_ERR,
  1790.                              "motFccJobQueue: msgQReceive failed! error %xn", 
  1791.                               0, 0, 0, 0, 0, 0);
  1792.                 }
  1793.             }
  1794.         else
  1795.             {
  1796.             (*(jobNode.routine)) (jobNode.param1, 
  1797.                                   jobNode.param2,
  1798.                                   jobNode.param3, 
  1799.                                   jobNode.param4,
  1800.                                   jobNode.param5);
  1801.             msgQRxStatus = OK;
  1802.             }
  1803.         } 
  1804.         intLockKey = intLock();  
  1805.         
  1806.         /* motFccJobQueue() is off the netJobRing */
  1807.         pDrvCtrl->txJobQState = FALSE; 
  1808.         intUnlock (intLockKey);
  1809.         return (msgQRxStatus);
  1810.     }
  1811. /*******************************************************************************
  1812. * motFccTxFreeJob - 
  1813. *
  1814. *
  1815. * RETURNS: N/A
  1816. */
  1817. LOCAL void motFccTxFreeJob 
  1818.     (
  1819.     DRV_CTRL *pDrvCtrl,void *pBuf,unsigned long info
  1820.     )
  1821.     {
  1822.     /* up-date statistics */
  1823.     if (info & PKT_TYPE_MULTI)
  1824.         {
  1825. pDrvCtrl->endObj.mib2Tbl.ifOutNUcastPkts += 1;
  1826.         }
  1827.     else
  1828.         {
  1829. END_ERR_ADD(&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1830.         }
  1831.     /* free the Mblk or the cluster, whichever is appropriate */
  1832.     if ((info & BUF_TYPE_MBLK))
  1833.         {
  1834. netMblkClChainFree((M_BLK *)pBuf);
  1835.         }
  1836.     else if ((info & BUF_TYPE_CL))
  1837.         {
  1838. NET_BUF_FREE(pBuf);
  1839.         }
  1840.     }
  1841. /*******************************************************************************
  1842. * motFccTxErrRecoverJob - 
  1843. *
  1844. *
  1845. * RETURNS: N/A
  1846. */
  1847. LOCAL void motFccTxErrRecoverJob
  1848.     (
  1849.     DRV_CTRL *pDrvCtrl, 
  1850.     void *bdPtr
  1851.     )
  1852.     {
  1853.     UINT32     immrVal = pDrvCtrl->immrVal; /* holder for the immr value */
  1854.     UINT8     fccNum = pDrvCtrl->fccNum;  /* holder for the fcc number */
  1855.     UINT8     fcc = fccNum - 1;  /* a convenience */
  1856.     volatile UINT32 cpcrVal;      /* a convenience */
  1857.     /* issue a init tx command to the CP */
  1858.     cpcrVal = 0;
  1859.     /* wait until the CP is clear */
  1860.     do {
  1861.     MOT_FCC_REG_LONG_RD (M8260_CPCR (immrVal), cpcrVal);
  1862.     } while (cpcrVal & M8260_CPCR_FLG);
  1863.     /* issue the command to the CP */
  1864.     cpcrVal = (M8260_CPCR_OP ((UINT8)M8260_CPCR_TX_INIT)
  1865.        | M8260_CPCR_SBC (M8260_CPCR_SBC_FCC1 | (fcc * 0x1))
  1866.        | M8260_CPCR_PAGE (M8260_CPCR_PAGE_FCC1 | (fcc * 0x1))
  1867.        | M8260_CPCR_MCN (M8260_CPCR_MCN_ETH)
  1868.        | M8260_CPCR_FLG);
  1869.     MOT_FCC_REG_LONG_WR (M8260_CPCR (immrVal), cpcrVal);
  1870.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  1871.     /* issue a restart tx command to the CP */
  1872.     cpcrVal = 0;
  1873.     /* wait until the CP is clear */
  1874.     do {
  1875.     MOT_FCC_REG_LONG_RD (M8260_CPCR (immrVal), cpcrVal);
  1876.     } while (cpcrVal & M8260_CPCR_FLG);
  1877.     /* issue the command to the CP */
  1878.     cpcrVal = (M8260_CPCR_OP ((UINT8)M8260_CPCR_TX_RESTART)
  1879.        | M8260_CPCR_SBC (M8260_CPCR_SBC_FCC1 | (fcc * 0x1))
  1880.        | M8260_CPCR_PAGE (M8260_CPCR_PAGE_FCC1 | (fcc * 0x1))
  1881.        | M8260_CPCR_MCN (M8260_CPCR_MCN_ETH)
  1882.        | M8260_CPCR_FLG);
  1883.     MOT_FCC_REG_LONG_WR (M8260_CPCR (immrVal), cpcrVal);
  1884.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  1885.     do {
  1886.     pDrvCtrl->fccPar->tbptr = (ULONG)bdPtr;
  1887.     } while(pDrvCtrl->fccPar->tbptr != (ULONG)bdPtr);
  1888.     pDrvCtrl->fccReg->fcc_fccm |= (M8260_FEM_ETH_TXE|M8260_FEM_ETH_TXB);
  1889.     pDrvCtrl->fccReg->fcc_gmr |= M8260_GFMR_ENT;
  1890.     }
  1891. /*******************************************************************************
  1892. * motFccInt - entry point for handling interrupts from the FCC
  1893. *
  1894. * The interrupting events are acknowledged to the device, so that the device
  1895. * will de-assert its interrupt signal.  The amount of work done here is kept
  1896. * to a minimum; the bulk of the work is deferred to the netTask.
  1897. *
  1898. * RETURNS: N/A
  1899. */
  1900. LOCAL void motFccInt 
  1901.     (
  1902.     DRV_CTRL *pDrvCtrl
  1903.     )
  1904.     {
  1905.     UINT16 event; /* event intr register */
  1906.     UINT16 mask; /* holder for the mask intr register */
  1907.     UINT16 status; /* status word */
  1908.     FCC_REG_T *reg = pDrvCtrl->fccReg;
  1909.     FCC_BD *bdPtr;
  1910.     ++pDrvCtrl->Stats->numIsrEntries;
  1911.     event = reg->fcc_fcce;
  1912.     reg->fcc_fcce = event;
  1913.     mask = reg->fcc_fccm;
  1914.     status = event & mask;
  1915.     /*
  1916.      * This driver gives highest priority to keeping the receive BDs ready
  1917.      * to receive data -- empty bit set, and an attached buffer. When 
  1918.      * processing frame interrupts, if a replacement buffer is not available
  1919.      * for the current BD, then that frame data is discarded. This is done
  1920.      * by simply clearing the length field and resetting the BD status word.
  1921.      * The buffer address that was previously attached to the BD will then
  1922.      * be over-written the next time the FCC consults that BD. The goal is
  1923.      * to prevent the 'buffer busy' condition where the FCC is receiving
  1924.      * frame data and has no empty BD in which to store the frame.
  1925.      * In practice, the 'busy' condition will still occur in some cases.
  1926.      *   1. Excessive interrupt latency caused by either the application
  1927.      *      or by other device drivers.
  1928.      *   2. Too few receive BDs.
  1929.      *   3. An excessive number of consecutive short frames (if enabled) or
  1930.      *      an excessive number of consecutive bad CRC frames.
  1931.      *      (NOTE: an excessive number of too long frames (LG) is not
  1932.      *       likely to be a problem)
  1933.      *   4. The intrusion of H/W debug devices (ICE, JTAG, etc.) causing
  1934.      *      excessive interrupt latency.
  1935.      * In general, if the FCC, for whatever reason, closes all the receive
  1936.      * BDs before this ISR gets a chance to process the BDs, busy will
  1937.      * likely occur. However, because this ISR immediately processes all
  1938.      * the BDs, we don't need any special handling when busy happens.
  1939.      * We simply make note of it and maintain a counter for it.
  1940.      */
  1941.     /* handle receive frame and busy interrupts */
  1942.     if (status & M8260_FEM_ETH_BSY)
  1943.         {
  1944. ++pDrvCtrl->Stats->motFccRxBsyErr;
  1945. MOT_FCC_LOG(MOT_FCC_DBG_INT_RX_ERR,
  1946.                     "motFccInt: ETH_BSY errorn",0,0,0,0,0,0);
  1947.         }
  1948.     if (status & M8260_FEM_ETH_RXF)
  1949.         {
  1950. int lostframes;
  1951. char *pBuf;
  1952. BPOOL *bpoolp;
  1953. MOT_FCC_LOG(MOT_FCC_DBG_INT,"motFccInt: rx intrn",0,0,0,0,0,0);
  1954. ++pDrvCtrl->Stats->numRXFInts;
  1955. lostframes = 0;
  1956. do {
  1957. bdPtr = &pDrvCtrl->rbdBase[pDrvCtrl->rbdIndex];
  1958. if ((bdPtr->word1 & M8260_FETH_RBD_E))
  1959.             {
  1960.     break; /* if BD is owned by CPM, don't touch it! */
  1961.     }
  1962. if (!(bpoolp = pDrvCtrl->RxFree))
  1963.             {
  1964.     ++lostframes;
  1965.     }
  1966.         else
  1967.             {
  1968.             pDrvCtrl->RxFree = bpoolp->next;
  1969.     bpoolp->next = NULL;
  1970.        if(pDrvCtrl->RxBufCount)
  1971.                 {
  1972.         pDrvCtrl->RxTail->next = bpoolp;
  1973.         }
  1974.             else
  1975.                 {
  1976.         pDrvCtrl->RxHead = bpoolp;
  1977.         }
  1978.     pDrvCtrl->RxTail = bpoolp;
  1979.     ++pDrvCtrl->RxBufCount;
  1980.             /* copy the whole descriptor to the container */
  1981.     bpoolp->desc = *bdPtr;
  1982.     /* take the replacement cluster buf pointer */
  1983.     pBuf = bpoolp->pBuf;
  1984.     /* and replace it with the previous cluster buf pointer */
  1985.     bpoolp->pBuf = pDrvCtrl->rBufList[pDrvCtrl->rbdIndex];
  1986.     /* then save the about-to-be-used cluster buf pointer */
  1987.     pDrvCtrl->rBufList[pDrvCtrl->rbdIndex] = pBuf;
  1988.             bdPtr->bdAddr = ROUND_UP((unsigned long)pBuf, 
  1989.                                          MOT_FCC_BUF_ALIGN );
  1990.     }
  1991. bdPtr->bdLen = 0;
  1992. /* 
  1993.          * update the status word: set WRAP bit for the last 
  1994.          * RBD in the ring 
  1995.          */
  1996. if (pDrvCtrl->rbdIndex == (pDrvCtrl->rbdNum - 1)) 
  1997.             {
  1998.     bdPtr->word1 = M8260_FETH_RBD_W | M8260_FETH_RBD_E | 
  1999.                            M8260_FETH_RBD_I;
  2000.     }
  2001.         else
  2002.             {
  2003.             bdPtr->word1 = M8260_FETH_RBD_E | M8260_FETH_RBD_I;
  2004.     }
  2005. /* move on to the next used RBD */
  2006. pDrvCtrl->rbdIndex = (pDrvCtrl->rbdIndex + 1) % (pDrvCtrl->rbdNum);
  2007. } while(TRUE);
  2008. if (lostframes)
  2009.             {
  2010.     pDrvCtrl->Stats->numRXFramesLostToBufferReuse += lostframes;
  2011. #if 0
  2012.    logMsg("%d receive frames lost due to no buffern",lostframes,0,0,0,0,0); 
  2013. #endif
  2014.     }
  2015.         }
  2016.     /* handle transmit errors and interrupts */
  2017.     if ((status & (M8260_FEM_ETH_TXE|M8260_FEM_ETH_TXB)))
  2018.         {
  2019. FCC_TBD_LIST *pTbdList;
  2020. UINT16 bdStatus;
  2021. void *pBuf;
  2022. ++pDrvCtrl->Stats->numTXBInts;
  2023. /* process all the consumed TBDs */
  2024. while (pDrvCtrl->cleanTbdNum < pDrvCtrl->tbdNum)
  2025.             {
  2026.     bdPtr = &pDrvCtrl->tbdBase[pDrvCtrl->usedTbdIndex];
  2027.     bdStatus = bdPtr->word1;
  2028.     if ((bdStatus & M8260_FETH_TBD_R))
  2029.                 {
  2030. break;
  2031.         }
  2032.     if (bdStatus & (M8260_FETH_TBD_LC | M8260_FETH_TBD_RL | 
  2033.                             M8260_FETH_TBD_UN | M8260_FETH_TBD_HB | 
  2034.                             M8260_FETH_TBD_CSL)) 
  2035.                 {
  2036. ++pDrvCtrl->Stats->motFccTxErr;
  2037. if ((bdStatus & M8260_FETH_TBD_RL))
  2038.                     {
  2039.     MOT_FCC_LOG (MOT_FCC_DBG_INT_TX_ERR, 
  2040.                                  "motFccTbdCheck: retransmit limit", 
  2041.                                  1, 2, 3, 4, 5, 6);
  2042.     ++pDrvCtrl->Stats->motFccTxRlErr;
  2043.     }
  2044. if ((bdStatus & M8260_FETH_TBD_LC))
  2045.                     {
  2046.     MOT_FCC_LOG (MOT_FCC_DBG_INT_TX_ERR, 
  2047.                                  "motFccTbdCheck: late collisionn", 
  2048.                                  1, 2, 3, 4, 5, 6);
  2049.     ++pDrvCtrl->Stats->motFccTxLcErr;
  2050.     }
  2051. if ((bdStatus & M8260_FETH_TBD_UN))
  2052.                     {
  2053.     MOT_FCC_LOG (MOT_FCC_DBG_INT_TX_ERR, 
  2054.                                  "motFccTbdCheck: tx underrunn", 
  2055.                                   1, 2, 3, 4, 5, 6);
  2056.     ++pDrvCtrl->Stats->motFccTxUrErr;
  2057.     }
  2058. if((bdStatus & M8260_FETH_TBD_CSL))
  2059.                     {
  2060.     MOT_FCC_LOG (MOT_FCC_DBG_INT_TX_ERR, 
  2061.                                  "motFccTbdCheck: carrier sense n", 
  2062.                                  1, 2, 3, 4, 5, 6);
  2063.     ++pDrvCtrl->Stats->motFccTxCslErr;
  2064.             }
  2065.                 }
  2066.             if ((bdStatus & (M8260_FETH_TBD_RL | M8260_FETH_TBD_UN | 
  2067.                              M8260_FETH_TBD_LC)))
  2068.                 {
  2069.         reg->fcc_gmr &= ~M8260_GFMR_ENT;
  2070.         reg->fcc_fcce = (M8260_FEM_ETH_TXE|M8260_FEM_ETH_TXB);
  2071.         reg->fcc_fccm &= ~(M8260_FEM_ETH_TXE|M8260_FEM_ETH_TXB);
  2072.         while (!(bdStatus & M8260_FETH_TBD_L) && 
  2073.                        pDrvCtrl->cleanTbdNum < pDrvCtrl->tbdNum)
  2074.                     {
  2075.             bdPtr->word1 &= 0x7fff;
  2076.             ++pDrvCtrl->cleanTbdNum;
  2077.             pDrvCtrl->usedTbdIndex = (pDrvCtrl->usedTbdIndex + 1) % 
  2078.                                               (pDrvCtrl->tbdNum);
  2079.             bdPtr = &pDrvCtrl->tbdBase[pDrvCtrl->usedTbdIndex];
  2080.             bdStatus = bdPtr->word1;
  2081.             }
  2082.         pTbdList = &pDrvCtrl->pTbdList[pDrvCtrl->usedTbdIndex];
  2083.         if ((bdStatus & M8260_FETH_TBD_L))
  2084.                     {
  2085.             if ((pBuf = pTbdList->pBuf))
  2086.                         {
  2087.         motFccTxFreeJob(pDrvCtrl,pBuf,pTbdList->info);
  2088.                 }
  2089.             bdPtr->word1 &= 0x7fff;
  2090.             ++pDrvCtrl->cleanTbdNum;
  2091.             pDrvCtrl->usedTbdIndex = (pDrvCtrl->usedTbdIndex + 1) % 
  2092.                                               (pDrvCtrl->tbdNum);
  2093.             bdPtr = &pDrvCtrl->tbdBase[pDrvCtrl->usedTbdIndex];
  2094.             }
  2095.                 else
  2096.                     {
  2097.             /* should be nothing to do here */
  2098.             }
  2099.         motFccTxErrRecoverJob(pDrvCtrl,(void*)bdPtr);
  2100.                 break;