📄 sndsend_cjw.c
字号:
/* sndsEnd.c - SNDS END network interface driver for Ethernet */
/* Copyright 1984-1997 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01f,25nov99,knp, changed the name from "end" to "secEnd"
01e,12nov99,knp, Corrected handling EIOCSFLAGS, added IFF_MULTICAST flag
01d,06nov99,knp, updated multicast address support
01c,18oct99,knp added polled mode support
01b,27sep99,nb added documentation
01a,20sep99,nts&knp adapted from WRS template
*/
/*
DESCRIPTION
This module implements the Enhanced Ethernet driver for Samsung SNDS100 Ver 1.0
Evaluation Board for their KS32C50100 microcontroller.
KS32C50100 is an ARM based processor with several integrated peripherals.
It has an interrupt controller, two 32-bit timers, one Ethernet controller,
two HDLC controllers, one IIC controller, general purpose I/O ports, and a
2-channel DMA controller.
The built-in Ethernet controller consists of 10/100 Ethernet MAC with MII
interface to an external PHY device and a Buffered DMA controller for
transferring data to and from the memory. The SNDS100 board has a Level One
LXT970 Ethernet PHY device that supports both 10Base-T and 100Base-T
Ethernet.
All the internal registers of the Ethernet MAC and BDMA controller are
accessible as 32-bit integers at the internal system register addresses as
defined in the KS32C50100 Microcontroller User's Manual. The register
addresses are defined in sndsend.h include file.
The driver requires several target-specific values provided as an input
string to the load routine. These target-specific values and the external
support routines are described below.
This network interface driver does not include support for trailer protocols
or data chaining. However, buffer loaning has been implemented in an effort
to boost performance.
This driver maintains cache coherency by setting the Address bit 26 (A26) of
descriptor and buffer addresses. KS32C50100 accesses all memory locations
with A26 set in a non-cached mode. However, A26 is not used for accessing
the memory. See the KS32C50100 Microcontroller User's Manual for details.
Because of this feature, allocating buffer space using the cacheDmaMalloc()
routine is not required.
BOARD LAYOUT
This device is on-chip. No jumpering diagram is necessary.
EXTERNAL INTERFACE
This driver provides the standard END external interface. The only external
interface is the sndsEndLoad() routine. The parameters are passed
into the sndsEndLoad() function as a single colon-delimited string.
The sndsEndLoad() function uses strtok() to parse the string, which it
expects to be of the following format:
<unit>:<speed>:<duplex>:<autoneg>
TARGET-SPECIFIC PARAMETERS
.IP <unit>
A convenient holdover from the former model. This parameter is used only
in the string name for the driver. Value must be 0
.IP <speed>
Indicates the desired network speed. Valid values are 10 and 100. This
parameter is ignored if auto-negotiation is enabled. See below.
.IP "<duplex>"
Indicates the desired duplex mode of operation. A value 1 indicates full-
duplex and a value 0 indicated half duplex. This parameter is ignored if
auto-negotiation is enabled.
.IP "<auto-neg>"
Indicates whether auto-negotiation has to be enabled or not. A value of 1
indicates that auto-negotiation should be enabled. A value of 0 indicates
that it should be disabled. If auto-negotiation is enabled, the speed and
duplex values are ignored.
.LP
SYSTEM RESOURCE USAGE
When implemented, this driver requires the following system resources:
- one mutual exclusion semaphore
- four interrupt vectors
The driver allocates the memory to share with the Ethernet device unit.
It does so by calling the calloc() routine. As a default, 64 transmit
descriptors (size=16 bytes), 64 transmit buffers (size=END_BUFSIZ), and
64 receive descriptors (size=16 bytes) are allocated. TX_FD_NUM and RX_FD_NUM
macros define the number of descriptors allocated.
As a default, 128 MBLK structures, 128 CLBLK structures and 128 clusters
(size=2048) are allocated in the net pool. END_MBLK_NUM and END_CL_NUM
macros define the number of structures allocated.
The macros SYS_INT_CONNECT, SYS_INT_DISCONNECT, and SYS_INT_ENABLE allow
the driver to be customized for BSPs that use special versions of these
routines.
The macro SYS_INT_CONNECT is used to connect the interrupt handler to
the appropriate vector. By default it is the routine intConnect().
The macro SYS_INT_DISCONNECT is used to disconnect the interrupt handler prior
to unloading the module. By default this is a dummy routine that
returns OK.
The macro SYS_INT_ENABLE is used to enable the interrupt level for the
end device. It is called once during initialization. By default this is
the routine intEnable().
The macro SYS_ENET_ADDR_GET is used to get the ethernet address (MAC)
for the device. The single argument to this routine is the END_DEVICE
pointer. By default this routine copies the ethernet address stored in
the global variable sndsEndEnetAddr defined in sndsend.h into the
END_DEVICE structure. The global variable has to be changed for changing
the MAC address of the Ethernet port.
SPECIAL CONSIDERATION
The MAC address of Ethernet port is hard-coded in the global array named
sndsEndEnetAddr defined in sndsEnd.h
The internal registers of MAC and BDMA controllers in the KS32C50100
microcontroller are accessible as 32-bit integers at pre-defined address
locations. Hence separate macros are not provided for register accesses.
All through the driver code, these registers are accessed directly.
INCLUDES:
end.h endLib.h etherMultiLib.h sndsend.h
SEE ALSO: muxLib, endLib
.I "Writing and Enhanced Network Driver"
*/
/* includes */
#include "vxWorks.h"
#include "sndsEnd.h" /* mod knp 7sep99"drv/end/sndsEnd.h"Common defines. */
#include "etherMultiLib.h" /* multicast stuff. */
#include "end.h" /* Common END structures. */
#include "endLib.h"
#include "lstLib.h" /* Needed to maintain protocol list. */
#include "cacheLib.h"
#include "stdlib.h"
#include "stdio.h"
#include "intLib.h"
#include "iv.h"
#include "netLib.h"
#include "config.h"
/* defines */
/* Configuration items */
#define ENET_HDR_REAL_SIZ 14
#define END_BUFSIZ (ETHERMTU + ENET_HDR_REAL_SIZ + 6)
#define END_SPEED 10000000
#define SNDS_CL_SIZE 2048
#define RX_FD_NUM 64
#define TX_FD_NUM 64
#define LS_POLLING 0x20
/*
* 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) \
{ \
IMPORT STATUS sysIntConnect(); \
*pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), \
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; /* HELP: need a real routine */ \
}
#endif
/* Macro to enable the appropriate interrupt level */
#ifndef SYS_INT_ENABLE
#define SYS_INT_ENABLE(pDrvCtrl) \
{ \
IMPORT void sysLanIntEnable(); \
sysLanIntEnable (pDrvCtrl->ilevel); \
}
#endif
/* Macro to get the ethernet address from the BSP */
#ifndef SYS_ENET_ADDR_GET
# define SYS_ENET_ADDR_GET(pDevice) \
{ \
IMPORT unsigned char sndsEndEnetAddr[]; \
bcopy ((char *)sndsEndEnetAddr, (char *)(&pDevice->enetAddr), 6); \
}
#endif
/*
* Macros to do a short (UINT16) access to the chip. Default
* assumes a normal memory mapped device.
*/
#ifndef SNDS_OUT_SHORT
# define SNDS_OUT_SHORT(pDrvCtrl,addr,value) \
(*(USHORT *)addr = value)
#endif
#ifndef SNDS_IN_SHORT
# define SNDS_IN_SHORT(pDrvCtrl,addr,pData) \
(*pData = *addr)
#endif
#ifndef SNDS_OUT_LONG
# define SNDS_OUT_LONG(pDrvCtrl,addr,value) \
(*(UINT32 *)addr = value)
#endif
#ifndef SNDS_IN_LONG
# define SNDS_IN_LONG(pDrvCtrl,addr,pData) \
(*pData = *addr)
#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)
/* typedefs */
typedef struct free_args
{
void* arg1;
void* arg2;
} FREE_ARGS;
/* The definition of the driver control structure */
typedef struct end_device
{
END_OBJ end; /* The class we inherit from. */
int unit; /* unit number */
int ivecBdmaTx; /* bdmaTx interrupt vector */
int ivecBdmaRx; /* bdmaRx interrupt vector */
int ivecMacTx; /* macTx interrupt vector */
int ivecMacRx; /* macRx interrupt vector */
long flags; /* Our local flags. */
UCHAR enetAddr[6]; /* ethernet address */
UCHAR netSpeed; /* 10 or 100 */
UCHAR duplexMode; /* HDX = 0. FDX = 1 */
UCHAR autoNeg; /* 1 = autoneg enabled */
BOOL fdInitialized; /* Set to TRUE after FD allocation */
ETHER_STATISTICS statistics; /* Ethernet statistics counters */
UINT32 addrList[32]; /* Array for storing addresses Max = 21, i.e. 32 long words */
UINT32 mcastAddrCount; /* Number of valid multicast addresses */
} END_DEVICE;
/* globals*/
/*
* This will only work if there is only a single unit, for multiple
* unit device drivers these should be integrated into the END_DEVICE
* structure.
*/
M_CL_CONFIG endMclConfig = /* network mbuf configuration table */
{
/*
no. mBlks no. clBlks memArea memSize
----------- ---------- ------- -------
*/
0, 0, NULL, 0
};
CL_DESC endClDescTbl [] = /* network cluster pool configuration table */
{
/*
clusterSize num memArea memSize
----------- ---- ------- -------
*/
{SNDS_CL_SIZE, 0, NULL, 0}
};
int endClDescTblNumEnt = (NELEMENTS(endClDescTbl));
/* new additions */
RECEIVE_FRAME_DESC *gpReceiveFrameDescStart;
TRANSMIT_FRAME_DESC *gpTransmitFrameDescStart;
UINT32 gStatusLengthPrevious; /* For bug fix */
BOOL gBugFixDone = FALSE;
/* Definitions for the flags field */
#define END_PROMISCUOUS_FLAG 0x1
#define END_RCV_HANDLING_FLAG 0x2
#define END_MBLK_NUM 400
#define END_CL_NUM 400
#define SNDS_DATA_OFFSET 2
#define SNDS_MAX_MULTI 20
/* DEBUG MACROS */
#undef DEBUG
#ifdef DEBUG
#include "nvLogLib.h" /* Needed to debug polled mode. */
int endDebug = 1;
#define ENDLOGMSG(x) \
if (endDebug) \
{ \
logMsg x; \
}
#else
#define ENDLOGMSG(x)
#endif /* ENDDEBUG */
/* LOCALS */
#ifdef INCLUDE_SNDS_END
/* forward static functions */
LOCAL void sndsEndReset (END_DEVICE *pDrvCtrl); /* added by knp/nts 14/9/99 */
LOCAL STATUS sndsEndStart (END_DEVICE *pDrvCtrl); /* added by knp/nts 14/9/99 */
LOCAL void sndsEndBdmaRxInt (END_DEVICE *pDrvCtrl); /* added by knp/nts 15/9/99 */
LOCAL void sndsEndBdmaTxInt (END_DEVICE *pDrvCtrl);
LOCAL void sndsEndMacRxInt (END_DEVICE *pDrvCtrl);
LOCAL void sndsEndMacTxInt (END_DEVICE *pDrvCtrl);
LOCAL void sndsEndHandleRcvInt (END_DEVICE *pDrvCtrl, UINT32 stat);
LOCAL STATUS sndsEndRecv (END_DEVICE *pDrvCtrl, char* pData, UINT32 length);
LOCAL void sndsEndConfig (END_DEVICE *pDrvCtrl);
LOCAL UINT32 sndsEndPhyRead (UINT32 phyRegAddr, UINT32 phyAddr);
LOCAL void sndsEndPhyWrite (UINT32 phyRegAddr, UINT32 phyAddr, UINT32 phyData);
LOCAL void sndsEndMacInitialize (END_DEVICE *pDevice);
LOCAL STATUS sndsEndFdInitialize (END_DEVICE *pDrvCrtl);
LOCAL void sndsEndFdFree (END_DEVICE *pDrvCtrl);
LOCAL void sndsEndBugFix (UINT16 *);
LOCAL void sndsEndAddrFilterSet (END_DEVICE *pDrvCtrl);
/* END Specific interfaces. */
/* This is the only externally visible interface. */
END_OBJ* sndsEndLoad (char* initString);
LOCAL STATUS sndsEndStart (END_DEVICE* pDrvCtrl);
LOCAL STATUS sndsEndStop (END_DEVICE* pDrvCtrl);
LOCAL STATUS sndsEndUnload ();
LOCAL int sndsEndIoctl (END_DEVICE* pDrvCtrl, int cmd, caddr_t data);
LOCAL STATUS sndsEndSend (END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
LOCAL STATUS sndsEndMCastAdd (END_DEVICE* pDrvCtrl, char* pAddress);
LOCAL STATUS sndsEndMCastDel (END_DEVICE* pDrvCtrl, char* pAddress);
LOCAL STATUS sndsEndMCastGet (END_DEVICE* pDrvCtrl, MULTI_TABLE* pTable);
LOCAL STATUS sndsEndPollSend (END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
LOCAL STATUS sndsEndPollRcv (END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
LOCAL STATUS sndsEndPollStart (END_DEVICE* pDrvCtrl);
LOCAL STATUS sndsEndPollStop (END_DEVICE* pDrvCtrl);
LOCAL STATUS sndsEndParse ();
LOCAL STATUS sndsEndMemInit ();
/*
* Declare our function table. This is static across all driver
* instances.
*/
LOCAL NET_FUNCS endFuncTable =
{
(STATUS (*) (END_OBJ*))sndsEndStart, /* Function to start the device. */
(STATUS (*) (END_OBJ*))sndsEndStop, /* Function to stop the device. */
(STATUS (*) (END_OBJ*))sndsEndUnload, /* Unloading function for the driver. */
(int (*) (END_OBJ*, int, caddr_t))sndsEndIoctl, /* Ioctl function for the driver. */
(STATUS (*) (END_OBJ* , M_BLK_ID))sndsEndSend, /* Send function for the driver. */
(STATUS (*) (END_OBJ*, char*))sndsEndMCastAdd, /* Multicast address add function for the driver. */
(STATUS (*) (END_OBJ*, char*))sndsEndMCastDel, /* Multicast address delete function for the driver. */
(STATUS (*) (END_OBJ*, MULTI_TABLE*))sndsEndMCastGet, /* Multicast table retrieve function for the driver. */
(STATUS (*) (END_OBJ*, M_BLK_ID))sndsEndPollSend, /* Polling send function for the driver. */
(STATUS (*) (END_OBJ*, M_BLK_ID))sndsEndPollRcv, /* Polling receive function for the driver. */
endEtherAddressForm, /* Put address info into a packet. */
endEtherPacketDataGet, /* Get a pointer to packet data. */
endEtherPacketAddrGet /* Get packet addresses. */
};
/*******************************************************************************
*
* sndsEndLoad - 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:
*
* "<unit>:<Speed>:<duplex>:<autoneg>"
*
* RETURNS: An END object pointer or NULL on error.
*/
END_OBJ* sndsEndLoad
(
char* initString /* String to be parsed by the driver. */
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -