📄 dp8381~1.c
字号:
/* dp83815End.c - dp83815 END network interface driver *//* Copyright 1984-1997 Wind River Systems, Inc. *//* Copyright 1999 TeamF1, Inc. *//*modification history--------------------01b,09aug99,mpy added poll support, fixed 01a,19jul99,mpy written by TeamF1 Inc, for National Semiconductor.*//*DESCRIPTIONThis module implements an END-style ethernet driver for the dp83815 PCIethernet device. Packet descriptors and data are transferred viabus-mastering, reducing the burden on the host CPU. The DP83815 can supportfull duplex 10/100 Mbps transmission and reception.The DP83815 driver is developed for use on VxWorks targets. It can beconfigured with a vxWorks (Tornado 2.0) pc486 BSP. The driver is capableof 10/100 Mbps Full/Half duplex mode operation via an internal PHY. BOARD LAYOUTThis is a chip specific driver, and hence contains no board specificinformation.CHIP FEATURES:..IPThe chip is bus-master capable and transfers packet descriptorsand data using DMA with burst sizes upto 128 words...IPIt supports 10 Mbps Ethernet and 100 Mbps Fast Ethernet via an internalPHY and emerging 1-2 Mbps home networking solutions via external PHY...IPFlexible Rx packet filtration including: perfect match, broadcast,multicast/unicast hash table, deep packet pattern matching...IPInternal Tx and Rx data FIFOs of 2KB each..iP802.3u Auto-Negotiation - advertised features configurable via EEPROM..iPFull duplex support for 10 and 100Mb/s data ratesSUPPORTED DRIVER FEATURES:The driver supports the following features:..IP "o 10 Mbps full duplex and half duplex"..IP "o 100 Mbps full duplex and half duplex"..IP "o Auto Negotiation"..IP "o Broadcast and perfect match transmit and receive"..IP "o ARP transmit and receive"..IP "o Promiscuous mode"..IP "o Multicast support"..IP "o Endian, and CPU architecture neutral"..IP "o Poll mode interface for system debugging"UNSUPPORTED FEATURES..IP "o ACPI"..IP "o Multiple ethernet addresses"..IP "o Wake on LAN and OnNow support for PC98/99, and other power-management features."..IP "o Magic packets with SecureON, VLAN"..IP "o Programming EEPROM/Flash"..IP "o Remote boot"DRIVER OPERATIONThe entry point to the driver from the MUX layer is the dp83815Load() routinewhich initializes the device and the driver to an operational state. Thedp83815Load() routine gets parameters via the <initString> and by calling aBSP routine, sysDp83815ParamGet().The driver makes use of two types of buffers for each device, DMA buffers andnon-DMA buffers. DMA buffers are used to allocate receive and transmitdescriptors, and buffers (clusters); while non-DMA buffers are used toallocate other management data viz., m-blocks, cluster blocks, and deviceobjects.The receive and transmit descriptors are arranged in two circularsingle-linked rings. While the transmit and receive buffers (clusters),cluster blocks, and m-blocks are managed by a vxWorks netpool. The descriptorrings are shared between the driver and the device. The device accesses thesedescriptors via DMA.During the initialization of the transmit and receive rings, anmBlk-clBlk-cluster construct is allocated and associated with each descriptor.The driver single-threads transmit operations. All transmit buffers are copiedinto the drivers transmit queue, while all receive buffers are loaned with nocopy to the upper layers.The driver makes use of appropriate macros to adjust for endian-ness of thehost CPU, PCI bus, Ethernet, and the DP device. It also performs appropriatetranslations of addresses for device use. These builtin features make thedriver extremely portable to run on various CPUs with minimum changes.DEVICE PARAMETERSThe <initString>, parameter to dp83815Load(), is used to specify thenumber of the transmit and recieve descriptors and the number of clusters fora device. The default number is defined by the macros, DP_RX_DESC_DEFAULT andDP_TX_DESC_DEFAULT. While the default number of clusters, clCount, iscalculated using,..CS (txDescCount + rxDescCount + DP_CL_EXTRA_DEFAULT)..CE The size of DMA buffer allocated for a device is calculated by,..CS ((clCount * (DP_BUF_SIZE + (2 * DP_ALIGN))) + \ ((rxDescCount + txDescCount) * (DP_QUEUE_ELE_SIZE)) + (2 * DP_ALIGN))..CE The first line in the above rule calculates the space needed for all transmitand recive buffers. An extra, DP_CL_EXTRA_DEFAULT, number of buffers are alsoallocated to enable buffers to be loaned to the upper layers. The second linein the rule calculates the space needed for transmit and receive queues.The driver allocates a DMA buffer of the required size if the buffer addressis specified either as NONE (-1) or NULL (0) in the <initString>. Otherwisethe address is assumed to point to a memory region which is cache-safe, and ofthe required size. Refer to the manual pages of dp83815Load() for moredetails.EXTERNAL SUPPORT REQUIREMENTSThe macros SYS_INT_CONNECT, SYS_INT_DISCONNECT, and SYS_INT_ENABLE allow thedriver to be customized for BSPs that use special versions of these routines.The macro SYS_INT_CONNECT is used to connect the interrupt handler tothe appropriate vector. By default it calls the routine intConnect().The macro SYS_INT_DISCONNECT is used to disconnect the interrupt handler priorto unloading the module. By default this is a dummy routine thatreturns OK.The macro SYS_INT_ENABLE is used to enable the interrupt level for theend device. It is called once during initialization. By default this isthe routine sysLanIntEnable(), defined in the BSP module `sysLib.c'.The macro SYS_ENET_ADDR_GET is used to get the ethernet address (MAC)for the device. The single argument to this routine is the END_DEVICEpointer. This macro, by default, calls the routine, sysDp83815EnetAddrGet().The driver uses the following external routines:..CS sysIntEnablePIC (int ilevel) sysDp83815EnetAddrGet (int unit, char *pEnetAddr) sysDp83815ParamGet (int unit, DP83815_PARAM *pParam)..CEThe routine sysIntEnablePIC() is used to enable interrupts at the specifiedinterrupt level. Routine sysDp83815EnetAddrGet() is called when the devicedoes not contain a valid ethernet address. The routine, sysDp83815ParamGet()is used to get the device specific parameters. The structure DP83815_PARAM isdefined in the driver header file, dp83815End.h.INCLUDES:end.h endLib.h etherMultiLib.h drv/end/dp83815End.hSEE ALSO: muxLib, endLib, netBufLibREFERENCES:..iP..I "Writing and Enhanced Network Driver"..iP..I "National Semiconductor DP83815 10/100 Mb/s Integrated PCI Ethernet Media Access Controller and Physical Layer, 1998."*//* includes */#include "vxWorks.h"#include "stdlib.h"#include "cacheLib.h"#include "intLib.h"#include "end.h" /* Common END structures. */#include "endLib.h"#include "lstLib.h" /* Needed to maintain protocol list. */#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 "net/unixLib.h"#include "net/protosw.h"#include "net/systm.h"#include "net/if_subr.h"#include "net/route.h"#include "sys/socket.h"#include "sys/ioctl.h"#include "sys/times.h"#include "drv/end/dp83815End.h"IMPORT int endMultiLstCnt (END_OBJ* pEnd);void mydelay(){ long i; for(i=0;i<0x1000;i++);}/* defines *//* Configuration items */#define END_SPEED_10M 10000000 /* 10Mbs */#define END_SPEED_100M 100000000 /* 100Mbs */#define END_SPEED END_SPEED_100M #define DP83815_MIN_FBUF 1500/* Cache macros */#define END_CACHE_INVALIDATE(address, len) \ CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))#define END_CACHE_FLUSH(address, len) \ CACHE_DRV_FLUSH (&pDrvCtrl->cacheFuncs, (address), (len))#define END_CACHE_PHYS_TO_VIRT(address) \ CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))#define END_CACHE_VIRT_TO_PHYS(address) \ CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))#define END_CACHE_VIRT_TO_BUS(address) \ (END_CACHE_VIRT_TO_PHYS(address) + pDrvCtrl->pciMemBase )#define END_CACHE_BUS_TO_VIRT(address) \ (END_CACHE_PHYS_TO_VIRT(address - pDrvCtrl->pciMemBase))/* * SWAP_BUS_TO_CPU_XX and SWAP_CPU_TO_BUS_XX macros swap 16 and 32 bit values * between the PCI bus's little endian byte-order and the CPU's native * byte-order. */#if (_BYTE_ORDER == _BIG_ENDIAN)#define BUS_TO_CPU_SWAP_16(X) swap16(X)#define BUS_TO_CPU_SWAP_32(X) swap32(X)#define CPU_TO_BUS_SWAP_16(X) swap16(X)#define CPU_TO_BUS_SWAP_32(X) swap32(X)#define CPU_TO_NET_SWAP_16(X) ((UINT16)(X))#define CPU_TO_NET_SWAP_32(X) ((UINT32)(X))#define NET_TO_CPU_SWAP_16(X) ((UINT16)(X))#define NET_TO_CPU_SWAP_32(X) ((UINT32)(X))#else /* (_BYTE_ORDER == _BIG_ENDIAN) */#define BUS_TO_CPU_SWAP_32(X) ((UINT32)(X))#define BUS_TO_CPU_SWAP_16(X) ((UINT16)(X))#define CPU_TO_BUS_SWAP_32(X) ((UINT32)(X))#define CPU_TO_BUS_SWAP_16(X) ((UINT16)(X))#define CPU_TO_NET_SWAP_16(X) swap16(X)#define CPU_TO_NET_SWAP_32(X) swap32(X)#define NET_TO_CPU_SWAP_16(X) swap16(X)#define NET_TO_CPU_SWAP_32(X) swap32(X)#endif /* (_BYTE_ORDER == _BIG_ENDIAN) *//* Macros to read/write 16/32 values at given io address *//*#define IO_READ_16(io_port) sysInWord((int) io_port)#define IO_WRITE_16(io_port, data) sysOutWord((int) io_port, data)#define IO_READ_32(io_port) sysInLong((int) io_port)#define IO_WRITE_32(io_port, data) sysOutLong((int) io_port, data)*/#define IO_READ_16(io_port) pciIoInWord((int) io_port)#define IO_WRITE_16(io_port, data) pciIoOutWord((int) io_port, data)#define IO_READ_32(io_port) pciIoInLong((long) io_port)#define IO_WRITE_32(io_port, data) pciIoOutLong((long) io_port, data)/* Macros to translate addresses between PCI bus and CPU */#define BUS_TO_CPU_ADDR_XLATE(X) BUS_TO_CPU_SWAP_32(END_CACHE_BUS_TO_VIRT(X))#define CPU_TO_BUS_ADDR_XLATE(X) CPU_TO_BUS_SWAP_32(END_CACHE_VIRT_TO_BUS(X))/* Macros to read/write 32/16 bit data to/from DP83815 device registers */#define DP_REG32_WRITE(reg, val) IO_WRITE_32 (iobase+(reg), \ CPU_TO_BUS_SWAP_32(val))#define DP_REG32_READ(reg) BUS_TO_CPU_SWAP_32(IO_READ_32 (iobase+(reg)))#define DP_REG16_WRITE(reg, val) IO_WRITE_16 (iobase+(reg), \ CPU_TO_BUS_SWAP_16(val))#define DP_REG16_READ(reg) BUS_TO_CPU_SWAP_16(IO_READ_16 (iobase+(reg)))#define DP_REG32_SET(reg, val) DP_REG32_WRITE(reg,DP_REG32_READ(reg)|(val))#define DP_REG32_CLR(reg, val) DP_REG32_WRITE(reg,DP_REG32_READ(reg)&~(val))#define DP_REG16_SET(reg, val) DP_REG16_WRITE(reg,DP_REG16_READ(reg)|(val))#define DP_REG16_CLR(reg, val) DP_REG16_WRITE(reg,DP_REG16_READ(reg)&~(val))/* * Default macro definitions for BSP interface. * These macros can be redefined in a wrapper file, to generate * a new module with an optimized interface. *//* Macro to connect interrupt handler to vector */#ifndef SYS_INT_CONNECT# define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) \ { \ IMPORT STATUS sysIntConnect(); \ *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), \ rtn, (int)arg); \ }#endif/* Macro to disconnect interrupt handler from vector */LOCAL VOID dummyIsr (void) { };#ifndef SYS_INT_DISCONNECT# define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) \ { \ IMPORT STATUS intConnect(); \ *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), \ dummyIsr, (int)arg); \ }#endif/* Macro to enable the appropriate interrupt level */STATUS sysIntEnablePIC (int intLevel) {return intEnable(intLevel);}#ifndef SYS_INT_ENABLE# define SYS_INT_ENABLE(pDrvCtrl) \ { \ sysIntEnablePIC (pDrvCtrl->ilevel);\ }#endif/* Macro to get the ethernet address from the BSP */#ifndef SYS_ENET_ADDR_GET# define SYS_ENET_ADDR_GET(pDevice) \ { \ unsigned char sysDp83815EnetAddr[6]; \ void sysDp83815EnetAddrGet(); \ sysDp83815EnetAddrGet (pDevice->unit, sysDp83815EnetAddr); \ bcopy ((char *)sysDp83815EnetAddr, (char *)(&pDevice->enetAddr), 6); \ }#endif/* * Macros to do a short (UINT16) access to the chip. Default * assumes a normal memory mapped device. */#ifndef DP83815_OUT_SHORT# define DP83815_OUT_SHORT(pDrvCtrl,addr,value) \ (*(USHORT *)addr = value)#endif#ifndef DP83815_IN_SHORT# define DP83815_IN_SHORT(pDrvCtrl,addr,pData) \ (*pData = *addr)#endif/* A shortcut for getting the hardware address from the MIB II stuff. */#define END_HADDR(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)#define END_HADDR_LEN(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)/* Set the the specified bit in a table */#define SET_BIT(bit, tbl) (*((UINT32*)(tbl)+(bit)/32) |= (UINT32)(1<<(bit)%32))/* data types */typedef volatile UINT8 * VIRT_ADDR; /* CPU virtual address */typedef volatile UINT8 * BUS_ADDR; /* BUS physical address *//* Driver private descriptor macros */#define DP_DESC_MBLKPTR 0x0c /* MBLK pointer offset */#define DP_QUEUE_ELE_NEXT(q) \ q->curDescAddr = DP_QUEUE_ELE_NEXT_GET(q, q->curDescAddr)#define DP_QUEUE_ELE_NEXT_GET(q, descAddr) \ ((descAddr) == (q)->lastDescAddr) ? (q)->firstDescAddr :\ ((descAddr) + DP_QUEUE_ELE_SIZE)#define UDELAY(x) \ { \ int i; \ for (i=0; i< (3*x); i++) \ { \ mydelay(); \ } \ } /* sysDelay(); */ /* Macros to get/set the values of the descriptor fields */#define DP_DESC_LNK_GET(ptr) *(UINT32 *)((VIRT_ADDR)ptr + DP_DESC_LNK)#define DP_DESC_CMDSTS_GET(ptr) *(UINT32 *)((VIRT_ADDR)ptr + DP_DESC_CMDSTS)#define DP_DESC_BUFPTR_GET(ptr) *(UINT32 *)((VIRT_ADDR)ptr + DP_DESC_BUFPTR)#define DP_DESC_MBLKPTR_GET(ptr) *(M_BLK_ID*)((VIRT_ADDR)ptr + DP_DESC_MBLKPTR)#define DP_DESC_LNK_SET(ptr, val) DP_DESC_LNK_GET(ptr) = (val)#define DP_DESC_CMDSTS_SET(ptr, val) DP_DESC_CMDSTS_GET(ptr) = (val)#define DP_DESC_BUFPTR_SET(ptr,val) DP_DESC_BUFPTR_GET(ptr) = (val)#define DP_DESC_MBLKPTR_SET(ptr,val) DP_DESC_MBLKPTR_GET(ptr) = (val)/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -