📄 dm9000end.c
字号:
/* dm9000End.c - dm9000 END network interface driver for MagicARM2410 */
/* V1.0 2008/03/20 */
#include "copyright_wrs.h"
#include "vxWorks.h"
#include "stdlib.h"
#include "cacheLib.h"
#include "intLib.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 "netBufLib.h"
#include "sysLib.h"
#include "errno.h"
#include "errnoLib.h"
#include "memLib.h"
#include "iosLib.h"
#undef ETHER_MAP_IP_MULTICAST
#include "etherMultiLib.h"
#include "end.h"
#include "muxLib.h"
#include "net/mbuf.h"
#include "net/if_subr.h"
#include "net/route.h"
#include "netinet/in.h"
#include "net/unixLib.h"
#include "net/protosw.h"
#include "net/systm.h"
#include "sys/socket.h"
#include "sys/ioctl.h"
#include "sys/times.h"
#include "arpLib.h"
#include "s3c2410x.h"
#include "stdio.h"
#include "string.h"
#define rpGPFCON (*(volatile unsigned *)0x56000050)
#define rpGPFUP (*(volatile unsigned *)0x56000058)
#define rpINTMSK (*(volatile unsigned *)0X4A000008)
#define rpINTPND (*(volatile unsigned *)0X4a000010)
#define rpSRCPND (*(volatile unsigned *)0X4a000000)
/* defines */
#define DM9000_REG00 0x00
#define DM9000_REG05 0x11
#define DM9000_REG05_OFF 0x00
#define DM9000_REGFF 0x83
#define DM9000_REGFF_OFF 0x80
#define DM9000_PHY 0x40
#define DM9000_PHY_OFF 0x01
#define DM9000_PHY_ON 0x00
#define DM9000_PKT_MAX 1536
#define DM9000_PKT_RDY 0x01
#define DM9000_10MHD 0x00
#define DM9000_100MHD 0x01
#define DM9000_10MFD 0x04
#define DM9000_100MFD 0x05
#define DM9000_AUTO 0x08
#define DM9008A 0x10
#define DM900xA_PCEL 0x15
#define DM9000_MEDIA_MODE DM9000_100MFD
/*DM9000 ADDRS*/
#define DM9000_IOADDR 0x18000300
#define DM9000_IODATA 0x18000304
/*DM9000 Tx buffer size*/
#define DM9000_FRAME_BUFSIZE 30000
#define DM9000_DEV_NAME "dmf"
#define DM9000_DEV_NAME_LEN 4
/*DM9000 MAC address */
unsigned char dmfEnetAddr [6] = {0x00, 0x13, 0xf6, 0x6c, 0x87, 0x90};
#ifndef ETHERMTU
#define ETHERMTU (1500)
#endif
#define END_BUFSIZ (1500 + 14 + 6)
#define EH_SIZE (14)
#define END_SPEED_10M 10000000
#define END_SPEED_100M 100000000
#define END_SPEED END_SPEED_100M
#define END_HADDR(pEnd) \
((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
#define END_HADDR_LEN(pEnd) \
((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
#define sysOutByte(port,data) (*(volatile UCHAR *)(port) = (UCHAR)(data))
#define sysInByte(port) (*(volatile UCHAR *)(port))
#define sysOutWord(port,data) (*(volatile USHORT *)(port) = (USHORT)(data))
#define sysInWord(port) (*(volatile USHORT *)(port))
#ifndef DM9000_OUT_REG
#define DM9000_OUT_REG(addr,value)\
{ \
sysOutByte( DM9000_IOADDR, addr);\
sysOutByte( DM9000_IODATA, value);\
}
#endif
#ifndef DM9000_IN_REG
#define DM9000_IN_REG(addr,data)\
{ \
sysOutByte( DM9000_IOADDR, addr);\
data = sysInByte(DM9000_IODATA);\
}
#endif
#ifndef DM9000_IN_ADDR
#define DM9000_IN_ADDR( addr ) \
addr = sysInByte(DM9000_IOADDR);
#endif
#ifndef DM9000_OUT_ADDR
#define DM9000_OUT_ADDR( addr ) \
sysOutByte(DM9000_IOADDR,addr);
#endif
#ifndef DM9000_IN_BYTE
#define DM9000_IN_BYTE( data ) \
data=sysInByte(DM9000_IODATA);
#endif
#ifndef DM9000_OUT_BYTE
#define DM9000_OUT_BYTE( data ) \
sysOutByte(DM9000_IODATA, data);
#endif
#ifndef DM9000_IN_WORD
#define DM9000_IN_WORD( data ) \
data = sysInWord( DM9000_IODATA);
#endif
#ifndef DM9000_OUT_WORD
#define DM9000_OUT_WORD( data ) \
sysOutWord( (DM9000_IODATA),data);
#endif
typedef struct end_device
{
END_OBJ end; /* The class we inherit from. */
int unit; /* unit number */
int ivec; /* interrupt vector */
int ilevel; /* interrupt level */
long flags; /* Our local flags. */
UCHAR enetAddr[6]; /* ethernet address */
CACHE_FUNCS cacheFuncs; /* cache function pointers */
CL_POOL_ID pClPoolId; /* cluster pool */
BOOL rxHandling; /* rcv task is scheduled */
UINT IOBase;
UCHAR io_mode; /* 0:word, 2:byte */
char tx_pkt_cnt;
USHORT queue_pkt_len;
UCHAR op_mode; /* PHY operation mode */
UCHAR mcastFilter[8]; /* multicast filter */
} END_DEVICE;
/*
* This will only work if there is only a single unit, for multiple
* unit device drivers these should be integrated into the END_DEVICE
* structure.
*/
M_CL_CONFIG dm9000MclBlkConfig = /* network mbuf configuration table */
{
/*
no. mBlks no. clBlks memArea memSize
---------- --------- ------- -------
*/
2048, 256, NULL, 0
};
CL_DESC dm9000ClDescTbl [] = /* network cluster pool configuration table */
{
/*
clusterSize num memArea memSize
----------- ---- ------- -------
*/
{2048, 128, NULL, 0}
};
int dm9000ClDescTblNumEnt = (NELEMENTS(dm9000ClDescTbl));
/* Definitions for the flags field */
#define DM9000_PROMISCUOUS 0x01
#define DM9000_POLLING 0x02
/* Status register bits, returned by dm9000StatusRead() */
#define DM9000_RINT 0x01 /* Rx interrupt pending */
#define DM9000_TINT 0x02 /* Tx interrupt pending */
#define DM9000_VALID_INT 0x03 /* Any valid interrupt pending */
#define DM9000_RXON 0x04 /* Rx on (enabled) */
#define DM9000_TFULL 0x08 /* tx full */
#define DM9000_RXRDY 0x10 /* data rdy */
#define DM9000_MIN_FBUF (30000) /* min first buffer size */
/* DEBUG MACROS */
#define DM_DEBUG_PRINT
#undef DM_DEBUG_PRINT
/* LOCALS */
/* forward static functions */
static void dmfe_reset_dm9000( END_DEVICE *dev );
static void dmfe_config_dm9000( END_DEVICE *dev, int oo);
static int dmfe_Copy_TxFrame( END_DEVICE *dev, char *pBuffer, int TxLen);
static int dmfe_Copy_RxFrame( END_DEVICE *dev, char *pBuffer ,UCHAR rxbyte);
static UCHAR dmfe_Get_NextPacket(void);
static int dmfe_Stop_Chip(END_DEVICE *dev);
static void set_PHY_mode( END_DEVICE *dev );
static USHORT phy_read( END_DEVICE *dev, int reg );
static void phy_write( END_DEVICE *dev, int reg, USHORT value);
static void uDelay( int us );
static void dmfGetPhyAndMulAdrs(END_DEVICE *dev);
static void dm9000Reset(END_DEVICE *pDrvCtrl);
static void dm9000Config(END_DEVICE *pDrvCtrl);
static void dm9000Int(END_DEVICE *pDrvCtrl);
static STATUS dm9000Recv(END_DEVICE *pDrvCtrl);
static UINT dm9000StatusRead(END_DEVICE *pDrvCtrl);
LOCAL void s3cExtIntPinEnable(void);
static void dm9000Chack(void);
/* This is the only externally visible interface. */
END_OBJ * sysEtherEndLoad (char *initString, void *pBSP);
static STATUS dm9000Start(END_DEVICE *pV);
static STATUS dm9000Stop(END_DEVICE *pV);
static int dm9000Ioctl(END_DEVICE *pV, int cmd, caddr_t data);
static STATUS dm9000Unload(END_DEVICE *pV );
static STATUS dm9000Send(END_DEVICE *pV, M_BLK_ID pBuf);
static STATUS dm9000MCastAdd(END_DEVICE *pV, char *pAddress);
static STATUS dm9000MCastDel(END_DEVICE *pV, char *pAddress);
static STATUS dm9000MCastGet(END_DEVICE *pV, MULTI_TABLE *pTable);
static STATUS dm9000PollStart(END_DEVICE *pV);
static STATUS dm9000PollStop(END_DEVICE *pV);
static STATUS dm9000PollSend(END_DEVICE *pV, M_BLK_ID pBuf);
static STATUS dm9000PollRcv(END_DEVICE *pV, M_BLK_ID pBuf);
static void dm9000AddrFilterSet(END_DEVICE *pDrvCtrl);
static STATUS dm9000Parse( END_DEVICE *pDrvCtrl, char *initString );
static STATUS dm9000MemInit( END_DEVICE *pDrvCtrl);
/*
* Declare our function table. This is static across all driver
* instances.
*/
static NET_FUNCS dm9000FuncTable =
{
(FUNCPTR) dm9000Start, /* Function to start the device. */
(FUNCPTR) dm9000Stop, /* Function to stop the device. */
(FUNCPTR) dm9000Unload, /* Unloading function for the driver. */
(FUNCPTR) dm9000Ioctl, /* Ioctl function for the driver. */
(FUNCPTR) dm9000Send, /* Send function for the driver. */
(FUNCPTR) dm9000MCastAdd, /* Multicast add function for the */
/* driver. */
(FUNCPTR) dm9000MCastDel, /* Multicast delete function for */
/* the driver. */
(FUNCPTR) dm9000MCastGet, /* Multicast retrieve function for */
/* the driver. */
(FUNCPTR) dm9000PollSend, /* Polling send function */
(FUNCPTR) dm9000PollRcv, /* Polling receive function */
endEtherAddressForm, /* put address info into a NET_BUFFER */
endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
endEtherPacketAddrGet /* Get packet addresses. */
};
/*******************************************************************************
*
* sysEtherEndLoad - initialize the driver and device
*
* This routine initializes the driver and the device to the operational state.
* All of the device specific parameters are passed in the initString.
*
* The string contains the target specific parameters like this:
*
* "register addr:int vector:int level:shmem addr:shmem size:shmem width"
*
* RETURNS: An END object pointer or NULL on error.
*/
END_OBJ* sysEtherEndLoad( char *initString, void *pBSP ) /* String to be parsed by the driver. */
{
END_DEVICE *pDrvCtrl;
int i;
#ifdef DM_DEBUG_PRINT
logMsg("DM9000 loading Now...\n", 0, 0, 0, 0, 0, 0);
#endif
if (initString == NULL)
{
#ifdef DM_DEBUG_PRINT
logMsg("sysEtherEndLoad Error: initString is NULL...\n", 0, 0, 0, 0, 0, 0);
#endif
return (NULL);
}
if (initString[0] == '\0')
{
bcopy((char *)DM9000_DEV_NAME, initString, DM9000_DEV_NAME_LEN);
#ifdef DM_DEBUG_PRINT
logMsg("sysEtherEndLoad: DM9000 Device Name String is 0...\n", 0, 0, 0, 0, 0, 0);
#endif
return ((END_OBJ*)OK);
}
/* allocate the device structure */
pDrvCtrl = (END_DEVICE *)calloc(sizeof (END_DEVICE), 1);
if (pDrvCtrl == NULL)
{
#ifdef DM_DEBUG_PRINT
logMsg("sysEtherEndLoad: calloc() == NULL\n", 0, 0, 0, 0, 0, 0);
#endif
goto errorExit;
}
pDrvCtrl->flags = 0;
pDrvCtrl->op_mode = DM9000_MEDIA_MODE;
pDrvCtrl->io_mode = 0;
/* parse the init string, filling in the device structure */
if (dm9000Parse(pDrvCtrl, initString) == ERROR)
{
#ifdef DM_DEBUG_PRINT
logMsg("sysEtherEndLoad: Parse Error!\n", 0, 0, 0, 0, 0, 0);
#endif
goto errorExit;
}
/* Ask the BSP to provide the ethernet address. */
bcopyBytes((char *)dmfEnetAddr,(char *)pDrvCtrl->enetAddr,6);
#ifdef DM_DEBUG_PRINT
for(i=0;i<6;i++)
logMsg("%x \n",pDrvCtrl->enetAddr[i],0,0,0,0,0);
#endif
/*Verify that it is the correct chip*/
dm9000Chack();
/* initialize the END and MIB2 parts of the structure
* The M2 element must come from m2Lib.h
* This dm9000 is set up for a DIX type ethernet device.
*/
if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, DM9000_DEV_NAME,
pDrvCtrl->unit, &dm9000FuncTable,"dm9000 END Driver.") == ERROR
|| END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
(UCHAR*)&(pDrvCtrl->enetAddr[0]), 6, 1500,
END_SPEED) == ERROR)
{
#ifdef DM_DEBUG_PRINT
logMsg("sysEtherEndLoad: END_OBJ_INIT() or END_MIB_INIT() failed!\n", 0, 0, 0, 0, 0, 0);
#endif
goto errorExit;
}
/* Perform memory allocation/distribution */
if (dm9000MemInit (pDrvCtrl) == ERROR)
{
goto errorExit;
}
/* reset and reconfigure the device */
dm9000Reset (pDrvCtrl);
dmfe_config_dm9000( pDrvCtrl, 1 );
/* set the flags to indicate readiness */
END_OBJ_READY (&pDrvCtrl->end,
IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX);
#ifdef DM_DEBUG_PRINT
logMsg("Dm9000 Loading Sucessfull!\n", 0, 0, 0, 0, 0, 0);
#endif
return (&pDrvCtrl->end);
errorExit:
if (pDrvCtrl != NULL)
free ((char *)pDrvCtrl);
return NULL;
}
/*******************************************************************************
*
* dm9000Parse - parse the init string
*
* Parse the input string. Fill in values in the driver control structure.
*
* The muxLib.o module automatically prepends the unit number to the user's
* initialization string from the BSP (configNet.h).
*
* RETURNS: OK or ERROR for invalid arguments.
*/
static STATUS dm9000Parse( END_DEVICE *pDrvCtrl, /* device pointer */
char *initString ) /* information string */
{
char * tok;
char * pHolder = NULL;
long address;
/* Unit number. */
tok = strtok_r (initString, ":", &pHolder);
if (tok == NULL) return ERROR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -