📄 if_fei.c
字号:
/* if_fei.c - Intel 82557 Ethernet network interface driver *//* Copyright 1998 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01q,28apr99,dat Merge from 2_0_001s,09mar99,cn added support for shared PCI interrupts (SPR# 24379).01r,14dec98,n_s fixed feiInit to properly set promiscuous mode. spr 24000.01q,16oct98,cn changed default to be BSD44_DRIVER, as 01o did not do it. Suppressed warning in feiIoctl() (SPR# 21880).01p,30sep98,cn moved call to I82557_INT_DISABLE after sys557Init() (SPR# 21879). Also suppressed some warnings (SPR# 21880).01o,16apr98,dat changed default to be BSD44_DRIVER01n,14apr98,sbs added global variable feiIntConnect. changed SYS_PCI_INT_CONNECT to SYS_INT_CONNECT. added documentation on how to use feiIntConnect.01m,18mar98,dat changed default to be BSD43_DRIVER. fixed compatibility01l,12mar98,sbs changed intConnect() to SYS_PCI_INT_CONNECT.01k,15jul97,spm removed driver initialization from ioctl support (SPR #8831)01j,25apr97,gnn added multicast by turning on promiscous mode.01i,03mar97,myz fixed spr 766301h,07apr97,spm code cleanup, corrected statistics, and upgraded to BSD 4.401h,10dec96,jdi doc: correct statement about # of external support functions.01g,20nov96,myz doc: removed the document for the sys557Intxxx functions01f,20nov96,myz correct the DOC problem in feiDumpPrint and feiErrCounterDump01e,20nov96,jdi doc: mangen fixes and general cleanup.01d,20nov96,hdn removed CSR_ADDR_GET() and ENET_ADDR_GET().01c,25oct96,myz added system memory interface and MDI control 01b,10oct96,dzb clean-up and bug fixes.01a,31aug96,dzb written, based on v03g of src/drv/netif/if_ei.c.*//*This module implements the Intel 82557 Ethernet network interface driver.This driver is designed to be moderately generic, operating unmodifiedacross the entire range of architectures and targets supported by VxWorks.This driver must be given several target-specific parameters, and someexternal support routines must be provided. These parameters, and themechanisms used to communicate them to the driver, are detailed below.This driver supports up to four individual units.EXTERNAL INTERFACEThe user-callable routine is feiattach(), which publishes the `fei'interface and performs some initialization.After calling feiattach() to publish the interface, an initializationroutine must be called to bring the device up to an operational state.The initialization routine is not a user-callable routine; upper layerscall it when the interface flag is set to `UP', or when the interface'sIP address is set.There is a global variable 'feiIntConnect' which specifies the interruptconnect routine to be used depending on the BSP. This is by default set to intConnect() and the user can override this to use any other interrupt connect routine ( say pciIntConnect() ) in sysHwInit() or any device specific initialization routine called in sysHwInit().TARGET-SPECIFIC PARAMETERS.iP "shared memory address"This parameter is passed to the driver via feiattach().The Intel 82557 device is a DMA-type device and typically sharesaccess to some region of memory with the CPU. This driver is designedfor systems that directly share memory between the CPU and the 82557.This parameter can be used to specify an explicit memory region for useby the 82557. This should be done on targets that restrict the 82557to a particular memory region. The constant `NONE' can be used to indicatethat there are no memory limitations, in which case the driverattempts to allocate the shared memory from the system space..iP "number of Command, Receive, and Loanable-Receive Frame Descriptors"These parameters are passed to the driver via feiattach().The Intel 82557 accesses frame descriptors (and their associated buffers)in memory for each frame transmitted or received. The number of framedescriptors can be configured at run-time using these parameters..iP "Ethernet address"This parameter is obtained by a call to an external support routine..LPEXTERNAL SUPPORT REQUIREMENTSThis driver requires the following external support function:.CS STATUS sys557Init (int unit, BOARD_INFO *pBoard).CEThis routine performs any target-specific initializationrequired before the 82557 device is initialized by the driver.The driver calls this routine every time it wants to [re]initializethe device. This routine returns OK, or ERROR if it fails.SYSTEM RESOURCE USAGEThe driver uses cacheDmaMalloc() to allocate memory to share with the 82557.The size of this area is affected by the configuration parameters specifiedin the feiattach() call. The size of one RFD (Receive Frame Descriptor) isis the same as one CFD (Command Frame Descriptor): 1536 bytes. For moreinformation about RFDs and CFDs, see the.I "Intel 82557 User's Manual."Either the shared memory region must be non-cacheable, or elsethe hardware must implement bus snooping. The driver cannot maintaincache coherency for the device because fields within the commandstructures are asynchronously modified by both the driver and the device,and these fields may share the same cache line.Additionally, this version of the driver does not handle virtual-to-physicalor physical-to-virtual memory mapping.TUNING HINTSThe only adjustable parameters are the number of Frame Descriptors that will becreated at run-time. These parameters are given to the driver when feiattach()is called. There is one CFD and one RFD associated with each transmittedframe and each received frame, respectively. For memory-limited applications,decreasing the number of CFDs and RFDs may be desirable. Increasing the numberof CFDs will provide no performance benefit after a certain point.Increasing the number of RFDs will provide more buffering before packets aredropped. This can be useful if there are tasks running at a higher prioritythan the net task.SEE ALSO: ifLib,.I "Intel 82557 User's Manual"*/#include "vxWorks.h"#include "wdLib.h"#include "sockLib.h"#include "memLib.h"#include "intLib.h"#include "iosLib.h"#include "errnoLib.h"#include "cacheLib.h"#include "netLib.h"#include "stdio.h"#include "stdlib.h"#include "string.h"#include "ioctl.h"#include "net/if.h"#include "netinet/in.h"#include "netinet/in_var.h"#include "net/unixLib.h"#include "net/if_subr.h"#include "iv.h"#include "sysLib.h"#include "etherLib.h"#include "vxLib.h"#include "logLib.h"#include "taskLib.h"#include "drv/netif/netifDev.h"#include "drv/netif/if_fei.h"#include "drv/pci/pciIntLib.h"/* defines *//* Change default to BSD44_DRIVER */ #ifndef BSD43_DRIVER#ifndef BSD44_DRIVER# define BSD44_DRIVER#endif /* BSD44_DRIVER */#endif /* BSD43_DRIVER */#undef FEI_DEBUG /* turns on debug output */#ifdef FEI_DEBUG#undef LOCAL#define LOCALLOCAL BOOL feiDebug = 1;#endif /* FEI_DEBUG */#define FEI_ACTION_TMO 1 /* action command timeout in seconds */#define FEI_SCB_TMO 1 /* SCB command timeout in seconds */#define FEI_INIT_TMO 1 /* 557 init timeout in seconds */#define FEI_TX_RESTART_TMO 1 /* tx restart watchdog timeout */#define TCB_TX_THRESH 0x10 /* Tx threshold value */#define BOARD_INT_ENABLE(unit) if ((int)pDrvCtrl->board.intEnable) \ (*pDrvCtrl->board.intEnable)(unit)#define BOARD_INT_DISABLE(unit) if ((int)pDrvCtrl->board.intDisable) \ (*pDrvCtrl->board.intDisable)(unit)#define BOARD_INT_ACK(unit) if ((int)pDrvCtrl->board.intAck) \ (*pDrvCtrl->board.intAck)(unit)#define LOCAL_TO_SYS_ADDR(unit,localAddr) ((int)pDrvCtrl->board.sysLocalToBus? \ (*pDrvCtrl->board.sysLocalToBus)(unit,localAddr):localAddr)#define SYS_TO_LOCAL_ADDR(unit,sysAddr) ((int)pDrvCtrl->board.sysBusToLocal? \ (*pDrvCtrl->board.sysBusToLocal)(unit,sysAddr):sysAddr)#define SYS_INT_CONNECT(vector, routine, parameter) (feiIntConnect \ ((VOIDFUNCPTR *) vector, routine, (int) parameter)) #define I82557_INT_ENABLE pDrvCtrl->pCSR->scbCommand = 0#define I82557_INT_DISABLE pDrvCtrl->pCSR->scbCommand = SCB_C_M/* typedefs */typedef struct mbuf MBUF;typedef struct arpcom IDR;typedef struct ifnet IFNET;typedef struct sockaddr SOCK;typedef struct drv_ctrl /* DRV_CTRL */ { IDR idr; /* interface data record */ BOOL attached; /* interface has been attached */ CSR * pCSR; /* Control/Status Register ptr */ CFD * pCFD; /* current Command Frame Descriptor */ RFD * pRFD; /* current Receive Frame Descriptor */ RFD * pRFDL; /* first loanable RFD */ WDOG_ID txRestart; /* tx restart watchdog */ BOOL rxHandle; /* rx handler scheduled */ BOOL txStall; /* tx handler stalled - no CFDs */ /* Board specific routines to manupalate this device */ BOARD_INFO board; } DRV_CTRL;/* globals */FUNCPTR feiIntConnect = (FUNCPTR) intConnect; IMPORT STATUS sys557Init (int unit, BOARD_INFO *pBoard);/* locals */LOCAL DRV_CTRL drvCtrl [FEI_MAX_UNITS];LOCAL int feiClkRate = 0;/* forward declarations */LOCAL STATUS feiInit (int unit);LOCAL void feiReset (int unit);LOCAL int feiIoctl (IFNET *pIfNet, int cmd, caddr_t data);#ifdef BSD43_DRIVERLOCAL int feiOutput (IDR *pIDR, MBUF *pMbuf, SOCK *pDestAddr);LOCAL void feiTxStartup (int unit);#elseLOCAL void feiTxStartup (DRV_CTRL *pDrvCtrl);#endifLOCAL void feiTxRestart (int unit);LOCAL void feiInt (DRV_CTRL *pDrvCtrl);LOCAL void feiHandleRecvInt (DRV_CTRL *pDrvCtrl);LOCAL STATUS feiReceive (DRV_CTRL *pDrvCtrl, RFD *pRfd);LOCAL void feiLoanFree (DRV_CTRL *pDrvCtrl, RFD *pRfd);LOCAL STATUS feiNOP (int unit);LOCAL STATUS feiDiag (int unit);LOCAL STATUS feiConfig (int unit);LOCAL STATUS feiIASetup (int unit);LOCAL UINT16 feiAction (int unit, UINT16 action);LOCAL STATUS feiSCBCommand (DRV_CTRL *pDrvCtrl, UINT8 cmd, BOOL addrValid, UINT32 *addr);#ifdef FEI_DEBUGLOCAL STATUS feiErrCounterDump ( int unit, UINT32 *memAddr);LOCAL STATUS feiDumpPrint (int unit);#endif /* FEI_DEBUG */static int feiMDIWrite ( int unit, int regAddr, int phyAddr, UINT16 writeData);static int feiMDIRead ( int unit, int regAddr, int phyAddr, UINT16 *retVal);static int feiPhyInit (int unit);static int feiMDIPhyConfig ( int unit, int phyAddr);static int feiMDIPhyLinkSet ( int unit, int phyAddr);/********************************************************************************* feiattach - publish the `fei' network interface** This routine publishes the `fei' interface by filling in a network interface* record and adding the record to the system list.** The 82557 shares a region of main memory with the CPU. The caller of this* routine can specify the address of this shared memory region through the* <memBase> parameter; if <memBase> is set to the constant `NONE', the* driver will allocate the shared memory region.** If the caller provides the shared memory region, the driver assumes* that this region does not require cache coherency operations.** If the caller indicates that feiattach() must allocate the shared memory* region, feiattach() will use cacheDmaMalloc() to obtain a block* of non-cacheable memory. The attributes of this memory will be checked,* and if the memory is not both read and write coherent, feiattach() will* abort and return ERROR.** A default number of 32 command (transmit) and 32 receive frames can be* selected by passing zero in the parameters <nCFD> and <nRFD>, respectively.* If <nCFD> or <nRFD> is used to select the number of frames, the values* should be greater than two.** A default number of 8 loanable receive frames can be selected by passing* zero in the parameters <nRFDLoan>, else set <nRFDLoan> to the desired* number of loanable receive frames. If <nRFDLoan> is set to -1, no* loanable receive frames will be allocated/used.** RETURNS: OK, or ERROR if the driver could not be published and initialized.** SEE ALSO: ifLib,* .I "Intel 82557 User's Manual"*/STATUS feiattach ( int unit, /* unit number */ char * memBase, /* address of shared memory (NONE = malloc) */ int nCFD, /* command frames (0 = default) */ int nRFD, /* receive frames (0 = default) */ int nRFDLoan /* loanable rx frames (0 = default, -1 = 0) */ ) { DRV_CTRL * pDrvCtrl; /* driver control structure pointer */ WDOG_ID txWd = NULL; /* tx restart watchdog */ CFD * pCFD; /* pointer to CFDs */ RFD * pRFD; /* pointer to RFDs */ UINT32 size; /* temporary size holder */ UINT32 sizeCFD = ROUND_UP (sizeof (CFD), 4); UINT32 sizeRFD = ROUND_UP (sizeof (RFD), 4); int ix; /* counter */ char bucket[2]; BOOL memAlloc = FALSE; /* sanity check the unit number */ if (unit < 0 || unit >= FEI_MAX_UNITS) return (ERROR); pDrvCtrl = &drvCtrl [unit]; if (pDrvCtrl->attached) /* already attached ? */ return (ERROR); /* initialize the default parameter for the Physical medium layer control*/ /* user has his chance to override in the BSP, just be CAREFUL */ pDrvCtrl->board.phyAddr = 1; pDrvCtrl->board.phySpeed = PHY_AUTO_SPEED; pDrvCtrl->board.phyDpx = PHY_AUTO_DPX; pDrvCtrl->board.others = 0; pDrvCtrl->board.tcbTxThresh = TCB_TX_THRESH; /* callout to perform adapter init */ if (sys557Init (unit, &pDrvCtrl->board) == ERROR) return (ERROR); /* get CSR address from PCI config space base register */ if ((int)(pDrvCtrl->pCSR = (CSR *)pDrvCtrl->board.baseAddr) == NULL) return (ERROR); /* probe for memory-mapped CSR */ if (vxMemProbe ((char *) &pDrvCtrl->pCSR->scbStatus, VX_READ, 2, &bucket[0]) != OK) { printf ("feiattach(): need MMU mapping for address 0x%x\n", (UINT32) pDrvCtrl->pCSR); return (ERROR); } I82557_INT_DISABLE; /* initialize the Physical medium layer */ if (feiPhyInit(unit) != OK) { printf("LINK FAILS, Check line connection\n"); } if (feiClkRate == 0) feiClkRate = sysClkRateGet (); /* determine number of Command and Receive Frame descriptors to use */ nCFD = nCFD ? nCFD : FEI_CFD_DEF; nRFD = nRFD ? nRFD : FEI_RFD_DEF; nRFDLoan = nRFDLoan ? nRFDLoan : FEI_RFD_LOAN; if (nRFDLoan == -1) nRFDLoan = 0; /* publish the interface record */#ifdef BSD43_DRIVER ether_attach ((IFNET *) & pDrvCtrl->idr, unit, "fei", (FUNCPTR) feiInit, (FUNCPTR) feiIoctl, (FUNCPTR) feiOutput, (FUNCPTR) feiReset);#else ether_attach ( (IFNET *) & pDrvCtrl->idr, unit, "fei", (FUNCPTR) feiInit, (FUNCPTR) feiIoctl, (FUNCPTR) ether_output, (FUNCPTR) feiReset ); pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)feiTxStartup;#endif /* calculate the total size of 82557 memory pool */ size = (sizeRFD * (nRFD + nRFDLoan)) + (sizeCFD * nCFD); /* * Establish the memory area that we will share with the device. If * the caller has provided an area, then we assume it is non-cacheable. * If the caller did not provide an area, then we must obtain it from * the system, using the cache savvy allocation routine. */ if (memBase == (char *) NONE) /* allocate on our own */ { /* this driver doesn't handle incoherent caches */ if (!CACHE_DMA_IS_WRITE_COHERENT () || !CACHE_DMA_IS_READ_COHERENT ()) { printf ("feiattach: shared memory not cache coherent\n"); goto error; } if ((memBase = cacheDmaMalloc (size)) == NULL) { printf ("feiattach: could not obtain memory\n"); goto error; } memAlloc = TRUE; } bzero (memBase, size); /* zero out entire region */ /* carve up the shared-memory region */ /* * N.B. * We are setting up the CFD list as a ring of TxCBs, tied off with a * CFD_C_SUSP as frames are copied into the data buffers. The * susp/resume model is used because the links to the next CFDs do * not change -- it is a fixed ring. Also note that if a CFD is needed * for anything else (e.g., DIAG, NOP, DUMP, CONFIG, or IASETUP comands), * then the commands will use the current CFD in the list. After the * command is complete, it will be set back to a TxCB by feiAction(). */ /* First ready CFD pointer */ pDrvCtrl->pCFD = pCFD = (CFD *) memBase; /* initialize the CFD ring */ for (ix = 0; ix < nCFD; ix++, pCFD++) { pCFD->cfdStatus = CFD_S_COMPLETE | CFD_S_OK; /* System bus address to link field */ LINK_WR (&pCFD->link, LOCAL_TO_SYS_ADDR(unit,((UINT32) pCFD + sizeCFD)) ); /* Previous CFD pointer */ pCFD->pPrev = (CFD *) ((UINT32) pCFD - sizeCFD); LINK_WR (&pCFD->cfdTcb.pTBD, 0xffffffff); /* no TBDs used */ pCFD->cfdTcb.txThresh = pDrvCtrl->board.tcbTxThresh; pCFD->cfdTcb.tbdNum = 0; } pCFD--; LINK_WR (&pCFD->link, LOCAL_TO_SYS_ADDR(unit,(UINT32)pDrvCtrl->pCFD) ) ; /* tie end of CFD ring, use system bus address */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -