⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sndshdlcend.c

📁 4510b的vxworks的BSP
💻 C
📖 第 1 页 / 共 3 页
字号:
/* sndsHdlcEnd.c - SNDS END network interface driver for HDLC */

/* Copyright 1984-1997 Wind River Systems, Inc. */
#include "copyright_wrs.h"

/*

modification history
--------------------
01c,12nov99,ak added INCLUDE_HDLC
01b,07Oct99,nb	added documentation
01a,1Oct99,ak   adapted from WRS template.

*/

/*
DESCRIPTION

This module implements the Enhanced HDLC 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 HDLC controller consists of 2 HDLC channels.  2 HDMA channels 
are provided for transferring data to and from the memory.  The HDLC controller
supports NRZ, NRZI, FM, and Manchester data formats.  An internal baud rate
generator can be used for generating TX and RX clock.  A DPLL is also provided
to recover clock from the received data.  Up to 10 Mbps data speeds are
supported.

All the internal registers of the HDLC 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 sndshdlcend.h include file.  MACROS are provided to read and write these
registers.

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 sndsHdlcEndLoad() routine.  The parameters are passed 
into the sndsHdlcEndLoad() function as a single colon-delimited string.
The sndsHdlcEndLoad() function uses strtok() to parse the string, which it 
expects to be of the following format:

<unit>:<channel>:<baudRate>:<dataFormat>

TARGET-SPECIFIC PARAMETERS

.IP <unit>
A convenient holdover from the former model.  This parameter is used only
in the string name for the driver.

.IP <channel>
Channel number of the HDLC channel.  0 indicates Channel A and 1 indicates
Channel B

.IP <baudRate>
Indicates the desired network Baud Rate.

.IP "<dataFormat>"
Indicates the data format desired on the medium.  0 indicates NRZ, 1 indicates
NRZI, 2 indicates FM0, 3 indicates FM1, and 4 indicates Manchester

.LP

SYSTEM RESOURCE USAGE
When implemented, each channel requires the following system resources:

    - one mutual exclusion semaphore
    - tw ointerrupt vectors

The driver allocates the memory to share with the HDLC device unit.
It does so by calling the calloc() routine.  As a default, 128 transmit 
descriptors (size=16 bytes), 128 transmit buffers (size=END_BUFSIZ),
64 receive descriptors (size=16 bytes) and 64 receive buffers (size=END_BUFSIZ)
are 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 HDLC address and mask
for the device.  The single argument to this routine is the END_DEVICE
pointer.  By default this routine copies the HDLC address stored in
the global variable sndsHdlcChanxAddr defined in sndsHdlcend.h into the 
HDLC_END_DEVICE structure.  The global variable has to be changed for changing
the address and mask of the HDLC channel.

SPECIAL CONSIDERATION

The address and mask of HDLC port is hard-coded in the global array named
sndsHdlcChanxAddr defined in sndsHdlcEnd.h

INCLUDES:
end.h endLib.h etherMultiLib.h sndsHdlcend.h

SEE ALSO: muxLib, endLib
.I "Writing and Enhanced Network Driver"
*/

/* includes */

#include "vxWorks.h"
#include "sndsHdlcEnd.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 "etherLib.h"
#include "config.h"


/* defines */
#define	SNDS_CL_SIZE	2048

/* Configuration items */

#define END_BUFSIZ      (ETHERMTU + ENET_HDR_REAL_SIZ + 6)

/*
 * 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 Hdlc address from the BSP */


#ifndef SYS_HDLCSTAT_ADDR_GET
#   define SYS_HDLCSTAT_ADDR_GET(pDevice) \
	{ \
	IMPORT UINT32 sndsHdlcChanBAddr[]; \
	IMPORT UINT32 sndsHdlcChanAAddr[]; \
	if (pDevice->channel == 0) \
	{ \
		pDevice->hdlcAddr=sndsHdlcChanAAddr[0];\
		pDevice->hdlcHmask=sndsHdlcChanAAddr[1];	\
	} \
	else \
	{ \
		pDevice->hdlcAddr=sndsHdlcChanBAddr[0];\
		pDevice->hdlcHmask=sndsHdlcChanBAddr[1]; \
	} \
	}
	
#endif

/*
 * Macros to do a short (UINT16) access to the chip. Default
 * assumes a normal memory mapped device.
 */

#ifndef SNDS_HDLC_REG_WRITE
#   define SNDS_HDLC_REG_WRITE(pDrvCtrl,addr,value) \
	(*(UINT32 *)((pDrvCtrl)->baseAddr+(addr)) = (value))
#endif

