www.pudn.com > S3c2410bsp.zip > ne2000End.c
/* ne2000End.c - NE2000 END network interface driver */
#include "copyright_wrs.h"
#include "vxWorks.h"
#include "endLib.h" /* Common END structures. */
#include "etherMultiLib.h"
#include "netLib.h"
#include "cacheLib.h"
#include "lstLib.h" /* Needed to maintain protocol list. */
#include "iv.h"
#include "stdlib.h"
#include "sysLib.h"
#include "intLib.h"
#include "taskLib.h"
#include "ne2000End.h"
#include "s3c2410x.h"
#include "wrSbcArm9.h"
#define NE2000_ALL_INTS (IM_OVWE | IM_TXEE | IM_RXEE | IM_PTXE | IM_PRXE)
/*#define NE2000_ALL_INTS (IM_PTXE | IM_PRXE)*/
#define CRC32_POLYNOMIAL 0x04c11db7
/* Configuration items */
#define END_SPEED 10000000
#define NE2000_DEV_NAME "ene"
#define NE2000_DEV_NAME_LEN 4
#ifndef SYS_INT_CONNECT
#define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) \
{ \
IMPORT STATUS intConnect(); \
*pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), \
rtn, (int)arg); \
}
#endif
#ifndef SYS_INT_DISCONNECT
#define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) \
{ \
*pResult = OK; /* HELP: need a real routine */ \
}
#endif
#ifndef SYS_INT_ENABLE
#define SYS_INT_ENABLE(pDrvCtrl) \
{ \
IMPORT STATUS intEnable(); \
intEnable (pDrvCtrl->ilevel); \
}
#endif
#ifndef SYS_ENET_ADDR_GET
#define SYS_ENET_ADDR_GET(pDevice) \
ne2000EnetAddrGet(pDevice)
#endif
#if (CPU_FAMILY == I80X86)
#ifndef SYS_OUT_CHAR
#define SYS_OUT_CHAR(pDrvCtrl,addr,value) \
sysOutByte((pDrvCtrl)->base + (int) (addr),(char) (value))
#endif
#ifndef SYS_IN_CHAR
#define SYS_IN_CHAR(pDrvCtrl,addr,pData) \
(*(pData) = (UCHAR) sysInByte((pDrvCtrl)->base + (int) (addr)))
#endif
#ifndef SYS_IN_WORD_STRING
#define SYS_IN_WORD_STRING(pDrvCtrl,addr,pData,len) \
(sysInWordString ((pDrvCtrl)->base + (int) (addr), (short *)(pData), \
(len)))
#endif
#ifndef SYS_OUT_WORD_STRING
#define SYS_OUT_WORD_STRING(pDrvCtrl,addr,pData,len) \
(sysOutWordString ((pDrvCtrl)->base + (int) (addr), (short *)(pData), \
(len)))
#endif
#else /* #if (CPU_FAMILY == I80X86) */
#ifndef SYS_OUT_CHAR
#define SYS_OUT_CHAR(pDrvCtrl,addr,value) \
sysOutByte((pDrvCtrl)->base + (UINT) (addr), (value))
#endif
#ifndef SYS_IN_CHAR
#define SYS_IN_CHAR(pDrvCtrl,addr,pData) \
(*(pData) = (UCHAR) sysInByte((pDrvCtrl)->base + (UINT) (addr)))
#endif
#ifndef SYS_IN_WORD_STRING
#define SYS_IN_WORD_STRING(pDrvCtrl,addr,pData,len) \
(sysInWordString ((pDrvCtrl)->base + (UINT) (addr), \
(UINT16 *)(pData), (len)))
#endif
#ifndef SYS_OUT_WORD_STRING
#define SYS_OUT_WORD_STRING(pDrvCtrl,addr,pData,len) \
(sysOutWordString ((pDrvCtrl)->base + (UINT) (addr), \
(UINT16 *) (pData), (len)))
#endif
#endif /* #if (CPU_FAMILY == I80X86) */
/* A shortcut for getting the hardware address from the MIB II stuff. */
#define END_HADDR(pEnd) \
((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
#define END_HADDR_LEN(pEnd) \
((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
/* Statistics we gather from the NE2000 */
typedef struct
{
UINT collisions;
UINT crcs;
UINT aligns;
UINT missed;
UINT overruns;
UINT disabled;
UINT deferring;
UINT underruns;
UINT aborts;
UINT outofwindow;
UINT heartbeats;
UINT badPacket;
UINT shortPacket;
UINT tnoerror;
UINT rnoerror;
UINT terror;
UINT rerror;
UINT overwrite;
UINT wrapped;
UINT interrupts;
UINT reset;
UINT strayint;
UINT jabber;
} NE2000_STAT;
typedef struct ne2000_device
{
END_OBJ endObj;
END_ERR lastError;
int lastIntError;
int unit;
int ivec;
int ilevel;
int byteAccess;
int usePromEnetAddr;
ULONG base;
int offset;
#ifdef _USE_SND_DMA_
char packetBuf [SAVE_SND_NUM][NE2000_BUFSIZ]; /* long-aligned */
int packetLen[SAVE_SND_NUM];
#else
char packetBuf[NE2000_BUFSIZ];
#endif
volatile long flags;
volatile UCHAR current;
volatile ULONG imask;
volatile NE2000_STAT stats;
UCHAR enetAddr[6];
UCHAR mcastFilter[8];
UCHAR nextPacket;
CL_POOL_ID clPoolId;
int configRegA;
int configRegB;
#ifdef _USE_SND_DMA_
int useHead;
int bufCount;
int freeHead;
#endif
#ifdef _USE_RECV_DMA_
char recvMapBuf[RECV_PAGE_NUM][RECV_PAGE_SIZE];
int nextMapPage;
#endif
} NE2000END_DEVICE;
NE2000END_DEVICE *gpDeviceCtrl = NULL;
struct macinfo
{ char ipadrinfo[50];
char netmaskinfo[50];
char gatewayinfo[50];
ULONG netmaskshowinfo;
UCHAR macshowinfo[6];
int dhcpflag;
int bootpflag;
};
struct macinfo MAC_INFO;
/* Definitions for the flags field */
#define END_PROMISCUOUS_FLAG 0x01
#define END_RECV_HANDLING_FLAG 0x02
#define END_TX_IN_PROGRESS 0x04
#define END_TX_BLOCKED 0x08
#define END_POLLING 0x10
#define END_OVERWRITE 0x20
#define END_OVERWRITE2 0x40
/***** DEBUG MACROS *****/
#undef DEBUG
#ifdef DEBUG
# include "stdio.h"
# include "logLib.h"
int endDebug = 1;
# define ENDLOGMSG(x) \
do { \
if (endDebug) \
logMsg x; \
} while (0)
#else
# define ENDLOGMSG(x)
#endif /* ENDDEBUG */
/***** LOCALS *****/
/* imports */
IMPORT char ne2000EnetAddr[];
IMPORT int endMultiLstCnt (END_OBJ *);
LOCAL void ne2000Int (NE2000END_DEVICE* pDrvCtrl);
LOCAL void ne2000HandleRcvInt (NE2000END_DEVICE* pDrvCtrl);
LOCAL void ne2000Config (NE2000END_DEVICE* pDrvCtrl,
int intEnable);
LOCAL void ne2000OverwriteRecover (NE2000END_DEVICE* pDrvCtrl,
UCHAR cmdStatus);
LOCAL int ne2000PacketGet (NE2000END_DEVICE* pDrvCtrl, char *pData);
LOCAL void ne2000AddrFilterSet (NE2000END_DEVICE* pDrvCtrl);
LOCAL UINT32 ne2000CrcWork (UINT8 inChar, UINT32 inCrc);
LOCAL void ne2000EnetAddrGet (NE2000END_DEVICE* pDrvCtrl);
LOCAL UCHAR ne2000GetCurr (NE2000END_DEVICE* pDrvCtrl);
LOCAL void ne2000DataIn (NE2000END_DEVICE* pDrvCtrl, int eneAddress,
int len, char* pData);
LOCAL void ne2000DataOut (NE2000END_DEVICE* pDrvCtrl, char* pData,
int len, int eneAddress);
LOCAL STATUS ne2000Parse (NE2000END_DEVICE* pDrvCtrl, char* initString);
LOCAL STATUS ne2000MemInit (NE2000END_DEVICE* pDrvCtrl);
LOCAL STATUS ne2000PollStart (NE2000END_DEVICE* pDrvCtrl);
LOCAL STATUS ne2000PollStop (NE2000END_DEVICE* pDrvCtrl);
/* END Specific interfaces. */
/* This is the only externally visible interface. */
END_OBJ * ne2000EndLoad (char* initString, void *pBSP);
LOCAL STATUS ne2000Start (void* pCookie);
LOCAL STATUS ne2000Stop (void* pCookie);
LOCAL STATUS ne2000Unload (void *pCookie);
LOCAL int ne2000Ioctl (void *pCookie, int cmd, caddr_t data);
LOCAL STATUS ne2000Send (void *pCookie, M_BLK_ID pBuf);
LOCAL STATUS ne2000MCastAdd (void *pCookie, char* pAddress);
LOCAL STATUS ne2000MCastDel (void *pCookie, char* pAddress);
LOCAL STATUS ne2000MCastGet (void *pCookie, MULTI_TABLE* pTable);
LOCAL STATUS ne2000PollSend (void *pCookie, M_BLK_ID pBuf);
LOCAL STATUS ne2000PollRecv (void *pCookie, M_BLK_ID pBuf);
#define U32 unsigned int
void ne2000DmaInit();
#ifdef _USE_SND_DMA_
void ne2000DmaSendInt();
void ne2000DmaSend(NE2000END_DEVICE* pDrvCtrl ,int eneAddress);
#else
void ne2000DmaSendInt();
void ne2000DmaSend(NE2000END_DEVICE* pDev , char *srcBuf , int sndLen);
#endif
#ifdef _USE_RECV_DMA_
void ne2000DmaRecvInt();
void ne2000DmaRecv(NE2000END_DEVICE *pDrvCtrl,int eneAddress,int len);
#endif
void ne2000OpenRecvIntLog();
LOCAL NET_FUNCS ne2000FuncTable =
{
(FUNCPTR) ne2000Start,
(FUNCPTR) ne2000Stop,
(FUNCPTR) ne2000Unload,
(FUNCPTR) ne2000Ioctl,
(FUNCPTR) ne2000Send,
(FUNCPTR) ne2000MCastAdd,
(FUNCPTR) ne2000MCastDel,
(FUNCPTR) ne2000MCastGet,
(FUNCPTR) ne2000PollSend,
(FUNCPTR) ne2000PollRecv,
endEtherAddressForm,
(FUNCPTR) endEtherPacketDataGet,
(FUNCPTR) endEtherPacketAddrGet
};
int dmaReadyFlag =TRUE;
int recvIntLog = FALSE;
/******************************************************************************
*
*
* RETURNS: An END object pointer or NULL on error.
*/
END_OBJ* ne2000EndLoad
(
char* initString,
void* pBSP
)
{
NE2000END_DEVICE *pDrvCtrl;
int level;
UCHAR regVal;
#ifdef DEBUG
printf ("ne2000EndLoad(%s)\n", initString);
printf ("\tinitString '%s'\n", initString ? initString : "");
printf ("\tpBSP '%s'\n", pBSP ? pBSP : "");
#endif
if (initString == NULL)
return (NULL);
if (initString[0] == '\0')
{
bcopy((char *)NE2000_DEV_NAME, initString, NE2000_DEV_NAME_LEN);
return (NULL);
}
pDrvCtrl = (NE2000END_DEVICE *) calloc (sizeof(NE2000END_DEVICE), 1);
if (pDrvCtrl == NULL)
goto errorExit;
if (ne2000Parse (pDrvCtrl, initString) == ERROR)
goto errorExit;
if (pDrvCtrl->configRegA != 0)
{
level = intLock ();
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE0);
SYS_IN_CHAR (pDrvCtrl, ENE_RBCR0, ®Val);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, pDrvCtrl->configRegA);
intUnlock (level);
}
if (pDrvCtrl->configRegB != 0)
{
level = intLock ();
SYS_IN_CHAR (pDrvCtrl, ENE_RBCR1, ®Val);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, pDrvCtrl->configRegB);
intUnlock (level);
}
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
if (pDrvCtrl->byteAccess)
SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS_8
| DCON_LOOPBK_OFF);
else
SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS16
| DCON_LOOPBK_OFF);
SYS_ENET_ADDR_GET (pDrvCtrl);
if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, NE2000_DEV_NAME,
pDrvCtrl->unit, &ne2000FuncTable,
"ne2000 Enhanced Network Driver") == ERROR)
goto errorExit;
if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
&pDrvCtrl->enetAddr[0], 6, ETHERMTU,
END_SPEED) == ERROR)
goto errorExit;
if (ne2000MemInit (pDrvCtrl) == ERROR)
goto errorExit;
END_OBJ_READY (&pDrvCtrl->endObj,
IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
#ifdef _USE_SND_DMA_
pDrvCtrl->useHead = 0x5a;
pDrvCtrl->freeHead = 0;
pDrvCtrl->bufCount = SAVE_SND_NUM;
#endif
gpDeviceCtrl = pDrvCtrl;
return (&pDrvCtrl->endObj);
errorExit:
if (pDrvCtrl != NULL)
free ((char *)pDrvCtrl);
return (NULL);
}
/******************************************************************************
* RETURNS: OK or ERROR for invalid arguments.
*/
LOCAL STATUS ne2000Parse
(
NE2000END_DEVICE * pDrvCtrl,
char * initString
)
{
char* tok;
char* holder = NULL;
tok = strtok_r (initString, ":", &holder);
if (tok == NULL)
return (ERROR);
pDrvCtrl->unit = atoi (tok);
tok = strtok_r (NULL, ":", &holder);
if (tok == NULL)
return (ERROR);
pDrvCtrl->base = strtoul (tok, NULL, 16);
tok = strtok_r (NULL, ":", &holder);
if (tok == NULL)
return (ERROR);
pDrvCtrl->ivec = strtoul (tok, NULL, 16);
tok = strtok_r (NULL, ":", &holder);
if (tok == NULL)
return (ERROR);
pDrvCtrl->ilevel = strtoul (tok, NULL, 16);
tok = strtok_r (NULL, ":", &holder);
if (tok == NULL)
return (ERROR);
pDrvCtrl->byteAccess = atoi (tok);
tok = strtok_r (NULL, ":", &holder);
if (tok == NULL)
return (ERROR);
pDrvCtrl->usePromEnetAddr = atoi (tok);
tok = strtok_r (NULL, ":", &holder);
if (tok == NULL)
return (ERROR);
pDrvCtrl->offset = strtoul (tok, NULL, 16);
pDrvCtrl->configRegA = 0;
tok = strtok_r (NULL, ":", &holder);
if (tok != NULL)
pDrvCtrl->configRegA = strtoul (tok, NULL, 16);
pDrvCtrl->configRegB = 0;
tok = strtok_r (NULL, ":", &holder);
if (tok != NULL)
pDrvCtrl->configRegB = strtoul (tok, NULL, 16);
return (OK);
}
/*******************************************************************************
* RETURNS: OK or ERROR.
*/
LOCAL STATUS ne2000MemInit
(
NE2000END_DEVICE * pDrvCtrl
)
{
M_CL_CONFIG eneMclBlkConfig;
CL_DESC clDesc; /* cluster description */
bzero ((char *)&eneMclBlkConfig, sizeof(eneMclBlkConfig));
bzero ((char *)&clDesc, sizeof(clDesc));
clDesc.clNum = 128;
clDesc.clSize = NE2000_BUFSIZ; /* allow for alignment */
clDesc.memSize = ((clDesc.clNum * (clDesc.clSize + 8)) + 4);
eneMclBlkConfig.mBlkNum = 64 * 4;
eneMclBlkConfig.clBlkNum = clDesc.clNum;
eneMclBlkConfig.memSize =
(eneMclBlkConfig.mBlkNum * (MSIZE + sizeof (long)))
+ (eneMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof (long)));
eneMclBlkConfig.memArea = (char *) memalign(sizeof (long),
eneMclBlkConfig.memSize);
if (eneMclBlkConfig.memArea == NULL)
return (ERROR);
clDesc.memArea = (char *) malloc (clDesc.memSize);
if (clDesc.memArea == NULL)
return (ERROR);
pDrvCtrl->endObj.pNetPool = (NET_POOL_ID) malloc (sizeof(NET_POOL));
if (pDrvCtrl->endObj.pNetPool == NULL)
return (ERROR);
if (netPoolInit (pDrvCtrl->endObj.pNetPool, &eneMclBlkConfig,
&clDesc, 1, NULL) == ERROR)
return (ERROR);
pDrvCtrl->clPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool,
NE2000_BUFSIZ, FALSE);
return (OK);
}
/*******************************************************************************
*/
LOCAL int ne2000Ioctl
(
void* pCookie,
int cmd,
caddr_t data
)
{
int error = 0;
long value;
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
ENDLOGMSG (("into ne2000Ioctl.\n", 0, 0, 0, 0, 0, 0));
switch ((UINT) cmd)
{
case EIOCSADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),
END_HADDR_LEN(&pDrvCtrl->endObj));
ENDLOGMSG (("ne2000Ioctl set phy addr.\n", 0, 0, 0, 0, 0, 0));
break;
case EIOCGADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data,
END_HADDR_LEN(&pDrvCtrl->endObj));
ENDLOGMSG (("ne2000Ioctl get phy addr.\n", 0, 0, 0, 0, 0, 0));
break;
case EIOCSFLAGS:
value = (long)data;
if (value < 0)
{
value = -value;
value--;
END_FLAGS_CLR (&pDrvCtrl->endObj, value);
}
else
END_FLAGS_SET (&pDrvCtrl->endObj, value);
ENDLOGMSG (("ne2000Ioctl set flag.\n", 0, 0, 0, 0, 0, 0));
ne2000Config (pDrvCtrl, TRUE);
break;
case EIOCGFLAGS:
*(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj);
ENDLOGMSG (("ne2000Ioctl get phy addr.\n", 0, 0, 0, 0, 0, 0));
break;
case EIOCPOLLSTART:
ne2000PollStart (pDrvCtrl);
ENDLOGMSG (("ne2000Ioctl pool start.\n", 0, 0, 0, 0, 0, 0));
break;
case EIOCPOLLSTOP:
ne2000PollStop (pDrvCtrl);
ENDLOGMSG (("ne2000Ioctl pool stop.\n", 0, 0, 0, 0, 0, 0));
break;
case EIOCGMIB2:
if (data == NULL)
return (EINVAL);
bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
sizeof(pDrvCtrl->endObj.mib2Tbl));
ENDLOGMSG (("ne2000Ioctl get mib table.\n", 0, 0, 0, 0, 0, 0));
break;
case EIOCGFBUF:
if (data == NULL)
return (EINVAL);
ENDLOGMSG (("ne2000Ioctl get buffer.\n", 0, 0, 0, 0, 0, 0));
break;
default:
error = EINVAL;
ENDLOGMSG (("ne2000Ioctl do nothing.\n", 0, 0, 0, 0, 0, 0));
}
return (error);
}
/*******************************************************************************
*
* ne2000Start - start the device
*
*
* RETURNS: OK or ERROR
*
*/
LOCAL STATUS ne2000Start
(
void* pCookie
)
{
UCHAR rxFilter; /* receiver configuration */
#ifdef DEBUG
static buf [256];
#endif
STATUS result;
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
SYS_INT_CONNECT (pDrvCtrl, ne2000Int, (int)pDrvCtrl, &result);
if (result == ERROR)
return (ERROR);
#ifdef _USE_RECV_DMA_
pDrvCtrl->imask = 0;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
ne2000AddrFilterSet (pDrvCtrl);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
if (pDrvCtrl->byteAccess)
SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS_8
| DCON_LOOPBK_OFF);
else
SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS16
| DCON_LOOPBK_OFF);
SYS_ENET_ADDR_GET (pDrvCtrl);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00);
rxFilter = RCON_BROAD;
if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
{
rxFilter |= RCON_GROUP;
}
ENDLOGMSG (("\tMulticast mode %s\n",
(rxFilter & RCON_GROUP) ? "on" : "off",
0, 0, 0, 0, 0));
if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_PROMISC)
{
rxFilter |= RCON_PROM;
}
ENDLOGMSG (("\tPromiscuous mode %s\n",
(rxFilter & RCON_PROM) ? "on" : "off",
0, 0, 0, 0, 0));
ENDLOGMSG (("\tsetting rxFilter = 0x%x\n", rxFilter,2,3,4,5,6));
SYS_OUT_CHAR (pDrvCtrl, ENE_RCON, rxFilter);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB1);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSTART, NE2000_PSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSTOP, NE2000_PSTOP);
SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND, NE2000_PSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, (char)0xff);
pDrvCtrl->imask = 0;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE1 | CMD_STOP);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA0, pDrvCtrl->enetAddr[0]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA1, pDrvCtrl->enetAddr[1]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA2, pDrvCtrl->enetAddr[2]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA3, pDrvCtrl->enetAddr[3]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA4, pDrvCtrl->enetAddr[4]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA5, pDrvCtrl->enetAddr[5]);
ENDLOGMSG (("enet addr %02x:%02x:%02x:%02x:%02x:%02x\n",
pDrvCtrl->enetAddr[0] & 0xff,
pDrvCtrl->enetAddr[1] & 0xff,
pDrvCtrl->enetAddr[2] & 0xff,
pDrvCtrl->enetAddr[3] & 0xff,
pDrvCtrl->enetAddr[4] & 0xff,
pDrvCtrl->enetAddr[5] & 0xff));
ne2000AddrFilterSet (pDrvCtrl);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR0, pDrvCtrl->mcastFilter[0]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR1, pDrvCtrl->mcastFilter[1]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR2, pDrvCtrl->mcastFilter[2]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR3, pDrvCtrl->mcastFilter[3]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR4, pDrvCtrl->mcastFilter[4]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR5, pDrvCtrl->mcastFilter[5]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR6, pDrvCtrl->mcastFilter[6]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR7, pDrvCtrl->mcastFilter[7]);
#ifdef DEBUG
ENDLOGMSG ((("Setting multicast addresses to:\n"),1,2,3,4,5,6));
sprintf(buf, "enet mcast %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
pDrvCtrl->mcastFilter[0] & 0xff,
pDrvCtrl->mcastFilter[1] & 0xff,
pDrvCtrl->mcastFilter[2] & 0xff,
pDrvCtrl->mcastFilter[3] & 0xff,
pDrvCtrl->mcastFilter[4] & 0xff,
pDrvCtrl->mcastFilter[5] & 0xff,
pDrvCtrl->mcastFilter[6] & 0xff,
pDrvCtrl->mcastFilter[7] & 0xff);
ENDLOGMSG (((buf),1,2,3,4,5,6));
#endif /* DEBUG */
#endif
END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
#ifdef _USE_RECV_DMA_
SYS_OUT_CHAR (pDrvCtrl, ENE_CURR, NE2000_PSTART + 1);
pDrvCtrl->nextPacket = NE2000_PSTART + 1;
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_NORMAL);
#endif
pDrvCtrl->imask = (pDrvCtrl->flags & END_POLLING) ? 0 : NE2000_ALL_INTS;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
SYS_INT_ENABLE (pDrvCtrl);
ne2000DmaInit();
return (OK);
}
/******************************************************************************
*
* ne2000Config - reconfigure the interface under us.
*
*
* NOMANUAL
*/
LOCAL void ne2000Config
(
NE2000END_DEVICE *pDrvCtrl,
BOOL intEnable
)
{
UCHAR rxFilter;
#ifdef DEBUG
static buf [256];
#endif
ENDLOGMSG (("ne2000Config: enter (intEnable=%d)\n",
intEnable, 0, 0, 0, 0, 0));
pDrvCtrl->imask = 0;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
ne2000AddrFilterSet (pDrvCtrl);
pDrvCtrl->flags &= (END_POLLING | END_OVERWRITE | END_OVERWRITE2);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
if (pDrvCtrl->byteAccess)
SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS_8
| DCON_LOOPBK_OFF);
else
SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS16
| DCON_LOOPBK_OFF);
SYS_ENET_ADDR_GET (pDrvCtrl);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00);
rxFilter = RCON_BROAD;
if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0)
{
rxFilter |= RCON_GROUP;
}
ENDLOGMSG (("\tMulticast mode %s\n",
(rxFilter & RCON_GROUP) ? "on" : "off",
0, 0, 0, 0, 0));
if (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_PROMISC)
{
rxFilter |= RCON_PROM;
}
ENDLOGMSG (("\tPromiscuous mode %s\n",
(rxFilter & RCON_PROM) ? "on" : "off",
0, 0, 0, 0, 0));
ENDLOGMSG (("\tsetting rxFilter = 0x%x\n", rxFilter,2,3,4,5,6));
SYS_OUT_CHAR (pDrvCtrl, ENE_RCON, rxFilter);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB1);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSTART, NE2000_PSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSTOP, NE2000_PSTOP);
SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND, NE2000_PSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, (char)0xff);
pDrvCtrl->imask = 0;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE1 | CMD_STOP);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA0, pDrvCtrl->enetAddr[0]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA1, pDrvCtrl->enetAddr[1]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA2, pDrvCtrl->enetAddr[2]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA3, pDrvCtrl->enetAddr[3]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA4, pDrvCtrl->enetAddr[4]);
SYS_OUT_CHAR (pDrvCtrl, ENE_STA5, pDrvCtrl->enetAddr[5]);
ENDLOGMSG (("enet addr %02x:%02x:%02x:%02x:%02x:%02x\n",
pDrvCtrl->enetAddr[0] & 0xff,
pDrvCtrl->enetAddr[1] & 0xff,
pDrvCtrl->enetAddr[2] & 0xff,
pDrvCtrl->enetAddr[3] & 0xff,
pDrvCtrl->enetAddr[4] & 0xff,
pDrvCtrl->enetAddr[5] & 0xff));
ne2000AddrFilterSet (pDrvCtrl);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR0, pDrvCtrl->mcastFilter[0]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR1, pDrvCtrl->mcastFilter[1]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR2, pDrvCtrl->mcastFilter[2]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR3, pDrvCtrl->mcastFilter[3]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR4, pDrvCtrl->mcastFilter[4]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR5, pDrvCtrl->mcastFilter[5]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR6, pDrvCtrl->mcastFilter[6]);
SYS_OUT_CHAR (pDrvCtrl, ENE_MAR7, pDrvCtrl->mcastFilter[7]);
#ifdef DEBUG
ENDLOGMSG ((("Setting multicast addresses to:\n"),1,2,3,4,5,6));
sprintf(buf, "enet mcast %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
pDrvCtrl->mcastFilter[0] & 0xff,
pDrvCtrl->mcastFilter[1] & 0xff,
pDrvCtrl->mcastFilter[2] & 0xff,
pDrvCtrl->mcastFilter[3] & 0xff,
pDrvCtrl->mcastFilter[4] & 0xff,
pDrvCtrl->mcastFilter[5] & 0xff,
pDrvCtrl->mcastFilter[6] & 0xff,
pDrvCtrl->mcastFilter[7] & 0xff);
ENDLOGMSG (((buf),1,2,3,4,5,6));
#endif /* DEBUG */
SYS_OUT_CHAR (pDrvCtrl, ENE_CURR, NE2000_PSTART + 1);
pDrvCtrl->nextPacket = NE2000_PSTART + 1;
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_NORMAL);
ENDLOGMSG (("ne2000Config: done\n", 0, 0, 0, 0, 0, 0));
pDrvCtrl->imask = ((pDrvCtrl->flags & END_POLLING) ? 0 : NE2000_ALL_INTS);
if (intEnable)
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
}
/*******************************************************************************
*/
LOCAL void ne2000OverwriteRecover
(
NE2000END_DEVICE *pDrvCtrl,
UCHAR cmdStatus
)
{
UCHAR stat;
BOOL reSend;
int recvLen = 0;
ENDLOGMSG (("ne2000OverwriteRecover: enter (flags=%x, imask=%x)\n",
pDrvCtrl->flags,pDrvCtrl->imask,0,0,0,0));
if (!(pDrvCtrl->flags & END_OVERWRITE2))
{
ENDLOGMSG (("ne2000OverwriteRecover: bad flags\n",
0,0,0,0,0,0));
#ifdef DEBUG
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
taskSuspend (0);
#else
return;
#endif
}
taskDelay ((sysClkRateGet() + 624)/ 625);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, 0x00);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, 0x00);
if ((cmdStatus & CMD_TXP) == 0)
reSend = FALSE;
else
{
SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &stat);
if ((stat & (ISTAT_PTX | ISTAT_TXE)) == 0)
{
reSend = TRUE;
}
else
{
reSend = FALSE;
}
}
SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, TCON_LB1);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
pDrvCtrl->flags &= ~END_OVERWRITE;
pDrvCtrl->current = ne2000GetCurr (pDrvCtrl);
#ifdef _USE_RECV_DMA_
if(pDrvCtrl->current>= pDrvCtrl->nextPacket)
{
recvLen = (pDrvCtrl->current-pDrvCtrl->nextPacket)*RECV_PAGE_SIZE;
}
else
{
recvLen = ((NE2000_PSTOP-pDrvCtrl->nextPacket)+(pDrvCtrl->current-NE2000_PSTART))*RECV_PAGE_SIZE;
}
ne2000DmaRecv(pDrvCtrl , (((UINT)pDrvCtrl->nextPacket << 8) & 0x0000ffff)
, recvLen);
#else
ne2000HandleRcvInt (pDrvCtrl);
#endif
}
/*******************************************************************************
*
*
* RETURNS: N/A.
*/
LOCAL void ne2000Int(NE2000END_DEVICE *pDrvCtrl)
{
UCHAR val;
UCHAR intStat;
UCHAR txStat;
UCHAR rxStat;
pDrvCtrl->stats.interrupts++;
SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &intStat);
intStat &= pDrvCtrl->imask;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, intStat);
SYS_IN_CHAR (pDrvCtrl, ENE_TSTAT, &txStat);
SYS_IN_CHAR (pDrvCtrl, ENE_RSTAT, &rxStat);
ENDLOGMSG (("ne2000Int: intStat=%02x imask=%02x txStat=%02x rxStat=%02x\n",
intStat, pDrvCtrl->imask, txStat, rxStat, 0, 0));
if(TRUE == recvIntLog)
{
logMsg ("ne2000Int: intStat=%02x imask=%02x txStat=%02x rxStat=%02x\n",
intStat, pDrvCtrl->imask, txStat, rxStat, 0, 0);
}
SYS_IN_CHAR (pDrvCtrl, ENE_COLCNT, &val);
pDrvCtrl->stats.collisions += val;
SYS_IN_CHAR (pDrvCtrl, ENE_ALICNT, &val);
pDrvCtrl->stats.aligns += val;
SYS_IN_CHAR (pDrvCtrl, ENE_CRCCNT, &val);
pDrvCtrl->stats.crcs += val;
SYS_IN_CHAR (pDrvCtrl, ENE_MPCNT, &val);
pDrvCtrl->stats.missed += val;
if (intStat & ISTAT_OVW) /* Overwrite */
{
UCHAR cmdStat;
UCHAR currNo ;
UCHAR bnry ;
currNo = ne2000GetCurr(pDrvCtrl);
SYS_IN_CHAR (pDrvCtrl, ENE_BOUND , &bnry);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
if (!(pDrvCtrl->flags & END_OVERWRITE2))
{
pDrvCtrl->flags |= (END_OVERWRITE | END_OVERWRITE2);
pDrvCtrl->lastError.errCode = END_ERR_WARN;
pDrvCtrl->lastError.pMesg = "Overwrite";
netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
(int) &pDrvCtrl->lastError,
0, 0, 0);
pDrvCtrl->stats.overwrite++;
SYS_IN_CHAR (pDrvCtrl, ENE_COLCNT, &cmdStat);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
ENDLOGMSG (("ne2000Int: overwrite detected\n",
0, 0, 0, 0, 0, 0));
netJobAdd ((FUNCPTR) ne2000OverwriteRecover, (int) pDrvCtrl,
cmdStat, 0, 0, 0);
}
pDrvCtrl->imask = 0;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
return;
}
if (intStat & ISTAT_RXE) /* Receive-error */
{
if (!pDrvCtrl->lastIntError)
{
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
pDrvCtrl->lastError.errCode = END_ERR_WARN;
pDrvCtrl->lastError.pMesg = "receive error";
netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
(int) &pDrvCtrl->lastError,
0, 0, 0);
}
++pDrvCtrl->lastIntError;
pDrvCtrl->stats.rerror++;
if (rxStat & RSTAT_OVER)
pDrvCtrl->stats.overruns++;
if (rxStat & RSTAT_DIS)
pDrvCtrl->stats.disabled++;
if (rxStat & RSTAT_DFR)
pDrvCtrl->stats.deferring++;
}
if (intStat & ISTAT_TXE) /* Transmit error-packet not sent */
{
if (!pDrvCtrl->lastIntError)
{
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
pDrvCtrl->lastError.errCode = END_ERR_WARN;
pDrvCtrl->lastError.pMesg = "transmit error";
netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
(int) &pDrvCtrl->lastError,
0, 0, 0);
}
++pDrvCtrl->lastIntError;
pDrvCtrl->stats.terror++;
if (txStat & TSTAT_ABORT)
{
pDrvCtrl->stats.aborts++;
pDrvCtrl->stats.collisions += 16;
}
if (txStat & TSTAT_UNDER)
pDrvCtrl->stats.underruns++;
}
if (intStat & ISTAT_PTX) /* Transmit-packet sent */
{
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
if (txStat & TSTAT_CDH)
pDrvCtrl->stats.heartbeats++;
if (txStat & TSTAT_OWC)
pDrvCtrl->stats.outofwindow++;
if (txStat & TSTAT_PTX)
pDrvCtrl->stats.tnoerror++;
}
if (!(intStat & (ISTAT_RXE | ISTAT_TXE)))
pDrvCtrl->lastIntError = 0;
if (intStat & ISTAT_PRX)
{
int recvLen = 0;
pDrvCtrl->current = ne2000GetCurr (pDrvCtrl);
ENDLOGMSG(("ne2000Int: input packet (flags=%x, current=%d)\n",
pDrvCtrl->flags, pDrvCtrl->current, 0, 0, 0, 0));
if (!(pDrvCtrl->flags & END_RECV_HANDLING_FLAG))
{
/* Disable RX int */
pDrvCtrl->imask &= ~IM_PRXE;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
pDrvCtrl->flags |= END_RECV_HANDLING_FLAG;
#ifdef _USE_RECV_DMA_
if(pDrvCtrl->current>= pDrvCtrl->nextPacket)
{
recvLen = (pDrvCtrl->current-pDrvCtrl->nextPacket)*RECV_PAGE_SIZE;
}
else
{
recvLen = ((NE2000_PSTOP-pDrvCtrl->nextPacket)+(pDrvCtrl->current-NE2000_PSTART))*RECV_PAGE_SIZE;
}
ne2000DmaRecv(pDrvCtrl , (((UINT)pDrvCtrl->nextPacket << 8) & 0x0000ffff)
, recvLen);
#else
(void)netJobAdd ((FUNCPTR)ne2000HandleRcvInt, (int)pDrvCtrl,
0,0,0,0);
#endif
}
}
if ((intStat & (ISTAT_TXE | ISTAT_PTX)) != 0)
{
#ifndef _USE_SND_DMA_
pDrvCtrl->flags &= ~END_TX_IN_PROGRESS;
ENDLOGMSG (("ne2000Int: Tx complete, blocked=%d\n",
(pDrvCtrl->flags & END_TX_BLOCKED) ? 1 : 0,0,0,0,0,0));
#else
if(pDrvCtrl->bufCount< SAVE_SND_NUM)
{
ne2000DmaSend(pDrvCtrl , (NE2000_TSTART << 8));
}
else
{
pDrvCtrl->flags &= ~END_TX_IN_PROGRESS;
}
#endif
if (pDrvCtrl->flags & END_TX_BLOCKED)
{
pDrvCtrl->imask &= ~(IM_TXEE | IM_PTXE);
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
pDrvCtrl->flags &= ~END_TX_BLOCKED;
netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj,
0, 0, 0, 0);
}
}
/* Flush the write pipe */
CACHE_PIPE_FLUSH ();
}
/*******************************************************************************
*
* ne2000HandleRcvInt - task level interrupt service for input packets
*
* This routine is called at task level indirectly by the interrupt
* service routine to do any message received processing.
*
* RETURNS: N/A.
*/
LOCAL void ne2000HandleRcvInt
(
NE2000END_DEVICE *pDrvCtrl
)
{
int oldLevel;
char *pBuf;
UCHAR currNo ;
UCHAR bnry ;
UCHAR stat;
int errFlag = FALSE;
ENDLOGMSG (("ne2000HandleRcvInt(%x): enter (flags=%x)\n",
pDrvCtrl,pDrvCtrl->flags,0,0,0,0));
pBuf = NULL;
while ((pDrvCtrl->flags & END_RECV_HANDLING_FLAG) || (pDrvCtrl->flags &END_OVERWRITE2))
{
int len;
CL_BLK_ID pClBlk;
M_BLK_ID pMblk; /* MBLK to send upstream */
SYS_IN_CHAR (pDrvCtrl, ENE_BOUND , &bnry);
if (pDrvCtrl->nextPacket == pDrvCtrl->current)
break;
if (pDrvCtrl->flags & END_OVERWRITE)
break;
if (!pBuf)
{
pBuf = netClusterGet (pDrvCtrl->endObj.pNetPool,
pDrvCtrl->clPoolId);
if (!pBuf)
{
errFlag = TRUE;
break;
}
}
len = ne2000PacketGet (pDrvCtrl, pBuf + pDrvCtrl->offset);
if (len <= 0)
{
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
errFlag = TRUE;
break;
}
pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool,
M_DONTWAIT, MT_DATA);
if (!pMblk)
{
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
errFlag = TRUE;
break;
}
pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT);
if (!pClBlk)
{
netMblkFree (pDrvCtrl->endObj.pNetPool, (M_BLK_ID)pMblk);
errFlag = TRUE;
break;
}
netClBlkJoin (pClBlk, pBuf, NE2000_BUFSIZ, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkPktHdr.len = len;
pMblk->mBlkHdr.mData += pDrvCtrl->offset;
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);
pBuf = NULL;
}
if (pBuf)
netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *) pBuf);
oldLevel = intLock ();
pDrvCtrl->flags &= ~END_RECV_HANDLING_FLAG;
pDrvCtrl->imask |= IM_PRXE;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
if(pDrvCtrl->flags &END_OVERWRITE2 )
{
currNo = ne2000GetCurr(pDrvCtrl);
SYS_IN_CHAR (pDrvCtrl, ENE_BOUND , &bnry);
if(TRUE == errFlag)
{
if(NE2000_PSTART ==currNo )
{
bnry = NE2000_PSTOP-1;
}
else
{
bnry = currNo-1;
}
SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND , bnry);
}
SYS_IN_CHAR (pDrvCtrl, ENE_INTSTAT, &stat);
SYS_OUT_CHAR (pDrvCtrl, ENE_INTSTAT, stat);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCON, 0x00);
pDrvCtrl->imask = NE2000_ALL_INTS;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
pDrvCtrl->flags &= ~END_OVERWRITE2;
}
intUnlock (oldLevel);
}
/*******************************************************************************
*
* ne2000DataIn - input bytes from NE2000 memory
*
* NOMANUAL
*/
LOCAL void ne2000DataIn
(
NE2000END_DEVICE * pDrvCtrl,
int eneAddress,
int len,
char * pData
)
{
if (len == 0)
{
return;
}
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, eneAddress & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, eneAddress >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RREAD | CMD_START);
SYS_IN_WORD_STRING (pDrvCtrl, ENE_DATA, pData, len/2);
if (len & 1)
SYS_IN_CHAR (pDrvCtrl, ENE_DATA, (pData + (len - 1)));
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
}
/*******************************************************************************
*
* ne2000DataOut - output bytes to NE2000 memory
*
* NOMANUAL
*/
void ne2000DmaInit()
{
#ifdef _USE_SND_DMA_
(void) intConnect (INUM_TO_IVEC(INT_VEC_DMA3),ne2000DmaSendInt, (int)0);
intEnable (INT_LVL_DMA3);
#endif
#ifdef _USE_RECV_DMA_
(void) intConnect (INUM_TO_IVEC(INT_VEC_DMA0),ne2000DmaRecvInt, (int)0);
intEnable (INT_LVL_DMA0);
#endif
}
#ifdef _USE_SND_DMA_
void ne2000DmaSendInt()
{
ENDLOGMSG (("into ne2000DmaSendInt.\n", 0, 0, 0, 0, 0, 0));
SYS_OUT_CHAR (gpDeviceCtrl, ENE_TSTART, NE2000_TSTART);
SYS_OUT_CHAR (gpDeviceCtrl, ENE_TCNTH,
gpDeviceCtrl->packetLen[gpDeviceCtrl->useHead] >> 8);
SYS_OUT_CHAR (gpDeviceCtrl, ENE_TCNTL,
gpDeviceCtrl->packetLen[gpDeviceCtrl->useHead] & 0xff);
if(gpDeviceCtrl->bufCount >=(SAVE_SND_NUM-1) )
{
gpDeviceCtrl->useHead = 0x5a;
gpDeviceCtrl->bufCount = SAVE_SND_NUM;
}
else
{
if(gpDeviceCtrl->useHead >= (SAVE_SND_NUM-1))
{
gpDeviceCtrl->useHead = 0;
}
else
{
gpDeviceCtrl->useHead++;
}
gpDeviceCtrl->bufCount++;
}
CACHE_PIPE_FLUSH ();
SYS_OUT_CHAR (gpDeviceCtrl, ENE_CMD, CMD_TXP | CMD_START);
}
void ne2000DmaSend(NE2000END_DEVICE* pDrvCtrl , int eneAddress)
{
char *sndBuf = NULL;
int sndLen = 0;
ENDLOGMSG (("into ne2000DmaSend.\n", 0, 0, 0, 0, 0, 0));
sndBuf = pDrvCtrl->packetBuf[pDrvCtrl->useHead];
sndLen = pDrvCtrl->packetLen[pDrvCtrl->useHead];
if (sndLen == 0)
{
ENDLOGMSG (("ne2000DmaSend:send len is 0.\n", 0, 0, 0, 0, 0, 0));
return;
}
if(rNE2000_DSTAT3 & 0xfffff)
{
ENDLOGMSG (("ne2000DmaSend:dma can not op.\n", 0, 0, 0, 0, 0, 0));
return ;
}
pDrvCtrl->flags |= END_TX_IN_PROGRESS;
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, eneAddress & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, eneAddress >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, sndLen & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, sndLen >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RWRITE | CMD_START);
rNE2000_DISRC3 = (int)sndBuf;
rNE2000_DISRCC3 = (0x0<<1) + 0x0;
rNE2000_DIDST3 = ((U32)(pDrvCtrl)->base+ (int)ENE_DATA);
rNE2000_DIDSTC3 = (0x0<<1)+0x1;
rNE2000_DCON3 = ((unsigned)1<<31)+(1<<30)+(1<<29)+(0<<28)+(1<<27)+(0<<23)+(1<<22)+(0<<20)+sndLen;/*((len-0x30)/2);*/
rNE2000_DMASKTRIG3 = (0x0<<2) + (0x1<<1) + (0x1<<0);
}
#else
void ne2000DmaSendInt()
{
}
void ne2000DmaSend(NE2000END_DEVICE* pDev , char *srcBuf , int sndLen)
{
if(rNE2000_DSTAT3 & 0xfffff)
{
return ;
}
rNE2000_DISRC3 = (int)srcBuf;
rNE2000_DISRCC3 = (0x0<<1) + 0x0;
rNE2000_DIDST3 = ((U32)(pDev)->base+ (int)ENE_DATA);
rNE2000_DIDSTC3 = (0x0<<1)+0x1;
rNE2000_DCON3 = ((unsigned)1<<31)+(1<<30)+(1<<29)+(0<<28)+(1<<27)+(0<<23)+(1<<22)+(0<<20)+sndLen;/*((len-0x30)/2);*/
rNE2000_DMASKTRIG3 = (0x0<<2) + (0x1<<1) + (0x1<<0);
}
#endif
#ifdef _USE_RECV_DMA_
void ne2000DmaRecvInt()
{
gpDeviceCtrl->nextMapPage = 0;
(void)netJobAdd ((FUNCPTR)ne2000HandleRcvInt, (int)gpDeviceCtrl,
0,0,0,0);
}
void ne2000DmaRecv(NE2000END_DEVICE *pDrvCtrl,int eneAddress,int len)
{
ENDLOGMSG (("into ne2000DmaRecv.\n", 0, 0, 0, 0, 0, 0));
if (len == 0)
{
pDrvCtrl->flags &= ~END_RECV_HANDLING_FLAG;
pDrvCtrl->imask |= IM_PRXE;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
return;
}
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, eneAddress & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, eneAddress >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RREAD | CMD_START);
rNE2000_DISRC0 = ((U32)(pDrvCtrl)->base+ (int)ENE_DATA);
rNE2000_DISRCC0 = (0x0<<1) + 0x1;
rNE2000_DIDST0 = ((U32)pDrvCtrl->recvMapBuf[0]);
rNE2000_DIDSTC0 = (0x0<<1)+0x0;
rNE2000_DCON0 = ((unsigned)1<<31)+(1<<30)+(1<<29)+(0<<28)+(1<<27)+(0<<23)+(1<<22)+(0<<20)+len;/*((len-0x30)/2);*/
rNE2000_DMASKTRIG0 = (0x0<<2) + (0x1<<1) + (0x1<<0);
}
#endif
/*******************************************************************************
*
* ne2000OpenRecvIntLog - output bytes to NE2000 memory
*
* NOMANUAL
*/
void ne2000OpenRecvIntLog()
{
recvIntLog = TRUE;
}
/*******************************************************************************
*
* ne2000DataOut - output bytes to NE2000 memory
*
* NOMANUAL
*/
LOCAL void ne2000DataOut
(
NE2000END_DEVICE * pDrvCtrl,
char * pData,
int len,
int eneAddress
)
{
ENDLOGMSG (("into ne2000DataOut.\n", 0, 0, 0, 0, 0, 0));
if (len == 0)
return;
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, (char)0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, eneAddress & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, eneAddress >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RWRITE | CMD_START);
#ifndef _USE_SND_DMA_
#ifndef _UNUSE_SND_DMA_
ne2000DmaSend(pDrvCtrl , pData , len);
#else
SYS_OUT_WORD_STRING (pDrvCtrl, ENE_DATA, pData, len/2);
if (len & 1)
SYS_OUT_CHAR (pDrvCtrl, ENE_DATA, *(pData + (len - 1)));
#endif
#endif
}
/*******************************************************************************
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS ne2000Send
(
void* pCookie,
M_BLK_ID pMblk
)
{
int len;
UCHAR cmdStat;
int level = 0;
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
ENDLOGMSG (("ne2000Send: enter: (flags=%x, imask=%x)\n",
pDrvCtrl->flags, pDrvCtrl->imask, 0, 0, 0, 0));
if (pDrvCtrl->flags & (END_OVERWRITE | END_OVERWRITE2))
{
return (END_ERR_BLOCK);
}
END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
#ifndef _USE_SND_DMA_
pDrvCtrl->flags |= END_TX_BLOCKED;
#endif
#ifndef _USE_SND_DMA_
if (pDrvCtrl->flags & END_TX_IN_PROGRESS)
{
int cnt;
ENDLOGMSG (("ne2000Send: waiting for TX_IN_PROGRESS\n",
0,0,0,0,0,0));
cnt = sysClkRateGet ();
while ((pDrvCtrl->flags & END_TX_IN_PROGRESS) && (cnt-- > 0))
{
taskDelay (1);
}
}
#endif
#ifndef _USE_SND_DMA_
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
if (pDrvCtrl->flags & (END_OVERWRITE | END_OVERWRITE2))
{
ENDLOGMSG (("ne2000Send: overwrite detected (timeout)\n",
0, 0, 0, 0, 0, 0));
pDrvCtrl->flags &= ~END_TX_BLOCKED;
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
return (END_ERR_BLOCK);
}
#endif
#ifndef _USE_SND_DMA_
if (pDrvCtrl->flags & END_TX_IN_PROGRESS)
{
UCHAR tstat;
SYS_IN_CHAR (pDrvCtrl, ENE_TSTAT, &tstat);
SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
ENDLOGMSG (("ne2000Send: timeout: flags=%x cmd=%02x stat=%02x\n",
pDrvCtrl->flags, cmdStat, tstat, 0, 0, 0));
ne2000Config (pDrvCtrl, FALSE);
}
#endif
#ifndef _USE_SND_DMA_
len = netMblkToBufCopy (pMblk, pDrvCtrl->packetBuf, NULL);
netMblkClChainFree (pMblk);
len = max (len, ETHERSMALL);
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0x00);
ne2000DataOut (pDrvCtrl, pDrvCtrl->packetBuf, len, (NE2000_TSTART << 8));
CACHE_PIPE_FLUSH ();
SYS_OUT_CHAR (pDrvCtrl, ENE_TSTART, NE2000_TSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTH, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTL, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_TXP | CMD_START);
pDrvCtrl->flags |= END_TX_IN_PROGRESS;
pDrvCtrl->imask |= (IM_TXEE | IM_PTXE);
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
#else
level = intLock ();
if(pDrvCtrl->bufCount>0)
{
len = netMblkToBufCopy (pMblk,
pDrvCtrl->packetBuf[pDrvCtrl->freeHead], NULL);
len = max (len, ETHERSMALL);
pDrvCtrl->packetLen[pDrvCtrl->freeHead] = len;
if(0x5a == pDrvCtrl->useHead )
{
pDrvCtrl->useHead = pDrvCtrl->freeHead;
}
if(pDrvCtrl->freeHead>= (SAVE_SND_NUM -1))
{
pDrvCtrl->freeHead =0;
}
else
{
pDrvCtrl->freeHead++;
}
pDrvCtrl->bufCount--;
intUnlock(level);
}
else
{
intUnlock(level);
return (END_ERR_BLOCK);
}
netMblkClChainFree (pMblk);
if (!(pDrvCtrl->flags & END_TX_IN_PROGRESS))
{
ne2000DmaSend(pDrvCtrl , (NE2000_TSTART << 8));
}
#endif
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
ENDLOGMSG (("ne2000Send: done: imask=%02x\n",
pDrvCtrl->imask, 0, 0, 0, 0, 0));
return (OK);
}
/*******************************************************************************
*
*
* RETURNS: ptr to next packet, or NULL if none ready.
*/
LOCAL int ne2000PacketGet
(
NE2000END_DEVICE *pDrvCtrl,
char *pData
)
{
UINT packetSize;
UCHAR uppByteCnt;
UINT8 tempPage;
UINT8 pageCount;
UINT packetLen = 0;
NE2000_HEADER h;
char tmpData[2048];
int tmpDataLen = 0;
ENDLOGMSG (("into ne2000PacketGet.\n", 0, 0, 0, 0, 0, 0));
if (pDrvCtrl->nextPacket == pDrvCtrl->current)
return (0);
#ifdef _USE_RECV_DMA_
memcpy(&h , pDrvCtrl->recvMapBuf[pDrvCtrl->nextMapPage] , sizeof (NE2000_HEADER));
#else
ne2000DataIn (pDrvCtrl,
(((UINT)pDrvCtrl->nextPacket << 8) & 0x0000ffff),
sizeof (NE2000_HEADER), (char *) &h);
#endif
if (h.next > pDrvCtrl->nextPacket)
uppByteCnt = (UCHAR) (h.next - pDrvCtrl->nextPacket);
else
uppByteCnt = (UCHAR) ((NE2000_PSTOP - pDrvCtrl->nextPacket)
+ (h.next - NE2000_PSTART));
if (h.lowByteCnt > 0xfc)
uppByteCnt -= 2;
else
uppByteCnt -= 1;
h.uppByteCnt = uppByteCnt;
packetSize = (((UINT)h.uppByteCnt << 8) + h.lowByteCnt) - 4;
pageCount = (UCHAR) ((packetSize + 4 + sizeof (NE2000_HEADER)
+ (ENE_PAGESIZE - 1)) / ENE_PAGESIZE);
tempPage = (UCHAR) (pDrvCtrl->nextPacket + pageCount);
if (tempPage >= NE2000_PSTOP)
tempPage -= (NE2000_PSTOP - NE2000_PSTART);
if ((h.next != tempPage) ||
(h.next < NE2000_PSTART) || (h.next >= NE2000_PSTOP))
{
pDrvCtrl->stats.badPacket++;
pDrvCtrl->stats.rerror++;
if (!(pDrvCtrl->flags & (END_OVERWRITE|END_OVERWRITE2)))
ne2000Config (pDrvCtrl, TRUE);
return (-1);
}
if (packetSize < 60)
{
pDrvCtrl->stats.shortPacket++;
goto doneGet;
}
if (packetSize > NE2000_BUFSIZ)
goto doneGet;
if (h.rstat & RSTAT_PRX)
{
if (h.rstat & (RSTAT_DFR | RSTAT_DIS))
{
pDrvCtrl->stats.badPacket++;
pDrvCtrl->stats.rerror++;
goto doneGet;
}
pDrvCtrl->stats.rnoerror++;
}
else
{
if (h.rstat & RSTAT_DFR)
pDrvCtrl->stats.jabber++;
pDrvCtrl->stats.rerror++;
goto doneGet;
}
packetLen = packetSize;
#ifdef _USE_RECV_DMA_
memcpy(pData , pDrvCtrl->recvMapBuf[pDrvCtrl->nextMapPage]+sizeof (NE2000_HEADER) , packetLen);
#else
tmpDataLen = ((packetLen+sizeof(NE2000_HEADER))/256+1)*256-sizeof(NE2000_HEADER);
ne2000DataIn (pDrvCtrl,
((UINT)pDrvCtrl->nextPacket << 8) + sizeof (NE2000_HEADER),
tmpDataLen,
tmpData);
memcpy(pData , tmpData , packetLen);
ENDLOGMSG (("into ne2000PacketGet.nextMapPage = %d:len = %d:tmplen = %d.\n", pDrvCtrl->nextPacket
, tmpDataLen , packetLen, 0, 0, 0));
#endif
doneGet:
#ifdef _USE_RECV_DMA_
if( pDrvCtrl->nextPacket<= h.next)
{
pDrvCtrl->nextMapPage += (h.next-pDrvCtrl->nextPacket);
}
else
{
pDrvCtrl->nextMapPage += ((NE2000_PSTOP-pDrvCtrl->nextPacket)+
(h.next-NE2000_PSTART));
}
#endif
pDrvCtrl->nextPacket = h.next;
SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND,
(pDrvCtrl->nextPacket != NE2000_PSTART ?
pDrvCtrl->nextPacket - 1 : NE2000_PSTOP - 1));
return (packetLen);
}
/******************************************************************************
*
* device.
*/
LOCAL STATUS ne2000PollRecv
(
void* pCookie,
M_BLK_ID pMblk
)
{
int len;
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
ENDLOGMSG (("into ne2000PollRecv.\n", 0, 0, 0, 0, 0, 0));
pDrvCtrl->current = ne2000GetCurr (pDrvCtrl);
if (pDrvCtrl->nextPacket == pDrvCtrl->current)
return ((STATUS) (EAGAIN));
if ((pMblk->mBlkHdr.mLen < NE2000_BUFSIZ)
|| !(pMblk->mBlkHdr.mFlags & M_EXT))
{
return ((STATUS) (EAGAIN));
}
ENDLOGMSG (("ne2000PollRecv: enter: imask=%02x\n",
pDrvCtrl->imask, 0, 0, 0, 0, 0));
len = ne2000PacketGet (pDrvCtrl, pMblk->mBlkHdr.mData + pDrvCtrl->offset);
if (len <= 0)
return ((STATUS) (EAGAIN));
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkPktHdr.len = len;
pMblk->mBlkHdr.mData += pDrvCtrl->offset;
ENDLOGMSG (("ne2000PollRecv: done: imask=%02x\n",
pDrvCtrl->imask, 0, 0, 0, 0, 0));
return (OK);
}
/*******************************************************************************
*
* device.
*/
static STATUS ne2000PollSend
(
void* pCookie,
M_BLK_ID pMblk
)
{
char * pBuf;
UCHAR cmdStat;
int len;
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
ENDLOGMSG (("ne2000PollSend: enter: imask=%x flags=%x\n",
pDrvCtrl->imask, pDrvCtrl->flags, 0, 0, 0, 0));
SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
while (cmdStat & CMD_TXP)
SYS_IN_CHAR (pDrvCtrl, ENE_DATA, &cmdStat);
#ifdef _USE_SND_DMA_
pBuf = pDrvCtrl->packetBuf[0];
#else
pBuf = pDrvCtrl->packetBuf;
#endif
len = netMblkToBufCopy (pMblk, pBuf, NULL);
len = max (len, ETHERSMALL);
#ifdef _USE_SND_DMA_
ne2000DataOut (pDrvCtrl, pDrvCtrl->packetBuf[0], len, (NE2000_TSTART << 8));
#else
ne2000DataOut (pDrvCtrl, pDrvCtrl->packetBuf, len, (NE2000_TSTART << 8));
#endif
CACHE_PIPE_FLUSH ();
SYS_OUT_CHAR (pDrvCtrl, ENE_TSTART, NE2000_TSTART);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTH, len >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTL, len & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_TXP | CMD_START);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
CACHE_PIPE_FLUSH ();
SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
while (cmdStat & CMD_TXP)
SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
ENDLOGMSG (("ne2000PollSend: done: imask=%x flags=%x\n",
pDrvCtrl->imask, pDrvCtrl->flags, 0, 0, 0, 0));
return (OK);
}
/*******************************************************************************
*
* ne2000PollStart - start polled mode operations
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS ne2000PollStart
(
NE2000END_DEVICE* pDrvCtrl
)
{
int oldLevel;
oldLevel = intLock ();
ENDLOGMSG (("ne2000PollStart: imask=%x flags=%x\n",
pDrvCtrl->imask, pDrvCtrl->flags, 0, 0, 0, 0));
pDrvCtrl->flags |= END_POLLING;
pDrvCtrl->imask = 0;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
intUnlock (oldLevel);
return (OK);
}
/*******************************************************************************
*
* ne2000PollStop - stop polled mode operations
*
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS ne2000PollStop
(
NE2000END_DEVICE* pDrvCtrl
)
{
int oldLevel;
oldLevel = intLock ();
pDrvCtrl->flags &= ~END_POLLING;
pDrvCtrl->imask = NE2000_ALL_INTS;
if (pDrvCtrl->flags & END_RECV_HANDLING_FLAG)
pDrvCtrl->imask &= ~IM_PRXE;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
ENDLOGMSG (("ne2000PollStop: imask=%x flags=%x\n",
pDrvCtrl->imask, pDrvCtrl->flags, 0, 0, 0, 0));
intUnlock (oldLevel);
return (OK);
}
/******************************************************************************
*
* ne2000AddrFilterSet - set the address filter for multicast addresses
*
*
* NOMANUAL
*/
LOCAL void ne2000AddrFilterSet
(
NE2000END_DEVICE *pDrvCtrl
)
{
int i;
int eAddr;
u_char enetChar;
u_char *pCp;
u_long crc;
ETHER_MULTI* pCurr;
ENDLOGMSG (("ne2000AddrFilterSet\n", 0, 0, 0, 0, 0, 0));
for (i = 0; i < 8; ++i)
pDrvCtrl->mcastFilter[i] = 0;
for (pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);
pCurr != NULL;
pCurr = END_MULTI_LST_NEXT(pCurr))
{
pCp = (unsigned char *)&pCurr->addr;
crc = 0xffffffff;
for (eAddr = 0; eAddr < 6; eAddr++)
{
enetChar = *pCp++;
crc = ne2000CrcWork (enetChar, crc);
}
crc >>= 26;
crc &= 0x3f;
pDrvCtrl->mcastFilter[crc >> 3] |= (1 << (crc & 7));
}
}
/*****************************************************************************
*
* ne2000CrcWork - return CRC using a 32 bit polynomial
*
*
* NOMANUAL
*
*/
LOCAL UINT32 ne2000CrcWork
(
UINT8 inChar,
UINT32 inCrc
)
{
UINT8 work = 0;
UINT8 wrap;
int i;
ENDLOGMSG (("into ne2000CrcWork.\n", 0, 0, 0, 0, 0, 0));
for (i = 0; i < 8; i++)
{
wrap = (inCrc >> 31);
inCrc <<= 1;
work = ((work << 1) | wrap) ^ inChar;
if (work & 1)
{
inCrc ^= CRC32_POLYNOMIAL;
}
work >>= 1;
inChar >>= 1;
}
return (inCrc);
}
/*****************************************************************************
*
* ne2000MCastAdd - add a multicast address for the device
*
*/
LOCAL STATUS ne2000MCastAdd
(
void* pCookie, /* device ptr */
char* pAddress
)
{
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
ENDLOGMSG (("ne2000MCastAdd - %02x:%02x:%02x:%02x:%02x:%02x\n",
pAddress[0]&0xff, pAddress[1]&0xff, pAddress[2]&0xff,
pAddress[3]&0xff, pAddress[4]&0xff, pAddress[5]&0xff));
if (etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddress) == ENETRESET)
{
}
return (OK);
}
/*****************************************************************************
*
* ne2000MCastDel - delete a multicast address for the device
*
*/
LOCAL STATUS ne2000MCastDel
(
void* pCookie, /* device ptr */
char* pAddress
)
{
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
ENDLOGMSG (("ne2000MCastDel - %02x:%02x:%02x:%02x:%02x:%02x\n",
pAddress[0]&0xff, pAddress[1]&0xff, pAddress[2]&0xff,
pAddress[3]&0xff, pAddress[4]&0xff, pAddress[5]&0xff));
if (etherMultiDel (&pDrvCtrl->endObj.multiList,
(char *)pAddress) == ENETRESET)
{
}
return (OK);
}
/*****************************************************************************
*
* ne2000MCastGet - get the multicast address list for the device
*
*/
LOCAL STATUS ne2000MCastGet
(
void* pCookie, /* device ptr */
MULTI_TABLE* pTable
)
{
int error;
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
ENDLOGMSG (("ne2000MCastGet\n", 0, 0, 0, 0, 0, 0));
error = etherMultiGet (&pDrvCtrl->endObj.multiList, pTable);
return (error);
}
/******************************************************************************
*
* ne2000Stop - stop the device
*
* RETURNS: OK or ERROR
*/
LOCAL STATUS ne2000Stop
(
void *pCookie
)
{
STATUS result = OK;
NE2000END_DEVICE* pDrvCtrl;
ENDLOGMSG (("into ne2000Stop.\n", 0, 0, 0, 0, 0, 0));
pDrvCtrl = (NE2000END_DEVICE *) pCookie;
END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING);
pDrvCtrl->imask = 0;
SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP);
ENDLOGMSG (("ne2000Stop\n", 0, 0, 0, 0, 0, 0));
SYS_INT_DISCONNECT (pDrvCtrl, ne2000Int, (int)pDrvCtrl, &result);
if (result == ERROR)
ENDLOGMSG (("Could not disconnect interrupt!\n", 1, 2, 3, 4, 5, 6));
return (result);
}
/******************************************************************************
*
* ne2000Unload - unload a driver from the system
*
*/
LOCAL STATUS ne2000Unload
(
void *pCookie
)
{
NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
ENDLOGMSG (("ne2000Unload\n", 0, 0, 0, 0, 0, 0));
END_OBJECT_UNLOAD (&pDrvCtrl->endObj); /* generic end unload functions */
return (OK);
}
/******************************************************************************
*
* ne2000EnetAddrGet - get enet address
*
* NOMANUAL
*/
LOCAL void ne2000EnetAddrGet
(
NE2000END_DEVICE* pDrvCtrl
)
{
int i;
ENDLOGMSG (("into ne2000EnetAddrGet.\n", 0, 0, 0, 0, 0, 0));
bcopyBytes ((char *) (0x7e000), &(MAC_INFO),sizeof(MAC_INFO));
if ((MAC_INFO.macshowinfo[0] !=0)||(MAC_INFO.macshowinfo[1] !=0)||(MAC_INFO.macshowinfo[2] !=0)||(MAC_INFO.macshowinfo[3] !=0)||(MAC_INFO.macshowinfo[4] !=0)||(MAC_INFO.macshowinfo[5] !=0))
{
for (i = 0; i < 6; ++i)
ne2000EnetAddr[i] = MAC_INFO.macshowinfo[i];
}
else
{
for (i = 0; i < 6; ++i)
MAC_INFO.macshowinfo[i] = ne2000EnetAddr[i];
SST39VF160_ChipProg(0x3F000,&(MAC_INFO),sizeof(MAC_INFO));
}
if (pDrvCtrl->usePromEnetAddr)
{
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, NE2000_EADDR_LOC);
SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, NE2000_CONFIG_PAGE);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, (EADDR_LEN * 2) & 0xff);
SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, (EADDR_LEN * 2) >> 8);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RREAD | CMD_START);
for (i = 0; i < 6; ++i)
{
char ch;
SYS_IN_CHAR (pDrvCtrl, ENE_DATA, &pDrvCtrl->enetAddr[i]);
if (pDrvCtrl->byteAccess)
SYS_IN_CHAR (pDrvCtrl, ENE_DATA, &ch);
}
for (i = 0; i < 6; ++i)
if (pDrvCtrl->enetAddr[i])
return;
}
for (i = 0; i < 6; ++i)
pDrvCtrl->enetAddr[i] = ne2000EnetAddr[i];
}
/******************************************************************************
*
* ne2000GetCurr - get current page
*
* RETURNS: current page that ENE is working on
*
* NOMANUAL
*/
LOCAL UCHAR ne2000GetCurr
(
NE2000END_DEVICE* pDrvCtrl
)
{
UCHAR curr;
ENDLOGMSG (("into ne2000GetCurr.\n", 0, 0, 0, 0, 0, 0));
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE1);
SYS_IN_CHAR (pDrvCtrl, ENE_CURR, &curr);
SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE0);
return (curr);
}