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

📄 if_seeq.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* if_seeq.c - Seeq 8005 Ethernet network interface driver *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01a,21apr96,mem  written, based on other drivers.*//*This module implements the Seeq 8005 Ethernet network interfacedriver.This driver was originally developed for the Motorola IDP ethernetcard.At this time, the driver makes the following assumptions:  - A 16-bit path to the SEEQ chip is available.This driver is designed to be moderately generic, operating unmodifiedacross the range of architectures and targets supported by VxWorks.To achieve this, the driver must be given several target-specificparameters, and some external support routines must be provided.These parameters, and the mechanisms used to communicate them to thedriver, are detailed below.  If any of the assumptions stated beloware not true for your particular hardware, this driver will probablynot function correctly with it.BOARD LAYOUTWe have yet to see documentation on the jumpers, so don't change them.EXTERNAL INTERFACEThis driver provides the standard external interface with thefollowing exceptions.  All initialization is performed within theattach routine; there is no separate initialization routine.Therefore, in the global interface structure, the function pointer tothe initialization routine is NULL.The only user-callable routine is seeqattach(), which publishes the`seeq' interface and initializes the driver and device.TARGET-SPECIFIC PARAMETERS.iP "base address of device registers"This parameter is passed to the driver by seeqattach().  It indicatesto the driver where to find the device registers..iP "interrupt vector"This parameter is passed to the driver by seeqattach()..iP "interrupt level"This parameter is passed to the driver by seeqattach()..iP "Ethernet address"This parameter is obtained directly from a global memory location.During initialization, the driver needs to know the Ethernet address forthe SEEQ device.  The driver assumes that this address is available ina global, six-byte character array, seeqEnetAddr[].  This array istypically created and stuffed by the BSP code..LPSYSTEM RESOURCE USAGEWhen implemented, this driver requires the following system resources:    - one interrupt vector    - one watchdog timer    - 12 bytes in the initialized data section (data)    - 4264 bytes in the uninitialized data section (BSS)    - 4096 bytes of allocated buffer space.The above data and BSS requirements are for the MCF5200 architectureand may vary for other architectures.  Code size (text) varies greatlybetween architectures and is therefore not quoted here.SEE ALSO: ifLib, .I "SEEQ 8005 Advanced Ethernet Data Link Controller"*//* includes */#include "vxWorks.h"#include "stdlib.h"#include "taskLib.h"#include "logLib.h"#include "intLib.h"#include "netLib.h"#include "stdio.h"#include "stdlib.h"#include "sysLib.h"#include "wdLib.h"#include "iv.h"#include "memLib.h"#include "sys/ioctl.h"#include "etherLib.h"#ifndef DOC             /* don't include when building documentation */#include "net/mbuf.h"#endif  /* DOC */#include "net/protosw.h"#include "sys/socket.h"#include "errno.h"#include "net/if.h"#include "net/route.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/if_ether.h"#include "net/if_subr.h"#include "semLib.h"/*HELP#include "drv/netif/if_seeq.h"            /* device description header */#include "if_seeq.h"            /* device description header *//* defines */#define DEBUG#define MAX_UNITS		1	/* maximum units supported */#define SEEQ_TX_OUTSTANDING	1	/* seeqTransmit outstanding */#define SEEQ_RX_OUTSTANDING	2	/* seeqReceive outstanding *//* Offset to LSB */#if _BYTE_ORDER == _BIG_ENDIAN#define SEEQ_LSB_OFFSET		1	/* offset to LSB */#define SEEQ_MSB_SHIFT		8	/* shift to MSB */#define SEEQ_CFG2_BSWAP 	SEEQ_CONF2_BYTE_SWAP /* config2 bswap bit */#else /* _BYTE_ORDER == _BIG_ENDIAN */#define SEEQ_LSB_OFFSET		0	/* offset to LSB */#define SEEQ_MSB_SHIFT		0	/* shift to MSB */#define SEEQ_CFG2_BSWAP 	0	/* config2 bswap bit */#endif /* _BYTE_ORDER == _BIG_ENDIAN *//* How much free space is in the TX buffer */#define TX_SPACE(pDrv) \	(((pDrv)->txNext < (pDrv)->txCurr) \	 ? ((pDrv)->txCurr - (pDrv)->txNext) \	 : ((((pDrv)->tea + 1) << 8) - ((pDrv)->txNext - (pDrv)->txCurr)))/* 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 ex_msg EX_MSG;               /* an EXOS message *//* The definition of the driver control structure */typedef struct drv_ctrl		/* DRV_CTRL */    {    IDR		idr;		/* Interface Data Record */    int		unit;		/* unit # */    BOOL	attached;	/* indicates unit is attached */    int		flags;		/* misc flags */    int		inum;		/* interrupt number */    int		ilevel;		/* interrupt level */    SEEQ_DEVICE	*devAdrs;	/* device structure address */    WDOG_ID	watchDog;	/* watchDog for waiting for chip */    BOOL	expired;	/* flag watchDog has expired */    USHORT	rea;		/* receive end area */    UINT	rxNext;		/* local buffer pointer for next packet */    UCHAR	*rxBuf;		/* receive buffer */    int		txCount;	/* # packets waiting to transmit */    USHORT	tea;		/* transmit end area */    UINT	txEnd;		/* end of tx area */    UINT	txCurr;		/* end of current xmit packet */    UINT	txNext;		/* local buffer pointer for next packet */    UCHAR	*txBuf;		/* transmit buffer */    int		txLow;		/* count of TX low reports */    } DRV_CTRL;#define DRV_CTRL_SIZ    sizeof(DRV_CTRL)/* globals */IMPORT	UCHAR	seeqEnetAddr []; /* Ethernet address to load */#ifdef DEBUGBOOL	seeqDebug = 0;#endifint	seeqIntCnt = 0;int	seeqTimeoutCnt = 0;/* locals */LOCAL	DRV_CTRL  drvCtrl [MAX_UNITS];/* forward declarations */IMPORT	void ether_attach ();	void	seeqChipReset (int unit);	void	seeqRxReset (int unit);	void	seeqTxReset (int unit);	void	seeqInt	(int unit);LOCAL	void	seeqReset (int unit);LOCAL	void	seeqReceive (int unit);LOCAL	void	seeqTransmit (int unit);LOCAL	void	seeqStart (int unit);LOCAL	int	seeqOutput (IDR *ifp, MBUF *m0, SOCK *dst);LOCAL	int	seeqIoctl (IDR *ifp, int cmd, caddr_t data);LOCAL	void	seeqTimeout (DRV_CTRL *pDrvCtrl);LOCAL	STATUS	seeqFlushFIFO (DRV_CTRL *pDrvCtrl);LOCAL	STATUS	seeqSetDMARead (DRV_CTRL *pDrvCtrl, USHORT addr);LOCAL	STATUS	seeqSetDMAWrite (DRV_CTRL *pDrvCtrl, USHORT addr);#ifndef SEEQ_READ#define SEEQ_READ(reg) \	*(USHORT *)(reg)#endif#ifndef SEEQ_READ_BYTE#define SEEQ_READ_BYTE(reg) \	*((volatile UCHAR *)(reg))#endif#ifndef SEEQ_WRITE#define SEEQ_WRITE(reg,data) \	*(USHORT *)(reg) = (USHORT)data#endif#ifndef SEEQ_WRITE_BYTE#define SEEQ_WRITE_BYTE(reg,data) \	*(volatile UCHAR *)(reg) = (UCHAR)data#endif/******************************************************************************** seeqattach - publish the `seeq' network interface and initialize*		the driver and device** This routine publishes the `seeq' 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 seeqattach    (    int	      unit,		/* unit number */    char     *devAdrs,		/* SEEQ I/O address */    int	      inum,		/* interrupt number */    int	      ilevel		/* interrupt level */    )    {    DRV_CTRL *pDrvCtrl;    /* Sanity check the unit number */    if (unit < 0 || unit >= MAX_UNITS)	return (ERROR);    /* Ensure single invocation per system life */    pDrvCtrl = & drvCtrl [unit];    if (pDrvCtrl->attached)	return (OK);    if ((pDrvCtrl->watchDog = wdCreate()) == NULL)	return (ERROR);    if (!(pDrvCtrl->txBuf = (UCHAR *) malloc (2048)))	{	wdDelete (pDrvCtrl->watchDog);	return (ERROR);	}    if (!(pDrvCtrl->rxBuf = (UCHAR *) malloc (2048)))	{	wdDelete (pDrvCtrl->watchDog);	free (pDrvCtrl->rxBuf);	return (ERROR);	}    /* Publish the interface data record */    ether_attach (&pDrvCtrl->idr.ac_if, unit, "seeq",		  (FUNCPTR) NULL, (FUNCPTR) seeqIoctl,		  (FUNCPTR) seeqOutput, (FUNCPTR) seeqReset);    /* Save some values */    pDrvCtrl->inum	 = inum;		 /* interrupt vector */    pDrvCtrl->ilevel	 = ilevel;		 /* interrupt level */    pDrvCtrl->devAdrs	 = (SEEQ_DEVICE *)devAdrs; /* SEEQ I/O address */    /* Obtain our Ethernet address and save it */    bcopy ((char *) seeqEnetAddr, (char *) pDrvCtrl->idr.ac_enaddr, 6);    if (intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC(inum), seeqInt, unit) == ERROR)	return (ERROR);    /* Reset the device */    seeqChipReset (pDrvCtrl->unit);    /* The interface is now up. */    pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);    /* Set our flag */    pDrvCtrl->attached = TRUE;    /*     * Enable the receiver, enable TX & RX interrupts,     * ack any pending interrupts.     */    SEEQ_WRITE	(pDrvCtrl->devAdrs->pCmd,		SEEQ_CMD_RX_ON  | SEEQ_CMD_RX_EN		| SEEQ_CMD_TX_OFF | SEEQ_CMD_TX_EN		| SEEQ_CMD_ALL_ACK);    return (OK);    }/******************************************************************************** seeqTimeout - note that the watchdog timer has expired.** NOMANUAL*/LOCAL void seeqTimeout    (    DRV_CTRL  *pDrvCtrl    )    {#ifdef DEBUG    if (seeqDebug)	logMsg ("seeqTimeout(%x)\n", (int) pDrvCtrl, 0, 0, 0, 0, 0);#endif    ++seeqTimeoutCnt;    pDrvCtrl->expired = TRUE;    }/******************************************************************************** seeqFlushFIFO - Wait for the seeq DMA FIFO to flush** NOMANUAL*/LOCAL STATUS seeqFlushFIFO    (    DRV_CTRL  *pDrvCtrl    )    {    SEEQ_DEVICE *pDev = pDrvCtrl->devAdrs;    pDrvCtrl->expired = FALSE;    wdStart (pDrvCtrl->watchDog, 2 * sysClkRateGet(),	     (FUNCPTR) seeqTimeout, (int) pDrvCtrl);    /* flush the FIFO */    while (!(SEEQ_READ(pDev->pStat) & SEEQ_STAT_FIFO_EMPTY)       && !pDrvCtrl->expired)	taskDelay(1);    wdCancel (pDrvCtrl->watchDog);    if (pDrvCtrl->expired)	return (ERROR);    return (OK);    }/******************************************************************************** seeqSetDMARead - Setup the FIFO for reading** NOMANUAL*/LOCAL STATUS seeqSetDMARead    (    DRV_CTRL  *pDrvCtrl,    USHORT    addr    )    {    SEEQ_DEVICE *pDev = pDrvCtrl->devAdrs;    /* Point into local buffer memory */    SEEQ_WRITE (pDev->pCfg1, ((SEEQ_READ(pDev->pCfg1) & 0xfff0)				| SEEQ_CONF1_LBUFFER));        /* Wait for FIFO ready if in write direction */    if (!(SEEQ_READ(pDev->pCmd) & SEEQ_STAT_FIFO_DIR))	if (seeqFlushFIFO (pDrvCtrl) != OK)	    return (ERROR);    /* Set DMA address */    SEEQ_WRITE (pDev->pDma, addr);    /* Set direction to read */    SEEQ_WRITE (pDev->pCmd, ((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK)					| SEEQ_CMD_FIFO_READ) );    pDrvCtrl->expired = FALSE;    wdStart (pDrvCtrl->watchDog, 2 * sysClkRateGet(),	     (FUNCPTR) seeqTimeout, (int) pDrvCtrl);    /* Wait for ready */    while (!(SEEQ_READ(pDev->pStat) & SEEQ_STAT_BUF_INT) && !pDrvCtrl->expired)	taskDelay(1);    wdCancel (pDrvCtrl->watchDog);    /* ack buffer window interrupt */    SEEQ_WRITE (pDev->pCmd, ((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK)				    | SEEQ_CMD_BUF_ACK));    if (pDrvCtrl->expired)	return (ERROR);    return (OK);    }/******************************************************************************** seeqSetDMAWrite - Setup the FIFO for writing.** NOMANUAL*/LOCAL STATUS seeqSetDMAWrite    (    DRV_CTRL  *pDrvCtrl,    USHORT    addr    )    {    SEEQ_DEVICE *pDev = pDrvCtrl->devAdrs;    /* Point into local buffer memory */    SEEQ_WRITE (pDev->pCfg1,  ((SEEQ_READ(pDev->pCfg1) & 0xfff0)				| SEEQ_CONF1_LBUFFER));            /* If already in write mode, wait until buffer writing is complete. */    if (SEEQ_READ(pDev->pCmd) & SEEQ_STAT_FIFO_DIR)	{	/* read direction */	SEEQ_WRITE (pDev->pCmd, ((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK)					    | SEEQ_CMD_FIFO_WRITE) );	}    else

⌨️ 快捷键说明

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