gei82543End.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:174k
源码类别:
VxWorks
开发平台:
C/C++
- /* gei82543End.c - Intel PRO/1000 F/T/XF/XT/MT/MF network adapter END driver */
- /* Copyright 1984-2002 Wind River Systems, Inc. */
- #include "copyright_wrs.h"
- /*
- modification history
- --------------------
- 01m,23may02,jln support 82545/82546 fiber-based adapter(spr 78084)
- clean interrupts only when packets can be processed
- 01l,02may02,jln support 82540/82545/82546 based adapters spr # 76739;
- stop device only after device has been started spr # 76511
- change input argument from vector to unit in SYS_INT_ENABLE
- and SYS_INT_DISABLE macros
- 01k,22apr02,rcs changed gei82543MemAllFree() to use free for
- pDrvCtrl->pTxDesCtlBase SPR# 76130
- 01j,22apr02,rcs removed taskDelay() from gei82543EndPollSend() SPR# 76102
- 01i,14jan02,dat Removing warnings from Diab compiler
- 01h,08nov01,jln coding workaround for TBI compatibility HW bug (spr# 71363),
- but disable it by default for testing issues.
- 01g,01sep01,jln clean up documentation
- 01f,10aug01,jln add support for 82544-based adapters spr# 69774; remove
- copying method for transmitting; add support for jumbo
- frames spr# 67477
- 01e,03may01,jln fix memory leak in gei82543EndStop (spr# 67116);
- added read operation before exit ISR to flush write buffer
- for PCI bridge; polish TX/RX handling
- 01d,01may01,jln change MACRO(s) GEI_READ_REG, GEI_READ_DESC_WORD, and
- GEI_READ_DESC_LONG for coding convention
- 01c,19apr01,jln clean up for spr#65326
- 01b,01apr01,jln clean up after code review (partial spr#65326).
- 01a,08jan01,jln created based on templateEnd.c and fei82557End.c END scheme
- */
- /*
- DESCRIPTION
- The gei82543End driver supports Intel PRO1000 T/F/XF/XT/MT/MF adaptors
- These adaptors use Intel 82543GC, 82544GC/EI, or 82540/82545/82546EB Gigabit
- Ethernet controllers.The 8254x are highly integrated, high-performance LAN
- controllers for 1000/100/10Mb/s transfer rates. They provide 32/64 bit 33/66Mhz
- interfaces to the PCI bus with 32/64 bit addressing and are fully compliant
- with PCI bus specification version 2.2. The 82544, 82545 and 82546 also
- provide PCI-X interface.
- The 8254x controllers implement all IEEE 802.3 receive and transmit
- MAC functions. They provide a Ten-Bit Interface (TBI) as specified in the IEEE
- 802.3z standard for 1000Mb/s full-duplex operation with 1.25 GHz Ethernet
- transceivers (SERDES), as well as a GMII interface as specified in
- IEEE 802.3ab for 10/100/1000 BASE-T transceivers, and also an MII interface as
- specified in IEEE 802.3u for 10/100 BASE-T transceivers.
- The 8254x controllers offer auto-negotiation capability for TBI and GMII/MII
- modes and also support IEEE 802.3x compliant flow control. Although these
- devices also support other advanced features such as receive and transmit
- IP/TCP/UDP checksum offloading, jumbo frames, and provide flash support up
- to 512KB and EEPROM support, this driver does NOT support these features.
- The 8254x establishes a shared memory communication system with the
- CPU, which is divided into two parts: the control/status registers and the
- receive/transmit descriptors/buffers. The control/status registers
- are on the 8254x chips and are only accessible with PCI or PCI-X
- memory cycles, whereas the other structures reside on the host. The buffer
- size can be programmed between 256 bytes to 16k bytes. This driver uses the
- receive buffer size of 2048 bytes for an MTU of 1500.
- The Intel PRO/1000 F/XF/MF adapters only implement the TBI mode of the
- 8254x controller with built-in SERDESs in the adaptors.
- The Intel PRO/1000 T adapters based on 82543GC implement the GMII mode with
- a Gigabit Ethernet Transceiver (PHY) of MARVELL's Alaska 88E1000/88E1000S.
- However, the PRO/1000 XT/MT adapters based on 82540/82544/82545/82546 use
- the built-in PHY in controllers.
- The driver on the current release supports both GMII mode for Intel
- PRO1000T/XT/MT adapers and TBI mode for Intel PRO1000 F/XF/MF adapters. However,
- it requires the target-specific initialization code (sys543BoardInit ())
- to distinguish these kinds of adapters by PCI device IDs.
- EXTERNAL INTERFACE
- The driver provides the standard external interface, gei82543EndLoad(), which
- takes a string of colon separated parameters. The parameter string is parsed
- using strtok_r() and each parameter in converted from a string representation
- to a binary.
- The format of the parameter string is:
- "<memBase>:<memSize>:<nRxDes>:<nTxDes>:<flags>:<offset>:<mtu>"
- TARGET-SPECIFIC PARAMETERS
- .IP <memBase>
- This parameter is passed to the driver via gei82543EndLoad().
- The 8254x is a DMA-type device and typically shares access to some region of
- memory with the CPU. This driver is designed for systems that directly share
- memory between the CPU and the 8254x.
- This parameter can be used to specify an explicit memory region for use
- by the 8254x chip. This should be done on targets that restrict the 8254x
- to a particular memory region. The constant `NONE' can be used to indicate
- that there are such memory, in which case the driver will allocate cache safe
- memory for its use using cacheDmaAlloc().
- .IP <memSize>
- The memory size parameter specifies the size of the pre-allocated memory
- region. The driver checks the size of the provided memory region is adequate
- with respect to the given number of transmit Descriptor and Receive
- Descriptor.
- .IP <nRxDes>
- This parameter specifies the number of transmit descriptors to be
- allocated. If this number is 0, a default value of 24 will be used.
- .IP <nTxDes>
- This parameter specifies the number of receive descriptors to be
- allocated. If this parameter is 0, a default of 24 is used.
- .IP <flags>
- This parameter is provided for user to customize this device driver for their
- application.
- GEI_END_SET_TIMER (0x01): a timer will be started to constantly free back the
- loaned transmit mBlks.
- GEI_END_SET_RX_PRIORITY (0x02): packet transfer (receive) from device to host
- memory will have higher priority than the packet transfer (transmit) from host
- memory to device in the PCI bus. For end-station application, it is suggested
- to set this priority in favor of receive operation to avoid receive overrun.
- However, for routing applications, it is not necessary to use this priority.
- This option is only for 82543-based adapters.
- GEI_END_FREE_RESOURCE_DELAY (0x04): when transmitting larger packets, the
- driver will hold mblks(s) from the network stack and return them after the
- driver has completed transmitting the packet, and either the timer has expired
- or there are no more available descriptors. If this option is not used, the
- driver will free mblk(s) when ever the packet transmission is done. This option
- will place greater demands on the network pool and should only be used in
- systems which have sufficient memory to allocate a large network pool. It is
- not advised for the memory-limited target systems.
- GEI_END_TBI_COMPATIBILITY (0x200): if this driver enables the workaround for
- TBI compatibility HW bugs (#define INCLUDE_TBI_COMPATIBLE), user can set
- this bit to enable a software workaround for the well-known TBI compatibility
- HW bug in the Intel PRO1000 T adapter. This bug is only occured in the
- copper-and-82543-based adapter, and the link partner has advertised only
- 1000Base-T capability.
- .IP <offset>
- This parameter is provided for the architectures which need DWORD (4 byte)
- alignment of the IP header. In that case, the value of OFFSET should be two,
- otherwise, the default value is zero.
- .LP
- EXTERNAL SUPPORT REQUIREMENTS
- This driver requires one external support function:
- .CS
- STATUS sys82543BoardInit (int unit, ADAPTOR_INFO *pBoard)
- .CE
- This routine performs some target-specific initialization such as EEPROM
- validation and obtaining ETHERNET address and initialization control words
- (ICWs) from EEPROM. The routine also initializes the adaptor-specific data
- structure. Some target-specific functions used later in driver operation
- are hooked up to that structure. It's strongly recommended that users provide
- a delay function with higher timing resolution. This delay function will be
- used in the PHY's read/write operations if GMII is used. The driver will use
- taskDelay() by default if user can NOT provide any delay function, and
- this will probably result in very slow PHY initialization process. The user
- should also specify the PHY's type of MII or GMII. This routine returns OK,
- or ERROR if it fails.
- .LP
- SYSTEM RESOURCE USAGE
- The driver uses cacheDmaMalloc() to allocate memory to share with the 8254xGC.
- The size of this area is affected by the configuration parameters specified
- in the gei82543EndLoad() call.
- Either the shared memory region must be non-cacheable, or else the hardware
- must implement bus snooping. The driver cannot maintain cache coherency for
- the device because fields within the command structures are asynchronously
- modified by both the driver and the device, and these fields may share the
- same cache line.
- SYSTEM TUNING HINTS
- Significant performance gains may be had by tuning the system and network stack.
- This may be especially necessary for achiving gigabit transfer rates.
- Increasing the network stack's pools are strongly recommended. This driver
- borrows mblks from the network stack to accerlate packet transmitting.
- Theoretically, the number borrowed clusters could be the same as the number of
- the device's transmit descriptors. However, if the network stack has fewer
- available clusters than available transmit descriptors then this will result
- in reduced throughput. Therefore, increasing the network stack's number of
- clusters relative to the number of transmit descriptors will increase bandwidth.
- Of course this technique will eventually reach a point of diminishing return.
- There are actually several sizes of clusters available in the network pool.
- Increasing any or all of these cluster sizes will result in some increase in
- performance. However, increasing the 2048-byte cluster size will likely have
- the greatest impact since this size will hold an entire MTU and header.
- Increasing the number of receive descriptors and clusters may also have
- positive impact.
- Increasing the buffer size of sockets can also be beneficial. This can
- significantly improve performance for a target system under higher transfer
- rates. However, it should be noted that large amounts of unread buffers idling
- in sockets reduces the resources available to the rest of the stack. This can,
- in fact, have a negative impact on bandwidth. One method to reduce this effect
- is to carefully adjust application tasks' priorities and possibly increase
- number of receive clusters.
- Callback functions defined in the sysGei82543End.c can be used to dynamically
- and/or statically change the internal timer registers such as ITR, RADV, and
- RDTR to reduce RX interrupt rate.
- INTERNAL
- This library contains two conditional compilation switchs: DRV_DEBUG and
- INCLUDE_GEI82543_DEBUG_ROUTINE. If defined, debug routines will be included.
- And output message can be selected by gei82543GCDebug variable.
- SEE ALSO: muxLib, endLib
- .I "RS-82543GC GIGABIT ETHERNET CONTROLLER NETWORKING DEVELOPER'S MANUAL"
- */
- /* includes */
- #include "vxWorks.h"
- #include "stdlib.h"
- #include "cacheLib.h"
- #include "intLib.h"
- #include "end.h" /* common END structures. */
- #include "endLib.h"
- #include "lstLib.h" /* needed to maintain protocol list. */
- #include "wdLib.h"
- #include "iv.h"
- #include "semLib.h"
- #include "logLib.h"
- #include "netLib.h"
- #include "stdio.h"
- #include "sysLib.h"
- #include "errno.h"
- #include "errnoLib.h"
- #include "memLib.h"
- #include "iosLib.h"
- #undef ETHER_MAP_IP_MULTICAST
- #include "etherMultiLib.h" /* multicast stuff. */
- #include "net/mbuf.h"
- #include "net/unixLib.h"
- #include "net/protosw.h"
- #include "net/systm.h"
- #include "net/if_subr.h"
- #include "net/route.h"
- #include "sys/socket.h"
- #include "sys/ioctl.h"
- #include "sys/times.h"
- #include "drv/end/gei82543End.h"
- /* IMPORT */
- IMPORT STATUS sys82543BoardInit (int, ADAPTOR_INFO *);
- IMPORT int endMultiLstCnt (END_OBJ* pEnd);
- /* defines */
- #undef INCLUDE_TBI_COMPATIBLE
- /* all 8254x chip registers are 32 bit long*/
- #if (_BYTE_ORDER == _BIG_ENDIAN)
- #define GEI_READ_REG(offset,result)
- do {
- UINT32 temp;
- temp = ((*(volatile UINT32 *)(pDrvCtrl->devRegBase + (offset))));
- result = LONGSWAP(temp); /* swap the data */
- } while (0)
- #define GEI_WRITE_REG(offset, value)
- ((*(volatile UINT32 *)(pDrvCtrl->devRegBase + (offset))) =
- (UINT32) LONGSWAP(value))
- #define GEI_WRITE_DESC_WORD(pDesc, offset, value)
- (*(UINT16 *)((UINT32)pDesc + offset) =
- (MSB(value) | LSB(value)<<8) & 0xffff)
- #define GEI_WRITE_DESC_LONG(pDesc, offset, value)
- (*(UINT32 *)((UINT32)pDesc + offset) =
- (UINT32) LONGSWAP(value))
- #define GEI_READ_DESC_WORD(pDesc, offset, result)
- do {
- UINT16 temp;
- temp = *(UINT16 *)((UINT32)pDesc + offset);
- result = (MSB(temp) | (LSB(temp) << 8)) & 0xffff;
- } while (0)
- #define GEI_READ_DESC_LONG(pDesc, offset, result)
- do {
- UINT32 temp;
- temp = *(UINT32 *)((UINT32)pDesc + offset);
- result = LONGSWAP(temp); /* swap the data */
- } while (0)
- #else /* (_BYTE_ORDER == _BIG_ENDIAN) */
- #define GEI_READ_REG(offset, result)
- result = (*(volatile UINT32 *)(pDrvCtrl->devRegBase + (offset)))
- #define GEI_WRITE_REG(offset, value)
- ((*(volatile UINT32 *)(pDrvCtrl->devRegBase + (offset))) =
- (UINT32)(value))
- #define GEI_WRITE_DESC_WORD(pDesc, offset, value)
- (*(UINT16 *)((UINT32)pDesc + offset) = (UINT16)(value & 0xffff))
- #define GEI_WRITE_DESC_LONG(pDesc, offset, value)
- (*(UINT32 *)((UINT32)pDesc + offset) = (UINT32)value)
- #define GEI_READ_DESC_WORD(pDesc, offset, result)
- result = ((UINT16)(*(UINT16 *)((UINT32)pDesc + offset)) & 0xffff)
- #define GEI_READ_DESC_LONG(pDesc, offset, result)
- result = ((UINT32)( *(UINT32 *)((UINT32)pDesc + offset)))
- #endif /* (_BYTE_ORDER == _BIG_ENDIAN) */
- #define GEI_WRITE_DESC_BYTE(pDesc, offset, value)
- (*(UINT8 *)((UINT32)pDesc + offset) = (UINT8) (value & 0xff))
- #define GEI_READ_DESC_BYTE(pDesc, offset)
- ((UINT8)( *(UINT8 *)((UINT32)pDesc + offset)) & 0xff)
- #define GEI_GET_RX_DESC_ADDR(offset)
- (pDrvCtrl->pRxDescBase + ((offset) * RXDESC_SIZE))
- #define GEI_GET_TX_DESC_ADDR(offset)
- (pDrvCtrl->pTxDescBase + ((offset) * TXDESC_SIZE))
- #define GEI_GET_TX_DESC_CTL_ADDR(offset)
- (pDrvCtrl->pTxDesCtlBase + (offset));
- #define GEI_GET_TX_DESC_TAIL_UPDATE(tmp, num)
- (tmp) = (pDrvCtrl->txDescTail + (num)) % (pDrvCtrl->txDescNum)
- #define GEI_GET_RX_DESC_TAIL_UPDATE(tmp, num)
- (tmp) = (pDrvCtrl->rxDescTail + (num)) % (pDrvCtrl->rxDescNum)
- #define ROUND_UP_MULTIPLE(x, y)
- ( ( ( x + ( y - 1 ) ) / y ) * y )
- /* bus/CPU address translation macros */
- #define GEI_VIRT_TO_BUS(virtAddr)
- (GEI_PHYS_TO_BUS (((UINT32) GEI_VIRT_TO_PHYS (virtAddr))))
- #define GEI_BUS_TO_VIRT(busAddr)
- ((GEI_PHYS_TO_VIRT ((UINT32) GEI_BUS_TO_PHYS (busAddr))))
- #define GEI_PHYS_TO_VIRT(physAddr)
- END_CACHE_PHYS_TO_VIRT ((char *)(physAddr))
- #define GEI_VIRT_TO_PHYS(virtAddr)
- END_CACHE_VIRT_TO_PHYS ((char *)(virtAddr))
- #define GEI_PHYS_TO_BUS(physAddr)
- PHYS_TO_BUS_ADDR (pDrvCtrl->unit, (physAddr))
- #define GEI_BUS_TO_PHYS(busAddr)
- BUS_TO_PHYS_ADDR (pDrvCtrl->unit, (busAddr))
- /* cache macros */
- #define END_CACHE_INVALIDATE(address, len)
- CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
- #define END_CACHE_PHYS_TO_VIRT(address)
- CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
- #define END_CACHE_VIRT_TO_PHYS(address)
- CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
- /* misc. */
- #define GEI_DESC_ALIGN_BYTE (128)
- /*
- * Default macro definitions for BSP interface.
- * These macros can be redefined in a wrapper file, to generate
- * a new module with an optimized interface.
- */
- /* macro to connect interrupt handler to vector */
- #ifndef SYS_INT_CONNECT
- #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)
- {
- *pResult = OK;
- if (pDrvCtrl->adaptor.intConnect)
- *pResult = (pDrvCtrl->adaptor.intConnect) ((VOIDFUNCPTR *)
- INUM_TO_IVEC (pDrvCtrl->adaptor.vector),
- rtn, (int)arg);
- }
- #endif
- /* macro to disconnect interrupt handler from vector */
- #ifndef SYS_INT_DISCONNECT
- #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)
- {
- *pResult = OK;
- if (pDrvCtrl->adaptor.intDisConnect)
- *pResult = (pDrvCtrl->adaptor.intDisConnect) ((VOIDFUNCPTR *)
- INUM_TO_IVEC (pDrvCtrl->adaptor.vector),
- rtn, (int)arg);
- }
- #endif
- /* macro to enable the appropriate interrupt level */
- #ifndef SYS_INT_ENABLE
- #define SYS_INT_ENABLE(pDrvCtrl)
- {
- pDrvCtrl->adaptor.intEnable(pDrvCtrl->unit);
- }
- #endif
- #ifndef SYS_INT_DISABLE
- #define SYS_INT_DISABLE(pDrvCtrl)
- {
- pDrvCtrl->adaptor.intDisable(pDrvCtrl->unit);
- }
- #endif
- /*
- * a shortcut for getting the hardware address
- * from the MIB II stuff.
- */
- #define END_HADDR(pEnd)
- ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
- #define END_HADDR_LEN(pEnd)
- ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
- /* device structure */
- typedef struct end_device
- {
- END_OBJ end; /* the class we inherit from. */
- int unit; /* unit number */
- UINT32 flags; /* flags for device configuration */
- UINT32 usrFlags; /* flags for user customization */
- CACHE_FUNCS cacheFuncs; /* cache function pointers */
- CL_POOL_ID pClPoolId; /* cluster pool ID */
- ADAPTOR_INFO adaptor; /* adaptor information */
- UINT32 devRegBase; /* virtual base address for registers */
- P_TX_DESCTL pTxDesCtlBase; /* pointer to the TX management array base */
- char *pTxDescBase; /* pointer to the TX descriptor base */
- char *pRxDescBase; /* pointer to the RX descriptor base */
- char * pRxBufBase; /* pointer to the RX buffer base */
- volatile int txDescTail; /* index to the TX tail */
- volatile int rxDescTail; /* index to the RX tail */
- int txDescNum; /* num of TX descriptors */
- int rxDescNum; /* num of RX descriptors */
- UINT32 rxBufSize; /* RX buffer size */
- UINT32 txReqDescNum; /* request number for TX descriptor */
- int mtu; /* maximum transfer unit */
- volatile int rxtxHandling; /* indicator for RX handling */
- volatile BOOL txStall; /* indicator for transmit stall */
- BOOL txActivity; /* TX activity flag */
- int txIntDelay; /* delay time for TX interrupt */
- int rxIntDelay; /* delay time for RX interrupt */
- int maxRxNumPerInt; /* maximum RX packets processed per Int */
- BOOL dmaPriority; /* indicator for TX/RX DMA prefer */
- UINT32 timerInterval; /* interval for timer interrupt */
- BOOL timerCheckTxStall; /* indicator for txStall checking */
- UINT32 multiCastFilterType; /* indicator of multicast table type */
- int flowCtrl; /* flow control setting */
- STATUS linkInitStatus; /* the status of first link */
- volatile UINT32 linkStatus; /* indicator for link status */
- BOOL linkMethod; /* indicator for link approaches */
- WDOG_ID timerId; /* timer ID */
- UINT32 txConfigureWord; /* copy of TX configuration word register */
- UINT32 devCtrlRegVal; /* control register value */
- UINT32 speed; /* device speed */
- UINT32 duplex; /* device duplex mode */
- UINT32 offset; /* offset for IP header */
- UINT32 cableType; /* cable type (Fiber or Copper) */
- BOOL memAllocFlag; /* indicator that the shared memory */
- /* allocated by driver */
- char * pMemBase; /* memory base for TX/RX area */
- int memSize; /* total memory size for RX/TX area */
- char * pMclkArea; /* address of Mclk */
- char * pTxPollBufAdr; /* address for TX buffer in polling mode */
- PHY_INFO * pPhyInfo; /* pointer to phyInfo structure */
- UINT32 phyInitFlags; /* Initial PHY flags for phyInfo */
- volatile UINT32 txDescLastCheck; /* index of the last checked TX desc */
- volatile UINT32 txDescFreeNum; /* available/usable TX desc number */
- STA_REG staRegs; /* statistic register structure */
- BOOL txResoFreeQuick; /* flag to free loaned mBlk quickly */
- volatile BOOL attach; /* indicator for drive attach */
- volatile BOOL devStartFlag; /* indicator for device start */
- UINT32 rxtxHandlerNum; /* num of rxtx handler calling */
- UINT32 rxIntCount; /* receive interrupt count */
- UINT32 txIntCount; /* transmit interrupt count */
- UINT32 rxORunIntCount; /* num of RX overrun interrupt count */
- UINT32 rxPacketNum; /* statistic RX packet number */
- UINT32 rxPacketDrvErr ; /* num of RX packet drop due to no resc */
- #ifdef INCLUDE_TBI_COMPATIBLE
- BOOL tbiCompatibility; /* TBI compatibility for HW bug */
- #endif
- } END_DEVICE;
- /* DEBUG MACROS */
- #undef DRV_DEBUG
- #undef INCLUDE_GEI82543_DEBUG_ROUTINE
- #undef GEI82543_NO_LOCAL
- #ifdef DEBUG
- #define LOGMSG(x,a,b,c,d,e,f)
- if (endDebug)
- {
- logMsg (x,a,b,c,d,e,f);
- }
- #else
- #define LOGMSG(x,a,b,c,d,e,f)
- #endif /* DEBUG */
- #ifdef GEI82543_NO_LOCAL
- #undef LOCAL
- #define LOCAL
- #endif
- #ifdef DRV_DEBUG
- #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_LOAD 0x0020
- #define DRV_DEBUG_IOCTL 0x0040
- #define DRV_DEBUG_TIMER 0x20000
- int gei82543GCDebug = 0x0;
- #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
- if (gei82543GCDebug & FLG)
- logMsg(X0, X1, X2, X3, X4, X5, X6);
- #define DRV_PRINT(FLG,X)
- if (gei82543GCDebug & FLG) printf X;
- #else /* DRV_DEBUG */
- #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
- #define DRV_PRINT(DBG_SW,X)
- #endif /* DRV_DEBUG */
- #ifdef INCLUDE_GEI82543_DEBUG_ROUTINE
- LOCAL void gei82543LedOff (int);
- LOCAL void gei82543LedOn (int);
- LOCAL void gei82543StatusShow (int);
- LOCAL UINT32 gei82543RegGet (int,UINT32);
- LOCAL void gei82543RegSet (int,UINT32, UINT32);
- #ifdef INCLUDE_TBI_COMPATIBLE
- LOCAL void gei82543TbiCompWr (int, int);
- #endif /* INCLUDE_TBI_COMPATIBLE */
- #endif /* INCLUDE_GEI82543_DEBUG_ROUTINE */
- /* forward functions */
- LOCAL void gei82543EndTimerHandler (END_DEVICE *);
- LOCAL void gei82543MemAllFree (END_DEVICE *);
- LOCAL STATUS gei82543linkStatusCheck (END_DEVICE *);
- LOCAL void gei82543TxRxEnable (END_DEVICE *);
- LOCAL void gei82543TxRxDisable (END_DEVICE *);
- LOCAL void gei82543Delay (END_DEVICE *, UINT32);
- LOCAL void gei82543RxSetup (END_DEVICE *);
- LOCAL void gei82543TxSetup (END_DEVICE *);
- LOCAL STATUS gei82543HwInit (END_DEVICE *);
- LOCAL void gei82543RxDesUpdate (END_DEVICE *,char *);
- LOCAL void gei82543DuplexGet (END_DEVICE *);
- LOCAL void gei82543SpeedGet (END_DEVICE *);
- LOCAL void gei82543HwStatusDump (END_DEVICE *);
- LOCAL STATUS gei82543linkInit (END_DEVICE *);
- LOCAL STATUS gei82543linkTBISetup (END_DEVICE *,BOOL);
- LOCAL STATUS gei82543TBIlinkForce (END_DEVICE *,BOOL, BOOL);
- LOCAL STATUS gei82543TBIHwAutoNegotiate (END_DEVICE *,BOOL, BOOL);
- LOCAL void gei82543EtherRxAdrSet (END_DEVICE *,UINT8 adr[],int);
- LOCAL void gei82543AllRxAdrClean (END_DEVICE *);
- LOCAL void gei82543McastAdrClean (END_DEVICE *);
- LOCAL void gei82543AllMtaAdrClean (END_DEVICE *);
- LOCAL void gei82543AllVlanClean (END_DEVICE *);
- LOCAL UINT32 gei82543DisableChipInt (END_DEVICE *);
- LOCAL void gei82543EnableChipInt (END_DEVICE *);
- LOCAL void gei82543Reset (END_DEVICE *);
- LOCAL void gei82543TxMblkFree (END_DEVICE *,int);
- LOCAL void gei82543TxMblkWaitClean (END_DEVICE *);
- LOCAL STATUS gei82543EndMCastAdd (END_DEVICE *,char*);
- LOCAL STATUS gei82543EndMCastDel (END_DEVICE *,char*);
- LOCAL STATUS gei82543EndMCastGet (END_DEVICE *,MULTI_TABLE*);
- LOCAL void gei82543EndInt (END_DEVICE *);
- LOCAL void gei82543RxTxIntHandle (END_DEVICE *);
- LOCAL STATUS gei82543Recv (END_DEVICE *,char *, UINT8);
- LOCAL void gei82543EndConfigure (END_DEVICE *);
- LOCAL void gei82543FlowCtrlRegsSet (END_DEVICE *);
- LOCAL STATUS gei82543PhyWrite (END_DEVICE *,UINT8,UINT8,UINT16);
- LOCAL STATUS gei82543PhyRead (END_DEVICE *,UINT8,UINT8,
- UINT16 *);
- LOCAL STATUS gei82544PhyWrite (END_DEVICE *,UINT8,UINT8,UINT16);
- LOCAL STATUS gei82544PhyRead (END_DEVICE *,UINT8,UINT8,
- UINT16 *);
- LOCAL void gei82543LoanTransmit (END_DEVICE *,M_BLK_ID);
- LOCAL void gei82543TxResoFree (END_DEVICE *);
- LOCAL int gei82543TxDesCleanGet (END_DEVICE *,int);
- LOCAL UINT32 gei82543TxStallCheck (END_DEVICE *);
- LOCAL void gei82543GMIIphyConfig (END_DEVICE *);
- LOCAL void gei82543GMIIphyReConfig (END_DEVICE *);
- LOCAL STATUS gei82543linkGMIISetup (END_DEVICE *);
- LOCAL STATUS gei82543linkGMIIPreInit (END_DEVICE *);
- /* END specific interfaces. */
- /* This is the only externally visible interface. */
- END_OBJ* gei82543EndLoad (char* initString);
- LOCAL STATUS gei82543EndStart (END_DEVICE* pDrvCtrl);
- LOCAL STATUS gei82543EndStop (END_DEVICE* pDrvCtrl);
- LOCAL int gei82543EndIoctl (END_DEVICE* pDrvCtrl, int cmd,
- caddr_t data);
- LOCAL STATUS gei82543EndUnload (END_DEVICE* pDrvCtrl);
- LOCAL STATUS gei82543EndSend (END_DEVICE* pDrvCtrl,
- M_BLK_ID pBuf);
- LOCAL STATUS gei82543EndMCastAdd (END_DEVICE* pDrvCtrl,
- char* pAddress);
- LOCAL STATUS gei82543EndMCastDel (END_DEVICE* pDrvCtrl,
- char* pAddress);
- LOCAL STATUS gei82543EndMCastGet (END_DEVICE* pDrvCtrl,
- MULTI_TABLE* pTable);
- LOCAL STATUS gei82543EndPollStart (END_DEVICE* pDrvCtrl);
- LOCAL STATUS gei82543EndPollStop (END_DEVICE* pDrvCtrl);
- LOCAL STATUS gei82543EndPollSend (END_DEVICE* pDrvCtrl,
- M_BLK_ID pBuf);
- LOCAL STATUS gei82543EndPollRcv (END_DEVICE* pDrvCtrl,
- M_BLK_ID pBuf);
- LOCAL void gei82543AddrFilterSet (END_DEVICE* pDrvCtrl);
- LOCAL STATUS gei82543EndParse (END_DEVICE*, char *);
- LOCAL STATUS gei82543EndMemInit (END_DEVICE*);
- /*
- * Declare our function table. This is LOCAL across all driver
- * instances.
- */
- LOCAL NET_FUNCS gei82543EndFuncTable =
- {
- (FUNCPTR) gei82543EndStart, /* Function to start the device. */
- (FUNCPTR) gei82543EndStop, /* Function to stop the device. */
- (FUNCPTR) gei82543EndUnload, /* Unloading function for the driver. */
- (FUNCPTR) gei82543EndIoctl, /* Ioctl function for the driver. */
- (FUNCPTR) gei82543EndSend, /* Send function for the driver. */
- (FUNCPTR) gei82543EndMCastAdd, /* Multicast add function for the */
- /* driver. */
- (FUNCPTR) gei82543EndMCastDel, /* Multicast delete function for */
- /* the driver. */
- (FUNCPTR) gei82543EndMCastGet, /* Multicast retrieve function for */
- /* the driver. */
- (FUNCPTR) gei82543EndPollSend, /* Polling send function */
- (FUNCPTR) gei82543EndPollRcv, /* Polling receive function */
- endEtherAddressForm, /* put address info into a NET_BUFFER */
- endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
- endEtherPacketAddrGet /* Get packet addresses. */
- };
- /*************************************************************************
- *
- * gei82543EndLoad - initialize the driver and device
- *
- * This routine initializes the driver and the device to the operational state.
- * All of the device specific parameters are passed in the initString.
- *
- * The string contains the target specific parameters like this:
- * "unitnum:shmem_addr:shmem_size:rxDescNum:txDescNum:usrFlags:offset:mtu"
- *
- * RETURNS: an END object pointer, NULL if error, or zero
- */
- END_OBJ* gei82543EndLoad
- (
- char *initString /* String to be parsed by the driver. */
- )
- {
- END_DEVICE *pDrvCtrl = NULL; /* pointer to device structure */
- DRV_LOG (DRV_DEBUG_LOAD, "Loading gei82543End Driver...n",
- 1, 2, 3, 4, 5, 6);
- /* sanity check */
- if (initString == NULL)
- return NULL;
- if (initString[0] == 0)
- {
- bcopy ((char *) DEVICE_NAME, (void *)initString, DEVICE_NAME_LENGTH);
- return 0;
- }
- /* allocate the device structure */
- pDrvCtrl = (END_DEVICE *)calloc (sizeof (END_DEVICE), 1);
- if (pDrvCtrl == NULL)
- goto errorExit;
- /* clean up driver structure */
- memset((void *)pDrvCtrl, 0, sizeof (END_DEVICE));
- /* parse the init string, filling in the device structure */
- if (gei82543EndParse (pDrvCtrl, initString) == ERROR)
- goto errorExit;
- /* zero adaptor structure */
- memset ((void *)&pDrvCtrl->adaptor, 0, sizeof(ADAPTOR_INFO));
- /* call BSP routine to get PCI information*/
- if (sys82543BoardInit (pDrvCtrl->unit, &pDrvCtrl->adaptor) != OK)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "Error in getting board infon",
- 1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- /* set up the base register */
- pDrvCtrl->devRegBase = (UINT32)(pDrvCtrl->adaptor.regBaseLow);
- /* set up device structure based on user's flags */
- if (pDrvCtrl->usrFlags & GEI_END_JUMBO_FRAME_SUPPORT)
- {
- if (pDrvCtrl->mtu <= 0)
- pDrvCtrl->mtu = GEI_DEFAULT_JUMBO_MTU_SIZE;
- pDrvCtrl->mtu = (pDrvCtrl->mtu <= ETHERMTU)? ETHERMTU :
- ((pDrvCtrl->mtu > GEI_MAX_JUMBO_MTU_SIZE)?
- GEI_MAX_JUMBO_MTU_SIZE : pDrvCtrl->mtu);
- }
- else /* normal frame */
- pDrvCtrl->mtu = ETHERMTU;
- /* increase transmit storage in FIFO for jumbo frames */
- if (pDrvCtrl->mtu > ETHERMTU)
- {
- GEI_WRITE_REG(INTEL_82543GC_PBA, 0x20); /* 24KB for TX buffer */
- }
- /* perform memory allocation for descriptors */
- if (gei82543EndMemInit (pDrvCtrl) == ERROR)
- goto errorExit;
- /* set up device structure based on user's flags */
- if (pDrvCtrl->usrFlags & GEI_END_SET_TIMER)
- {
- pDrvCtrl->timerId = wdCreate ();
- if (pDrvCtrl->timerId == NULL)
- DRV_LOG (DRV_DEBUG_LOAD, ("create timer failsn"),
- 1, 2, 3, 4, 5, 6);
- }
- if (pDrvCtrl->usrFlags & GEI_END_SET_RX_PRIORITY)
- pDrvCtrl->dmaPriority = DMA_RX_PRIORITY;
- else
- pDrvCtrl->dmaPriority = DMA_FAIR_RX_TX;
- if (pDrvCtrl->usrFlags & GEI_END_FREE_RESOURCE_DELAY)
- {
- pDrvCtrl->txIntDelay = TXINT_DELAY_MORE;
- pDrvCtrl->txResoFreeQuick = FALSE;
- }
- else
- {
- pDrvCtrl->txIntDelay = TXINT_DELAY_LESS;
- pDrvCtrl->txResoFreeQuick = TRUE;
- }
- #ifdef INCLUDE_TBI_COMPATIBLE
- pDrvCtrl->tbiCompatibility = FALSE;
- #endif /* INCLUDE_TBI_COMPATIBLE */
- /* stop/reset the chip before configuration */
- gei82543Reset (pDrvCtrl);
- /* disable all chip interrupt */
- gei82543DisableChipInt (pDrvCtrl);
- /* turn off system interrupts */
- SYS_INT_DISABLE(pDrvCtrl);
- /* set the default value for device */
- pDrvCtrl->rxIntDelay = DEFAULT_RXINT_DELAY;
- pDrvCtrl->maxRxNumPerInt = DEFAULT_RXRES_PROCESS_FACTOR *
- pDrvCtrl->rxDescNum;
- pDrvCtrl->timerInterval = DEFAULT_TIMER_INTERVAL;
- pDrvCtrl->flowCtrl = DEFAULT_FLOW_CONTRL;
- pDrvCtrl->duplex = DEFAULT_DUPLEX_MODE;
- /* Misc. setting */
- pDrvCtrl->flags = 0;
- pDrvCtrl->linkStatus = LINK_STATUS_UNKNOWN;
- pDrvCtrl->linkMethod = GEI82543_HW_AUTO;
- pDrvCtrl->txConfigureWord = (TXCW_ANE_BIT | TXCW_FD_BIT);
- pDrvCtrl->multiCastFilterType = DEFAULT_MULTI_FILTER_TYPE;
- pDrvCtrl->attach = FALSE;
- pDrvCtrl->devStartFlag = FALSE;
- /* initialize the END and MIB2 parts of the structure */
- /*
- * The M2 element must come from m2Lib.h
- * This setting is for a DIX type ethernet device.
- */
- if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, DEVICE_NAME,
- pDrvCtrl->unit, &gei82543EndFuncTable,
- "gei82543End Driver.") == ERROR ||
- END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
- &pDrvCtrl->adaptor.enetAddr[0], 6, pDrvCtrl->mtu,
- END_SPEED) == ERROR )
- goto errorExit;
- /* disable RX/TX operations now, will be re-enable in Start function */
- gei82543TxRxDisable (pDrvCtrl);
- pDrvCtrl->attach = TRUE;
- DRV_LOG (DRV_DEBUG_LOAD, ("loading gei82543End...OKn"),1,2,3,4,5,6);
- return (&pDrvCtrl->end);
- errorExit:
- /* free all allocated memory */
- gei82543MemAllFree (pDrvCtrl);
- if (pDrvCtrl != NULL)
- free ((char *)pDrvCtrl);
- DRV_LOG (DRV_DEBUG_LOAD, ("Loading gei82543End...Errorn"),
- 1, 2, 3, 4, 5, 6);
- return NULL;
- }
- /*************************************************************************
- *
- * gei82534EndParse - parse the init string
- *
- * Parse the input string. Fill in values in the driver control structure.
- *
- * RETURNS: OK or ERROR for invalid arguments.
- */
- LOCAL STATUS gei82543EndParse
- (
- END_DEVICE * pDrvCtrl, /* device pointer */
- char * initString /* information string */
- )
- {
- char * tok;
- char * pHolder = NULL;
- DRV_LOG (DRV_DEBUG_LOAD, ("gei82543EndParse...n"), 1, 2, 3, 4, 5, 6);
- /* parse the initString */
- tok = strtok_r (initString, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->unit = atoi (tok);
- /* address of shared memory */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->pMemBase = (char *) strtoul (tok, NULL, 16);
- /* size of shared memory */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->memSize = strtoul (tok, NULL, 16);
- /* number of rx descriptors */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->rxDescNum = strtoul (tok, NULL, 16);
- /* number of tx descriptors */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->txDescNum = strtoul (tok, NULL, 16);
- /* get the usrFlags */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->usrFlags = strtoul (tok, NULL, 16);
- /* get the offset value */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok != NULL)
- pDrvCtrl->offset = atoi (tok);
- DRV_LOG (DRV_DEBUG_LOAD,
- ("gei82543EndParse: unit=%d pMemBase=0x%x memSize=0x%x
- rxDescNums=%d txDescNum=%d, usrFlags=0x%xn"),
- pDrvCtrl->unit,
- (int)pDrvCtrl->pMemBase,
- (int) pDrvCtrl->memSize,
- pDrvCtrl->rxDescNum,
- pDrvCtrl->txDescNum,
- pDrvCtrl->usrFlags
- );
- /* check Jumbo Frame support */
- if (pDrvCtrl->usrFlags & GEI_END_JUMBO_FRAME_SUPPORT)
- {
- /* get mtu */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok != NULL)
- pDrvCtrl->mtu = atoi (tok);
- DRV_LOG (DRV_DEBUG_LOAD, ("mtu = %dn"),pDrvCtrl->mtu,
- 2, 3, 4, 5, 6);
- }
- return OK;
- }
- /*************************************************************************
- *
- * gei82543MemAllFree - free all memory allocated by driver
- *
- * This routine returns all allocated memory by this driver to OS
- *
- * RETURN: N/A
- */
- LOCAL void gei82543MemAllFree
- (
- END_DEVICE * pDrvCtrl /* device to be initialized */
- )
- {
- if (pDrvCtrl == NULL)
- return;
- /* release TxDesCtl */
- if (pDrvCtrl->pTxDesCtlBase != NULL)
- {
- free (pDrvCtrl->pTxDesCtlBase);
- }
- if (pDrvCtrl->pTxPollBufAdr != NULL)
- {
- cacheDmaFree (pDrvCtrl->pTxPollBufAdr);
- }
- /* release TX/RX descriptors and RX buffer */
- if (pDrvCtrl->pMemBase != NULL && (pDrvCtrl->memAllocFlag == TRUE))
- {
- cacheDmaFree (pDrvCtrl->pMemBase);
- }
- /* release RX mBlk pool */
- if (pDrvCtrl->pMclkArea != NULL)
- {
- cfree (pDrvCtrl->pMclkArea);
- }
- /* release netPool structure */
- if (pDrvCtrl->end.pNetPool != NULL)
- {
- if (netPoolDelete(pDrvCtrl->end.pNetPool) != OK)
- {
- LOGMSG("netPoolDelete failsn", 0,0,0,0,0,0);
- }
- free ((char *)pDrvCtrl->end.pNetPool);
- }
- return;
- }
- /*************************************************************************
- *
- * gei82543EndMemInit - allocate and initialize memory for driver
- *
- * This routine allocates and initializes memory for descriptors and
- * corresponding buffers, and sets up the receive data pool for receiving
- * packets.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS gei82543EndMemInit
- (
- END_DEVICE * pDrvCtrl /* device to be initialized */
- )
- {
- M_CL_CONFIG geiMclBlkConfig; /* Mblk */
- CL_DESC geiClDesc; /* Cluster descriptor */
- UINT32 size; /* required memory size */
- UINT32 tmpBase; /* temporary memory base */
- UINT32 bufSz; /* real cluster size */
- int bufNum; /* temp variable */
- DRV_LOG (DRV_DEBUG_LOAD, ("gei82543EndMemInit...n"), 1, 2, 3, 4, 5, 6);
- /* set the default TX/RX descriptor Number */
- if (pDrvCtrl->txDescNum == 0)
- pDrvCtrl->txDescNum = DEFAULT_NUM_TXDES;
- if (pDrvCtrl->rxDescNum == 0)
- pDrvCtrl->rxDescNum = DEFAULT_NUM_RXDES;
- /* round up to multiple of 8, hardware requirement */
- pDrvCtrl->txDescNum = ROUND_UP_MULTIPLE(pDrvCtrl->txDescNum,
- INTEL_82543GC_MULTIPLE_DES);
- pDrvCtrl->rxDescNum = ROUND_UP_MULTIPLE((UINT32)pDrvCtrl->rxDescNum,
- (UINT32)INTEL_82543GC_MULTIPLE_DES);
- /* calculate reasonable receive buffer size */
- size = pDrvCtrl->mtu + GEI_DEFAULT_ETHERHEADER + ETHER_CRC_LENGTH;
- if (size > GEI_MAX_FRAME_SIZE)
- return ERROR;
- if (pDrvCtrl->usrFlags & GEI_END_JUMBO_FRAME_SUPPORT)
- {
- for (bufSz = 2048; bufSz <= 16384; bufSz = bufSz << 1)
- {
- if (size <= bufSz)
- {
- pDrvCtrl->rxBufSize = bufSz;
- break;
- }
- }
- }
- else /* normal frame */
- pDrvCtrl->rxBufSize = 2048;
- /* add cluster ID and offset */
- bufSz = size + pDrvCtrl->offset + CL_OVERHEAD;
- bufNum = bufSz / GEI_DESC_ALIGN_BYTE;
- if (bufSz != (bufNum * GEI_DESC_ALIGN_BYTE))
- bufSz = (bufNum + 1) * GEI_DESC_ALIGN_BYTE;
- /* get the needed memory size */
- size = pDrvCtrl->txDescNum * TXDESC_SIZE + /* for TX descriptor */
- pDrvCtrl->rxDescNum * RXDESC_SIZE + /* for RX descriptor */
- pDrvCtrl->rxDescNum * bufSz * /* for RX buffer */
- (DEFAULT_LOAN_RXBUF_FACTOR + 1) + /* for RX loan buffer */
- 1024; /* for alignment */
- if ((int)(pDrvCtrl->pMemBase) == NONE)
- {
- if (!CACHE_DMA_IS_WRITE_COHERENT ())
- {
- DRV_LOG (DRV_DEBUG_LOAD, ("gei82543EndMemInit: shared memory not
- cache coherentn"), 1, 2, 3, 4, 5, 6);
- return ERROR;
- }
- /* alloc memory in driver */
- pDrvCtrl->pMemBase = cacheDmaMalloc (size);
- if (pDrvCtrl->pMemBase == NULL) /* no memory available */
- {
- DRV_LOG (DRV_DEBUG_LOAD, ("gei82543EndMemInit: could not obtain
- memoryn"), 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- pDrvCtrl->memSize = size;
- pDrvCtrl->cacheFuncs = cacheDmaFuncs;
- pDrvCtrl->memAllocFlag = TRUE;
- }
- else
- {
- /*
- * if user has provided a shared memory, we assume
- * it is a cache safe area
- */
- if (pDrvCtrl->memSize < size)
- {
- DRV_LOG (DRV_DEBUG_LOAD, ("GEI82543EndMemInit: not enough
- memoryn"), 1, 2, 3, 4, 5, 6);
- return ERROR;
- }
- pDrvCtrl->cacheFuncs = cacheNullFuncs;
- pDrvCtrl->memAllocFlag = FALSE;
- }
- /* zero the pre-provided or allocated memory */
- memset((void *)pDrvCtrl->pMemBase, 0, size);
- /* set the TX descriptor base address, align to 128 byte */
- pDrvCtrl->pTxDescBase = (char *)(((UINT32)(pDrvCtrl->pMemBase) +
- (GEI_DESC_ALIGN_BYTE - 1)) &
- ~(GEI_DESC_ALIGN_BYTE - 1));
- /* set the RX descriptor base Address */
- pDrvCtrl->pRxDescBase = (char *)GEI_GET_TX_DESC_ADDR(pDrvCtrl->txDescNum);
- tmpBase = (UINT32)GEI_GET_RX_DESC_ADDR(pDrvCtrl->rxDescNum);
- /* set the RX buffer base address */
- pDrvCtrl->pRxBufBase = (char *)(((tmpBase + (GEI_DESC_ALIGN_BYTE)) &
- ~(GEI_DESC_ALIGN_BYTE - 1)) - CL_OVERHEAD);
- /* allocate memory for txDescriptor manager array */
- size = pDrvCtrl->txDescNum * sizeof(TX_DESCTL);
- pDrvCtrl->pTxDesCtlBase = (P_TX_DESCTL) malloc (size);
- if ((pDrvCtrl->pTxDesCtlBase) == NULL)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndMemInit: TxDesCtl memory
- unavailablen",1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- /* get a buffer for TX polling mode */
- pDrvCtrl->pTxPollBufAdr = cacheDmaMalloc (bufSz);
- if ((pDrvCtrl->pTxPollBufAdr) == NULL)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndMemInit: Tx Polling memory
- unavailablen",1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- /* clean up txDesCtl memory */
- memset((void *)pDrvCtrl->pTxDesCtlBase, 0, size);
- /*
- * set up RX mBlk pool
- * This is how we set up and END netPool using netBufLib(1).
- * This code is pretty generic.
- */
- if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
- goto errorExit;
- bzero ((char *)&geiMclBlkConfig, sizeof(geiMclBlkConfig));
- bzero ((char *)&geiClDesc, sizeof(geiClDesc));
- geiMclBlkConfig.mBlkNum = pDrvCtrl->rxDescNum *
- (DEFAULT_MBLK_NUM_FACTOR + 1);
- geiClDesc.clNum = pDrvCtrl->rxDescNum *
- (DEFAULT_LOAN_RXBUF_FACTOR + 1);
- geiClDesc.clSize = bufSz - CL_OVERHEAD;
- geiMclBlkConfig.clBlkNum = geiClDesc.clNum;
- /* calculate the total memory for all the M-Blks and CL-Blks. */
- geiMclBlkConfig.memSize =
- ((geiMclBlkConfig.mBlkNum * (M_BLK_SZ + sizeof (long))) +
- (geiMclBlkConfig.clBlkNum * CL_BLK_SZ + sizeof(long)));
- if ((geiMclBlkConfig.memArea = (char *) memalign (sizeof(long),
- geiMclBlkConfig.memSize)) ==
- NULL)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndMemInit: MclBlkConfig memory
- unavailablen",1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- pDrvCtrl->pMclkArea = geiMclBlkConfig.memArea;
- geiClDesc.memSize = geiClDesc.clNum * (geiClDesc.clSize + CL_OVERHEAD);
- geiClDesc.memArea = (char *)(pDrvCtrl->pRxBufBase);
- geiClDesc.memArea = (char *)(((UINT32) geiClDesc.memArea + 0x3) & ~0x3);
- /* initialize the memory pool. */
- if (netPoolInit(pDrvCtrl->end.pNetPool, &geiMclBlkConfig,
- &geiClDesc, 1,NULL) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndMemInit: Could not
- init bufferingn", 1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->end.pNetPool,
- geiClDesc.clSize, FALSE)) == NULL)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndMemInit: Could not find specified
- pool IDn", 1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- CACHE_PIPE_FLUSH ();
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndMemInit...OKn", 1, 2, 3, 4, 5, 6);
- return OK;
- errorExit:
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndMemInit...ERRORn", 1, 2, 3,4,5,6);
- return ERROR;
- }
- /*************************************************************************
- *
- * gei82543EndStart - setup and start the device
- *
- * This routine connects interrupts, initializes receiver and transmitter,
- * and enable the device for running
- *
- * RETURNS: OK or ERROR
- */
- LOCAL STATUS gei82543EndStart
- (
- END_DEVICE * pDrvCtrl /* device ID */
- )
- {
- STATUS result; /* results of start device */
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStart...n", 1, 2, 3, 4, 5, 6);
- if (pDrvCtrl->attach != TRUE)
- return ERROR;
- /* disable all chip interrupts */
- gei82543DisableChipInt (pDrvCtrl);
- /* turn off system interrupts */
- SYS_INT_DISABLE(pDrvCtrl);
- /* initialize the hardware and set up link */
- if (gei82543HwInit (pDrvCtrl) != OK)
- {
- DRV_LOG (DRV_DEBUG_LOAD, ("gei82543EndStart: link setup failsn"),
- 1, 2, 3, 4, 5, 6);
- LOGMSG("link failsn", 1, 2, 3, 4, 5, 6);
- }
- /* disable TX/RX now */
- gei82543TxRxDisable (pDrvCtrl);
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStart: set up TX structuren",
- 1, 2, 3, 4, 5, 6);
- /* initialize SW/HW structures for TX */
- gei82543TxSetup (pDrvCtrl);
- /* initialize SW/HW structure for RX */
- gei82543RxSetup (pDrvCtrl);
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStart: configure devicen",
- 1, 2, 3, 4, 5, 6);
- /* configure devices */
- pDrvCtrl->flags = DEFAULT_DRV_FLAGS;
- END_FLAGS_CLR (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
- gei82543EndConfigure (pDrvCtrl);
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStart: Connect interruptn",
- 1, 2, 3, 4, 5, 6);
- /* connect interrupt handler */
- SYS_INT_CONNECT(pDrvCtrl, gei82543EndInt, (int)pDrvCtrl, &result);
- if (result == ERROR)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStart: connect interrupt
- ERROR !n", 1, 2, 3, 4, 5, 6);
- return ERROR;
- }
- /* clean up all statistic registers */
- gei82543HwStatusDump (pDrvCtrl);
- /* clean all pending interrupts */
- gei82543DisableChipInt (pDrvCtrl);
- /* turn on system interrupt */
- SYS_INT_ENABLE(pDrvCtrl);
- /* enable interrupt in chip level */
- gei82543EnableChipInt (pDrvCtrl);
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStart: Interrupt enablen",
- 1, 2, 3, 4, 5, 6);
- /* set the END flags, make driver ready to start */
- END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS |
- IFF_BROADCAST | IFF_MULTICAST));
- gei82543EndConfigure (pDrvCtrl);
- /* wait for chip to settle down */
- taskDelay (sysClkRateGet () / 20);
- /* check link status again before really start */
- if (gei82543linkStatusCheck (pDrvCtrl) != OK)
- {
- LOGMSG("gei82543EndStart:Link is down n", 1, 2, 3, 4, 5, 6);
- }
- /* set the internal timer */
- if (pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)
- {
- ADAPTOR_INFO * pBoard = &pDrvCtrl->adaptor; /* pointer to board specific struct */
- if (pBoard->sysGeiInitTimerSetup != NULL)
- if (pBoard->sysGeiInitTimerSetup (&pDrvCtrl->adaptor))
- {
- if (!(pBoard->devTimerUpdate.rdtrVal & 0xffff0000))
- GEI_WRITE_REG(INTEL_82543GC_RDTR,pBoard->devTimerUpdate.rdtrVal);
- if (!(pBoard->devTimerUpdate.radvVal & 0xffff0000))
- GEI_WRITE_REG(INTEL_82546EB_RADV,pBoard->devTimerUpdate.radvVal);
- if (!(pBoard->devTimerUpdate.itrVal & 0xffff0000))
- GEI_WRITE_REG(INTEL_82546EB_ITR,pBoard->devTimerUpdate.itrVal);
- pDrvCtrl->timerInterval = (pBoard->devTimerUpdate.watchDogIntVal <= 0) ?
- DEFAULT_TIMER_INTERVAL : (pBoard->devTimerUpdate.watchDogIntVal);
- }
- }
- /* start the timer if configured */
- if (pDrvCtrl->usrFlags & GEI_END_SET_TIMER)
- {
- if (pDrvCtrl->timerId)
- wdStart(pDrvCtrl->timerId, pDrvCtrl->timerInterval * sysClkRateGet(),
- (FUNCPTR) gei82543EndTimerHandler, (int) pDrvCtrl);
- }
- /* set the device start flag */
- pDrvCtrl->devStartFlag = TRUE;
- /* enable TX and RX operation */
- gei82543TxRxEnable (pDrvCtrl);
- DRV_LOG (DRV_DEBUG_LOAD, "gei82543EndStart...Donen", 1, 2, 3, 4, 5, 6);
- return (OK);
- }
- /*************************************************************************
- *
- * gei82543EndSend - driver send routine
- *
- * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
- * The buffer must already have the addressing information properly installed
- * in it. This is done by a higher layer.
- *
- * RETURNS: OK or ERROR.
- *
- * ERRNO: EINVAL
- */
- LOCAL STATUS gei82543EndSend
- (
- END_DEVICE * pDrvCtrl, /* device ptr */
- M_BLK_ID pMblk /* data to send */
- )
- {
- M_BLK_ID pMblkDup = pMblk; /* temporary pMblk */
- int mBlkNum; /* num of mBlk of a packet */
- DRV_LOG (DRV_DEBUG_TX, "gei82543EndSend...n", 1, 2, 3, 4, 5, 6);
- if (pMblk == NULL)
- return ERROR;
- /* return if entering polling mode */
- if (pDrvCtrl->flags & FLAG_POLLING_MODE)
- {
- netMblkClChainFree (pMblk);
- errno = EINVAL;
- return (ERROR);
- }
- END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
- /* get the mBlk number in this packet */
- mBlkNum = 0;
- while (pMblkDup != NULL)
- {
- mBlkNum++;
- pMblkDup = pMblkDup->mBlkHdr.mNext;
- }
- /*
- * release mBlks if the number of mBlks in this packet exceeds the maximum
- * available transmit descriptors
- */
- if (mBlkNum >= pDrvCtrl->txDescNum)
- {
- DRV_LOG (DRV_DEBUG_TX, ("gei82543EndSend:mBlks num exceeds max TX descn"),
- 1, 2, 3, 4, 5, 6);
- netMblkClChainFree (pMblk);
- errno = EINVAL;
- END_TX_SEM_GIVE (&pDrvCtrl->end);
- return (ERROR);
- }
- if ((mBlkNum > pDrvCtrl->txDescFreeNum) &&
- (mBlkNum > gei82543TxDesCleanGet(pDrvCtrl,FREE_ALL_AUTO)))
- {
- /* not enough TX descriptors */
- DRV_LOG (DRV_DEBUG_TX, ("gei82543EndSend: No TX descriptor
- availablen"), 1, 2, 3, 4, 5, 6);
- if (pDrvCtrl->txStall != TRUE)
- {
- pDrvCtrl->txStall = TRUE;
- pDrvCtrl->txReqDescNum = mBlkNum;
- if (pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)
- {
- /* enable the TXD_LOW interrupt */
- GEI_WRITE_REG(INTEL_82543GC_IMS, IMS_TXDLOW_BIT);
- }
- GEI_WRITE_REG(INTEL_82543GC_TIDV, MIN_TXINT_DELAY);
- }
- END_TX_SEM_GIVE (&pDrvCtrl->end);
- return (END_ERR_BLOCK);
- }
- /* bump statistic counter */
- if (pMblk->mBlkHdr.mData[0] & (UINT8) 0x01)
- pDrvCtrl->end.mib2Tbl.ifOutNUcastPkts += 1;
- else
- END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
- DRV_LOG (DRV_DEBUG_TX, "loan buffers of the packet and transmit...n",
- 1, 2, 3, 4, 5, 6);
- pDrvCtrl->txActivity = TRUE;
- gei82543LoanTransmit (pDrvCtrl, pMblk);
- /* release semaphore now */
- END_TX_SEM_GIVE (&pDrvCtrl->end);
- DRV_LOG (DRV_DEBUG_TX, ("gei82543EndSend...Done"), 1, 2, 3, 4, 5, 6);
- return (OK);
- }
- /**********************************************************************
- *
- * gei82543LoanTransmit - store the mbuf address into TX descriptor to transmit
- *
- * This routine stores the mbuf address into the Tx descriptors address field,
- * and then directly transfer data from mbuf to chip memory without copying,
- * The loaned mBlk will be freed later
- *
- * RETURNS: N/A.
- */
- LOCAL void gei82543LoanTransmit
- (
- END_DEVICE * pDrvCtrl, /* END device structure */
- M_BLK_ID pMblkFirst /* pointer to the beginning of a mBlk */
- )
- {
- P_TX_DESCTL pDescCtl; /* pointer to a Tx descriptor */
- /* control structure*/
- char * pDesc; /* pointer to a descriptor */
- M_BLK_ID pMblk; /* pointer to a Mblk */
- UINT32 len; /* temporary len for each mBlk */
- UINT32 totalLen = 0; /* total length of this packet */
- UINT32 index = 0; /* index to the number of mBlk */
- int tmpTail; /* temporary tail index of TX descriptor*/
- UINT32 poptSta = 0; /* value in the option and status filed */
- UINT32 dataCtx; /* value in the command field */
- dataCtx = ((TXD_CMD_IDE | TXD_CMD_RS) << 24);
- pMblk = pMblkFirst;
- FOREVER
- {
- /* get the available TX descriptor and its manager */
- GEI_GET_TX_DESC_TAIL_UPDATE(tmpTail, index);
- pDescCtl = GEI_GET_TX_DESC_CTL_ADDR(tmpTail);
- pDesc = GEI_GET_TX_DESC_ADDR(tmpTail);
- len = pMblk->mBlkHdr.mLen;
- totalLen += len;
- /* flush buffer for cache coherence */
- cacheFlush(DATA_CACHE, (void *)(pMblk->mBlkHdr.mData), len);
- GEI_WRITE_DESC_LONG(pDesc, TXDESC_BUFADRHIGH_OFFSET, 0);
- GEI_WRITE_DESC_LONG(pDesc, TXDESC_BUFADRLOW_OFFSET,
- (UINT32)GEI_VIRT_TO_BUS((UINT32)(pMblk->mBlkHdr.mData)));
- /* zero the status field in the TX descriptor */
- GEI_WRITE_DESC_LONG(pDesc, TXDESC_STATUS_OFFSET, poptSta);
- pMblk = pMblk->mBlkHdr.mNext;
- index++;
- if (pMblk == NULL || pMblk->mBlkHdr.mLen == 0)
- {
- /* the last mBlk for this packet */
- pDescCtl->txType = TX_DESC_TYPE_EOP;
- pDescCtl->mBlk = pMblkFirst;
- if (totalLen < ETHERSMALL)
- len = max (len, len + ETHERSMALL - totalLen);
- /* set up the length/commond field */
- GEI_WRITE_DESC_LONG(pDesc, TXDESC_LENGTH_OFFSET,
- ((UINT16)len | (dataCtx) |
- ((TXD_CMD_EOP | TXD_CMD_IFCS) << 24)));
- break;
- }
- else
- {
- pDescCtl->txType = TX_DESC_TYPE_CHAIN;
- pDescCtl->mBlk = NULL;
- /* set up the length field */
- GEI_WRITE_DESC_LONG(pDesc, TXDESC_LENGTH_OFFSET,
- ((UINT16)len | dataCtx));
- }
- } /* FOREVER */
- /* update the tail pointer in the driver structure */
- GEI_GET_TX_DESC_TAIL_UPDATE(pDrvCtrl->txDescTail, index);
- pDrvCtrl->txDescFreeNum -= index;
- CACHE_PIPE_FLUSH();
- /* update the tail pointer in TDT register */
- GEI_WRITE_REG(INTEL_82543GC_TDT, pDrvCtrl->txDescTail);
- return;
- }
- /*************************************************************************
- *
- * gei82543TxDesCleanGet - clean up TX descriptors
- *
- * This routine cleans up TX descriptors and update available TX descriptor
- * for transmitting.
- *
- * RETURNS: number of available TX descriptors
- */
- LOCAL int gei82543TxDesCleanGet
- (
- END_DEVICE * pDrvCtrl, /* device to clean up TX descriptor */
- int mode /* clean up mode Force/Auto */
- )
- {
- P_TX_DESCTL pDescCtl; /* TX descriptor control structure */
- char * pDesc; /* pointer to descriptor */
- int maxTxDesFree; /* maximum available TX descriptors to free */
- int index; /* index */
- /* check the maximum free TX Desc */
- maxTxDesFree = pDrvCtrl->txDescNum - 1;
- while (pDrvCtrl->txDescFreeNum != maxTxDesFree)
- {
- index = (pDrvCtrl->txDescLastCheck + 1) % (pDrvCtrl->txDescNum);
- pDesc = GEI_GET_TX_DESC_ADDR(index);
- /* check data has been transmitted */
- if (mode != FREE_ALL_FORCE)
- if (!(GEI_READ_DESC_BYTE(pDesc, TXDESC_STATUS_OFFSET) &
- TXD_STAT_DD))
- break;
- pDescCtl = GEI_GET_TX_DESC_CTL_ADDR(index);
- if (pDescCtl->txType == TX_DESC_TYPE_EOP && pDescCtl->mBlk != NULL)
- {
- /* free loaned TX buffers */
- netMblkClChainFree (pDescCtl->mBlk);
- pDescCtl->mBlk = NULL;
- }
- /* mark descrptor clean */
- pDescCtl->txType = TX_DESC_TYPE_CLEAN;
- /* update the index of descriptor checked */
- pDrvCtrl->txDescLastCheck = index;
- /* update the available TX descriptor */
- pDrvCtrl->txDescFreeNum++;
- }
- return (pDrvCtrl->txDescFreeNum);
- }
- /*************************************************************************
- *
- * gei82543EndInt - handle 82543 chip interrupt event
- *
- * This routine is called at interrupt level in response to an interrupt from
- * the controller.
- *
- * RETURNS: N/A.
- */
- LOCAL void gei82543EndInt
- (
- END_DEVICE * pDrvCtrl /* device to handle interrupt */
- )
- {
- UINT32 stat; /* cause of interrupt */
- UINT32 statusRegVal; /* status register value */
- UINT32 intTypeChk; /* type of interrupt to be checked */
- DRV_LOG (DRV_DEBUG_INT, "gei82543EndInt ...n", 1, 2, 3, 4, 5, 6);
- /* read the device status register */
- GEI_READ_REG(INTEL_82543GC_ICR, stat);
- stat &= INTEL_82543GC_VALID_INT;
- /* return if not interrupt for this device */
- if (stat == 0)
- {
- DRV_LOG (DRV_DEBUG_INT, "gei82543EndInt: PCI interrupt is not
- caused by this GEI devicen", 1, 2, 3, 4, 5, 6);
- return;
- }
- /* handle link interrupt event */
- if (stat & INT_LINK_CHECK)
- {
- DRV_LOG (DRV_DEBUG_INT, "gei82543EndInt: get a Link problemn",
- 1, 2, 3, 4, 5, 6);
- /* link status change, get status register */
- GEI_READ_REG(INTEL_82543GC_STATUS, statusRegVal);
- if (statusRegVal & STATUS_LU_BIT)
- {
- /* link is up */
- if (pDrvCtrl->cableType == GEI_FIBER_MEDIA)
- {
- /*
- * restart link if partner send back a TXCW after
- * force link
- */
- UINT32 rxcwRegVal;
- UINT32 txcwRegVal;
- GEI_READ_REG(INTEL_82543GC_RXCW, rxcwRegVal);
- GEI_READ_REG(INTEL_82543GC_TXCW, txcwRegVal);
- if ((pDrvCtrl->linkMethod == GEI82543_FORCE_LINK) &&
- (rxcwRegVal & RXCW_C_BIT) &&
- (!(txcwRegVal & TXCW_ANE_BIT)))
- {
- DRV_LOG (DRV_DEBUG_INT, "gei82543EndInt: Hardware
- Auto-Negotiation restartn", 1, 2, 3, 4, 5, 6);
- netJobAdd ((FUNCPTR)gei82543linkTBISetup, (int)pDrvCtrl,
- FALSE, 0, 0, 0);
- return;
- }
- }
- else if (pDrvCtrl->cableType == GEI_COPPER_MEDIA)
- {
- LOGMSG("Reconfig device ... n",1,2,3,4,5,6);
- /* re-configure device based on GMII negotiation results */
- if (pDrvCtrl->linkMethod == GEI82543_HW_AUTO)
- {
- netJobAdd ((FUNCPTR) gei82543GMIIphyReConfig,
- (int)pDrvCtrl, 0, 0, 0, 0);
- return;
- }
- }
- }
- else /* if link is down */
- {
- return;
- }
- }
- if (pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)
- {
- if (stat & INT_RXTO_BIT)
- pDrvCtrl->rxIntCount++;
- if (stat & INT_RXO_BIT)
- pDrvCtrl->rxORunIntCount++;
- if (stat & (INT_TXDW_BIT | INT_TXDLOW_BIT))
- pDrvCtrl->txIntCount++;
- intTypeChk = AVAIL_RX_TX_INT | INT_TXDLOW_BIT;
- }
- else
- {
- intTypeChk = AVAIL_RX_TX_INT;
- }
- /* tNetTask handles RX/TX interrupts */
- if ((stat & intTypeChk) && (pDrvCtrl->rxtxHandling != TRUE))
- {
- pDrvCtrl->rxtxHandling = TRUE;
- /* disable receive / transmit interrupt */
- GEI_WRITE_REG(INTEL_82543GC_IMC, intTypeChk);
- /*
- * NOTE: Read back any chip register to flush PCI
- * bridge write buffer in case this adaptor is behind
- * a PCI bridge.
- */
- CACHE_PIPE_FLUSH ();
- GEI_READ_REG(INTEL_82543GC_IMS, stat);
- /* defer the handling ... */
- netJobAdd ((FUNCPTR) gei82543RxTxIntHandle, (int)pDrvCtrl, 0,
- 0, 0, 0);
- }
- DRV_LOG (DRV_DEBUG_INT, "gei82543EndInt...Donen", 1, 2, 3, 4, 5, 6);
- return;
- }
- /*************************************************************************
- *
- * gei82543RxTxIntHandle - receive/transmit interrupt handle in task mode
- *
- * This routine gets the receive packet and pass them to upper network stack.
- * It also cleans up TX descriptor if necessary.
- *
- * RETURNS: N/A.
- */
- LOCAL void gei82543RxTxIntHandle
- (
- END_DEVICE * pDrvCtrl /* device to handle RX/TX */
- )
- {
- UINT32 rxCountPerInt = 0; /* maximum RX descriptors to handle a int */
- UINT32 retry = 0; /* retry count */
- char * pRxDesc; /* RX descriptor pointer */
- UINT32 stat; /* cause of interrupt */
- UINT32 txRestartChk = TX_RESTART_NONE; /* flag chk if txRestart is scheduled */
- UINT8 rxdStat; /* status of recv descriptor */
- DRV_LOG (DRV_DEBUG_RX, "gei82543RxTxIntHandle...n", 1, 2, 3, 4, 5, 6);
- do {
- while (rxCountPerInt++ < pDrvCtrl->maxRxNumPerInt)
- {
- /* get the current RX descriptor */
- pRxDesc = GEI_GET_RX_DESC_ADDR(pDrvCtrl->rxDescTail);
- END_CACHE_INVALIDATE ((UINT32)pRxDesc, RXDESC_SIZE);
- /* check RX descriptor status */
- rxdStat = GEI_READ_DESC_BYTE(pRxDesc,RXDESC_STATUS_OFFSET);
- if ((rxdStat & RXD_STAT_DD) == 0)
- break;
- /* process an incoming packet */
- if (gei82543Recv (pDrvCtrl, pRxDesc, rxdStat) != OK)
- {
- break;
- }
- }
- if (retry++ == 3 || rxCountPerInt >= pDrvCtrl->maxRxNumPerInt)
- break;
- /* handle case that TX stalls */
- if (pDrvCtrl->txStall && txRestartChk != TX_RESTART_TRUE)
- txRestartChk = gei82543TxStallCheck (pDrvCtrl);
- GEI_READ_REG(INTEL_82543GC_ICR, stat);
- } while (stat & AVAIL_RX_INT);
- pDrvCtrl->rxtxHandling = FALSE;
- if (pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)
- {
- pDrvCtrl->rxtxHandlerNum++;
- pDrvCtrl->rxPacketNum += rxCountPerInt;
- }
- /* free loaned mBlk if needed */
- if (pDrvCtrl->txResoFreeQuick == TRUE)
- gei82543TxMblkFree (pDrvCtrl, FREE_ALL_AUTO);
- /* enable RX/TX interrupts */
- if (pDrvCtrl->txStall && pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)
- {
- GEI_WRITE_REG(INTEL_82543GC_IMS, (AVAIL_RX_TX_INT | IMS_TXDLOW_BIT));
- }
- else
- {
- GEI_WRITE_REG(INTEL_82543GC_IMS, AVAIL_RX_TX_INT);
- }
- /* if muxTxRestart is not in tNetTask job queue, chk TxStall */
- if (txRestartChk != TX_RESTART_TRUE)
- gei82543TxStallCheck (pDrvCtrl);
- CACHE_PIPE_FLUSH();
- DRV_LOG (DRV_DEBUG_RX, "gei82543RxTxIntHandle...Donen",
- 1, 2, 3, 4, 5, 6);
- return;
- }
- /*************************************************************************
- *
- * gei82543TxStallCheck - handling TX stalling due to out of TX descriptors
- *
- * This routine checks the availability of TX descriptors, and restart
- * transmitting if TX descriptor available
- *
- * RETURN: TX_RESTART_TRUE if muxTxRestart is put into tNetTask job queue,
- * otherwise, TX_RESTART_NONE
- */
- LOCAL UINT32 gei82543TxStallCheck
- (
- END_DEVICE * pDrvCtrl /* device to check TX stall */
- )
- {
- int txFreeDescNum; /* available Tx number */
- DRV_LOG (DRV_DEBUG_TX, "handle txStall ...n", 1, 2, 3, 4, 5, 6);
- /* take a semaphore */
- END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
- if (pDrvCtrl->txStall == FALSE)
- {
- END_TX_SEM_GIVE (&pDrvCtrl->end);
- return TX_RESTART_NONE;
- }
- txFreeDescNum = gei82543TxDesCleanGet (pDrvCtrl, FREE_ALL_AUTO);
- if (pDrvCtrl->txReqDescNum <= txFreeDescNum)
- {
- /* TX Descriptors available, restart transmit */
- DRV_LOG (DRV_DEBUG_TX, "Restart muxn", 1, 2, 3, 4, 5, 6);
- (void) netJobAdd ((FUNCPTR) muxTxRestart, (int)&pDrvCtrl->end,
- 0, 0, 0, 0);
- if (pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)
- {
- /* disable the TXD_LOW interrupt */
- GEI_WRITE_REG(INTEL_82543GC_IMC, IMC_TXDLOW_BIT);
- }
- GEI_WRITE_REG(INTEL_82543GC_TIDV, pDrvCtrl->txIntDelay);
- pDrvCtrl->txStall = FALSE;
- END_TX_SEM_GIVE (&pDrvCtrl->end);
- return TX_RESTART_TRUE;
- }
- END_TX_SEM_GIVE (&pDrvCtrl->end);
- return TX_RESTART_NONE;
- }
- /*************************************************************************
- *
- * gei82543Recv - process an incoming packet
- *
- * This routine checks the incoming packet, and passes it the upper layer.
- *
- * RETURNS: OK, or ERROR if receiving fails
- */
- LOCAL STATUS gei82543Recv
- (
- END_DEVICE * pDrvCtrl, /* device structure */
- char * pRxDesc, /* pointer to RX descriptor */
- UINT8 rxdStat /* RX descriptor status */
- )
- {
- UINT16 len; /* len of packet received */
- M_BLK_ID pMblk; /* mBlk to store this packet */
- volatile char * pCluster = NULL; /* cluster pointer */
- volatile char * pNewCluster = NULL; /* new cluster pointer */
- volatile CL_BLK_ID pClBlk = NULL; /* cluster block pointer */
- char * pData; /* receve data pointer */
- UINT32 bufAddr; /* buffer address */
- UINT8 rxdErr; /* RX descriptor Error field */
- DRV_LOG (DRV_DEBUG_RX, "gei82543Recv start...n", 1, 2, 3, 4, 5, 6);
- /* check packet status */
- if (!(rxdStat & RXD_STAT_EOP))
- {
- DRV_LOG (DRV_DEBUG_RX, "Packet EOP not setn", 1, 2, 3, 4, 5, 6);
- LOGMSG("Packet EOP not set n",1,2,3,4,5,6);
- goto receiveError;
- }
- rxdErr = GEI_READ_DESC_BYTE(pRxDesc, RXDESC_ERROR_OFFSET);
- #ifdef INCLUDE_TBI_COMPATIBLE
- rxdErr &= (UINT8)(~(RXD_ERROR_IPE | RXD_ERROR_TCPE | RXD_ERROR_RSV));
- GEI_READ_DESC_WORD(pRxDesc, RXDESC_LENGTH_OFFSET, len);
- if (rxdErr)
- {
- BOOL frameAccept = FALSE;
- if (rxdErr == RXD_ERROR_CE && pDrvCtrl->tbiCompatibility)
- {
- UINT8 * bufAdr;
- UINT8 lastChar;
- /* software workaround for TBI compatibility problem */
- GEI_READ_DESC_LONG(pRxDesc, RXDESC_BUFADRLOW_OFFSET, (UINT32)bufAdr);
- lastChar = *(UINT8 *)((UINT32)bufAdr + len - 1);
- if (lastChar == CARRIER_EXTENSION_BYTE &&
- len > (MIN_ETHER_PACKET_SIZE + RX_CRC_LEN) &&
- len <= (pDrvCtrl->mtu + GEI_DEFAULT_ETHERHEADER + RX_CRC_LEN + 1))
- {
- frameAccept = TRUE;
- rxdErr = 0;
- len--;
- }
- }
- if (frameAccept != TRUE)
- {
- DRV_LOG (DRV_DEBUG_RX, "Packet Error 0x%xn", rxdErr,
- 2, 3, 4, 5, 6);
- LOGMSG("Packet error 0x%x n",rxdErr, 2, 3, 4, 5, 6);
- goto receiveError;
- }
- }
- #else /* !INCLUDE_TBI_COMPATIBLE */
- if (rxdErr & (UINT8)(~(RXD_ERROR_IPE | RXD_ERROR_TCPE)))
- {
- DRV_LOG (DRV_DEBUG_RX, "Packet Error 0x%xn", rxdErr, 2, 3, 4, 5, 6);
- LOGMSG("Packet error 0x%x n",rxdErr, 2, 3, 4, 5, 6);
- goto receiveError;
- }
- /* get packet length */
- GEI_READ_DESC_WORD(pRxDesc, RXDESC_LENGTH_OFFSET, len);
- #endif /* INCLUDE_TBI_COMPATIBLE */
- len -= RX_CRC_LEN;
- len &= ~0xc000;
- if (len > (pDrvCtrl->mtu + GEI_DEFAULT_ETHERHEADER) ||
- len < MIN_ETHER_PACKET_SIZE)
- {
- DRV_LOG (DRV_DEBUG_RX, ("invalid packet length=0x%x!n"), len,
- 0, 0, 0, 0, 0);
- goto receiveError;
- }
- /*
- * we implicitly using loaning here, if copying is necessary this
- * step may be skipped, but the data must be copied before being
- * passed up to the protocols.
- */
- pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool,
- pDrvCtrl->pClPoolId);
- if (pNewCluster == NULL)
- {
- DRV_LOG (DRV_DEBUG_RX, "Not free new Cluster!n", 1, 2, 3, 4, 5, 6);
- goto receiveError;
- }
- /* grab a cluster block to marry to the cluster we received. */
- if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
- {
- netClFree (pDrvCtrl->end.pNetPool, (unsigned char *)pNewCluster);
- DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
- goto receiveError;
- }
- /*
- * OK we've got a spare descriptor, let's get an M_BLK_ID and marry it
- * to the one in the ring.
- */
- if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA))
- == NULL)
- {
- netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
- netClFree (pDrvCtrl->end.pNetPool, (unsigned char *)pNewCluster);
- DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
- goto receiveError;
- }
- GEI_READ_DESC_LONG(pRxDesc, RXDESC_BUFADRLOW_OFFSET, bufAddr);
- pCluster = GEI_BUS_TO_VIRT(bufAddr);
- pData = (char *) pCluster;
- END_CACHE_INVALIDATE ((UINT32)pCluster, len);
- pCluster -= pDrvCtrl->offset;
- netClBlkJoin (pClBlk, (char *)pCluster, len, NULL, 0, 0, 0);
- netMblkClJoin (pMblk, pClBlk);
- if ((*pData ) & (UINT8) 0x01)
- pDrvCtrl->end.mib2Tbl.ifInNUcastPkts += 1;
- else
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
- /* set up Mblk */
- pMblk->mBlkHdr.mLen = len;
- pMblk->mBlkHdr.mFlags |= M_PKTHDR;
- pMblk->mBlkPktHdr.len = len;
- pMblk->mBlkHdr.mData = (char *)pData;
- /* update the new descriptor, and update the tail pointer */
- gei82543RxDesUpdate(pDrvCtrl, (char *)pNewCluster);
- /* call the upper layer's receive routine. */
- END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
- DRV_LOG (DRV_DEBUG_RX, "Receive done!n", 1, 2, 3, 4, 5, 6);
- return OK;
- receiveError:
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
- gei82543RxDesUpdate (pDrvCtrl, NULL);
- if (pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)
- {
- pDrvCtrl->rxPacketDrvErr++;
- }
- DRV_LOG (DRV_DEBUG_RX, "Receive ERROR!n", 1, 2, 3, 4, 5, 6);
- return ERROR;
- }
- /*************************************************************************
- *
- * gei82543RxDesUpdate - clean up the receive descriptor
- *
- * This routine cleans up receive descriptors, hook up to a new cluster
- * if needed, and then update the tail pointer to make it available to the
- * hardware.
- *
- * RETURNS: N/A
- */
- LOCAL void gei82543RxDesUpdate
- (
- END_DEVICE * pDrvCtrl, /* device to update */
- char * pCluster /* new cluster pointer */
- )
- {
- int tempTail; /* temporary tail index */
- char * pRxDesc = NULL; /* RX descriptor */
- DRV_LOG (DRV_DEBUG_RX, "gei82543RxDesUpdate...n", 1, 2, 3, 4, 5, 6);
- /* get the RX tail descriptor */
- pRxDesc = GEI_GET_RX_DESC_ADDR(pDrvCtrl->rxDescTail);
- if (pCluster != NULL)
- {
- pCluster += pDrvCtrl->offset;
- GEI_WRITE_DESC_LONG(pRxDesc, RXDESC_BUFADRLOW_OFFSET,
- (UINT32)GEI_VIRT_TO_BUS(pCluster));
- }
- /* clean up status field */
- GEI_WRITE_DESC_BYTE(pRxDesc,RXDESC_STATUS_OFFSET, 0);
- /* save the tail pointer before update */
- tempTail = pDrvCtrl->rxDescTail;
- /* update the tail pointer */
- GEI_GET_RX_DESC_TAIL_UPDATE(pDrvCtrl->rxDescTail, 1);
- /* kick this descriptor for receiving packet */
- GEI_WRITE_REG(INTEL_82543GC_RDT, tempTail);
- CACHE_PIPE_FLUSH();
- DRV_LOG (DRV_DEBUG_RX, "gei82543RxDesUpdate...Donen",
- 1, 2, 3, 4, 5, 6);
- return;
- }
- /*************************************************************************
- *
- * gei82543TxMblkFree - free transmit mBlk(s)
- *
- * This routine frees transmit mBlk(s) after packets have been transmitted
- * on wire.
- *
- * RETURNS: N/A.
- */
- LOCAL void gei82543TxMblkFree
- (
- END_DEVICE * pDrvCtrl, /* device to free transmit mBlk(s) */
- int mode /* AUTO/FORCE */
- )
- {
- int maxFreeTxDesc;
- DRV_LOG (DRV_DEBUG_TX, "gei82543TxMblkFree...n", 1, 2, 3, 4, 5, 6);
- /* take semaphore */
- END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
- gei82543TxDesCleanGet (pDrvCtrl, mode);
- /* sanity check */
- if (mode == FREE_ALL_FORCE)
- {
- maxFreeTxDesc = pDrvCtrl->txDescNum - 1;
- if (pDrvCtrl->txDescFreeNum != maxFreeTxDesc)
- {
- LOGMSG("Panic: TX Descriptors are not cleaned upn", 1,2,3,4,5,6);
- }
- }
- END_TX_SEM_GIVE (&pDrvCtrl->end);
- DRV_LOG (DRV_DEBUG_TX, "gei82543TxMblkFree...Donen", 1, 2, 3, 4, 5, 6);
- return;
- }
- /*****************************************************************************
- *
- * gei82543TxResoFree - free loaned TX mBlks constantly
- *
- * This routine frees loaned TX mBlks constantly, and updates device statistics,
- * it may also execute a callback function defined in sysGei82543End.c
- *
- * RETURNS: N/A
- */
- LOCAL void gei82543TxResoFree
- (
- END_DEVICE * pDrvCtrl /* END device */
- )
- {
- ADAPTOR_INFO * pBoard; /* pointer to device specific struct */
- DEVDRV_STAT * pStat; /* pointer to device/driver statistics */
- DEV_TIMER * pTimer; /* pointer to driver specific timer info */
- int ti; /* timer interval */
- DRV_LOG (DRV_DEBUG_TIMER, "gei82543TxResoFree...startn",
- 1, 2, 3, 4, 5, 6);
- gei82543TxMblkFree (pDrvCtrl, FREE_ALL_AUTO);
- /* set the internal timer */
- if (pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)
- {
- pBoard = &pDrvCtrl->adaptor;
- if (pBoard->sysGeiDynaTimerSetup != NULL)
- {
- pStat = &pBoard->devDrvStat;
- ti = pDrvCtrl->timerInterval;
- pStat->rxtxHandlerNum = pDrvCtrl->rxtxHandlerNum / ti;
- pStat->rxIntCount = pDrvCtrl->rxIntCount / ti;
- pStat->txIntCount = pDrvCtrl->txIntCount / ti;
- pStat->rxORunIntCount = pDrvCtrl->rxORunIntCount / ti;
- pStat->rxPacketNum = pDrvCtrl->rxPacketNum / ti;
- pStat->rxPacketDrvErr = pDrvCtrl->rxPacketDrvErr / ti;
- GEI_READ_REG(INTEL_82543GC_TPT, pDrvCtrl->staRegs.tpt);
- pStat->txPacketNum = pDrvCtrl->staRegs.tpt / ti;
- if (pBoard->sysGeiDynaTimerSetup (pBoard))
- {
- pTimer = &pBoard->devTimerUpdate;
- if (!(pTimer->rdtrVal & 0xffff0000))
- GEI_WRITE_REG(INTEL_82543GC_RDTR,pTimer->rdtrVal);
- if (!(pTimer->radvVal & 0xffff0000))
- GEI_WRITE_REG(INTEL_82546EB_RADV,pTimer->radvVal);
- if (!(pTimer->itrVal & 0xffff0000))
- GEI_WRITE_REG(INTEL_82546EB_ITR,pTimer->itrVal);
- pDrvCtrl->timerInterval = (pTimer->watchDogIntVal <= 0) ?
- DEFAULT_TIMER_INTERVAL : (pTimer->watchDogIntVal);
- }
- /* clean up */
- pDrvCtrl->rxtxHandlerNum = 0;
- pDrvCtrl->rxIntCount = 0;
- pDrvCtrl->txIntCount = 0;
- pDrvCtrl->rxORunIntCount = 0;
- pDrvCtrl->rxPacketNum = 0;
- pDrvCtrl->rxPacketDrvErr = 0;
- }
- }
- /* restart timer */
- wdStart (pDrvCtrl->timerId, pDrvCtrl->timerInterval * sysClkRateGet(),
- (FUNCPTR) gei82543EndTimerHandler, (int) pDrvCtrl);
- DRV_LOG (DRV_DEBUG_TIMER, "gei82543TxResoFree...Donen",
- 1, 2, 3, 4, 5, 6);
- }
- /*****************************************************************************
- *
- * gei82543EndTimerHandler - timer interrupt handler routine
- *
- * This routine handle timer interrupts to free TX resources
- *
- * RETURNS: N/A
- */
- LOCAL void gei82543EndTimerHandler
- (
- END_DEVICE * pDrvCtrl /* END device structure */
- )
- {
- DRV_LOG (DRV_DEBUG_TIMER, ("gei82543EndTimerHandler...n"),
- 1, 2, 3, 4, 5, 6);
- if (pDrvCtrl->txDescFreeNum != (pDrvCtrl->txDescNum - 1) ||
- ((pDrvCtrl->adaptor.sysGeiDynaTimerSetup != NULL) &&
- (pDrvCtrl->adaptor.boardType == PRO1000_546_BOARD)))
- {
- netJobAdd ((FUNCPTR)gei82543TxResoFree, (int)pDrvCtrl,0,0,0,0);
- }
- else
- wdStart (pDrvCtrl->timerId, pDrvCtrl->timerInterval * sysClkRateGet(),
- (FUNCPTR) gei82543EndTimerHandler, (int) pDrvCtrl);
- DRV_LOG (DRV_DEBUG_TIMER, ("gei82543EndTimerHandler...DONEn"),
- 1, 2, 3, 4, 5, 6);
- return;
- }
- /*************************************************************************
- *
- * gei82543EndIoctl - the driver I/O control routine
- *
- * Process an ioctl request.
- *
- * RETURNS: A command specific response, usually OK or ERROR.
- */
- LOCAL int gei82543EndIoctl
- (
- END_DEVICE * pDrvCtrl, /* device receiving command */
- int cmd, /* ioctl command code */
- caddr_t data /* command argument */
- )
- {
- int error = 0;
- long value;
- DRV_LOG (DRV_DEBUG_IOCTL, ("IOCTL command beginn"), 0,0,0,0,0,0);
- switch ((UINT)cmd)
- {
- case EIOCSADDR:
- if (data == NULL)
- return (EINVAL);
- bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
- END_HADDR_LEN(&pDrvCtrl->end));
- break;
- case EIOCGADDR:
- if (data == NULL)
- return (EINVAL);
- bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
- END_HADDR_LEN(&pDrvCtrl->end));
- break;
- case EIOCSFLAGS:
- value = (long)data;
- if (value < 0)
- {
- value = -value;
- value--;
- END_FLAGS_CLR (&pDrvCtrl->end, value);
- }
- else
- END_FLAGS_SET (&pDrvCtrl->end, value);
- DRV_LOG (DRV_DEBUG_IOCTL, ("endFlag=0x%xn"),
- END_FLAGS_GET(&pDrvCtrl->end), 0,0,0,0,0);
- END_FLAGS_CLR (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
- gei82543EndConfigure(pDrvCtrl);
- END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
- break;
- case EIOCGFLAGS:
- *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
- break;
- case EIOCPOLLSTART: /* Begin polled operation */
- gei82543EndPollStart (pDrvCtrl);
- break;
- case EIOCPOLLSTOP: /* End polled operation */
- gei82543EndPollStop (pDrvCtrl);
- break;
- case EIOCGMIB2: /* return MIB information */
- if (data == NULL)
- return (EINVAL);
- bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
- sizeof(pDrvCtrl->end.mib2Tbl));
- break;
- case EIOCMULTIADD:
- error = gei82543EndMCastAdd (pDrvCtrl, (char *) data);
- break;
- case EIOCMULTIDEL:
- error = gei82543EndMCastDel (pDrvCtrl, (char *) data);
- break;
- case EIOCMULTIGET:
- error = gei82543EndMCastGet (pDrvCtrl, (MULTI_TABLE *) data);
- break;
- default:
- DRV_LOG (DRV_DEBUG_IOCTL, ("invalid IOCTL command n"),
- 0,0,0,0,0,0);
- error = EINVAL;
- }
- DRV_LOG (DRV_DEBUG_IOCTL, ("IOCTL command Donen"), 0,0,0,0,0,0);
- return (error);
- }
- /*************************************************************************
- *
- * gei82543EndConfigure - re-configure chip interface
- *
- * This routine re-configures the interface such as promisc, multicast
- * and broadcast modes
- *
- * RETURNS: N/A.
- */
- LOCAL void gei82543EndConfigure
- (
- END_DEVICE * pDrvCtrl /* device to configure */
- )
- {
- int oldVal = 0;
- int newVal = 0;
- DRV_LOG (DRV_DEBUG_IOCTL, ("gei82543EndConfig...n"), 1,2,3,4,5,6);
- (void)taskLock ();
- /* save flags for later use */
- oldVal = pDrvCtrl->flags;
- newVal = END_FLAGS_GET(&pDrvCtrl->end);
- /* set the driver flag based on END_FLAGS */
- if (newVal & IFF_PROMISC)
- pDrvCtrl->flags |= FLAG_PROMISC_MODE;
- else
- pDrvCtrl->flags &= ~FLAG_PROMISC_MODE;
- if (newVal & IFF_ALLMULTI)
- pDrvCtrl->flags |= FLAG_ALLMULTI_MODE;
- else
- pDrvCtrl->flags &= ~FLAG_ALLMULTI_MODE;
- if (newVal & IFF_MULTICAST)
- pDrvCtrl->flags |= FLAG_MULTICAST_MODE;
- else
- pDrvCtrl->flags &= ~FLAG_MULTICAST_MODE;
- if (newVal & IFF_BROADCAST)
- pDrvCtrl->flags |= FLAG_BROADCAST_MODE;
- else
- pDrvCtrl->flags &= ~FLAG_BROADCAST_MODE;
- if (oldVal == pDrvCtrl->flags)
- {
- (void)taskUnlock ();
- return;
- }
- /* read RX control register */
- GEI_READ_REG(INTEL_82543GC_RCTL, oldVal);
- newVal = oldVal;
- /* prepare new value for RX control register */
- if (pDrvCtrl->flags & FLAG_PROMISC_MODE)
- newVal |= (RCTL_UPE_BIT | RCTL_MPE_BIT | RCTL_BAM_BIT);
- else
- newVal &= ~(RCTL_UPE_BIT | RCTL_MPE_BIT);
- if (pDrvCtrl->flags & FLAG_ALLMULTI_MODE)
- newVal |= RCTL_MPE_BIT;
- else if (!(pDrvCtrl->flags & FLAG_PROMISC_MODE))
- newVal &= ~RCTL_MPE_BIT;
- if (pDrvCtrl->flags & FLAG_BROADCAST_MODE)
- newVal |= RCTL_BAM_BIT;
- else if (!(pDrvCtrl->flags & FLAG_PROMISC_MODE))
- newVal &= ~RCTL_BAM_BIT;
- /* set up RX control register if needed */
- if (newVal != oldVal)
- GEI_WRITE_REG(INTEL_82543GC_RCTL, newVal);
- /* set up Multicasting address */
- if (pDrvCtrl->flags & FLAG_MULTICAST_MODE)
- gei82543AddrFilterSet (pDrvCtrl);
- else
- gei82543McastAdrClean(pDrvCtrl);
- (void)taskUnlock ();
- DRV_LOG (DRV_DEBUG_IOCTL, ("gei82543EndConfig...Donen"),
- 0, 0, 0, 0, 0, 0);
- return;
- }
- /*************************************************************************
- *
- * gei82543AddrFilterSet - set the address filter for multicast addresses
- *
- * This routine goes through all of the multicast addresses on the list
- * of addresses (added with the endAddrAdd() routine) and sets the
- * device's filter correctly.
- *
- * RETURNS: N/A.
- */
- LOCAL void gei82543AddrFilterSet
- (
- END_DEVICE *pDrvCtrl /* device to be updated */
- )
- {
- ETHER_MULTI* pCurr; /* multi table address */
- int count; /* number of multi address */
- int i; /* index */
- int col; /* column in MTA */
- int row; /* row in MTA */
- int tmp; /* temporary */
- UINT8 tmpBuf[ETHER_ADDRESS_SIZE]; /* array to save ETH addr */
- UINT16 hashVal; /* hash value for MTA */
- UINT32 lowAdr; /* adr low in RTA */
- UINT32 highAdr; /* adr high in RTA */
- DRV_LOG (DRV_DEBUG_IOCTL, ("gei82543AddrFilterSet...n"), 0,0,0,0,0,0);
- /* clean up all multicasting address in RTA and MTA */
- gei82543McastAdrClean(pDrvCtrl);
- /* get the number of multicasting address */
- if ((count = END_MULTI_LST_CNT(&pDrvCtrl->end)) == 0)
- return;
- if (count > MAX_NUM_MULTI)
- {
- LOGMSG("only accept %d multicast addressn",MAX_NUM_MULTI,2,3,4,5,6);
- count = MAX_NUM_MULTI;
- }
- /*
- * The first 15 multicast will stored in the RAT (RAL/RAH)
- * the rest are stored in MAT
- */
- pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
- /* the first entry (i=0) in RAT is not for multicast addr */
- for (i = 1; i< NUM_RAR && count; i++, count--)
- {
- memcpy (tmpBuf, (char *)&pCurr->addr, ETHER_ADDRESS_SIZE);
- lowAdr = tmpBuf[0] | (tmpBuf[1] << 8) | (tmpBuf[2] << 16) |
- (tmpBuf[3] << 24);
- highAdr = tmpBuf[4] | (tmpBuf[5] << 8);
- GEI_WRITE_REG((INTEL_82543GC_RAL + 8 * i), lowAdr);
- GEI_WRITE_REG((INTEL_82543GC_RAH +8 * i), (highAdr | RAH_AV_BIT));
- pCurr = END_MULTI_LST_NEXT(pCurr);
- }
- /* configure MTA table if more multicast address remaining */
- while (count--)
- {
- memcpy (tmpBuf, (char *)&pCurr->addr, ETHER_ADDRESS_SIZE);
- /*
- * compose hash value based on filter type :
- * MULTI_FILTER_TYPE_47_36: 47 - 36 bits for dest multicast addr match
- * MULTI_FILTER_TYPE_46_35: 46 - 35 bits for dest multicast addr match
- * MULTI_FILTER_TYPE_45_34: 45 - 34 bits for dest multicast addr match
- * MULTI_FILTER_TYPE_43_32: 43 - 32 bits for dest multicast addr match
- */
- if (pDrvCtrl->multiCastFilterType == MULTI_FILTER_TYPE_47_36)
- hashVal = (tmpBuf[4] >> 4) | ((UINT16)(tmpBuf[5]) << 4);
- else if (pDrvCtrl->multiCastFilterType == MULTI_FILTER_TYPE_46_35)
- hashVal = (tmpBuf[4] >> 3) | ((UINT16)(tmpBuf[5]) << 5);
- else if (pDrvCtrl->multiCastFilterType == MULTI_FILTER_TYPE_45_34)
- hashVal = (tmpBuf[4] >> 2) | ((UINT16)(tmpBuf[5]) << 6 );
- else if (pDrvCtrl->multiCastFilterType == MULTI_FILTER_TYPE_43_32)
- hashVal = tmpBuf[4] | ((UINT16)(tmpBuf[5]) << 8 );
- else
- {
- LOGMSG("Error in compose multicast hash valuen",1,2,3,4,5,6);
- return;
- }
- /* the first 5 bits is the bit location (32 maximum) in a register */
- col = hashVal & 0x1f;
- /* the remaining 7 bits is for the register offset (128 maximum) */
- row = (hashVal >> 5) & 0x7f;
- GEI_READ_REG((INTEL_82543GC_MTA + row * 32), tmp);
- /* find the right bit location */
- tmp |= (1 << col);
- GEI_WRITE_REG((INTEL_82543GC_MTA + row * 32), tmp);
- pCurr = END_MULTI_LST_NEXT(pCurr);
- }
- taskDelay (sysClkRateGet() / 20);
- DRV_LOG (DRV_DEBUG_IOCTL,("gei82543AddrFilterSet...Donen"), 0,0,0,0,0,0);
- return;
- }
- /*************************************************************************
- *
- * gei82543EndMCastAdd - add a multicast address for the device
- *
- * This routine adds a multicast address to whatever the driver
- * is already listening for. It then resets the address filter.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS gei82543EndMCastAdd
- (
- END_DEVICE * pDrvCtrl, /* device pointer */
- char * pAddress /* new address to add */
- )
- {
- int error;
- if ((error = etherMultiAdd (&pDrvCtrl->end.multiList, pAddress)) ==
- ENETRESET)
- {
- pDrvCtrl->end.nMulti++;
- if (pDrvCtrl->end.nMulti > MAX_NUM_MULTI)
- {
- pDrvCtrl->end.nMulti--;
- etherMultiDel (&pDrvCtrl->end.multiList,pAddress);
- return ERROR;
- }
- else
- gei82543AddrFilterSet(pDrvCtrl);
- }
- return (OK);
- }
- /*************************************************************************
- *
- * gei82543EndMCastDel - delete a multicast address for the device
- *
- * This routine removes a multicast address from whatever the driver
- * is listening for. It then resets the address filter.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS gei82543EndMCastDel
- (
- END_DEVICE * pDrvCtrl, /* device pointer */
- char * pAddress /* address to be deleted */
- )
- {
- int error;
- if ((error = etherMultiDel (&pDrvCtrl->end.multiList,(char *)pAddress))
- == ENETRESET)
- {
- gei82543AddrFilterSet(pDrvCtrl);
- pDrvCtrl->end.nMulti--;
- }
- return (OK);
- }
- /*****************************************************************************
- *
- * gei82543EndMCastGet - get the multicast address list for the device
- *
- * This routine gets the multicast list of whatever the driver
- * is already listening for.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS gei82543EndMCastGet
- (
- END_DEVICE * pDrvCtrl, /* device pointer */
- MULTI_TABLE * pTable /* address table to be filled in */
- )
- {
- return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
- }
- /*************************************************************************
- *
- * gei82453EndPollRcv - routine to receive a packet in polling mode.
- *
- * This routine receive a packet in polling mode
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS gei82543EndPollRcv
- (
- END_DEVICE * pDrvCtrl, /* device to be polled */
- M_BLK_ID pMblk /* mBlk to receive */
- )
- {
- char* pCluster; /* receiving packet addr */
- char* pRxDesc; /* RX descriptor addr */
- int len; /* packet length */
- STATUS retVal = OK; /* return value */
- UINT32 bufAddr; /* buffer address */
- DRV_LOG (DRV_DEBUG_POLL_RX, "gei82543EndPollRcv...n",
- 1, 2, 3, 4, 5, 6);
- if (!(pMblk->mBlkHdr.mFlags & M_EXT))
- {
- DRV_LOG (DRV_DEBUG_POLL_RX, "poll receive: bad mblkn",
- 1, 2, 3, 4, 5, 6);
- return (EAGAIN);
- }
- pRxDesc = GEI_GET_RX_DESC_ADDR(pDrvCtrl->rxDescTail);
- END_CACHE_INVALIDATE ((UINT32)pRxDesc, RXDESC_SIZE);
- /* check RX descriptor status */
- if (!(GEI_READ_DESC_BYTE(pRxDesc,RXDESC_STATUS_OFFSET) & RXD_STAT_DD))
- return (EAGAIN);
- if (!(GEI_READ_DESC_BYTE(pRxDesc,RXDESC_STATUS_OFFSET) & RXD_STAT_EOP)
- || (GEI_READ_DESC_BYTE(pRxDesc, RXDESC_ERROR_OFFSET)) )
- {
- DRV_LOG (DRV_DEBUG_POLL_RX, "packet Error or EOP not setn", 1, 2,
- 3, 4, 5, 6);
- retVal = EAGAIN;
- goto errorExit;
- }
- /* get the packet length */
- GEI_READ_DESC_WORD(pRxDesc, RXDESC_LENGTH_OFFSET, len);
- #ifdef INCLUDE_TBI_COMPATIBLE
- {
- UINT8 rxdErr;
- rxdErr = GEI_READ_DESC_BYTE(pRxDesc, RXDESC_ERROR_OFFSET);
- rxdErr &= (UINT8)(~(RXD_ERROR_IPE | RXD_ERROR_TCPE | RXD_ERROR_RSV));
- if (rxdErr)
- {
- BOOL frameAccept = FALSE;
- if (rxdErr == RXD_ERROR_CE && pDrvCtrl->tbiCompatibility)
- {
- UINT8 * bufAdr;
- UINT8 lastChar;
- /* software workaround for TBI compatibility problem */
- GEI_READ_DESC_LONG(pRxDesc, RXDESC_BUFADRLOW_OFFSET, (UINT32)bufAdr);
- lastChar = *(UINT8 *)((UINT32)bufAdr + len - 1);
- if (lastChar == CARRIER_EXTENSION_BYTE &&
- len > (MIN_ETHER_PACKET_SIZE + RX_CRC_LEN) &&
- len <= (pDrvCtrl->mtu + GEI_DEFAULT_ETHERHEADER + RX_CRC_LEN + 1))
- {
- frameAccept = TRUE;
- rxdErr = 0;
- len--;
- }