📄 if_nicevb.c
字号:
/* if_nicEvb.c - National Semiconductor ST-NIC Chip network interface driver *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------03i,05may97,tam re-work driver to improve reliability and performances: modified receive interrupt processing and error handling, fixed bug in nicTxStartup(), added function nicPagePtrUpdate() and nicResetDelay().03h,21apr97,mkw reset count to 0 before timeout check in nicTransmit and set TRANS_TIMOUT value to 400.03g,18apr97,mkw Fixed nicTransmit to use count value.03g,15jul97,spm added ARP request to SIOCSIFADDR ioctl handler03f,05mar97,map added sysEnetAddrGet() call to fetch MAC address (SPR# 7745)03f,07apr97,spm code cleanup, corrected statistics, and upgraded to BSD 4.403e,10dec96,tpr removed intEnable() prototype. Defined in intLib.h now.03d,18sep96,p_m added SYNC definition for CPUs other than PPC03c,08aug96,tam added code to synchronize i/o acess in nicWritePort().03b,03mar96,tam replaced sysIntEnablePIC by intEnable().03a,02feb96,dzb re-worked many parts of driver. implemented Rx buffer-loaning. fixed nicRestart to recover gracefully from DMA overflow. re-worked Tx code to send directly from mbuf chain. changed to turn off Rx interrupts, instead of an active flag. fixed nicRead() to flush extra DMA-byte on Rx error.02d,11jul95,amp used intLock(), implemented nicEnetAddrGet(), cleanup.02c,29jun95,caf changed name to "nicEvb".02b,27jun95,amp improved reliability.02a,16jun95,amp modified if_nic.c for EVB403.01z,11aug93,jmm Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h01y,19feb93,jdi documentation cleanup.01x,15oct92,rfs Added documentation.01w,02oct92,rfs Made multiple attach calls per unit return OK.01v,09sep92,gae documentation tweaks.01u,02sep92,ajm added conditional compilation for __STDC__ (DEC)01t,18aug92,rfs Revised to follow style of other drivers. Added cache support. Reworked OVW error recovery.01s,23jun92,ajm fixed ansi warnings for pktBufRead calls went back and fixed all 68k ansi warnings01r,26may92,rrr the tree shuffle -changed includes to have absolute path from h/01q,26may92,ajm got rid of HOST_DEC def's (new compiler) updated copyright01p,10oct91,rfs modified pktBufRead() & pktBufWrite() to return if len is zero01o,04oct91,rrr passed through the ansification filter -changed functions to ansi style -changed includes to have absolute path from h/ -changed VOID to void -changed copyright notice01n,28sep91,ajm ifdef'd HOST_DEC for compiler problem01m,02Aug91,rfs cleanup of transmit design, int handler, NIC command register was being handled incorrectly, DMA operations required semaphoring and error checking, changed names, deleted nicdelay(), deleted excessive include files. Provided correct OVW recovery. Your basic rewrite.01l,01may91,elh fixed transmit buffering problems, added changes from heurikon, removed DMAState, XmtByteCount.01k,20sep90,dab made nicInit() return int.01j,10aug90,dnw added forward declarations of void routines. added include of if_subr.h.01i,11jul90,hjb removed code that uses gotIp. made nicRead() a void function. changed references to do_protocol() to use do_protocol_with_type().01h,19apr90,hjb deleted param.h, de-linted.01g,18mar90,hjb reduction of redundant code and addition of cluster support. added error recording (TXE, RXE), removed unnecessary error handler which didn't do anything. delinted.01f,18sep89,cwp added multiple transmit buffer support01e,14sep89,dab changed iv68k.h to iv.h.01d,15jun89,cwp fixed ring buffer overflow and transmit errors.01c,04apr89,cwp first working version.01b,25feb89,cwp added changes from unix driver.01a,12jan89,cwp written.*//*This module implements the National Semiconductor 83902A ST-NIC Ethernetnetwork interface driver.This driver is non-generic and is for use on the IBM EVB403 board. Only unit number zero is supported. The driver must be given several target-specific parameters. These parameters, and the mechanisms used to communicate them to the driver, are detailed below.BOARD LAYOUTThis device is on-board. No jumpering diagram is necessary.EXTERNAL INTERFACEThis driver provides the standard external interface with the followingexceptions. All initialization is performed within the attach routine; thereis no separate initialization routine. Therefore, in the global interfacestructure, the function pointer to the initialization routine is NULL.The only user-callable routine is nicEvbattach(), which publishes the `nicEvb'interface and initializes the driver and device.TARGET-SPECIFIC PARAMETERS.iP "device I/O address"This parameter is passed to the driver by nicEvbattach().It specifies the base address of the device's I/O registerset..iP "interrupt vector"This parameter is passed to the driver by nicEvbattach().It specifies the interrupt vector to be used by the driverto service an interrupt from the ST-NIC device. The driver will connectthe interrupt handler to this vector by calling intConnect()..iP "device restart/reset delay"The global variable nicRestartDelay (UINT32), defined in this file, should be initialized in the BSP sysHwInit() routine. nicRestartDelay is used only with PowerPC platform and is equal to the number of time base increments which makes for 1.6 msec. This corresponds to the delay necessary to respect when restarting or resetting the device..LPEXTERNAL SUPPORT REQUIREMENTSThe driver requires the following support functions:.iP "STATUS sysEnetAddrGet (int unit, UINT8 * addr)" "" 9 -1The driver expects this routine to provide the six-byte Ethernet hardwareaddress that will be used by <unit>. This routine must copy the six-byteaddress to the space provided by <addr>. This routine is expected to returnOK on success, or ERROR. The driver calls this routine, during deviceinitialization, from the nicEnetAddrGet() routine..LPSYSTEM RESOURCE USAGEWhen implemented, this driver requires the following system resources: - one mutual exclusion semaphore - one interrupt vectorSEE ALSO: ifLib*//* includes */#include "vxWorks.h"#include "iv.h"#include "stdlib.h"#include "intLib.h"#include "netLib.h"#ifdef NIC_DEBUG#include "logLib.h"#endif#include "taskLib.h"#include "logLib.h"#include "net/mbuf.h"#include "sys/ioctl.h"#include "errno.h"#include "net/if.h"#include "net/unixLib.h"#include "net/if_subr.h"#include "netinet/in_var.h"#include "netinet/if_ether.h"#include "etherLib.h"#include "semLib.h"#include "drv/netif/netifDev.h"#include "drv/netif/if_nicEvb.h"#include "vxLib.h"#include "private/funcBindP.h"/* defines */#if (CPU_FAMILY == PPC)#define NIC_USE_PPCTIMEBASE#else /* CPU_FAMILY == PPC */#undef NIC_USE_PPCTIMEBASE#endif /* CPU_FAMILY == PPC */#define MAX_UNITS 1 /* max number of units supported */#define TRANS_TIMEOUT 400 /* times to poll for end of Tx */#define L_POOL 0x4 /* Rx loan buffers in pool *//* debug macros */#undef NIC_INSTRUMENT /* instrument the driver */#undef NIC_DEBUG /* log debug messages *//* * NIC_FASTER, if defined, improved the driver throuput, however the driver * seems to be less reliable. Left undefined for now. */#undef NIC_FASTER /* improve throuput but less stable *//* typedefs */typedef struct mbuf MBUF;typedef struct arpcom IDR; /* Interface Data Record wrapper */typedef struct ifnet IFNET; /* real Interface Data Record */typedef struct sockaddr SOCK;typedef struct ether_header ETH_HDR;typedef struct rx_hdr { UINT8 status; /* status of packet */ UINT8 nextRxPage; /* page next pkt starts at */ UINT8 cntL; /* low byte of frame length */ UINT8 cntH; /* high byte of frame length */ } RX_HDR;#define RX_HDR_SIZ sizeof(RX_HDR)typedef struct rx_frame { UINT16 pad1; RX_HDR rxHdr; /* receive status header */ ETH_HDR enetHdr; /* ethernet header */ UINT8 data [ETHERMTU];/* frame data */ UINT32 fcs; /* frame check sequence */ UINT8 refCnt; /* loaner reference count */ UINT8 pad2; } RX_FRAME;#define RX_FRAME_SIZ sizeof(RX_FRAME)typedef struct drv_ctrl /* driver control structure */ { IDR idr; /* interface data record */ BOOL attached; /* indicates unit is attached */ int nicIntVec; /* interrupt vector */ SEM_ID dmaSem; /* exclusive use of remote DMA */ UINT8 nextPkt; /* NIC buf page for next pkt */ NIC_DEVICE * nicAddr; /* address of NIC chip */ RX_FRAME * pRxFrame; /* Rx frame memory */ RX_FRAME * lPool [L_POOL]; /* Rx loaner pool */ int lIndex; /* Rx loaner pool index */ } DRV_CTRL;/* globals */UINT32 nicRestartDelay = 30000;/* number of time base ticks to wait for */ /* when resetting the chip */#ifdef NIC_INSTRUMENTUINT32 nicRestartNb = 0; /* number of restart due to ring overflow */UINT32 nicIntNb = 0; /* number of receive interrupt */UINT32 nicLen = 0; /* lenght of the current received packet */UINT32 nicHdrStat = 0; /* status byte of the current received packet */UINT32 nicNextPage = 0; /* page pointer to the next received packet */UINT32 nicCurrentPage = 0; /* start page of the current packet */UINT32 nicTxNb = 0; /* number of transmitted packets */UINT32 nicTxTimeout = 0; /* number of transmit time-out */UINT32 nicInitNb = 0; /* number of time device is re-initialized */#endifIMPORT STATUS sysEnetAddrGet (int unit, UINT8 * addr);/* locals */LOCAL DRV_CTRL drvCtrl [MAX_UNITS];/* forward declarations */#ifdef __STDC__LOCAL void nicReset (int unit);LOCAL void nicIntr (int unit);LOCAL void nicRestart (DRV_CTRL *pDrvCtrl, UINT8 cr);LOCAL void nicHandleInt (DRV_CTRL *pDrvCtrl);LOCAL BOOL nicRead (DRV_CTRL *pDrvCtrl);#ifdef BSD43_DRIVERLOCAL int nicOutput (IDR *pIDR, MBUF *pMbuf, SOCK *pDest);#endifLOCAL int nicIoctl (IDR *pIDR, int cmd, caddr_t data);LOCAL void nicEnetAddrGet (int unit);LOCAL void nicConfig (int unit);LOCAL STATUS nicPktBufRead (DRV_CTRL *pDrvCtrl, UINT32 nicBufAddr, UINT32 len, char *pData);LOCAL void nicWriteCr (NIC_DEVICE *pNic, UINT8 value);LOCAL void nicWriteReg (NIC_DEVICE *pNic, volatile UINT8 *pReg, UINT8 value, UINT8 page);LOCAL UINT8 nicReadReg (NIC_DEVICE *pNic, volatile UINT8 *pReg, char page);LOCAL STATUS nicTransmit (DRV_CTRL *pDrvCtrl, MBUF *pMbuf, int len, BOOL waitFlag);LOCAL void nicWritePort (UINT8 value);LOCAL STATUS nicReceive (DRV_CTRL *pDrvCtrl, UINT32 nicBufAddr, char *pData, int len);#ifdef BSD43_DRIVERLOCAL STATUS nicTxStartup(int unit);#elseLOCAL STATUS nicTxStartup(DRV_CTRL *pDrvCtrl);#endifLOCAL UINT8 nicReadPort (void);LOCAL void nicLoanFree (DRV_CTRL *pDrvCtrl, RX_FRAME *pRx);LOCAL BOOL nicPagePtrUpdate (DRV_CTRL * pDrvCtrl);LOCAL void nicResetDelay (void);#else /* __STDC__ */LOCAL void nicReset ();LOCAL void nicIntr ();LOCAL void nicRestart ();LOCAL void nicHandleInt ();LOCAL BOOL nicRead ();LOCAL int nicOutput ();LOCAL int nicIoctl ();LOCAL void nicEnetAddrGet ();LOCAL void nicConfig ();LOCAL STATUS nicPktBufRead ();LOCAL void nicWriteCr ();LOCAL void nicWriteReg ();LOCAL UINT8 nicReadReg ();LOCAL STATUS nicTransmit ();LOCAL void nicWritePort ();LOCAL STATUS nicReceive ();LOCAL STATUS nicTxStartup();LOCAL UINT8 nicReadPort ();LOCAL void nicNicFree ();LOCAL BOOL nicPagePtrUpdate ();LOCAL void nicResetDelay () ;#endif /* __STDC__ *//********************************************************************************* nicEvbattach - publish and initialize the `nicEvb' network interface driver** This routine publishes the `nicEvb' interface by filling in a network* interface record and adding this record to the system list. It also* initializes the driver and the device to the operational state.** RETURNS: OK, or ERROR if the receive buffer memory could not be allocated.*/STATUS nicEvbattach ( int unit, /* unit number */ NIC_DEVICE * pNic, /* address of NIC chip */ int ivec /* interrupt vector to use */ ) { DRV_CTRL * pDrvCtrl; /* driver control struct */ RX_FRAME * pPool; /* receive memory pool */ int ix; /* counter */ if (unit < 0 || unit >= MAX_UNITS) /* sanity check the unit number */ return (ERROR); pDrvCtrl = &drvCtrl [unit]; if (pDrvCtrl->attached) /* ensure single invocation */ return (OK); if ((pPool = (RX_FRAME *) malloc ((L_POOL + 1) * RX_FRAME_SIZ)) == NULL) return (ERROR); for (ix = 0; ix < L_POOL; ix++) /* assign addresses of Rx pool */ pDrvCtrl->lPool [ix] = pPool++; pDrvCtrl->lIndex = L_POOL; /* initialize loaner pool index */ pDrvCtrl->pRxFrame = pPool; /* link in primary buffer */ pDrvCtrl->nicAddr = pNic; /* save NIC address */ pDrvCtrl->nicIntVec = ivec; /* save int vector number */ pDrvCtrl->nextPkt = CURR; /* reset to initial value */ pDrvCtrl->dmaSem = semMCreate (SEM_Q_PRIORITY); /* publish the interface data record */#ifdef BSD43_DRIVER ether_attach (&pDrvCtrl->idr.ac_if, unit, "nicEvb", (FUNCPTR) NULL, (FUNCPTR) nicIoctl, (FUNCPTR) nicOutput, (FUNCPTR) nicReset);#else ether_attach ( &pDrvCtrl->idr.ac_if, unit, "nicEvb", (FUNCPTR) NULL, (FUNCPTR) nicIoctl, (FUNCPTR) ether_output, (FUNCPTR) nicReset ); pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)nicTxStartup;#endif /* connect the interrupt handler */ (void) intConnect (INUM_TO_IVEC (ivec), nicIntr, 0); intEnable (ivec); nicConfig (unit); /* configure the device */ /* raise the interface flags */ pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS; pDrvCtrl->attached = TRUE; return (OK); }/********************************************************************************* nicReset - reset of interface** This routine performs a software reset of the ST-NIC device.** RETURNS: N/A.** NOMANUAL*/void nicReset ( int unit /* device unit to reset */ ) { DRV_CTRL * pDrvCtrl = &drvCtrl [unit]; NIC_DEVICE * pNic = pDrvCtrl->nicAddr; pDrvCtrl->idr.ac_if.if_flags = 0; nicWriteCr (pNic, STP | ABORT | RPAGE0); taskDelay (2); /* wait at least 1.6 mSec */ }/********************************************************************************* nicIntr - The driver's interrupt handler** This function clears the cause of the device interrupt(s) and then acts* on the individual possible causes. The primary goal of this routine is to* minimize the time spent in it. This is accomplished by deferring processing* to the netTask via the netJobAdd() function.** Note that in case the receiver overruns, we promptly mark the interface as* "down" and leave error handling to task-level. This is in case netTask* is in the midst of DMA activity, we must allow it to complete. The receive* handler will give up when it discovers the interface is down, which will* then allow netTask to run our OVW handler. This provides a nice orderly* error recovery.** RETURNS: N/A.*/LOCAL void nicIntr ( int unit ) { DRV_CTRL * pDrvCtrl = &drvCtrl [unit]; NIC_DEVICE * pNic = pDrvCtrl->nicAddr; /* NIC registers */ UINT8 isr; /* copy of ISR */ UINT8 cr; /* copy of CR */#ifdef NIC_INSTRUMENT nicIntNb++;#endif isr = nicReadReg(pNic, &pNic->Isr, RPAGE0); nicWriteReg(pNic, &pNic->Isr, isr, RPAGE0); /* handle receiver overrun */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -