📄 if_mbc.c
字号:
/* if_mbc.c - Motorola 68EN302 network-interface driver *//* Copyright 1996-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01h,15jul97,spm removed driver initialization from ioctl support (SPR #8831)01g,07apr97,spm code cleanup, corrected statistics, and upgraded to BSD 4.401h,06jun97,map renamed mbcRestartTx to mbcDeviceRestart, code to retart device on rx FIFO overflow problem [SPR# 8670]01g,07may97,map corrected rx buffer initialization loop [SPR# 8481]01f,06nov96,dgp doc: final formatting01e,20aug96,map doc updates01d,12aug96,map made mbcIntr global01c,09aug96,map clean compiler warnings in mbcattach()01b,08aug96,map modified for en302 ethernet01a,09may96,dzb derived from v01a of src/drv/netif/if_cpm.c.*//*DESCRIPTIONThis is a driver for the Ethernet controller on the 68EN302 chip. The devicesupports a 16-bit interface, data rates up to 10 Mbps, a dual-ported RAM, andtransparent DMA. The dual-ported RAM is used for a 64-entry CAM table, and a128-entry buffer descriptor table. The CAM table is used to set the Ethernetaddress of the Ethernet device or to program multicast addresses. The bufferdescriptor table is partitioned into fixed-size transmit and receive tables.The DMA operation is transparent and transfers data between the internal FIFOsand external buffers pointed to by the receive- and transmit-buffer descriptorsduring transmits and receives.The driver currently supports one Ethernet module controller, but it can beextended to support multiple controllers when needed. An Ethernet moduleis initialized by calling mbcattach().The driver supports buffer loaning for performance and input/output hookroutines. It does not support multicast addresses.The driver requires that the memory used for transmit and receive buffers beallocated in cache-safe RAM area. A glitch in the EN302 Rev 0.1 device causes the Ethernet transmitter tolock up from time to time. The driver uses a watchdog timer to reset theEthernet device when the device runs out of transmit buffers and cannotrecover within 20 clock ticks.BOARD LAYOUTThis device is on-chip. No jumpering diagram is necessary. EXTERNAL INTERFACEThis driver presents the standard WRS network driver API: first the deviceunit must be attached with the mbcattach() routine, then it must beinitialized with the mbcInit() routine.The only user-callable routine is mbcattach(), which publishes the `mbc'interface and initializes the driver structures.TARGET-SPECIFIC PARAMETERS.iP "Ethernet module base address"This parameter is passed to the driver via mbcattach().This parameter is the base address of the Ethernet module. The driveraddresses all other Ethernet device registers as offsets from this address..iP "interrupt vector number"This parameter is passed to the driver via mbcattach().The driver configures the Ethernet device to use this parameter whilegenerating interrupt ack cycles. The interrupt service routine mbcIntr() isexpected to be attached to the corresponding interrupt vector externally,typically in sysHwInit2()..iP "number of transmit and receive buffer descriptors"These parameters are passed to the driver via mbcattach().The number of transmit and receive buffer descriptors (BDs) used isconfigurable by the user while attaching the driver. Each BD is 8 bytes insize and resides in the chip's dual-ported memory, while its associatedbuffer, 1520 bytes in size, resides in cache-safe conventional RAM. A minimumof 2 receive and 2 transmit BDs should be allocated. If this parameter isNULL, a default of 32 BDs will be used. The maximum number of BDs depends onhow the dual-ported BD RAM is partitioned. The 128 BDs in the dual-ported BDRAM can partitioned into transmit and receive BD regions with 8, 16, 32, or 64transmit BDs and corresponding 120, 112, 96, or 64 receive BDs..iP "Ethernet DMA parameters"This parameter is passed to the driver via mbcattach().This parameter is used to specify the settings of burst limit, water-mark, andtransmit early, which control the Ethernet DMA, and is used to set the EDMAregister..iP "base address of the buffer pool"This parameter is passed to the driver via mbcattach().This parameter is used to notify the driver that space for the transmit andreceive buffers need not be allocated, but should be taken from acache-coherent private memory space provided by the user at the given address.The user should be aware that memory used for buffers must be 4-byte alignedand non-cacheable. All the buffers must fit in the given memory space; nochecking will be performed. This includes all transmit and receive buffers(see above) and an additional 16 receive loaner buffers, unless the number ofreceive BDs is less than 16, in which case that number of loaner buffers willbe used. Each buffer is 1520 bytes. If this parameter is "NONE", space forbuffers will be obtained by calling cacheDmaMalloc() in cpmattach()..LPEXTERNAL SUPPORT REQUIREMENTSThe driver requires the following support functions:.iP "STATUS sysEnetAddrGet (int unit, UINT8 * addr)" "" 9 -1The driver expects this routine to provide the six-byte Ethernet hardwareaddress that will be used by <unit>. This routine must copy the six-byteaddress to the space provided by <addr>. This routine is expected to returnOK on success, or ERROR. The driver calls this routine, during deviceinitialization, from the cpmInit() routine..LPSYSTEM RESOURCE USAGEThe driver requires the following system resource: - one mutual exclusion semaphore - one interrupt vector - one watchdog timer - 0 bytes in the initialized data section (data) - 296 bytes in the uninitialized data section (bss)The data and BSS sections are quoted for the CPU32 architecture.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 only operate 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 MC68EN302 User's Manual",.I "Motorola MC68EN302 Device Errata, May 30, 1996"*//* 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_mbc.h"#include "wdLib.h"/* defines */#define MAX_UNITS 1 /* max ethernet 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 TX_BUF_SIZE FRAME_MAX /* size of a transmit buffer */#define RX_BUF_SIZE FRAME_MAX /* size of a receive buffer */#define FRAME_MIN 0x0040 /* minimum frame size */#define L_POOL 0x10 /* number of Rx loaner buffers in pool */#define WD_TIMEOUT 20 /* number of clock ticks for reset timeout*//* register access macros */#ifndef MBC_REG_READ# define MBC_REG_READ(b, r) (*(UINT16 *)((b) + (r)))#endif /* MBC_REG_READ */#ifndef MBC_REG_WRITE# define MBC_REG_WRITE(b, r, v) (*(UINT16 *)((b) + (r)) = (v))#endif /* MBC_REG_WRITE */#define MBC_REG_UPDATE(b, r, v) MBC_REG_WRITE((b), (r), \ MBC_REG_READ((b), (r)) |(v))#define MBC_REG_RESET(b, r, v) MBC_REG_WRITE((b), (r), \ MBC_REG_READ((b), (r)) & ~(v))#define MBC_IEVNT_READ(b) MBC_REG_READ((b), MBC_IEVNT)#define MBC_IMASK_READ(b) MBC_REG_READ((b), MBC_IMASK)#define MBC_ECNTL_READ(b) MBC_REG_READ((b), MBC_ECNTL)#define MBC_INTR_ACK(b, v) MBC_REG_WRITE((b), MBC_IEVNT, (v))#define MBC_INTR_DISABLE(b, v) MBC_REG_RESET((b), MBC_IMASK, (v))#define MBC_INTR_ENABLE(b, v) MBC_REG_UPDATE((b), MBC_IMASK, (v)) /* typedefs */typedef struct mbuf MBUF;typedef struct arpcom IDR; /* Interface Data Record */typedef struct ifnet IFNET;typedef struct ifreq IFREQ;typedef struct sockaddr SOCK;typedef struct drv_ctrl /* DRV_CTRL */ { IDR idr; /* mbc interface data record */ BOOL initialized; /* inidicates that the unit is initialized */ int nLoan; /* number of buffers in the loaner pool */ UINT8 * lPool[L_POOL]; /* loaner pool */ UINT8 refCnt[L_POOL]; /* loaner buffer reference counters */ UINT8 * pRefCnt[L_POOL];/* pointer to the reference counters */ MBC_DEV ether; /* mbc device */ UINT16 resetCounter; /* number of times the device was reset */ WDOG_ID wdId; /* watchdog id */ UINT16 inum; /* interrupt number */ UINT16 dmaParms; /* DMA parameters */ } DRV_CTRL;/* globals */IMPORT STATUS sysEnetAddrGet (int unit, UINT8 * addr);IMPORT void sysMbcDmaParmGet (int unit, UINT16 * pParm);/* locals */LOCAL DRV_CTRL drvCtrl[MAX_UNITS]; /* forward declarations */LOCAL STATUS mbcInit (int uint);LOCAL int mbcIoctl (IFNET * pIfNet, int cmd, caddr_t data);#ifdef BSD43_DRIVERLOCAL int mbcOutput (IFNET * pIfNet, MBUF * pMbuf, SOCK * pSock);#endifLOCAL void mbcReset (int uint);#ifdef BSD43_DRIVERLOCAL void mbcStartOutput (int unit);#elseLOCAL void mbcStartOutput (DRV_CTRL *pDrvCtrl);#endifLOCAL void mbcHandleInt (DRV_CTRL * pDrvCtrl);LOCAL void mbcDeviceRestart (int unit);LOCAL void mbcRecv (DRV_CTRL * pDrvCtrl, MBC_BD * pRxBd);LOCAL void mbcLoanFree (DRV_CTRL * pDrvCtrl, UINT8 * pRxBuf, UINT8 * pRefCnt);void mbcIntr (int unit);/********************************************************************************* mbcattach - publish the `mbc' network interface and initialize the driver** The routine publishes the `mbc' interface by adding an `mbc' Interface Data* Record (IDR) to the global network interface list.** The Ethernet controller uses buffer descriptors from an on-chip dual-ported* RAM region, while the buffers are allocated in RAM external to the* controller. The buffer memory pool can be allocated in a non-cacheable RAM* region and passed as parameter <bufBase>. Otherwise <bufBase> is NULL and* the buffer memory pool is allocated by the routine using cacheDmaMalloc().* The driver uses this buffer pool to allocate the specified number of* 1518-byte buffers for transmit, receive, and loaner pools.** The parameters <txBdNum> and <rxBdNum> specify the number of buffers* to allocate for transmit and receive. If either of these parameters* is NULL, the default value of 2 is used. The number of loaner buffers* allocated is the lesser of <rxBdNum> and 16.** The on-chip dual ported RAM can only be partitioned so that the maximum* receive and maximum transmit BDs are:* .iP* Transmit BDs: 8, Receive BDs: 120* .iP* Transmit BDs: 16, Receive BDs: 112* .iP* Transmit BDs: 32, Receive BDs: 96* .iP* Transmit BDs: 64, Receive BDs: 64* .LP** RETURNS: ERROR, if <unit> is out of range> or non-cacheable memory cannot be * allocated; otherwise TRUE.** SEE ALSO: ifLib,* .I "Motorola MC68EN302 User's Manual"*/STATUS mbcattach ( int unit, /* unit number */ void * pEmBase, /* ethernet module base address */ int inum, /* interrupt vector number */ int txBdNum, /* number of transmit buffer descriptors */ int rxBdNum, /* number of receive buffer descriptors */ int dmaParms, /* DMA parameters */ UINT8 * bufBase /* address of memory pool; NONE = malloc it */ ) { DRV_CTRL * pDrvCtrl; MBC_BD * pBd; UINT8 bdSize; UINT8 txBdMax; UINT8 rxBdMax; UINT8 nLoan; UINT8 * txBuf; UINT8 * rxBuf; UINT8 * loanBuf; int counter; /* sanity check - unit number */ if (unit < 0 || unit >= MAX_UNITS) return (ERROR); pDrvCtrl = & drvCtrl[unit]; pDrvCtrl->initialized = FALSE; /* Use default values if the parameters are NULL */ if (txBdNum == NULL) txBdNum = TX_BD_DEFAULT; if (rxBdNum == NULL) rxBdNum = RX_BD_DEFAULT; /* Use the default minimum value if the given value is smaller */ txBdNum = max (TX_BD_MIN, txBdNum); rxBdNum = max (RX_BD_MIN, rxBdNum); /* Ensure that txBdNum, and rxBdNum are within range */ if (txBdNum > 64) txBdNum = 64; for (bdSize = MBC_EDMA_BDS_8; bdSize <= MBC_EDMA_BDS_64; bdSize++) { txBdMax = 1 << (bdSize + 3); /* set txBdMax to (8, 16, 32, 64) */ rxBdMax = MBC_BD_MAX - txBdMax; if (txBdNum <= txBdMax) { if (rxBdNum > rxBdMax) rxBdNum = rxBdMax; break; } } /* set the number of receive loaner buffers */ nLoan = min (rxBdNum, L_POOL); /* fill in the driver control parameters */ pDrvCtrl->nLoan = nLoan; pDrvCtrl->ether.mbcNum = unit; pDrvCtrl->ether.bdSize = bdSize; pDrvCtrl->ether.txBdNum = txBdNum; pDrvCtrl->ether.rxBdNum = rxBdNum; pDrvCtrl->ether.txBdBase = (MBC_BD *) ((int) pEmBase + MBC_EBD); pDrvCtrl->ether.rxBdBase = (MBC_BD *) ((int) pEmBase + MBC_EBD + sizeof (MBC_BD) * (1 << (bdSize + 3))); pDrvCtrl->ether.txBdNext = 0; pDrvCtrl->ether.rxBdNext = 0; pDrvCtrl->ether.pDevBase = pEmBase; pDrvCtrl->resetCounter = 0; pDrvCtrl->inum = inum; pDrvCtrl->dmaParms = dmaParms & (MBC_EDMA_BLIM_MSK | MBC_EDMA_WMRK_MSK | MBC_EDMA_TSRLY); /* create a watchdog timer */ pDrvCtrl->wdId = wdCreate(); if (pDrvCtrl->wdId == NULL) return (ERROR); /* set up the transmit and receive buffers */ if (bufBase == (UINT8 *) NONE) { /* allocate the memory pool */ txBuf = cacheDmaMalloc (txBdNum * TX_BUF_SIZE); if (txBuf == NULL) { wdDelete (pDrvCtrl->wdId); return (ERROR); } rxBuf = cacheDmaMalloc (rxBdNum * RX_BUF_SIZE); if (rxBuf == NULL) { wdDelete (pDrvCtrl->wdId); cacheDmaFree (txBuf); return (ERROR); } loanBuf = cacheDmaMalloc (nLoan * RX_BUF_SIZE); if (loanBuf == NULL) pDrvCtrl->nLoan = nLoan = 0; } else { /* partition memory pool for transmit/receive/loaner buffers */ txBuf = bufBase; rxBuf = txBuf + (txBdNum * TX_BUF_SIZE); loanBuf = rxBuf + (rxBdNum * RX_BUF_SIZE); } /* take the device out of reset state */ MBC_REG_WRITE ((int)pEmBase, MBC_ECNTL, MBC_ECNTL_RES_OFF); /* Associate a buffer with each buffer descriptor */ pBd = pDrvCtrl->ether.txBdBase; for (counter = 0; counter < txBdNum; counter++, pBd++) pBd->dataPointer = txBuf + (counter * TX_BUF_SIZE); pBd = pDrvCtrl->ether.rxBdBase; for (counter = 0; counter < rxBdNum; counter++, pBd++) pBd->dataPointer = rxBuf + (counter * RX_BUF_SIZE); /* Initialize the loaner buffer pool */ for (counter = 0; counter < nLoan; counter++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -