📄 if_seeq.c
字号:
/* 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 + -