#ifndef SNDS_HDLC_REG_READ
#   define SNDS_HDLC_REG_READ(pDrvCtrl,addr,pData) \
	((pData) = *(UINT32 *)((pDrvCtrl)->baseAddr+(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 */
#define END_MBLK_NUM	128			
#define END_CL_NUM		128
#define	CLDESCTBL_NUM_ENT 1
        
/* The definition of the driver control structure */

typedef struct hdlc_end_device	
    {
    END_OBJ     end;			/* The class we inherit from. */
    int			unit;			/* unit number */
	int		channel;		/* Channel number */
	
    int         hdlcVecTx;      /* HDLC TX  vector */
    int         hdlcVecRx;      /* HDLC RX  vector */
	int 		baudRate;		/* Baud rate */
	int 		dataFormat;		/* Data Format */
	UINT32		baseAddr;		/* Base addr of HDLC */
    long		flags;			/* Our local flags. */
    UINT32		hdlcAddr;		/* Hdlc Station address */	
    UINT32		hdlcHmask;		/* Hdlc Mask Address*/	
	M_CL_CONFIG hdlcEndMclConfig;	/* MBLK config */
	CL_DESC hdlcEndClDescTbl [CLDESCTBL_NUM_ENT];	/* Cluster config */
	SNDSHDLCBD 	*gpTxBDStart;	/* Start of TX BDs */
	SNDSHDLCBD 	*gpRxBDStart;	/* Start of RX BDs */
	SHTXSTATUS	gHTxStatus;		/* TX Statistics */
	SHRXSTATUS	gHRxStatus;		/* RX Statistics */
    } HDLC_END_DEVICE;


/* Definitions for the flags field */

#define END_PROMISCUOUS_FLAG	0x1
#define END_RCV_HANDLING_FLAG	0x2
#define END_POLLING				0x4

/* 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_HDLC_END

/* forward static functions */

LOCAL void	sndsHdlcEndReset	(HDLC_END_DEVICE *pDrvCtrl);
LOCAL void	sndsHdlcEndHandleRcvInt (HDLC_END_DEVICE *pDrvCtrl, UINT32 status);
LOCAL STATUS sndsHdlcEndRecv	(HDLC_END_DEVICE *pDrvCtrl, char* pData, UINT32 len);
LOCAL void  sndsHdlcEndInitialize(HDLC_END_DEVICE *pDevice);
LOCAL void	sndsHdlcTxBuffInitialize(HDLC_END_DEVICE *pDrvCtrl);
LOCAL void	sndsHdlcRxBuffInitialize(HDLC_END_DEVICE *pDrvCtrl);
LOCAL void  sndsHdlcTxInt(HDLC_END_DEVICE *pDrvCtrl);
LOCAL void  sndsHdlcRxInt(HDLC_END_DEVICE *pDrvCtrl);
LOCAL void 	sndsHdlcEndFree(HDLC_END_DEVICE *pDrvCtrl);
LOCAL void	sndsHdlcEndConfig	(HDLC_END_DEVICE *pDrvCtrl);

/* END Specific interfaces. */

/* This is the only externally visible interface. */

END_OBJ* 	sndsHdlcEndLoad (char* initString);

LOCAL STATUS	sndsHdlcEndStart	(HDLC_END_DEVICE* pDrvCtrl);
LOCAL STATUS	sndsHdlcEndStop	(HDLC_END_DEVICE* pDrvCtrl);
LOCAL STATUS	sndsHdlcEndUnload	();
LOCAL int		sndsHdlcEndIoctl	(HDLC_END_DEVICE* pDrvCtrl, int cmd, caddr_t data);
LOCAL STATUS	sndsHdlcEndSend	(HDLC_END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
LOCAL STATUS	sndsHdlcEndMCastAdd (HDLC_END_DEVICE* pDrvCtrl, char* pAddress);
LOCAL STATUS	sndsHdlcEndMCastDel (HDLC_END_DEVICE* pDrvCtrl, char* pAddress);
LOCAL STATUS	sndsHdlcEndMCastGet (HDLC_END_DEVICE* pDrvCtrl,
				    MULTI_TABLE* pTable);
LOCAL STATUS	sndsHdlcEndPollSend (HDLC_END_DEVICE* pDrvCtrl, M_BLK_ID* pBuf);
LOCAL STATUS	sndsHdlcEndPollRcv (HDLC_END_DEVICE* pDrvCtrl, M_BLK_ID* pBuf);
LOCAL STATUS	sndsHdlcEndPollStart (HDLC_END_DEVICE* pDrvCtrl);
LOCAL STATUS	sndsHdlcEndPollStop (HDLC_END_DEVICE* pDrvCtrl);
LOCAL STATUS	sndsHdlcEndParse	();
LOCAL STATUS	sndsHdlcEndMemInit	();

/*
 * Declare our function table.  This is static across all driver
 * instances.
 */

LOCAL NET_FUNCS endFuncTable =
    {
    (STATUS (*) (END_OBJ*))sndsHdlcEndStart,				/* Function to start the device. */
    (STATUS (*) (END_OBJ*))sndsHdlcEndStop,				/* Function to stop the device. */
    (STATUS (*) (END_OBJ*))sndsHdlcEndUnload,				/* Unloading function for the driver. */
    (int (*) (END_OBJ*, int, caddr_t))sndsHdlcEndIoctl,				/* Ioctl function for the driver. */
	(STATUS (*) (END_OBJ* , M_BLK_ID))sndsHdlcEndSend,				/* Send function for the driver. */
    (STATUS (*) (END_OBJ*, char*))sndsHdlcEndMCastAdd,			/* Multicast address add function for the driver. */
    (STATUS (*) (END_OBJ*, char*))sndsHdlcEndMCastDel,			/* Multicast address delete function for the driver. */
    (STATUS (*) (END_OBJ*, MULTI_TABLE*))sndsHdlcEndMCastGet,			/* Multicast table retrieve function for the driver. */
    (STATUS (*) (END_OBJ*, M_BLK_ID))sndsHdlcEndPollSend,			/* Polling send function for the driver. */
    (STATUS (*) (END_OBJ*, M_BLK_ID))sndsHdlcEndPollRcv,				/* Polling receive function for the driver. */
    endEtherAddressForm,        /* Put address info into a packet.  */
    endEtherPacketDataGet,      /* Get a pointer to packet data. */
    endEtherPacketAddrGet       /* Get packet addresses. */
    };

/*******************************************************************************
*
* sndsHdlcEndLoad - 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:channel:baudRate:dataFormat"
*
* RETURNS: An END object pointer or NULL on error.
*/

END_OBJ* sndsHdlcEndLoad
    (
    char* initString		/* String to be parsed by the driver. */
    )
    {
    HDLC_END_DEVICE 	*pDrvCtrl;

	if (initString[0] == NULL)
	{
		strcpy (initString, "hdlc");
		return (END_OBJ *)0;
	}

    /* allocate the device structure */
    pDrvCtrl = (HDLC_END_DEVICE *)calloc (sizeof (HDLC_END_DEVICE), 1);
    if (pDrvCtrl == NULL)
		goto errorExit;

    /* parse the init string, filling in the device structure */
    if (sndsHdlcEndParse (pDrvCtrl, initString) == ERROR)
		goto errorExit;

	if (pDrvCtrl->channel == 0)
		{
		pDrvCtrl->hdlcVecTx = INT_LVL_HDLCTxA;
		pDrvCtrl->hdlcVecRx = INT_LVL_HDLCRxA;
		pDrvCtrl->baseAddr = ASIC_BASE + HDLC_CHANNELA_BASE;
		}
	else
		{
		pDrvCtrl->hdlcVecTx = INT_LVL_HDLCTxB;
		pDrvCtrl->hdlcVecRx = INT_LVL_HDLCRxB;
		pDrvCtrl->baseAddr = ASIC_BASE + HDLC_CHANNELB_BASE;
		}
    /* Ask the BSP to provide the hdlc address. */
    SYS_HDLCSTAT_ADDR_GET(pDrvCtrl);
	strcpy (pDrvCtrl->end.devObject.name, "hdlc");
	strcpy (pDrvCtrl->end.devObject.description, "Samsung SNDS100 END HDLC Driver");

    /* initialize the END and MIB2 parts of the structure */
    
    if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, "hdlc",
                      pDrvCtrl->unit, &endFuncTable,
                      "HDLC Driver.") == ERROR
     || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_sdlc,
                      (UCHAR *)&pDrvCtrl->hdlcAddr, 4, ETHERMTU,
                      pDrvCtrl->baudRate)
		    == ERROR)
		goto errorExit;

    /* Perform memory allocation/distribution */

    if (sndsHdlcEndMemInit (pDrvCtrl) == ERROR)
		goto errorExit;

    /* reset and reconfigure the device */

    sndsHdlcEndReset (pDrvCtrl);
	sndsHdlcEndInitialize(pDrvCtrl);
    sndsHdlcEndConfig (pDrvCtrl);

    /* set the flags to indicate readiness */

    END_OBJ_READY (&pDrvCtrl->end,
		    IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST);
    ENDLOGMSG (("Done loading end...", 1, 2, 3, 4, 5, 6));

    return (&pDrvCtrl->end);

errorExit:
    if (pDrvCtrl != NULL)
		free ((char *)pDrvCtrl);

    return NULL;
    }

/*******************************************************************************
*
* sndsHdlcEndParse - parse the init string
*
* Parse the input string.  Fill in values in the driver control structure.
*
* The initialization string format is:
*  "unit:channel:baurate:dataFormat"
*
* .bS
* unit		Device unit number, a small integer.
* channel	Channel number of HDLC
* baudRate	HDLC serial baud rate
* dataFormat	NRZ/NRZI/FM/Manchester
* .bE
*
* RETURNS: OK or ERROR for invalid arguments.
*/

STATUS sndsHdlcEndParse
    (
    HDLC_END_DEVICE * pDrvCtrl,	/* device pointer */
    char * initString		/* information string */
    )
    {
    char*	tok;
    char*	pHolder = NULL;

    /* Parse the initString */

    /* Unit number. */

    tok = strtok_r (initString, ":", &pHolder);
    if (tok == NULL)
		return ERROR;
    pDrvCtrl->unit = atoi (tok);

    /* Tx Interrupt vector. */

    tok = strtok_r (NULL, ":", &pHolder);
    if (tok == NULL)
		return ERROR;
    pDrvCtrl->channel = atoi (tok);

     /* Rx Interrupt vector. */
	tok = strtok_r (NULL, ":", &pHolder);
    if (tok == NULL)
		return ERROR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -