original files of m241
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
# Makefile - makefile for target/src/drv/end
|
||||
#
|
||||
# Copyright (c) 1996-2011 Wind River Systems, Inc.
|
||||
#
|
||||
# The right to copy, distribute, modify or otherwise make use
|
||||
# of this software may be licensed only pursuant to the terms
|
||||
# of an applicable Wind River license agreement.
|
||||
#
|
||||
# modification history
|
||||
# --------------------
|
||||
# 03j,19sep11,rlg remove bcm1250 elements
|
||||
# 03i,29dec09,h_k removed unsupported module builds from LP64.
|
||||
# 03h,12nov08,dlk Compile endCommon.o and endEtherHdr.o with CC_OPTIM_NORMAL.
|
||||
# Turn off -fvolatile/-Xpointers-volatile for endCommon.o,
|
||||
# endEtherHdr.o, endLib.o, and miiLib.o.
|
||||
# 03g,07jul08,jpb Changed SMP conditional.
|
||||
# 03f,21may08,dlk Add endCommon.o for simulators. Add endEtherHdr.o.
|
||||
# 03e,14mar08,dlk MUX2 redesign.
|
||||
# 03d,11apr07,rec add support for M5200
|
||||
# 03c,06jul07,pch For SMP, build only endLib and miiLib
|
||||
# 03b,26jun07,mze Only build smEnd.o smEndShow.o if not SMP
|
||||
# 03a,09mar07,pes Update for new MIPS library structure.
|
||||
# 02z,01jun06,wap Compile non-driver files with full optimization
|
||||
# 02y,18nov05,j_b add motFecEnd for MCF5400
|
||||
# 02x,12sep05,pch add amd8111LanEnd driver for maple BSP
|
||||
# 02w,15aug05,kkz Updating doc values
|
||||
# 02v,29apr05,kkz Updating for new doc directory
|
||||
# 02u,31jan05,dtr Add in compilation of TSEC driver.
|
||||
# 02t,07dec04,h_k removed sh7615End.
|
||||
# 02s,15sep04,jln removed endNetBufLib.o
|
||||
# 02r,21jun04,rcs removed ln7990End.o and ntEnd.o from OBJS_COMMON
|
||||
# 02q,21jun04,mdo Remove deprecated motFccEnd.c.
|
||||
# 02p,14jun04,h_k added wancomEnd for PPC604 and MIPS64.
|
||||
# 02o,08jun04,jeg added smEnd support for simulators
|
||||
# 02n,27may04,dgp change output dir and TOC structure (DOC_CHAPTER & DOC_DIR)
|
||||
# 02n,04may04,pch SPR 94932: remove PPC32 special case
|
||||
# 02m,01mar04,jln add smEnd/smEndShow
|
||||
# 02l,04feb04,pch PPC32 floating-point adjustments
|
||||
# 02k,10dec03,pch restored emacEnd, motCpmEnd, motFcc2End, motFccEnd,
|
||||
# nicEvbEnd which are still used
|
||||
# 02j,05dec03,rcs removed unsupported files from DOC_FILES and OBJS_COMMON
|
||||
# 02i,14jul03,jln add emacEnd.c
|
||||
# 02h,14apr03,pch Add PPC32 support
|
||||
# 02g,21mar03,rcs Added endNetBufLib.o to OBJS_COMMON SPR# 87039
|
||||
# 02f,03feb03,m_h Shorten list of IPv6 supported drivers
|
||||
# 02e,14jan03,m_h IPv6 support
|
||||
# 02e,14jan03,gjc SPR#85164 and SPR#85093
|
||||
# Adding motFcc2End.c and m8260SccEnd.c
|
||||
# 02d,20jun02,pgh Add bcm1250MacEnd.c.
|
||||
# 02c,17may02,zmm Global au1000 name changes. SPR 77333.
|
||||
# 02b,12mar02,dat SPR 72518 Drivers docs in separate directory
|
||||
# 02a,16nov01,dgp remove ntEnd.c from doc build
|
||||
# 01z,09nov01,jmp only build endLib.o for simulators.
|
||||
# 01y,12oct01,tam added repackaging support
|
||||
# 01x,14jun01,rcs added gei82543End
|
||||
# 01w,17sep99,ms_ add motFccEnd
|
||||
# 01v,14apr99,cn added miiLib
|
||||
# 01w,01jun01,mem Added au1000End.c
|
||||
# 01v,14apr99,cn added miiLib
|
||||
# 01z,11oct00,zl build sh7615End.o for SH7600 only
|
||||
# 01y,29aug00,rsh add sh7615End device to build list
|
||||
# 01x,17may00,zl corrected DOC_FILES for ns83902
|
||||
# 01w,10apr00,zl renamed nicEnd to ns83902End
|
||||
# 01v,07apr00,zl added nicEnd support
|
||||
# 01u,16mar99,dat nicEvb is only for PPC403. mbcEnd only for 68302
|
||||
# 01t,13mar99,db added mbcEnd support.
|
||||
# 01s,12mar99,cn added el3c90xEnd support (SPR# 25327).
|
||||
# 01r,12mar99,ms_ add elt3c509End.o to OBJS_COMMON
|
||||
# 01q,11mar99,db added mb86960End support.
|
||||
# 01p,08mar99,sbs added ultraEnd support.
|
||||
# 01o,04mar99,cn added motFecEnd support (SPR# 23153).
|
||||
# 01n,17feb99,sut added nicEvbEnd support.
|
||||
# 01m,01feb99,jkf added ln97xEnd support.
|
||||
# 01l,26jan99,dat merge from 1_0_x. (added motCpmEnd.c, ne2000End.c)
|
||||
# 01k,01jun98,dat fixed EXTRA_INCLUDES to use TGT_DIR, added fei and olicom
|
||||
# drivers.
|
||||
# 01j,13mar98,cn added fei82557End to OBJS_COMMON and DOC_FILES.
|
||||
# 01i,04may98,cym added ntEnd (Windows ULIP driver.)
|
||||
# 01h,02apr98,jpd added iOlicomEnd driver to DOC_FILES
|
||||
# 01g,06dec97,tam added dec21x4xEnd and removed dec21x40End.
|
||||
# 01f,25aug97,vin deleted the sonic driver for the beta2 patch.
|
||||
# 01e,03May97,sal restored sonic driver to DOC_FILES
|
||||
# 01d,30apr97,jag deleted the sonic driver from the DOC_FILES due to man page
|
||||
# errors.
|
||||
# 01c,24apr97,map added dec21x40End
|
||||
# 01b,18apr97,sal added the sn83932End.c
|
||||
# 01a,28feb97,vin created from 01d of MakeSkel
|
||||
#
|
||||
# DESCRIPTION
|
||||
# This file contains the makefile rules for building ENDs (Enhanced
|
||||
# Network Drivers) into the VxWorks library.
|
||||
#
|
||||
# Old style network drivers (i.e. BSD style) are contained in src/drv/netif.
|
||||
#
|
||||
|
||||
TGT_DIR=$(WIND_BASE)/target
|
||||
|
||||
LIB_BASE_NAME=drv
|
||||
|
||||
# Including defs.library to see if _WRS_CONFIG_SMP or _WRS_CONFIG_LP64 is
|
||||
# defined.
|
||||
# It must be after LIB_BASE_NAME
|
||||
include $(TGT_DIR)/h/make/defs.library
|
||||
|
||||
DOC_FILES= emacEnd.c endCommon.c endLib.c endEtherHdr.c \
|
||||
ne2000End.c dec21x40End.c \
|
||||
fei82557End.c gei82543End.c iOlicomEnd.c elt3c509End.c \
|
||||
ln97xEnd.c motFecEnd.c el3c90xEnd.c miiLib.c ns83902End.c \
|
||||
auEnd.c motFcc2End.c m8260SccEnd.c \
|
||||
smEnd.c smEndShow.c wancomEnd.c amd8111LanEnd.c
|
||||
|
||||
EXTRA_INCLUDE=-I$(TGT_DIR)/h/
|
||||
|
||||
OBJS_COMMON = endCommon.o endLib.o endEtherHdr.o \
|
||||
ne2000End.o dec21x40End.o \
|
||||
fei82557End.o gei82543End.o iOlicomEnd.o ln97xEnd.o \
|
||||
elt3c509End.o el3c90xEnd.o miiLib.o ns83902End.o \
|
||||
smEnd.o smEndShow.o
|
||||
OBJS_MCF5400 = motFecEnd.o
|
||||
OBJS_MIPSI32 = auEnd.o
|
||||
OBJS_MIPSI64 = wancomEnd.o
|
||||
OBJS_PPC403 = nicEvbEnd.o
|
||||
OBJS_PPC405 = emacEnd.o
|
||||
OBJS_PPC440 = emacEnd.o
|
||||
OBJS_PPC603 = motFcc2End.o m8260SccEnd.o
|
||||
OBJS_PPC604 = wancomEnd.o
|
||||
OBJS_PPC860 = motCpmEnd.o motFecEnd.o
|
||||
OBJS_PPC32 = emacEnd.o nicEvbEnd.o motFcc2End.o m8260SccEnd.o \
|
||||
motCpmEnd.o motFecEnd.o wancomEnd.o motTsecEnd.o \
|
||||
amd8111LanEnd.o
|
||||
|
||||
ifdef _WRS_CONFIG_LP64
|
||||
OBJS = endCommon.o endLib.o endEtherHdr.o
|
||||
else
|
||||
ifdef _WRS_CONFIG_SMP
|
||||
OBJS = endCommon.o endLib.o endEtherHdr.o miiLib.o
|
||||
else
|
||||
OBJS = $(OBJS_COMMON) $(OBJS_$(CPU))
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# redefine OBJS for simulators since only endLib.o need to be built
|
||||
#
|
||||
ifneq ($(subst SIM,,$(CPU)),$(CPU))
|
||||
OBJS = endCommon.o endLib.o endEtherHdr.o smEnd.o smEndShow.o
|
||||
endif
|
||||
|
||||
IPV6_OBJS_COMMON = endLib.o ne2000End.o dec21x40End.o \
|
||||
fei82557End.o gei82543End.o iOlicomEnd.o ln97xEnd.o \
|
||||
elt3c509End.o el3c90xEnd.o miiLib.o
|
||||
|
||||
# Suppress local build of generic drivers for all PPC except generic PPC32.
|
||||
ifeq ($(VX_CPU_FAMILY),ppc)
|
||||
ifneq ($(CPU),PPC32)
|
||||
IPV6_OBJS_COMMON=
|
||||
endif
|
||||
endif
|
||||
|
||||
IPV6_OBJS_MCF5200 =
|
||||
IPV6_OBJS_MCF5400 = motFecEnd.o
|
||||
IPV6_OBJS_MIPSI32 = auEnd.o
|
||||
IPV6_OBJS_MIPSI64 = wancomEnd.o
|
||||
IPV6_OBJS_PPC403 = nicEvbEnd.o
|
||||
IPV6_OBJS_PPC405 = emacEnd.o
|
||||
IPV6_OBJS_PPC440 = emacEnd.o
|
||||
IPV6_OBJS_PPC603 = motFcc2End.o m8260SccEnd.o
|
||||
IPV6_OBJS_PPC604 = wancomEnd.o
|
||||
IPV6_OBJS_PPC860 = motCpmEnd.o motFecEnd.o
|
||||
IPV6_OBJS_PPC32 = emacEnd.o nicEvbEnd.o motFcc2End.o \
|
||||
m8260SccEnd.o motCpmEnd.o motFecEnd.o wancomEnd.o \
|
||||
amd8111LanEnd.o
|
||||
|
||||
ifdef _WRS_CONFIG_LP64
|
||||
IPV6_OBJS = endLib.o
|
||||
else
|
||||
ifdef _WRS_CONFIG_SMP
|
||||
IPV6_OBJS = endLib.o miiLib.o
|
||||
else
|
||||
IPV6_OBJS = $(IPV6_OBJS_COMMON) $(IPV6_OBJS_$(CPU))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(BUILD_IPV6),)
|
||||
OBJS = $(IPV6_OBJS)
|
||||
EXTRA_DEFINE += -DWR_IPV6
|
||||
endif
|
||||
|
||||
# Unfortunately, adding $(CC_OPTIM_NORMAL) doesn't
|
||||
# turn off -fvolatile or -Xpointers-volatile, so do it
|
||||
# manually. Also, turn of -Xsize-opt=0 for diab.
|
||||
ifeq ($(findstring gnu, $(TOOL)), gnu)
|
||||
CFLAGS_endCommon.o = $(CC_OPTIM_NORMAL) -fno-volatile
|
||||
CFLAGS_endEtherHdr.o = $(CC_OPTIM_NORMAL) -fno-volatile
|
||||
CFLAGS_endLib.o = $(CC_OPTIM_NORMAL) -fno-volatile
|
||||
CFLAGS_miiLib.o = $(CC_OPTIM_NORMAL) -fno-volatile
|
||||
else
|
||||
CFLAGS_endCommon.o = $(CC_OPTIM_NORMAL) -Xpointers-volatile=0 -Xsize-opt=0
|
||||
CFLAGS_endEtherHdr.o = $(CC_OPTIM_NORMAL) -Xpointers-volatile=0 -Xsize-opt=0
|
||||
CFLAGS_endLib.o = $(CC_OPTIM_NORMAL) -Xpointers-volatile=0 -Xsize-opt=0
|
||||
CFLAGS_miiLib.o = $(CC_OPTIM_NORMAL) -Xpointers-volatile=0 -Xsize-opt=0
|
||||
endif
|
||||
|
||||
include $(TGT_DIR)/h/make/rules.library
|
||||
|
||||
CC_OPTIM=$(CC_OPTIM_DRIVER)
|
||||
include $(TGT_DIR)/h/make/defs.drivers
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,957 @@
|
||||
/* endCommon.c - common support for END2/END/NPT style network drivers */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008-2009, 2013 Wind River Systems, Inc.
|
||||
*
|
||||
* The right to copy, distribute, modify or otherwise make use of this
|
||||
* software may be licensed only pursuant to the terms of an applicable Wind
|
||||
* River license agreement.
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
01l,04sep13,xms fix CHECKED_RETURN error. (WIND00414265)
|
||||
01k,04may09,cww Updated wdStart parameter types
|
||||
01j,29apr09,h_k updated for LP64 support.
|
||||
01i,24nov08,dlk Go to new scalable semaphore APIs to avoid inlining
|
||||
causing code size increase.
|
||||
01h,27aug08,dlk Move from deprecated 'minimal' semaphore API to 'inline' API.
|
||||
Use inline semaphores for both UP and SMP.
|
||||
01g,12jun08,dlk Initialize pEndObj->pMib2Tbl in endM2Init().
|
||||
01f,03jun08,dlk Move MCACHE stuff to endLib.c also.
|
||||
01e,21may08,dlk Move the endPool infrastructure to endLib.c.
|
||||
01d,12may08,dlk Move _func_end2VxBusConnect here from ipcom_end2.c for
|
||||
scalability.
|
||||
01c,11may08,dlk Small documentation correction.
|
||||
01b,26mar08,dlk Move end8023AddressForm(), endEtherAddressForm(),
|
||||
endEtherPacketDataGet(), and endEtherPacketAddrGet()
|
||||
from here to endLib.c.
|
||||
01a,14mar08,dlk Written. Copied most contents from endLib.c.
|
||||
*/
|
||||
|
||||
/*
|
||||
DESCRIPTION
|
||||
This library contains support routines common to all styles of VxWorks
|
||||
network driver (END2, END, and NPT).
|
||||
|
||||
Support routines for END2-style drivers only are found in end2Lib.
|
||||
Support routines for END-style drivers only are found in endLib.
|
||||
Support routines for NPT-style drivers only are found in nptLib.
|
||||
|
||||
Routines specific to particular drivers belong in the drivers themselves.
|
||||
This library does contains some routines specific to particular classes
|
||||
of drivers (e.g. ethernet drivers).
|
||||
|
||||
To use this feature, include the following component:
|
||||
INCLUDE_END_COMMON
|
||||
|
||||
INCLUDE FILES: endLib.h
|
||||
*/
|
||||
|
||||
/* includes */
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <endLib.h>
|
||||
#include <muxLib.h>
|
||||
#include <string.h>
|
||||
#include <private/muxLibP.h>
|
||||
|
||||
#include <memLib.h>
|
||||
#include <stdlib.h>
|
||||
#include <memPartLib.h>
|
||||
#include <netBufLib.h> /* FIXME */
|
||||
#include <etherMultiLib.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netLib.h>
|
||||
#include <wdLib.h>
|
||||
#include <m2IfLib.h>
|
||||
#include <intLib.h>
|
||||
#include <spinLockLib.h>
|
||||
|
||||
/* defines */
|
||||
|
||||
/* typedefs */
|
||||
|
||||
/* forward declarations */
|
||||
|
||||
STATUS _endM2Packet_1213 (END_OBJ *, M_BLK_ID, UINT);
|
||||
STATUS _endM2Packet_2233 (END_OBJ *, M_BLK_ID, UINT);
|
||||
|
||||
/* globals */
|
||||
|
||||
MIB_ROUTINES * pMibRtn; /* structure to hold MIB-II callback pointers */
|
||||
FUNCPTR endM2Packet = _endM2Packet_1213; /* default. can be set to 2233 */
|
||||
u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
M_BLK_ID (*_func_endEtherAddressForm) ();
|
||||
M_BLK_ID (*_func_end8023AddressForm) ();
|
||||
STATUS (*_func_endEtherPacketDataGet) ();
|
||||
STATUS (*_func_endEtherPacketAddrGet) (M_BLK_ID, M_BLK_ID,
|
||||
M_BLK_ID, M_BLK_ID, M_BLK_ID);
|
||||
|
||||
VOIDFUNCPTR _func_end2VxBusConnect;
|
||||
|
||||
/* locals */
|
||||
|
||||
LOCAL void endPollStatsJobQueue (END_IFDRVCONF *);
|
||||
LOCAL void endPollStatsPoll (END_IFDRVCONF *);
|
||||
|
||||
void endTxSemTake
|
||||
(
|
||||
END_OBJ* pEnd,
|
||||
int tmout
|
||||
)
|
||||
{
|
||||
#ifdef END_TX_SEM_INLINE
|
||||
(void)semMTake_inline (pEnd->txSem, tmout, END_TXSEM_INLINE_OPTS);
|
||||
#elif defined (END_TX_SEM_SCALABLE)
|
||||
(void)semMTakeScalable (pEnd->txSem, tmout, END_TXSEM_SCALABLE_OPTS);
|
||||
#else
|
||||
(void)semTake(pEnd->txSem,tmout);
|
||||
#endif
|
||||
}
|
||||
|
||||
void endTxSemGive
|
||||
(
|
||||
END_OBJ* pEnd
|
||||
)
|
||||
{
|
||||
#ifdef END_TX_SEM_INLINE
|
||||
(void)semMGive_inline (pEnd->txSem, END_TXSEM_INLINE_OPTS);
|
||||
#elif defined (END_TX_SEM_SCALABLE)
|
||||
(void)semMGiveScalable (pEnd->txSem, END_TXSEM_SCALABLE_OPTS);
|
||||
#else
|
||||
(void)semGive (pEnd->txSem);
|
||||
#endif
|
||||
}
|
||||
|
||||
void endFlagsClr
|
||||
(
|
||||
END_OBJ* pEnd,
|
||||
int clrBits
|
||||
)
|
||||
{
|
||||
pEnd->flags &= ~clrBits;
|
||||
}
|
||||
|
||||
void endFlagsSet
|
||||
(
|
||||
END_OBJ* pEnd,
|
||||
int setBits
|
||||
)
|
||||
{
|
||||
pEnd->flags |= (setBits);
|
||||
}
|
||||
|
||||
int endFlagsGet
|
||||
(
|
||||
END_OBJ* pEnd
|
||||
)
|
||||
{
|
||||
return(pEnd->flags);
|
||||
}
|
||||
|
||||
int endMultiLstCnt
|
||||
(
|
||||
END_OBJ* pEnd
|
||||
)
|
||||
{
|
||||
return(lstCount(&pEnd->multiList));
|
||||
}
|
||||
|
||||
ETHER_MULTI* endMultiLstFirst
|
||||
(
|
||||
END_OBJ *pEnd
|
||||
)
|
||||
{
|
||||
return((ETHER_MULTI *)(lstFirst(&pEnd->multiList)));
|
||||
}
|
||||
|
||||
ETHER_MULTI* endMultiLstNext
|
||||
(
|
||||
ETHER_MULTI* pCurrent
|
||||
)
|
||||
{
|
||||
return((ETHER_MULTI *)(lstNext(&pCurrent->node)));
|
||||
}
|
||||
|
||||
char* endDevName
|
||||
(
|
||||
END_OBJ* pEnd
|
||||
)
|
||||
{
|
||||
return(pEnd->devObject.name);
|
||||
}
|
||||
|
||||
void endObjectUnload
|
||||
(
|
||||
END_OBJ* pEnd
|
||||
)
|
||||
{
|
||||
if (pEnd->txSem != NULL)
|
||||
semDelete (pEnd->txSem);
|
||||
|
||||
lstFree (&pEnd->multiList);
|
||||
if (pEnd->pSnarf != NULL)
|
||||
{
|
||||
KHEAP_FREE (pEnd->pSnarf);
|
||||
}
|
||||
|
||||
pEnd->devObject.dummyBinding = NULL;
|
||||
|
||||
pEnd->pSnarf = NULL;
|
||||
pEnd->pTyped = NULL;
|
||||
pEnd->pPromisc = NULL;
|
||||
pEnd->pStop = NULL;
|
||||
pEnd->nProtoSlots = 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endM2Init - Initialize MIB-II agnostically (1213 or 2233)
|
||||
*
|
||||
* This routine encapsulates and generalizes mib2Init and endObjFlagSet
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
STATUS endM2Init
|
||||
(
|
||||
END_OBJ * pEndObj, /* object to be initialized */
|
||||
long ifType, /* ifType from m2Lib.h */
|
||||
UCHAR * phyAddr, /* MAC/PHY address */
|
||||
int addrLength, /* MAC/PHY address length */
|
||||
int mtuSize, /* MTU size */
|
||||
int speed, /* interface speed */
|
||||
UINT flags /* flags to set in the pEndObj */
|
||||
)
|
||||
{
|
||||
M2_INTERFACETBL *pM2Int; /* 1213 struct to be initialized */
|
||||
int status;
|
||||
|
||||
pEndObj->pMib2Tbl = NULL;
|
||||
|
||||
if (pMibRtn == NULL) /* 1213? */
|
||||
{
|
||||
pM2Int = &(pEndObj->mib2Tbl);
|
||||
status = mib2Init (pM2Int, ifType, phyAddr,
|
||||
addrLength, mtuSize, speed);
|
||||
}
|
||||
|
||||
else /* 2233? */
|
||||
{
|
||||
status = (pMibRtn->mibTblInit) (&pEndObj->end_m2Id, ifType,
|
||||
phyAddr, addrLength,
|
||||
mtuSize, speed,
|
||||
pEndObj->devObject.name,
|
||||
pEndObj->devObject.unit);
|
||||
if (status == OK)
|
||||
{
|
||||
pEndObj->pMib2Tbl = &pEndObj->end_m2Id;
|
||||
endM2Packet = _endM2Packet_2233;
|
||||
flags |= END_MIB_2233;
|
||||
}
|
||||
}
|
||||
|
||||
endObjFlagSet (pEndObj, flags);
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endM2Free - Frees what endM2Init allocates
|
||||
*
|
||||
* This routine determines what endM2Init created, and frees it
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
STATUS endM2Free
|
||||
(
|
||||
END_OBJ * pEndObj /* object where m2 data lives */
|
||||
)
|
||||
{
|
||||
if (pEndObj->pMib2Tbl != &pEndObj->end_m2Id &&
|
||||
pEndObj->pMib2Tbl != NULL)
|
||||
return (pMibRtn->mibFree) (pEndObj->pMib2Tbl);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endM2Ioctl - generic ioctl
|
||||
*
|
||||
* This routine handles the EIOCGMIB2 and EIOCGMIB2233 ioctls.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO: EINVAL
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
int endM2Ioctl
|
||||
(
|
||||
END_OBJ * pEndObj, /* object where m2 data lives */
|
||||
UINT32 cmd, /* command to process */
|
||||
caddr_t data /* pointer to data */
|
||||
)
|
||||
{
|
||||
int error = OK;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case EIOCGMIB2:
|
||||
if (data == NULL)
|
||||
error=EINVAL;
|
||||
else
|
||||
bcopy ((char *) &pEndObj->mib2Tbl, (char *) data,
|
||||
sizeof (pEndObj->mib2Tbl));
|
||||
|
||||
break;
|
||||
|
||||
case EIOCGMIB2233:
|
||||
if ((data == NULL) || (pEndObj->pMib2Tbl == NULL))
|
||||
error = EINVAL;
|
||||
else
|
||||
*((M2_ID **)data) = pEndObj->pMib2Tbl;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* _endM2Packet_1213 - count a packet assuming 1213
|
||||
*
|
||||
* This routine counts a packet in the absence of 2233.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
STATUS _endM2Packet_1213
|
||||
(
|
||||
END_OBJ * pEndObj, /* object where counter lives */
|
||||
M_BLK_ID pMblk, /* packet to count */
|
||||
UINT ctrl /* M2_PACKET_IN OUT, etc. */
|
||||
)
|
||||
{
|
||||
M2_INTERFACETBL *pMib = &(pEndObj->mib2Tbl); /* struct to be updated */
|
||||
BOOL isNUcast = 0; /* is the packet non-unicast? */
|
||||
int status = OK;
|
||||
int nMACOffset = 0;
|
||||
|
||||
/* we know that the destination address is the first byte in the frame */
|
||||
if (pMblk != NULL)
|
||||
{
|
||||
/*
|
||||
* Special handling for 802.4 and 802.5. In 802.4,
|
||||
* the destination address is preceded by a single
|
||||
* frame control byte. In 802.5, the destination
|
||||
* address is preceded by an access control byte
|
||||
* and a frame control byte.
|
||||
*/
|
||||
|
||||
if (pMib->ifType == M2_ifType_iso88024_tokenBus)
|
||||
nMACOffset = 1;
|
||||
|
||||
if (pMib->ifType == M2_ifType_iso88025_tokenRing)
|
||||
nMACOffset = 2;
|
||||
|
||||
isNUcast = (pMblk->mBlkHdr.mData[nMACOffset] & (UINT8) 0x01);
|
||||
}
|
||||
else
|
||||
/* Don't go on */
|
||||
return (ERROR);
|
||||
|
||||
switch (ctrl)
|
||||
{
|
||||
case M2_PACKET_IN_ERROR:
|
||||
pMib->ifInErrors++;
|
||||
break;
|
||||
|
||||
case M2_PACKET_IN:
|
||||
if (isNUcast)
|
||||
pMib->ifInNUcastPkts++;
|
||||
else
|
||||
pMib->ifInUcastPkts++;
|
||||
pMib->ifInOctets += pMblk->mBlkPktHdr.len;
|
||||
break;
|
||||
|
||||
case M2_PACKET_OUT_ERROR:
|
||||
pMib->ifOutErrors++;
|
||||
break;
|
||||
|
||||
case M2_PACKET_OUT:
|
||||
if (isNUcast)
|
||||
pMib->ifOutNUcastPkts++;
|
||||
else
|
||||
pMib->ifOutUcastPkts++;
|
||||
pMib->ifOutOctets += pMblk->mBlkHdr.mLen;
|
||||
break;
|
||||
|
||||
case M2_PACKET_IN_DISCARD:
|
||||
pMib->ifInDiscards++;
|
||||
break;
|
||||
|
||||
case M2_PACKET_OUT_DISCARD:
|
||||
pMib->ifOutDiscards++;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = ERROR;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* _endM2Packet_2233 - count a packet assuming 2233
|
||||
*
|
||||
* This routine counts a packet in the presence of 2233.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
STATUS _endM2Packet_2233
|
||||
(
|
||||
END_OBJ * pEndObj, /* object where counter lives */
|
||||
M_BLK_ID pMblk, /* packet to count */
|
||||
UINT ctrl /* M2_PACKET_IN OUT, etc. */
|
||||
)
|
||||
{
|
||||
int status = OK;
|
||||
M2_ID * pMib2Tbl; /* RFC 2233 MIB objects */
|
||||
pMib2Tbl = pEndObj->pMib2Tbl;
|
||||
|
||||
switch (ctrl)
|
||||
{
|
||||
case M2_PACKET_IN_ERROR:
|
||||
status = (pMib2Tbl->m2CtrUpdateRtn) (pMib2Tbl,
|
||||
M2_ctrId_ifInErrors, 1);
|
||||
break;
|
||||
|
||||
case M2_PACKET_IN:
|
||||
case M2_PACKET_OUT:
|
||||
status = (pMib2Tbl->m2PktCountRtn) (pMib2Tbl, ctrl,
|
||||
(UCHAR *) pMblk->m_data,
|
||||
(size_t) pMblk->m_pkthdr.len);
|
||||
break;
|
||||
|
||||
case M2_PACKET_OUT_ERROR:
|
||||
status = (pMib2Tbl->m2CtrUpdateRtn) (pMib2Tbl,
|
||||
M2_ctrId_ifOutErrors, 1);
|
||||
break;
|
||||
|
||||
case M2_PACKET_IN_DISCARD:
|
||||
status = (pMib2Tbl->m2CtrUpdateRtn) (pMib2Tbl,
|
||||
M2_ctrId_ifInDiscards, 1);
|
||||
break;
|
||||
|
||||
case M2_PACKET_OUT_DISCARD:
|
||||
status = (pMib2Tbl->m2CtrUpdateRtn) (pMib2Tbl,
|
||||
M2_ctrId_ifOutDiscards, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = ERROR;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endMibIfInit - Initialize the MIB-II callback pointers
|
||||
*
|
||||
* This routine initializes the MIB-II pointers used by the callback macros.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
STATUS endMibIfInit
|
||||
(
|
||||
FUNCPTR pMibTblInitRtn,
|
||||
FUNCPTR pMibAllocRtn,
|
||||
FUNCPTR pMibFreeRtn,
|
||||
FUNCPTR pMibCtrUpdate,
|
||||
FUNCPTR pMibVarUpdate
|
||||
)
|
||||
{
|
||||
if ((pMibTblInitRtn != NULL) &&
|
||||
(pMibAllocRtn != NULL) && (pMibFreeRtn != NULL) &&
|
||||
(pMibCtrUpdate != NULL) && (pMibVarUpdate != NULL))
|
||||
{
|
||||
if (pMibRtn == NULL)
|
||||
{
|
||||
if ((pMibRtn =
|
||||
(MIB_ROUTINES *) KHEAP_ALLOC (sizeof (MIB_ROUTINES))) == NULL)
|
||||
{
|
||||
return(ERROR);
|
||||
}
|
||||
}
|
||||
pMibRtn->mibTblInit = pMibTblInitRtn;
|
||||
pMibRtn->mibAlloc = pMibAllocRtn; /* deprecate */
|
||||
pMibRtn->mibFree = pMibFreeRtn; /* deprecate */
|
||||
pMibRtn->mibCntUpdate = pMibCtrUpdate;
|
||||
pMibRtn->mibVarUpdate = pMibVarUpdate;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* mib2Init - initialize a MIB-II structure
|
||||
*
|
||||
* Initialize a MIB-II structure. Set all error counts to zero. Assume
|
||||
* a 10Mbps Ethernet device.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
STATUS mib2Init
|
||||
(
|
||||
M2_INTERFACETBL *pMib, /* struct to be initialized */
|
||||
long ifType, /* ifType from m2Lib.h */
|
||||
UCHAR * phyAddr, /* MAC/PHY address */
|
||||
int addrLength, /* MAC/PHY address length */
|
||||
int mtuSize, /* MTU size */
|
||||
int speed /* interface speed */
|
||||
)
|
||||
{
|
||||
/* Clear out our statistics. */
|
||||
|
||||
bzero ((char *)pMib, sizeof (*pMib));
|
||||
|
||||
pMib->ifPhysAddress.addrLength = addrLength;
|
||||
|
||||
/* Obtain our Ethernet address and save it */
|
||||
bcopy ((char *) phyAddr, (char *)pMib->ifPhysAddress.phyAddress,
|
||||
pMib->ifPhysAddress.addrLength);
|
||||
|
||||
/* Set static statistics. assume ethernet */
|
||||
|
||||
pMib->ifType = ifType;
|
||||
pMib->ifMtu = mtuSize;
|
||||
pMib->ifSpeed = speed;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* mib2ErrorAdd - change a MIB-II error count
|
||||
*
|
||||
* This function adds a specified value to one of the MIB-II error counters in a
|
||||
* MIB-II interface table. The counter to be altered is specified by the
|
||||
* errCode argument. errCode can be MIB2_IN_ERRS, MIB2_IN_UCAST, MIB2_OUT_ERRS
|
||||
* or MIB2_OUT_UCAST. Specifying a negative value reduces the error count, a
|
||||
* positive value increases the error count.
|
||||
*
|
||||
* RETURNS: OK
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
STATUS mib2ErrorAdd
|
||||
(
|
||||
M2_INTERFACETBL * pMib,
|
||||
int errCode,
|
||||
int value
|
||||
)
|
||||
{
|
||||
|
||||
switch (errCode)
|
||||
{
|
||||
default:
|
||||
case MIB2_IN_ERRS:
|
||||
pMib->ifInErrors += value;
|
||||
break;
|
||||
|
||||
case MIB2_IN_UCAST:
|
||||
pMib->ifInUcastPkts += value;
|
||||
break;
|
||||
|
||||
case MIB2_OUT_ERRS:
|
||||
pMib->ifOutErrors += value;
|
||||
break;
|
||||
|
||||
case MIB2_OUT_UCAST:
|
||||
pMib->ifOutUcastPkts += value;
|
||||
break;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* endObjInit - initialize an END_OBJ structure
|
||||
*
|
||||
* This routine initializes an END_OBJ structure and fills it with data from
|
||||
* the argument list. It also creates and initializes semaphores and
|
||||
* protocol list.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
STATUS endObjInit
|
||||
(
|
||||
END_OBJ * pEndObj, /* object to be initialized */
|
||||
DEV_OBJ* pDevice, /* ptr to device struct */
|
||||
char * pBaseName, /* device base name, for example, "ln" */
|
||||
int unit, /* unit number */
|
||||
NET_FUNCS * pFuncTable, /* END device functions */
|
||||
char* pDescription
|
||||
)
|
||||
{
|
||||
size_t maxLen;
|
||||
|
||||
pEndObj->devObject.pDevice = pDevice;
|
||||
|
||||
/* Create the transmit semaphore. */
|
||||
|
||||
#ifdef END_TX_SEM_INLINE
|
||||
pEndObj->txSem = semMCreate (END_TXSEM_INLINE_OPTS & SEM_MUT_OPTIONS_MASK);
|
||||
#elif defined (END_TX_SEM_SCALABLE)
|
||||
pEndObj->txSem = semMCreate (END_TXSEM_SCALABLE_OPTS & SEM_MUT_OPTIONS_MASK);
|
||||
#else
|
||||
pEndObj->txSem = semMCreate ( SEM_Q_PRIORITY |
|
||||
SEM_DELETE_SAFE |
|
||||
SEM_INVERSION_SAFE);
|
||||
#endif
|
||||
|
||||
if (pEndObj->txSem == NULL)
|
||||
{
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
/* Install data and functions into the network node. */
|
||||
|
||||
pEndObj->flags = 0;
|
||||
|
||||
/* initialize protocol table (empty) */
|
||||
|
||||
pEndObj->pSnarf = NULL;
|
||||
pEndObj->pTyped = NULL;
|
||||
pEndObj->pPromisc = NULL;
|
||||
pEndObj->pStop = NULL;
|
||||
pEndObj->nProtoSlots = 0;
|
||||
|
||||
/* Don't modify the strings passed as arguments! */
|
||||
|
||||
maxLen = sizeof(pEndObj->devObject.name) - 1;
|
||||
|
||||
strncpy (pEndObj->devObject.name, pBaseName, maxLen);
|
||||
pEndObj->devObject.name [maxLen] = EOS;
|
||||
|
||||
maxLen = sizeof(pEndObj->devObject.description) - 1;
|
||||
|
||||
strncpy (pEndObj->devObject.description, pDescription, maxLen);
|
||||
pEndObj->devObject.description [maxLen] = EOS;
|
||||
|
||||
pEndObj->devObject.unit = unit;
|
||||
|
||||
pEndObj->pFuncTable = pFuncTable;
|
||||
|
||||
/* Clear multicast info. */
|
||||
|
||||
lstInit (&pEndObj->multiList);
|
||||
pEndObj->nMulti = 0;
|
||||
|
||||
pEndObj->devObject.dummyBinding = pEndObj;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* endObjFlagSet - set the `flags' member of an END_OBJ structure
|
||||
*
|
||||
* As input, this routine expects a pointer to an END_OBJ structure
|
||||
* (the <pEnd> parameter) and a flags value (the <flags> parameter).
|
||||
* This routine sets the 'flags' member of the END_OBJ structure
|
||||
* to the value of the <flags> parameter.
|
||||
*
|
||||
* Because this routine assumes that the driver interface is now up,
|
||||
* this routine also sets the 'attached' member of the referenced END_OBJ
|
||||
* structure to TRUE.
|
||||
*
|
||||
* RETURNS: OK
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
STATUS endObjFlagSet
|
||||
(
|
||||
END_OBJ * pEnd,
|
||||
UINT flags
|
||||
)
|
||||
{
|
||||
pEnd->attached = TRUE;
|
||||
pEnd->flags = flags;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPollStatsPoll - poll an interface's information
|
||||
*
|
||||
* This routine calls the endPollStatsIfPoll() routine to gather
|
||||
* information from a particular interface, then re-arms the interface's
|
||||
* polling watchdog timer.
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
LOCAL void endPollStatsPoll
|
||||
(
|
||||
END_IFDRVCONF *pDrvConf
|
||||
)
|
||||
{
|
||||
|
||||
if (pDrvConf == NULL)
|
||||
return;
|
||||
|
||||
/* Gather the stats */
|
||||
|
||||
pDrvConf->ifPollRtn (pDrvConf);
|
||||
|
||||
/*
|
||||
* Reload the watchdog.
|
||||
* don't need return from function call
|
||||
*/
|
||||
|
||||
(void) wdStart(pDrvConf->ifWatchdog, pDrvConf->ifPollInterval,
|
||||
(WD_RTN) endPollStatsJobQueue, (_Vx_usr_arg_t) pDrvConf);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPollStatsJobQueue - polling stats counter scheduler routine
|
||||
*
|
||||
* This routine is an intermediary function necessitated by the fact
|
||||
* that wdStart() only takes two arguments: we need to pass it three
|
||||
* (netJobAdd(), plus two others). This routine just invokes netJobAdd()
|
||||
* to call the endPollStatsIfPoll() routine and passes it a pointer to
|
||||
* the END_IFDRVCONF structure being polled. We must use netJobAdd()
|
||||
* here to avoid executing the rest of the polling code at interrupt
|
||||
* context.
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
LOCAL void endPollStatsJobQueue
|
||||
(
|
||||
END_IFDRVCONF *pDrvConf
|
||||
)
|
||||
{
|
||||
|
||||
if (netJobAdd ((FUNCPTR) endPollStatsPoll, (_Vx_usr_arg_t) pDrvConf, 0, 0, 0, 0)
|
||||
!= OK)
|
||||
{
|
||||
/* Reload the watchdog. */
|
||||
|
||||
(void) wdStart(pDrvConf->ifWatchdog, pDrvConf->ifPollInterval,
|
||||
(WD_RTN) endPollStatsJobQueue, (_Vx_usr_arg_t) pDrvConf);
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPollStatsInit - initialize polling statistics updates
|
||||
*
|
||||
* This routine is used to begin polling of the interface specified by
|
||||
* pCookie and will periodically call out to the pIfPollRtn function, which
|
||||
* will collect the interface statistics. If the driver supports polling
|
||||
* updates, this routine will start a watchdog that will invoke the
|
||||
* pIfPollRtn routine periodically. The watchdog will automatically
|
||||
* re-arm itself. The pIfPollRtn will be passed a pointer to the driver's
|
||||
* END_IFDRVCONF structure as an argument.
|
||||
*
|
||||
* RETURNS: ERROR if the driver doesn't support polling, otherwise OK.
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
STATUS endPollStatsInit
|
||||
(
|
||||
void * pCookie,
|
||||
FUNCPTR pIfPollRtn
|
||||
)
|
||||
{
|
||||
END_IFDRVCONF * pDrvConf;
|
||||
int error;
|
||||
PROTOCOL_BINDING tmpBinding;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
if (pCookie == NULL || pIfPollRtn == NULL)
|
||||
return (ERROR);
|
||||
|
||||
tmpBinding.pEnd = PDEVCOOKIE_TO_ENDOBJ(pCookie);
|
||||
|
||||
if (tmpBinding.pEnd == NULL)
|
||||
return (ERROR);
|
||||
|
||||
/* Get this driver's configuration info */
|
||||
|
||||
error = muxIoctl ((void *)&tmpBinding, EIOCGPOLLCONF,
|
||||
(caddr_t) &pDrvConf);
|
||||
|
||||
/* Return error if driver doesn't support stats polling. */
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Create the watchdog. */
|
||||
|
||||
pDrvConf->ifWatchdog = wdCreate ();
|
||||
if (pDrvConf->ifWatchdog == NULL)
|
||||
return (ERROR);
|
||||
|
||||
pDrvConf->ifEndObj = NULL;
|
||||
pDrvConf->ifMuxCookie = pCookie;
|
||||
pDrvConf->ifPollRtn = pIfPollRtn;
|
||||
|
||||
/* Kick off the watchdog. */
|
||||
|
||||
return wdStart (pDrvConf->ifWatchdog, pDrvConf->ifPollInterval,
|
||||
(WD_RTN) endPollStatsJobQueue, (_Vx_usr_arg_t) pDrvConf);
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endEtherCrc32BeGet - calculate a big-endian CRC-32 checksum
|
||||
*
|
||||
* This routine performs a big endian CRC 32 calculation over an
|
||||
* arbitrary block of data. Many ethernet controllers implement multicast
|
||||
* filtering using a hash table where a CRC-32 checksum of the multicast
|
||||
* group address is used as the table index. This function is provided
|
||||
* as a convenience so that each driver doesn't need its own private copy.
|
||||
*
|
||||
* RETURNS: the 32-bit checksum of the supplied buffer
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
UINT32 endEtherCrc32BeGet
|
||||
(
|
||||
const UINT8 *pBuf,
|
||||
size_t len
|
||||
)
|
||||
{
|
||||
size_t i;
|
||||
UINT32 crc, carry;
|
||||
int bit;
|
||||
UINT8 data;
|
||||
|
||||
crc = 0xffffffff; /* initial value */
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
for (data = *pBuf++, bit = 0; bit < 8; bit++, data >>= 1)
|
||||
{
|
||||
carry = ((crc & 0x80000000) ? 1 : 0) ^ (data & 0x01);
|
||||
crc <<= 1;
|
||||
if (carry)
|
||||
crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
|
||||
}
|
||||
}
|
||||
|
||||
return (crc);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endEtherCrc32LeGet - calculate a little-endian CRC-32 checksum
|
||||
*
|
||||
* This routine performs a little endian CRC 32 calculation over an
|
||||
* arbitrary block of data. Many ethernet controllers implement multicast
|
||||
* filtering using a hash table where a CRC-32 checksum of the multicast
|
||||
* group address is used as the table index. This function is provided
|
||||
* as a convenience so that each driver doesn't need its own private copy.
|
||||
*
|
||||
* RETURNS: the 32-bit checksum of the supplied buffer
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
UINT32 endEtherCrc32LeGet
|
||||
(
|
||||
const UINT8 *pBuf,
|
||||
size_t len
|
||||
)
|
||||
{
|
||||
static const UINT32 crcTab[] =
|
||||
{
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
||||
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
||||
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
|
||||
};
|
||||
size_t i;
|
||||
UINT32 crc;
|
||||
|
||||
crc = 0xffffffff; /* initial value */
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
crc ^= pBuf[i];
|
||||
crc = (crc >> 4) ^ crcTab[crc & 0xf];
|
||||
crc = (crc >> 4) ^ crcTab[crc & 0xf];
|
||||
}
|
||||
|
||||
return (crc);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
/* endEtherHdr.c - legacy mux/muxTk ethernet/802.3 header forming routines */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008, 2013-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* The right to copy, distribute, modify or otherwise make use of this
|
||||
* software may be licensed only pursuant to the terms of an applicable Wind
|
||||
* River license agreement.
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
12jun14,p_x check parameters of endEtherAddressForm(). (VXW6-82932)
|
||||
01c,22sep13,xms fix NULL_RETURNS error. (WIND00414265)
|
||||
01b,24nov08,dlk Add string.h header.
|
||||
01a,21may08,dlk Written. Moved routines here from endLib.c.
|
||||
*/
|
||||
|
||||
/*
|
||||
DESCRIPTION
|
||||
This library contains M_BLK-oriented routines used to construct and parse
|
||||
Ethernet II or 802.3 link headers. These routines are referenced
|
||||
by most END-style network drivers, but are also used by legacy M_BLK-
|
||||
oriented protocols, even in the case that only END2 drivers are in
|
||||
the system.
|
||||
|
||||
To use this feature, include the following component:
|
||||
INCLUDE_END_ETHER_HDR
|
||||
|
||||
INCLUDE FILES: endLib.h
|
||||
*/
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <endLib.h>
|
||||
#include <muxLib.h>
|
||||
#include <string.h>
|
||||
/* #include <private/muxLibP.h> */
|
||||
#include <net/mbuf.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#define LLC_SNAP_FRAMELEN 8
|
||||
|
||||
void endEtherHdrInit (void)
|
||||
{
|
||||
/*
|
||||
* Function pointers used for scalability -- so that
|
||||
* END2 drivers need not reference these routines
|
||||
* directly to provide them when available for legacy
|
||||
* protocols.
|
||||
*/
|
||||
_func_endEtherPacketDataGet = endEtherPacketDataGet;
|
||||
_func_endEtherPacketAddrGet = endEtherPacketAddrGet;
|
||||
_func_end8023AddressForm = end8023AddressForm;
|
||||
_func_endEtherAddressForm = endEtherAddressForm;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* end8023AddressForm - form an 802.3 address into a packet
|
||||
*
|
||||
* This routine accepts the source and destination addressing information
|
||||
* through <pSrcAddr> and <pDstAddr> mBlks and returns an M_BLK_ID to the
|
||||
* assembled link level header. If the <bcastFlag> argument is TRUE, it
|
||||
* sets the destination address to the link-level broadcast address and
|
||||
* ignores the <pDstAddr> contents. This routine prepends the link level header
|
||||
* into <pMblk> if there is enough space available or it allocates a new
|
||||
* mBlk/clBlk/cluster and prepends the new mBlk to the mBlk chain passed in
|
||||
* <pMblk>. This routine returns a pointer to an mBlk which contains the
|
||||
* link level header information.
|
||||
*
|
||||
* RETURNS: M_BLK_ID or NULL.
|
||||
*
|
||||
* ERRNO
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
M_BLK_ID end8023AddressForm
|
||||
(
|
||||
M_BLK_ID pMblk,
|
||||
M_BLK_ID pSrcAddr,
|
||||
M_BLK_ID pDstAddr,
|
||||
BOOL bcastFlag
|
||||
)
|
||||
{
|
||||
short dataLen; /* length of data including LLC */
|
||||
USHORT *pSrc;
|
||||
USHORT *pDst;
|
||||
|
||||
struct llc * pLlc; /* link layer control header */
|
||||
|
||||
dataLen = pMblk->mBlkPktHdr.len + LLC_SNAP_FRAMELEN;
|
||||
dataLen = htons (dataLen);
|
||||
|
||||
M_PREPEND(pMblk, SIZEOF_ETHERHEADER + LLC_SNAP_FRAMELEN, M_DONTWAIT);
|
||||
|
||||
if (pMblk != NULL)
|
||||
{
|
||||
CSUM_IPHDR_OFFSET(pMblk) = SIZEOF_ETHERHEADER + LLC_SNAP_FRAMELEN;
|
||||
|
||||
/* Fill in destination address */
|
||||
|
||||
pDst = (USHORT *)pMblk->m_data;
|
||||
if (bcastFlag)
|
||||
{
|
||||
pDst[0] = 0xFFFF;
|
||||
pDst[1] = 0xFFFF;
|
||||
pDst[2] = 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSrc = (USHORT *)pDstAddr->m_data;
|
||||
pDst[0] = pSrc[0];
|
||||
pDst[1] = pSrc[1];
|
||||
pDst[2] = pSrc[2];
|
||||
}
|
||||
|
||||
/* Fill in source address */
|
||||
|
||||
pDst += 3;
|
||||
pSrc = (USHORT *)pSrcAddr->m_data;
|
||||
pDst[0] = pSrc[0];
|
||||
pDst[1] = pSrc[1];
|
||||
pDst[2] = pSrc[2];
|
||||
|
||||
/* Fill in length */
|
||||
|
||||
pDst += 3;
|
||||
pDst[0] = dataLen;
|
||||
|
||||
/* Fill in LLC using SNAP values */
|
||||
|
||||
pDst++;
|
||||
pLlc = (struct llc *) pDst;
|
||||
|
||||
pLlc->llc_dsap = LLC_SNAP_LSAP;
|
||||
pLlc->llc_ssap = LLC_SNAP_LSAP;
|
||||
pLlc->llc_un.type_snap.control = LLC_UI;
|
||||
pLlc->llc_un.type_snap.org_code[0] =
|
||||
pLlc->llc_un.type_snap.org_code[1] =
|
||||
pLlc->llc_un.type_snap.org_code[2] = 0;
|
||||
|
||||
/* Enter ethernet network type code into the LLC snap field */
|
||||
|
||||
pLlc->llc_un.type_snap.ether_type = pDstAddr->mBlkHdr.reserved;
|
||||
|
||||
}
|
||||
|
||||
return(pMblk);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endEtherAddressForm - form an Ethernet address into a packet
|
||||
*
|
||||
* This routine accepts the source and destination addressing information
|
||||
* through <pSrcAddr> and <pDstAddr> and returns an 'M_BLK_ID' that points
|
||||
* to the assembled link-level header. To do this, this routine prepends
|
||||
* the link-level header into the cluster associated with <pMblk> if there
|
||||
* is enough space available in the cluster. It then returns a pointer to
|
||||
* the pointer referenced in <pMblk>. However, if there is not enough space
|
||||
* in the cluster associated with <pMblk>, this routine reserves a
|
||||
* new 'mBlk'-'clBlk'-cluster construct for the header information.
|
||||
* It then prepends the new 'mBlk' to the 'mBlk' passed in <pMblk>. As the
|
||||
* function value, this routine then returns a pointer to the new 'mBlk',
|
||||
* which the head of a chain of 'mBlk' structures. The second element of this
|
||||
* chain is the 'mBlk' referenced in <pMblk>.
|
||||
*
|
||||
* RETURNS: M_BLK_ID or NULL.
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
M_BLK_ID endEtherAddressForm
|
||||
(
|
||||
M_BLK_ID pMblk, /* pointer to packet mBlk */
|
||||
M_BLK_ID pSrcAddr, /* pointer to source address */
|
||||
M_BLK_ID pDstAddr, /* pointer to destination address */
|
||||
BOOL bcastFlag /* use link-level broadcast? */
|
||||
)
|
||||
{
|
||||
USHORT *pDst;
|
||||
USHORT *pSrc;
|
||||
|
||||
/* validate parameters */
|
||||
|
||||
if ((pMblk == NULL) || (pSrcAddr == NULL) || (pDstAddr == NULL))
|
||||
return (NULL);
|
||||
|
||||
M_PREPEND(pMblk, SIZEOF_ETHERHEADER, M_DONTWAIT);
|
||||
|
||||
/*
|
||||
* This routine has been optimized somewhat in order to avoid
|
||||
* the use of bcopy(). On some architectures, a bcopy() could
|
||||
* result in a call into (allegedly) optimized architecture-
|
||||
* specific routines. This may be fine for copying large chunks
|
||||
* of data, but we're only copying 6 bytes. It's simpler just
|
||||
* to open code some 16-bit assignments. The compiler would be
|
||||
* hard-pressed to produce sub-optimal code for this, and it
|
||||
* avoids at least one function call (possibly several).
|
||||
*/
|
||||
|
||||
if (pMblk != NULL)
|
||||
{
|
||||
CSUM_IPHDR_OFFSET(pMblk) = SIZEOF_ETHERHEADER;
|
||||
|
||||
pDst = (USHORT *)pMblk->m_data;
|
||||
if (bcastFlag)
|
||||
{
|
||||
pDst[0] = 0xFFFF;
|
||||
pDst[1] = 0xFFFF;
|
||||
pDst[2] = 0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSrc = (USHORT *)pDstAddr->m_data;
|
||||
pDst[0] = pSrc[0];
|
||||
pDst[1] = pSrc[1];
|
||||
pDst[2] = pSrc[2];
|
||||
}
|
||||
|
||||
/* Advance to the source address field, fill it in. */
|
||||
pDst += 3;
|
||||
pSrc = (USHORT *)pSrcAddr->m_data;
|
||||
pDst[0] = pSrc[0];
|
||||
pDst[1] = pSrc[1];
|
||||
pDst[2] = pSrc[2];
|
||||
|
||||
((struct ether_header *)pMblk->m_data)->ether_type =
|
||||
pDstAddr->mBlkHdr.reserved;
|
||||
}
|
||||
|
||||
return(pMblk);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endEtherPacketDataGet - return the beginning of the packet data
|
||||
*
|
||||
* This routine fills the given <pLinkHdrInfo> with the appropriate offsets.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
STATUS endEtherPacketDataGet
|
||||
(
|
||||
M_BLK_ID pMblk,
|
||||
LL_HDR_INFO * pLinkHdrInfo
|
||||
)
|
||||
{
|
||||
struct ether_header * pEnetHdr;
|
||||
struct ether_header enetHdr;
|
||||
|
||||
struct llc * pLLCHdr;
|
||||
struct llc llcHdr;
|
||||
|
||||
USHORT etherType;
|
||||
|
||||
pLinkHdrInfo->destAddrOffset = 0;
|
||||
pLinkHdrInfo->destSize = 6;
|
||||
pLinkHdrInfo->srcAddrOffset = 6;
|
||||
pLinkHdrInfo->srcSize = 6;
|
||||
|
||||
/* Try for RFC 894 first as it's the most common. */
|
||||
|
||||
/*
|
||||
* make sure entire ether_header is in first M_BLK
|
||||
* if not then copy the data to a temporary buffer
|
||||
*/
|
||||
|
||||
if (pMblk->mBlkHdr.mLen < SIZEOF_ETHERHEADER)
|
||||
{
|
||||
pEnetHdr = &enetHdr;
|
||||
if (netMblkOffsetToBufCopy (pMblk, 0, (char *) pEnetHdr,
|
||||
SIZEOF_ETHERHEADER, (FUNCPTR) bcopy)
|
||||
< SIZEOF_ETHERHEADER)
|
||||
{
|
||||
return(ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
pEnetHdr = (struct ether_header *)pMblk->mBlkHdr.mData;
|
||||
|
||||
etherType = ntohs(pEnetHdr->ether_type);
|
||||
|
||||
/* Deal with 802.3 addressing. */
|
||||
|
||||
/* Here is the algorithm. */
|
||||
/* If the etherType is less than or equal to the MTU then we know that */
|
||||
/* this is an 802.x address from RFC 1700. */
|
||||
if (etherType <= ETHERMTU)
|
||||
{
|
||||
|
||||
/*
|
||||
* make sure entire ether_header + llc_hdr is in first M_BLK
|
||||
* if not then copy the data to a temporary buffer
|
||||
*/
|
||||
|
||||
if (pMblk->mBlkHdr.mLen < SIZEOF_ETHERHEADER + LLC_SNAP_FRAMELEN)
|
||||
{
|
||||
pLLCHdr = &llcHdr;
|
||||
if (netMblkOffsetToBufCopy (pMblk, SIZEOF_ETHERHEADER,
|
||||
(char *) pLLCHdr, LLC_SNAP_FRAMELEN,
|
||||
(FUNCPTR) bcopy)
|
||||
< LLC_SNAP_FRAMELEN)
|
||||
{
|
||||
return(ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
pLLCHdr = (struct llc *)((char *)pEnetHdr + SIZEOF_ETHERHEADER);
|
||||
|
||||
/* Now it may be IP over 802.x so we check to see if the */
|
||||
/* destination SAP is IP, if so we snag the ethertype from the */
|
||||
/* proper place. */
|
||||
|
||||
/* Now if it's NOT IP over 802.x then we just used the DSAP as */
|
||||
/* the etherType. */
|
||||
|
||||
if (pLLCHdr->llc_dsap == LLC_SNAP_LSAP)
|
||||
{
|
||||
etherType = ntohs(pLLCHdr->llc_un.type_snap.ether_type);
|
||||
pLinkHdrInfo->dataOffset = SIZEOF_ETHERHEADER + 8;
|
||||
}
|
||||
else
|
||||
{ /* no SNAP header */
|
||||
pLinkHdrInfo->dataOffset = SIZEOF_ETHERHEADER + 3;
|
||||
etherType = pLLCHdr->llc_dsap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pLinkHdrInfo->dataOffset = SIZEOF_ETHERHEADER;
|
||||
}
|
||||
pLinkHdrInfo->pktType = etherType;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endEtherPacketAddrGet - locate the addresses in a packet
|
||||
*
|
||||
* This routine takes a 'M_BLK_ID', locates the address information, and
|
||||
* adjusts the M_BLK_ID structures referenced in <pSrc>, <pDst>, <pESrc>,
|
||||
* and <pEDst> so that their pData members point to the addressing
|
||||
* information in the packet. The addressing information is not copied.
|
||||
* All 'mBlk' structures share the same cluster.
|
||||
*
|
||||
* RETURNS: OK
|
||||
*
|
||||
* ERRNO
|
||||
*/
|
||||
|
||||
STATUS endEtherPacketAddrGet
|
||||
(
|
||||
M_BLK_ID pMblk, /* pointer to packet */
|
||||
M_BLK_ID pSrc, /* pointer to local source address */
|
||||
M_BLK_ID pDst, /* pointer to local destination address */
|
||||
M_BLK_ID pESrc, /* pointer to remote source address (if any) */
|
||||
M_BLK_ID pEDst /* pointer to remote destination address (if any) */
|
||||
)
|
||||
{
|
||||
|
||||
if (pSrc != NULL)
|
||||
{
|
||||
pSrc = netMblkDup (pMblk, pSrc);
|
||||
if (pSrc == NULL)
|
||||
return (ERROR);
|
||||
|
||||
pSrc->mBlkHdr.mData += 6;
|
||||
pSrc->mBlkHdr.mLen = 6;
|
||||
}
|
||||
if (pDst != NULL)
|
||||
{
|
||||
pDst = netMblkDup (pMblk, pDst);
|
||||
if (pDst == NULL)
|
||||
return (ERROR);
|
||||
|
||||
pDst->mBlkHdr.mLen = 6;
|
||||
}
|
||||
if (pESrc != NULL)
|
||||
{
|
||||
pESrc = netMblkDup (pMblk, pESrc);
|
||||
if (pESrc == NULL)
|
||||
return (ERROR);
|
||||
|
||||
pESrc->mBlkHdr.mData += 6;
|
||||
pESrc->mBlkHdr.mLen = 6;
|
||||
}
|
||||
if (pEDst != NULL)
|
||||
{
|
||||
pEDst = netMblkDup (pMblk, pEDst);
|
||||
if (pEDst == NULL)
|
||||
return (ERROR);
|
||||
pEDst->mBlkHdr.mLen = 6;
|
||||
}
|
||||
|
||||
return (OK);
|
||||
}
|
||||
@@ -0,0 +1,593 @@
|
||||
/* endLib.c - support library for END-based drivers */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008, 2013 Wind River Systems, Inc.
|
||||
*
|
||||
* The right to copy, distribute, modify or otherwise make use of this
|
||||
* software may be licensed only pursuant to the terms of an applicable Wind
|
||||
* River license agreement.
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
01f,04sep13,xms fix CHECKED_RETURN error. (WIND00414265)
|
||||
01e,24nov08,dlk Add string.h header.
|
||||
01d,03jun08,dlk Move (disabled) END MCACHE code here.
|
||||
01c,21may08,dlk Move end8023AddressForm(), endEtherAddressForm() to
|
||||
endEtherAddr.c for better scalability.
|
||||
01b,26mar08,dlk Move end8023AddressForm(), endEtherAddressForm(),
|
||||
endEtherPacketDataGet(), and endEtherPacketAddrGet()
|
||||
here from endCommon.c
|
||||
01a,14mar08,dlk Written. Most former contents moved to endCommon.c.
|
||||
*/
|
||||
|
||||
/*
|
||||
DESCRIPTION
|
||||
This library contains support routines for END-style network drivers.
|
||||
These routines are common to all END-style drivers. Specialized routines
|
||||
should only appear in the drivers themselves. Routines shared by all styles
|
||||
of drivers (END2, END, NPT) are found in endCommon.
|
||||
|
||||
To use this feature, include the following component:
|
||||
INCLUDE_END
|
||||
|
||||
INCLUDE FILES: endLib.h
|
||||
*/
|
||||
|
||||
/* includes */
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <endLib.h>
|
||||
#include <muxLib.h>
|
||||
#include <string.h>
|
||||
#include <private/muxLibP.h>
|
||||
#include <net/mbuf.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#define LLC_SNAP_FRAMELEN 8
|
||||
|
||||
int endPoolClSize = END_MCACHE_CLSIZE;
|
||||
int endPoolJumboClSize = END_JUMBO_CLSIZE;
|
||||
|
||||
LOCAL STATUS endPoolInternalCreate (int, NET_POOL_ID *, int);
|
||||
|
||||
#ifdef END_POOL_MCACHE
|
||||
LOCAL M_BLK_ID endCache[END_MCACHE_SIZE];
|
||||
LOCAL UINT32 endCacheCnt = 0;
|
||||
LOCAL UINT32 endCacheHead = 0;
|
||||
LOCAL UINT32 endCacheTail = 0;
|
||||
LOCAL spinlockIsr_t endCacheLock;
|
||||
LOCAL BOOL endCacheInit = FALSE;
|
||||
#endif
|
||||
|
||||
void endLibInit (void)
|
||||
{
|
||||
MUX_END_STYLE_INFO * style = &muxEndStyles[END_STYLE_END];
|
||||
style->rxRtn = muxReceive;
|
||||
}
|
||||
|
||||
void endRcvRtnCall
|
||||
(
|
||||
END_OBJ* pEnd,
|
||||
M_BLK_ID pData
|
||||
)
|
||||
{
|
||||
if (pEnd->receiveRtn)
|
||||
{
|
||||
pEnd->receiveRtn ((pEnd), pData);
|
||||
}
|
||||
else
|
||||
netMblkClChainFree (pData);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* muxReceive - handle a packet from a device driver
|
||||
*
|
||||
* An END calls this routine to transfer a packet to one or more bound
|
||||
* services.
|
||||
*
|
||||
* NOTE: The stack receive routine installed by a protocol must not alter
|
||||
* the packet if it returns FALSE. This restriction is not currently stated
|
||||
* in the manual.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*
|
||||
* ERRNO: S_muxLib_NO_DEVICE
|
||||
*
|
||||
* NOMANUAL
|
||||
*/
|
||||
|
||||
STATUS muxReceive
|
||||
(
|
||||
void * pCookie, /* device identifier from driver's load routine */
|
||||
M_BLK_ID pMblk /* buffer containing received frame */
|
||||
)
|
||||
{
|
||||
PROTO_ENTRY * pProto;
|
||||
END_OBJ * pEnd;
|
||||
long type;
|
||||
LL_HDR_INFO llHdrInfo;
|
||||
|
||||
pEnd = (END_OBJ *)pCookie;
|
||||
|
||||
#ifdef DEBUG_CHECKS
|
||||
if (pEnd == NULL || pMblk == NULL)
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
if (pEnd->pFuncTable->packetDataGet == NULL ||
|
||||
pEnd->pFuncTable->packetDataGet (pMblk, &llHdrInfo, pEnd) != OK)
|
||||
{
|
||||
goto err_data_get;
|
||||
}
|
||||
|
||||
type = llHdrInfo.pktType;
|
||||
|
||||
/*
|
||||
* Loop through the protocol list.
|
||||
* If a service's receive routine returns TRUE, it has consumed the
|
||||
* packet. The receive routine must return FALSE for other services
|
||||
* to see the packet.
|
||||
*
|
||||
* The order of services in the list (established during the bind)
|
||||
* determines their priority. SNARF services have the priority over
|
||||
* every other service type. PROMISC services have the lowest priority.
|
||||
* If multiple SNARF or PROMISC services exist, the order is first-come,
|
||||
* first-served, which could prevent some services from seeing matching
|
||||
* data if an earlier entry consumes it.
|
||||
*/
|
||||
|
||||
for (pProto = pEnd->pSnarf; pProto < pEnd->pStop; pProto++)
|
||||
{
|
||||
if (pProto->rr.endRcv == NULL)
|
||||
continue;
|
||||
|
||||
if (type == pProto->type ||
|
||||
pProto->type == MUX_PROTO_SNARF ||
|
||||
pProto->type == MUX_PROTO_PROMISC)
|
||||
{
|
||||
if (pProto->rr.endRcv (pProto->pBinding, type, pMblk,
|
||||
&llHdrInfo, pProto->recvRtnArg))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unknown service. Free the packet. */
|
||||
|
||||
if (pEnd->flags & END_MIB_2233)
|
||||
{
|
||||
/* RFC 2233 type of MIB variables supported */
|
||||
|
||||
MIB_CNT_UPDATE(pEnd->pMib2Tbl, M2_ctrId_ifInUnknownProtos, 1, NULL);
|
||||
}
|
||||
else /* RFC 1213 style MIB */
|
||||
{
|
||||
pEnd->mib2Tbl.ifInUnknownProtos++;
|
||||
}
|
||||
|
||||
/* if the flow comes here then free the mBlk */
|
||||
|
||||
netMblkClChainFree (pMblk);
|
||||
|
||||
out:
|
||||
return OK;
|
||||
|
||||
err_data_get:
|
||||
if (pEnd->flags & END_MIB_2233)
|
||||
{
|
||||
MIB_CNT_UPDATE(pEnd->pMib2Tbl, M2_ctrId_ifInErrors, 1, NULL);
|
||||
}
|
||||
else /* 1213-style MIB */
|
||||
{
|
||||
pEnd->mib2Tbl.ifInErrors++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CHECKS
|
||||
err:
|
||||
#endif
|
||||
if (pMblk)
|
||||
netMblkClChainFree (pMblk);
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPoolCreate - create a buffer pool for an END driver
|
||||
*
|
||||
* This function is a helper routine for END drivers to simplify the creation
|
||||
* of a driver-private buffer pool. The caller need only specify the number of
|
||||
* tuples in the pool. The resulting pool will have an equal number of
|
||||
* mBlks, cluster blocks and clusters (this is the typical requirement for
|
||||
* driver usage). The clusters in the pool will always be the same size,
|
||||
* governed by the endPoolClSize global variable. The default size is
|
||||
* 1536 bytes.
|
||||
*
|
||||
* Note that clusters will be allocated from cached storage. This may
|
||||
* be unsuitable for some drivers, however this is not an issue for
|
||||
* drivers that are VxBus-compliant: cache coherence issues should be
|
||||
* handled internally by the vxbDmaBuf API.
|
||||
*
|
||||
* RETURNS: OK if pool is successfully created, otherwise ERROR
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
STATUS endPoolCreate
|
||||
(
|
||||
int tupleCnt,
|
||||
NET_POOL_ID * ppNetPool
|
||||
)
|
||||
{
|
||||
return (endPoolInternalCreate (tupleCnt, ppNetPool, endPoolClSize));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPoolJumboCreate - create a jumbo buffer pool for an END driver
|
||||
*
|
||||
* This function is a helper routine for END drivers to simplify the creation
|
||||
* of a driver-private buffer pool. It's similar to the endPoolCreate()
|
||||
* function, except that it creates a pool of 9K jumbo buffers for drivers
|
||||
* that support jumbo frames.
|
||||
*
|
||||
* RETURNS: OK if pool is successfully created, otherwise ERROR
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
STATUS endPoolJumboCreate
|
||||
(
|
||||
int tupleCnt,
|
||||
NET_POOL_ID * ppNetPool
|
||||
)
|
||||
{
|
||||
return (endPoolInternalCreate (tupleCnt, ppNetPool, endPoolJumboClSize));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPoolInternalCreate - internal pool creation function
|
||||
*
|
||||
* This function contains common code used by the endPoolCreate() and
|
||||
* endPoolJumboCreate() functions.
|
||||
*
|
||||
* RETURNS: OK if pool is successfully created, otherwise ERROR
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*
|
||||
* NOMANUAL
|
||||
*/
|
||||
|
||||
LOCAL STATUS endPoolInternalCreate
|
||||
(
|
||||
int tupleCnt,
|
||||
NET_POOL_ID * ppNetPool,
|
||||
int size
|
||||
)
|
||||
{
|
||||
NETBUF_CFG netBufCfg;
|
||||
NETBUF_CL_DESC clDescTbl;
|
||||
NET_POOL_ID pPool;
|
||||
|
||||
if (ppNetPool == NULL || tupleCnt == 0)
|
||||
return (ERROR);
|
||||
|
||||
bzero ((char *)&netBufCfg, sizeof(netBufCfg));
|
||||
bzero ((char *)&clDescTbl, sizeof(clDescTbl));
|
||||
|
||||
netBufCfg.pName = NULL;
|
||||
netBufCfg.attributes = ATTR_AC_SH_ISR;
|
||||
netBufCfg.ctrlNumber = tupleCnt;
|
||||
netBufCfg.ctrlPartId = NULL;
|
||||
netBufCfg.bMemExtraSize = 0;
|
||||
netBufCfg.pClDescTbl = &clDescTbl;
|
||||
netBufCfg.pClDescTbl->clNum = tupleCnt;
|
||||
netBufCfg.pClDescTbl->clSize = size;
|
||||
netBufCfg.clDescTblNumEnt = 1;
|
||||
|
||||
pPool = netPoolCreate (&netBufCfg, _pLinkPoolFuncTbl);
|
||||
|
||||
if (pPool == NULL)
|
||||
return (ERROR);
|
||||
|
||||
*ppNetPool = pPool;
|
||||
|
||||
#ifdef END_POOL_MCACHE
|
||||
if (endCacheInit == FALSE)
|
||||
{
|
||||
endCacheInit = TRUE;
|
||||
SPIN_LOCK_ISR_INIT(&endCacheLock, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPoolDestroy - destroy a pool created with endPoolCreate()
|
||||
*
|
||||
* This function is used to release a buffer pool created with the
|
||||
* endPoolCreate() function. All memory allocated for use by the pool
|
||||
* will be returned.
|
||||
*
|
||||
* RETURNS: OK if pool is successfully destroyed, otherwise ERROR
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
STATUS endPoolDestroy
|
||||
(
|
||||
NET_POOL_ID pNetPool
|
||||
)
|
||||
{
|
||||
|
||||
/* don't need return from function call */
|
||||
|
||||
(void) netPoolRelease (pNetPool, NET_REL_IN_CONTEXT);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
#ifdef END_POOL_MCACHE
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPoolTupleGet - allocate an mBlk tuple for an END driver
|
||||
*
|
||||
* This function allocate an mBlk tuple from a pool created with the
|
||||
* endPoolCreate() routine. It works in conjunction with the mBlk
|
||||
* recycle cache to optimize performance when allocating buffers in
|
||||
* the transmit and receive paths in END drivers. If an mBlk tuple
|
||||
* is available in the cache, the buffer will be allocated from it
|
||||
* directly. Otherwise, a tuple will be allocated from the pool.
|
||||
*
|
||||
* Buffers allocated with endPoolTupleAlloc() should always be
|
||||
* released with endPoolTupleFree().
|
||||
*
|
||||
* RETURNS: a pointer to an mBlk, otherwise NULL if none are available
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
M_BLK_ID endPoolTupleGet
|
||||
(
|
||||
NET_POOL_ID pNetPool
|
||||
)
|
||||
{
|
||||
M_BLK_ID pMblk;
|
||||
|
||||
/* Try to allocate from the mBlk recycle cache first. */
|
||||
|
||||
SPIN_LOCK_ISR_TAKE(&endCacheLock);
|
||||
pMblk = endCache[endCacheTail];
|
||||
if (endCacheCnt == 0 || pMblk->m_extSize != pNetPool->clTbl[0]->clSize)
|
||||
{
|
||||
SPIN_LOCK_ISR_GIVE(&endCacheLock);
|
||||
goto alloc;
|
||||
}
|
||||
|
||||
pMblk = endCache[endCacheTail];
|
||||
END_MCACHE_INC(endCacheTail);
|
||||
endCacheCnt--;
|
||||
|
||||
SPIN_LOCK_ISR_GIVE(&endCacheLock);
|
||||
return (pMblk);
|
||||
|
||||
alloc:
|
||||
|
||||
/*
|
||||
* Cache is empty, allocate tuple from the pool.
|
||||
* Since it's a linkBufPool, we use mBlkGet() for speed.
|
||||
*/
|
||||
|
||||
pMblk = mBlkGet (pNetPool, M_DONTWAIT, MT_DATA);
|
||||
|
||||
if (pMblk != NULL)
|
||||
{
|
||||
/* Tag this mBlk so we know to cache it later. Also set
|
||||
* the lengths, needed by vxbDmaBufMapMblkLoad.
|
||||
*/
|
||||
|
||||
pMblk->m_len =
|
||||
pMblk->m_pkthdr.len = pMblk->m_extSize - pNetPool->clOffset;
|
||||
pMblk->m_extArg3 = END_MCACHE_TAG;
|
||||
}
|
||||
|
||||
return (pMblk);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endPoolTupleFree - free an mBlk tuple for an END driver
|
||||
*
|
||||
* This function releases an mBlk tuple from a pool created with the
|
||||
* endPoolCreate() routine. It works in conjunction with the mBlk
|
||||
* recycle cache to optimize performance when allocating buffers in
|
||||
* the transmit and receive paths in END drivers. If the buffer was
|
||||
* allocated using endPoolTupleAlloc(), it will be put back into
|
||||
* the mBlk recycle cache, assuming there's room for it. If not,
|
||||
* it will be released back to its original pool.
|
||||
*
|
||||
* For buffers not allocated using endPoolTupleFree(), this routine
|
||||
* is equivalent to netMblkClChainFree().
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
void endPoolTupleFree
|
||||
(
|
||||
M_BLK_ID pMblk
|
||||
)
|
||||
{
|
||||
int clOffset;
|
||||
|
||||
if (pMblk->m_next != NULL ||
|
||||
pMblk->m_extRefCnt != 1 ||
|
||||
pMblk->m_extArg3 != END_MCACHE_TAG ||
|
||||
pMblk->m_ext->pNetPool->mBlkFree == 0)
|
||||
goto release;
|
||||
|
||||
clOffset = pMblk->m_ext->pNetPool->clOffset;
|
||||
|
||||
SPIN_LOCK_ISR_TAKE(&endCacheLock);
|
||||
|
||||
if (endCacheCnt == END_MCACHE_SIZE)
|
||||
{
|
||||
SPIN_LOCK_ISR_GIVE(&endCacheLock);
|
||||
goto release;
|
||||
}
|
||||
|
||||
pMblk->pClBlk->clFreeArg3 = 0;
|
||||
pMblk->m_data = pMblk->m_extBuf + clOffset;
|
||||
pMblk->m_len = pMblk->m_pkthdr.len = pMblk->m_extSize - clOffset;
|
||||
pMblk->m_flags = M_EXT;
|
||||
pMblk->m_pkthdr.csum_flags = 0;
|
||||
|
||||
endCache[endCacheHead] = pMblk;
|
||||
END_MCACHE_INC(endCacheHead);
|
||||
endCacheCnt++;
|
||||
|
||||
SPIN_LOCK_ISR_GIVE(&endCacheLock);
|
||||
|
||||
return;
|
||||
|
||||
release:
|
||||
netMblkClChainFree (pMblk);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endMcacheGet - allocate an mBlk tuple from the mBlk recycle cache
|
||||
*
|
||||
* This function obtains an mBlk tuple stored in a fast mBlk recycle cache.
|
||||
*
|
||||
* This cache is used to provide a performance boost for drivers used in
|
||||
* devices designed for traffic forwarding or bridging. In this devices,
|
||||
* buffers from the RX side of an inbound interface are often directly
|
||||
* retransmitted via the TX side of an outbound interface, after which
|
||||
* they are released back to the RX interface's mBlk pool. This may consume
|
||||
* a lot of overhead depending on the pool implementation.
|
||||
*
|
||||
* Using the mBlk recycle cache may reduce this overhead. The cache is
|
||||
* implemented as a simple 128-entry pointer array. When a tuple is to
|
||||
* be released by the TX completion handler in a network driver, it can
|
||||
* be put in the recycle cache instead of released with netMblkClChainFree().
|
||||
* Whenever another interface needs a tuple to replenish its RX resources,
|
||||
* it can allocate it from the pool instead of doing a netTupleGet().
|
||||
* The cache only holds 128 tuple pointers, the cache get and put operations
|
||||
* use a minimum of processing and are usually faster than the netTupleGet()
|
||||
* and netMblkClChainFree() paths, which shaves some cycles off the time
|
||||
* needed to process a given packet.
|
||||
*
|
||||
* RETURNS: a pointer to an mBlk tuple, or NULL if the cache is empty
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
M_BLK_ID endMcacheGet
|
||||
(
|
||||
void
|
||||
)
|
||||
{
|
||||
M_BLK_ID pMblk;
|
||||
|
||||
SPIN_LOCK_ISR_TAKE(&endCacheLock);
|
||||
if (endCacheCnt == 0)
|
||||
{
|
||||
pMblk = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pMblk = endCache[endCacheTail];
|
||||
END_MCACHE_INC(endCacheTail);
|
||||
endCacheCnt--;
|
||||
|
||||
out:
|
||||
SPIN_LOCK_ISR_GIVE(&endCacheLock);
|
||||
return (pMblk);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endMcachePut - store an mBlk tuple in the mBlk recycle cache
|
||||
*
|
||||
* This function places a pointer to an mBlk tuple in the mBlk recycle
|
||||
* cache, as long as there is room to store it. The cache only holds 128
|
||||
* pointers, so storing the pointer will fail if the cache is full.
|
||||
*
|
||||
* RETURNS: OK of the tuple was successfully cached, otherwise ERROR
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
STATUS endMcachePut
|
||||
(
|
||||
M_BLK_ID pMblk
|
||||
)
|
||||
{
|
||||
STATUS status;
|
||||
|
||||
SPIN_LOCK_ISR_TAKE(&endCacheLock);
|
||||
if (endCacheCnt == END_MCACHE_SIZE)
|
||||
{
|
||||
status = ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pMblk->m_data = pMblk->m_extBuf;
|
||||
|
||||
endCache[endCacheHead] = pMblk;
|
||||
END_MCACHE_INC(endCacheHead);
|
||||
endCacheCnt++;
|
||||
status = OK;
|
||||
|
||||
out:
|
||||
SPIN_LOCK_ISR_GIVE(&endCacheLock);
|
||||
return (status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* endMcacheFlush - flush all tuples from the mBlk recycle cache
|
||||
*
|
||||
* This function removes all mBlk tuple pointers from the mBlk recycle
|
||||
* cache and frees them with netMblkClChainFree(). This function must be
|
||||
* called whenever any interface that uses the recycle cache is stopped
|
||||
* so that cached buffers can be properly reclaimed.
|
||||
*
|
||||
* RETURNS: N/A
|
||||
*
|
||||
* ERRNO: N/A
|
||||
*/
|
||||
|
||||
void endMcacheFlush
|
||||
(
|
||||
void
|
||||
)
|
||||
{
|
||||
M_BLK_ID pMblk;
|
||||
|
||||
SPIN_LOCK_ISR_TAKE(&endCacheLock);
|
||||
|
||||
while (endCacheCnt)
|
||||
{
|
||||
pMblk = endCache[endCacheTail];
|
||||
END_MCACHE_INC(endCacheTail);
|
||||
endCacheCnt--;
|
||||
SPIN_LOCK_ISR_GIVE(&endCacheLock);
|
||||
netMblkClChainFree (pMblk);
|
||||
SPIN_LOCK_ISR_TAKE(&endCacheLock);
|
||||
}
|
||||
|
||||
SPIN_LOCK_ISR_GIVE(&endCacheLock);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* END_POOL_MCACHE */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,774 @@
|
||||
/* loopEnd.c - software loopback END */
|
||||
|
||||
/* Copyright 1984-2006 Wind River Systems, Inc. */
|
||||
#include "copyright_wrs.h"
|
||||
|
||||
/* $NetBSD: loopEnd.c,v 1.13 1994/10/30 21:48:50 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)loopEnd.c 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
01m,05sep06,kch Removed unnecessary coreip header includes.
|
||||
01l,31aug04,mdo Documentation fixes for apigen
|
||||
01k,14jan99,sut prepended protocol information
|
||||
01j,14jan99,sut moved to tor2_0_0, renamed to loopEnd.c
|
||||
01i,14jan99,sut added routines loAddressForm, loPacketDataGet, loPacketAddrGet
|
||||
01h,13jan99,sut revoved loPollStart and loPollEnd
|
||||
01g,13jan99,sut put back again multicast support
|
||||
01f,13jan99,sut added more documentation
|
||||
01e,12jan99,sut removed ether address storage
|
||||
01d,12jan99,sut added debug routines
|
||||
01c,11jan99,sut removed multicast support
|
||||
01b,11jan99,sut converted into END driver
|
||||
01a,07jan99,sut started with netif/if_loop.c
|
||||
*/
|
||||
|
||||
/*
|
||||
DESCRIPTION
|
||||
This module implements the software loopback Enhanced Network Driver (END).
|
||||
The only external routine is loEndLoad(), which can only be called from mux
|
||||
interface.
|
||||
|
||||
The driver does not support polled mode operations. Even though the polled
|
||||
mode interfaces are exported to mux layer, just returns ERROR for polled mode
|
||||
operations.
|
||||
|
||||
|
||||
BOARD LAYOUT
|
||||
This device is "software only." A jumpering diagram is not applicable.
|
||||
|
||||
|
||||
EXTERNAL INTERFACE
|
||||
The only external interface is the loEndLoad() routine, which expects
|
||||
the <initString> parameter as input. At present this routine expects only
|
||||
<unit> from this string. This parameter passes in a colon-delimited string of
|
||||
the format:
|
||||
|
||||
<unit>
|
||||
|
||||
The loEndLoad() function uses strtok() to parse the string
|
||||
|
||||
TARGET-SPECIFIC PARAMETERS
|
||||
|
||||
\is
|
||||
\i <unit>
|
||||
A convenient holdover from the former model. This parameter is used only
|
||||
in the string name for the driver.
|
||||
\ie
|
||||
|
||||
SEE ALSO: ifLib
|
||||
*/
|
||||
#include "vxWorks.h"
|
||||
#include "stdlib.h"
|
||||
#include "end.h"
|
||||
#include "endLib.h"
|
||||
#include "lstLib.h"
|
||||
#include "wdLib.h"
|
||||
#include "iv.h"
|
||||
#include "semLib.h"
|
||||
#include "etherLib.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 "sys/ioctl.h"
|
||||
#include "sys/times.h"
|
||||
|
||||
|
||||
|
||||
/* maximum packet size */
|
||||
#define LO_SPEED 10000000
|
||||
|
||||
#define LO_MIN_FBUF 0 /* Minimum size of the first buffer in a */
|
||||
/* chain. */
|
||||
|
||||
#define LO_ADDR_LEN 0 /* address length */
|
||||
#define LO_HDR_LEN 0 /* header length */
|
||||
|
||||
|
||||
/* Naming items */
|
||||
#define LO_DEV_NAME "lo"
|
||||
#define LO_DEV_NAME_LEN 3
|
||||
|
||||
|
||||
/* device states */
|
||||
|
||||
#define LO_ST_STOPPED 0x80
|
||||
|
||||
#define LO_IS_DEV_STOPPED(pDrvCtrl)\
|
||||
((pDrvCtrl->state & LO_ST_STOPPED) == LO_ST_STOPPED)
|
||||
|
||||
#define LO_DEV_STOP(pDrvCtrl) (pDrvCtrl->state |= LO_ST_STOPPED)
|
||||
#define LO_DEV_START(pDrvCtrl) (pDrvCtrl->state &= (!LO_ST_STOPPED))
|
||||
|
||||
#define LO_PROTOCOL_LEN sizeof(USHORT)
|
||||
|
||||
#undef DRV_DEBUG
|
||||
|
||||
#ifdef DRV_DEBUG
|
||||
#define DRV_DEBUG_OFF 0x0000
|
||||
#define DRV_DEBUG_POLL 0x0001
|
||||
#define DRV_DEBUG_LOAD 0x0002
|
||||
#define DRV_DEBUG_IOCTL 0x0004
|
||||
#define DRV_DEBUG_LOG_NVRAM 0x0008
|
||||
|
||||
#ifdef LOCAL
|
||||
#undef LOCAL
|
||||
#endif /* LOCAL */
|
||||
|
||||
#define LOCAL ;
|
||||
|
||||
int loDebug = DRV_DEBUG_OFF; /* Turn it off initially. */
|
||||
#include "nvLogLib.h"
|
||||
|
||||
|
||||
#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
|
||||
if ((loDebug & FLG)&&(FLG & DRV_DEBUG_POLL)) \
|
||||
nvLogMsg(X0, X1, X2, X3, X4, X5, X6); \
|
||||
else if (loDebug & FLG) \
|
||||
logMsg(X0, X1, X2, X3, X4, X5, X6);
|
||||
|
||||
#define DRV_PRINT(FLG,X) \
|
||||
if (loDebug & 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*/
|
||||
|
||||
|
||||
/* The definition of the driver control structure */
|
||||
#define U16 unsigned short int
|
||||
|
||||
typedef struct lo_device
|
||||
{
|
||||
END_OBJ end; /* The class we inherit from. */
|
||||
int unit; /* unit number */
|
||||
U16 state;
|
||||
u_short errorStat; /* error status */
|
||||
} LOEND_DEVICE;
|
||||
|
||||
/* forward declarations */
|
||||
|
||||
/* This is the only externally visible interface. */
|
||||
|
||||
END_OBJ* loEndLoad (char* initString);
|
||||
|
||||
/* END interfaces */
|
||||
|
||||
LOCAL STATUS loUnload (LOEND_DEVICE* pDrvCtrl);
|
||||
LOCAL STATUS loIoctl (LOEND_DEVICE* pDrvCtrl, int cmd, caddr_t data);
|
||||
LOCAL STATUS loSend (LOEND_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
|
||||
LOCAL STATUS loStart (LOEND_DEVICE* pDrvCtrl);
|
||||
LOCAL STATUS loStop (LOEND_DEVICE* pDrvCtrl);
|
||||
LOCAL STATUS loMCastAddrAdd (LOEND_DEVICE* pDrvCtrl, char* pAddress);
|
||||
LOCAL STATUS loMCastAddrDel (LOEND_DEVICE* pDrvCtrl, char* pAddress);
|
||||
LOCAL STATUS loMCastAddrGet (LOEND_DEVICE* pDrvCtrl,
|
||||
MULTI_TABLE* pTable);
|
||||
LOCAL STATUS loPollSend (LOEND_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
|
||||
LOCAL STATUS loPollReceive (LOEND_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
|
||||
|
||||
M_BLK_ID loAddressForm (M_BLK_ID pMblk, M_BLK_ID pSrcAddr, M_BLK_ID pDstAddr);
|
||||
|
||||
STATUS loPacketDataGet (M_BLK_ID pMblk, LL_HDR_INFO* pLinkHdrInfo);
|
||||
STATUS loPacketAddrGet (M_BLK_ID pMblk, M_BLK_ID pSrc, M_BLK_ID pDst,
|
||||
M_BLK_ID pESrc, M_BLK_ID pEDst);
|
||||
|
||||
LOCAL STATUS loInitStringParse ();
|
||||
|
||||
|
||||
/*
|
||||
* Declare our function table. This is static across all driver
|
||||
* instances.
|
||||
*/
|
||||
|
||||
LOCAL NET_FUNCS loFuncTable =
|
||||
{
|
||||
(FUNCPTR)loStart, /* Function to start the device. */
|
||||
(FUNCPTR)loStop, /* Function to stop the device. */
|
||||
(FUNCPTR)loUnload, /* Unloading function for the driver. */
|
||||
(FUNCPTR)loIoctl, /* Ioctl function for the driver. */
|
||||
(FUNCPTR)loSend, /* Send function for the driver. */
|
||||
(FUNCPTR)loMCastAddrAdd, /* Multicast address add */
|
||||
(FUNCPTR)loMCastAddrDel, /* Multicast address delete */
|
||||
(FUNCPTR)loMCastAddrGet, /* Multicast table retrieve */
|
||||
(FUNCPTR)loPollSend, /* Polling send function for the driver. */
|
||||
(FUNCPTR)loPollReceive, /* Polling receive function for the driver. */
|
||||
loAddressForm, /* Put address info into a packet. */
|
||||
loPacketDataGet, /* Get a pointer to packet data. */
|
||||
loPacketAddrGet /* Get packet addresses. */
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* loEndLoad - 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 <initString>, which
|
||||
* expects a string of the following format:
|
||||
*
|
||||
* <unit>
|
||||
*
|
||||
* This routine can be called in two modes. If it is called with an empty but
|
||||
* allocated string, it places the name of this device (that is, "lo") into
|
||||
* the <initString> and returns 0.
|
||||
*
|
||||
* If the string is allocated and not empty, the routine attempts to load
|
||||
* the driver using the values specified in the string.
|
||||
*
|
||||
* RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
|
||||
* device if the <initString> was NULL.
|
||||
*/
|
||||
END_OBJ* loEndLoad
|
||||
(
|
||||
char* initString /* string to be parse by the driver */
|
||||
)
|
||||
{
|
||||
LOEND_DEVICE *pDrvCtrl;
|
||||
|
||||
DRV_LOG (DRV_DEBUG_LOAD, "Loading lo...\n", 1, 2, 3, 4, 5, 6);
|
||||
|
||||
if (initString == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (initString[0] == NULL)
|
||||
{
|
||||
bcopy((char *)LO_DEV_NAME, initString, LO_DEV_NAME_LEN);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* allocate the device structure */
|
||||
|
||||
pDrvCtrl = (LOEND_DEVICE *)calloc (sizeof (LOEND_DEVICE), 1);
|
||||
|
||||
if (pDrvCtrl == NULL)
|
||||
goto errorExit;
|
||||
|
||||
/* parse the init string, filling in the device structure */
|
||||
|
||||
if (loInitStringParse (pDrvCtrl, initString) == ERROR)
|
||||
goto errorExit;
|
||||
|
||||
|
||||
/* initialize the END and MIB2 parts of the structure */
|
||||
|
||||
if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, LO_DEV_NAME,
|
||||
pDrvCtrl->unit, &loFuncTable,
|
||||
"Loopback Enhanced Network Driver") == ERROR
|
||||
|| END_MIB_INIT (&pDrvCtrl->end, M2_ifType_softwareLoopback, NULL,
|
||||
LO_ADDR_LEN, 0, LO_SPEED)
|
||||
== ERROR)
|
||||
goto errorExit;
|
||||
|
||||
|
||||
/* set the flags to indicate readiness */
|
||||
|
||||
END_OBJ_READY (&pDrvCtrl->end,
|
||||
IFF_UP | IFF_RUNNING | IFF_LOOPBACK | IFF_MULTICAST);
|
||||
|
||||
DRV_LOG (DRV_DEBUG_LOAD, "Done loading lo...\n", 1, 2, 3, 4, 5, 6);
|
||||
|
||||
return (&pDrvCtrl->end);
|
||||
|
||||
errorExit:
|
||||
if (pDrvCtrl != NULL)
|
||||
free ((char *)pDrvCtrl);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* loUnload - unload a driver from the system
|
||||
*
|
||||
* This function first brings down the device, and then frees any
|
||||
* stuff that was allocated by the driver in the load function.
|
||||
*/
|
||||
|
||||
LOCAL STATUS loUnload
|
||||
(
|
||||
LOEND_DEVICE* pDrvCtrl
|
||||
)
|
||||
{
|
||||
END_OBJECT_UNLOAD (&pDrvCtrl->end);
|
||||
|
||||
return (OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* loStart - start the device
|
||||
*
|
||||
* This function calls BSP functions to connect interrupts and start the
|
||||
* device running in interrupt mode.
|
||||
*
|
||||
* RETURNS: OK or ERROR
|
||||
*
|
||||
*/
|
||||
|
||||
LOCAL STATUS loStart
|
||||
(
|
||||
LOEND_DEVICE *pDrvCtrl
|
||||
)
|
||||
{
|
||||
LO_DEV_START(pDrvCtrl);
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* loStop - stop the device
|
||||
*
|
||||
* This function calls BSP functions to disconnect interrupts and stop
|
||||
* the device from operating in interrupt mode.
|
||||
*
|
||||
* RETURNS: OK or ERROR
|
||||
*/
|
||||
|
||||
LOCAL STATUS loStop
|
||||
(
|
||||
LOEND_DEVICE *pDrvCtrl
|
||||
)
|
||||
{
|
||||
LO_DEV_STOP(pDrvCtrl);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* loIoctl - the driver I/O control routine
|
||||
*
|
||||
* Process an ioctl request.
|
||||
*/
|
||||
|
||||
LOCAL STATUS loIoctl
|
||||
(
|
||||
LOEND_DEVICE *pDrvCtrl,
|
||||
int cmd,
|
||||
caddr_t data
|
||||
)
|
||||
{
|
||||
STATUS error = OK;
|
||||
long value;
|
||||
|
||||
if (LO_IS_DEV_STOPPED(pDrvCtrl))
|
||||
return ERROR;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case EIOCSADDR:
|
||||
return (ERROR);
|
||||
break;
|
||||
|
||||
case EIOCGADDR:
|
||||
return (ERROR);
|
||||
break;
|
||||
|
||||
case EIOCSFLAGS:
|
||||
value = (long)data;
|
||||
if (value < 0)
|
||||
{
|
||||
value = -value;
|
||||
value--; /* HELP: WHY ??? */
|
||||
END_FLAGS_CLR (&pDrvCtrl->end, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
END_FLAGS_SET (&pDrvCtrl->end, value);
|
||||
}
|
||||
break;
|
||||
|
||||
case EIOCGFLAGS:
|
||||
*(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
|
||||
break;
|
||||
|
||||
case EIOCPOLLSTART: /* fall through */
|
||||
case EIOCPOLLSTOP:
|
||||
error = ERROR;
|
||||
break;
|
||||
|
||||
case EIOCGMIB2:
|
||||
if (data == NULL)
|
||||
return (EINVAL);
|
||||
bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
|
||||
sizeof(pDrvCtrl->end.mib2Tbl));
|
||||
break;
|
||||
|
||||
case EIOCGFBUF:
|
||||
if (data == NULL)
|
||||
return (EINVAL);
|
||||
*(int *)data = LO_MIN_FBUF;
|
||||
break;
|
||||
|
||||
case EIOCGMWIDTH:
|
||||
if (data == NULL)
|
||||
return (EINVAL);
|
||||
*(int *)data = 0;
|
||||
break;
|
||||
|
||||
|
||||
case EIOCGHDRLEN:
|
||||
if (data == NULL)
|
||||
return (EINVAL);
|
||||
*(int *)data = LO_HDR_LEN;
|
||||
break;
|
||||
|
||||
case EIOCMULTIADD:
|
||||
case EIOCMULTIDEL:
|
||||
case EIOCMULTIGET:
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* loSend - the 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. The last arguments are a free
|
||||
* routine to be called when the device is done with the buffer and a pointer
|
||||
* to the argument to pass to the free routine.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*/
|
||||
|
||||
LOCAL STATUS loSend
|
||||
(
|
||||
LOEND_DEVICE *pDrvCtrl, /* device ptr */
|
||||
M_BLK_ID pMblk /* data to send */
|
||||
)
|
||||
{
|
||||
|
||||
STATUS retValue = OK;
|
||||
|
||||
if (LO_IS_DEV_STOPPED(pDrvCtrl))
|
||||
retValue = ERROR;
|
||||
else
|
||||
{
|
||||
/* Bump the statistic counter. */
|
||||
|
||||
END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
|
||||
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
|
||||
|
||||
/* Call the upper layer's receive routine. */
|
||||
|
||||
END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
|
||||
}
|
||||
return (retValue);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* loInitStringParse - parse the initialization string
|
||||
*
|
||||
* Parse the input string. Fill in values in the driver control structure.
|
||||
* The initialization string format is:
|
||||
* <unit>
|
||||
*
|
||||
* \is
|
||||
* \i <unit>
|
||||
* Device unit number, a small integer.
|
||||
* \ie
|
||||
*
|
||||
* RETURNS: OK, or ERROR if any arguments are invalid.
|
||||
*/
|
||||
STATUS loInitStringParse
|
||||
(
|
||||
LOEND_DEVICE* pDrvCtrl,
|
||||
char* initString
|
||||
)
|
||||
{
|
||||
char * tok;
|
||||
char * pHolder = NULL;
|
||||
|
||||
|
||||
/* Parse the initString */
|
||||
|
||||
/* Unit number. */
|
||||
|
||||
tok = strtok_r (initString, ":", &pHolder);
|
||||
if (tok == NULL)
|
||||
return ERROR;
|
||||
|
||||
pDrvCtrl->unit = atoi (tok);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* loMCastAddrAdd - 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 if fails to add
|
||||
*/
|
||||
|
||||
LOCAL STATUS loMCastAddrAdd
|
||||
(
|
||||
LOEND_DEVICE *pDrvCtrl,
|
||||
char* pAddress
|
||||
)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = etherMultiAdd (&pDrvCtrl->end.multiList, pAddress);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* loMCastAddrDel - 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 if fails to delete
|
||||
*/
|
||||
|
||||
LOCAL STATUS loMCastAddrDel
|
||||
(
|
||||
LOEND_DEVICE* pDrvCtrl,
|
||||
char* pAddress
|
||||
)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = etherMultiDel (&pDrvCtrl->end.multiList, pAddress);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* loMCastAddrGet - 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 if fails to get
|
||||
*
|
||||
*/
|
||||
|
||||
LOCAL STATUS loMCastAddrGet
|
||||
(
|
||||
LOEND_DEVICE* pDrvCtrl,
|
||||
MULTI_TABLE* pTable
|
||||
)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = etherMultiGet (&pDrvCtrl->end.multiList, pTable);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* loPollSend - routine to send a packet in polled mode.
|
||||
*
|
||||
* This routine is called by a user to try and send a packet on the
|
||||
* device.
|
||||
*
|
||||
* RETURNS: ERROR always
|
||||
*/
|
||||
|
||||
LOCAL STATUS loPollSend
|
||||
(
|
||||
LOEND_DEVICE* pDrvCtrl,
|
||||
M_BLK_ID pMblk
|
||||
)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* loPollReceive - routine to receive a packet in polled mode.
|
||||
*
|
||||
* This routine is called by a user to try and get a packet from the
|
||||
* device.
|
||||
*
|
||||
* RETURNS: ERROR always
|
||||
*/
|
||||
|
||||
LOCAL STATUS loPollReceive
|
||||
(
|
||||
LOEND_DEVICE *pDrvCtrl,
|
||||
M_BLK_ID pMblk
|
||||
)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* loAddressForm - form an Ethernet address into a packet
|
||||
*
|
||||
* This routine accepts the source and destination addressing information
|
||||
* through <pSrcAddr> and <pDstAddr> and returns an 'M_BLK_ID' that points
|
||||
* to the assembled link-level header. To do this, this routine prepends
|
||||
* the link-level header into the cluster associated with <pMblk> if there
|
||||
* is enough space available in the cluster. It then returns a pointer to
|
||||
* the pointer referenced in <pMblk>. However, if there is not enough space
|
||||
* in the cluster associated with <pMblk>, this routine reserves a
|
||||
* new 'mBlk'-'clBlk'-cluster construct for the header information.
|
||||
* It then prepends the new 'mBlk' to the 'mBlk' passed in <pMblk>. As the
|
||||
* function value, this routine then returns a pointer to the new 'mBlk',
|
||||
* which the head of a chain of 'mBlk' structures. The second element of this
|
||||
* chain is the 'mBlk' referenced in <pMblk>.
|
||||
*
|
||||
* RETURNS: M_BLK_ID or NULL.
|
||||
*/
|
||||
|
||||
M_BLK_ID loAddressForm
|
||||
(
|
||||
M_BLK_ID pMblk, /* pointer to packet mBlk */
|
||||
M_BLK_ID pSrcAddr, /* pointer to source address */
|
||||
M_BLK_ID pDstAddr /* pointer to destination address */
|
||||
)
|
||||
{
|
||||
|
||||
M_PREPEND(pMblk, LO_PROTOCOL_LEN, M_DONTWAIT);
|
||||
|
||||
if (pMblk != NULL)
|
||||
bcopy ((char *)&pDstAddr->mBlkHdr.reserved,
|
||||
pMblk->m_data, LO_PROTOCOL_LEN);
|
||||
|
||||
return (pMblk);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* loPacketDataGet - return the beginning of the packet data
|
||||
*
|
||||
* This routine fills the given <pLinkHdrInfo> with the appropriate offsets.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*/
|
||||
|
||||
STATUS loPacketDataGet
|
||||
(
|
||||
M_BLK_ID pMblk,
|
||||
LL_HDR_INFO * pLinkHdrInfo
|
||||
)
|
||||
{
|
||||
pLinkHdrInfo->destAddrOffset = 0;
|
||||
pLinkHdrInfo->destSize = 0;
|
||||
pLinkHdrInfo->srcAddrOffset = 0;
|
||||
pLinkHdrInfo->srcSize = 0;
|
||||
pLinkHdrInfo->dataOffset = LO_PROTOCOL_LEN;
|
||||
bcopy (pMblk->m_data, (char *)&pLinkHdrInfo->pktType, LO_PROTOCOL_LEN);
|
||||
|
||||
return (OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* loPacketAddrGet - locate the addresses in a packet
|
||||
*
|
||||
* This routine takes a 'M_BLK_ID', locates the address information, and
|
||||
* adjusts the M_BLK_ID structures referenced in <pSrc>, <pDst>, <pESrc>,
|
||||
* and <pEDst> so that their pData members point to the addressing
|
||||
* information in the packet. The addressing information is not copied.
|
||||
* All 'mBlk' structures share the same cluster.
|
||||
*
|
||||
* RETURNS: OK or ERROR.
|
||||
*/
|
||||
|
||||
STATUS loPacketAddrGet
|
||||
(
|
||||
M_BLK_ID pMblk, /* pointer to packet */
|
||||
M_BLK_ID pSrc, /* pointer to local source address */
|
||||
M_BLK_ID pDst, /* pointer to local destination address */
|
||||
M_BLK_ID pESrc, /* pointer to remote source address (if any) */
|
||||
M_BLK_ID pEDst /* pointer to remote destination address (if any) */
|
||||
)
|
||||
{
|
||||
|
||||
if (pSrc != NULL)
|
||||
{
|
||||
pSrc->mBlkHdr.mData = NULL;
|
||||
pSrc->mBlkHdr.mLen = 0;
|
||||
}
|
||||
if (pDst != NULL)
|
||||
{
|
||||
pDst->mBlkHdr.mLen = 0;
|
||||
}
|
||||
if (pESrc != NULL)
|
||||
{
|
||||
pESrc->mBlkHdr.mData = NULL;
|
||||
pESrc->mBlkHdr.mLen = 0;
|
||||
}
|
||||
if (pEDst != NULL)
|
||||
{
|
||||
pEDst->mBlkHdr.mLen = 0;
|
||||
}
|
||||
|
||||
return (OK);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,324 @@
|
||||
/* smEndShow.c - shared memory network END driver show routines */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999, 2001, 2004, 2006, 2009-2010, 2013 Wind River Systems, Inc.
|
||||
*
|
||||
* The right to copy, distribute, modify or otherwise make use
|
||||
* of this software may be licensed only pursuant to the terms
|
||||
* of an applicable Wind River license agreement.
|
||||
*/
|
||||
|
||||
/*
|
||||
modification history
|
||||
--------------------
|
||||
01j,14jun13,fao Fix Coverity Prevent warnings. (WIND00414265)
|
||||
01i,04jun10,pch fix build warnings
|
||||
01h,12may09,e_d add check unitTbl. (WIND00165866)
|
||||
01g,11may06,dgp doc: fix NPG reference in lib
|
||||
01f,31aug04,mdo Documentation fixes for apigen
|
||||
01e,06feb04,jln ported to base6 and T221
|
||||
01d,09apr01,mas made IP address string conversion endian agnostic (SPR 65709)
|
||||
01c,26mar01,mas man page clean up (SPR 63976)
|
||||
01b,04oct99,mas componentized.
|
||||
01a,03mar99,mas Created from smNetShow.c rev 01c, 16sep92 (SPR 25573).
|
||||
*/
|
||||
|
||||
/*
|
||||
DESCRIPTION
|
||||
This library provides show routines for the shared memory network interface
|
||||
END driver.
|
||||
|
||||
The smNetShow() routine is provided as a diagnostic aid to show current
|
||||
shared memory network status.
|
||||
|
||||
INCLUDE FILES: smPktLib.h
|
||||
|
||||
SEE ALSO:
|
||||
the network stack programmer's guide.
|
||||
*/
|
||||
|
||||
#include "vxWorks.h"
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "smPktLib.h"
|
||||
#include "vxLib.h"
|
||||
#include "muxLib.h"
|
||||
#include "netinet/in.h"
|
||||
#include "inetLib.h"
|
||||
#include "smLib.h"
|
||||
#include "drv/end/smEnd.h"
|
||||
|
||||
|
||||
/* shared memory device name and unit number */
|
||||
|
||||
LOCAL char dfltSmDevName[] = "sm";
|
||||
LOCAL unsigned unit = 0;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* smEndShowInit - routine to drag in and configure smNetShow routine
|
||||
*
|
||||
* This routine is called after the smEnd driver has started. It records the
|
||||
* device name of the first shared memory device which is not known until BSP
|
||||
* compile routine.
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
void smEndShowInit (void)
|
||||
{
|
||||
FAST SM_END_DEV * pSmEndDev; /* END device pointer */
|
||||
static BOOL initialized = FALSE;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
if (unitTbl != NULL)
|
||||
{
|
||||
if (unitTbl[0] == NULL)
|
||||
printf ("SM0 show init failed: SM0 not initialized.\n");
|
||||
|
||||
/* get pointer to first SM device and record its name/unit */
|
||||
|
||||
else
|
||||
{
|
||||
pSmEndDev = unitTbl[0];
|
||||
strncpy (dfltSmDevName, pSmEndDev->devName, 2);
|
||||
unit = pSmEndDev->unit;
|
||||
initialized = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf ("SM show init failed: SM not initialized.\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* smNetShow - show information about a shared memory network
|
||||
*
|
||||
* This routine displays information about the different CPUs configured
|
||||
* in a shared memory network specified by <endName>. It prints error
|
||||
* statistics and zeros these fields if <zero> is set to TRUE.
|
||||
*
|
||||
* EXAMPLE
|
||||
* \cs
|
||||
* -> smNetShow
|
||||
* Anchor Local Addr: 0x10000800, Hard TAS
|
||||
* Sequential addressing enabled.
|
||||
* Master IP address: 192.168.207.1 Local IP address: 192.168.207.2
|
||||
*
|
||||
* heartbeat = 56, header at 0x1071d5b4, free pkts = 29.
|
||||
*
|
||||
* cpu int type arg1 arg2 arg3 queued pkts
|
||||
* --- -------- ---------- ---------- ---------- -----------
|
||||
* 0 mbox-4 0xd 0x807ffffc 0 0
|
||||
* 1 poll 0xd 0xfb001000 0x80 0
|
||||
*
|
||||
* PACKETS ERRORS
|
||||
* Unicast Brdcast
|
||||
* Input Output Input Output Input Output
|
||||
* ======= ======= ======= ======= + ======= =======
|
||||
* 3 2 0 2 | 0 0
|
||||
* value = 0 = 0x0
|
||||
* \ce
|
||||
*
|
||||
* RETURNS: OK, or ERROR if there is a hardware setup problem or the routine
|
||||
* cannot be initialized.
|
||||
*/
|
||||
|
||||
STATUS smNetShow
|
||||
(
|
||||
char * endName, /* shared memory device name (NULL = current)*/
|
||||
BOOL zero /* TRUE = zero the totals */
|
||||
)
|
||||
{
|
||||
FAST SM_END_DEV * pSmEndDev; /* END device pointer */
|
||||
SM_ANCHOR * pAnchor; /* pointer to anchor */
|
||||
FAST int cpuNum; /* cpu number */
|
||||
struct in_addr masterAddr; /* master IP address */
|
||||
struct in_addr localAddr; /* local IP address */
|
||||
SM_PKT_MEM_HDR * pSmPktHdr; /* packet header */
|
||||
SM_PKT_INFO smPktInfo; /* info structure */
|
||||
SM_PKT_CPU_INFO cpuInfo; /* cpu info struct */
|
||||
FAST SM_CPU_DESC * pCpuDesc; /* sm CPU descriptor */
|
||||
FAST SM_HDR * pSmHdr;
|
||||
unsigned len; /* length of sm device name */
|
||||
int bogus; /* bogus space */
|
||||
char mAddrStr [INET_ADDR_LEN];
|
||||
char lAddrStr [INET_ADDR_LEN];
|
||||
|
||||
/* use default name and unit number if no interface name specified */
|
||||
|
||||
if ((endName == NULL) || (strlen (endName) < 1))
|
||||
endName = dfltSmDevName;
|
||||
|
||||
/* else, derive name and unit # from input name */
|
||||
|
||||
else if ((len = strcspn (endName, "0123456789")) != 0)
|
||||
{
|
||||
unit = atoi (&endName[len]);
|
||||
endName[len] = 0; /* leave just name remaining */
|
||||
}
|
||||
|
||||
if ((pSmEndDev = (SM_END_DEV *)endFindByName (endName, unit)) == NULL)
|
||||
{
|
||||
printf ("Device %s%u not attached\n", endName, unit);
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
/* check validity of anchor */
|
||||
|
||||
pAnchor = pSmEndDev->pAnchor;
|
||||
printf ("Anchor Local Addr: %p", (void *) pAnchor);
|
||||
if (vxMemProbe ((char *) pAnchor, VX_READ, 4, (char *) &bogus) != OK)
|
||||
{
|
||||
printf (", UNREADABLE\n");
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
if (ntohl (pAnchor->readyValue) != SM_READY) /* check ready value */
|
||||
{
|
||||
printf (", UNINITIALIZED\n");
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
if (smIsAlive (pAnchor, &(pAnchor->smPktHeader),
|
||||
pSmEndDev->smPktDesc.smDesc.base, 5, 0) == FALSE)
|
||||
{
|
||||
printf (", NO HEARTBEAT\n");
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
if (smPktInfoGet (&(pSmEndDev->smPktDesc), &smPktInfo) == ERROR)
|
||||
{
|
||||
printf (" CPU NOT ATTACHED\n");
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
if (smPktInfo.smInfo.tasType == SM_TAS_SOFT)
|
||||
printf (", SOFT TAS\n");
|
||||
else
|
||||
printf (", Hard TAS\n");
|
||||
|
||||
pSmPktHdr = SM_OFFSET_TO_LOCAL (ntohl (pAnchor->smPktHeader),
|
||||
pSmEndDev->smPktDesc.smDesc.base,
|
||||
SM_PKT_MEM_HDR *);
|
||||
|
||||
pSmHdr = SM_OFFSET_TO_LOCAL (ntohl (pAnchor->smHeader), (unsigned)pAnchor,
|
||||
SM_HDR *);
|
||||
pCpuDesc = SM_OFFSET_TO_LOCAL (ntohl (pSmHdr->cpuTable), (unsigned)pAnchor,
|
||||
SM_CPU_DESC *);
|
||||
if (pSmPktHdr->reserved1 != 0)
|
||||
{
|
||||
localAddr.s_addr = htonl (pSmEndDev->startAddr);
|
||||
masterAddr.s_addr = pSmPktHdr->reserved1;
|
||||
printf ("Sequential addressing enabled.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
localAddr.s_addr = htonl (pSmEndDev->ipAddr);
|
||||
masterAddr.s_addr = pCpuDesc->reserved1;
|
||||
printf ("Sequential addressing disabled.\n");
|
||||
}
|
||||
|
||||
inet_ntoa_b (masterAddr, mAddrStr);
|
||||
inet_ntoa_b (localAddr, lAddrStr);
|
||||
printf ("Master IP address: %s Local IP address: %s\n",
|
||||
mAddrStr, lAddrStr);
|
||||
|
||||
printf ("\nheartbeat = %d, header at %p, free pkts = %d.\n\n",
|
||||
ntohl (pSmPktHdr->heartBeat), (void *) pSmPktHdr,
|
||||
smPktInfo.freePkts);
|
||||
|
||||
|
||||
/* print out info for each CPU */
|
||||
|
||||
printf (
|
||||
"cpu int type arg1 arg2 arg3 queued pkts\n");
|
||||
printf (
|
||||
"--- -------- ---------- ---------- ---------- -----------\n");
|
||||
|
||||
for (cpuNum = 0; cpuNum < smPktInfo.smInfo.maxCpus; ++cpuNum)
|
||||
{
|
||||
if (smPktCpuInfoGet (&(pSmEndDev->smPktDesc), cpuNum, &cpuInfo) == ERROR)
|
||||
return (ERROR);
|
||||
|
||||
if (cpuInfo.status == SM_CPU_ATTACHED)
|
||||
{
|
||||
printf ("%2d ", cpuNum);
|
||||
switch (cpuInfo.smCpuInfo.intType)
|
||||
{
|
||||
case SM_INT_NONE:
|
||||
printf ("poll ");
|
||||
break;
|
||||
case SM_INT_MAILBOX_1:
|
||||
printf ("mbox-1 ");
|
||||
break;
|
||||
case SM_INT_MAILBOX_2:
|
||||
printf ("mbox-2 ");
|
||||
break;
|
||||
case SM_INT_MAILBOX_4:
|
||||
printf ("mbox-4 ");
|
||||
break;
|
||||
case SM_INT_MAILBOX_R1:
|
||||
printf ("mbox-1r ");
|
||||
break;
|
||||
case SM_INT_MAILBOX_R2:
|
||||
printf ("mbox-2r ");
|
||||
break;
|
||||
case SM_INT_MAILBOX_R4:
|
||||
printf ("mbox-4r ");
|
||||
break;
|
||||
case SM_INT_BUS:
|
||||
printf ("bus-int ");
|
||||
break;
|
||||
case SM_INT_USER_1:
|
||||
printf ("user 1 ");
|
||||
break;
|
||||
case SM_INT_USER_2:
|
||||
printf ("user 2 ");
|
||||
break;
|
||||
default:
|
||||
printf ("%#8x", cpuInfo.smCpuInfo.intType);
|
||||
break;
|
||||
}
|
||||
|
||||
printf (" %#10x %#10x %#10x", cpuInfo.smCpuInfo.intArg1,
|
||||
cpuInfo.smCpuInfo.intArg2, cpuInfo.smCpuInfo.intArg3);
|
||||
printf (" %3d\n", cpuInfo.inputPkts);
|
||||
}
|
||||
}
|
||||
|
||||
printf ("\n PACKETS ERRORS\n");
|
||||
printf (" Unicast Brdcast\n");
|
||||
printf (" Input Output Input Output Input Output\n");
|
||||
printf ("======= ======= ======= ======= + ======= =======\n");
|
||||
printf ("%7lu %7lu %7lu %7lu | %7lu %7lu\n",
|
||||
pSmEndDev->end.mib2Tbl.ifInUcastPkts,
|
||||
pSmEndDev->end.mib2Tbl.ifOutUcastPkts,
|
||||
pSmEndDev->end.mib2Tbl.ifInNUcastPkts,
|
||||
pSmEndDev->end.mib2Tbl.ifOutNUcastPkts,
|
||||
pSmEndDev->end.mib2Tbl.ifInErrors,
|
||||
pSmEndDev->end.mib2Tbl.ifOutErrors);
|
||||
|
||||
/* if requested, zero the interface statistics */
|
||||
|
||||
if (zero)
|
||||
{
|
||||
pSmEndDev->end.mib2Tbl.ifInUcastPkts = 0;
|
||||
pSmEndDev->end.mib2Tbl.ifOutUcastPkts = 0;
|
||||
pSmEndDev->end.mib2Tbl.ifInNUcastPkts = 0;
|
||||
pSmEndDev->end.mib2Tbl.ifOutNUcastPkts = 0;
|
||||
pSmEndDev->end.mib2Tbl.ifInErrors = 0;
|
||||
pSmEndDev->end.mib2Tbl.ifOutErrors = 0;
|
||||
}
|
||||
|
||||
return (OK);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user