⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_med.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* if_med.c - Matrix DB-ETH Ethernet network interface driver *//* "Copyright 1989, Matrix Corporation" *//* Copyright 1984-1997 Wind River Systems, Inc. *//*modification history--------------------02m,15jul97,spm  removed driver initialization from ioctl support (SPR #8831);                  cleaned up handling of promiscuous mode02l,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.402k,16dec96,dat  fixed SPR 3026, incorrect test in medNIC_AwaitStop. 		 Removed compiler warnings.02j,05may93,caf  tweaked for ansi.02i,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h02h,09sep92,gae  documentation tweaks.02g,26may92,rrr  the tree shuffle		  -changed includes to have absolute path from h/02f,04oct91,rrr  passed through the ansification filter                  -changed functions to ansi style		  -changed includes to have absolute path from h/		  -fixed #else and #endif		  -changed VOID to void		  -changed copyright notice02e,20sep90,dab  made medInit() return int.02d,10aug90,dnw  added include of if_subr.h.02c,11jul90,hjb  changed references to do_protocol() to use		 do_protocol_with_type().  de-linted.02b,26jun90,hjb  upgrade to use cluster and if_subr routines;	   +dab  integrated in the new distribution from Matrix.02a,05may90,dab  cleanup of Matrix version 01t.01a,25sep89,srm  written by modifying if_ln.c.*//*DESCRIPTIONThis module implements theMatrix DB-ETH Ethernet network interface driver.There is one user-callable routine: medattach().BOARD LAYOUTThis device is onboard.  No jumpering diagram required.SEE ALSO: ifLib*/#include "vxWorks.h"#include "net/mbuf.h"#include "net/protosw.h"#include "sys/ioctl.h"#include "sys/socket.h"#include "errno.h"#include "net/uio.h"#include "net/if.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "netinet/ip_var.h"#include "netinet/in_var.h"#include "netinet/if_ether.h"#include "net/if_subr.h"#include "etherLib.h"#include "vme.h"#include "iv.h"#include "iosLib.h"#include "ioLib.h"#include "memLib.h"#include "net/systm.h"#include "sys/types.h"#include "drv/netif/if_med.h"#include "intLib.h"#include "logLib.h"#include "stdio.h"#include "sysLib.h"#include "netLib.h"#include "net/if_subr.h"IMPORT void   sysDbusEtherIntEnable ();IMPORT ULONG  tickGet ();#define  NIC_INTERRUPTS_HANDLED   (nic_PKT_RECV_NO_ERRORS \                                 | nic_PKT_RECV_ERROR     \                                 | nic_PKT_XMIT_NO_ERRORS \                                 | nic_PKT_XMIT_ERROR     \                                 | nic_RECV_BFR_OVF_WARN  \                                 | nic_NET_STATS_CNTR_OVF)/* Actual arguments for medSetNIC_IMR() */#define  MASK_NONE               0#define  UNMASK_NONE             0/* DB-ETH addresses as seen from the CPU */#define  ETH_ADRS_PROM_ADRS    ((u_long)dbeth_ETH_ADDR_ROM           \                                + ((u_long)es->nicAddr & 0xfff00000))#define  NIC_XMIT_BFR_ADRS     ((u_long)dbeth_NIC_XMIT_BFR           \                                + ((u_long)es->nicAddr & 0xfff00000))#define  NIC_RECV_BFR_ADRS(R)  ((u_long)dbeth_NIC_RECV_BFR           \                                + ((u_long)es->nicAddr & 0xfff00000)    \                                + ((u_long)(R) << 8))#define  END_OF_RECV_BFR       ((u_long)dbeth_NIC_RECV_BFR_END       \                                + ((u_long)es->nicAddr & 0xfff00000))/* NIC register initial values */#define PSTART  (u_char) (dbeth_NIC_RECV_BFR >> 8)#define PSTOP   (u_char) ((dbeth_NIC_RECV_BFR + dbeth_NIC_RECV_BFR_SIZE) >> 8)#define	BNRY    (u_char) (PSTART)#define CURR    (u_char) (BNRY + 1)/* kludge, to force compilation of IP interface code */#ifndef INET#define INET#endif	/* INET *//* globals */u_int medLogCount = 50;  /* log every medLogCount number of errors *//* locals */LOCAL med_Stats_s       med_Stats;LOCAL struct med_softc *med_softc [NNIC];/* forward static functions */static void medRecv (struct med_softc *es, struct ether_header *eh, int len);static nic_RecvHdr_s *medGetRecvPacket (struct med_softc *es);static void medRecvIntrHandler (struct med_softc *es);static int medIoctl (struct ifnet *ifp, int cmd, caddr_t data);static void medXmitIntrHandler (struct med_softc *es, u_char xmitStatus);static void medIntr (int unit);static void medRecordRecvError (struct med_softc *es);static void medIntEnable (BOOL bEnable);static void medReset (int unit);static int medInit (int unit);static u_char bitReverse (u_char in);static void medEthAddrGet (int unit);static void medConfigNIC (int unit);#ifdef BSD43_DRIVERstatic int medOutput (struct ifnet *ifp, struct mbuf *m0, struct sockaddr		*dst);static void medStartOutput (int unit);#elsestatic void medStartOutput (struct med_softc *es);#endifstatic xmitBCB_s *medXmitBfrAlloc (struct med_softc *es);static STATUS medXmitPacket (struct med_softc *es, char *pPacket, u_short		packetLen);static void medReadTallyCntrs (struct med_softc *es);static void medMoveWrappedPacket (struct med_softc *es, nic_RecvHdr_s		*pRecvPacket, u_long pktSize);static void medSetNIC_IMR (struct med_softc *es, u_char unmaskBits, u_char		maskBits);static void medNIC_AwaitStop (NIC_DEVICE *pNIC);static void medXmitBfrDealloc (xmitQCB_s *pXmitQCB);static STATUS medXmtrLock (lockID_t *pLock);static void medXmtrUnlock (lockID_t *pLock);/********************************************************************************* medattach - publish the interface, and initialize the driver and device** The routine publishes `med' the interface by filling in a network interface* record and adding this record to the system list.  This routine also* initializes the driver and the device to the operational state.** RETURNS: OK or ERROR*/STATUS medattach    (    int unit,           /* unit number */    char *addr,         /* address of Dbus Ethernet board */    int ivec,           /* interrupt vector to connect to */    int ilevel          /* interrupt level */    )    {    FAST struct med_softc *es;    FAST NIC_DEVICE *pNicDev = (NIC_DEVICE *) (addr + (u_long) dbeth_NIC_ADDR);    /* allocate and initialize med descriptor (med_softc) */    if ((es = (struct med_softc *) calloc (1, sizeof (struct med_softc)))        == NULL)        {        printErr ("med%d: ERROR - malloc failed.\n", es->es_if.if_unit);	return (ERROR);        }    med_softc [unit] = es;	/* set ptr to med descriptor in array */    /* allocate and initialize overflow buffer for wrapped receive packets */    if ((es->pOvfRecvBfr = (nic_RecvHdr_s *)calloc (1, OVERFLOW_BFR_SIZE)) == 0)        {        printErr ("med%d: ERROR - malloc failed.\n", es->es_if.if_unit);	return (ERROR);        }    es->bFirstInit  = TRUE;            /* Unit 'unit' not yet initialized */    es->nicAddr     = pNicDev;    es->nicIntLevel = ilevel;    es->nicIntVec   = ivec;    (void) intConnect (INUM_TO_IVEC (ivec), medIntr, unit);    medReset (unit);#ifdef BSD43_DRIVER    ether_attach ( (struct ifnet *)&es->es_if, unit, "med",		  medInit, medIoctl, medOutput, (FUNCPTR) medReset);#else    ether_attach (                 &es->es_if,                 unit,                  "med",		 (FUNCPTR) medInit,                  (FUNCPTR) medIoctl,                  (FUNCPTR) ether_output,                  (FUNCPTR) medReset                 );    es->es_if.if_start = (FUNCPTR)medStartOutput;#endif    medIntEnable (TRUE);      /* enable the DB-ETH interrupt */    medInit (unit);    return (OK);    }/********************************************************************************* medRecv - receive packet processing** Process Ethernet receive completion:* If input error, just drop packet. (This is handled in medRecvIntrHandler.)* Otherwise purge input buffered data path and examine* packet to determine type.  If can't determine length* from type, then have to drop packet.  Otherwise decapsulate* packet based on type and pass to type-specific higher-level* input routine.*/LOCAL void medRecv    (    FAST struct med_softc *es,    FAST struct ether_header *eh,   /* ether header followed by packet data */    int len    )    {    FAST struct mbuf	      *m;    FAST u_char		      *pData;    int		       	       off;    es->es_if.if_ipackets++;    /* call input hook if any */    if (etherInputHookRtn != NULL &&	(*etherInputHookRtn) (&es->es_if, (char *) eh, len))	{	return;		/* input hook has already processed this packet */	}#ifdef BSD43_DRIVER    /* This legacy code is not correct for the BSD 4.4 stack. It would     * also treat multicast addresses like alien packets, and not send     * them up the stack. The higher-level protocols in the new stack     * can handle these addresses, and will discard them if they do not     * match an existing multicast group.     */    /* do software filter if controller is in promiscuous mode */    if (es->bPromisc)	{	if ((bcmp ((char *) eh->ether_dhost,	/* not our adrs? */		     (char *) es->es_enaddr,		     sizeof (eh->ether_dhost)) != 0) &&	    (bcmp ((char *) eh->ether_dhost,	/* not broadcast? */		     (char *) etherbroadcastaddr,		     sizeof (eh->ether_dhost)) != 0))	    {	    return;				/* not for us */	    }	}#endif    if (len >= sizeof (struct ether_header))        len -= sizeof (struct ether_header);    else        len = 0;    pData = ((u_char *) eh) + (sizeof (struct ether_header));#ifdef BSD43_DRIVER    /*     * Deal with trailer protocol: if type is trailer     * get true type from first 16-bit word past data.     * Remember that type was trailer by setting off.     */    check_trailer (eh, pData, &len, &off, &es->es_if);    if (len == 0)        return;					/* sanity */#endif    m = copy_to_mbufs (pData, len, off, (struct ifnet *) &es->es_if);    if (m == NULL)        {        es->es_if.if_ierrors++;	return;        }#ifdef BSD43_DRIVER    do_protocol_with_type (eh->ether_type, m, &es->es_ac, len);#else    do_protocol (eh, m, &es->es_ac, len);#endif    return;    }/********************************************************************************* medGetRecvPacket - return the address of the next packet received** If a packet is available in the NIC receive buffer, return its address.* Otherwise, return NULL.*/LOCAL nic_RecvHdr_s *medGetRecvPacket    (    FAST struct med_softc  *es    )    {    FAST u_char          currNIC_WritePage;    FAST NIC_DEVICE     *pNIC = es->nicAddr;    FAST int             oldLevel;    /*     * Select NIC register page 1, and retrieve the CURR register,     * re-select NIC register page 0.     */    oldLevel = intLock();    pNIC->Cr = (u_char) (RPAGE1 | ABORT | STA);    currNIC_WritePage = pNIC->Curr;    pNIC->Cr = (u_char) (RPAGE0 | ABORT | STA);    intUnlock (oldLevel);    if (es->pktNextToRead == currNIC_WritePage)  /* No new packets. */        {        return ((nic_RecvHdr_s *) NULL);        }    return ((nic_RecvHdr_s *) NIC_RECV_BFR_ADRS (es->pktNextToRead));    }/********************************************************************************* medRecvIntrHandler - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.*/LOCAL void medRecvIntrHandler    (    FAST struct med_softc  *es    )    {    FAST nic_RecvHdr_s  *pRecvPacket;    FAST u_char          recvStatus;    FAST u_long          pktSize;    FAST NIC_DEVICE     *pNIC = es->nicAddr;    if (es->bRecvBfrOvfl)  /* Ignore packets on receive buffer overflow; */        return;            /* they all will be dropped.                  */    while (TRUE)        {        while ((pRecvPacket = medGetRecvPacket (es)) != (nic_RecvHdr_s *) NULL)            {            if (es->bRecvBfrOvfl)                return;            recvStatus = pRecvPacket->recvStatus;            if  ((recvStatus & PRX) == nic_RECV_NO_ERROR)                {                pktSize = (u_long) pRecvPacket->byteCntL                        | (u_long) (pRecvPacket->byteCntH << 8);                /*                 * If the packet is wrapped around in the receive buffer,                 * move it to a contiguous buffer.                 */                if (((u_long) pRecvPacket + pktSize) > (u_long) END_OF_RECV_BFR)                    {                    medMoveWrappedPacket (es, pRecvPacket, pktSize);                    medRecv (es, &(es->pOvfRecvBfr->eh), (int) pktSize);                    }                else                    medRecv (es, &(pRecvPacket->eh), (int) pktSize);                es->pktNextToRead = pRecvPacket->nextPkt;                /*                 * Ensure that the "boundry" register is maintained one page                 * behind the "current"  register.                 */                if (es->pktNextToRead ==		    ((u_char) ((u_short) dbeth_NIC_RECV_BFR) >> 8))		    {                    pNIC->Bnry = PSTOP - 1;		    }                else                    pNIC->Bnry = es->pktNextToRead - 1;                }            else                {                if ((recvStatus & DIS) == nic_RCVR_DISABLED)                   logMsg("med%d: receiver disabled\n",			es->es_if.if_unit, 0,0,0,0,0);                if ((recvStatus & DFR) == nic_RCVR_DEFERRING)                   logMsg("med%d: receiver deferring\n", 			es->es_if.if_unit, 0,0,0,0,0);                }            }   /* while ((pRecvPacket ... */        if (pNIC->Isr & PRX)           /* pending recv interrupt ?   */            {            pNIC->Isr = PRX;           /* clear interrupt flag       */            med_Stats.PRX_intrCount++; /* update statistics monitor  */            }        else if (pNIC->Isr & RXE)      /* pending recv error interrupt ? */            {            pNIC->Isr = RXE;           /* clear interrupt flag       */            medRecordRecvError (es);            }        else            {                          /* no recv interrupt          */            /* Re-enable PRX and RXE interrupts. */            medSetNIC_IMR (es,  nic_PKT_RECV_NO_ERRORS                              | nic_PKT_RECV_ERROR, MASK_NONE);            break; /* break from while (TRUE) */            }        }       /* while (TRUE)            */    }/********************************************************************************* medIoctl - process an ioctl request.*/LOCAL int medIoctl    (    FAST struct ifnet *ifp,    int cmd,    caddr_t data    )    {    int 			unit  = ifp->if_unit;    FAST struct med_softc * 	es = med_softc [unit];    int 			s     = splimp ();    int 			error = 0;    short 			flags;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -