📄 if_cs.c
字号:
/* if_cs.c - Crystal Semiconductor CS8900 network interface driver */
/* */
/* Copyright 2000 Crystal Semiconductor Corp. */
/* */
/* Last release: v2.08a */
/* Mod level for last release: 08a */
/*
modification history
--------------------
v2.08a,08May01, kml
-Added support for SH3. ALIGMENT_32BIT needs to be defined for SH3, ARM, MIPS.
v2.07a,09Oct00, kml
-Padded 2 bytes in RxBuf to make IP header in the WORD boundary.
-Fixed the bug that if CPU type is MIPS, an extra byte is sent
when an odd-aligned buffer and odd length data are passed.
v2.06a, 22Nov99, kml:
-Take out all MULTICAST related functions when BSD4.3 driver is built.
v2.05a, 09Nov99, kml:
-Fix the bug that in the BSD4.3 version, netJobAdd() should pass the address
of CS_SOFTC instead of the interface unit number to match the argument passed
to csEventHandler(CS_SOFTC *pCS).
v2.04a,24Sep99, kml -Take out IFF_MULTICAST in BSD43 mode because not supported.
-Change receiving buffer size from 32 to 64.
-Correction: If the memory address parameter is zero, the CS8900 operates in the
mode specified by EEPROM or the Config Flag parameter.
03a,14May99,kml -Added support for Promiscuous Mode.
-Added support for Multicasting.
-Corredted the calculation of the MIB2 static variables:
if_opackets and if_ipaclets.
-Added codes to disable CS8900's interrupt in csInitChip()
when SOFT_RESET is defined.
-Made modification not to give up the frame when TX_UnderRun
occurrs and chip is not ready for TX.
02a,31Mar99,kml converted to BSD44 driver, merge from SENS
01g.25nov97.jla Added defs to help a page fault with hard resets.
HARD_RESET does hard chip resets
SOFT_RESET does a softer, kinder sort of reset
The routine csResetChip does one or the other based
on the define set in if_cs.h
01q,11apr97,rks Implementd "early tx" support. Required mods to csAttach
(initialization), csInitChip (early tx int enable),
csTxNextFrame, and csBufferEvent.
01p,09apr97,rks Replaced common TX code in csStartOutput and csTransmitEvent
with a new routine csTxNextFrame().
Added conditional compile for a Tx Queue depth and max TX
Queue depth counter if CS_DEBUG_ENABLE defined.
01o,07apr97,rks Changed queue routines (enqueue and deueue) to make the data
update prior to pointer update. Removed the int lock/unlock
around the queue accesses in csEventHandler (no longer needed
with the new queue routines).
Moved the m_freem call to after the intUnlock in csStartOutput.
01n,01apr97,rks Implemented a local queue for TX frames. On csStartOuput call,
the interface's queue is drained. Frames are then taken from
the local queue in csStartOutput and at ISR level for transmit
to ensure the interface's queue is manipulated only by routines
at the same context (csStartOuput and ether_output).
01m,30mar97,rks Modified the csIntHandler. Removed the chip int disables and
replaced with CLI/STI pairs only around queue manipulations.
Also, now use a "NetJobDepth" counter instead of an active flag
to determine if another csIntHandler needs to be queued.
Moved the netJobAdd logic to the bottom of the ISR and removed
it from all the ISR sub-routines.
01l,27mar97,rks Bracketed mbuff routines in csProcessReceive with splnet/splx.
01k,28feb97,rks Added circular queue manipulation routines to handle TX mbufs
to be freed and RX frames to be handled at the task level.
Created generic event handler (csEventHandler) to processe RX
frame processing and TX mbuff freeing at the task level.
Added a counter to ensure never more than 2 instances of the
event handler are queued for tNetTask processing.
01j,27feb97,rks Added support for the collision counter. Moved support for Rx
miss counter to ISR (saves a function call).
01h,25feb97,rks Modifications for MIPS suppport (prevent word reads from odd
addresses in csCopyTXFrame. Debug macro to replace csError
routine. (Greg Rasche)
01g,07jan97,rks Modified csAttach to remove parameter for specifying
Ethernet address.
01f,16dec96,rks Divided the driver into two files, this file for
system-indendent routines and "sysEnet.c" containing
target-specific routines and macros for "IO mode" operations.
Added BYTE_SWAP macro for all non-constant io values
to the CS8900. Replace pcX86-specific io routine
calls with SYS_IN/OUT macros.
01e,12dec96,rks Moved the pTxFrameChain variable to the CS_SOFTC structure.
Moved the int disable in csStartOutput to immediately
before the Rdy4TxNow poll. Mutex'd the call to
IF_DEQUEUE in csStartOutput with splnet/splx.
01d,05dec96,rks Removed the processing of every RX miss and implemented
support for RX miss statistics using the RX miss counter
with RX Miss Counter Overflow interrupts instead.
01c,25nov96,rks Added version number to statistics reported by csShow(),
Added support for TX on Rdy4Tx interrupts, Created
routine csFreeTxFrame() to move call of m_freem()
to task level Added statistic reported by csShow for
Rdy4Tx events
01b,16nov96,rks Removed support for collision counter (AnyColliE) to
improve system perf.
01a,12jul96,q_s Written.
*/
/*
DESCRIPTION
This module implements the Crystal Semiconductor CS8900 Ethernet network
interface driver.
This driver's structure is designed to facilitate porting to any architecture
supported by VxWorks. The routines in this file are system independent. A
library of system-dependent routines in the file "sysEnet.c" must be provided
for the target system. This driver supports only one unit per system board.
SYSTEM DEPENDENT SUPPORT ROUTINES
This driver requires five system-dependent support routines. These five
routines are defined in sysEnet.c.
* sysEnetGetConfig( CS_SOFTC *pCS )
This routine takes configuration parameters not specifed to csAttach(), if
any, from non-volatile storage (e.g. an attached EEPROM) and puts them in
the cs_softc structure.
* sysEnetAddrGet( int Unit, unsigned char *pAddr )
This routine obtains the Ethernet MAC address from non-volatile storage or
from the "csEnetAddr" array in sysEnet.c dependent on the
CS8900_ENET_ADDR_FROM_BOARD flag passed to csAttach() and saves the
Ethernet address to the arpcom structure.
* sysEnetHWInit( CS_SOFTC *pCS )
This routine uses global variables in the cs_softc structure to configure the
adapter for the board-specific IO circuitry and supported media types.
* sysEnetIntEnable( CS_SOFTC *pCS )
This routine enables the interrupt used by the CS8900 at the system level.
* sysEnetIntDisable( CS_SOFTC *pCS )
This routine disables the interrupt used by the CS8900 at the system level. It
is not currently used by this driver.
INCLUDE FILES: if_cs.h, sysEnet.c
*/
/* INCLUDES */
#include "vxWorks.h"
#include "sysLib.h"
#include "intLib.h"
#include "logLib.h"
#include "netLib.h"
#include "etherLib.h"
#include "stdio.h"
#include "iv.h"
#include "ioctl.h"
#include "taskLib.h"
#include "net/if_subr.h"
#include "if_cs.h"
#include "sysEnet.c" /* lib of BSP specific routines used by CS8900 driver */
/* DEFINES */
#define CS_DRIVER_VER "2.08a" /* Driver revsion number */
/* ALIGMENT_32BIT needs to be defined for the processors that perform 32-bit
read/write, such as ARM, Strong ARM, SH3, SH4, and MIPS.
If the data buffer for transmission starts on an odd address boundary, copy it
to a temporary buffer that starts on an even address boundary, and write the
temporary buffer to the CS8900 Chip. */
/* #define ALIGMENT_32BIT */
/*********************** debug macro *******************************/
BOOL csDebug = TRUE; /* this flag is used to turn DEBUG on or off */
#define CS_DEBUG_ENABLE
#ifdef CS_DEBUG_ENABLE
#define LOGMSG if(csDebug)logMsg
#undef LOCAL
#define LOCAL
typedef struct {
UINT32 arg1;
UINT32 arg2;
UINT32 arg3;
UINT32 arg4;
} CS_HISTORY_TYPE;
#define CS_HISTORY_SIZE 100
CS_HISTORY_TYPE csHistory[ CS_HISTORY_SIZE ];
UINT32 csHistoryIndex;
/* function prototypes */
STATUS csHistoryInit( void );
STATUS csHistoryShow( void );
STATUS csHistoryAdd( UINT32 arg1, UINT32 arg2, UINT32 arg3, UINT32 arg4 );
#else
#define LOGMSG
#endif
/*********************** end debug macro *******************************/
/* FORWARD DECLARATIONS */
STATUS csAttach( int Unit, int IOAddr, int IntVector, int IntLevel,
int MemAddr, int MediaType, int DMAChannel, int ConfigFlags );
LOCAL STATUS csVerifyChip( CS_SOFTC *pCS );
LOCAL STATUS csInit( int Unit );
LOCAL void csReset( int Unit );
LOCAL int csIoctl( struct ifnet *pIf, int Command, char *pData );
LOCAL STATUS csResetChip( CS_SOFTC *pCS );
LOCAL void csInitChip( CS_SOFTC *pCS );
#ifdef BSD43_DRIVER
LOCAL void csStartOutput (int Unit);
LOCAL int csOutput (struct ifnet *pIf, struct mbuf *pMbufChain,
SOCKADDR *pDst);
#else
LOCAL void csStartOutput (CS_SOFTC *pCS);
#endif
LOCAL void csCopyTxFrame( CS_SOFTC *pCS, struct mbuf *pMbufChain );
LOCAL void csIntr( int Unit );
LOCAL void csBufferEvent( CS_SOFTC *pCS, USHORT BuffEvent );
LOCAL void csTransmitEvent( CS_SOFTC *pCS, USHORT TxEvent );
LOCAL void csReceiveEvent( CS_SOFTC *pCS, USHORT RxEvent );
LOCAL void csCopyRxFrame( CS_SOFTC *pCS, PRXBUF pRxBuff );
LOCAL void csProcessReceive( CS_SOFTC *pCS, PRXBUF pRxBuff );
LOCAL STATUS csInitRxBuff( CS_SOFTC *pCS );
LOCAL PRXBUF csAllocRxBuff( CS_SOFTC *pCS );
LOCAL void csFreeRxBuff( CS_SOFTC *pCS, PRXBUF pRxBuff );
void csShow( int Unit, BOOL Zap );
LOCAL USHORT csReadPacketPage( CS_SOFTC *pCS, USHORT Offset );
LOCAL void csWritePacketPage( CS_SOFTC *pCS, USHORT Offset, USHORT Value );
LOCAL void csInitQueue( CIR_QUEUE *Q );
LOCAL void *csDequeue( CIR_QUEUE *Q );
LOCAL STATUS csEnqueue( CIR_QUEUE *Q, void *pBuff );
LOCAL void csEventHandler( CS_SOFTC *pCS );
LOCAL BOOL csQueueEmpty( CIR_QUEUE *Q );
LOCAL void csTxNextFrame( CS_SOFTC *pCS );
/*********************** Functions for Multicasting *************************/
#ifndef BSD43_DRIVER
LOCAL UCHAR calculateHashIndex(UCHAR *pMulticastAddr);
LOCAL void updateCrc( USHORT bit );
LOCAL void csMCastAdd(CS_SOFTC *pCS, char *pData);
LOCAL void csMCastDel(CS_SOFTC *pCS, char *pData);
/* used to calculate multicast hash index */
int CRC_Poly[] = {1,1,1,0, 1,1,0,1,
1,0,1,1, 1,0,0,0,
1,0,0,0, 0,0,1,1,
0,0,1,0, 0,0,0,0 };
int CRC[33];
#endif
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* OS Entry-point Routines *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*******************************************************************************
*
* csAttach -
*
* This routine is a major entry point to this network interface driver and is
* called only once per operating system reboot by the operating system startup
* code. This routine is called before the csInit() routine.
*
* This routine takes passed-in configuration parameters and parameters from
* the EEPROM and fills in the instance global variables in the cs_softc
* structure. These variables are later used by the csInitChip() routine.
*
* This routine connects the interrupt handler, csIntr(), to the specified
* interrupt vector, initializes the 8259 PIC and resets the CS8900 chip.
*
* Finally, this routine calls the ether_attach() routine, to fill in the ifnet
* structure and attach this network interface driver to the system. The
* driver's main entry points (csInit(), csIoctl(), csOutput(), csReset()) are
* made visable to the protocol stack.
*
* RETURNS: OK, or ERROR if any of the called routines fail.
*
*/
STATUS csAttach( int Unit, int IOAddr, int IntVector, int IntLevel,int MemAddr, int MediaType, int DMAChannel , int ConfigFlags )
{
FAST CS_SOFTC *pCS;
if ( Unit >= CS_MAX_NUM_UNITS )
{
LOGMSG("csAttach: Invalid unit number (%d)\n",
Unit,0,0,0,0,0 );
return ERROR;
}
pCS = &cs_softc[Unit];
/* Save the passed-in parameters */
pCS->IOAddr = IOAddr;
pCS->IntLevel = IntLevel;
pCS->IntVector = IntVector;
pCS->pPacketPage = (USHORT *)MemAddr;
pCS->MediaType = MediaType;
pCS->ConfigFlags = ConfigFlags;
/* Start out in IO mode */
pCS->InMemoryMode = FALSE;
/* Init TX in progress flag */
pCS->TxInProgress = FALSE;
/* Init the TX start command */
pCS->TxStartCMD = CS_INITIAL_START_CMD;
/* Set counters to zero */
pCS->TxUnderruns = 0;
pCS->TotalTxUnderruns = 0;
pCS->RxDepth = 0;
pCS->MaxRxDepth = 0;
pCS->MaxTxDepth = 0;
pCS->LoanCount = 0;
pCS->Rdy4TxInts = 0;
pCS->NetJobDepth = 0;
#ifdef CS_DEBUG_ENABLE
pCS->TxQueueDepth = 0;
pCS->MaxTxQueueDepth = 0;
#endif
/* Initialize local queues */
pCS->pTxBuffFreeList = &TxBuffFreeList;
pCS->pRxBuffProcessList = &RxBuffProcessList;
pCS->pTxQueue = &TxQueue;
csInitQueue( pCS->pTxBuffFreeList );
csInitQueue( pCS->pRxBuffProcessList );
csInitQueue( pCS->pTxQueue );
/* Allocate the receive frame buffers */
if ( csInitRxBuff(pCS) == ERROR )
{
LOGMSG("csAttach: unit %d Can not allocate receive buffers\n",
Unit,0,0,0,0,0 );
return ERROR;
}
/* Verify that it is the correct chip */
if ( csVerifyChip(pCS) == ERROR )
{
LOGMSG("csAttach: unit %d, csVerifyChip failed\n",
Unit,0,0,0,0,0 );
return ERROR;
}
/* Get any CS8900 parameters not specifed in network interface table */
if ( sysEnetGetConfig(pCS) == ERROR )
{
LOGMSG("csAttach: unit %d, sysEnetGetConfig failed\n",
Unit,0,0,0,0,0 );
return ERROR;
}
/* Get Ethernet addr in BSP-specific manner and copy to ArpCom structure */
if ( sysEnetAddrGet(Unit,pCS->ArpCom.ac_enaddr) == ERROR )
{
LOGMSG("csAttach: unit %d, sysEnetAddrGet failed\n",
Unit,0,0,0,0,0 );
return ERROR;
}
/* Setup the interrupt handler and the IDT table entry */
if ( intConnect(INUM_TO_IVEC(pCS->IntVector),csIntr,Unit) == ERROR )
{
LOGMSG("csAttach: unit %d, Can not connect intertupt\n",
Unit,0,0,0,0,0 );
return ERROR;
}
/* Enable CS8900 interrupts at the system level */
if ( sysEnetIntEnable(pCS) == ERROR )
{
LOGMSG("csAttach: unit %d, sysEnetIntEnable failed\n",
Unit,0,0,0,0,0 );
return( ERROR );
}
/* Reset the chip */
if ( csResetChip(pCS) == ERROR )
{
LOGMSG("csAttach: unit %d, Can not reset chip\n",
Unit,0,0,0,0,0 );
return ERROR;
}
/* Attach this network interface driver to the system */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -