📄 dm9000xend.c
字号:
/*dm9000xend.c*/#include "vxWorks.h"#include "iv.h"#include "vme.h"#include "net/mbuf.h"#include "lstLib.h"#include "semLib.h"#include "sys/times.h"#include "net/unixLib.h"#include "net/protosw.h"#include "sys/socket.h"#include "sys/ioctl.h"#include "errno.h"#include "memLib.h"#include "intLib.h"#include "net/route.h"#include "iosLib.h"#include "errnoLib.h"#include "logLib.h"#include "cacheLib.h"#include "netLib.h"#include "stdio.h"#include "stdlib.h"#include "sysLib.h"#include "etherLib.h"#include "net/systm.h"#include "net/if_subr.h"#include "config.h"#undef ETHER_MAP_IP_MULTICAST#include "etherMultiLib.h"#include "end.h"#include "endLib.h"#include "dm9000xEnd.h"#include "config.h"#ifdef INCLUDE_DM_END/*#define CONFIG_DM9K_BASE (0x10000000+(1<<23)+0x300)*/#define CONFIG_DM9K_BASE (0x10000000+0x300)#define DM9000_DEV_NAME "dm"#define DM9000_DEV_NAME_LEN 3#define DM9000_EADR_LEN 6#define DM9000_SPEED 10000000 /* 10Mbps or 100Mbps *//* Board/System/Debug information/definition ---------------- */#define ADVERTISE_SLCT 0x001f /* Selector bits */#define ADVERTISE_CSMA 0x0001 /* Only selector supported */#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */#define ADVERTISE_RESV 0x1c00 /* Unused... */#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */#define ADVERTISE_NPAGE 0x8000 /* Next page bit */#define BMCR_RESV 0x003f /* Unused... */#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */#define BMCR_CTST 0x0080 /* Collision test */#define BMCR_FULLDPLX 0x0100 /* Full duplex */#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */#define BMCR_SPEED100 0x2000 /* Select 100Mbps */#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */#define BMCR_RESET 0x8000 /* Reset the DP83840 */#define MII_BMCR 0x00 /* Basic mode control register */#define MII_BMSR 0x01 /* Basic mode status register */#define MII_PHYSID1 0x02 /* PHYS ID 1 */#define MII_PHYSID2 0x03 /* PHYS ID 2 */#define MII_ADVERTISE 0x04 /* Advertisement control reg */#define MII_LPA 0x05 /* Link partner ability reg */#define MII_EXPANSION 0x06 /* Expansion register */#define MII_DCOUNTER 0x12 /* Disconnect counter */#define MII_FCSCOUNTER 0x13 /* False carrier counter */#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */#define MII_RERRCOUNTER 0x15 /* Receive error counter */#define MII_SREVISION 0x16 /* Silicon revision */#define MII_RESV1 0x17 /* Reserved... */#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */#define MII_PHYADDR 0x19 /* PHY address */#define MII_RESV2 0x1a /* Reserved... */#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */#define MII_NCONFIG 0x1c /* Network interface config */#define DM9000_REG00 0x00#define DM9000_REG05 0x30 /* SKIP_CRC/SKIP_LONG */#define DM9000_REG08 0x27#define DM9000_REG09 0x38#define DM9000_REG0A 0xff#define DM9000_REGFF 0x83 /* IMR */#define DM9000_PHY 0x40 /* PHY address 0x01 */#define TRUE 1#define FALSE 0#define CARDNAME "dm9000"#define DMFE_TIMER_WUT jiffies+(HZ*2) /* timer wakeup time : 2 second */#define DMFE_TX_TIMEOUT (HZ*2) /* tx packet time-out time 1.5 s" */#define DMFE_DEBUG 0#ifndef SYS_ENET_ADDR_GET#define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress) \ do { \ IMPORT STATUS sysEnetAddrGet (int, char*); \ sysEnetAddrGet (pDrvCtrl->unit, pAddress); \ } while (0)#endif /* SYS_ENET_ADDR_GET */enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD = 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO = 8, DM9000_1M_HPNA = 0x10};typedef struct dm9000_end_device /* driver control structure */ { END_OBJ endObj; /* The class we inherit from. */ int unit; /* unit number */ UCHAR enetAddr[DM9000_EADR_LEN]; /* ethernet address */ CL_POOL_ID pClPoolId; /* cluster pool Id */ M_CL_CONFIG mClCfg; /* mBlk & cluster config structure */ CL_DESC clDesc; /* cluster descriptor table */ u32 ioaddr; /* Register I/O base address */ u32 io_data; /* Data I/O address */ u16 irq; /* IRQ */ u8 op_mode; /* PHY operation mode */ u8 reg0, reg5, reg8, reg9, rega; /* registers saved */ int flags; u8 io_mode; /* 0:word, 2:byte */ } DM9000_END_DEVICE;/* Global variable declaration ----------------------------- */static int dmfe_debug = 0;/* For module input parameter */static int media_mode = DM9000_AUTO;static u8 reg5 = DM9000_REG05;static u8 reg8 = DM9000_REG08;static u8 reg9 = DM9000_REG09;static u8 rega = DM9000_REG0A;/* function declaration ------------------------------------- */static int dmfe_probe(DM9000_END_DEVICE *pDrvCtrl);static int dmfe_open(DM9000_END_DEVICE *pDrvCtrl);static int dmfe_start_xmit(M_BLK* pMblk, DM9000_END_DEVICE *pDrvCtrl);static int dmfe_stop( DM9000_END_DEVICE *pDrvCtrl);static void dmfe_interrupt(DM9000_END_DEVICE *pDrvCtrl);static void dmfe_init_dm9000(DM9000_END_DEVICE *pDrvCtrl);static u8 ior(DM9000_END_DEVICE *pDrvCtrl, int);static void iow(DM9000_END_DEVICE *pDrvCtrl, int reg, int value);static int dmfe_phy_read(DM9000_END_DEVICE *pDrvCtrl, int phyaddr_unsused, int reg);static void dmfe_phy_write(DM9000_END_DEVICE *pDrvCtrl, int phyaddr_unused, int reg, int value);static u16 read_srom_word(DM9000_END_DEVICE *pDrvCtrl, int);static void dmfe_rx(DM9000_END_DEVICE *pDrvCtrl);static void dm9000_hash_table(DM9000_END_DEVICE *pDrvCtrl);LOCAL STATUS dm9000InitParse(DM9000_END_DEVICE * pDrvCtrl,char * initString);LOCAL STATUS dm9000InitMem(DM9000_END_DEVICE * pDrvCtrl);LOCAL void dm9000EnetAddrGet(DM9000_END_DEVICE*pDrvCtrl, char*addr);LOCAL STATUS dm9000PollStart(DM9000_END_DEVICE* pDrvCtrl);LOCAL STATUS dm9000PollStop(DM9000_END_DEVICE* pDrvCtrl);static void dmfe_shutdown(DM9000_END_DEVICE *pDrvCtrl);static void dmfe_mx1_ins(u_long ioaddr, u_char * buf, int len);#define DRV_FLAGS_SET(setBits) \ (pDrvCtrl->flags |= (setBits))#define DRV_FLAGS_ISSET(setBits) \ (pDrvCtrl->flags & (setBits))#define DRV_FLAGS_CLR(clrBits) \ (pDrvCtrl->flags &= ~(clrBits))#define DRV_FLAGS_GET() \ (pDrvCtrl->flags)#define DM9000_IS_IN_POLL_MODE() \ ((DRV_FLAGS_GET() & NS83902_FLAG_POLL) == DM9000_FLAG_POLL)#define DM9000_SEM_TAKE(pDrvCtrl, timeout) \ semTake ((pDrvCtrl)->endObj.txSem, timeout)#define DM9000_SEM_GIVE(pDrvCtrl) \ semGive((pDrvCtrl)->endObj.txSem)/* 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)#define END_FLAGS_ISSET(pEnd, setBits) \ ((pEnd)->flags & (setBits))/* network buffers configuration */M_CL_CONFIG dm9000MclBlkConfig = /* network mbuf configuration table */ { /* no. mBlks no. clBlks memArea memSize --------- ---------- ------- ------- */ 100, 100, NULL, 0 };CL_DESC dm9000ClDescTbl [] = /* cluster pool configuration table */ { /* clSize num memArea memSize ------ ---- ------- ------- */ {2048, 100, NULL, 0} }; int dm9000ClDescTblNumEnt = (NELEMENTS(dm9000ClDescTbl));/* DM9000 network board routine ---------------------------- */LOCAL STATUS dm9000Start ( DM9000_END_DEVICE *pDrvCtrl );LOCAL STATUS dm9000Stop ( DM9000_END_DEVICE* pDrvCtrl );LOCAL STATUS dm9000Unload ( DM9000_END_DEVICE* pDrvCtrl );LOCAL int dm9000Ioctl ( DM9000_END_DEVICE* pDrvCtrl, int cmd, caddr_t data );LOCAL STATUS dm9000Send ( DM9000_END_DEVICE* pDrvCtrl, M_BLK* pMblk );LOCAL STATUS dm9000MCastAddrAdd ( DM9000_END_DEVICE* pDrvCtrl, char * pAddr );LOCAL STATUS dm9000MCastAddrDel ( DM9000_END_DEVICE* pDrvCtrl, char * pAddr );LOCAL STATUS dm9000MCastAddrGet ( DM9000_END_DEVICE* pDrvCtrl, MULTI_TABLE * pTable );LOCAL STATUS dm9000PollSend ( DM9000_END_DEVICE* pDrvCtrl, M_BLK* pMblk );LOCAL STATUS dm9000PollReceive ( DM9000_END_DEVICE* pDrvCtrl, M_BLK* pMblk );LOCAL void dm9000Int ( DM9000_END_DEVICE* pDrvCtrl );/* * Declare our function table. This is static across all driver * instances. */LOCAL NET_FUNCS dm9000FuncTable = { (FUNCPTR)dm9000Start, /* Function to start the device. */ (FUNCPTR)dm9000Stop, /* Function to stop the device. */ (FUNCPTR)dm9000Unload, /* Unloading function */ (FUNCPTR)dm9000Ioctl, /* Ioctl function */ (FUNCPTR)dm9000Send, /* Send function */ (FUNCPTR)dm9000MCastAddrAdd, /* Multicast address add */ (FUNCPTR)dm9000MCastAddrDel, /* Multicast address delete */ (FUNCPTR)dm9000MCastAddrGet, /* Multicast table retrieve */ (FUNCPTR)dm9000PollSend, /* Polling send function */ (FUNCPTR)dm9000PollReceive, /* Polling receive function */ endEtherAddressForm, /* Put address info into a packet. */ endEtherPacketDataGet, /* Get a pointer to packet data. */ endEtherPacketAddrGet, /* Get packet addresses. */ NULL /* Bind function */ };DM9000_END_DEVICE *temp;/******************************************************************************** dm9000EndLoad - 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>.* 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, "ln") 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* dm9000EndLoad ( char* initString /* string to be parsed */ ) { DM9000_END_DEVICE *pDrvCtrl; if (initString == NULL) return (NULL); if (initString[0] == '\0') { bcopy((char *)DM9000_DEV_NAME, initString, DM9000_DEV_NAME_LEN); return (0); } /* allocate the device structure */ pDrvCtrl = (DM9000_END_DEVICE *)calloc (sizeof (DM9000_END_DEVICE), 1); if (pDrvCtrl == NULL) goto errorExit; /* parse the init string, filling in the device structure */ if (dm9000InitParse (pDrvCtrl, initString) == ERROR) { printf("index error.\n\r"); goto errorExit; } /* Have the BSP hand us our address. *//* pDrvCtrl->enetAddr[0] = 0x00; pDrvCtrl->enetAddr[1] = 0x00; pDrvCtrl->enetAddr[2] = 0x3e; pDrvCtrl->enetAddr[3] = 0x26; pDrvCtrl->enetAddr[4] = 0x0a; pDrvCtrl->enetAddr[5] = 0x00;*/ dm9000EnetAddrGet (pDrvCtrl, (char*) &(pDrvCtrl->enetAddr));/* printf ( "ENET Addr: %x:%x:%x:%x:%x:%x \n", pDrvCtrl->enetAddr[0], pDrvCtrl->enetAddr[1], pDrvCtrl->enetAddr[2], pDrvCtrl->enetAddr[3], pDrvCtrl->enetAddr[4], pDrvCtrl->enetAddr[5]);*/ /* initialize the END and MIB2 parts of the structure */ if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, DM9000_DEV_NAME, pDrvCtrl->unit, &dm9000FuncTable, "dm9000 Network Driver") == ERROR || END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd, &pDrvCtrl->enetAddr[0], DM9000_EADR_LEN, ETHERMTU, DM9000_SPEED) == ERROR) goto errorExit; /* Perform memory allocation */ if (dm9000InitMem (pDrvCtrl) == ERROR) { goto errorExit; } /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST); /* save the device address */ dmfe_probe(pDrvCtrl); temp = pDrvCtrl;#if 1 return (&pDrvCtrl->endObj);errorExit: dm9000Unload (pDrvCtrl); return NULL; #endif }/********************************************************************************* ns83902InitParse - parse the initialization string** Parse the input string and fill in values in the driver control structure.** RETURNS: OK, or ERROR if any arguments are invalid.*/LOCAL STATUS dm9000InitParse ( DM9000_END_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; }/********************************************************************************* ns83902InitMem - initialize memory for NIC chip** Using data in the control structure, setup and initialize the memory* areas needed. If the memory address is not already specified, then allocate* cache safe memory.** RETURNS: OK or ERROR.*/LOCAL STATUS dm9000InitMem ( DM9000_END_DEVICE * pDrvCtrl /* device to be initialized */ ) { /* allocate netpool */ if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); /* Set number of M-Blks and CL-Blks*/ /* Calculate the total memory for all the M-Blks and CL-Blks. */ dm9000MclBlkConfig.memSize = dm9000MclBlkConfig.mBlkNum * (MSIZE + sizeof (long)) + dm9000MclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)); /* allocate memory for M-Blks and CL-Blks */ dm9000MclBlkConfig.memArea = (char *) memalign (sizeof(long), dm9000MclBlkConfig.memSize); if (dm9000MclBlkConfig.memArea == NULL) return (ERROR); /* Calculate the memory size of all the clusters. */ dm9000ClDescTbl[0].memSize = sizeof(long) + dm9000ClDescTbl[0].clNum * (dm9000ClDescTbl[0].clSize + 8); /* Allocate memory for clusters */ dm9000ClDescTbl[0].memArea = (char *) memalign (sizeof(long), dm9000ClDescTbl[0].memSize); if (dm9000ClDescTbl[0].memArea == NULL) { return (ERROR); } /* Save clusters start address for later use */ /* Initialize the net buffer pool with buffers */ if (netPoolInit (pDrvCtrl->endObj.pNetPool, &dm9000MclBlkConfig, &dm9000ClDescTbl[0], dm9000ClDescTblNumEnt, NULL) == ERROR) { return (ERROR); } /* Store the cluster pool id as others need it later. */ pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool, dm9000ClDescTbl[0].clSize, FALSE); if (pDrvCtrl->pClPoolId == NULL) return (ERROR); return (OK); }/********************************************************************************* ns83902EnetAddrGet - get the Ethernet address.** Get ethernet address from the BSP.** RETURNS: N/A.*/LOCAL void dm9000EnetAddrGet ( DM9000_END_DEVICE* pDrvCtrl, char* addr ) {#if _BYTE_ORDER == _BIG_ENDIAN /* For big endian we need to swap byte order */ int i; char bytes[6]; SYS_ENET_ADDR_GET (pDrvCtrl, bytes); for (i=0; i<6; i++) *addr++ = bytes[5-i];#else /* _BYTE_ORDER == _LITTLE_ENDIAN */ /* Little endian is in correct order */ SYS_ENET_ADDR_GET (pDrvCtrl, addr);#endif /* _BYTE_ORDER == _BIG_ENDIAN */ }/********************************************************************************* ns83902Start - start the device
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -