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

📄 if_elc.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* if_elc.c - SMC 8013WC Ethernet network interface driver *//* Copyright 1984-1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------02b,11jan99,aeg  fixed multiple semaphore inits in elcattach ().02a,15jul97,spm  removed driver initialization from ioctl support (SPR #8831)01z,15may97,spm  reverted to bcopy routines for mbufs in BSD 4.401y,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.401x,14jun95,hdn  removed function declarations defined in sysLib.h.01w,01feb95,jdi  doc cleanup; made elcShow() NOMANUAL.01v,29nov94,hdn  added a semaphore in ultraPut().01u,12nov94,tmk  removed some IMPORTed function decs and included unixLib.h01t,03oct94,hdn  implemented two transmit buffers.		 enabled getting OUT2 bit of IRR in EEROM.		 deleted while loop in ultraPut().01s,03dec93,hdn  added documentation.01r,29nov93,hdn  removed netJobAdd (elcPut, ..) in elcIntr().01q,28nov93,hdn  changed NELC to 1.01p,24nov93,hdn  removed TXING and txreq flags.		 added checking TXP bit before the transmission. 01o,23nov93,hdn  removed cacheInvalidate(). 01n,22nov93,hdn  added elcdetach () for the warm start.01m,15nov93,hdn  added support for Thin Ethernet(10Base2, BNC)01l,05nov93,hdn  added cacheFlush() and cacheInvalidate().01k,04nov93,hdn  cleaned up.01j,03nov93,hdn  made RAM size 16Kbytes. cleaned up.01i,05sep93,hdn  added sysIntEnablePIC ().01h,02sep93,hdn  added macros about PIC.01g,11aug93,hdn  changed a way of setting a handler for stray interrupt IRQ7.01f,23jun93,hdn  made address, irq software configuarable.01e,17jun93,hdn  updated to 5.1.01d,28may93,hdn  deleted a zero wait bit. fixed a race condition.01c,23apr93,hdn  fixed a bug which appears when a packet is wrapped.		 fixed a stray interrupt 15.		 moved a interrupt masking to the top of elcGet.01b,03jan93,hdn  fixed bugs and cleaned up.01a,09jun92,hdn  written.*//*DESCRIPTIONThis module implements the SMC 8013WC network interface driver.BOARD LAYOUTThe W1 jumper should be set in position SOFT.The W2 jumper should be set in position NONE/SOFT.CONFIGURATIONThe I/O address, RAM address, RAM size, and IRQ levels are defined in config.h.The I/O address must match the one stored in EEROM.  The configuration software supplied by the manufacturer should be used to set the I/O address. IRQ levels 2,3,4,5,7,9,10,11,15 are supported.  Thick Ethernet (AUI) andThin Ethernet (BNC) are configurable by changing the macro CONFIG_ELCin config.h.EXTERNAL INTERFACEThe only user-callable routines are elcattach() and elcShow():.iP elcattach() 14publishes the `elc' interface and initializes the driver and device..iP elcShow()displays statistics that are collected in the interrupt handler..LP*/#include "vxWorks.h"#include "net/mbuf.h"#include "net/protosw.h"#include "net/unixLib.h"#include "ioctl.h"#include "socket.h"#include "errnoLib.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 "etherLib.h"#include "vme.h"#include "iv.h"#include "iosLib.h"#include "ioLib.h"#include "memLib.h"#include "net/systm.h"#include "net/if_subr.h"#include "sysLib.h"#include "vxLib.h"#include "stdio.h"#include "intLib.h"#include "logLib.h"#include "string.h"#include "netLib.h"#include "stdlib.h"#include "semLib.h"#include "cacheLib.h"#include "drv/intrCtl/i8259a.h"#include "drv/netif/if_elc.h"/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */#define	NELC	1	/* max number of ELC controllers */LOCAL ELC_SOFTC elc_softc [NELC];LOCAL IRQ_TABLE irqTable [] =    {    {0xff,  0xff},		/* IRQ0  not supported  */    {0xff,  0xff},		/* IRQ1  not supported  */    {0x0,   0x0},		/* IRQ2  		*/    {0x0,   0x1},		/* IRQ3  		*/    {0x1,   0x3},		/* IRQ4  		*/    {0x0,   0x2},		/* IRQ5  		*/    {0xff,  0xff},		/* IRQ6  not supported  */    {0x0,   0x3},		/* IRQ7  		*/    {0xff,  0xff},		/* IRQ8  not supported  */    {0x0,   0x0},		/* IRQ9  		*/    {0x1,   0x0},		/* IRQ10 		*/    {0x1,   0x1},		/* IRQ11 		*/    {0xff,  0xff},		/* IRQ12 not supported  */    {0xff,  0xff},		/* IRQ13 not supported  */    {0xff,  0xff},		/* IRQ14 not supported  */    {0x1,   0x2},		/* IRQ15 		*/    {0, 0},    };LOCAL BOOL elcAttached = FALSE;LOCAL SEMAPHORE elcSyncSem;		/* syncronization semaphore *//* forward static functions */static void	elcreset (int unit);static int	elcinit (int unit);static void	elcintr (int unit);static int	elcioctl (struct ifnet *ifp, int cmd, caddr_t data);#ifdef BSD43_DRIVERstatic int	elcoutput (struct ifnet *ifp, struct mbuf *m0, struct sockaddr		*dst);#endifstatic void	elcGet (int unit);#ifdef BSD43_DRIVERstatic void	elcPut (int unit);#elsestatic void	elcPut (ELC_SOFTC *sc);#endifstatic void	elcReset (int unit);static void	elcGetAddr (int unit);static void	bicInit (int unit);static void	elcInit (int unit);static UCHAR	elcGetCurr (int unit);       void	elcShow (int unit, BOOL zap);       void	elcdetach (int unit);/********************************************************************************* elcattach - publish the `elc' network interface and initialize the driver and device** This routine attaches an `elc' Ethernet interface to the network if the* device exists.  It makes the interface available by filling in the network* interface record.  The system will initialize the interface when it is* ready to accept packets.** RETURNS: OK or ERROR.** SEE ALSO: ifLib, netShow*/STATUS elcattach     (    int unit,           /* unit number */    int ioAddr,         /* address of elc's shared memory */    int ivec,           /* interrupt vector to connect to */    int ilevel,         /* interrupt level */    int memAddr,        /* address of elc's shared memory */    int memSize,        /* size of elc's shared memory */    int config		/* 0: RJ45 + AUI(Thick)  1: RJ45 + BNC(Thin) */    )    {    FAST ELC_SOFTC *sc = &elc_softc[unit];    if ((UINT)unit >= NELC)	{	errnoSet (S_iosLib_CONTROLLER_NOT_PRESENT);	return (ERROR);	}    sc->bicAddr		= ioAddr;    sc->elcAddr		= ioAddr + 0x10;    sc->memAddr		= memAddr;    sc->memSize		= memSize;    if (ilevel == 0  || ilevel == 1  || ilevel == 6 || ilevel == 8 ||	ilevel == 12 || ilevel == 13 || ilevel == 14)	ilevel = 3;                     /* default is IRQ3 */    sc->intLevel	= ilevel;    sc->intVec		= ivec;    sc->config		= config;    sc->transmitPage[0]	= SMC8013WC_TSTART0;    sc->transmitPage[1]	= SMC8013WC_TSTART1;    sc->transmitCnt	= 0;    /* synchronization semaphore must be initialized only once */    if (!elcAttached)	semBInit (&elcSyncSem, SEM_Q_FIFO, SEM_FULL);    bicInit (unit);			/* initialize BIC */    elcInit (unit);			/* initialize ELC */    elcGetAddr (unit);			/* get ethernet address */    (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (ivec), (VOIDFUNCPTR)elcintr, unit);    /* enable interrupt */    sysOutByte (ELC_INTMASK (sc->elcAddr), 	IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE);    sysIntEnablePIC (ilevel);#ifdef BSD43_DRIVER    ether_attach (&sc->es_if, unit, "elc", (FUNCPTR)elcinit, (FUNCPTR)elcioctl,		  (FUNCPTR)elcoutput, (FUNCPTR)elcreset);#else    ether_attach (                 &sc->es_if,                  unit,                  "elc",                  (FUNCPTR)elcinit,                  (FUNCPTR)elcioctl,		 (FUNCPTR)ether_output,                  (FUNCPTR)elcreset                 );    sc->es_if.if_start = (FUNCPTR)elcPut;#endif    elcinit (unit);    elcAttached = TRUE;    return (OK);    }/********************************************************************************* elcreset - reset the interface*/LOCAL void elcreset     (    int unit     )    {    elcReset (unit);    }/********************************************************************************* elcinit - initialize elc** Restart the link level software on the board and mark the interface up.** RETURNS: 0*/LOCAL int elcinit     (    int unit     )    {    FAST ELC_SOFTC *sc = &elc_softc[unit];    sc->es_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business*/    return (0);    }/********************************************************************************* elcintr - Ethernet interface interrupt** Hand off reading of packets from the interface to task level.*/LOCAL void elcintr     (    int unit     )    {    FAST ELC_SOFTC *sc = &elc_softc[unit];    sc->elcStat.interrupts++;    sysBusIntAck (sc->intLevel);			/* acknowledge int */    /* acknowledge interrupt, get Transmit/Receive status */    sc->istat = sysInByte (ELC_INTSTAT (sc->elcAddr));    sysOutByte (ELC_INTSTAT (sc->elcAddr), sc->istat);    sc->tstat = sysInByte (ELC_TSTAT (sc->elcAddr));    sc->rstat = sysInByte (ELC_RSTAT (sc->elcAddr));    /* get xxxCount Reg that is cleared after read access */    sc->elcStat.collisions += sysInByte (ELC_COLCNT (sc->elcAddr));    sc->elcStat.aligns += sysInByte (ELC_ALICNT (sc->elcAddr));    sc->elcStat.crcs += sysInByte (ELC_CRCCNT (sc->elcAddr));    sc->elcStat.missed += sysInByte (ELC_MPCNT (sc->elcAddr));    if (sc->istat & ISTAT_OVW) /* Receive buffer ring overwrite */	{        sysOutByte (ELC_BOUND(sc->elcAddr), sysInByte (ELC_BOUND(sc->elcAddr)));	sc->elcStat.overwrite++;        sc->es_if.if_ierrors++;	}    if (sc->istat & ISTAT_RXE) /* Receive-error */	{        sc->es_if.if_ierrors++;	sc->elcStat.rerror++;	if (sc->rstat & RSTAT_OVER)	    sc->elcStat.overruns++;	if (sc->rstat & RSTAT_DIS)	    sc->elcStat.disabled++;	if (sc->rstat & RSTAT_DFR)	    sc->elcStat.deferring++;	}    if (sc->istat & ISTAT_PRX) /* Receive */	{        sc->current = elcGetCurr (unit);	if ((sc->flags & RXING) == 0)	    {            sc->flags |= RXING;	    (void) netJobAdd ((FUNCPTR)elcGet, unit, 0,0,0,0);	    }	if (sc->rstat & RSTAT_PRX)	    sc->elcStat.rnoerror++;	}    if (sc->istat & (ISTAT_TXE | ISTAT_PTX)) /* Transmit-error, Transmit */	{	semGive (&elcSyncSem);        if (sc->istat & ISTAT_TXE)            {            sc->es_if.if_oerrors++;            sc->es_if.if_opackets--;	    sc->elcStat.terror++;            }	if (sc->tstat & TSTAT_ABORT)	    {	    sc->elcStat.aborts++;	    sc->elcStat.collisions += 16;	    }	if (sc->tstat & TSTAT_UNDER)	    sc->elcStat.underruns++;	if (sc->tstat & TSTAT_CDH)	    sc->elcStat.heartbeats++;	if (sc->tstat & TSTAT_OWC)	    sc->elcStat.outofwindow++;	if (sc->tstat & TSTAT_PTX)	    sc->elcStat.tnoerror++;	}    }/********************************************************************************* elcGet - read a packet off the interface** Copy packets from a RING into an mbuf and hand it to the next higher layer.*/LOCAL void elcGet     (    int unit    )    {    FAST ELC_SOFTC *sc = &elc_softc[unit];    FAST ELC_HEADER *pH;    FAST struct ether_header *eh;    FAST struct mbuf *m;    int len;#ifdef BSD43_DRIVER    int off;#endif    int ix = 0;    USHORT wrapSize;    USHORT packetSize;    char *pSrc;    char *pDst;    UCHAR *pData;    UCHAR uppByteCnt;unlucky:    ix = 0;    while ((sc->next != sc->current) && (ix++ < SMC8013WC_PSTOP))	{	/* Invalidate cache */        cacheDrvInvalidate (&cacheDmaFuncs, 		            (UCHAR *)(sc->memAddr + (SMC8013WC_PSTART << 8)),		            (sc->memSize - (SMC8013WC_PSTART << 8)));	pH = (ELC_HEADER *)(sc->memAddr + 			   (((UINT)sc->next << 8) & 0x0000ffff));	/* sanity check */	if ((pH->next < SMC8013WC_PSTART) || (pH->next >= SMC8013WC_PSTOP))	    {	    sc->elcStat.badPacket++;	    pH->next = sc->next + sc->uppByteCnt + 1;	    if (pH->next >= SMC8013WC_PSTOP)		pH->next = SMC8013WC_PSTART + (pH->next - SMC8013WC_PSTOP);	    }	if (*(USHORT *)(&pH->lowByteCnt) < 64)	    {	    sc->elcStat.shortPacket++;	    goto doneGet;	    }        sc->es_if.if_ipackets++;        /* bump statistic */	/* get uppByteCnt from pH->next because of the bug of a chip */	if (pH->next > sc->next)	    {	    wrapSize = 0;	    uppByteCnt = pH->next - sc->next;	    }	else	    {	    wrapSize = (SMC8013WC_PSTOP - sc->next) << 8;	    uppByteCnt = (SMC8013WC_PSTOP - sc->next) + 			 (pH->next - SMC8013WC_PSTART);	    }	if (pH->lowByteCnt > 0xfc)	    uppByteCnt -= 2;	else	    uppByteCnt -= 1;	packetSize = (uppByteCnt << 8) | pH->lowByteCnt;	pH->uppByteCnt = uppByteCnt;	if (wrapSize > packetSize)	    wrapSize = 0;	/* copy separated frame to a temporary buffer */	if (wrapSize)	    {	    sc->elcStat.wrapped++;	    pSrc = (char *)pH;	    pDst = (char *)sc->receiveBuf;	    bcopy (pSrc, pDst, wrapSize);	    pSrc = (char *)(sc->memAddr + (SMC8013WC_PSTART << 8));	    pDst += wrapSize;	    len = packetSize - wrapSize;	    if (len)		bcopy (pSrc, pDst, len);	    }        len = packetSize - 4;			/* remove CRCs 4 bytes */        if (wrapSize)	    eh = (struct ether_header *)((UINT)sc->receiveBuf + 		sizeof (ELC_HEADER));        else	    eh = (struct ether_header *)((UINT)pH + sizeof (ELC_HEADER));        /* call input hook if any */        if ((etherInputHookRtn != NULL) &&	    (* etherInputHookRtn) (&sc->es_if, (char *) eh, len))	    {	    goto doneGet;	    }        if (len >= SIZEOF_ETHERHEADER)            len -= SIZEOF_ETHERHEADER;        else            {            sc->es_if.if_ierrors++;         /* bump error statistic */	    goto doneGet;            }        pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;#ifdef BSD43_DRIVER        check_trailer (eh, pData, &len, &off, &sc->es_if);        /* copy data from the ring buffer to mbuf a long-word at a time */                m = bcopy_to_mbufs (pData, len, off, (struct ifnet *) &sc->es_if, 2);        if (m == NULL)            {            sc->es_if.if_ierrors++;         /* bump error statistic */	    goto doneGet;            }

⌨️ 快捷键说明

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