dec21x40End.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:165k
源码类别:
VxWorks
开发平台:
C/C++
- /* dec21x40End.c - END-style DEC 21x40 PCI Ethernet network interface driver */
- /* Copyright 1984-2002 Wind River Systems, Inc. */
- #include "copyright_wrs.h"
- /*
- modification history
- --------------------
- 03r,30may02,sru Add run-time control of byte-swapping for PCI master
- operations
- 03q,13may02,rcs added loanBuf option to End Loan string. #SPR 73414
- 03p,13may02,rcs changed pDrvCtrl->pPhyInfo->phyMaxDelay to a multiple of
- sysClkRateGet() & referenced pDrvCtrl->pPhyInfo->phyDelayParm
- to sysClkRateGet(). SPR# 77012
- 03o,06may02,rcs corrected behaviour and documentation for when memBase != -1
- SPR# 75455
- 03n,06may02,rcs define all DRV_DEBUG flags and default DRV_LOG to display
- DRV_DEBUG_LOAD conditions. SPR# 75457
- 03m,22apr02,rcs added init of pDrvCtrl->txPollSendBuf to dec21x40InitMem()
- and changed dec21x40PollSend() to usepDrvCtrl->txPollSendBuf.
- SPR# 76102
- 03l,25mar02,pmr fixed usage of rDesc3 (SPR 73470, 34891).
- 03k,18jan02,rcs facilitated common source base with either RFC 1213 or
- RFC 2233 depending on INCLUDE_RFC_1213 macro.
- 03j,14jan02,dat Removing warnings from Diab compiler
- 03i,20jul01,rcs used LE_BYTE_SWAP in dec21140EnetAddrGet() to return correct
- enetaddr for little endian archs (SPR# 69093)
- 03h,28aug01,ann adding the code that copies the pMib2Tbl contents into
- mib2Tbl for backward compatibility - SPR 69697 & 69758
- 03g,16aug01,ann providing the fix for SPR 69673
- 03f,13jul01,ann eliminating the mibStyle variable and accomodating the
- END_MIB_2233 flag in the END flags field
- 03e,15jun01,rcs set dec21x40Start() taskDelay to sysClkRateGet() / 30
- 03d,29mar01,spm merged changes from version 02h of tor2_0.open_stack
- branch (wpwr VOB, base 02d) for unified code base
- 03c,23feb01,rcs increased taskDelay to 2 in dec21x40Start() to ensure adequate
- time for the software reset of the dec21x40 device to complete.
- SPR# 64192
- 03b,14feb01,rcs moved intConnect to before the chip's interupts are enabled
- SPR# 31314.
- 03a,13feb01,rcs saved and restored CSR0 before and after software reset in
- dec21x40Start() SPR# 64192
- 02z,08feb01,rcs moved decode non-register user flags to before
- dec21x40EnetAddrGet() call. SPR# 63881
- 02y,14dec00,rcs removed reference to sysDelay()
- 02x,15nov00,jpd added _func_dec2114xIntAck (SPR #62330).
- 02w,25oct00,dat SPR 34891 removing PHYS_TO_VIRT translations
- 02v,20sep00,dat SPR 32058, allow for alternate intConnect rtn
- 02u,17jul00,bri Standardisation
- 02t,17apr00,an Added support to force HomePNA speed and power via user flags.
- 02s,13apr00,an Added support for special dec21145 media change technique.
- The driver must be called with DEC_USR_HPNA_PREFER_10BT
- user flag set to select this mode. This is NOT the default
- mode of operation.
- 02r,18feb00,an Added support for dec21145. See explaination below.
- 02q,11jun00,ham removed reference to etherLib.
- 02p,08may00,jgn SPR 31198, Various fixes for use on ARM + Kingston KNE100TX
- (MII) card
- 02o,24apr00,dmw Fixed extended format block type 2 selection.
- 02n,24apr00,dmw Added Full Duplex support for adapters with PHY's.
- 02m,24mar00,dat fixed string handling, added fix to reset code
- 02l,01mar00,stv fixed backward compatibility issues for the alignment fix.Also
- corrected documentation & updated a debug message.
- 02k,24feb00,stv made a selective merge to add alignment fix.
- 02j,27jan00,dat fixed use of NULL
- 02i,08nov99,cn integrated with miiLib. Also fixed SPR #21116, #28315.
- 02h,01oct99,pfl Fix for spr 22196 was missing, added it again.
- 02g,16sep99,stv Fixed errors due to usage of DRV_LOG macro.
- 02f,01sep99,dat SPR 28573 and Debug clean up.
- 02e,17aug99,dmw Added MII/Phy force modes.
- 02d,11mar99,tm Added MII/Phy r/w for 2114x link status check (SPR 22196)
- 02c,02mar99,tm txRingClean in ISR to improve small pkt throughput (SPR 23950)
- 02b,01feb99,scb Added support for dec21143. (SPR 22887)
- 02a,30sep98,dbt Adding missing code in poll receive routine.
- 01z,22sep98,dat SPR 22325, system mode transition + lint fixes.
- 01y,07aug98,cn updated documentation about user flags.
- 01w,31jul98,cn removed setting CSR6_FD in xxxMediaSelect [SPR# 21683].
- Also moved some indeces setting in xxxStart [SPR#21557].
- 01v,20apr98,map preserve CSR6_PS in xxxChipReset [SPR# 21013]
- 01u,10dec97,kbw man page fiddlings
- 01t,08dec97,gnn END code review fixes.
- 01s,20nov97,gnn fixed spr#9555, configurable TDS and RDS.
- 01r,19oct97,vin moved swapping of loaned buffer before END_RCV_RTN_CALL
- 01q,17oct97,vin removed extra free.
- 01p,09oct97,vin delete unwanted frees in PollSend routine
- 01o,07oct97,vin fixed multicasting, MIB MTU size to ETHER_MTU
- 01n,25sep97,gnn SENS beta feedback fixes
- 01m,24sep97,vin added clBlk related calls
- 01l,02sep97,gnn fixed a race condition in the txRestart handling.
- 01k,25aug97,vin adjusted cluster mem size.
- 01j,22aug97,vin fixed initialization of cluster mem area.
- 01i,22aug97,gnn fixed a bug in polled mode.
- 01h,21aug97,vin added changes for newBuffering API
- 01g,12aug97,gnn changes necessitated by MUX/END update.
- 01f,08aug97,map fixed muxBufInit for user-specified bufpool.
- added ilevel arg to sysLanIntDisable().
- update collision statistics.
- added more flags to userFlags.
- 01e,10jun97,map renamed funcDec21x40MediaSelect to _func_dec21x40MediaSelect.
- 01d,28may97,kbw general text edit
- map added DEC SROM support for media configuration.
- 01c,23apr97,map cleaned up; replaced SWAP_SHORT with PCISWAP_SHORT.
- 01b,16apr97,map added support for dec21140.
- 01a,07apr97,map modified if_dc.c to END style.
- */
- /*
- This module implements a DEC 21x40 PCI Ethernet network interface driver and
- supports both the 21040, 21140, 21143, 21145 versions of the chip.
- The DEC 21x40 PCI Ethernet controller is little endian because it interfaces
- with a little-endian PCI bus. Although PCI configuration for a device is
- handled in the BSP, all other device programming and initialization needs
- are handled in this module.
- This driver is designed to be moderately generic. Without modification, it can
- operate across the full range of architectures and targets supported by VxWorks.
- To achieve this, the driver requires a few external support routines as well
- as several target-specific parameters. These parameters, and the mechanisms
- used to communicate them to the driver, are detailed below. If any of the
- assumptions stated below are not true for your particular hardware, you need
- to modify the driver before it can operate correctly on your hardware.
- On the 21040, the driver configures the 10BASE-T interface by default,waits for
- two seconds, and checks the status of the link. If the link status indicates
- failure, AUI interface is configured.
- On other versions of the 21x40 family, the driver reads media information from
- a DEC serial ROM and configures the media. To configure the media on targets
- that do not support a DEC format serial ROM, the driver calls the
- target-specific media-select routine referenced in
- the `_func_dec21x40MediaSelect' hook.
- The 21145 supports HomePNA 1.0 (Home Phone Line) Networking as well as
- 10Base-T. The HomePNA port can be forced to 1 MB/sec or 0.7 MB/sec mode
- via the DEC_USR_HPNA_FORCE_FAST and DEC_USR_HPNA_FORCE_SLOW user flags,
- respectively. If these flags are not set then the speed is set using
- the SROM settings.
- Unlike the Ethernet phys, the HomePNA phy can not determine link failure and
- therefore will never notify the driver when the HomePNA port is
- disconnected. However, to allow media change, the driver can be configured
- to ALWAYS perfer 10Base-T over HomePNA by interrupting on 10Base-T link pass
- interrupt. Upon 10Base-T link failure, the driver will revert back to HomePNA.
- Since this method violates the preference rules outlined in Intel/DEC SROM
- format spec, this is not the default mode of operation.
- The driver must be started with DEC_USR_HPNA_PREFER_10BT user flag set to
- set the driver into this mode.
- The driver supports big-endian or little-endian architectures (as a
- configurable option). The driver also and contains error recovery code
- that handles known device errata related to DMA activity.
- Big-endian processors can be connected to the PCI bus through some controllers
- that take care of hardware byte swapping. In such cases, all the registers
- which the chip DMAs to have to be swapped and written to, so that when the
- hardware swaps the accesses, the chip would see them correctly. The chip still
- has to be programmed to operate in little endian mode as it is on the PCI
- bus. If the cpu board hardware automatically swaps all the accesses to and
- from the PCI bus, then input and output byte stream need not be swapped.
- BOARD LAYOUT
- This device is on-board. No jumpering diagram is necessary.
- EXTERNAL INTERFACE
- The driver provides one standard external interface, dec21x40EndLoad(). As
- input, this function expects a string of colon-separated parameters. The
- parameters should be specified as hexadecimal strings (optionally preceded
- by "0x" or a minus sign "-"). Although the parameter string is parsed
- using endTok_r(), each parameter is converted from string to binary by a
- call to:
- .CS
- strtoul(parameter, NULL, 16).
- .CE
- The format of the parameter string is:
- "<deviceAddr>:<pciAddr>:<iVec>:<iLevel>:<numRds>:<numTds>:
- <memBase>:<memSize>:<userFlags>:<phyAddr>:<pPhyTbl>:<phyFlags>:<offset>:
- <loanBufs>:<drvFlags>"
- TARGET-SPECIFIC PARAMETERS
- .IP <deviceAddr>
- This is the base address at which the hardware device registers are located.
- .IP <pciAddr>
- This parameter defines the main memory address over the PCI bus. It is used to
- translate a physical memory address into a PCI-accessible address.
- .IP <iVec>
- This is the interrupt vector number of the hardware interrupt generated by
- this Ethernet device. The driver uses intConnect() to attach an interrupt
- handler for this interrupt. The BSP can change this by modifying the global
- pointer dec21x40IntConnectRtn with the desired routines (usually pciIntConnect).
- .IP <iLevel>
- This parameter defines the level of the hardware interrupt.
- .IP <numRds>
- The number of receive descriptors to use. This controls how much data
- the device can absorb under load. If this is specified as NONE (-1),
- the default of 32 is used.
- .IP <numTds>
- The number of transmit descriptors to use. This controls how much data
- the device can absorb under load. If this is specified as NONE (-1) then
- the default of 64 is used.
- .IP <memBase>
- This parameter specifies the base address of a DMA-able cache-free
- pre-allocated memory region for use as a memory pool for transmit/receive
- descriptors and buffers including loaner buffers. If there is no pre-allocated
- memory available for the driver, this parameter should be -1 (NONE). In which
- case, the driver allocates cache safe memory for its use using cacheDmaAlloc().
- .IP <memSize>
- The memory size parameter specifies the size of the pre-allocated memory
- region. If memory base is specified as NONE (-1), the driver ignores this
- parameter. When specified this value must account for transmit/receive
- descriptors and buffers and loaner buffers
- .IP <userFlags>
- User flags control the run-time characteristics of the Ethernet
- chip. Most flags specify non default CSR0 and CSR6 bit values. Refer to
- dec21x40End.h for the bit values of the flags and to the device hardware
- reference manual for details about device capabilities, CSR6 and CSR0.
- .IP <phyAddr>
- This optional parameter specifies the address on the MII (Media Independent
- Interface) bus of a MII-compliant PHY (Physical Layer Entity). The module
- that is responsible for optimally configuring the media layer will start
- scanning the MII bus from the address in <phyAddr>. It will retrieve the
- PHY's address regardless of that, but, since the MII management interface,
- through which the PHY is configured, is a very slow one, providing an
- incorrect or invalid address may result in a particularly long boot process.
- If the flag <DEC_USR_MII> is not set, this parameter is ignored.
- .IP <pPhyTbl>
- This optional parameter specifies the address of a auto-negotiation table
- for the PHY being used.
- The user only needs to provide a valid value for this parameter
- if he wants to affect the order how different technology abilities are
- negotiated.
- If the flag <DEC_USR_MII> is not set, this parameter is ignored.
- .IP <phyFlags>
- This optional parameter allows the user to affect the PHY's configuration
- and behaviour. See below, for an explanation of each MII flag.
- If the flag <DEC_USR_MII> is not set, this parameter is ignored.
- .IP <offset>
- This parameter defines the offset which is used to solve alignment problem.
- .IP <loanBufs>
- This optional parameter allows the user to select the amount of loaner buffers
- allocated for the driver's net pool to be loaned to the stack in receive
- operations. The default number of loaner buffers is 32. The number of loaner
- buffers must be accounted for when calculating the memory size specified by
- memSize.
- .IP <drvFlags>
- This optional parameter allows the user to enable driver-specific features.
- Device Type: Although the default device type is DEC 21040, specifying
- the DEC_USR_21140 flag bit turns on DEC 21140 functionality.
- Ethernet Address: The Ethernet address is retrieved from standard serial
- ROM on both DEC 21040, and DEC 21140 devices. If the retrieve from ROM fails,
- the driver calls the sysDec21x40EnetAddrGet() BSP routine.
- Specifying DEC_USR_XEA flag bit tells the driver should, by default,
- retrieve the Ethernet address using the sysDec21x40EnetAddrGet() BSP routine.
- Priority RX processing: The driver programs the chip to process the
- transmit and receive queues at the same priority. By specifying DEC_USR_BAR_RX,
- the device is programmed to process receives at a higher priority.
- TX poll rate: By default, the driver sets the Ethernet chip into a
- non-polling mode. In this mode, if the transmit engine is idle, it is
- kick-started every time a packet needs to be transmitted. Alternatively,
- the chip can be programmed to poll for the next available transmit
- descriptor if the transmit engine is in idle state. The poll rate is
- specified by one of DEC_USR_TAP_<xxx> flags.
- Cache Alignment: The DEC_USR_CAL_<xxx> flags specify the address
- boundaries for data burst transfers.
- DMA burst length: The DEC_USR_PBL_<xxx> flags specify the maximum
- number of long words in a DMA burst.
- PCI multiple read: The DEC_USR_RML flag specifies that a device
- supports PCI memory-read-multiple.
- Full Duplex Mode: When set, the DEC_USR_FD flag allows the device to
- work in full duplex mode, as long as the PHY used has this
- capability. It is worth noting here that in this operation mode,
- the dec21x40 chip ignores the Collision and the Carrier Sense signals.
- MII interface: some boards feature an MII-compliant Physical Layer Entity
- (PHY). In this case, and if the flag <DEC_USR_MII> is set, then the optional
- fields <phyAddr>, <pPhyTbl>, and <phyFlags> may be used to affect the
- PHY's configuration on the network.
- 10Base-T Mode: when the flag <DEC_USR_MII_10MB> is set, then the PHY will
- negotiate this technology ability, if present.
- 100Base-T Mode: when the flag <DEC_USR_MII_100MB> is set, then the PHY will
- negotiate this technology ability, if present.
- Half duplex Mode: when the flag <DEC_USR_MII_HD> is set, then the PHY will
- negotiate this technology ability, if present.
- Full duplex Mode: when the flag <DEC_USR_MII_FD> is set, then the PHY will
- negotiate this technology ability, if present.
- Auto-negotiation: the driver's default behaviour is to enable auto-negotiation,
- as defined in "IEEE 802.3u Standard". However, the user may disable this
- feature by setting the flag <DEC_USR_MII_NO_AN> in the <phyFlags> field of
- the load string.
- Auto-negotiation table: the driver's default behaviour is to enable the
- standard auto-negotiation process, as defined in "IEEE 802.3u Standard".
- However, the user may wish to force the PHY to negotiate its technology
- abilities a subset at a time, and according to a particular order. The
- flag <DEC_USR_MII_AN_TBL> in the <phyFlags> field may be used to tell the
- driver that the PHY should negotiate its abilities as dictated by the
- entries in the <pPhyTbl> of the load string.
- If the flag <DEC_USR_MII_NO_AN> is set, this parameter is ignored.
- Link monitoring: this feature enables the netTask to periodically monitor
- the PHY's link status for link down events. If any such event occurs, and
- if the flag <DEC_USR_MII_BUS_MON> is set, then a driver's optionally provided
- routine is executed, and the link is renegotiated.
- Transmit treshold value: The DEC_USR_THR_XXX flags enable the user to
- choose among different threshold values for the transmit FIFO.
- Transmission starts when the frame size within the transmit FIFO is
- larger than the treshold value. This should be selected taking into
- account the actual operating speed of the PHY. Again, see the device
- hardware reference manual for details.
- EXTERNAL SUPPORT REQUIREMENTS
- This driver requires three external support functions and provides a hook
- function:
- .IP sysLanIntEnable()
- .CS
- void sysLanIntEnable (int level)
- .CE
- This routine provides a target-specific interface for enabling Ethernet device
- interrupts at a specified interrupt level.
- .IP sysLanIntDisable()
- .CS
- void sysLanIntDisable (void)
- .CE
- This routine provides a target-specific interface for disabling Ethernet device
- interrupts.
- .IP sysDec21x40EnetAddrGet()
- .CS
- STATUS sysDec21x40EnetAddrGet (int unit, char *enetAdrs)
- .CE
- This routine provides a target-specific interface for accessing a device
- Ethernet address.
- .IP `_func_dec21x40MediaSelect'
- .CS
- FUNCPTR _func_dec21x40MediaSelect
- .CE
- If `_func_dec21x40MediaSelect' is NULL, this driver provides a default
- media-select routine that reads and sets up physical media using the
- configuration information from a Version 3 DEC Serial ROM. Any other media
- configuration can be supported by initializing `_func_dec21x40MediaSelect',
- typically in sysHwInit(), to a target-specific media select routine.
- A media select routine is typically defined as:
- .ne 8
- .CS
- STATUS decMediaSelect
- (
- DEC21X40_DRV_CTRL * pDrvCtrl, /@ driver control @/
- UINT * pCsr6Val /@ CSR6 return value @/
- )
- {
- ...
- }
- .CE
- The <pDrvCtrl> parameter is a pointer to the driver control structure that this
- routine can use to access the Ethenet device. The driver control structure
- member 'mediaCount', is initialized to 0xff at startup, while the other media
- control members ('mediaDefault', 'mediaCurrent', and 'gprModeVal') are
- initialized to zero. This routine can use these fields in any manner.
- However, all other driver control structure members should be considered
- read-only and should not be modified.
- This routine should reset, initialize, and select an appropriate media. It
- should also write necessary the CSR6 bits (port select, PCS, SCR, and full
- duplex) to the memory location pointed to by <pCsr6Val>. The driver uses
- this value to program register CSR6. This routine should return OK or ERROR.
- .iP "VOIDFUNCPTR _func_dec2114xIntAck" "" 9 -1
- This driver does acknowledge the LAN interrupts. However if the board hardware
- requires specific interrupt acknowledgement, not provided by this driver,
- the BSP should define such a routine and attach it to the driver via
- _func_dec2114xIntAck.
- PCI ID VALUES
- The dec21xxx series chips are now owned and manufactured by Intel. Chips may
- be identified by either PCI Vendor ID. ID value 0x1011 for Digital, or
- ID value 0x8086 for Intel. Check the Intel web site for latest information.
- The information listed below may be out of date.
- .CS
- Chip Vendor ID Device ID
- dec 21040 0x1011 0x0002
- dec 21041 0x1011 0x0014
- dec 21140 0x1011 0x0009
- dec 21143 0x1011 0x0019
- dec 21145 0x8086 0x0039
- .CE
- SEE ALSO: ifLib,
- .I "DECchip 21040 Ethernet LAN Controller for PCI,"
- .I "Digital Semiconductor 21140A PCI Fast Ethernet LAN Controller,"
- .I "Using the Digital Semiconductor 21140A with Boot ROM, Serial ROM,
- and External Register: An Application Note"
- .I "Intel 21145 Phoneline/Ethernet LAN Controller Hardware Ref. Manual"
- .I "Intel 21145 Phoneline/Ethernet LAN Controller Specification Update"
- INTERNAL
- We modified the driver to use rDesc3 to hold the virtual address of the buffer.
- This allows us to eliminate all PHYS_TO_VIRT translations that were previously
- used. PHYS_TO_VIRT translations are extremely costly in T3.0.
- */
- /* includes */
- #include "vxWorks.h"
- #include "wdLib.h"
- #include "iv.h"
- #include "vme.h"
- #include "net/mbuf.h"
- #include "net/unixLib.h"
- #include "net/protosw.h"
- #include "sys/socket.h"
- #include "sys/ioctl.h"
- #include "errno.h"
- #include "memLib.h"
- #include "intLib.h"
- #include "net/route.h"
- #include "errnoLib.h"
- #include "cacheLib.h"
- #include "logLib.h"
- #include "netLib.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "sysLib.h"
- #include "net/systm.h"
- #include "sys/times.h"
- #include "net/if_subr.h"
- #include "netinet/if_ether.h"
- #include "miiLib.h"
- #include "drv/end/dec21x40End.h"
- #undef ETHER_MAP_IP_MULTICAST
- #include "etherMultiLib.h"
- #include "end.h"
- #include "endLib.h"
- #include "lstLib.h"
- #include "semLib.h"
- /* defines */
- #define DRV_DEBUG_OFF 0x0000
- #define DRV_DEBUG_RX 0x0001
- #define DRV_DEBUG_TX 0x0002
- #define DRV_DEBUG_INT 0x0004
- #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
- #define DRV_DEBUG_POLL_RX 0x0008
- #define DRV_DEBUG_POLL_TX 0x0010
- #define DRV_DEBUG_IOCTL 0x0040
- #define DRV_DEBUG_LOAD 0x0020
- #define DRV_DEBUG_INIT 0x0100
- #define DRV_DEBUG_MII 0x0080
- #define DRV_DEBUG_POLL_REDIR 0x10000
- #define DRV_DEBUG_LOG_NVRAM 0x20000
- #define DRV_DEBUG_ALL 0xffffffff
- #undef DRV_DEBUG
- #ifdef DRV_DEBUG
- int decTxInts=0;
- int decRxInts=0;
- int decTxErrors = 0;
- int decRxErrors = 0;
- int decTxTpsErrors = 0;
- int decTxBufErrors = 0;
- int decTxTjtErrors = 0;
- int decTxUnfErrors = 0;
- int decTxLcErrors = 0;
- int decRxBufErrors = 0;
- int decRxRpsErrors = 0;
- int decRxWtErrors = 0;
- int decDescErrors = 0;
- IMPORT int dataDump();
- IMPORT int eAdrsDisplay();
- #endif /*DRV_DEBUG*/
- /* default to enable DRV_DEBUG_LOAD to display initialization errors. */
- int decDebug = DRV_DEBUG_INIT;
- #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
- if (decDebug & FLG)
- logMsg(X0, X1, X2, X3, X4, X5, X6);
- #define END_FLAGS_ISSET(pEnd, setBits)
- ((pEnd)->flags & (setBits))
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- #define END_HADDR(pEnd)
- ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
- #define END_HADDR_LEN(pEnd)
- ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
- #else /* Then RFC 2233 */
- /* New RFC 2233 mib2 interface */
- #define END_HADDR(pEnd)
- ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.phyAddress)
- #define END_HADDR_LEN(pEnd)
- ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.addrLength)
- #endif /* INCLUDE_RFC_1213 */
- #define DEC_SPEED_1 1000000 /* 1 Mbps HomePNA */
- #define DEC_SPEED_10 10000000 /* 10 Mbps */
- #define DEC_SPEED_100 100000000 /* 100 Mbps */
- #define DEC_SPEED_DEF DEC_SPEED_10
- #define EADDR_LEN 6 /* ethernet address length */
- #define DEC_PKT_SIZE (ETHERMTU + SIZEOF_ETHERHEADER + EADDR_LEN)
- #define DEC_LOOPS_PER_NS 4
- #define DEC_NSDELAY(nsec) do {
- volatile int nx = 0;
- volatile int loop = ((nsec)*dec21x40Loops);
- for (nx = 0; nx < loop; nx++)
- ;
- } while (0)
- #define DEC_BUF_ALLOC_ROUTINE
- (FUNCPTR) (DRV_FLAGS_ISSET(DEC_MEMOWN) ?
- cacheDmaMalloc : NULL)
- #define DEC_BUF_POOL_ADRS
- (char *)(DRV_FLAGS_ISSET(DEC_MEMOWN) ?
- NULL:(pDrvCtrl->txRing + pDrvCtrl->numTds))
- /* DRV_CTRL flags access macros */
- #define DRV_FLAGS_SET(setBits)
- (pDrvCtrl->flags |= (setBits))
- #define DRV_FLAGS_ISSET(setBits)
- (pDrvCtrl->flags & (setBits))
- #define DRV_FLAGS_CLR(clrBits)
- (pDrvCtrl->flags &= ~(clrBits))
- #define DRV_FLAGS_GET()
- (pDrvCtrl->flags)
- /* DRV_CTRL user flags access macros */
- #define DRV_USR_FLAGS_SET(setBits)
- (pDrvCtrl->usrFlags |= (setBits))
- #define DRV_USR_FLAGS_ISSET(setBits)
- (pDrvCtrl->usrFlags & (setBits))
- #define DRV_USR_FLAGS_CLR(clrBits)
- (pDrvCtrl->usrFlags &= ~(clrBits))
- #define DRV_USR_FLAGS_GET()
- (pDrvCtrl->usrFlags)
- #define DRV_PHY_FLAGS_ISSET(setBits)
- (pDrvCtrl->miiPhyFlags & (setBits))
- /* Cache macros */
- #define DEC_CACHE_INVALIDATE(address, len)
- CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
- #define DEC_CACHE_VIRT_TO_PHYS(address)
- CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
- #define DEC_CACHE_PHYS_TO_VIRT(address)
- CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
- /* memory to PCI address translation macros */
- #define PCI_TO_MEM_PHYS(pciAdrs)
- (((ULONG)(pciAdrs)) - (pDrvCtrl->pciMemBase))
- #define DEC_PCI_TO_VIRT(pciAdrs)
- DEC_CACHE_PHYS_TO_VIRT (PCI_TO_MEM_PHYS (pciAdrs))
- #define MEM_TO_PCI_PHYS(memAdrs)
- (((ULONG)(memAdrs)) + (pDrvCtrl->pciMemBase))
- #define DEC_VIRT_TO_PCI(vAdrs)
- MEM_TO_PCI_PHYS (DEC_CACHE_VIRT_TO_PHYS (vAdrs))
- #ifndef TCP_MSS
- #define TCP_MSS 536 /* TCP maximum segment size */
- #endif
- #define RWIN (TCP_MSS * 4) /* Receive window size */
- /*
- * CSR access macros
- *
- * To optimize CSR accesses, redefine DEC_CSR_READ and
- * DEC_CSR_WRITE macros in a wrapper file.
- */
- #ifndef DEC_CSR_READ
- #define DEC_CSR_READ(csr)
- dec21x40CsrRead(pDrvCtrl, (csr))
- #endif /* DEC_CSR_READ */
- #ifndef DEC_CSR_WRITE
- #define DEC_CSR_WRITE(csr,val)
- dec21x40CsrWrite(pDrvCtrl, (csr), (val))
- #endif /* DEC_CSR_WRITE */
- #define DEC_CSR_UPDATE(csr,val)
- DEC_CSR_WRITE((csr), DEC_CSR_READ(csr) | (val))
- #define DEC_CSR_RESET(csr,val)
- DEC_CSR_WRITE((csr), DEC_CSR_READ(csr) & ~(val))
- #define DEC_SROM_CMD_WRITE(adrs,delay)
- do {
- DEC_CSR_WRITE(CSR9, CSR9_21140_SR | CSR9_21140_WR | (adrs));
- DEC_NSDELAY (delay);
- } while (0)
- #define DEC_SROM_CMD_READ()
- ((DEC_CSR_READ(CSR9) & 0x8) >> 3)
- /* MII read/write access macros */
- #define CSR9_MII_WR 0x00000000
- #define DEC_MII_BIT_READ(pBData)
- do {
- DEC_CSR_WRITE (CSR9, CSR9_21140_MII | CSR9_21140_RD);
- DEC_NSDELAY (100);
- DEC_CSR_WRITE (CSR9, CSR9_21140_MII | CSR9_21140_RD | CSR9_21140_MDC);
- DEC_NSDELAY (100);
- *(pBData) |= CSR9_MII_DBIT_RD (DEC_CSR_READ (CSR9));
- } while (0)
- #define DEC_MII_BIT_WRITE(data)
- do {
- DEC_CSR_WRITE (CSR9, CSR9_MII_DBIT_WR(data) |
- CSR9_MII_WR | CSR9_21140_WR);
- DEC_NSDELAY (100);
- DEC_CSR_WRITE (CSR9, CSR9_MII_DBIT_WR(data) |
- CSR9_MII_WR | CSR9_21140_WR | CSR9_21140_MDC);
- DEC_NSDELAY (100);
- } while (0)
- #define DEC_MII_RTRISTATE
- do {
- int retVal;
- DEC_MII_BIT_READ (&retVal);
- } while (0)
- #define DEC_MII_WTRISTATE
- do {
- DEC_MII_BIT_WRITE(0x1);
- DEC_MII_BIT_WRITE(0x0);
- } while (0)
- #define DEC_MII_WRITE(data, bitCount)
- do {
- int i=(bitCount);
- while (i--)
- DEC_MII_BIT_WRITE (((data) >> i) & 0x1);
- } while (0)
- #define DEC_MII_READ(pData, bitCount)
- do {
- int i=(bitCount);
- while (i--)
- {
- *(pData) <<= 1;
- DEC_MII_BIT_READ (pData);
- }
- } while (0)
- /*
- * Default macro definitions for BSP interface.
- * These macros can be redefined in a wrapper file, to generate
- * a new module with an optimized interface.
- */
- #ifndef SYS_INT_CONNECT
- #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)
- do {
- int vector = pDrvCtrl->ivec;
- if (!pDrvCtrl->intrConnect)
- {
- pDrvCtrl->intrConnect = TRUE;
- *pResult = (*dec21x40IntConnectRtn) (
- (VOIDFUNCPTR *)INUM_TO_IVEC (vector),
- (rtn), (int)(arg));
- }
- } while (0)
- #endif /*SYS_INT_CONNECT*/
- #ifndef SYS_INT_DISCONNECT
- #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)
- do {
- /* set pDrvCtrl->intrConnect to FALSE if appropriate */
- *pResult = OK;
- } while (0)
- #endif /*SYS_INT_DISCONNECT*/
- #ifndef SYS_INT_ENABLE
- #define SYS_INT_ENABLE(pDrvCtrl)
- do {
- IMPORT void sysLanIntEnable();
- sysLanIntEnable (pDrvCtrl->ilevel);
- } while (0)
- #endif /*SYS_INT_ENABLE*/
- #ifndef SYS_INT_DISABLE
- #define SYS_INT_DISABLE(pDrvCtrl)
- do {
- IMPORT void sysLanIntDisable();
- sysLanIntDisable (pDrvCtrl->ilevel);
- } while (0)
- #endif /*SYS_INT_DISABLE*/
- #define END_MIB_SPEED_SET(pEndObj, speed)
- ((pEndObj)->mib2Tbl.ifSpeed=speed)
- #define NET_BUF_ALLOC()
- netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->clPoolId)
- #define NET_BUF_FREE(pBuf)
- netClFree (pDrvCtrl->endObj.pNetPool, pBuf)
- #define NET_MBLK_ALLOC()
- mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)
- #define NET_MBLK_FREE(pMblk)
- netMblkFree (pDrvCtrl->endObj.pNetPool, (M_BLK_ID)pMblk)
- #define NET_CL_BLK_ALLOC()
- clBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)
- #define NET_CL_BLK_FREE(pClblk)
- clBlkFree (pDrvCtrl->endObj.pNetPool, (CL_BLK_ID)pClBlk)
- #define NET_MBLK_BUF_FREE(pMblk)
- netMblkClFree ((M_BLK_ID)pMblk)
- #define NET_MBLK_CHAIN_FREE(pMblk)
- do {
- M_BLK *pNext;
- pNext=pMblk;
- while (pNext)
- pNext=NET_MBLK_BUF_FREE (pNext);
- } while (0)
- #define NET_MBLK_CL_JOIN(pMblk, pClBlk)
- netMblkClJoin ((pMblk), (pClBlk))
- #define NET_CL_BLK_JOIN(pClBlk, pBuf, len)
- netClBlkJoin ((pClBlk), (pBuf), (len), NULL, 0, 0, 0)
- #define DRV_CTRL DEC21X40_DRV_CTRL
- /* structure sizes */
- #define DRV_CTRL_SIZ sizeof(DRV_CTRL)
- #define RD_SIZ sizeof(DEC_RD)
- #define TD_SIZ sizeof(DEC_TD)
- /* locals */
- /* Default network buffer configuration */
- int dec21x40Loops = DEC_LOOPS_PER_NS; /* spin loops per nsec */
- FUNCPTR dec21x40IntConnectRtn = intConnect;
- /* constant data to set PHY control register */
- LOCAL const UINT dcForcePhyModes[] =
- {
- MII_CR_100 | MII_CR_FDX, /* 100FD */
- MII_CR_100, /* 100HD */
- MII_CR_FDX, /* 10FD */
- 0, /* 10HD */
- -1
- } ;
- /* forward declarations */
- LOCAL STATUS dec21x40InitParse (DRV_CTRL *pDrvCtrl, char *InitString);
- LOCAL STATUS dec21x40InitMem (DRV_CTRL *pDrvCtrl);
- LOCAL STATUS dec21x40IASetup (DRV_CTRL *pDrvCtrl);
- LOCAL void dec21x40ModeSet (DRV_CTRL *pDrvCtrl);
- LOCAL int dec21x40HashIndex (char *eAddr);
- LOCAL void dec21x40Int (DRV_CTRL *pDrvCtrl);
- LOCAL STATUS dec21x40Recv (DRV_CTRL *pDrvCtrl, DEC_RD *rmd);
- LOCAL STATUS dec21x40ChipReset (DRV_CTRL *pDrvCtrl);
- LOCAL void dec21040AuiTpInit (DRV_CTRL *pDrvCtrl);
- LOCAL void dec21x40CsrWrite (DRV_CTRL *pDrvCtrl, int reg, ULONG value);
- LOCAL ULONG dec21x40CsrRead (DRV_CTRL *pDrvCtrl, int reg);
- LOCAL STATUS dec21x40EnetAddrGet (DRV_CTRL *pDrvCtrl, char *enetAdrs);
- LOCAL STATUS dec21040EnetAddrGet (DRV_CTRL *pDrvCtrl, char *enetAdrs);
- LOCAL STATUS dec21140EnetAddrGet (DRV_CTRL *pDrvCtrl, char *enetAdrs);
- LOCAL void dec21x40Restart (DRV_CTRL *pDrvCtrl);
- LOCAL STATUS dec21x40MediaChange (DRV_CTRL *pDrvCtrl);
- LOCAL DEC_TD * dec21x40TxDGet (DRV_CTRL *pDrvCtrl);
- LOCAL DEC_RD * dec21x40RxDGet (DRV_CTRL *pDrvCtrl);
- LOCAL void dec21x40TxRingClean (DRV_CTRL *pDrvCtrl);
- LOCAL void dec21x40RxIntHandle (DRV_CTRL *pDrvCtrl);
- LOCAL STATUS dec21140MediaSelect (DRV_CTRL *pDrvCtrl, UINT *pCsr6Val);
- LOCAL STATUS dec21143MediaSelect (DRV_CTRL *pDrvCtrl, UINT *pCsr6Val);
- LOCAL STATUS dec21145DecodeExt7InfoBlock ( DRV_CTRL *pDrvCtrl,
- UCHAR * pInfoBlock);
- LOCAL STATUS dec21145MediaSelect (DRV_CTRL *pDrvCtrl, UINT *pCsr6Val);
- LOCAL STATUS dec21x40PhyPreInit (DRV_CTRL *pDrvCtrl, UCHAR * pInfoBlock);
- LOCAL STATUS dec21x40MiiInit (DRV_CTRL *pDrvCtrl, UINT *pCsr6Val,
- UCHAR * pInfoBlock);
- LOCAL STATUS dec21x40MiiRead ( DRV_CTRL *pDrvCtrl, UINT8 phyAdrs, UINT8 phyReg,
- UINT16 *pRetVal);
- LOCAL STATUS dec21x40MiiWrite (DRV_CTRL *pDrvCtrl, UINT8 phyAdrs, UINT8 phyReg,
- USHORT data);
- /* externals */
- IMPORT STATUS sysDec21x40EnetAddrGet (int unit, char *enetAdrs);
- /* globals */
- USHORT dec21140SromWordRead (DRV_CTRL *pDrvCtrl, UCHAR lineCnt);
- FUNCPTR _func_dec21x40MediaSelect = (FUNCPTR) NULL;
- VOIDFUNCPTR _func_dec2114xIntAck = (VOIDFUNCPTR) NULL;
- #ifdef DRV_DEBUG
- #include "netShow.h"
- IMPORT void netPoolShow (NET_POOL_ID);
- void decCsrShow (int inst);
- void decShow (int inst);
- #endif /* DRV_DEBUG */
- /* END Specific interfaces. */
- END_OBJ * dec21x40EndLoad (char *initString);
- LOCAL STATUS dec21x40Unload (DRV_CTRL *pDrvCtrl);
- LOCAL STATUS dec21x40Start (DRV_CTRL *pDrvCtrl);
- LOCAL STATUS dec21x40Stop (DRV_CTRL *pDrvCtrl);
- LOCAL int dec21x40Ioctl (DRV_CTRL *pDrvCtrl, int cmd, caddr_t data);
- LOCAL STATUS dec21x40Send (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
- LOCAL STATUS dec21x40MCastAddrAdd (DRV_CTRL *pDrvCtrl, char* pAddress);
- LOCAL STATUS dec21x40MCastAddrDel (DRV_CTRL *pDrvCtrl, char* pAddress);
- LOCAL STATUS dec21x40MCastAddrGet (DRV_CTRL *pDrvCtrl,
- MULTI_TABLE *pTable);
- LOCAL STATUS dec21x40PollSend (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
- LOCAL STATUS dec21x40PollReceive (DRV_CTRL *pDrvCtrl, M_BLK *pMblk);
- LOCAL STATUS dec21x40PollStart (DRV_CTRL *pDrvCtrl);
- LOCAL STATUS dec21x40PollStop (DRV_CTRL *pDrvCtrl);
- /*
- * Define the device function table. This is static across all driver
- * instances.
- */
- LOCAL NET_FUNCS netFuncs =
- {
- (FUNCPTR)dec21x40Start, /* start func. */
- (FUNCPTR)dec21x40Stop, /* stop func. */
- (FUNCPTR)dec21x40Unload, /* unload func. */
- (FUNCPTR)dec21x40Ioctl, /* ioctl func. */
- (FUNCPTR)dec21x40Send, /* send func. */
- (FUNCPTR)dec21x40MCastAddrAdd,/* multicast add func. */
- (FUNCPTR)dec21x40MCastAddrDel,/* multicast delete func. */
- (FUNCPTR)dec21x40MCastAddrGet,/* multicast get fun. */
- (FUNCPTR)dec21x40PollSend, /* polling send func. */
- (FUNCPTR)dec21x40PollReceive, /* polling receive func. */
- endEtherAddressForm, /* put address info into a NET_BUFFER */
- endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
- endEtherPacketAddrGet /* Get packet addresses. */
- };
- /******************************************************************************
- *
- * endTok_r - get a token string (modified version)
- *
- * This modified version can be used with optional parameters. If the
- * parameter is not specified, this version returns NULL. It does not
- * signify the end of the original string, but that the parameter is null.
- *
- * .CS
- *
- * /@ required parameters @/
- *
- * string = endTok_r (initString, ":", &pLast);
- * if (string == NULL)
- * return ERROR;
- * reqParam1 = strtoul (string);
- *
- * string = endTok_r (NULL, ":", &pLast);
- * if (string == NULL)
- * return ERROR;
- * reqParam2 = strtoul (string);
- *
- * /@ optional parameters @/
- *
- * string = endTok_r (NULL, ":", &pLast);
- * if (string != NULL)
- * optParam1 = strtoul (string);
- *
- * string = endTok_r (NULL, ":", &pLast);
- * if (string != NULL)
- * optParam2 = strtoul (string);
- * .CE
- */
- char * endTok_r
- (
- char * string, /* string to break into tokens */
- const char * separators, /* the separators */
- char ** ppLast /* pointer to serve as string index */
- )
- {
- if ((string == NULL) && ((string = *ppLast) == NULL))
- return (NULL);
- if ((*ppLast = strpbrk (string, separators)) != NULL)
- *(*ppLast)++ = EOS;
- /* Return NULL, if string is empty */
- if (*string == EOS)
- return NULL;
- return (string);
- }
- /***************************************************************************
- *
- * dec21x40EndLoad - initialize the driver and device
- *
- * This routine initializes the driver and the device to an operational state.
- * All of the device-specific parameters are passed in the <initStr>.
- * If this routine is called with an empty but allocated string, it puts the
- * name of this device (that is, "dc") into the <initStr> and returns 0.
- * If the string is allocated but not empty, this routine tries to load
- * the device.
- *
- * RETURNS: An END object pointer or NULL on error.
- */
- END_OBJ* dec21x40EndLoad
- (
- char* initStr /* String to be parse by the driver. */
- )
- {
- DRV_CTRL *pDrvCtrl;
- char eAdrs[EADDR_LEN]; /* ethernet address */
- if (initStr == NULL)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "dec21x40EndLoad: NULL initStrrn",
- 0,0,0,0,0,0);
- return (NULL);
- }
- if (initStr[0] == ' ')
- {
- bcopy((char *)DRV_NAME, initStr, DRV_NAME_LEN);
- return (0);
- }
- /* Allocate a control structure for this device */
- pDrvCtrl = calloc (sizeof(DRV_CTRL), 1);
- if (pDrvCtrl == NULL)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"%s - Failed to allocate control structuren",
- (int)DRV_NAME, 0,0,0,0,0 );
- return (NULL);
- }
- pDrvCtrl->flags = 0;
- pDrvCtrl->intrConnect = FALSE;
- pDrvCtrl->mediaCount = 0xff;
- pDrvCtrl->homePNAPhyValuesFound = FALSE;
- pDrvCtrl->offset = 0;
- if (dec21x40InitParse (pDrvCtrl, initStr) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_INIT, "%s - Failed to parse initialization"
- "parametersn",
- (int)DRV_NAME,0,0,0,0,0);
- return (NULL);
- }
- if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ*)pDrvCtrl, DRV_NAME,
- pDrvCtrl->unit, &netFuncs,
- "dec21x40 Enhanced Network Driver") == ERROR)
- {
- DRV_LOG (DRV_DEBUG_INIT, "%s%d - Failed to initialize END objectn",
- (int)DRV_NAME, pDrvCtrl->unit, 0,0,0,0);
- return (NULL);
- }
- if (dec21x40InitMem (pDrvCtrl) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_INIT, "dec21x40InitMem failed",0,0,0,0,0,0);
- goto error;
- }
- /* decode non-register user flags */
- if (pDrvCtrl->usrFlags & DEC_USR_XEA)
- DRV_FLAGS_SET (DEC_BSP_EADRS);
- switch (pDrvCtrl->usrFlags & DEC_USR_VER_MSK)
- {
- case DEC_USR_21143 :
- DRV_FLAGS_SET (DEC_21143);
- break;
- case DEC_USR_21140 :
- DRV_FLAGS_SET (DEC_21140);
- break;
- case DEC_USR_21145 :
- DRV_FLAGS_SET (DEC_21145);
- break;
- default :
- DRV_FLAGS_SET (DEC_21040);
- break;
- }
- if (dec21x40EnetAddrGet (pDrvCtrl, eAdrs) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_INIT, "%s%d - Failed to read ethernet addressn",
- (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
- goto error;
- }
- DRV_LOG (DRV_DEBUG_LOAD,
- "ENET: %x:%x:%x:%x:%x:%xn",
- eAdrs[0], eAdrs[1], eAdrs[2], eAdrs[3], eAdrs[4], eAdrs[5]);
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- /* Initialize MIB-II entries */
- if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
- (UINT8*) eAdrs, 6,
- ETHERMTU, DEC_SPEED_DEF) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_INIT, "%s%d - MIB-II initializations failedn",
- (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
- goto error;
- }
- /* Mark the device ready with default flags */
- END_OBJ_READY (&pDrvCtrl->endObj,
- IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
- #else
- /* New RFC 2233 mib2 interface */
- /* Initialize MIB-II entries (for RFC 2233 ifXTable) */
- pDrvCtrl->endObj.pMib2Tbl = m2IfAlloc(M2_ifType_ethernet_csmacd,
- (UINT8*) eAdrs, 6,
- ETHERMTU, DEC_SPEED_DEF,
- DRV_NAME, pDrvCtrl->unit);
- if (pDrvCtrl->endObj.pMib2Tbl == NULL)
- {
- printf ("%s%d - MIB-II initializations failedn",
- DRV_NAME, pDrvCtrl->unit);
- goto error;
- }
- /*
- * Set the RFC2233 flag bit in the END object flags field and
- * install the counter update routines.
- */
- #if defined(END_MIB_2233)
- pDrvCtrl->endObj.flags |= END_MIB_2233;
- #endif /* defined(END_MIB_2233) */
- m2IfPktCountRtnInstall(pDrvCtrl->endObj.pMib2Tbl, m2If8023PacketCount);
- /*
- * Make a copy of the data in mib2Tbl struct as well. We do this
- * mainly for backward compatibility issues. There might be some
- * code that might be referencing the END pointer and might
- * possibly do lookups on the mib2Tbl, which will cause all sorts
- * of problems.
- */
- bcopy ((char *)&pDrvCtrl->endObj.pMib2Tbl->m2Data.mibIfTbl,
- (char *)&pDrvCtrl->endObj.mib2Tbl, sizeof (M2_INTERFACETBL));
- /* Mark the device ready with default flags */
- #if defined(END_MIB_2233)
- END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST |
- IFF_BROADCAST | END_MIB_2233);
- #else /* !defined(END_MIB_2233) */
- END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST |
- IFF_BROADCAST);
- #endif /* !defined(END_MIB_2233) */
- #endif /* INCLUDE_RFC_1213 */
- return (&pDrvCtrl->endObj);
- /* Handle error cases */
- error:
- dec21x40Unload (pDrvCtrl);
- return (NULL);
- }
- /***************************************************************************
- *
- * dec21x40Unload - unload a driver from the system
- *
- * This routine deallocates lists, and free allocated memory.
- *
- * RETURNS: OK, always.
- */
- LOCAL STATUS dec21x40Unload
- (
- DRV_CTRL *pDrvCtrl
- )
- {
- DRV_LOG (DRV_DEBUG_LOAD, "EndUnloadn", 0, 0, 0, 0, 0, 0);
- #ifndef INCLUDE_RFC_1213
- /* New RFC 2233 mib2 interface */
- /* Free MIB-II entries */
- m2IfFree(pDrvCtrl->endObj.pMib2Tbl);
- pDrvCtrl->endObj.pMib2Tbl = NULL;
- #endif /* INCLUDE_RFC_1213 */
- /* deallocate lists */
- END_OBJ_UNLOAD (&pDrvCtrl->endObj);
- /* deallocate allocated shared memory */
- if (DRV_FLAGS_ISSET (DEC_MEMOWN) && pDrvCtrl->memBase)
- cacheDmaFree (pDrvCtrl->memBase);
- return (OK);
- }
- /***************************************************************************
- *
- * dec21x40InitParse - parse parameter values from initString
- *
- * The initialization string is modified by muxLib.o to include the unit number
- * as the first parameter.
- *
- * Parse the input string. Fill in values in the driver control structure.
- *
- * The initialization string format is:
- * "<device addr>:<PCI addr>:<ivec>:<ilevel>:<mem base>:<mem size>:
- * <user flags>:<phyAddr>:<pPhyTbl>:<phyFlags>:<offset>:<loanBufs>:<drvFlags>"
- *
- * .bS
- * device addr base address of hardware device registers
- * PCI addr main memory address over the PCI bus
- * ivec interrupt vector number
- * ilevel interrupt level
- * mem base base address of a DMA-able, cache free,pre-allocated memory
- * mem size size of the pre-allocated memory
- * user flags User flags control the run-time characteristics of the chip
- * phyAddr MII PHY address (optional)
- * pPhyTbl address of auto-negotiation table (optional)
- * phyFlags PHY configuration flags (optional)
- * offset Memory offset for alignment (optional)
- * loanBufs number of loaner clusters (optional)
- * drvFlags Driver flags control the runtime characteristics of the driver
- *
- * The last six arguments are optional. If the PHY address is to be specified
- * then phyAddr, pPhyTbl, and phyFlags should all be specified together.
- *
- * RETURNS: OK or ERROR for invalid arguments.
- */
- LOCAL STATUS dec21x40InitParse
- (
- DRV_CTRL *pDrvCtrl,
- char *initString
- )
- {
- char * tok; /* an initString token */
- char * holder=NULL; /* points to initString fragment beyond tok */
- UINT32 tokValue;
- DRV_LOG (DRV_DEBUG_LOAD, "InitParse: Initstr=%sn",
- (int) initString, 0, 0, 0, 0, 0);
- tok = endTok_r(initString, ":", &holder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->unit = atoi(tok);
- tok=endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->devAdrs = strtoul (tok, NULL, 16);
- tok=endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->pciMemBase = strtoul (tok, NULL, 16);
- tok=endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->ivec = strtoul (tok, NULL, 16);
- tok=endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->ilevel = strtoul (tok, NULL, 16);
- tok = endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return ERROR;
- if (atoi(tok) < 0)
- pDrvCtrl->numRds = NUM_RDS_DEF;
- else
- pDrvCtrl->numRds = atoi(tok);
- tok = endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return ERROR;
- if (atoi(tok) < 0)
- pDrvCtrl->numTds = NUM_TDS_DEF;
- else
- pDrvCtrl->numTds = atoi(tok);
- tok=endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->memBase = (char *) strtoul (tok, NULL, 16);
- tok=endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->memSize = strtoul (tok, NULL, 16);
- tok=endTok_r(NULL, ":", &holder);
- if (tok == NULL)
- return (ERROR);
- pDrvCtrl->usrFlags = strtoul(tok, NULL, 16);
- /*
- * Start of optional parameters. Set each optional parameter to
- * its default value, so that each will have a reasonable value
- * if we run out of fields during the string parse.
- */
- pDrvCtrl->phyAddr = (UINT8) 0xFF;
- pDrvCtrl->pMiiPhyTbl = NULL;
- pDrvCtrl->miiPhyFlags = (DEC_USR_MII_10MB | DEC_USR_MII_HD |
- DEC_USR_MII_100MB | DEC_USR_MII_FD |
- DEC_USR_MII_BUS_MON);
- pDrvCtrl->offset = 0;
- pDrvCtrl->loanBufs = NUM_LOAN;
- pDrvCtrl->drvFlags = 0;
- /* phyAddr */
- tok = endTok_r (NULL, ":", &holder);
- if (tok == NULL)
- goto endOptionalParams;
- pDrvCtrl->phyAddr = (UINT8) strtoul (tok, NULL, 16);
- /* pMiiPhyTbl - must be supplied if phyAddr was given */
- tok = endTok_r (NULL, ":", &holder);
- if (tok == NULL)
- return (ERROR);
- tokValue = strtoul (tok, NULL, 16);
- if ((INT32) tokValue != -1)
- pDrvCtrl->pMiiPhyTbl = (MII_AN_ORDER_TBL *) tokValue;
- /* miiPhyFlags - must be supplied if phyAddr was given */
- tok = endTok_r (NULL, ":", &holder);
- if (tok == NULL)
- return (ERROR);
- tokValue = strtoul (tok, NULL, 16);
- if ((INT32) tokValue != -1)
- pDrvCtrl->miiPhyFlags = tokValue;
- /* offset */
- tok = endTok_r (NULL, ":", &holder);
- if (tok == NULL)
- goto endOptionalParams;
- if (atoi(tok) >= 0)
- pDrvCtrl->offset = atoi (tok);
- /* loanBufs */
- tok = endTok_r (NULL, ":", &holder);
- if (tok == NULL)
- goto endOptionalParams;
- tokValue = (UINT32) strtoul (tok, NULL, 16);
- if ((INT32) tokValue != -1)
- pDrvCtrl->loanBufs = tokValue;
- /* drvFlags */
- tok = endTok_r (NULL, ":", &holder);
- if (tok == NULL)
- goto endOptionalParams;
- pDrvCtrl->drvFlags = (UINT32) strtoul (tok, NULL, 16);
- if (pDrvCtrl->drvFlags & DEC_DRV_NOSWAP_MASTER)
- DRV_FLAGS_SET (DEC_NOSWAP_MASTER);
- endOptionalParams:
- /* print debug info */
- DRV_LOG (DRV_DEBUG_LOAD,
- "EndLoad: unit=%d devAdrs=0x%x ivec=0x%x ilevel=0x%xn",
- pDrvCtrl->unit, pDrvCtrl->devAdrs, pDrvCtrl->ivec,
- pDrvCtrl->ilevel, 0, 0);
- DRV_LOG (DRV_DEBUG_LOAD,
- " membase=0x%x memSize=0x%xn",
- (int)pDrvCtrl->memBase, pDrvCtrl->memSize, 0,0,0,0);
- DRV_LOG (DRV_DEBUG_LOAD,
- " pciMemBase=0x%x flags=0x%x usrFlags=0x%x offset=%dn",
- (int)pDrvCtrl->pciMemBase, pDrvCtrl->flags, pDrvCtrl->usrFlags,
- pDrvCtrl->offset, 0, 0);
- DRV_LOG (DRV_DEBUG_LOAD,
- " phyAddr=0x%x pMiiPhyTbl=0x%x miiPhyFlags=0x%xn",
- (int) pDrvCtrl->phyAddr, (int) pDrvCtrl->pMiiPhyTbl,
- (int) pDrvCtrl->miiPhyFlags,
- 0,0,0);
- DRV_LOG (DRV_DEBUG_LOAD,
- " loanBufs=%d drvFlags=0x%xn",
- (int) pDrvCtrl->loanBufs, (int) pDrvCtrl->drvFlags, 0, 0, 0, 0);
- return OK;
- }
- /***************************************************************************
- *
- * dec21x40InitMem - initialize memory
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS dec21x40InitMem
- (
- DRV_CTRL * pDrvCtrl
- )
- {
- DEC_RD * pRxD = pDrvCtrl->rxRing;
- DEC_TD * pTxD = pDrvCtrl->txRing;
- M_CL_CONFIG dcMclBlkConfig;
- CL_DESC clDesc; /* cluster description */
- char * pBuf;
- int ix;
- int sz;
- char * pShMem;
- DRV_LOG (DRV_DEBUG_LOAD, "InitMemn", 0, 0, 0, 0, 0, 0);
- /* Establish a region of shared memory */
- /* We now know how much shared memory we need. If the caller
- * provides a specific memory region, we check to see if the provided
- * region is large enough for our needs. If the caller did not
- * provide a specific region, then we attempt to allocate the memory
- * from the system, using the cache aware allocation system call.
- */
- switch ((int)pDrvCtrl->memBase)
- {
- default : /* caller provided memory */
- /* Establish size of shared memory region we require */
- sz = ((pDrvCtrl->numRds * (DEC_BUFSIZ + RD_SIZ + 4)) +
- (pDrvCtrl->numTds * (DEC_BUFSIZ + TD_SIZ + 4)) +
- (pDrvCtrl->loanBufs * (DEC_BUFSIZ + 4)) + 4);
- if ( pDrvCtrl->memSize < sz ) /* not enough space */
- {
- DRV_LOG ( DRV_DEBUG_INIT, "%s%d: not enough memory providedn",
- (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
- return ( ERROR );
- }
- pShMem = pDrvCtrl->memBase; /* set the beginning of pool */
- /* assume pool is cache coherent, copy null structure */
- pDrvCtrl->cacheFuncs = cacheNullFuncs;
- break;
- case NONE : /* get our own memory */
- /*
- * Because the structures that are shared between the device
- * and the driver may share cache lines, the possibility exists
- * that the driver could flush a cache line for a structure and
- * wipe out an asynchronous change by the device to a neighboring
- * structure. Therefore, this driver cannot operate with memory
- * that is not write coherent. We check for the availability of
- * such memory here, and abort if the system did not give us what
- * we need.
- */
- if (!CACHE_DMA_IS_WRITE_COHERENT ())
- {
- DRV_LOG ( DRV_DEBUG_INIT, "dc: device requires cache"
- "coherent memoryn",
- 0,0,0,0,0,0);
- return (ERROR);
- }
- sz = (((pDrvCtrl->numRds + 1) * RD_SIZ) +
- ((pDrvCtrl->numTds + 1) * TD_SIZ));
- pDrvCtrl->memBase =
- pShMem = (char *) cacheDmaMalloc ( sz );
- if (pShMem == NULL)
- {
- DRV_LOG ( DRV_DEBUG_LOAD, "%s%d - system memory unavailablen",
- (int)DRV_NAME, pDrvCtrl->unit, 0,0,0,0);
- return (ERROR);
- }
- pDrvCtrl->memSize = sz;
- DRV_FLAGS_SET (DEC_MEMOWN);
- /* copy the DMA structure */
- pDrvCtrl->cacheFuncs = cacheDmaFuncs;
- break;
- }
- /* zero the shared memory */
- bzero (pShMem, (int) sz);
- /* carve Rx memory structure */
- pRxD =
- pDrvCtrl->rxRing = (DEC_RD *) (((int)pShMem + 0x03) & ~0x03);
- /* carve Tx memory structure */
- pTxD =
- pDrvCtrl->txRing = (DEC_TD *) (pDrvCtrl->rxRing + pDrvCtrl->numRds);
- /* Initialize net buffer pool for tx/rx buffers */
- bzero ((char *)&dcMclBlkConfig, sizeof(dcMclBlkConfig));
- bzero ((char *)&clDesc, sizeof(clDesc));
- dcMclBlkConfig.mBlkNum = (pDrvCtrl->numRds + pDrvCtrl->loanBufs) * 4;
- clDesc.clNum = pDrvCtrl->numRds + pDrvCtrl->numTds +
- pDrvCtrl->loanBufs;
- dcMclBlkConfig.clBlkNum = clDesc.clNum;
- /*
- * mBlk and cluster configuration memory size initialization
- * memory size adjusted to hold the netPool pointer at the head.
- */
- dcMclBlkConfig.memSize = ((dcMclBlkConfig.mBlkNum *
- (MSIZE + sizeof (long))) +
- (dcMclBlkConfig.clBlkNum *
- (CL_BLK_SZ + sizeof (long))));
- if ((dcMclBlkConfig.memArea = (char *)memalign(sizeof (long),
- dcMclBlkConfig.memSize))
- == NULL)
- return (ERROR);
- clDesc.clSize = DEC_BUFSIZ;
- clDesc.memSize = ((clDesc.clNum * (clDesc.clSize + 4)) + 4);
- if (DRV_FLAGS_ISSET(DEC_MEMOWN))
- {
- clDesc.memArea = (char *) cacheDmaMalloc (clDesc.memSize);
- if (clDesc.memArea == NULL)
- {
- DRV_LOG (DRV_DEBUG_INIT, "%s%d - system memory unavailablen",
- (int)DRV_NAME, pDrvCtrl->unit, 0,0,0,0);
- return (ERROR);
- }
- }
- else
- clDesc.memArea = (char *) (pDrvCtrl->txRing + pDrvCtrl->numTds);
- if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
- return (ERROR);
- /* Initialize the net buffer pool with transmit buffers */
- if (netPoolInit (pDrvCtrl->endObj.pNetPool, &dcMclBlkConfig,
- &clDesc, 1, NULL) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_INIT, "%s%d - netPoolInit failedn",
- (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
- return (ERROR);
- }
- /* Save the cluster pool id */
- pDrvCtrl->clPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool,
- DEC_BUFSIZ, FALSE);
- /* Clear all indices */
- pDrvCtrl->rxIndex=0;
- pDrvCtrl->txIndex=0;
- pDrvCtrl->txDiIndex=0;
- /* Setup the receive ring */
- for (ix = 0; ix < pDrvCtrl->numRds; ix++, pRxD++)
- {
- pBuf = (char *) NET_BUF_ALLOC();
- if (pBuf == NULL)
- {
- DRV_LOG (DRV_DEBUG_INIT, "%s%d - netClusterGet failedn",
- (int)DRV_NAME, pDrvCtrl->unit,0,0,0,0);
- return (ERROR);
- }
- pRxD->rDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pBuf)); /* buffer 1 */
- pRxD->rDesc3 = PCISWAP ((ULONG)pBuf); /* save virt addr */
- /* buffer size */
- pRxD->rDesc1 = PCISWAP (RDESC1_RBS1_VAL (DEC_BUFSIZ) |
- RDESC1_RBS2_VAL (0));
- if (ix == (pDrvCtrl->numRds - 1)) /* if its is last one */
- pRxD->rDesc1 |= PCISWAP (RDESC1_RER); /* end of receive ring */
- pRxD->rDesc0 = PCISWAP (RDESC0_OWN); /* give ownership to chip */
- }
- /* Setup the transmit ring */
- for (ix = 0; ix < pDrvCtrl->numTds; ix++, pTxD++)
- {
- /* empty -- no buffers at this time */
- pTxD->tDesc2 = 0;
- pTxD->tDesc3 = 0;
- pTxD->tDesc1 = PCISWAP ((TDESC1_TBS1_PUT(0) | /* buffer1 size */
- TDESC1_TBS2_PUT(0) | /* buffer2 size */
- TDESC1_IC | /* intrpt on xmit */
- TDESC1_LS | /* last segment */
- TDESC1_FS)); /* first segment */
- if (ix == (pDrvCtrl->numTds - 1)) /* if its is last one */
- pTxD->tDesc1 |= PCISWAP (TDESC1_TER); /* end of Xmit ring */
- pTxD->tDesc0 = 0; /* owner is host */
- }
- /* Fill the buffer for txPollSend */
- pDrvCtrl->txPollSendBuf = NET_BUF_ALLOC();
- /* Flush the write pipe */
- CACHE_PIPE_FLUSH ();
- return (OK);
- }
- /***************************************************************************
- *
- * dec21x40Start - start the device
- *
- * This function initializes the device and calls BSP functions to connect
- * interrupts and start the device running in interrupt mode.
- *
- * The complement of this routine is dec21x40Stop. Once a unit is reset by
- * dec21x40Stop, it may be re-initialized to a running state by this routine.
- *
- * RETURNS: OK if successful, otherwise ERROR
- */
- LOCAL STATUS dec21x40Start
- (
- DRV_CTRL * pDrvCtrl /* device to start */
- )
- {
- int retVal;
- UINT csr0Val;
- UINT csr6Val = 0;
- UINT usrFlags = pDrvCtrl->usrFlags;
- UINT tries = 0;
- DRV_LOG (DRV_DEBUG_LOAD,
- "Start, IO base addr: 0x%x ivec %d, ilevel %d, mempool base addr: 0x%xn",
- pDrvCtrl->devAdrs, pDrvCtrl->ivec, pDrvCtrl->ilevel,
- (int)(pDrvCtrl->memBase),
- 0, 0);
- DRV_LOG (DRV_DEBUG_LOAD,
- " pciMemBase=0x%x flags=0x%x usrFlags=0x%xn",
- (int)pDrvCtrl->pciMemBase, pDrvCtrl->flags, pDrvCtrl->usrFlags,
- 0, 0, 0);
- restart:
- /* Reset the device */
- DEC_CSR_WRITE (CSR6, 0);
- dec21x40ChipReset (pDrvCtrl);
- /* Clear all indices */
- pDrvCtrl->rxIndex=0;
- pDrvCtrl->txIndex=0;
- pDrvCtrl->txDiIndex=0;
- pDrvCtrl->txCleaning = FALSE;
- pDrvCtrl->rxHandling = FALSE;
- pDrvCtrl->txBlocked = FALSE;
- if (! DRV_FLAGS_ISSET (DEC_21040))
- {
- if (_func_dec21x40MediaSelect != NULL)
- retVal = (* _func_dec21x40MediaSelect) (pDrvCtrl, &csr6Val);
- else if (DRV_FLAGS_ISSET (DEC_21140))
- retVal = dec21140MediaSelect (pDrvCtrl, &csr6Val);
- else if (DRV_FLAGS_ISSET (DEC_21143))
- retVal = dec21143MediaSelect (pDrvCtrl, &csr6Val);
- else if (DRV_FLAGS_ISSET (DEC_21145))
- retVal = dec21145MediaSelect (pDrvCtrl, &csr6Val);
- else
- retVal = ERROR;
- if (retVal == ERROR)
- return (ERROR);
- if (csr6Val & CSR6_21140_PS)
- {
- /* changing PS requires a software reset */
- DEC_CSR_UPDATE (CSR6, CSR6_21140_PS);
- /* copy CSR0 before the software reset */
- csr0Val = DEC_CSR_READ (CSR0);
- DEC_CSR_WRITE (CSR0, CSR0_SWR);
- /* wait for software reset to complete before restoring CSRO */
- taskDelay(sysClkRateGet()/30);
- /* restore CSR0 */
- DEC_CSR_WRITE (CSR0, csr0Val);
- csr6Val |= CSR6_21140_HBD;
- /* clear CSR13 and 14 if 21143 - Appendix D, Port Selection */
- if (usrFlags & DEC_USR_21143)
- {
- DEC_CSR_WRITE (CSR13, 0);
- DEC_CSR_WRITE (CSR14, 0);
- }
- }
- csr6Val &= DEC_USR_CSR6_MSK;
- csr6Val |= CSR6_21140_MB1;
- /* decode CSR6 specific options from userFlags */
- if (usrFlags & DEC_USR_SF)
- csr6Val |= CSR6_21140_SF;
- if (usrFlags & DEC_USR_THR_MSK)
- csr6Val |= (usrFlags & DEC_USR_THR_MSK) >> DEC_USR_THR_SHF;
- if (usrFlags & DEC_USR_SB)
- csr6Val |= CSR6_SB;
- if (usrFlags & DEC_USR_PB)
- csr6Val |= CSR6_PB;
- if (usrFlags & DEC_USR_SC)
- csr6Val |= CSR6_21140_SC;
- if (usrFlags & DEC_USR_CA)
- csr6Val |= CSR6_CAE;
- }
- else
- dec21040AuiTpInit (pDrvCtrl);
- /* Write start of receive ring */
- DEC_CSR_WRITE (CSR3, DEC_VIRT_TO_PCI(pDrvCtrl->rxRing));
- /* Write start of transmit ring */
- DEC_CSR_WRITE (CSR4, DEC_VIRT_TO_PCI(pDrvCtrl->txRing));
- /* clear the status register */
- DEC_CSR_WRITE (CSR5, 0xffffffff);
- /* setup CSR6 - start transmitter */
- DEC_CSR_WRITE (CSR6, csr6Val | CSR6_ST);
- DRV_LOG (DRV_DEBUG_LOAD, "Writing CSR6 = %#08xnCSR7 = %#08xn",
- csr6Val | CSR6_ST, DEC_CSR_READ (CSR7),
- 0,0,0,0);
- taskDelay (sysClkRateGet() * 2);
- /* Check status of link */
- tries++; /* Increment the number of attempts to find media */
- if ((csr6Val & CSR6_21140_PS) && (csr6Val & CSR6_21140_PCS))
- {
- /* 100 Mbps non-MII mode */
- if (DEC_CSR_READ (CSR12) & CSR12_21143_LS100)
- {
- /* LS100 indicates link state down */
- if (tries < pDrvCtrl->mediaCount)
- {
- DRV_LOG (DRV_DEBUG_INIT, "100Mbps link failed - restartingn",
- 0,0,0,0,0,0);
- goto restart;
- }
- else
- {
- DRV_LOG (DRV_DEBUG_INIT, "100Mbps link failed - abortingn",
- 0,0,0,0,0,0);
- return ERROR;
- }
- }
- }
- else if ((csr6Val & CSR6_21140_PS) == 0)
- {
- /* 10 Mbps mode */
- if (DEC_CSR_READ (CSR12) & (CSR12_21143_LS10 | CSR12_21040_LKF))
- {
- /* Link down */
- if (tries < pDrvCtrl->mediaCount)
- {
- DRV_LOG (DRV_DEBUG_INIT, "10Mbps link failed - restartingn",
- 0,0,0,0,0,0);
- goto restart;
- }
- else
- {
- DRV_LOG (DRV_DEBUG_INIT, "10Mbps link failed - abortingn",
- 0,0,0,0,0,0);
- return ERROR;
- }
- }
- }
- /* setup ethernet address and filtering mode */
- dec21x40IASetup (pDrvCtrl);
- /* set operating mode and start the receiver */
- dec21x40ModeSet (pDrvCtrl);
- /* Connect the interrupt handler */
- SYS_INT_CONNECT (pDrvCtrl, dec21x40Int, pDrvCtrl, &retVal);
- if (retVal == ERROR)
- return (ERROR);
- /* set up the interrupts */
- pDrvCtrl->intrMask = (CSR7_NIM | /* normal interrupt mask */
- CSR7_RIM | /* rcv interrupt mask */
- CSR7_TIM | /* xmit interrupt mask */
- CSR7_TUM | /* xmit buff unavailble mask */
- CSR7_AIM | /* abnormal interrupt mask */
- CSR7_SEM | /* system error mask */
- CSR7_RUM ); /* rcv buff unavailable mask */
- if (DRV_FLAGS_ISSET(DEC_21145)
- && (pDrvCtrl->usrFlags & (DEC_USR_HPNA_PREFER_10BT)))
- {
- /* link fail, pass/anc mask */
- pDrvCtrl->intrMask |= (CSR7_ANC | CSR7_21040_LFM );
- }
- DEC_CSR_WRITE (CSR7, pDrvCtrl->intrMask);
- if (DRV_FLAGS_ISSET (DEC_21040))
- DEC_CSR_UPDATE (CSR7, CSR7_21040_LFM); /* link fail mask */
- /* mark the interface -- up */
- END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
- /* Enable LAN interrupts */
- SYS_INT_ENABLE (pDrvCtrl);
- pDrvCtrl->rxLen = 0;
- pDrvCtrl->rxMaxLen = RWIN;
- return OK;
- }
- /***************************************************************************
- *
- * dec21x40Stop - stop the device
- *
- * This routine disables interrupts, and resets the device.
- *
- * RETURNS: OK or ERROR
- */
- LOCAL STATUS dec21x40Stop
- (
- DRV_CTRL *pDrvCtrl
- )
- {
- int retVal = OK;
- PHY_INFO * pPhyInfo = pDrvCtrl->pPhyInfo;
- DRV_LOG (DRV_DEBUG_LOAD, "Stopn", 0, 0, 0, 0, 0, 0);
- /* mark the interface -- down */
- END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING);
- /* Disable LAN interrupts */
- SYS_INT_DISABLE (pDrvCtrl);
- /* stop transmit and receive */
- DEC_CSR_RESET (CSR6, CSR6_ST | CSR6_SR);
- if ((pDrvCtrl->usrFlags & DEC_USR_21145) == 0)
- {
- if ((pPhyInfo != NULL) && MII_PHY_FLAGS_ARE_SET (MII_PHY_INIT))
- {
- if (intCnt == 0)
- {
- if (miiPhyUnInit (pPhyInfo) == ERROR)
- return (ERROR);
- free (pPhyInfo);
- }
- else
- {
- /*
- * Defer these to task level since they cannot be performed at
- * interrupt level
- */
- netJobAdd ((FUNCPTR) miiPhyUnInit, (int) pPhyInfo, 0,0,0,0);
- netJobAdd ((FUNCPTR) free, (int) pPhyInfo, 0,0,0,0);
- }
- pDrvCtrl->pPhyInfo = NULL;
- }
- }
- /* disconnect interrupt */
- SYS_INT_DISCONNECT (pDrvCtrl, dec21x40Int, (int)pDrvCtrl, &retVal);
- return (retVal);
- }
- /***************************************************************************
- *
- * dec21x40MediaChange - start the device
- *
- * Restarts the device after cleaning up the transmit and receive queues. This
- * routine should be called only after dec21x40Stop().
- *
- * RETURNS: OK or ERROR
- */
- LOCAL STATUS dec21x40MediaChange
- (
- DRV_CTRL *pDrvCtrl
- )
- {
- if (dec21x40Stop (pDrvCtrl) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_INIT, "dec21x40MediaChange, unable to stopn",
- 0, 0, 0, 0, 0, 0);
- return (ERROR);
- }
- DRV_LOG (DRV_DEBUG_ALL, "%s%d - stopped device.n",
- (int)DRV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
- netJobAdd ((FUNCPTR) dec21x40Restart, (int) pDrvCtrl, 0,0,0,0);
- return (OK);
- }
- /***************************************************************************
- *
- * dec21x40Restart - start the device
- *
- * Restarts the device after cleaning up the transmit and receive queues. This
- * routine should be called only after dec21x40Stop().
- *
- * RETURNS: OK or ERROR
- */
- LOCAL void dec21x40Restart
- (
- DRV_CTRL *pDrvCtrl
- )
- {
- DEC_TD *pTxD = pDrvCtrl->txRing;
- FREE_BUF *pFreeBuf = pDrvCtrl->freeBuf;
- int count;
- DRV_LOG (DRV_DEBUG_ALL, "%s%d - restarting device.n",
- (int)DRV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
- /* cleanup the tx and rx queues */
- dec21x40TxRingClean (pDrvCtrl);
- dec21x40RxIntHandle (pDrvCtrl);
- /* drop rest of the queued tx packets */
- for (count=pDrvCtrl->numTds; count; count--, pTxD++, pFreeBuf++)
- {
- if (pFreeBuf->pClBuf != NULL)
- {
- NET_BUF_FREE(pFreeBuf->pClBuf);
- pFreeBuf->pClBuf = NULL;
- }
- DEC_CACHE_INVALIDATE (pTxD, TD_SIZ);
- if (pTxD->tDesc1 & PCISWAP(TDESC1_SET))
- {
- pTxD->tDesc1 &= PCISWAP(~(TDESC1_SET | TDESC1_FT0));
- pTxD->tDesc0 = 0;
- }
- else if (pTxD->tDesc0 & PCISWAP(TDESC0_OWN|TDESC0_ES))
- {
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
- #else
- /* New RFC 2233 mib2 interface */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
- pMib2Tbl,
- M2_ctrId_ifOutErrors,
- 1);
- }
- #endif /* INCLUDE_RFC_1213 */
- pTxD->tDesc0 = 0;
- }
- }
- /* Reset indices */
- pDrvCtrl->rxIndex=0;
- pDrvCtrl->txIndex=0;
- pDrvCtrl->txDiIndex=0;
- /* Restart the device */
- dec21x40Start (pDrvCtrl);
- }
- /***************************************************************************
- *
- * dec21x40Ioctl - interface ioctl procedure
- *
- * Process an interface ioctl request.
- *
- * This routine implements the network interface control functions.
- * It handles EIOCSADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS, EIOCMULTIADD,
- * EIOCMULTIDEL, EIOCMULTIGET, EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2 commands.
- *
- * RETURNS: OK if successful, otherwise EINVAL.
- */
- LOCAL int dec21x40Ioctl
- (
- DRV_CTRL * pDrvCtrl,
- int cmd,
- caddr_t data
- )
- {
- int error=0;
- long value;
- int savedFlags;
- END_OBJ * pEndObj=&pDrvCtrl->endObj;
- DRV_LOG (DRV_DEBUG_IOCTL,
- "Ioctl unit=0x%x cmd=%d data=0x%xn",
- pDrvCtrl->unit, cmd, (int)data, 0, 0, 0);
- switch ((UINT)cmd)
- {
- case EIOCSADDR:
- if (data == NULL)
- error = EINVAL;
- else
- {
- /* Copy and install the new address */
- bcopy ((char *)data, (char *)END_HADDR(pEndObj),
- END_HADDR_LEN(pEndObj));
- dec21x40IASetup (pDrvCtrl);
- }
- break;
- case EIOCGADDR:
- if (data == NULL)
- error = EINVAL;
- else
- bcopy ((char *)END_HADDR(pEndObj), (char *)data,
- END_HADDR_LEN(pEndObj));
- #ifdef DRV_DEBUG
- {
- char *cp = (char *)data;
- DRV_LOG (DRV_DEBUG_IOCTL,
- "EIOCGADDR: %x:%x:%x:%x:%x:%xn",
- cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
- }
- #endif /*DRV_DEBUG*/
- break;
- case EIOCSFLAGS:
- value = (long) data;
- if (value < 0)
- {
- value = -value;
- value--;
- END_FLAGS_CLR (pEndObj, value);
- }
- else
- END_FLAGS_SET (pEndObj, value);
- /* handle IIF_PROMISC and IFF_ALLMULTI */
- savedFlags = DRV_FLAGS_GET();
- if (END_FLAGS_ISSET (pEndObj, IFF_PROMISC))
- DRV_FLAGS_SET (DEC_PROMISC);
- else
- DRV_FLAGS_CLR (DEC_PROMISC);
- if (END_FLAGS_GET(pEndObj) & (IFF_MULTICAST | IFF_ALLMULTI))
- DRV_FLAGS_SET (DEC_MCAST);
- else
- DRV_FLAGS_CLR (DEC_MCAST);
- DRV_LOG (DRV_DEBUG_IOCTL,
- "endFlags=0x%x savedFlags=0x%x newFlags=0x%xn",
- END_FLAGS_GET(pEndObj), savedFlags, DRV_FLAGS_GET(),
- 0, 0, 0);
- if ((DRV_FLAGS_GET() != savedFlags) &&
- (END_FLAGS_GET(pEndObj) & IFF_UP))
- dec21x40ModeSet (pDrvCtrl);
- break;
- case EIOCGFLAGS: /* move to mux */
- DRV_LOG (DRV_DEBUG_IOCTL, "EIOCGFLAGS: 0x%x: 0x%xn",
- pEndObj->flags, *(long *)data, 0, 0, 0, 0);
- if (data == NULL)
- error = EINVAL;
- else
- *(long *)data = END_FLAGS_GET(pEndObj);
- break;
- case EIOCMULTIADD: /* move to mux */
- error = dec21x40MCastAddrAdd (pDrvCtrl, (char *)data);
- break;
- case EIOCMULTIDEL: /* move to mux */
- error = dec21x40MCastAddrDel (pDrvCtrl, (char *)data);
- break;
- case EIOCMULTIGET: /* move to mux */
- error = dec21x40MCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data);
- break;
- case EIOCPOLLSTART: /* move to mux */
- dec21x40PollStart (pDrvCtrl);
- break;
- case EIOCPOLLSTOP: /* move to mux */
- dec21x40PollStop (pDrvCtrl);
- break;
- case EIOCGMIB2: /* move to mux */
- if (data == NULL)
- error=EINVAL;
- else
- bcopy((char *)&pEndObj->mib2Tbl, (char *)data,
- sizeof(pEndObj->mib2Tbl));
- break;
- #ifndef INCLUDE_RFC_1213
- /* New RFC 2233 mib2 interface */
- case EIOCGMIB2233:
- if ((data == NULL) || (pEndObj->pMib2Tbl == NULL))
- error = EINVAL;
- else
- *((M2_ID **)data) = pEndObj->pMib2Tbl;
- break;
- #endif /* INCLUDE_RFC_1213 */
- default:
- error = EINVAL;
- }
- return (error);
- }
- /***************************************************************************
- *
- * dec21x40ModeSet - promiscuous & multicast operation and start receiver
- *
- * RETURNS: N/A
- */
- LOCAL void dec21x40ModeSet
- (
- DRV_CTRL *pDrvCtrl
- )
- {
- int opMode = CSR6_SR; /* start receiver */
- DRV_LOG (DRV_DEBUG_IOCTL, "ModeSetn", 0, 0, 0, 0, 0, 0);
- if (DRV_FLAGS_ISSET (DEC_MCAST))
- opMode |= CSR6_PM; /* rx multicast */
- if (DRV_FLAGS_ISSET (DEC_PROMISC))
- opMode |= CSR6_PR; /* rx promiscuous */
- DEC_CSR_WRITE (CSR6, (DEC_CSR_READ (CSR6) & ~(CSR6_PM|CSR6_PR)) | opMode);
- return;
- }
- /***************************************************************************
- *
- * dec21x40HashIndex - compute the hash index for an ethernet address
- *
- * RETURNS: hash index for an ethernet address.
- */
- LOCAL int dec21x40HashIndex
- (
- char * eAddr
- )
- {
- UINT8 eAddrByte;
- int index; /* hash index - return value */
- int byte; /* loop - counter */
- int bit; /* loop - counter */
- UINT crc = 0xffffffff;
- UINT8 msb;
- for (byte=0; byte<6; byte++)
- {
- eAddrByte = eAddr[byte];
- for (bit=0; bit<8; bit++)
- {
- msb = crc >> 31;
- crc <<= 1;
- if (msb ^ (eAddrByte & 0x1))
- {
- crc ^= DEC_CRC_POLY;
- crc |= 0x1;
- }
- eAddrByte >>= 1;
- }
- }
- /*
- * return the upper 9 bits of the CRC in a decreasing order of
- * significance.
- * crc <31..23> as index <0..8>
- */
- index = 0;
- for (bit=0; bit<9; bit++)
- index |= ((crc >> (31-bit)) & 0x1) << bit;
- return index;
- }
- /***************************************************************************
- *
- * dec21x40IASetup - set up physical and multicast addresses
- *
- * This routine sets up a filter frame to filter the physical addresses
- * and all the current multicast addresses.
- *
- * While the first call to this routine during chip initialization requires
- * that the receiver be turned off, subsequent calls do not.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS dec21x40IASetup
- (
- DRV_CTRL * pDrvCtrl /* pointer to device control structure */
- )
- {
- UINT8 ethBcastAdrs[]={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- UINT8 *pFltrFrm;
- UINT8 *pAdrs;
- ETHER_MULTI *pMCastNode;
- DEC_TD *pTxD;
- ULONG csr7Val;
- char * pBuf;
- int index;
- int timeout;
- /* gain exclusive access to transmitter */
- END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
- /* get a free transmit descriptor */
- pTxD = dec21x40TxDGet (pDrvCtrl);
- if (pTxD == NULL)
- {
- DRV_LOG (DRV_DEBUG_INIT, "dec21x40TxDGet failedn", 1, 2, 3, 4, 5, 6);
- END_TX_SEM_GIVE (&pDrvCtrl->endObj);
- return (ERROR);
- }
- DRV_LOG (DRV_DEBUG_IOCTL, "IASetup 0x%xn", pTxD->tDesc0, 0, 0, 0, 0, 0);
- /* get a buffer */
- pBuf = NET_BUF_ALLOC();
- if (pBuf == NULL)
- {
- DRV_LOG (DRV_DEBUG_INIT, "netClusterGet failedn", 1, 2, 3, 4, 5, 6);
- END_TX_SEM_GIVE (&pDrvCtrl->endObj);
- return (ERROR);
- }
- /* align the frame */
- pFltrFrm = (UINT8 *) (((int)pBuf + 0x3) & ~0x3);
- /* clear all entries */
- bzero (pFltrFrm, FLTR_FRM_SIZE);
- /* install multicast addresses */
- for (pMCastNode = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);
- pMCastNode != NULL;
- pMCastNode = END_MULTI_LST_NEXT (pMCastNode))
- {
- index = dec21x40HashIndex (pMCastNode->addr);
- pFltrFrm [DEC_FLT_INDEX(index/8)] |= 1 << (index % 8);
- }
- /* install an ethernet broadcast address */
- index = dec21x40HashIndex (ethBcastAdrs);
- pFltrFrm [DEC_FLT_INDEX(index/8)] |= 1 << (index % 8);
- /* install the physical address */
- pAdrs = (UINT8 *)END_HADDR (&pDrvCtrl->endObj);
- for (index=0; index<6; index++)
- pFltrFrm [FLTR_FRM_PHY_ADRS_OFF + DEC_FLT_INDEX(index)] = pAdrs[index];
- /* transmit the frame */
- pTxD->tDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pFltrFrm));
- pTxD->tDesc3 = 0;
- /* frame type is SETUP, filtering mode is HASH + 1 perfect */
- pTxD->tDesc1 |= PCISWAP (TDESC1_SET | TDESC1_FT0);
- pTxD->tDesc1 &= PCISWAP (~TDESC1_TBS1_MSK);
- pTxD->tDesc1 |= PCISWAP (TDESC1_TBS1_PUT(FLTR_FRM_SIZE));
- pTxD->tDesc1 &= PCISWAP (~(TDESC1_LS|TDESC1_FS));
- pTxD->tDesc0 = PCISWAP(TDESC0_OWN); /* ready for transmit */
- CACHE_PIPE_FLUSH();
- /* Advance our management index */
- pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds;
- /* mask interrupts */
- csr7Val = DEC_CSR_READ (CSR7);
- DEC_CSR_WRITE (CSR7, 0);
- /* start tx */
- if (DRV_FLAGS_ISSET(DEC_TX_KICKSTART))
- DEC_CSR_WRITE (CSR1, CSR1_TPD);
- /* wait for completion */
- timeout=0xffffff;
- while (timeout && (pTxD->tDesc0 != (~PCISWAP (TDESC0_OWN))))
- timeout--;
- if (timeout <= 0)
- {
- DRV_LOG (DRV_DEBUG_INIT, "no toggle on OWN bit 0x%x %xn",
- (int)(&pTxD->tDesc0), pTxD->tDesc0, 3, 4, 5, 6);
- END_TX_SEM_GIVE (&pDrvCtrl->endObj);
- return (ERROR);
- }
- /* restore TXD bits */
- pTxD->tDesc0 = 0;
- pTxD->tDesc1 &= PCISWAP (~(TDESC1_SET | TDESC1_FT0));
- pTxD->tDesc1 |= PCISWAP (TDESC1_LS | TDESC1_FS);
- pTxD->tDesc2 = 0;
- CACHE_PIPE_FLUSH();
- /* restore interrupts */
- DEC_CSR_WRITE (CSR7, csr7Val);
- /* free the buffer */
- NET_BUF_FREE (pBuf);
- /* release exclusive access */
- END_TX_SEM_GIVE (&pDrvCtrl->endObj);
- /* return success */
- return (OK);
- }
- /***************************************************************************
- *
- * dec21x40MCastAddrAdd - add a multicast address
- *
- *
- * RETURNS: OK on success, ERROR otherwise.
- */
- LOCAL STATUS dec21x40MCastAddrAdd
- (
- DRV_CTRL * pDrvCtrl,
- char * pAddr
- )
- {
- int retVal;
- DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrAddn", 0, 0, 0, 0, 0, 0);
- retVal = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddr);
- if (retVal == ENETRESET)
- return dec21x40IASetup (pDrvCtrl);
- return ((retVal == OK) ? OK : ERROR);
- }
- /***************************************************************************
- *
- * dec21x40MCastAddrDel - remove a multicast address
- *
- *
- * RETURNS: OK on success, ERROR otherwise.
- */
- LOCAL STATUS dec21x40MCastAddrDel
- (
- DRV_CTRL * pDrvCtrl,
- char * pAddr
- )
- {
- int retVal;
- DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrDeln", 0, 0, 0, 0, 0, 0);
- retVal = etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr);
- if (retVal == ENETRESET)
- return dec21x40IASetup (pDrvCtrl);
- return ((retVal == OK) ? OK : ERROR);
- }
- /***************************************************************************
- *
- * dec21x40MCastAddrGet - retreive current multicast address list
- *
- *
- * RETURNS: OK on success; otherwise ERROR.
- */
- LOCAL STATUS dec21x40MCastAddrGet
- (
- DRV_CTRL * pDrvCtrl,
- MULTI_TABLE *pTable
- )
- {
- DRV_LOG (DRV_DEBUG_IOCTL, "MCastAddrGetn", 0, 0, 0, 0, 0, 0);
- return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable));
- }
- /***************************************************************************
- *
- * dec21x40Send - transmit an ethernet packet
- *
- * RETURNS: OK on success; and ERROR otherwise.
- */
- LOCAL STATUS dec21x40Send
- (
- DRV_CTRL *pDrvCtrl,
- M_BLK *pMblk
- )
- {
- DEC_TD * pTxD;
- char * pBuf;
- int len;
- int s;
- DRV_LOG (DRV_DEBUG_TX, "S:0x%x ", pDrvCtrl->txIndex, 0, 0, 0, 0, 0);
- /* Gain exclusive access to transmit */
- END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
- /* Get the next TXD */
- pTxD = dec21x40TxDGet (pDrvCtrl);
- pBuf = NET_BUF_ALLOC();
- if ((pTxD == NULL) || (pBuf == NULL))
- {
- DRV_LOG (DRV_DEBUG_TX, "No available TxBufs n", 0, 0, 0, 0, 0, 0);
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
- #else
- /* New RFC 2233 mib2 interface */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
- M2_ctrId_ifOutErrors, 1);
- }
- #endif
- END_TX_SEM_GIVE (&pDrvCtrl->endObj);
- if (pBuf)
- NET_BUF_FREE (pBuf);
- if (!pDrvCtrl->txCleaning && !pDrvCtrl->txBlocked)
- dec21x40TxRingClean (pDrvCtrl);
- s = intLock();
- pDrvCtrl->txBlocked = TRUE; /* transmitter not ready */
- intUnlock(s);
- return (END_ERR_BLOCK); /* just return without freeing mBlk chain */
- }
- /* copy and free the MBLK */
- len = netMblkToBufCopy (pMblk, pBuf, NULL);
- NET_MBLK_CHAIN_FREE (pMblk);
- /* setup the transmit buffer pointers */
- pTxD->tDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pBuf));
- pTxD->tDesc3 = 0;
- /* setup frame len */
- pTxD->tDesc1 &= PCISWAP (~TDESC1_TBS1_MSK);
- pTxD->tDesc1 |= PCISWAP (TDESC1_TBS1_PUT(len));
- /* transfer ownership to device */
- pTxD->tDesc0 = PCISWAP(TDESC0_OWN);
- CACHE_PIPE_FLUSH();
- /* Save the buf info */
- pDrvCtrl->freeBuf[pDrvCtrl->txIndex].pClBuf = pBuf;
- /* Advance our management index */
- pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds;
- if (DRV_FLAGS_ISSET(DEC_TX_KICKSTART))
- DEC_CSR_WRITE (CSR1, CSR1_TPD);
- END_TX_SEM_GIVE (&pDrvCtrl->endObj);
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- /* update statistics */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
- #endif /* INCLUDE_RFC_1213 */
- return (OK);
- }
- /***************************************************************************
- *
- * dec21x40Recv - pass a received frame to the upper layer
- *
- *
- * RETURNS: OK, always.
- */
- LOCAL STATUS dec21x40Recv
- (
- DRV_CTRL * pDrvCtrl,
- DEC_RD * pRxD
- )
- {
- END_OBJ * pEndObj = &pDrvCtrl->endObj;
- M_BLK_ID pMblk; /* MBLK to send upstream */
- CL_BLK_ID pClBlk; /* pointer to clBlk */
- char * pBuf; /* A replacement buffer for the current RxD */
- char * pData; /* Data pointer for the current RxD */
- char * pTmp;
- int len; /* Len of the current data */
- DRV_LOG (DRV_DEBUG_RX, ("R"), 0, 0, 0, 0, 0, 0);
- /* check for errors */
- if (pRxD->rDesc0 & PCISWAP(RDESC0_ES))
- {
- DRV_LOG (DRV_DEBUG_RX, ("- "), 0, 0, 0, 0, 0, 0);
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (pEndObj, MIB2_OUT_ERRS, +1);
- #else
- /* New RFC 2233 mib2 interface */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
- M2_ctrId_ifInErrors, 1);
- }
- #endif /* INCLUDE_RFC_1213 */
- goto cleanRxD;
- }
- DRV_LOG (DRV_DEBUG_RX, ("+ "), 0, 0, 0, 0, 0, 0);
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (pEndObj, MIB2_IN_UCAST, +1);
- #endif /* INCLUDE_RFC_1213 */
- /* Allocate an MBLK, and a replacement buffer */
- pMblk = NET_MBLK_ALLOC();
- pBuf = NET_BUF_ALLOC();
- pClBlk = NET_CL_BLK_ALLOC();
- if ((pMblk == NULL) || (pBuf == NULL) || (pClBlk == NULL))
- {
- DRV_LOG (DRV_DEBUG_RX, "No available RxBufs n", 0, 0, 0, 0, 0, 0);
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (pEndObj, MIB2_IN_ERRS, +1);
- #else
- /* New RFC 2233 mib2 interface */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
- M2_ctrId_ifInErrors, 1);
- }
- #endif /* INCLUDE_RFC_1213 */
- if (pMblk)
- NET_MBLK_FREE (pMblk);
- if (pBuf)
- NET_BUF_FREE (pBuf);
- if (pClBlk)
- NET_CL_BLK_FREE (pClBlk);
- goto cleanRxD;
- }
- /* Get the data pointer and len from the current RxD */
- len = DEC_FRAME_LEN_GET (PCISWAP (pRxD->rDesc0)) - ETH_CRC_LEN;
- pData = (char *) PCISWAP (pRxD->rDesc3); /* buff virtual address */
- /*
- * The code above solves alignment problem when the CPU and the
- * ethernet chip don't accept longword unaligned addresses.
- *
- * Pb: When the ethernet chip receives a packet from the network,
- * it needs a longword aligned buffer to copy the data. To process the
- * IP packet, MUX layer adds a SIZEOF_ETHERHEADER(0x14) offset to the
- * data buffer. So the CPU obtains a longword unaligned buffer and
- * a fault execption occurs when it reads "ip_src" and "ip_dst" fields
- * in the IP structure (ip_src and ip_dst fields are longwords).
- *
- * The problem is solved copying the data in a new buffer in which
- * the IP structure is aligned.
- */
- if (pDrvCtrl->offset != 0)
- {
- /* exchange buffer addresses */
- pTmp = pData;
- pData = pBuf;
- pBuf = pTmp;
- /* copy data in new unaligned buffer */
- pData += pDrvCtrl->offset;
- memcpy(pData, pBuf, len);
- }
- /* Restore orignal buffer address to be able to free it */
- pData -= pDrvCtrl->offset;
- #ifndef INCLUDE_RFC_1213
- /* New RFC 2233 mib2 interface */
- /* RFC 2233 mib2 counter update for incoming packet */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,
- M2_PACKET_IN, pData, len);
- }
- #endif /* INCLUDE_RFC_1213 */
- /* Associate the data pointer with the MBLK */
- NET_CL_BLK_JOIN (pClBlk, pData, DEC_BUFSIZ);
- /* Associate the data pointer with the MBLK */
- NET_MBLK_CL_JOIN (pMblk, pClBlk);
- pMblk->mBlkHdr.mData += pDrvCtrl->offset;
- pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */
- pMblk->mBlkHdr.mLen = len; /* set the data len */
- pMblk->mBlkPktHdr.len = len; /* set the total len */
- pDrvCtrl->rxLen += len;
- /* Make cache consistent with memory */
- DEC_CACHE_INVALIDATE (pData, len);
- /* Install the new data buffer */
- pRxD->rDesc2 = PCISWAP (DEC_VIRT_TO_PCI (pBuf));
- pRxD->rDesc3 = PCISWAP ((ULONG)pBuf); /* virtual buffer address */
- /* mark the descriptor ready to receive */
- pRxD->rDesc0 = PCISWAP (RDESC0_OWN);
- /* advance management index */
- pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds;
- CACHE_PIPE_FLUSH();
- /* send the frame to the upper layer, and possibly switch to system mode */
- END_RCV_RTN_CALL (pEndObj, pMblk);
- return (OK);
- cleanRxD:
- /* mark the descriptor ready to receive */
- pRxD->rDesc0 = PCISWAP (RDESC0_OWN);
- CACHE_PIPE_FLUSH();
- /* advance management index */
- pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds;
- return (OK);
- }
- /***************************************************************************
- *
- * dec21x40RxIntHandle - perform receive processing
- *
- * RETURNS: N/A
- */
- LOCAL void dec21x40RxIntHandle
- (
- DRV_CTRL * pDrvCtrl
- )
- {
- DEC_RD *pRxD;
- pDrvCtrl->rxHandling = TRUE;
- pDrvCtrl->rxLen = 0;
- while ((pRxD = dec21x40RxDGet (pDrvCtrl)) &&