📄 if_cpm.c
字号:
/* if_cpm.c - Motorola CPM core network interface driver *//* Copyright 1996-1998 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01f,13apr98,map modified SCC_DEV to SCC_ETHER_DEV.01e,15jul97,spm removed driver initialization from ioctl support (SPR #8831); corrected wait in reset routine; changed interrupt handler to match if_qu driver01d,07apr97,spm code cleanup, corrected statistics, and upgraded to BSD 4.401c,06nov96,dgp doc: final formatting01b,06aug96,dat fixed scce register handling, and interrupt service rtn01a,09may96,dzb derived from v01e of src/drv/netif/if_qu.c.*//*DESCRIPTIONThis module implements the driver for the Motorola CPM core Ethernet networkinterface used in the M68EN360 and PPC800-series communications controllers.The driver is designed to support the Ethernet mode of an SCC residing on theCPM processor core. It is generic in the sense that it does not carewhich SCC is being used, and it supports up to four individual units per board.The driver must be given several target-specific parameters, and some externalsupport routines must be provided. These parameters, and the mechanisms usedto communicate them to the driver, are detailed below.This network interface driver does not include support for trailer protocolsor data chaining. However, buffer loaning has been implemented in an effort toboost performance. This driver provides support for four individual device units.This driver maintains cache coherency by allocating buffer space using thecacheDmaMalloc() routine. It is assumed that cache-safe memory is returned;this driver does not perform cache flushing and invalidating.BOARD LAYOUTThis device is on-chip. No jumpering diagram is necessary.EXTERNAL INTERFACEThis driver presents the standard WRS network driver API: the deviceunit must be attached and initialized with the cpmattach() routine.The only user-callable routine is cpmattach(), which publishes the `cpm'interface and initializes the driver structures.TARGET-SPECIFIC PARAMETERSThese parameters are passed to the driver via cpmattach()..iP "address of SCC parameter RAM"This parameter is the address of the parameter RAM used to control theSCC. Through this address, and the address of the SCCregisters (see below), different network interface units are able to usedifferent SCCs without conflict. This parameter points to the internalmemory of the chip where the SCC physically resides, which may not necessarilybe the master chip on the target board..iP "address of SCC registers"This parameter is the address of the registers used to control theSCC. Through this address, and the address of the SCCparameter RAM (see above), different network interface units are able to usedifferent SCCs without conflict. This parameter points to the internalmemory of the chip where the SCC physically resides, which may not necessarilybe the master chip on the target board..iP "interrupt-vector offset"This driver configures the SCC to generate hardware interruptsfor various events within the device. The interrupt-vector offsetparameter is used to connect the driver's ISR to the interrupt througha call to intConnect()..iP "address of transmit and receive buffer descriptors"These parameters indicate the base locations of the transmit and receivebuffer descriptor (BD) rings. Each BD takes up 8 bytes ofdual-ported RAM, and it is the user's responsibility to ensure that allspecified BDs will fit within dual-ported RAM. This includes any otherBDs the target board may be using, including other SCCs, SMCs, and theSPI device. There is no default for these parameters; they must beprovided by the user..iP "number of transmit and receive buffer descriptors"The number of transmit and receive buffer descriptors (BDs) used isconfigurable by the user upon attaching the driver. Each bufferdescriptor resides in 8 bytes of the chip's dual-ported RAM space,and each one points to a 1520-byte buffer in regular RAM. There mustbe a minimum of two transmit and two receive BDs. There is no maximumnumber of buffers, but there is a limit to how much the driver speed increasesas more buffers are added, and dual-ported RAM space is at a premium.If this parameter is "NULL", a default value of 32 BDs is used..iP "base address of buffer pool"This parameter is used to notify the driver that space for the transmitand receive buffers need not be allocated, but should be taken from acache-coherent private memory space provided by the user at the givenaddress. The user should be aware that memory used for buffers must be4-byte aligned and non-cacheable. All the buffersmust fit in the given memory space; no checking is performed.This includes all transmit and receive buffers (see above) and anadditional 16 receive loaner buffers. If the number of receiveBDs is less than 16, that number of loaner buffers isused. Each buffer is 1520 bytes. If this parameter is "NONE," spacefor buffers is obtained by calling cacheDmaMalloc() in cpmattach()..LPEXTERNAL SUPPORT REQUIREMENTSThis driver requires seven external support functions:.iP "STATUS sysCpmEnetEnable (int unit)" "" 9 -1This routine is expected to perform any target-specific functions requiredto enable the Ethernet controller. These functions typically includeenabling the Transmit Enable signal (TENA) and connecting the transmitand receive clocks to the SCC.The driver calls this routine, once per unit, from the cpmInit() routine..iP "void sysCpmEnetDisable (int unit)"This routine is expected to perform any target-specific functions requiredto disable the Ethernet controller. This usually involves disabling theTransmit Enable (TENA) signal.The driver calls this routine from the cpmReset() routine each time a unitis disabled..iP "STATUS sysCpmEnetCommand (int unit, UINT16 command)"This routine is expected to issue a command to the Ethernet interfacecontroller. The driver calls this routine to perform basic commands,such as restarting the transmitter and stopping reception..iP "void sysCpmEnetIntEnable (int unit)"This routine is expected to enable the interrupt for the Ethernet interfacespecified by <unit>..iP "void sysCpmEnetIntDisable (int unit)"This routine is expected to disable the interrupt for the Ethernet interfacespecified by <unit>..iP "void sysCpmEnetIntClear (int unit)"This routine is expected to clear the interrupt for the Ethernet interfacespecified by <unit>..iP "STATUS sysCpmEnetAddrGet (int unit, UINT8 * addr)"The driver expects this routine to provide the 6-byte Ethernethardware address that will be used by <unit>. This routine must copythe 6-byte address to the space provided by <addr>. This routine isexpected to return OK on success, or ERROR.The driver calls this routine, once per unit, from the cpmInit() routine..LPSYSTEM RESOURCE USAGEThis driver requires the following system resources: - one mutual exclusion semaphore - one interrupt vector - 0 bytes in the initialized data section (data) - 1272 bytes in the uninitialized data section (BSS) The data and BSS sections are quoted for the CPU32 architecture and may varyfor other architectures. The code size (text) varies greatly betweenarchitectures, and is therefore not quoted here.If the driver allocates the memory shared with the Ethernet device unit,it does so by calling the cacheDmaMalloc() routine. For the default caseof 32 transmit buffers, 32 receive buffers, and 16 loaner buffers, the totalsize requested is 121,600 bytes. If a non-cacheable memory region is providedby the user, the size of this region should be this amount, unless theuser has specified a different number of transmit or receive BDs.This driver can operate only if the shared memory region is non-cacheable,or if the hardware implements bus snooping. The driver cannot maintaincache coherency for the device because the buffers are asynchronouslymodified by both the driver and the device, and these fields may share thesame cache line. Additionally, the chip's dual ported RAM must bedeclared as non-cacheable memory where applicable.SEE ALSO: ifLib,.I "Motorola MC68EN360 User's Manual",.I "Motorola MPC860 User's Manual",.I "Motorola MPC821 User's Manual"INTERNAL*//* includes */#include "vxWorks.h"#include "iv.h"#include "taskLib.h"#include "memLib.h"#include "ioctl.h"#include "etherLib.h"#include "net/mbuf.h"#include "net/protosw.h"#include "socket.h"#include "errno.h"#include "net/if.h"#include "net/unixLib.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 "cacheLib.h"#include "stdio.h"#include "intLib.h"#include "netLib.h"#include "drv/netif/netifDev.h"#include "drv/netif/if_cpm.h"/* defines */#define MAX_UNITS 4 /* max cpm units */#define ENET_ADDR_SIZE 0x6 /* size of Ethernet src/dest addresses */#define TX_BD_MIN 2 /* minimum number of Tx buffer descriptors */#define RX_BD_MIN 2 /* minimum number of Rx buffer descriptors */#define TX_BD_DEFAULT 0x20 /* default number of Tx buffer descriptors */#define RX_BD_DEFAULT 0x20 /* default number of Rx buffer descriptors */#define FRAME_MAX 0x05ee /* maximum frame size */#define FRAME_MAX_AL 0x05f0 /* maximum frame size, 4 byte alligned */#define FRAME_MIN 0x0040 /* minimum frame size */#define L_POOL 0x10 /* number of Rx loaner buffers in pool *//* typedefs */typedef struct mbuf MBUF;typedef struct arpcom IDR; /* Interface Data Record */typedef struct ifnet IFNET;typedef struct sockaddr SOCK;typedef struct drv_ctrl /* DRV_CTRL */ { IDR idr; /* Interface Data Record */ BOOL attached; /* indicates unit is attached */ BOOL txStop; /* emergency stop output */ int nLoanRxBd; /* number of receive buffers left to loan */ UINT8 * lPool[L_POOL]; /* receive BD loaner pool */ UINT8 * pRefCnt[L_POOL];/* stack of reference count pointers */ UINT8 refCnt[L_POOL]; /* actual reference count values */ SCC_ETHER_DEV ether; /* Ethernet SCC device */ } DRV_CTRL;/* globals */IMPORT STATUS sysCpmEnetEnable (int unit);IMPORT void sysCpmEnetDisable (int unit);IMPORT STATUS sysCpmEnetAddrGet (int unit, UINT8 * addr);IMPORT STATUS sysCpmEnetCommand (int unit, UINT16 command);IMPORT void sysCpmEnetIntEnable (int unit);IMPORT void sysCpmEnetIntDisable (int unit);IMPORT void sysCpmEnetIntClear (int unit);/* locals */LOCAL DRV_CTRL drvCtrl[MAX_UNITS]; /* array of driver control *//* forward declarations */#ifdef __STDC__LOCAL STATUS cpmInit (int unit);#ifdef BSD43_DRIVERLOCAL int cpmOutput (IFNET * pIfNet, MBUF * pMbuf, SOCK * pSock);LOCAL void cpmStartOutput (int unit);#elseLOCAL void cpmStartOutput (DRV_CTRL * pDrvCtrl);#endifLOCAL int cpmIoctl (IFNET * pIfNet, int cmd, caddr_t data);LOCAL STATUS cpmReset (int unit);LOCAL void cpmIntr (int unit);LOCAL void cpmTxRestart (int unit);LOCAL void cpmHandleInt (DRV_CTRL * pDrvCtrl);LOCAL void cpmRecv (DRV_CTRL * pDrvCtrl, SCC_BUF * pRxBd);LOCAL void cpmLoanFree (DRV_CTRL * pDrvCtrl, UINT8 * pRxBuf, UINT8 * pRef);#else /* __STDC__ */LOCAL STATUS cpmInit ();LOCAL int cpmOutput ();LOCAL void cpmStartOutput ();LOCAL int cpmIoctl ();LOCAL STATUS cpmReset ();LOCAL void cpmIntr ();LOCAL void cpmTxRestart ();LOCAL void cpmHandleInt ();LOCAL void cpmRecv (); LOCAL void cpmLoanFree (); #endif /* __STDC__ *//********************************************************************************* cpmattach - publish the `cpm' network interface and initialize the driver** The routine publishes the `cpm' interface by filling in a network Interface* Data Record (IDR) and adding this record to the system's interface list.** The SCC shares a region of memory with the driver. The caller of this* routine can specify the address of a shared, non-cacheable memory region* with <bufBase>. If this parameter is NONE, the driver obtains this* memory region by calling cacheDmaMalloc(). Non-cacheable memory space* is important for cases where the SCC is operating with a processor* that has a data cache.** Once non-cacheable memory is obtained, this routine divides up the* memory between the various buffer descriptors (BDs). The number* of BDs can be specified by <txBdNum> and <rxBdNum>, or if NULL, a* default value of 32 BDs will be used. Additional buffers are* reserved as receive loaner buffers. The number of loaner buffers is the* lesser of <rxBdNum> and a default value of 16.** The user must specify the location of the transmit and receive BDs in* the CPU's dual-ported RAM. <txBdBase> and <rxBdBase> give the* base address of the BD rings. Each BD uses 8 bytes. Care must be taken so* that the specified locations for Ethernet BDs do not conflict with other* dual-ported RAM structures. ** Up to four individual device units are supported by this driver. Device* units may reside on different processor chips, or may be on different SCCs* within a single CPU.* * Before this routine returns, it calls cpmReset() and cpmInit() to * configure the Ethernet controller, and connects the interrupt vector <ivec>.** RETURNS: OK or ERROR.** SEE ALSO: ifLib,* .I "Motorola MC68360 User's Manual",* .I "Motorola MPC821 and MPC860 User's Manual"*/STATUS cpmattach ( int unit, /* unit number */ SCC * pScc, /* address of SCC parameter RAM */ SCC_REG * pSccReg, /* address of SCC registers */ VOIDFUNCPTR * ivec, /* interrupt vector offset */ SCC_BUF * txBdBase, /* transmit buffer descriptor base address */ SCC_BUF * rxBdBase, /* receive buffer descriptor base address */ int txBdNum, /* number of transmit buffer descriptors */ int rxBdNum, /* number of receive buffer descriptors */ UINT8 * bufBase /* address of memory pool; NONE = malloc it */ ) { DRV_CTRL * pDrvCtrl; int counter; int loanNum = L_POOL; UINT8 * txBuf; UINT8 * rxBuf; UINT8 * loanBuf; if (unit < 0 || unit >= MAX_UNITS) /* sanity check the unit number */ return (ERROR); pDrvCtrl = & drvCtrl[unit]; /* ensure single invocation */ if (pDrvCtrl->attached) return (ERROR); /* do a quick check of input parameters */ if (txBdBase == rxBdBase) return (ERROR); /* publish the Interface Data Record */#ifdef BSD43_DRIVER ether_attach (& pDrvCtrl->idr.ac_if, unit, "cpm", (FUNCPTR) cpmInit, (FUNCPTR) cpmIoctl, (FUNCPTR) cpmOutput, (FUNCPTR) cpmReset);#else ether_attach ( &pDrvCtrl->idr.ac_if, unit, "cpm", (FUNCPTR) cpmInit, (FUNCPTR) cpmIoctl, (FUNCPTR) ether_output, (FUNCPTR) cpmReset ); pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)cpmStartOutput;#endif /* use default number of buffer descriptors if user did not specify */ if (txBdNum == NULL) txBdNum = TX_BD_DEFAULT; if (rxBdNum == NULL) rxBdNum = RX_BD_DEFAULT; /* must be at least two transmit and receive buffer descriptors */ txBdNum = max (TX_BD_MIN, txBdNum); rxBdNum = max (RX_BD_MIN, rxBdNum); loanNum = min (rxBdNum, loanNum); /* fill in driver control structure for <unit> */ pDrvCtrl->nLoanRxBd = loanNum; pDrvCtrl->ether.txBdNum = txBdNum; pDrvCtrl->ether.rxBdNum = rxBdNum; pDrvCtrl->ether.txBdBase = txBdBase; pDrvCtrl->ether.rxBdBase = rxBdBase; pDrvCtrl->ether.txBufSize = FRAME_MAX_AL; pDrvCtrl->ether.rxBufSize = FRAME_MAX_AL; pDrvCtrl->ether.pScc = pScc; pDrvCtrl->ether.pSccReg = pSccReg; /* set up Rx and Tx buffers */ if (bufBase == (UINT8 *) NONE) { /* allocate memory pools */ txBuf = cacheDmaMalloc (txBdNum * pDrvCtrl->ether.txBufSize); if (txBuf == NULL) return (ERROR); rxBuf = cacheDmaMalloc (rxBdNum * pDrvCtrl->ether.rxBufSize); if (rxBuf == NULL) { free (txBuf); return (ERROR); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -