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

VxWorks

开发平台:

C/C++

  1. /* dec21x40End.c - END-style DEC 21x40 PCI Ethernet network interface driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 03r,30may02,sru  Add run-time control of byte-swapping for PCI master
  8.                  operations
  9. 03q,13may02,rcs  added loanBuf option to End Loan string. #SPR 73414
  10. 03p,13may02,rcs  changed pDrvCtrl->pPhyInfo->phyMaxDelay to a multiple of 
  11.                  sysClkRateGet() & referenced pDrvCtrl->pPhyInfo->phyDelayParm 
  12.                  to sysClkRateGet(). SPR# 77012
  13. 03o,06may02,rcs  corrected behaviour and documentation for when memBase != -1
  14.                  SPR# 75455
  15. 03n,06may02,rcs  define all DRV_DEBUG flags and default DRV_LOG to display 
  16.                  DRV_DEBUG_LOAD conditions. SPR# 75457   
  17. 03m,22apr02,rcs  added init of  pDrvCtrl->txPollSendBuf to dec21x40InitMem() 
  18.                  and changed dec21x40PollSend() to usepDrvCtrl->txPollSendBuf. 
  19.                  SPR# 76102
  20. 03l,25mar02,pmr  fixed usage of rDesc3 (SPR 73470, 34891).
  21. 03k,18jan02,rcs  facilitated common source base with either RFC 1213 or 
  22.                  RFC 2233 depending on INCLUDE_RFC_1213 macro.
  23. 03j,14jan02,dat  Removing warnings from Diab compiler
  24. 03i,20jul01,rcs  used LE_BYTE_SWAP in dec21140EnetAddrGet() to return correct
  25.                  enetaddr for little endian archs (SPR# 69093)
  26. 03h,28aug01,ann  adding the code that copies the pMib2Tbl contents into
  27.                  mib2Tbl for backward compatibility - SPR 69697 & 69758
  28. 03g,16aug01,ann  providing the fix for SPR 69673
  29. 03f,13jul01,ann  eliminating the mibStyle variable and accomodating the
  30.                  END_MIB_2233 flag in the END flags field
  31. 03e,15jun01,rcs  set dec21x40Start() taskDelay to sysClkRateGet() / 30
  32. 03d,29mar01,spm  merged changes from version 02h of tor2_0.open_stack
  33.                  branch (wpwr VOB, base 02d) for unified code base
  34. 03c,23feb01,rcs  increased taskDelay to 2 in dec21x40Start() to ensure adequate
  35.                  time for the software reset of the dec21x40 device to complete.
  36.                  SPR# 64192
  37. 03b,14feb01,rcs  moved intConnect to before the chip's interupts are enabled
  38.                  SPR# 31314.
  39. 03a,13feb01,rcs  saved and restored CSR0 before and after software reset in 
  40.                  dec21x40Start() SPR# 64192
  41. 02z,08feb01,rcs  moved decode non-register user flags to before 
  42.                  dec21x40EnetAddrGet() call. SPR# 63881   
  43. 02y,14dec00,rcs  removed reference to sysDelay()
  44. 02x,15nov00,jpd  added _func_dec2114xIntAck (SPR #62330).
  45. 02w,25oct00,dat  SPR 34891 removing PHYS_TO_VIRT translations
  46. 02v,20sep00,dat  SPR 32058, allow for alternate intConnect rtn
  47. 02u,17jul00,bri  Standardisation
  48. 02t,17apr00,an   Added support to force HomePNA speed and power via user flags.
  49. 02s,13apr00,an   Added support for special dec21145 media change technique.
  50.                  The driver must be called with DEC_USR_HPNA_PREFER_10BT 
  51.  user flag set to select this mode. This is NOT the default 
  52.  mode of operation.
  53. 02r,18feb00,an   Added support for dec21145. See explaination below.
  54. 02q,11jun00,ham  removed reference to etherLib.
  55. 02p,08may00,jgn  SPR 31198, Various fixes for use on ARM + Kingston KNE100TX 
  56.                  (MII) card
  57. 02o,24apr00,dmw  Fixed extended format block type 2 selection.
  58. 02n,24apr00,dmw  Added Full Duplex support for adapters with PHY's.
  59. 02m,24mar00,dat  fixed string handling, added fix to reset code
  60. 02l,01mar00,stv  fixed backward compatibility issues for the alignment fix.Also
  61.                  corrected documentation & updated a debug message. 
  62. 02k,24feb00,stv  made a selective merge to add alignment fix.
  63. 02j,27jan00,dat  fixed use of NULL
  64. 02i,08nov99,cn   integrated with miiLib. Also fixed SPR #21116, #28315.
  65. 02h,01oct99,pfl  Fix for spr 22196 was missing, added it again.
  66. 02g,16sep99,stv  Fixed errors due to usage of DRV_LOG macro.
  67. 02f,01sep99,dat  SPR 28573 and Debug clean up.
  68. 02e,17aug99,dmw  Added MII/Phy force modes.
  69. 02d,11mar99,tm   Added MII/Phy r/w for 2114x link status check (SPR 22196)
  70. 02c,02mar99,tm   txRingClean in ISR to improve small pkt throughput (SPR 23950)
  71. 02b,01feb99,scb  Added support for dec21143. (SPR 22887)
  72. 02a,30sep98,dbt  Adding missing code in poll receive routine.
  73. 01z,22sep98,dat  SPR 22325, system mode transition + lint fixes.
  74. 01y,07aug98,cn   updated documentation about user flags.
  75. 01w,31jul98,cn   removed setting CSR6_FD in xxxMediaSelect [SPR# 21683].
  76.  Also moved some indeces setting in xxxStart [SPR#21557].
  77. 01v,20apr98,map  preserve CSR6_PS in xxxChipReset [SPR# 21013]
  78. 01u,10dec97,kbw  man page fiddlings
  79. 01t,08dec97,gnn  END code review fixes.
  80. 01s,20nov97,gnn  fixed spr#9555, configurable TDS and RDS.
  81. 01r,19oct97,vin  moved swapping of loaned buffer before END_RCV_RTN_CALL
  82. 01q,17oct97,vin  removed extra free.
  83. 01p,09oct97,vin  delete unwanted frees in PollSend routine
  84. 01o,07oct97,vin  fixed multicasting, MIB MTU size to ETHER_MTU
  85. 01n,25sep97,gnn  SENS beta feedback fixes
  86. 01m,24sep97,vin  added clBlk related calls
  87. 01l,02sep97,gnn  fixed a race condition in the txRestart handling.
  88. 01k,25aug97,vin  adjusted cluster mem size.
  89. 01j,22aug97,vin  fixed initialization of cluster mem area.
  90. 01i,22aug97,gnn  fixed a bug in polled mode.
  91. 01h,21aug97,vin  added changes for newBuffering API
  92. 01g,12aug97,gnn  changes necessitated by MUX/END update.
  93. 01f,08aug97,map  fixed muxBufInit for user-specified bufpool.
  94.                  added ilevel arg to sysLanIntDisable().
  95.                  update collision statistics.
  96.                  added more flags to userFlags.
  97. 01e,10jun97,map  renamed funcDec21x40MediaSelect to _func_dec21x40MediaSelect.
  98. 01d,28may97,kbw  general text edit
  99.             map  added DEC SROM support for media configuration.
  100. 01c,23apr97,map  cleaned up; replaced SWAP_SHORT with PCISWAP_SHORT.
  101. 01b,16apr97,map  added support for dec21140.
  102. 01a,07apr97,map  modified if_dc.c to END style.
  103. */
  104. /*
  105. This module implements a DEC 21x40 PCI Ethernet network interface driver and
  106. supports both the 21040, 21140, 21143, 21145 versions of the chip.
  107. The DEC 21x40 PCI Ethernet controller is little endian because it interfaces
  108. with a little-endian PCI bus.  Although PCI configuration for a device is
  109. handled in the BSP, all other device programming and initialization needs 
  110. are handled in this module.
  111. This driver is designed to be moderately generic. Without modification, it can
  112. operate across the full range of architectures and targets supported by VxWorks.
  113. To achieve this, the driver requires a few external support routines as well
  114. as several target-specific parameters.  These parameters, and the mechanisms
  115. used to communicate them to the driver, are detailed below.  If any of the
  116. assumptions stated below are not true for your particular hardware, you need
  117. to modify the driver before it can operate correctly on your hardware.
  118. On the 21040, the driver configures the 10BASE-T interface by default,waits for
  119. two seconds, and checks the status of the link. If the link status indicates
  120. failure, AUI interface is configured.
  121. On other versions of the 21x40 family, the driver reads media information from
  122. a DEC serial ROM and configures the media.  To configure the media on targets 
  123. that do not support a DEC format serial ROM, the driver calls the 
  124. target-specific media-select routine referenced in
  125. the `_func_dec21x40MediaSelect' hook. 
  126. The 21145 supports HomePNA 1.0 (Home Phone Line) Networking as well as 
  127. 10Base-T. The HomePNA port can be forced to 1 MB/sec or 0.7 MB/sec mode
  128. via the DEC_USR_HPNA_FORCE_FAST and DEC_USR_HPNA_FORCE_SLOW user flags,
  129. respectively. If these flags are not set then the speed is set using
  130. the SROM settings.
  131. Unlike the Ethernet phys, the HomePNA phy can not determine link failure and
  132. therefore will never notify the driver when the HomePNA port is 
  133. disconnected. However, to allow media change, the driver can be configured 
  134. to ALWAYS perfer 10Base-T over HomePNA by interrupting on 10Base-T link pass 
  135. interrupt. Upon 10Base-T link failure, the driver will revert back to HomePNA.
  136. Since this method violates the preference rules outlined in Intel/DEC SROM 
  137. format spec, this is not the default mode of operation. 
  138. The driver must be started with DEC_USR_HPNA_PREFER_10BT user flag set to 
  139. set the driver into this mode.
  140. The driver supports big-endian or little-endian architectures (as a 
  141. configurable option).  The driver also and contains error recovery code 
  142. that handles known device errata related to DMA activity.
  143. Big-endian processors can be connected to the PCI bus through some controllers
  144. that take care of hardware byte swapping. In such cases, all the registers
  145. which the chip DMAs to have to be swapped and written to, so that when the
  146. hardware swaps the accesses, the chip would see them correctly. The chip still
  147. has to be programmed to operate in little endian mode as it is on the PCI
  148. bus.  If the cpu board hardware automatically swaps all the accesses to and
  149. from the PCI bus, then input and output byte stream need not be swapped.
  150. BOARD LAYOUT
  151. This device is on-board.  No jumpering diagram is necessary.
  152. EXTERNAL INTERFACE
  153. The driver provides one standard external interface, dec21x40EndLoad().  As 
  154. input, this function expects a string of colon-separated parameters. The 
  155. parameters should be specified as hexadecimal strings (optionally preceded 
  156. by "0x" or a minus sign "-").  Although the parameter string is parsed 
  157. using endTok_r(), each parameter is converted from string to binary by a 
  158. call to:
  159. .CS
  160.     strtoul(parameter, NULL, 16).
  161. .CE
  162. The format of the parameter string is:
  163.  "<deviceAddr>:<pciAddr>:<iVec>:<iLevel>:<numRds>:<numTds>:
  164. <memBase>:<memSize>:<userFlags>:<phyAddr>:<pPhyTbl>:<phyFlags>:<offset>:
  165. <loanBufs>:<drvFlags>"
  166. TARGET-SPECIFIC PARAMETERS
  167. .IP <deviceAddr>
  168. This is the base address at which the hardware device registers are located.
  169. .IP <pciAddr>
  170. This parameter defines the main memory address over the PCI bus. It is used to
  171. translate a physical memory address into a PCI-accessible address.
  172. .IP <iVec>
  173. This is the interrupt vector number of the hardware interrupt generated by
  174. this Ethernet device.  The driver uses intConnect() to attach an interrupt
  175. handler for this interrupt. The BSP can change this by modifying the global
  176. pointer dec21x40IntConnectRtn with the desired routines (usually pciIntConnect).
  177. .IP <iLevel>
  178. This parameter defines the level of the hardware interrupt.
  179. .IP <numRds>
  180. The number of receive descriptors to use.  This controls how much data
  181. the device can absorb under load.  If this is specified as NONE (-1), 
  182. the default of 32 is used.
  183. .IP <numTds>
  184. The number of transmit descriptors to use.  This controls how much data
  185. the device can absorb under load.  If this is specified as NONE (-1) then
  186. the default of 64 is used.
  187. .IP <memBase>
  188. This parameter specifies the base address of a DMA-able cache-free
  189. pre-allocated memory region for use as a memory pool for transmit/receive
  190. descriptors and buffers including loaner buffers.  If there is no pre-allocated
  191. memory available for the driver, this parameter should be -1 (NONE). In which 
  192. case, the driver allocates cache safe memory for its use using cacheDmaAlloc().
  193. .IP <memSize>
  194. The memory size parameter specifies the size of the pre-allocated memory
  195. region. If memory base is specified as NONE (-1), the driver ignores this
  196. parameter.  When specified this value must account for transmit/receive
  197. descriptors and buffers and loaner buffers 
  198. .IP <userFlags>
  199. User flags control the run-time characteristics of the Ethernet
  200. chip.  Most flags specify non default CSR0 and CSR6 bit values. Refer to
  201. dec21x40End.h for the bit values of the flags and to the device hardware
  202. reference manual for details about device capabilities, CSR6 and CSR0.
  203. .IP <phyAddr>
  204. This optional parameter specifies the address on the MII (Media Independent
  205. Interface) bus of a MII-compliant PHY (Physical Layer Entity). The module 
  206. that is responsible for optimally configuring the media layer will start 
  207. scanning the MII bus from the address in <phyAddr>. It will retrieve the 
  208. PHY's address regardless of that, but, since the MII management interface, 
  209. through which the PHY is configured, is a very slow one, providing an 
  210. incorrect or invalid address may result in a particularly long boot process.
  211. If the flag <DEC_USR_MII> is not set, this parameter is ignored.
  212. .IP <pPhyTbl>
  213. This optional parameter specifies the address of a auto-negotiation table
  214. for the PHY being used. 
  215. The user only needs to provide a valid value for this parameter
  216. if he wants to affect the order how different technology abilities are 
  217. negotiated.
  218. If the flag <DEC_USR_MII> is not set, this parameter is ignored.
  219. .IP <phyFlags>
  220. This optional parameter allows the user to affect the PHY's configuration
  221. and behaviour. See below, for an explanation of each MII flag.
  222. If the flag <DEC_USR_MII> is not set, this parameter is ignored.
  223. .IP <offset>
  224. This parameter defines the offset which is used to solve alignment problem.
  225. .IP <loanBufs>
  226. This optional parameter allows the user to select the amount of loaner buffers
  227. allocated for the driver's net pool to be loaned to the stack in receive 
  228. operations.  The default number of loaner buffers is 32. The number of loaner
  229. buffers must be accounted for when calculating the memory size specified by
  230. memSize. 
  231. .IP <drvFlags>
  232. This optional parameter allows the user to enable driver-specific features.
  233. Device Type: Although the default device type is DEC 21040, specifying 
  234. the DEC_USR_21140 flag bit turns on DEC 21140 functionality.
  235. Ethernet Address: The Ethernet address is retrieved from standard serial 
  236. ROM on both DEC 21040, and DEC 21140 devices. If the retrieve from ROM fails, 
  237. the driver calls the sysDec21x40EnetAddrGet() BSP routine. 
  238. Specifying DEC_USR_XEA flag bit tells the driver should, by default, 
  239. retrieve the Ethernet address using the sysDec21x40EnetAddrGet() BSP routine.
  240. Priority RX processing: The driver programs the chip to process the 
  241. transmit and receive queues at the same priority. By specifying DEC_USR_BAR_RX,
  242. the device is programmed to process receives at a higher priority.
  243. TX poll rate: By default, the driver sets the Ethernet chip into a 
  244. non-polling mode. In this mode, if the transmit engine is idle, it is 
  245. kick-started every time a packet needs to be transmitted.  Alternatively, 
  246. the chip can be programmed to poll for the next available transmit 
  247. descriptor if the transmit engine is in idle state. The poll rate is 
  248. specified by one of DEC_USR_TAP_<xxx> flags.
  249. Cache Alignment: The DEC_USR_CAL_<xxx> flags specify the address 
  250. boundaries for data burst transfers.
  251. DMA burst length: The DEC_USR_PBL_<xxx> flags specify the maximum 
  252. number of long words in a DMA burst.
  253. PCI multiple read: The DEC_USR_RML flag specifies that a device 
  254. supports PCI memory-read-multiple.
  255. Full Duplex Mode: When set, the DEC_USR_FD flag allows the device to 
  256. work in full duplex mode, as long as the PHY used has this
  257. capability. It is worth noting here that in this operation mode, 
  258. the dec21x40 chip ignores the Collision and the Carrier Sense signals.
  259. MII interface: some boards feature an MII-compliant Physical Layer Entity
  260. (PHY). In this case, and if the flag <DEC_USR_MII> is set, then the optional
  261. fields <phyAddr>, <pPhyTbl>, and <phyFlags> may be used to affect the
  262. PHY's configuration on the network. 
  263. 10Base-T Mode: when the flag <DEC_USR_MII_10MB> is set, then the PHY will
  264. negotiate this technology ability, if present.
  265. 100Base-T Mode: when the flag <DEC_USR_MII_100MB> is set, then the PHY will
  266. negotiate this technology ability, if present.
  267. Half duplex Mode: when the flag <DEC_USR_MII_HD> is set, then the PHY will
  268. negotiate this technology ability, if present.
  269. Full duplex Mode: when the flag <DEC_USR_MII_FD> is set, then the PHY will
  270. negotiate this technology ability, if present.
  271. Auto-negotiation: the driver's default behaviour is to enable auto-negotiation,
  272. as defined in "IEEE 802.3u Standard". However, the user may disable this
  273. feature by setting the flag <DEC_USR_MII_NO_AN> in the <phyFlags> field of
  274. the load string.
  275. Auto-negotiation table: the driver's default behaviour is to enable the
  276. standard auto-negotiation process, as defined in "IEEE 802.3u Standard". 
  277. However, the user may wish to force the PHY to negotiate its technology
  278. abilities a subset at a time, and according to a particular order. The
  279. flag <DEC_USR_MII_AN_TBL> in the <phyFlags> field may be used to tell the
  280. driver that the PHY should negotiate its abilities as dictated by the
  281. entries in the <pPhyTbl> of the load string.
  282. If the flag <DEC_USR_MII_NO_AN> is set, this parameter is ignored.
  283. Link monitoring: this feature enables the netTask to periodically monitor
  284. the PHY's link status for link down events. If any such event occurs, and
  285. if the flag <DEC_USR_MII_BUS_MON> is set, then a driver's optionally provided
  286. routine is executed, and the link is renegotiated.
  287. Transmit treshold value: The DEC_USR_THR_XXX flags enable the user to 
  288. choose among different threshold values for the transmit FIFO. 
  289. Transmission starts when the frame size within the transmit FIFO is 
  290. larger than the treshold value. This should be selected taking into 
  291. account the actual operating speed of the PHY.  Again, see the device 
  292. hardware reference manual for details.
  293. EXTERNAL SUPPORT REQUIREMENTS
  294. This driver requires three external support functions and provides a hook
  295. function:
  296. .IP sysLanIntEnable()
  297. .CS
  298.     void sysLanIntEnable (int level)
  299. .CE
  300. This routine provides a target-specific interface for enabling Ethernet device
  301. interrupts at a specified interrupt level.
  302. .IP sysLanIntDisable()
  303. .CS
  304.     void sysLanIntDisable (void)
  305. .CE
  306. This routine provides a target-specific interface for disabling Ethernet device
  307. interrupts.
  308. .IP sysDec21x40EnetAddrGet()
  309. .CS
  310.     STATUS sysDec21x40EnetAddrGet (int unit, char *enetAdrs)
  311. .CE
  312. This routine provides a target-specific interface for accessing a device
  313. Ethernet address.
  314. .IP `_func_dec21x40MediaSelect'
  315. .CS
  316.     FUNCPTR _func_dec21x40MediaSelect
  317. .CE
  318. If `_func_dec21x40MediaSelect' is NULL, this driver provides a default 
  319. media-select routine that reads and sets up physical media using the 
  320. configuration information from a Version 3 DEC Serial ROM. Any other media
  321. configuration can be supported by initializing `_func_dec21x40MediaSelect',
  322. typically in sysHwInit(), to a target-specific media select routine.
  323. A media select routine is typically defined as:
  324. .ne 8
  325. .CS
  326.    STATUS decMediaSelect
  327.        (
  328.        DEC21X40_DRV_CTRL * pDrvCtrl,   /@ driver control @/
  329.        UINT * pCsr6Val    /@ CSR6 return value @/
  330.        )
  331.        {
  332.            ...
  333.        }
  334. .CE
  335. The <pDrvCtrl> parameter is a pointer to the driver control structure that this
  336. routine can use to access the Ethenet device. The driver control structure
  337. member 'mediaCount', is initialized to 0xff at startup, while the other media
  338. control members ('mediaDefault', 'mediaCurrent', and 'gprModeVal') are 
  339. initialized to zero. This routine can use these fields in any manner. 
  340. However, all other driver control structure members should be considered 
  341. read-only and should not be modified.
  342. This routine should reset, initialize, and select an appropriate media.  It
  343. should also write necessary the CSR6 bits (port select, PCS, SCR, and full 
  344. duplex) to the memory location pointed to by <pCsr6Val>. The driver uses 
  345. this value to program register CSR6. This routine should return OK or ERROR.
  346. .iP "VOIDFUNCPTR _func_dec2114xIntAck" "" 9 -1
  347. This driver does acknowledge the LAN interrupts. However if the board hardware
  348. requires specific interrupt acknowledgement, not provided by this driver,
  349. the BSP should define such a routine and attach it to the driver via
  350. _func_dec2114xIntAck.
  351. PCI ID VALUES
  352. The dec21xxx series chips are now owned and manufactured by Intel.  Chips may
  353. be identified by either PCI Vendor ID.  ID value 0x1011 for Digital, or
  354. ID value 0x8086 for Intel.  Check the Intel web site for latest information.
  355. The information listed below may be out of date.
  356. .CS
  357.     Chip         Vendor ID      Device ID
  358.     dec 21040      0x1011        0x0002
  359.     dec 21041      0x1011        0x0014
  360.     dec 21140      0x1011        0x0009
  361.     dec 21143      0x1011        0x0019
  362.     dec 21145      0x8086        0x0039
  363. .CE
  364. SEE ALSO: ifLib, 
  365. .I "DECchip 21040 Ethernet LAN Controller for PCI,"
  366. .I "Digital Semiconductor 21140A PCI Fast Ethernet LAN Controller,"
  367. .I "Using the Digital Semiconductor 21140A with Boot ROM, Serial ROM, 
  368. and External Register: An Application Note"
  369. .I "Intel 21145 Phoneline/Ethernet LAN Controller Hardware Ref. Manual"
  370. .I "Intel 21145 Phoneline/Ethernet LAN Controller Specification Update"
  371. INTERNAL
  372. We modified the driver to use rDesc3 to hold the virtual address of the buffer.
  373. This allows us to eliminate all PHYS_TO_VIRT translations that were previously
  374. used.  PHYS_TO_VIRT translations are extremely costly in T3.0.
  375. */
  376. /* includes */
  377. #include "vxWorks.h"
  378. #include "wdLib.h"
  379. #include "iv.h"
  380. #include "vme.h"
  381. #include "net/mbuf.h"
  382. #include "net/unixLib.h"
  383. #include "net/protosw.h"
  384. #include "sys/socket.h"
  385. #include "sys/ioctl.h"
  386. #include "errno.h"
  387. #include "memLib.h"
  388. #include "intLib.h"
  389. #include "net/route.h"
  390. #include "errnoLib.h"
  391. #include "cacheLib.h"
  392. #include "logLib.h"
  393. #include "netLib.h"
  394. #include "stdio.h"
  395. #include "stdlib.h"
  396. #include "sysLib.h"
  397. #include "net/systm.h"
  398. #include "sys/times.h"
  399. #include "net/if_subr.h"
  400. #include "netinet/if_ether.h"
  401. #include "miiLib.h"
  402. #include "drv/end/dec21x40End.h"
  403. #undef ETHER_MAP_IP_MULTICAST
  404. #include "etherMultiLib.h"
  405. #include "end.h"
  406. #include "endLib.h"
  407. #include "lstLib.h"
  408. #include "semLib.h"
  409. /* defines */
  410. #define DRV_DEBUG_OFF 0x0000
  411. #define DRV_DEBUG_RX 0x0001
  412. #define DRV_DEBUG_TX 0x0002
  413. #define DRV_DEBUG_INT 0x0004
  414. #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
  415. #define DRV_DEBUG_POLL_RX 0x0008
  416. #define DRV_DEBUG_POLL_TX 0x0010
  417. #define DRV_DEBUG_IOCTL 0x0040
  418. #define DRV_DEBUG_LOAD 0x0020
  419. #define DRV_DEBUG_INIT 0x0100
  420. #define DRV_DEBUG_MII 0x0080
  421. #define DRV_DEBUG_POLL_REDIR 0x10000
  422. #define DRV_DEBUG_LOG_NVRAM 0x20000
  423. #define DRV_DEBUG_ALL 0xffffffff 
  424. #undef  DRV_DEBUG
  425. #ifdef DRV_DEBUG
  426. int     decTxInts=0;
  427. int     decRxInts=0;
  428. int decTxErrors = 0;
  429. int decRxErrors = 0;
  430. int decTxTpsErrors = 0;
  431. int decTxBufErrors = 0;
  432. int decTxTjtErrors = 0;
  433. int decTxUnfErrors = 0;
  434. int decTxLcErrors = 0;
  435. int decRxBufErrors = 0;
  436. int decRxRpsErrors = 0;
  437. int decRxWtErrors = 0;
  438. int decDescErrors = 0;
  439. IMPORT int dataDump();
  440. IMPORT int eAdrsDisplay();
  441. #endif /*DRV_DEBUG*/
  442. /* default to enable DRV_DEBUG_LOAD to display initialization errors. */
  443. int decDebug = DRV_DEBUG_INIT;
  444. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)                        
  445. if (decDebug & FLG)                                             
  446.             logMsg(X0, X1, X2, X3, X4, X5, X6);
  447. #define END_FLAGS_ISSET(pEnd, setBits)                                  
  448.             ((pEnd)->flags & (setBits))
  449.  
  450. #ifdef INCLUDE_RFC_1213
  451. /* Old RFC 1213 mib2 interface */
  452. #define END_HADDR(pEnd)                                                 
  453.                 ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  454. #define END_HADDR_LEN(pEnd)                                             
  455.                 ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  456. #else  /* Then RFC 2233 */
  457. /* New RFC 2233  mib2 interface */
  458. #define END_HADDR(pEnd)                                                 
  459.                 ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.phyAddress)
  460. #define END_HADDR_LEN(pEnd)                                             
  461.                 ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.addrLength)
  462. #endif /* INCLUDE_RFC_1213 */
  463. #define DEC_SPEED_1 1000000              /* 1 Mbps HomePNA */
  464. #define DEC_SPEED_10 10000000             /* 10 Mbps */
  465. #define DEC_SPEED_100 100000000            /* 100 Mbps */
  466. #define DEC_SPEED_DEF DEC_SPEED_10
  467. #define EADDR_LEN 6                    /* ethernet address length */
  468. #define DEC_PKT_SIZE (ETHERMTU + SIZEOF_ETHERHEADER + EADDR_LEN)
  469. #define DEC_LOOPS_PER_NS 4
  470. #define DEC_NSDELAY(nsec) do {
  471. volatile int nx = 0;                            
  472. volatile int loop = ((nsec)*dec21x40Loops);
  473. for (nx = 0; nx < loop; nx++)
  474. ;                  
  475. } while (0)
  476. #define DEC_BUF_ALLOC_ROUTINE                                           
  477. (FUNCPTR) (DRV_FLAGS_ISSET(DEC_MEMOWN) ?                        
  478.                    cacheDmaMalloc : NULL)
  479. #define DEC_BUF_POOL_ADRS                                               
  480. (char *)(DRV_FLAGS_ISSET(DEC_MEMOWN) ?                          
  481.                   NULL:(pDrvCtrl->txRing + pDrvCtrl->numTds))
  482. /* DRV_CTRL flags access macros */
  483. #define DRV_FLAGS_SET(setBits)                                          
  484. (pDrvCtrl->flags |= (setBits))
  485. #define DRV_FLAGS_ISSET(setBits)                                        
  486. (pDrvCtrl->flags & (setBits))
  487. #define DRV_FLAGS_CLR(clrBits)                                          
  488. (pDrvCtrl->flags &= ~(clrBits))
  489. #define DRV_FLAGS_GET()                                                 
  490.         (pDrvCtrl->flags)
  491. /* DRV_CTRL user flags access macros */
  492. #define DRV_USR_FLAGS_SET(setBits)                                      
  493. (pDrvCtrl->usrFlags |= (setBits))
  494. #define DRV_USR_FLAGS_ISSET(setBits)                                    
  495. (pDrvCtrl->usrFlags & (setBits))
  496. #define DRV_USR_FLAGS_CLR(clrBits)                                      
  497. (pDrvCtrl->usrFlags &= ~(clrBits))
  498. #define DRV_USR_FLAGS_GET()                                             
  499.         (pDrvCtrl->usrFlags)
  500. #define DRV_PHY_FLAGS_ISSET(setBits)                                    
  501. (pDrvCtrl->miiPhyFlags & (setBits))
  502. /* Cache macros */
  503. #define DEC_CACHE_INVALIDATE(address, len)                              
  504.         CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
  505. #define DEC_CACHE_VIRT_TO_PHYS(address)                                 
  506.         CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
  507. #define DEC_CACHE_PHYS_TO_VIRT(address)                                 
  508.         CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
  509. /* memory to PCI address translation macros */
  510. #define PCI_TO_MEM_PHYS(pciAdrs)                                        
  511. (((ULONG)(pciAdrs)) - (pDrvCtrl->pciMemBase))
  512. #define DEC_PCI_TO_VIRT(pciAdrs)                                        
  513.         DEC_CACHE_PHYS_TO_VIRT (PCI_TO_MEM_PHYS (pciAdrs))
  514. #define MEM_TO_PCI_PHYS(memAdrs)                                        
  515. (((ULONG)(memAdrs)) + (pDrvCtrl->pciMemBase))
  516. #define DEC_VIRT_TO_PCI(vAdrs)                                          
  517. MEM_TO_PCI_PHYS (DEC_CACHE_VIRT_TO_PHYS (vAdrs))
  518. #ifndef TCP_MSS
  519. #define TCP_MSS 536 /* TCP maximum segment size */
  520. #endif
  521. #define RWIN (TCP_MSS * 4) /* Receive window size */
  522. /*
  523.  * CSR access macros
  524.  *
  525.  * To optimize CSR accesses, redefine DEC_CSR_READ and
  526.  * DEC_CSR_WRITE macros in a wrapper file.
  527.  */
  528. #ifndef DEC_CSR_READ
  529. #define DEC_CSR_READ(csr)                                               
  530. dec21x40CsrRead(pDrvCtrl, (csr))
  531. #endif /* DEC_CSR_READ */
  532. #ifndef DEC_CSR_WRITE
  533. #define DEC_CSR_WRITE(csr,val)                                          
  534. dec21x40CsrWrite(pDrvCtrl, (csr), (val))
  535. #endif /* DEC_CSR_WRITE */
  536. #define DEC_CSR_UPDATE(csr,val)                                         
  537. DEC_CSR_WRITE((csr), DEC_CSR_READ(csr) | (val))
  538.     
  539. #define DEC_CSR_RESET(csr,val)                                          
  540. DEC_CSR_WRITE((csr), DEC_CSR_READ(csr) & ~(val))
  541.     
  542. #define DEC_SROM_CMD_WRITE(adrs,delay)                                  
  543. do {                                                               
  544.         DEC_CSR_WRITE(CSR9, CSR9_21140_SR | CSR9_21140_WR | (adrs));    
  545.         DEC_NSDELAY (delay);
  546.         } while (0)
  547. #define DEC_SROM_CMD_READ()                                             
  548. ((DEC_CSR_READ(CSR9) & 0x8) >> 3)
  549. /* MII read/write access macros */
  550.    
  551. #define CSR9_MII_WR 0x00000000
  552. #define DEC_MII_BIT_READ(pBData)                                        
  553.         do {                                                               
  554.         DEC_CSR_WRITE (CSR9, CSR9_21140_MII | CSR9_21140_RD);           
  555.         DEC_NSDELAY (100);
  556.         DEC_CSR_WRITE (CSR9, CSR9_21140_MII | CSR9_21140_RD | CSR9_21140_MDC);
  557.         DEC_NSDELAY (100);
  558.         *(pBData) |= CSR9_MII_DBIT_RD (DEC_CSR_READ (CSR9));
  559.         } while (0)
  560. #define DEC_MII_BIT_WRITE(data)                                      
  561.         do {                                                            
  562.         DEC_CSR_WRITE (CSR9, CSR9_MII_DBIT_WR(data) |                
  563.                       CSR9_MII_WR | CSR9_21140_WR);                  
  564.         DEC_NSDELAY (100);                                           
  565.         DEC_CSR_WRITE (CSR9, CSR9_MII_DBIT_WR(data) |                
  566.                       CSR9_MII_WR | CSR9_21140_WR | CSR9_21140_MDC); 
  567.         DEC_NSDELAY (100);                                           
  568.         } while (0)
  569. #define DEC_MII_RTRISTATE           
  570.         do {                        
  571.         int retVal;                 
  572.         DEC_MII_BIT_READ (&retVal); 
  573.         } while (0)
  574. #define DEC_MII_WTRISTATE           
  575.         do {                        
  576.         DEC_MII_BIT_WRITE(0x1);     
  577.         DEC_MII_BIT_WRITE(0x0);     
  578.         } while (0)
  579. #define DEC_MII_WRITE(data, bitCount)                
  580.         do {                                         
  581.         int i=(bitCount);                            
  582.                                                      
  583.         while (i--)                                  
  584.             DEC_MII_BIT_WRITE (((data) >> i) & 0x1); 
  585.         } while (0)
  586. #define DEC_MII_READ(pData, bitCount) 
  587.         do {                          
  588.         int i=(bitCount);             
  589.                                       
  590.         while (i--)                   
  591.             {                         
  592.             *(pData) <<= 1;           
  593.             DEC_MII_BIT_READ (pData); 
  594.             }                         
  595.         } while (0)
  596. /*
  597.  * Default macro definitions for BSP interface.
  598.  * These macros can be redefined in a wrapper file, to generate
  599.  * a new module with an optimized interface.
  600.  */
  601. #ifndef SYS_INT_CONNECT
  602. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)                       
  603.     do {                                                                
  604.     int vector = pDrvCtrl->ivec;                                        
  605.     if (!pDrvCtrl->intrConnect)                                         
  606.         {                                                               
  607.         pDrvCtrl->intrConnect = TRUE;                                   
  608.        *pResult = (*dec21x40IntConnectRtn) (                            
  609.                                (VOIDFUNCPTR *)INUM_TO_IVEC (vector),    
  610.                                 (rtn), (int)(arg));                     
  611.         }                                                               
  612.     } while (0)
  613. #endif /*SYS_INT_CONNECT*/
  614.  
  615. #ifndef SYS_INT_DISCONNECT
  616. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)                    
  617.     do {                                                                
  618.     /* set pDrvCtrl->intrConnect to FALSE if appropriate */             
  619.     *pResult = OK;
  620.     } while (0)
  621. #endif /*SYS_INT_DISCONNECT*/
  622. #ifndef SYS_INT_ENABLE
  623. #define SYS_INT_ENABLE(pDrvCtrl)                                        
  624.     do {                                                                
  625.     IMPORT void sysLanIntEnable();                                      
  626.     sysLanIntEnable (pDrvCtrl->ilevel);                                 
  627.     } while (0)
  628. #endif /*SYS_INT_ENABLE*/
  629. #ifndef SYS_INT_DISABLE
  630. #define SYS_INT_DISABLE(pDrvCtrl)                                       
  631.     do {                                                                
  632.     IMPORT void sysLanIntDisable();                                     
  633.     sysLanIntDisable (pDrvCtrl->ilevel);                                
  634.     } while (0)
  635. #endif /*SYS_INT_DISABLE*/
  636. #define END_MIB_SPEED_SET(pEndObj, speed)                               
  637. ((pEndObj)->mib2Tbl.ifSpeed=speed)
  638. #define NET_BUF_ALLOC()                                                 
  639.     netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->clPoolId)
  640. #define NET_BUF_FREE(pBuf)                                              
  641.     netClFree (pDrvCtrl->endObj.pNetPool, pBuf)
  642. #define NET_MBLK_ALLOC()                                                
  643.     mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)
  644. #define NET_MBLK_FREE(pMblk)                                            
  645.     netMblkFree (pDrvCtrl->endObj.pNetPool, (M_BLK_ID)pMblk)
  646. #define NET_CL_BLK_ALLOC()                                              
  647.     clBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)
  648. #define NET_CL_BLK_FREE(pClblk)                                         
  649.     clBlkFree (pDrvCtrl->endObj.pNetPool, (CL_BLK_ID)pClBlk)
  650.             
  651. #define NET_MBLK_BUF_FREE(pMblk)                                        
  652.     netMblkClFree ((M_BLK_ID)pMblk)
  653. #define NET_MBLK_CHAIN_FREE(pMblk)                                      
  654.     do {                                                                
  655.     M_BLK *pNext;                                                       
  656.                                                                         
  657.     pNext=pMblk;                                                        
  658.     while (pNext)                                                       
  659.         pNext=NET_MBLK_BUF_FREE (pNext);                                
  660.     } while (0)
  661.     
  662. #define NET_MBLK_CL_JOIN(pMblk, pClBlk)                              
  663.     netMblkClJoin ((pMblk), (pClBlk))
  664. #define NET_CL_BLK_JOIN(pClBlk, pBuf, len)                             
  665.     netClBlkJoin ((pClBlk), (pBuf), (len), NULL, 0, 0, 0)
  666.         
  667. #define DRV_CTRL DEC21X40_DRV_CTRL
  668. /* structure sizes */
  669. #define DRV_CTRL_SIZ sizeof(DRV_CTRL)
  670. #define RD_SIZ sizeof(DEC_RD)
  671. #define TD_SIZ sizeof(DEC_TD)
  672. /* locals */
  673. /* Default network buffer configuration */
  674. int dec21x40Loops = DEC_LOOPS_PER_NS; /* spin loops per nsec */
  675. FUNCPTR dec21x40IntConnectRtn = intConnect;
  676. /* constant data to set PHY control register */
  677. LOCAL const UINT dcForcePhyModes[] = 
  678.     {
  679.     MII_CR_100 | MII_CR_FDX, /* 100FD */
  680.     MII_CR_100, /* 100HD */
  681.     MII_CR_FDX, /* 10FD  */
  682.     0, /* 10HD  */
  683.     -1
  684.     } ;
  685. /* forward declarations */
  686. LOCAL STATUS dec21x40InitParse (DRV_CTRL *pDrvCtrl, char *InitString);
  687. LOCAL STATUS dec21x40InitMem (DRV_CTRL *pDrvCtrl);
  688. LOCAL STATUS dec21x40IASetup (DRV_CTRL *pDrvCtrl);
  689. LOCAL void  dec21x40ModeSet (DRV_CTRL *pDrvCtrl);
  690. LOCAL int dec21x40HashIndex (char *eAddr);
  691. LOCAL void  dec21x40Int (DRV_CTRL *pDrvCtrl);
  692. LOCAL STATUS  dec21x40Recv (DRV_CTRL *pDrvCtrl, DEC_RD *rmd);
  693. LOCAL STATUS  dec21x40ChipReset (DRV_CTRL *pDrvCtrl);
  694. LOCAL void dec21040AuiTpInit (DRV_CTRL *pDrvCtrl);
  695. LOCAL void  dec21x40CsrWrite (DRV_CTRL *pDrvCtrl, int reg, ULONG value);
  696. LOCAL ULONG  dec21x40CsrRead (DRV_CTRL *pDrvCtrl, int reg);
  697. LOCAL STATUS  dec21x40EnetAddrGet (DRV_CTRL *pDrvCtrl, char *enetAdrs);
  698. LOCAL STATUS  dec21040EnetAddrGet (DRV_CTRL *pDrvCtrl, char *enetAdrs);
  699. LOCAL STATUS  dec21140EnetAddrGet (DRV_CTRL *pDrvCtrl, char *enetAdrs);
  700. LOCAL void dec21x40Restart (DRV_CTRL *pDrvCtrl);
  701. LOCAL STATUS dec21x40MediaChange (DRV_CTRL *pDrvCtrl);
  702. LOCAL DEC_TD * dec21x40TxDGet (DRV_CTRL *pDrvCtrl);
  703. LOCAL DEC_RD * dec21x40RxDGet (DRV_CTRL *pDrvCtrl);
  704. LOCAL void  dec21x40TxRingClean (DRV_CTRL *pDrvCtrl);
  705. LOCAL void  dec21x40RxIntHandle (DRV_CTRL *pDrvCtrl);
  706. LOCAL STATUS  dec21140MediaSelect (DRV_CTRL *pDrvCtrl, UINT *pCsr6Val);
  707. LOCAL STATUS  dec21143MediaSelect (DRV_CTRL *pDrvCtrl, UINT *pCsr6Val);
  708. LOCAL STATUS dec21145DecodeExt7InfoBlock ( DRV_CTRL *pDrvCtrl,
  709.                                            UCHAR * pInfoBlock);
  710. LOCAL STATUS  dec21145MediaSelect (DRV_CTRL *pDrvCtrl, UINT *pCsr6Val);
  711. LOCAL STATUS  dec21x40PhyPreInit  (DRV_CTRL *pDrvCtrl, UCHAR * pInfoBlock);
  712. LOCAL STATUS  dec21x40MiiInit  (DRV_CTRL *pDrvCtrl, UINT *pCsr6Val,
  713.   UCHAR * pInfoBlock);
  714. LOCAL STATUS dec21x40MiiRead ( DRV_CTRL *pDrvCtrl, UINT8 phyAdrs, UINT8 phyReg,
  715.                               UINT16 *pRetVal);
  716. LOCAL STATUS dec21x40MiiWrite (DRV_CTRL *pDrvCtrl, UINT8 phyAdrs, UINT8 phyReg,
  717.                                USHORT data);
  718. /* externals */
  719. IMPORT STATUS sysDec21x40EnetAddrGet (int unit, char *enetAdrs);
  720. /* globals */
  721. USHORT dec21140SromWordRead (DRV_CTRL *pDrvCtrl, UCHAR lineCnt);
  722. FUNCPTR _func_dec21x40MediaSelect = (FUNCPTR) NULL;
  723. VOIDFUNCPTR _func_dec2114xIntAck = (VOIDFUNCPTR) NULL;
  724. #ifdef DRV_DEBUG
  725. #include "netShow.h"
  726. IMPORT void netPoolShow (NET_POOL_ID);
  727. void decCsrShow (int inst);
  728. void decShow (int inst);
  729. #endif /* DRV_DEBUG */
  730. /* END Specific interfaces. */
  731. END_OBJ * dec21x40EndLoad (char *initString);
  732. LOCAL STATUS dec21x40Unload (DRV_CTRL *pDrvCtrl);
  733. LOCAL STATUS dec21x40Start (DRV_CTRL *pDrvCtrl);
  734. LOCAL STATUS dec21x40Stop (DRV_CTRL *pDrvCtrl);
  735. LOCAL int dec21x40Ioctl (DRV_CTRL *pDrvCtrl, int cmd, caddr_t data);
  736. LOCAL STATUS dec21x40Send (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  737. LOCAL STATUS dec21x40MCastAddrAdd (DRV_CTRL *pDrvCtrl, char* pAddress);
  738. LOCAL STATUS dec21x40MCastAddrDel (DRV_CTRL *pDrvCtrl, char* pAddress);
  739. LOCAL STATUS dec21x40MCastAddrGet (DRV_CTRL *pDrvCtrl, 
  740.                                       MULTI_TABLE *pTable);
  741. LOCAL STATUS dec21x40PollSend (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  742. LOCAL STATUS dec21x40PollReceive (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
  743. LOCAL STATUS dec21x40PollStart (DRV_CTRL *pDrvCtrl);
  744. LOCAL STATUS dec21x40PollStop (DRV_CTRL *pDrvCtrl);
  745. /* 
  746.  * Define the device function table.  This is static across all driver
  747.  * instances.
  748.  */
  749. LOCAL NET_FUNCS netFuncs = 
  750.     {
  751.     (FUNCPTR)dec21x40Start, /* start func. */                 
  752.     (FUNCPTR)dec21x40Stop, /* stop func. */
  753.     (FUNCPTR)dec21x40Unload, /* unload func. */                
  754.     (FUNCPTR)dec21x40Ioctl, /* ioctl func. */                 
  755.     (FUNCPTR)dec21x40Send, /* send func. */                  
  756.     (FUNCPTR)dec21x40MCastAddrAdd,/* multicast add func. */         
  757.     (FUNCPTR)dec21x40MCastAddrDel,/* multicast delete func. */      
  758.     (FUNCPTR)dec21x40MCastAddrGet,/* multicast get fun. */          
  759.     (FUNCPTR)dec21x40PollSend, /* polling send func. */          
  760.     (FUNCPTR)dec21x40PollReceive, /* polling receive func. */       
  761.     endEtherAddressForm, /* put address info into a NET_BUFFER */
  762.     endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
  763.     endEtherPacketAddrGet /* Get packet addresses. */
  764.     };
  765. /******************************************************************************
  766. *
  767. * endTok_r - get a token string (modified version)
  768. *
  769. * This modified version can be used with optional parameters.  If the
  770. * parameter is not specified, this version returns NULL.  It does not
  771. * signify the end of the original string, but that the parameter is null.
  772. *
  773. * .CS
  774. *
  775. *    /@ required parameters @/
  776. *
  777. *    string = endTok_r (initString, ":", &pLast);
  778. *    if (string == NULL)
  779. *        return ERROR;
  780. *    reqParam1 = strtoul (string);
  781. *
  782. *    string = endTok_r (NULL, ":", &pLast);
  783. *    if (string == NULL)
  784. *        return ERROR;
  785. *    reqParam2 = strtoul (string);
  786. *
  787. *    /@ optional parameters @/
  788. *
  789. *    string = endTok_r (NULL, ":", &pLast);
  790. *    if (string != NULL)
  791. *        optParam1 = strtoul (string);
  792. *
  793. *    string = endTok_r (NULL, ":", &pLast);
  794. *    if (string != NULL)
  795. *        optParam2 = strtoul (string);
  796. * .CE
  797. */
  798.  
  799. char * endTok_r
  800.     (
  801.     char *       string,      /* string to break into tokens */
  802.     const char * separators,  /* the separators */
  803.     char **      ppLast               /* pointer to serve as string index */
  804.     )
  805.     {
  806.     if ((string == NULL) && ((string = *ppLast) == NULL))
  807.       return (NULL);
  808.     if ((*ppLast = strpbrk (string, separators)) != NULL)
  809.       *(*ppLast)++ = EOS;
  810.     /* Return NULL, if string is empty */
  811.     if (*string == EOS)
  812.       return NULL;
  813.     return (string);
  814.     }
  815. /***************************************************************************
  816. *
  817. * dec21x40EndLoad - initialize the driver and device
  818. *
  819. * This routine initializes the driver and the device to an operational state.
  820. * All of the device-specific parameters are passed in the <initStr>.
  821. * If this routine is called with an empty but allocated string, it puts the 
  822. * name of this device (that is, "dc") into the <initStr> and returns 0.
  823. * If the string is allocated but not empty, this routine tries to load
  824. * the device.
  825. *
  826. * RETURNS: An END object pointer or NULL on error.
  827. */
  828. END_OBJ* dec21x40EndLoad
  829.     (
  830.     char* initStr /* String to be parse by the driver. */
  831.     )
  832.     {
  833.     DRV_CTRL *pDrvCtrl;
  834.     char eAdrs[EADDR_LEN];            /* ethernet address */
  835.     if (initStr == NULL)
  836.         {
  837.         DRV_LOG (DRV_DEBUG_LOAD, "dec21x40EndLoad: NULL initStrrn",
  838.  0,0,0,0,0,0);
  839.         return (NULL);
  840.         }
  841.     
  842.     if (initStr[0] == '')
  843.         {
  844.         bcopy((char *)DRV_NAME, initStr, DRV_NAME_LEN);
  845.         return (0);
  846.         }
  847.     /* Allocate a control structure for this device */
  848.     pDrvCtrl = calloc (sizeof(DRV_CTRL), 1);
  849.     if (pDrvCtrl == NULL)
  850.         {
  851.         DRV_LOG (DRV_DEBUG_LOAD,"%s - Failed to allocate control structuren",
  852.                   (int)DRV_NAME, 0,0,0,0,0 ); 
  853.         return (NULL);
  854.         }
  855.     pDrvCtrl->flags = 0;
  856.     pDrvCtrl->intrConnect = FALSE;
  857.     pDrvCtrl->mediaCount = 0xff;
  858.     pDrvCtrl->homePNAPhyValuesFound = FALSE;
  859.     pDrvCtrl->offset = 0;
  860.     if (dec21x40InitParse (pDrvCtrl, initStr) == ERROR)
  861.         {
  862.         DRV_LOG  (DRV_DEBUG_INIT, "%s - Failed to parse initialization"
  863. "parametersn",
  864.         (int)DRV_NAME,0,0,0,0,0);
  865.         return (NULL);
  866.         }
  867.     if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ*)pDrvCtrl, DRV_NAME,
  868.                       pDrvCtrl->unit, &netFuncs,
  869.                       "dec21x40 Enhanced Network Driver") == ERROR)
  870.         {
  871.         DRV_LOG  (DRV_DEBUG_INIT, "%s%d - Failed to initialize END objectn",
  872.                   (int)DRV_NAME, pDrvCtrl->unit, 0,0,0,0);
  873.         return (NULL);
  874.         }
  875.     if (dec21x40InitMem (pDrvCtrl) == ERROR)
  876.         {
  877.         DRV_LOG (DRV_DEBUG_INIT, "dec21x40InitMem failed",0,0,0,0,0,0);
  878.         goto error;
  879.         }
  880.     /* decode non-register user flags */
  881.     if (pDrvCtrl->usrFlags & DEC_USR_XEA)
  882.         DRV_FLAGS_SET (DEC_BSP_EADRS);
  883.     switch (pDrvCtrl->usrFlags & DEC_USR_VER_MSK)
  884.         {
  885.         case DEC_USR_21143 :
  886.             DRV_FLAGS_SET (DEC_21143);
  887.             break;
  888.         case DEC_USR_21140 :
  889.             DRV_FLAGS_SET (DEC_21140);
  890.             break;
  891.         case DEC_USR_21145 :
  892.             DRV_FLAGS_SET (DEC_21145);
  893.             break;
  894.         default :
  895.             DRV_FLAGS_SET (DEC_21040);
  896.             break;
  897.         }
  898.     if (dec21x40EnetAddrGet (pDrvCtrl, eAdrs) == ERROR)
  899.         {
  900.         DRV_LOG  (DRV_DEBUG_INIT, "%s%d - Failed to read ethernet addressn",
  901.                   (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
  902.         goto error;
  903.         }
  904.     DRV_LOG (DRV_DEBUG_LOAD,
  905.              "ENET: %x:%x:%x:%x:%x:%xn",
  906.              eAdrs[0], eAdrs[1], eAdrs[2], eAdrs[3], eAdrs[4], eAdrs[5]);
  907. #ifdef INCLUDE_RFC_1213  
  908.     /* Old RFC 1213 mib2 interface */
  909.     /* Initialize MIB-II entries */
  910.     if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
  911.                       (UINT8*) eAdrs, 6,
  912.                        ETHERMTU, DEC_SPEED_DEF) == ERROR)
  913.         {
  914.         DRV_LOG  (DRV_DEBUG_INIT, "%s%d - MIB-II initializations failedn",
  915.                   (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
  916.         goto error;
  917.         }
  918.     /* Mark the device ready with default flags */
  919.     END_OBJ_READY (&pDrvCtrl->endObj, 
  920.                    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
  921.    
  922. #else 
  923.     /* New RFC 2233  mib2 interface */
  924.     /* Initialize MIB-II entries (for RFC 2233 ifXTable) */
  925.     pDrvCtrl->endObj.pMib2Tbl = m2IfAlloc(M2_ifType_ethernet_csmacd,
  926.                                           (UINT8*) eAdrs, 6,
  927.                                           ETHERMTU, DEC_SPEED_DEF,
  928.                                           DRV_NAME, pDrvCtrl->unit);
  929.     if (pDrvCtrl->endObj.pMib2Tbl == NULL)
  930.         {
  931.         printf ("%s%d - MIB-II initializations failedn",
  932.                 DRV_NAME, pDrvCtrl->unit);
  933.         goto error;
  934.         }
  935.     /*
  936.      * Set the RFC2233 flag bit in the END object flags field and
  937.      * install the counter update routines.
  938.      */
  939. #if defined(END_MIB_2233)
  940.     pDrvCtrl->endObj.flags |= END_MIB_2233;
  941. #endif  /* defined(END_MIB_2233) */
  942.     m2IfPktCountRtnInstall(pDrvCtrl->endObj.pMib2Tbl, m2If8023PacketCount);
  943.     /*
  944.      * Make a copy of the data in mib2Tbl struct as well. We do this
  945.      * mainly for backward compatibility issues. There might be some
  946.      * code that might be referencing the END pointer and might
  947.      * possibly do lookups on the mib2Tbl, which will cause all sorts
  948.      * of problems.
  949.      */
  950.     bcopy ((char *)&pDrvCtrl->endObj.pMib2Tbl->m2Data.mibIfTbl,
  951.                    (char *)&pDrvCtrl->endObj.mib2Tbl, sizeof (M2_INTERFACETBL));
  952.     /* Mark the device ready with default flags */
  953. #if defined(END_MIB_2233)
  954.     END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST | 
  955.                                       IFF_BROADCAST | END_MIB_2233);
  956. #else /* !defined(END_MIB_2233) */
  957.     END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST | 
  958.                                       IFF_BROADCAST);
  959. #endif /* !defined(END_MIB_2233) */
  960. #endif /* INCLUDE_RFC_1213 */
  961.     return (&pDrvCtrl->endObj);
  962.     /* Handle error cases */
  963. error:
  964.     dec21x40Unload (pDrvCtrl);
  965.     return (NULL);
  966.     }
  967. /***************************************************************************
  968. *
  969. * dec21x40Unload - unload a driver from the system
  970. *
  971. * This routine deallocates lists, and free allocated memory.
  972. *
  973. * RETURNS: OK, always.
  974. */
  975. LOCAL STATUS dec21x40Unload
  976.     (
  977.     DRV_CTRL *pDrvCtrl
  978.     )
  979.     {
  980.     DRV_LOG (DRV_DEBUG_LOAD, "EndUnloadn", 0, 0, 0, 0, 0, 0);
  981. #ifndef INCLUDE_RFC_1213
  982.     /* New RFC 2233 mib2 interface */
  983.     /* Free MIB-II entries */
  984.     m2IfFree(pDrvCtrl->endObj.pMib2Tbl);
  985.     pDrvCtrl->endObj.pMib2Tbl = NULL;
  986. #endif /* INCLUDE_RFC_1213 */
  987.     /* deallocate lists */
  988.     END_OBJ_UNLOAD (&pDrvCtrl->endObj);
  989.     /* deallocate allocated shared memory */
  990.     if (DRV_FLAGS_ISSET (DEC_MEMOWN)  && pDrvCtrl->memBase)
  991.         cacheDmaFree (pDrvCtrl->memBase);
  992.     return (OK);
  993.     }
  994. /***************************************************************************
  995. *
  996. * dec21x40InitParse - parse parameter values from initString
  997. *
  998. * The initialization string is modified by muxLib.o to include the unit number
  999. * as the first parameter.
  1000. *
  1001. * Parse the input string.  Fill in values in the driver control structure.
  1002. *
  1003. * The initialization string format is:
  1004. * "<device addr>:<PCI addr>:<ivec>:<ilevel>:<mem base>:<mem size>:
  1005. *  <user flags>:<phyAddr>:<pPhyTbl>:<phyFlags>:<offset>:<loanBufs>:<drvFlags>"
  1006. *
  1007. * .bS
  1008. * device addr base address of hardware device registers
  1009. * PCI addr main memory address over the PCI bus
  1010. * ivec interrupt vector number
  1011. * ilevel interrupt level
  1012. * mem base base address of a DMA-able, cache free,pre-allocated  memory
  1013. * mem size size of the pre-allocated memory
  1014. * user flags User flags control the run-time characteristics of the chip
  1015. * phyAddr MII PHY address (optional)
  1016. * pPhyTbl address of auto-negotiation table (optional)
  1017. * phyFlags PHY configuration flags (optional)
  1018. * offset        Memory offset for alignment (optional)
  1019. * loanBufs      number of loaner clusters (optional)
  1020. * drvFlags Driver flags control the runtime characteristics of the driver
  1021. *
  1022. * The last six arguments are optional. If the PHY address is to be specified
  1023. * then phyAddr, pPhyTbl, and phyFlags should all be specified together.
  1024. *
  1025. * RETURNS: OK or ERROR for invalid arguments.
  1026. */
  1027. LOCAL STATUS dec21x40InitParse
  1028.     (
  1029.     DRV_CTRL *pDrvCtrl,
  1030.     char  *initString
  1031.     )
  1032.     {
  1033.     char * tok; /* an initString token */
  1034.     char * holder=NULL; /* points to initString fragment beyond tok */
  1035.     UINT32 tokValue;
  1036.     
  1037.     DRV_LOG (DRV_DEBUG_LOAD, "InitParse: Initstr=%sn",
  1038.              (int) initString, 0, 0, 0, 0, 0);
  1039.     tok = endTok_r(initString, ":", &holder);
  1040.     if (tok == NULL)
  1041.         return ERROR;
  1042.     pDrvCtrl->unit = atoi(tok);
  1043.     tok=endTok_r(NULL, ":", &holder);
  1044.     if (tok == NULL)
  1045.         return ERROR;
  1046.     pDrvCtrl->devAdrs = strtoul (tok, NULL, 16);
  1047.     
  1048.     tok=endTok_r(NULL, ":", &holder);
  1049.     if (tok == NULL)
  1050.         return ERROR;
  1051.     pDrvCtrl->pciMemBase = strtoul (tok, NULL, 16);
  1052.     tok=endTok_r(NULL, ":", &holder);
  1053.     if (tok == NULL)
  1054.         return ERROR;
  1055.     pDrvCtrl->ivec = strtoul (tok, NULL, 16);
  1056.     tok=endTok_r(NULL, ":", &holder);
  1057.     if (tok == NULL)
  1058.         return ERROR;
  1059.     pDrvCtrl->ilevel = strtoul (tok, NULL, 16);
  1060.     
  1061.     tok = endTok_r(NULL, ":", &holder);
  1062.     if (tok == NULL)
  1063.         return ERROR;
  1064.     if (atoi(tok) < 0)
  1065.         pDrvCtrl->numRds = NUM_RDS_DEF;
  1066.     else
  1067.         pDrvCtrl->numRds = atoi(tok);
  1068.     
  1069.     tok = endTok_r(NULL, ":", &holder);
  1070.     if (tok == NULL)
  1071.         return ERROR;
  1072.     if (atoi(tok) < 0)
  1073.         pDrvCtrl->numTds = NUM_TDS_DEF;
  1074.     else
  1075.         pDrvCtrl->numTds = atoi(tok);
  1076.     tok=endTok_r(NULL, ":", &holder);
  1077.     if (tok == NULL)
  1078.         return ERROR;
  1079.     pDrvCtrl->memBase = (char *) strtoul (tok, NULL, 16);
  1080.     tok=endTok_r(NULL, ":", &holder);
  1081.     if (tok == NULL)
  1082.         return ERROR;
  1083.     pDrvCtrl->memSize = strtoul (tok, NULL, 16);
  1084.     tok=endTok_r(NULL, ":", &holder);
  1085.     if (tok == NULL)
  1086.         return (ERROR);
  1087.     pDrvCtrl->usrFlags = strtoul(tok, NULL, 16);
  1088.  
  1089.     /*
  1090.      * Start of optional parameters.  Set each optional parameter to
  1091.      * its default value, so that each will have a reasonable value
  1092.      * if we run out of fields during the string parse.
  1093.      */
  1094.     pDrvCtrl->phyAddr = (UINT8) 0xFF;
  1095.     pDrvCtrl->pMiiPhyTbl = NULL;
  1096.     pDrvCtrl->miiPhyFlags = (DEC_USR_MII_10MB | DEC_USR_MII_HD |
  1097.     DEC_USR_MII_100MB | DEC_USR_MII_FD |
  1098.     DEC_USR_MII_BUS_MON);
  1099.     pDrvCtrl->offset   = 0;
  1100.     pDrvCtrl->loanBufs = NUM_LOAN;
  1101.     pDrvCtrl->drvFlags = 0;
  1102.     /* phyAddr */
  1103.     tok = endTok_r (NULL, ":", &holder);
  1104.     if (tok == NULL)
  1105. goto endOptionalParams;
  1106.     pDrvCtrl->phyAddr = (UINT8) strtoul (tok, NULL, 16);
  1107.     /* pMiiPhyTbl - must be supplied if phyAddr was given */
  1108.     tok = endTok_r (NULL, ":", &holder);
  1109.     if (tok == NULL)
  1110. return (ERROR);
  1111.     tokValue = strtoul (tok, NULL, 16);
  1112.     if ((INT32) tokValue != -1)
  1113. pDrvCtrl->pMiiPhyTbl = (MII_AN_ORDER_TBL *) tokValue;
  1114.     /* miiPhyFlags - must be supplied if phyAddr was given */
  1115.     tok = endTok_r (NULL, ":", &holder);
  1116.     if (tok == NULL)
  1117. return (ERROR);
  1118.     tokValue = strtoul (tok, NULL, 16);
  1119.     if ((INT32) tokValue != -1)
  1120. pDrvCtrl->miiPhyFlags = tokValue;
  1121.  
  1122.     /* offset */
  1123.     tok = endTok_r (NULL, ":", &holder);
  1124.     if (tok == NULL)
  1125. goto endOptionalParams;
  1126.     if (atoi(tok) >= 0)
  1127. pDrvCtrl->offset = atoi (tok);
  1128.     /* loanBufs */
  1129.     tok = endTok_r (NULL, ":", &holder);
  1130.     if (tok == NULL)
  1131. goto endOptionalParams;
  1132.     tokValue = (UINT32) strtoul (tok, NULL, 16);
  1133.     if ((INT32) tokValue != -1)
  1134. pDrvCtrl->loanBufs = tokValue;
  1135.     /* drvFlags */
  1136.     tok = endTok_r (NULL, ":", &holder);
  1137.     if (tok == NULL)
  1138. goto endOptionalParams;
  1139.     pDrvCtrl->drvFlags = (UINT32) strtoul (tok, NULL, 16);
  1140.     if (pDrvCtrl->drvFlags & DEC_DRV_NOSWAP_MASTER)
  1141. DRV_FLAGS_SET (DEC_NOSWAP_MASTER);
  1142. endOptionalParams:
  1143.     /* print debug info */
  1144.     DRV_LOG (DRV_DEBUG_LOAD,
  1145.             "EndLoad: unit=%d devAdrs=0x%x ivec=0x%x ilevel=0x%xn",
  1146.             pDrvCtrl->unit, pDrvCtrl->devAdrs, pDrvCtrl->ivec,
  1147.     pDrvCtrl->ilevel, 0, 0);
  1148.     DRV_LOG (DRV_DEBUG_LOAD,
  1149.             "         membase=0x%x memSize=0x%xn",
  1150.             (int)pDrvCtrl->memBase, pDrvCtrl->memSize, 0,0,0,0);
  1151.     
  1152.     DRV_LOG (DRV_DEBUG_LOAD,
  1153.              "        pciMemBase=0x%x flags=0x%x usrFlags=0x%x offset=%dn",
  1154.              (int)pDrvCtrl->pciMemBase, pDrvCtrl->flags, pDrvCtrl->usrFlags,
  1155.              pDrvCtrl->offset, 0, 0);
  1156.     DRV_LOG (DRV_DEBUG_LOAD,
  1157.      "        phyAddr=0x%x pMiiPhyTbl=0x%x miiPhyFlags=0x%xn",
  1158.      (int) pDrvCtrl->phyAddr, (int) pDrvCtrl->pMiiPhyTbl,
  1159.      (int) pDrvCtrl->miiPhyFlags,
  1160.      0,0,0);
  1161.     DRV_LOG (DRV_DEBUG_LOAD,
  1162.      "        loanBufs=%d drvFlags=0x%xn", 
  1163.      (int) pDrvCtrl->loanBufs, (int) pDrvCtrl->drvFlags, 0, 0, 0, 0);
  1164.     return OK;
  1165.     }
  1166. /***************************************************************************
  1167. *
  1168. * dec21x40InitMem - initialize memory
  1169. *
  1170. * RETURNS: OK or ERROR.
  1171. */
  1172. LOCAL STATUS dec21x40InitMem
  1173.     (
  1174.     DRV_CTRL * pDrvCtrl
  1175.     )
  1176.     {
  1177.     DEC_RD * pRxD = pDrvCtrl->rxRing;
  1178.     DEC_TD * pTxD = pDrvCtrl->txRing;
  1179.     M_CL_CONFIG dcMclBlkConfig;
  1180.     CL_DESC clDesc;                      /* cluster description */
  1181.     char * pBuf;
  1182.     int ix;
  1183.     int sz;
  1184.     char * pShMem;
  1185.     
  1186.     DRV_LOG (DRV_DEBUG_LOAD, "InitMemn", 0, 0, 0, 0, 0, 0);
  1187.     /* Establish a region of shared memory */
  1188.      
  1189.     /* We now know how much shared memory we need.  If the caller
  1190.      * provides a specific memory region, we check to see if the provided
  1191.      * region is large enough for our needs.  If the caller did not
  1192.      * provide a specific region, then we attempt to allocate the memory
  1193.      * from the system, using the cache aware allocation system call.
  1194.      */
  1195.     switch ((int)pDrvCtrl->memBase)
  1196.         {
  1197.         default :       /* caller provided memory */
  1198.             /* Establish size of shared memory region we require */
  1199.             sz = ((pDrvCtrl->numRds * (DEC_BUFSIZ + RD_SIZ + 4))  +
  1200.                   (pDrvCtrl->numTds * (DEC_BUFSIZ + TD_SIZ + 4))  +
  1201.                   (pDrvCtrl->loanBufs * (DEC_BUFSIZ + 4)) + 4);
  1202.             if ( pDrvCtrl->memSize < sz )     /* not enough space */
  1203.                 {
  1204.                 DRV_LOG ( DRV_DEBUG_INIT, "%s%d: not enough memory providedn",
  1205.                          (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
  1206.                 return ( ERROR );
  1207.                 }
  1208.             pShMem = pDrvCtrl->memBase;      /* set the beginning of pool */
  1209.             /* assume pool is cache coherent, copy null structure */
  1210.             pDrvCtrl->cacheFuncs = cacheNullFuncs;
  1211.             break;
  1212.         case NONE :     /* get our own memory */
  1213.             /* 
  1214.              * Because the structures that are shared between the device
  1215.              * and the driver may share cache lines, the possibility exists
  1216.              * that the driver could flush a cache line for a structure and
  1217.              * wipe out an asynchronous change by the device to a neighboring
  1218.              * structure. Therefore, this driver cannot operate with memory
  1219.              * that is not write coherent.  We check for the availability of
  1220.              * such memory here, and abort if the system did not give us what
  1221.              * we need.
  1222.              */
  1223.             if (!CACHE_DMA_IS_WRITE_COHERENT ())
  1224.                 {
  1225.                 DRV_LOG  ( DRV_DEBUG_INIT, "dc: device requires cache"
  1226. "coherent memoryn",
  1227.         0,0,0,0,0,0);
  1228.                 return (ERROR);
  1229.                 }
  1230.             sz = (((pDrvCtrl->numRds + 1) * RD_SIZ) +
  1231.                   ((pDrvCtrl->numTds + 1) * TD_SIZ));
  1232.             pDrvCtrl->memBase = 
  1233.                 pShMem = (char *) cacheDmaMalloc ( sz );
  1234.             if (pShMem == NULL)
  1235.                 {
  1236.                 DRV_LOG ( DRV_DEBUG_LOAD, "%s%d - system memory unavailablen",
  1237.                           (int)DRV_NAME, pDrvCtrl->unit, 0,0,0,0);
  1238.                 return (ERROR);
  1239.                 }
  1240.             pDrvCtrl->memSize = sz;
  1241.             DRV_FLAGS_SET (DEC_MEMOWN);
  1242.             /* copy the DMA structure */
  1243.             pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  1244.             break;
  1245.         }
  1246.     /* zero the shared memory */
  1247.     bzero (pShMem, (int) sz);
  1248.     /* carve Rx memory structure */
  1249.     pRxD =
  1250.         pDrvCtrl->rxRing = (DEC_RD *) (((int)pShMem + 0x03) & ~0x03);
  1251.     /* carve Tx memory structure */
  1252.     pTxD =
  1253.         pDrvCtrl->txRing = (DEC_TD *) (pDrvCtrl->rxRing + pDrvCtrl->numRds);
  1254.     /* Initialize net buffer pool for tx/rx buffers */
  1255.     bzero ((char *)&dcMclBlkConfig, sizeof(dcMclBlkConfig));
  1256.     bzero ((char *)&clDesc, sizeof(clDesc));
  1257.     
  1258.     dcMclBlkConfig.mBlkNum  = (pDrvCtrl->numRds + pDrvCtrl->loanBufs) * 4;
  1259.     clDesc.clNum      = pDrvCtrl->numRds + pDrvCtrl->numTds + 
  1260.                               pDrvCtrl->loanBufs;
  1261.     dcMclBlkConfig.clBlkNum = clDesc.clNum;
  1262.     /*
  1263.      * mBlk and cluster configuration memory size initialization
  1264.      * memory size adjusted to hold the netPool pointer at the head.
  1265.      */
  1266.     dcMclBlkConfig.memSize = ((dcMclBlkConfig.mBlkNum *
  1267.                                (MSIZE + sizeof (long))) +
  1268.                               (dcMclBlkConfig.clBlkNum *
  1269.                                (CL_BLK_SZ + sizeof (long))));
  1270.     
  1271.     if ((dcMclBlkConfig.memArea = (char *)memalign(sizeof (long),
  1272.                                                    dcMclBlkConfig.memSize))
  1273.         == NULL)
  1274.         return (ERROR);
  1275.     
  1276.     clDesc.clSize  = DEC_BUFSIZ;
  1277.     clDesc.memSize  = ((clDesc.clNum * (clDesc.clSize + 4)) + 4);
  1278.     if (DRV_FLAGS_ISSET(DEC_MEMOWN))
  1279.         {
  1280.         clDesc.memArea = (char *) cacheDmaMalloc (clDesc.memSize);
  1281.         if (clDesc.memArea == NULL)
  1282.             {
  1283.             DRV_LOG  (DRV_DEBUG_INIT,  "%s%d - system memory unavailablen",
  1284.                       (int)DRV_NAME, pDrvCtrl->unit, 0,0,0,0);
  1285.             return (ERROR);
  1286.             }
  1287.         }
  1288.     else
  1289.         clDesc.memArea = (char *) (pDrvCtrl->txRing + pDrvCtrl->numTds);
  1290.     
  1291.     if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  1292.         return (ERROR);
  1293.     /* Initialize the net buffer pool with transmit buffers */
  1294.     if (netPoolInit (pDrvCtrl->endObj.pNetPool, &dcMclBlkConfig,
  1295.                      &clDesc, 1, NULL) == ERROR)
  1296.         {
  1297.         DRV_LOG  (DRV_DEBUG_INIT, "%s%d - netPoolInit failedn",
  1298.   (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
  1299.         return (ERROR);
  1300.         }
  1301.     /* Save the cluster pool id */
  1302.     pDrvCtrl->clPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool,
  1303.                                       DEC_BUFSIZ, FALSE);
  1304.     /* Clear all indices */
  1305.     pDrvCtrl->rxIndex=0;
  1306.     pDrvCtrl->txIndex=0;
  1307.     pDrvCtrl->txDiIndex=0;
  1308.     /* Setup the receive ring */
  1309.     for (ix = 0; ix < pDrvCtrl->numRds; ix++, pRxD++)
  1310.         {
  1311.         pBuf = (char *) NET_BUF_ALLOC();
  1312.         if (pBuf == NULL)
  1313.             {
  1314.             DRV_LOG  (DRV_DEBUG_INIT, "%s%d - netClusterGet failedn",
  1315.       (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
  1316.             return (ERROR);
  1317.             }
  1318. pRxD->rDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pBuf)); /* buffer 1 */
  1319.         pRxD->rDesc3 = PCISWAP ((ULONG)pBuf);      /* save virt addr */
  1320. /* buffer size */
  1321. pRxD->rDesc1 = PCISWAP (RDESC1_RBS1_VAL (DEC_BUFSIZ) | 
  1322.                                 RDESC1_RBS2_VAL (0));
  1323. if (ix == (pDrvCtrl->numRds - 1)) /* if its is last one */
  1324.     pRxD->rDesc1 |= PCISWAP (RDESC1_RER); /* end of receive ring */
  1325. pRxD->rDesc0 = PCISWAP (RDESC0_OWN); /* give ownership to chip */
  1326.         }
  1327.     /* Setup the transmit ring */
  1328.     for (ix = 0; ix < pDrvCtrl->numTds; ix++, pTxD++)
  1329.         {
  1330.         /* empty -- no buffers at this time */
  1331. pTxD->tDesc2 = 0;
  1332. pTxD->tDesc3 = 0;
  1333. pTxD->tDesc1 = PCISWAP ((TDESC1_TBS1_PUT(0) |   /* buffer1 size */
  1334.                                  TDESC1_TBS2_PUT(0) |   /* buffer2 size */
  1335.                                  TDESC1_IC          |  /* intrpt on xmit */
  1336.                                  TDESC1_LS          | /* last segment */
  1337.                                  TDESC1_FS)); /* first segment */
  1338. if (ix == (pDrvCtrl->numTds - 1))    /* if its is last one */
  1339.     pTxD->tDesc1 |= PCISWAP (TDESC1_TER); /* end of Xmit ring */
  1340. pTxD->tDesc0 = 0;                    /* owner is host */
  1341.         }
  1342.     /* Fill the buffer for txPollSend */
  1343.     pDrvCtrl->txPollSendBuf = NET_BUF_ALLOC();
  1344.     /* Flush the write pipe */
  1345.     CACHE_PIPE_FLUSH ();
  1346.     return (OK);
  1347.     }
  1348. /***************************************************************************
  1349. *
  1350. * dec21x40Start - start the device
  1351. *
  1352. * This function initializes the device and calls BSP functions to connect
  1353. * interrupts and start the device running in interrupt mode.
  1354. *
  1355. * The complement of this routine is dec21x40Stop.  Once a unit is reset by
  1356. * dec21x40Stop, it may be re-initialized to a running state by this routine.
  1357. *
  1358. * RETURNS: OK if successful, otherwise ERROR
  1359. */
  1360. LOCAL STATUS dec21x40Start
  1361.     (
  1362.     DRV_CTRL * pDrvCtrl /* device to start */
  1363.     )
  1364.     {
  1365.     int    retVal;
  1366.     UINT   csr0Val; 
  1367.     UINT   csr6Val   = 0;
  1368.     UINT   usrFlags  = pDrvCtrl->usrFlags;
  1369.     UINT   tries     = 0;
  1370.     DRV_LOG (DRV_DEBUG_LOAD, 
  1371.      "Start, IO base addr: 0x%x ivec %d, ilevel %d, mempool base addr: 0x%xn",
  1372.       pDrvCtrl->devAdrs, pDrvCtrl->ivec, pDrvCtrl->ilevel,
  1373.       (int)(pDrvCtrl->memBase), 
  1374.       0, 0);
  1375.     DRV_LOG (DRV_DEBUG_LOAD,
  1376.              "        pciMemBase=0x%x flags=0x%x usrFlags=0x%xn",
  1377.              (int)pDrvCtrl->pciMemBase, pDrvCtrl->flags, pDrvCtrl->usrFlags,
  1378.              0, 0, 0);
  1379. restart:
  1380.     /* Reset the device */
  1381.     DEC_CSR_WRITE (CSR6, 0);
  1382.     dec21x40ChipReset (pDrvCtrl);
  1383.     /* Clear all indices */
  1384.     pDrvCtrl->rxIndex=0;
  1385.     pDrvCtrl->txIndex=0;
  1386.     pDrvCtrl->txDiIndex=0;
  1387.  
  1388.     pDrvCtrl->txCleaning = FALSE;
  1389.     pDrvCtrl->rxHandling = FALSE;
  1390.     pDrvCtrl->txBlocked = FALSE;
  1391.     if (! DRV_FLAGS_ISSET (DEC_21040))
  1392.         {
  1393.         if (_func_dec21x40MediaSelect != NULL)
  1394.             retVal = (* _func_dec21x40MediaSelect) (pDrvCtrl, &csr6Val);
  1395. else if (DRV_FLAGS_ISSET (DEC_21140))
  1396.             retVal = dec21140MediaSelect (pDrvCtrl, &csr6Val);
  1397. else if (DRV_FLAGS_ISSET (DEC_21143))
  1398.     retVal = dec21143MediaSelect (pDrvCtrl, &csr6Val);
  1399. else if (DRV_FLAGS_ISSET (DEC_21145))
  1400.     retVal = dec21145MediaSelect (pDrvCtrl, &csr6Val);
  1401. else
  1402.     retVal = ERROR;
  1403.         if (retVal == ERROR)
  1404.             return (ERROR);
  1405.         
  1406.         if (csr6Val & CSR6_21140_PS)
  1407.             {
  1408.            
  1409.             /* changing PS requires a software reset */
  1410.             DEC_CSR_UPDATE (CSR6, CSR6_21140_PS);
  1411.             /* copy CSR0 before the software reset */
  1412.             csr0Val = DEC_CSR_READ (CSR0); 
  1413.             DEC_CSR_WRITE (CSR0, CSR0_SWR);
  1414.             /* wait for software reset to complete before restoring CSRO */ 
  1415.             taskDelay(sysClkRateGet()/30);
  1416.             /* restore CSR0 */
  1417.             DEC_CSR_WRITE (CSR0, csr0Val);  
  1418.             csr6Val |= CSR6_21140_HBD;
  1419.    
  1420.             /* clear CSR13 and 14 if 21143 - Appendix D, Port Selection */
  1421.  
  1422.             if (usrFlags & DEC_USR_21143)
  1423.                 {   
  1424.                 DEC_CSR_WRITE (CSR13, 0);
  1425.                 DEC_CSR_WRITE (CSR14, 0);
  1426.                 }
  1427.             }
  1428.         csr6Val &= DEC_USR_CSR6_MSK;
  1429.         csr6Val |= CSR6_21140_MB1;
  1430.         /* decode CSR6 specific options from userFlags */
  1431.         if (usrFlags & DEC_USR_SF)
  1432.             csr6Val |= CSR6_21140_SF;
  1433.         if (usrFlags & DEC_USR_THR_MSK)
  1434.             csr6Val |= (usrFlags & DEC_USR_THR_MSK) >> DEC_USR_THR_SHF;
  1435.         if (usrFlags & DEC_USR_SB)
  1436.             csr6Val |= CSR6_SB;
  1437.         if (usrFlags & DEC_USR_PB)
  1438.             csr6Val |= CSR6_PB;
  1439.         if (usrFlags & DEC_USR_SC)
  1440.             csr6Val |= CSR6_21140_SC;
  1441.         if (usrFlags & DEC_USR_CA)
  1442.             csr6Val |= CSR6_CAE;
  1443.         }
  1444.     else
  1445.         dec21040AuiTpInit (pDrvCtrl);
  1446.     /* Write start of receive ring */
  1447.     DEC_CSR_WRITE (CSR3, DEC_VIRT_TO_PCI(pDrvCtrl->rxRing));
  1448.     /* Write start of transmit ring */
  1449.     DEC_CSR_WRITE (CSR4, DEC_VIRT_TO_PCI(pDrvCtrl->txRing));
  1450.     /* clear the status register */
  1451.     DEC_CSR_WRITE (CSR5, 0xffffffff);
  1452.     /* setup CSR6 - start transmitter */
  1453.     DEC_CSR_WRITE (CSR6, csr6Val | CSR6_ST);
  1454.     DRV_LOG (DRV_DEBUG_LOAD, "Writing CSR6 = %#08xnCSR7 = %#08xn",
  1455.      csr6Val | CSR6_ST, DEC_CSR_READ (CSR7),
  1456.      0,0,0,0);
  1457.     taskDelay (sysClkRateGet() * 2);
  1458.     /* Check status of link */
  1459.     tries++; /* Increment the number of attempts to find media */
  1460.     if ((csr6Val & CSR6_21140_PS) && (csr6Val & CSR6_21140_PCS))
  1461. {
  1462. /* 100 Mbps non-MII mode */
  1463. if (DEC_CSR_READ (CSR12) & CSR12_21143_LS100)
  1464.     {
  1465.     /* LS100 indicates link state down */
  1466.     if (tries < pDrvCtrl->mediaCount)
  1467. {
  1468. DRV_LOG (DRV_DEBUG_INIT, "100Mbps link failed - restartingn",
  1469.  0,0,0,0,0,0);
  1470. goto restart;
  1471. }
  1472.     else
  1473. {
  1474. DRV_LOG (DRV_DEBUG_INIT, "100Mbps link failed - abortingn",
  1475.  0,0,0,0,0,0);
  1476. return ERROR;
  1477. }
  1478.     }
  1479. }
  1480.     else if ((csr6Val & CSR6_21140_PS) == 0)
  1481. {
  1482. /* 10 Mbps mode */
  1483. if (DEC_CSR_READ (CSR12) & (CSR12_21143_LS10 | CSR12_21040_LKF))
  1484.     {
  1485.     /* Link down */
  1486.     if (tries < pDrvCtrl->mediaCount)
  1487. {
  1488. DRV_LOG (DRV_DEBUG_INIT, "10Mbps link failed - restartingn",
  1489.  0,0,0,0,0,0);
  1490. goto restart;
  1491. }
  1492.     else
  1493. {
  1494. DRV_LOG (DRV_DEBUG_INIT, "10Mbps link failed - abortingn",
  1495.  0,0,0,0,0,0);
  1496.         return ERROR;
  1497. }
  1498.     }
  1499. }
  1500.     /* setup ethernet address and filtering mode */
  1501.     dec21x40IASetup (pDrvCtrl);
  1502.     /* set operating mode and start the receiver */
  1503.     dec21x40ModeSet (pDrvCtrl);
  1504.     /* Connect the interrupt handler */
  1505.     SYS_INT_CONNECT (pDrvCtrl, dec21x40Int, pDrvCtrl, &retVal);
  1506.     if (retVal == ERROR)
  1507.         return (ERROR);
  1508.     /* set up the interrupts */
  1509.     pDrvCtrl->intrMask = (CSR7_NIM |        /* normal interrupt mask */
  1510.                           CSR7_RIM |         /* rcv  interrupt mask */
  1511.                           CSR7_TIM |         /* xmit interrupt mask */
  1512.                           CSR7_TUM |         /* xmit buff unavailble mask */
  1513.                           CSR7_AIM |         /* abnormal interrupt mask */
  1514.                           CSR7_SEM |         /* system error mask */
  1515.                           CSR7_RUM );       /* rcv buff unavailable mask */
  1516.     if (DRV_FLAGS_ISSET(DEC_21145) 
  1517.  && (pDrvCtrl->usrFlags & (DEC_USR_HPNA_PREFER_10BT)))
  1518. {
  1519. /* link fail, pass/anc mask */
  1520. pDrvCtrl->intrMask |= (CSR7_ANC | CSR7_21040_LFM );  
  1521. }
  1522.     DEC_CSR_WRITE (CSR7, pDrvCtrl->intrMask);
  1523.     if (DRV_FLAGS_ISSET (DEC_21040))
  1524.         DEC_CSR_UPDATE (CSR7, CSR7_21040_LFM);   /* link fail mask */
  1525.     /* mark the interface -- up */
  1526.     END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  1527.     /* Enable LAN interrupts */
  1528.     SYS_INT_ENABLE (pDrvCtrl);
  1529.     pDrvCtrl->rxLen = 0;
  1530.     pDrvCtrl->rxMaxLen = RWIN;
  1531.     return OK;
  1532.     }
  1533. /***************************************************************************
  1534. *
  1535. * dec21x40Stop - stop the device
  1536. *
  1537. * This routine disables interrupts, and resets the device.
  1538. *
  1539. * RETURNS: OK or ERROR
  1540. */
  1541. LOCAL STATUS dec21x40Stop
  1542.     (
  1543.     DRV_CTRL *pDrvCtrl
  1544.     )
  1545.     {
  1546.     int retVal  = OK;
  1547.     PHY_INFO * pPhyInfo = pDrvCtrl->pPhyInfo;
  1548.     DRV_LOG (DRV_DEBUG_LOAD, "Stopn", 0, 0, 0, 0, 0, 0);
  1549.     /* mark the interface -- down */
  1550.     END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING);
  1551.     /* Disable LAN interrupts */
  1552.     SYS_INT_DISABLE (pDrvCtrl);
  1553.     /* stop transmit and receive */
  1554.     DEC_CSR_RESET (CSR6, CSR6_ST | CSR6_SR);
  1555.     if ((pDrvCtrl->usrFlags & DEC_USR_21145) == 0)
  1556. {
  1557. if ((pPhyInfo != NULL) && MII_PHY_FLAGS_ARE_SET (MII_PHY_INIT))
  1558.     {
  1559.     if (intCnt == 0)
  1560. {
  1561. if (miiPhyUnInit (pPhyInfo) == ERROR)
  1562.     return (ERROR);
  1563. free (pPhyInfo);
  1564. }
  1565.     else
  1566. {
  1567. /*
  1568.  * Defer these to task level since they cannot be performed at
  1569.  * interrupt level
  1570.  */
  1571. netJobAdd ((FUNCPTR) miiPhyUnInit, (int) pPhyInfo, 0,0,0,0);
  1572. netJobAdd ((FUNCPTR) free, (int) pPhyInfo, 0,0,0,0);
  1573. }
  1574.     pDrvCtrl->pPhyInfo = NULL;
  1575.     }
  1576. }
  1577.     /* disconnect interrupt */
  1578.     SYS_INT_DISCONNECT (pDrvCtrl, dec21x40Int, (int)pDrvCtrl, &retVal);
  1579.     return (retVal);
  1580.     }
  1581. /***************************************************************************
  1582. *
  1583. * dec21x40MediaChange - start the device
  1584. *
  1585. * Restarts the device after cleaning up the transmit and receive queues. This
  1586. * routine should be called only after dec21x40Stop().
  1587. *
  1588. * RETURNS: OK or ERROR
  1589. */
  1590. LOCAL STATUS dec21x40MediaChange
  1591.     (
  1592.     DRV_CTRL *pDrvCtrl
  1593.     )
  1594.     {
  1595.     if (dec21x40Stop (pDrvCtrl) == ERROR)
  1596. {
  1597. DRV_LOG (DRV_DEBUG_INIT, "dec21x40MediaChange, unable to stopn",
  1598. 0, 0, 0, 0, 0, 0);
  1599. return (ERROR);
  1600. }
  1601.     DRV_LOG (DRV_DEBUG_ALL, "%s%d - stopped device.n",
  1602.             (int)DRV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
  1603.     netJobAdd ((FUNCPTR) dec21x40Restart, (int) pDrvCtrl, 0,0,0,0);
  1604.     return (OK);
  1605.     }
  1606. /***************************************************************************
  1607. *
  1608. * dec21x40Restart - start the device
  1609. *
  1610. * Restarts the device after cleaning up the transmit and receive queues. This
  1611. * routine should be called only after dec21x40Stop().
  1612. *
  1613. * RETURNS: OK or ERROR
  1614. */
  1615. LOCAL void dec21x40Restart
  1616.     (
  1617.     DRV_CTRL *pDrvCtrl
  1618.     )
  1619.     {
  1620.     DEC_TD  *pTxD = pDrvCtrl->txRing;
  1621.     FREE_BUF *pFreeBuf = pDrvCtrl->freeBuf;
  1622.     int count;
  1623.     
  1624.     DRV_LOG (DRV_DEBUG_ALL, "%s%d - restarting device.n",
  1625.             (int)DRV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
  1626.     
  1627.     /* cleanup the tx and rx queues */
  1628.     dec21x40TxRingClean (pDrvCtrl);
  1629.     dec21x40RxIntHandle (pDrvCtrl);
  1630.     /* drop rest of the queued tx packets */
  1631.     for (count=pDrvCtrl->numTds; count; count--, pTxD++, pFreeBuf++)
  1632.         {
  1633.         if (pFreeBuf->pClBuf != NULL)
  1634.             {
  1635.             NET_BUF_FREE(pFreeBuf->pClBuf);
  1636.             pFreeBuf->pClBuf = NULL;
  1637.             }
  1638.         DEC_CACHE_INVALIDATE (pTxD, TD_SIZ);
  1639.         
  1640.         if (pTxD->tDesc1 & PCISWAP(TDESC1_SET))
  1641.             {
  1642.             pTxD->tDesc1 &= PCISWAP(~(TDESC1_SET | TDESC1_FT0));
  1643.             pTxD->tDesc0 = 0;
  1644.             }
  1645.         else if (pTxD->tDesc0 & PCISWAP(TDESC0_OWN|TDESC0_ES))
  1646.             {
  1647. #ifdef INCLUDE_RFC_1213
  1648.             /* Old RFC 1213 mib2 interface */
  1649.             END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1650.             END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
  1651.             
  1652. #else 
  1653.             /* New RFC 2233 mib2 interface */
  1654.             if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  1655.                 {
  1656.                 pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
  1657.                                                                     pMib2Tbl,
  1658.                                                           M2_ctrId_ifOutErrors,
  1659.                                                           1);
  1660.                 }
  1661. #endif /* INCLUDE_RFC_1213 */
  1662.             pTxD->tDesc0 = 0;
  1663.             }
  1664.         }
  1665.     /* Reset indices */
  1666.     pDrvCtrl->rxIndex=0;
  1667.     pDrvCtrl->txIndex=0;
  1668.     pDrvCtrl->txDiIndex=0;
  1669.     /* Restart the device */
  1670.     dec21x40Start (pDrvCtrl);
  1671.     }
  1672. /***************************************************************************
  1673. *
  1674. * dec21x40Ioctl - interface ioctl procedure
  1675. *
  1676. * Process an interface ioctl request.
  1677. *
  1678. * This routine implements the network interface control functions.
  1679. * It handles EIOCSADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS, EIOCMULTIADD,
  1680. * EIOCMULTIDEL, EIOCMULTIGET, EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2 commands.
  1681. *
  1682. * RETURNS: OK if successful, otherwise EINVAL.
  1683. */
  1684. LOCAL int dec21x40Ioctl
  1685.     (
  1686.     DRV_CTRL * pDrvCtrl,
  1687.     int cmd,
  1688.     caddr_t data
  1689.     )
  1690.     {
  1691.     int error=0;
  1692.     long value;
  1693.     int savedFlags;
  1694.     END_OBJ * pEndObj=&pDrvCtrl->endObj;
  1695.     
  1696.     DRV_LOG (DRV_DEBUG_IOCTL,
  1697.              "Ioctl unit=0x%x cmd=%d data=0x%xn",
  1698.              pDrvCtrl->unit, cmd, (int)data, 0, 0, 0);
  1699.     switch ((UINT)cmd)
  1700.         {
  1701.         case EIOCSADDR:
  1702.             if (data == NULL)
  1703.                 error = EINVAL;
  1704.             else
  1705.                 {
  1706.                 /* Copy and install the new address */
  1707.                 bcopy ((char *)data, (char *)END_HADDR(pEndObj),
  1708.                        END_HADDR_LEN(pEndObj));
  1709.                 dec21x40IASetup (pDrvCtrl);
  1710.                 }
  1711.             break;
  1712.             
  1713.         case EIOCGADDR:
  1714.             if (data == NULL)
  1715.                 error = EINVAL;
  1716.             else
  1717.                 bcopy ((char *)END_HADDR(pEndObj), (char *)data,
  1718.                        END_HADDR_LEN(pEndObj));
  1719. #ifdef DRV_DEBUG
  1720.             {
  1721.             char *cp = (char *)data;
  1722.             DRV_LOG (DRV_DEBUG_IOCTL,
  1723.                           "EIOCGADDR: %x:%x:%x:%x:%x:%xn",
  1724.                           cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
  1725.             }
  1726. #endif /*DRV_DEBUG*/
  1727.             break;
  1728.         case EIOCSFLAGS:
  1729.             value = (long) data;
  1730.             if (value < 0)
  1731.                 {
  1732.                 value = -value;
  1733.                 value--;
  1734.                 END_FLAGS_CLR (pEndObj, value);
  1735.                 }
  1736.             else
  1737.                 END_FLAGS_SET (pEndObj, value);
  1738.             /* handle IIF_PROMISC and IFF_ALLMULTI */
  1739.             savedFlags = DRV_FLAGS_GET();
  1740.             if (END_FLAGS_ISSET (pEndObj, IFF_PROMISC))
  1741.                 DRV_FLAGS_SET (DEC_PROMISC);
  1742.             else
  1743.                 DRV_FLAGS_CLR (DEC_PROMISC);
  1744.             if (END_FLAGS_GET(pEndObj) & (IFF_MULTICAST | IFF_ALLMULTI))
  1745.                 DRV_FLAGS_SET (DEC_MCAST);
  1746.             else
  1747.                 DRV_FLAGS_CLR (DEC_MCAST);
  1748.             DRV_LOG (DRV_DEBUG_IOCTL,
  1749.                        "endFlags=0x%x savedFlags=0x%x newFlags=0x%xn",
  1750.                         END_FLAGS_GET(pEndObj), savedFlags, DRV_FLAGS_GET(),
  1751. 0, 0, 0);
  1752.             if ((DRV_FLAGS_GET() != savedFlags) &&
  1753.                 (END_FLAGS_GET(pEndObj) & IFF_UP))
  1754.                 dec21x40ModeSet (pDrvCtrl);
  1755.             break;
  1756.         case EIOCGFLAGS:                     /* move to mux */
  1757.             DRV_LOG (DRV_DEBUG_IOCTL, "EIOCGFLAGS: 0x%x: 0x%xn",
  1758.                     pEndObj->flags, *(long *)data, 0, 0, 0, 0);
  1759.             if (data == NULL)
  1760.                 error = EINVAL;
  1761.             else
  1762.                 *(long *)data = END_FLAGS_GET(pEndObj);
  1763.             break;
  1764.         case EIOCMULTIADD:                   /* move to mux */
  1765.             error = dec21x40MCastAddrAdd (pDrvCtrl, (char *)data);
  1766.             break;
  1767.         case EIOCMULTIDEL:                   /* move to mux */
  1768.             error = dec21x40MCastAddrDel (pDrvCtrl, (char *)data);
  1769.             break;
  1770.         case EIOCMULTIGET:                   /* move to mux */
  1771.             error = dec21x40MCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data);
  1772.             break;
  1773.         case EIOCPOLLSTART:                  /* move to mux */
  1774.             dec21x40PollStart (pDrvCtrl);
  1775.             break;
  1776.         case EIOCPOLLSTOP:                   /* move to mux */
  1777.             dec21x40PollStop (pDrvCtrl);
  1778.             break;
  1779.         case EIOCGMIB2:                      /* move to mux */
  1780.             if (data == NULL)
  1781.                 error=EINVAL;
  1782.             else
  1783.                 bcopy((char *)&pEndObj->mib2Tbl, (char *)data,
  1784.                       sizeof(pEndObj->mib2Tbl));
  1785.             break;
  1786. #ifndef INCLUDE_RFC_1213
  1787.         /* New RFC 2233 mib2 interface */
  1788.         case EIOCGMIB2233:
  1789.             if ((data == NULL) || (pEndObj->pMib2Tbl == NULL))
  1790.                 error = EINVAL;
  1791.             else
  1792.                 *((M2_ID **)data) = pEndObj->pMib2Tbl;
  1793.             break;
  1794. #endif /* INCLUDE_RFC_1213 */
  1795.         default:
  1796.             error = EINVAL;
  1797.         }
  1798.     return (error);
  1799.     }
  1800. /***************************************************************************
  1801. *
  1802. * dec21x40ModeSet - promiscuous & multicast operation and start receiver
  1803. *
  1804. * RETURNS: N/A
  1805. */
  1806. LOCAL void dec21x40ModeSet
  1807.     (
  1808.     DRV_CTRL *pDrvCtrl
  1809.     )
  1810.     {
  1811.     int opMode = CSR6_SR;                    /* start receiver */
  1812.     DRV_LOG (DRV_DEBUG_IOCTL, "ModeSetn", 0, 0, 0, 0, 0, 0);
  1813.     if (DRV_FLAGS_ISSET (DEC_MCAST))
  1814.         opMode |= CSR6_PM;                   /* rx multicast */
  1815.     if (DRV_FLAGS_ISSET (DEC_PROMISC))
  1816.         opMode |= CSR6_PR;                   /* rx promiscuous */
  1817.     
  1818.     DEC_CSR_WRITE (CSR6, (DEC_CSR_READ (CSR6) & ~(CSR6_PM|CSR6_PR)) | opMode);
  1819.     return;
  1820.     }
  1821. /***************************************************************************
  1822. *
  1823. * dec21x40HashIndex - compute the hash index for an ethernet address
  1824. *
  1825. * RETURNS: hash index for an ethernet address.
  1826. */
  1827. LOCAL int dec21x40HashIndex
  1828.     (
  1829.     char * eAddr
  1830.     )
  1831.     {
  1832.     UINT8 eAddrByte;
  1833.     int index;                       /* hash index - return value */
  1834.     int byte;                        /* loop - counter */
  1835.     int bit;                         /* loop - counter */
  1836.     UINT crc = 0xffffffff;
  1837.     UINT8 msb;
  1838.     for (byte=0; byte<6; byte++)
  1839.         {
  1840.         eAddrByte = eAddr[byte];
  1841.         for (bit=0; bit<8; bit++)
  1842.             {
  1843.             msb = crc >> 31;
  1844.             crc <<= 1;
  1845.             if (msb ^ (eAddrByte & 0x1))
  1846.                 {
  1847.                 crc ^= DEC_CRC_POLY;
  1848.                 crc |= 0x1;
  1849.                 }
  1850.             eAddrByte >>= 1;
  1851.             }
  1852.         }
  1853.     /*
  1854.      * return the upper 9 bits of the CRC in a decreasing order of
  1855.      * significance.
  1856.      * crc <31..23> as index <0..8>
  1857.      */
  1858.     index = 0;
  1859.     for (bit=0; bit<9; bit++)
  1860.         index |= ((crc >> (31-bit)) & 0x1) << bit;
  1861.     return index;
  1862.     }
  1863. /***************************************************************************
  1864. *
  1865. * dec21x40IASetup - set up physical and multicast addresses
  1866. *
  1867. * This routine sets up a filter frame to filter the physical addresses
  1868. * and all the current multicast addresses.
  1869. *
  1870. * While the first call to this routine during chip initialization requires
  1871. * that the receiver be turned off, subsequent calls do not.
  1872. * RETURNS: OK or ERROR.
  1873. */
  1874. LOCAL STATUS dec21x40IASetup
  1875.     (
  1876.     DRV_CTRL * pDrvCtrl  /* pointer to device control structure */
  1877.     )
  1878.     {
  1879.     UINT8 ethBcastAdrs[]={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  1880.     UINT8  *pFltrFrm;
  1881.     UINT8 *pAdrs;
  1882.     ETHER_MULTI *pMCastNode;
  1883.     DEC_TD *pTxD;
  1884.     ULONG csr7Val;
  1885.     char * pBuf;
  1886.     int index;
  1887.     int timeout;
  1888.     /* gain exclusive access to transmitter */
  1889.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  1890.     
  1891.     /* get a free transmit descriptor */
  1892.     pTxD = dec21x40TxDGet (pDrvCtrl);
  1893.     if (pTxD == NULL)
  1894.         {
  1895.         DRV_LOG (DRV_DEBUG_INIT, "dec21x40TxDGet failedn", 1, 2, 3, 4, 5, 6);
  1896.         END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1897.         return (ERROR);
  1898.         }
  1899.     DRV_LOG (DRV_DEBUG_IOCTL, "IASetup 0x%xn", pTxD->tDesc0, 0, 0, 0, 0, 0);
  1900.     /* get a buffer */
  1901.     pBuf = NET_BUF_ALLOC();
  1902.     if (pBuf == NULL)
  1903.         {
  1904.         DRV_LOG (DRV_DEBUG_INIT, "netClusterGet failedn", 1, 2, 3, 4, 5, 6);
  1905.         END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1906.         return (ERROR);
  1907.         }
  1908.     /* align the frame */
  1909.     pFltrFrm = (UINT8 *) (((int)pBuf + 0x3) & ~0x3);
  1910.     /* clear all entries */
  1911.     bzero (pFltrFrm, FLTR_FRM_SIZE);
  1912.     /* install multicast addresses */
  1913.     for (pMCastNode = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);
  1914.          pMCastNode != NULL;
  1915.          pMCastNode = END_MULTI_LST_NEXT (pMCastNode))
  1916.         {
  1917.         index = dec21x40HashIndex (pMCastNode->addr);
  1918.         pFltrFrm [DEC_FLT_INDEX(index/8)] |= 1 << (index % 8);
  1919.         }
  1920.     /* install an ethernet broadcast address */
  1921.     index = dec21x40HashIndex (ethBcastAdrs);
  1922.     pFltrFrm [DEC_FLT_INDEX(index/8)] |= 1 << (index % 8);
  1923.     /* install the physical address */
  1924.     pAdrs = (UINT8 *)END_HADDR (&pDrvCtrl->endObj);
  1925.     for (index=0; index<6; index++)
  1926.         pFltrFrm [FLTR_FRM_PHY_ADRS_OFF + DEC_FLT_INDEX(index)] = pAdrs[index];
  1927.     /* transmit the frame */
  1928.     pTxD->tDesc2  = PCISWAP (DEC_VIRT_TO_PCI (pFltrFrm));
  1929.     pTxD->tDesc3  = 0;
  1930.     /* frame type is SETUP, filtering mode is HASH + 1 perfect */
  1931.     pTxD->tDesc1 |= PCISWAP (TDESC1_SET | TDESC1_FT0); 
  1932.     pTxD->tDesc1 &= PCISWAP (~TDESC1_TBS1_MSK);
  1933.     pTxD->tDesc1 |= PCISWAP (TDESC1_TBS1_PUT(FLTR_FRM_SIZE));
  1934.     pTxD->tDesc1 &= PCISWAP (~(TDESC1_LS|TDESC1_FS));
  1935.     pTxD->tDesc0  = PCISWAP(TDESC0_OWN);      /* ready for transmit */
  1936.     CACHE_PIPE_FLUSH();
  1937.     /* Advance our management index */
  1938.     pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds;
  1939.     /* mask interrupts */
  1940.     csr7Val = DEC_CSR_READ (CSR7);
  1941.     DEC_CSR_WRITE (CSR7, 0);
  1942.     /* start tx */
  1943.     if (DRV_FLAGS_ISSET(DEC_TX_KICKSTART))
  1944.         DEC_CSR_WRITE (CSR1, CSR1_TPD);
  1945.     /* wait for completion */
  1946.     timeout=0xffffff;
  1947.     while (timeout && (pTxD->tDesc0 != (~PCISWAP (TDESC0_OWN))))
  1948. timeout--;
  1949.     if (timeout <= 0)
  1950. {
  1951. DRV_LOG (DRV_DEBUG_INIT, "no toggle on OWN bit 0x%x %xn", 
  1952.  (int)(&pTxD->tDesc0), pTxD->tDesc0, 3, 4, 5, 6);
  1953.         END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1954. return (ERROR);
  1955. }
  1956.     /* restore TXD bits */
  1957.     pTxD->tDesc0  = 0;
  1958.     pTxD->tDesc1 &= PCISWAP (~(TDESC1_SET | TDESC1_FT0));
  1959.     pTxD->tDesc1 |= PCISWAP (TDESC1_LS | TDESC1_FS);
  1960.     pTxD->tDesc2  = 0;
  1961.     CACHE_PIPE_FLUSH();
  1962.     /* restore interrupts */
  1963.     DEC_CSR_WRITE (CSR7, csr7Val);
  1964.     /* free the buffer */
  1965.     NET_BUF_FREE (pBuf);
  1966.     /* release exclusive access */
  1967.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1968.     /* return success */
  1969.     return (OK);
  1970.     }
  1971. /***************************************************************************
  1972. *
  1973. * dec21x40MCastAddrAdd - add a multicast address
  1974. *
  1975. *
  1976. * RETURNS: OK on success, ERROR otherwise.
  1977. */
  1978. LOCAL STATUS dec21x40MCastAddrAdd
  1979.     (
  1980.     DRV_CTRL * pDrvCtrl,
  1981.     char * pAddr
  1982.     )
  1983.     {
  1984.     int retVal;
  1985.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrAddn", 0, 0, 0, 0, 0, 0);
  1986.     retVal = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddr);
  1987.     if (retVal == ENETRESET)
  1988.         return dec21x40IASetup (pDrvCtrl);
  1989.     return ((retVal == OK) ? OK : ERROR);
  1990.     }
  1991. /***************************************************************************
  1992. *
  1993. * dec21x40MCastAddrDel - remove a multicast address
  1994. *
  1995. *
  1996. * RETURNS: OK on success, ERROR otherwise.
  1997. */
  1998. LOCAL STATUS dec21x40MCastAddrDel
  1999.     (
  2000.     DRV_CTRL * pDrvCtrl,
  2001.     char * pAddr
  2002.     )
  2003.     {
  2004.     int retVal;
  2005.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrDeln", 0, 0, 0, 0, 0, 0);
  2006.     retVal = etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr);
  2007.     if (retVal == ENETRESET)
  2008.         return dec21x40IASetup (pDrvCtrl);
  2009.     return ((retVal == OK) ? OK : ERROR);
  2010.     }
  2011. /***************************************************************************
  2012. *
  2013. * dec21x40MCastAddrGet - retreive current multicast address list
  2014. *
  2015. *
  2016. * RETURNS: OK on success; otherwise ERROR.
  2017. */
  2018. LOCAL STATUS dec21x40MCastAddrGet
  2019.     (
  2020.     DRV_CTRL * pDrvCtrl,
  2021.     MULTI_TABLE *pTable
  2022.     )
  2023.     {
  2024.     DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrGetn", 0, 0, 0, 0, 0, 0);
  2025.     return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable));
  2026.     }
  2027. /***************************************************************************
  2028. *
  2029. * dec21x40Send - transmit an ethernet packet
  2030. *
  2031. * RETURNS: OK on success; and ERROR otherwise.
  2032. */
  2033. LOCAL STATUS dec21x40Send
  2034.     (
  2035.     DRV_CTRL *pDrvCtrl,
  2036.     M_BLK *pMblk
  2037.     )
  2038.     {
  2039.     DEC_TD * pTxD;
  2040.     char * pBuf;
  2041.     int len;
  2042.     int         s;
  2043.     DRV_LOG (DRV_DEBUG_TX, "S:0x%x ", pDrvCtrl->txIndex, 0, 0, 0, 0, 0);
  2044.     /* Gain exclusive access to transmit */
  2045.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  2046.     /* Get the next TXD */
  2047.     pTxD = dec21x40TxDGet (pDrvCtrl);
  2048.     pBuf = NET_BUF_ALLOC();
  2049.     if ((pTxD == NULL) || (pBuf == NULL))
  2050.         {
  2051. DRV_LOG (DRV_DEBUG_TX, "No available TxBufs n", 0, 0, 0, 0, 0, 0);
  2052. #ifdef INCLUDE_RFC_1213
  2053.         /* Old RFC 1213 mib2 interface */
  2054.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  2055. #else        
  2056.         /* New RFC 2233 mib2 interface */
  2057.         if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  2058.             {
  2059.             pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
  2060.                                                       M2_ctrId_ifOutErrors, 1);
  2061.             }
  2062. #endif
  2063.         END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  2064.         if (pBuf)
  2065.             NET_BUF_FREE (pBuf);
  2066.         if (!pDrvCtrl->txCleaning && !pDrvCtrl->txBlocked)
  2067.             dec21x40TxRingClean (pDrvCtrl);
  2068.         
  2069.         s = intLock();
  2070.         pDrvCtrl->txBlocked = TRUE;        /* transmitter not ready */
  2071.         intUnlock(s);
  2072.         return (END_ERR_BLOCK); /* just return without freeing mBlk chain */
  2073.         }
  2074.     /* copy and free the MBLK */
  2075.     len = netMblkToBufCopy (pMblk, pBuf, NULL);
  2076.     NET_MBLK_CHAIN_FREE (pMblk);
  2077.     /* setup the transmit buffer pointers */
  2078.     pTxD->tDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pBuf));
  2079.     pTxD->tDesc3 = 0;
  2080.     /* setup frame len */
  2081.     pTxD->tDesc1 &= PCISWAP (~TDESC1_TBS1_MSK);
  2082.     pTxD->tDesc1 |= PCISWAP (TDESC1_TBS1_PUT(len));
  2083.     /* transfer ownership to device */
  2084.     pTxD->tDesc0  = PCISWAP(TDESC0_OWN);      
  2085.     CACHE_PIPE_FLUSH();
  2086.     /* Save the buf info */
  2087.     pDrvCtrl->freeBuf[pDrvCtrl->txIndex].pClBuf    = pBuf;
  2088.     /* Advance our management index */
  2089.     pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds;
  2090.     if (DRV_FLAGS_ISSET(DEC_TX_KICKSTART))
  2091.         DEC_CSR_WRITE (CSR1, CSR1_TPD);
  2092.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  2093. #ifdef INCLUDE_RFC_1213
  2094.     /* Old RFC 1213 mib2 interface */
  2095.     /* update statistics */
  2096.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  2097.     
  2098. #endif /* INCLUDE_RFC_1213 */
  2099.     return (OK);
  2100.     }
  2101. /***************************************************************************
  2102. *
  2103. * dec21x40Recv - pass a received frame to the upper layer
  2104. *
  2105. *
  2106. * RETURNS: OK, always.
  2107. */
  2108. LOCAL STATUS dec21x40Recv
  2109.     (
  2110.     DRV_CTRL * pDrvCtrl,
  2111.     DEC_RD * pRxD
  2112.     )
  2113.     {
  2114.     END_OBJ * pEndObj = &pDrvCtrl->endObj;
  2115.     M_BLK_ID pMblk;      /* MBLK to send upstream */
  2116.     CL_BLK_ID pClBlk;     /* pointer to clBlk */
  2117.     char * pBuf;      /* A replacement buffer for the current RxD */
  2118.     char * pData;      /* Data pointer for the current RxD */
  2119.     char * pTmp;
  2120.     int      len;     /* Len of the current data */
  2121.     DRV_LOG (DRV_DEBUG_RX, ("R"), 0, 0, 0, 0, 0, 0);
  2122.     
  2123.     /* check for errors */
  2124.     if (pRxD->rDesc0 & PCISWAP(RDESC0_ES))
  2125.         {
  2126.         DRV_LOG (DRV_DEBUG_RX, ("- "), 0, 0, 0, 0, 0, 0);
  2127. #ifdef INCLUDE_RFC_1213
  2128.         /* Old RFC 1213 mib2 interface */
  2129.         END_ERR_ADD (pEndObj, MIB2_OUT_ERRS, +1);
  2130.         
  2131. #else
  2132.         /* New RFC 2233 mib2 interface */
  2133.         if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  2134.             {
  2135.             pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
  2136.                                                       M2_ctrId_ifInErrors, 1);
  2137.             }
  2138. #endif /* INCLUDE_RFC_1213 */
  2139.         goto cleanRxD;
  2140.         }
  2141.     DRV_LOG (DRV_DEBUG_RX, ("+ "), 0, 0, 0, 0, 0, 0);
  2142. #ifdef INCLUDE_RFC_1213
  2143.     /* Old RFC 1213 mib2 interface */
  2144.     END_ERR_ADD (pEndObj, MIB2_IN_UCAST, +1);
  2145.     
  2146. #endif /* INCLUDE_RFC_1213 */
  2147.     /* Allocate an MBLK, and a replacement buffer */
  2148.     pMblk = NET_MBLK_ALLOC();
  2149.     pBuf  = NET_BUF_ALLOC();
  2150.     pClBlk = NET_CL_BLK_ALLOC(); 
  2151.     if ((pMblk == NULL) || (pBuf == NULL) || (pClBlk == NULL))
  2152.         {
  2153. DRV_LOG (DRV_DEBUG_RX, "No available RxBufs n", 0, 0, 0, 0, 0, 0);
  2154. #ifdef INCLUDE_RFC_1213
  2155.         /* Old RFC 1213 mib2 interface */
  2156.         END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1);
  2157.         
  2158. #else
  2159.         /* New RFC 2233 mib2 interface */
  2160.         if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  2161.             {
  2162.             pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
  2163.                                                       M2_ctrId_ifInErrors, 1);
  2164.             }
  2165. #endif /* INCLUDE_RFC_1213 */
  2166.         if (pMblk)
  2167.             NET_MBLK_FREE (pMblk);
  2168.         if (pBuf)
  2169.             NET_BUF_FREE (pBuf);
  2170.         if (pClBlk)
  2171.             NET_CL_BLK_FREE (pClBlk);
  2172.         goto cleanRxD;
  2173.         }
  2174.     /* Get the data pointer and len from the current RxD */
  2175.     len   = DEC_FRAME_LEN_GET (PCISWAP (pRxD->rDesc0)) - ETH_CRC_LEN; 
  2176.     pData = (char *) PCISWAP (pRxD->rDesc3); /* buff virtual address */
  2177.     /*
  2178.      * The code above solves alignment problem when the CPU and the
  2179.      * ethernet chip don't accept longword unaligned addresses.
  2180.      * 
  2181.      * Pb: When the ethernet chip receives a packet from the network,
  2182.      * it needs a longword aligned buffer to copy the data. To process the
  2183.      * IP packet, MUX layer adds a SIZEOF_ETHERHEADER(0x14) offset to the
  2184.      * data buffer. So the CPU obtains a longword unaligned buffer and
  2185.      * a fault execption occurs when it reads "ip_src" and "ip_dst" fields 
  2186.      * in the IP structure (ip_src and ip_dst fields are longwords).
  2187.      *
  2188.      * The problem is solved copying the data in a new buffer in which
  2189.      * the IP structure is aligned.
  2190.      */  
  2191.     if (pDrvCtrl->offset != 0)
  2192. {
  2193. /* exchange buffer addresses */
  2194. pTmp = pData;
  2195. pData = pBuf;
  2196. pBuf = pTmp;
  2197. /* copy data in new unaligned buffer */
  2198.  
  2199. pData += pDrvCtrl->offset;
  2200. memcpy(pData, pBuf, len);
  2201.         }
  2202.     /* Restore orignal buffer address to be able to free it */
  2203.  
  2204.     pData -= pDrvCtrl->offset; 
  2205. #ifndef INCLUDE_RFC_1213
  2206.     /* New RFC 2233 mib2 interface */
  2207.     /* RFC 2233 mib2 counter update for incoming packet */
  2208.     if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  2209.         {
  2210.         pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,
  2211.                                                  M2_PACKET_IN, pData, len);
  2212.         }
  2213. #endif /* INCLUDE_RFC_1213 */
  2214.     /* Associate the data pointer with the MBLK */
  2215.     NET_CL_BLK_JOIN (pClBlk, pData, DEC_BUFSIZ);
  2216.     
  2217.     /* Associate the data pointer with the MBLK */
  2218.     NET_MBLK_CL_JOIN (pMblk, pClBlk);
  2219.     pMblk->mBlkHdr.mData += pDrvCtrl->offset; 
  2220.     pMblk->mBlkHdr.mFlags  |= M_PKTHDR; /* set the packet header */
  2221.     pMblk->mBlkHdr.mLen = len; /* set the data len */
  2222.     pMblk->mBlkPktHdr.len  = len; /* set the total len */
  2223.     pDrvCtrl->rxLen += len;
  2224.     /* Make cache consistent with memory */
  2225.     DEC_CACHE_INVALIDATE (pData, len);
  2226.     /* Install the new data buffer */
  2227.     pRxD->rDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pBuf));
  2228.     pRxD->rDesc3 = PCISWAP ((ULONG)pBuf); /* virtual buffer address */
  2229.     /* mark the descriptor ready to receive */
  2230.     pRxD->rDesc0 = PCISWAP (RDESC0_OWN);
  2231.     
  2232.     /* advance management index */
  2233.     pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds;
  2234.     CACHE_PIPE_FLUSH();
  2235.     /* send the frame to the upper layer, and possibly switch to system mode */
  2236.     END_RCV_RTN_CALL (pEndObj, pMblk);
  2237.     return (OK);
  2238. cleanRxD:
  2239.     /* mark the descriptor ready to receive */
  2240.     pRxD->rDesc0 = PCISWAP (RDESC0_OWN);
  2241.     
  2242.     CACHE_PIPE_FLUSH();
  2243.     /* advance management index */
  2244.     pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds;
  2245.     return (OK);
  2246.     }
  2247. /***************************************************************************
  2248. *
  2249. * dec21x40RxIntHandle - perform receive processing
  2250. *
  2251. * RETURNS: N/A
  2252. */
  2253. LOCAL void dec21x40RxIntHandle
  2254.     (
  2255.     DRV_CTRL * pDrvCtrl
  2256.     )
  2257.     {
  2258.     DEC_RD *pRxD;
  2259.     pDrvCtrl->rxHandling = TRUE;
  2260.     pDrvCtrl->rxLen = 0;
  2261.    
  2262.     while ((pRxD = dec21x40RxDGet (pDrvCtrl)) &&