📄 ultraend.c
字号:
/* ultraEnd.c - SMC Ultra Elite END network interface driver *//* Copyright 1984-1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01b,09mar99,sbs changed SYS_INT_ENABLE and SYS_INT_DISABLE to use device specific BSP routines. 01a,06jan99,dra written.*//*DESCRIPTIONThis module implements the SMC Elite Ultra Ethernt network interface driver.This driver supports single transmission and multiple reception. TheCurrent register is a write pointer to the ring. The Bound registeris a read pointer from the ring. This driver gets the Currentregister at the interrupt level and sets the Bound register at thetask level. The interrupt is only masked during configuration or inpolled mode.CONFIGURATIONThe W1 jumper should be set in the position of "Software Configuration".The defined I/O address in config.h must match the one stored in EEROM. The RAM address, the RAM size, and the IRQ level are defined in config.h. IRQ levels 2,3,5,7,10,11,15 are supported.EXTERNAL SUPPORT REQUIREMENTSThis driver requires several external support functions, defined as macros:.CS SYS_INT_CONNECT(pDrvCtrl, routine, arg) SYS_INT_DISCONNECT (pDrvCtrl, routine, arg) SYS_INT_ENABLE(pDrvCtrl) SYS_INT_DISABLE(pDrvCtrl) SYS_IN_BYTE(pDrvCtrl, reg, pData) SYS_OUT_BYTE(pDrvCtrl, reg, pData).CEThese macros allow the driver to be customized for BSPs that usespecial versions of these routines.The macro SYS_INT_CONNECT is used to connect the interrupt handler tothe appropriate vector. By default it is the routine intConnect().The macro SYS_INT_DISCONNECT is used to disconnect the interrupt handler priorto unloading the module. By default this is a dummy routine thatreturns OK.The macro SYS_INT_ENABLE is used to enable the interrupt level for theend device. It is called once during initialization. It calls anexternal board level routine sysUltraIntEnable().The macro SYS_INT_DISABLE is used to disable the interrupt level for theend device. It is called once during shutdown. It calls anexternal board level routine sysUltraIntDisable().The macros SYS_IN_BYTE and SYS_OUT_BYTE are used for accessing theultra device. The default macros map these operations ontosysInByte() and sysOutByte().INCLUDES:end.h endLib.h etherMultiLib.hSEE ALSO: muxLib, endLib.I "Writing an Enhanced Network Driver"*//* includes */#include "vxWorks.h"#include "stdlib.h"#include "cacheLib.h"#include "intLib.h"#include "end.h" /* Common END structures. */#include "endLib.h"#include "lstLib.h" /* Needed to maintain protocol list. */#include "wdLib.h"#include "iv.h"#include "semLib.h"#include "etherLib.h"#include "logLib.h"#include "netLib.h"#include "stdio.h"#include "sysLib.h"#include "errno.h"#include "errnoLib.h"#include "memLib.h"#include "iosLib.h"#undef ETHER_MAP_IP_MULTICAST#include "etherMultiLib.h" /* multicast stuff. */#include "net/mbuf.h"#include "net/unixLib.h"#include "net/protosw.h"#include "net/systm.h"#include "net/if_subr.h"#include "net/route.h"#include "sys/socket.h"#include "sys/ioctl.h"#include "sys/times.h"#include "drv/end/ultraEnd.h"/* defines *//* Configuration items */#define ULTRA_SPEED_10M 10000000 /* 10Mbs */#define ULTRA_SPEED ULTRA_SPEED_10M/* Definitions for the flags field */#define ULTRA_POLLING 0x01#define ULTRA_TX_IN_PROGRESS 0x02#define ULTRA_TX_BLOCKED 0x04#define ULTRA_RCV_HANDLING_FLAG 0x08/* Debug macros */#undef DRV_DEBUG#ifdef DRV_DEBUG#define DRV_DEBUG_OFF 0x0000#define DRV_DEBUG_RX 0x0001#define DRV_DEBUG_TX 0x0002#define DRV_DEBUG_INT 0x0004#define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)#define DRV_DEBUG_POLL_RX 0x0008#define DRV_DEBUG_POLL_TX 0x0010#define DRV_DEBUG_LOAD 0x0020#define DRV_DEBUG_IOCTL 0x0040#define DRV_DEBUG_ERR 0x0080#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \ do \ { \ if (ultraDebug & (FLG)) \ logMsg (X0, X1, X2, X3, X4, X5, X6); \ } \ while (0)#define DRV_PRINT(FLG, X) \ do \ { \ if (ultraDebug & (FLG)) \ printf X; \ } \ while (0)#else /* DRV_DEBUG */#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) do {} while (0)#define DRV_PRINT(FLG, X) do {} while (0)#endif /* DRV_DEBUG *//* Cache macros */#define ULTRA_CACHE_INVALIDATE(address, len) \ CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))/* * Default macro definitions for BSP interface. These macros can be * redefined in a wrapper file, to generate a new module with an * optimized interface. *//* Macro to connect interrupt handler to vector */#ifndef SYS_INT_CONNECT#define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) \ { \ IMPORT STATUS sysIntConnect(); \ *(pResult) = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC ((pDrvCtrl)->ivec), \ rtn, (int)(arg)); \ }#endif/* Macro to disconnect interrupt handler from vector */LOCAL VOID dummyIsr (void) { };#ifndef SYS_INT_DISCONNECT#define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) \ { \ IMPORT STATUS intConnect(); \ *(pResult) = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC ((pDrvCtrl)->ivec), \ dummyIsr, (int)(arg)); \ }#endif/* Macro to enable the appropriate interrupt level */#ifndef SYS_INT_ENABLE#define SYS_INT_ENABLE(pDrvCtrl) \ { \ IMPORT void sysUltraIntEnable(); \ sysUltraIntEnable ((pDrvCtrl)->intLevel); \ }#endif/* Macro to disable the appropriate interrupt level */#ifndef SYS_INT_DISABLE#define SYS_INT_DISABLE(pDrvCtrl) \ { \ IMPORT void sysUltraIntDisable(); \ sysUltraIntDisable ((pDrvCtrl)->intLevel); \ }#endif/* * Macros to do a byte access to the chip. Default assumes an * I/O mapped device accessed in the x86 fashion. */#ifndef SYS_OUT_BYTE#define SYS_OUT_BYTE(pDrvCtrl, addr, value) \ (sysOutByte ((pDrvCtrl)->ioAddr+(addr), value))#endif#ifndef SYS_IN_BYTE#define SYS_IN_BYTE(pDrvCtrl, addr, pData) \ (*(pData) = sysInByte ((pDrvCtrl)->ioAddr+(addr)))#endif/* A shortcut for getting the hardware address from the MIB II stuff. */#define END_HADDR(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)#define END_HADDR_LEN(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)/* typedefs *//* The definition of the driver control structure */typedef struct ultra_device { END_OBJ endObj; /* The class we inherit from. */ END_ERR lastError; /* Last error passed to muxError */ int unit; /* unit number */ int ivec; /* interrupt vector */ int ilevel; /* interrupt level */ int ioAddr; /* address of ultra's shared memory */ int memAddr; /* address of ultra's shared memory */ int memSize; /* size of ultra's shared memory */ int config; /* device config (TP, BNC) */ int offset; /* packet data offset */ UINT transmitPage[2]; /* start of TX packets */ UINT transmitCnt; /* number of TX packets sent */ UCHAR current; /* location of current RX packet */ UCHAR nextPacket; /* location of next RX packet */ UCHAR istat; /* current interrupt status */ UCHAR tstat; /* current TX status */ UCHAR rstat; /* current RX status */ UCHAR uppByteCnt; /* last upper byte count */ UCHAR intLevel; /* interrupt level from table */ ULONG flags; /* Our local flags. */ UCHAR enetAddr[6]; /* ethernet address */ UCHAR mcastFilter[8]; /* multicast address mask */ CACHE_FUNCS cacheFuncs; /* cache function pointers */ CL_POOL_ID clPoolId; /* cluster pool */ } ULTRA_DEVICE;/* globals */#ifdef DRV_DEBUGint ultraDebug = 0x00;#endif /* DRV_DEBUG *//* locals */LOCAL IRQ_TABLE irqTable [] = { { 2, 0x15}, { 2, 0x15}, { 2, 0x15}, { 3, 0x19}, { 3, 0x19}, { 5, 0x1d}, { 5, 0x1d}, { 7, 0x51}, { 7, 0x51}, { 7, 0x51}, {10, 0x55}, {11, 0x59}, {11, 0x59}, {11, 0x59}, {11, 0x59}, {15, 0x5d} };/* forward declarations */IMPORT int endMultiLstCnt (END_OBJ* pEnd);LOCAL void ultraInt (ULTRA_DEVICE *pDrvCtrl);LOCAL STATUS ultraRecv (ULTRA_DEVICE *pDrvCtrl);LOCAL void ultraConfig (ULTRA_DEVICE *pDrvCtrl);LOCAL int ultraPacketGet (ULTRA_DEVICE *pDrvCtrl, UCHAR *pDst);LOCAL void ultraAddrFilterSet (ULTRA_DEVICE *pDrvCtrl);LOCAL void ultraHandleRcvInt (ULTRA_DEVICE *pDrvCtrl);LOCAL STATUS ultraParse (ULTRA_DEVICE* pDrvCtrl, char* initString);LOCAL STATUS ultraMemInit (ULTRA_DEVICE* pDrvCtrl, int clNum);LOCAL STATUS ultraPollStart (ULTRA_DEVICE* pDrvCtrl);LOCAL STATUS ultraPollStop (ULTRA_DEVICE* pDrvCtrl);LOCAL void ultraReset (ULTRA_DEVICE* pDrvCtrl);/* Ultra Specific interfaces. */LOCAL STATUS ultraStart (void* pObj);LOCAL STATUS ultraStop (void* pObj);LOCAL STATUS ultraUnload (void* pObj);LOCAL int ultraIoctl (void* pObj, int cmd, caddr_t data);LOCAL STATUS ultraSend (void* pObj, M_BLK_ID pBuf); LOCAL STATUS ultraMCastAdd (void* pObj, char* pAddress);LOCAL STATUS ultraMCastDel (void* pObj, char* pAddress);LOCAL STATUS ultraMCastGet (void* pObj, MULTI_TABLE* pTable);LOCAL STATUS ultraPollSend (void* pObj, M_BLK_ID pBuf);LOCAL STATUS ultraPollRcv (void* pObj, M_BLK_ID pBuf);/* This is the only externally visible interface. */END_OBJ* ultraLoad (char* initString);/* * Declare our function table. This is static across all driver * instances. */LOCAL NET_FUNCS ultraFuncTable = { ultraStart, /* Function to start the device. */ ultraStop, /* Function to stop the device. */ ultraUnload, /* Unloading function for the driver. */ ultraIoctl, /* Ioctl function for the driver. */ ultraSend, /* Send function for the driver. */ ultraMCastAdd, /* Multicast add function for the driver */ ultraMCastDel, /* Multicast delete function for the driver */ ultraMCastGet, /* Multicast get function for the driver */ ultraPollSend, /* Polling send function */ ultraPollRcv, /* Polling receive function */ endEtherAddressForm, /* put address info into a NET_BUFFER */ endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */ endEtherPacketAddrGet /* Get packet addresses. */ };/********************************************************************************* ultraLoad - initialize the driver and device** This routine initializes the driver and the device to the operational state.* All of the device-specific parameters are passed in <initString>, which* expects a string of the following format:** <unit>:<ioAddr>:<memAddr>:<vecNum>:<intLvl>:<config>:<offset>"** This routine can be called in two modes. If it is called with an empty but* allocated string, it places the name of this device (that is, "ultra") into * the <initString> and returns 0.** If the string is allocated and not empty, the routine attempts to load* the driver using the values specified in the string.** RETURNS: An END object pointer, or NULL on error, or 0 and the name of the* device if the <initString> was NULL.*/END_OBJ* ultraLoad ( char * initString /* String to be parsed by the driver. */ ) { ULTRA_DEVICE * pDrvCtrl; if (initString == NULL) return (NULL); if (initString[0] == NULL) { bcopy ((char *)DEV_NAME, initString, DEV_NAME_LEN); return (NULL); } DRV_LOG (DRV_DEBUG_LOAD, "ultraLoad: loading\n", (int) DEV_NAME, 2, 3, 4, 5, 6); /* allocate the device structure */ pDrvCtrl = (ULTRA_DEVICE *)calloc (sizeof (ULTRA_DEVICE), 1); if (pDrvCtrl == NULL) goto errorExit; /* parse the init string, filling in the device structure */ if (ultraParse (pDrvCtrl, initString) == ERROR) { logMsg ("ultraLoad: bad initialization string\n", 1, 2, 3, 4, 5, 6); goto errorExit; } DRV_LOG (DRV_DEBUG_LOAD, "ultraLoad: unit=%d ivec=%x ilevel=%x ioAddr=%x memAddr=%x config=%x\n", pDrvCtrl->unit, pDrvCtrl->ivec, pDrvCtrl->ilevel, pDrvCtrl->ioAddr, pDrvCtrl->memAddr, pDrvCtrl->config); /* Setup the rest of pDrvCtrl */ pDrvCtrl->intLevel = irqTable [pDrvCtrl->ilevel].irq; pDrvCtrl->transmitPage[0] = ULTRA_TSTART0; pDrvCtrl->transmitPage[1] = ULTRA_TSTART1; pDrvCtrl->transmitCnt = 0; pDrvCtrl->memSize = ULTRA_RAMSIZE; pDrvCtrl->cacheFuncs = cacheDmaFuncs; /* Reset the device */ ultraReset (pDrvCtrl); /* Get ethernet address from card */ SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_PS0 | CMD_STP); SYS_IN_BYTE (pDrvCtrl, CTRL_LAN0, &pDrvCtrl->enetAddr[0]); SYS_IN_BYTE (pDrvCtrl, CTRL_LAN1, &pDrvCtrl->enetAddr[1]); SYS_IN_BYTE (pDrvCtrl, CTRL_LAN2, &pDrvCtrl->enetAddr[2]); SYS_IN_BYTE (pDrvCtrl, CTRL_LAN3, &pDrvCtrl->enetAddr[3]); SYS_IN_BYTE (pDrvCtrl, CTRL_LAN4, &pDrvCtrl->enetAddr[4]); SYS_IN_BYTE (pDrvCtrl, CTRL_LAN5, &pDrvCtrl->enetAddr[5]); SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_STP); /* initialize the END and MIB2 parts of the structure */ if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, "ultra", pDrvCtrl->unit, &ultraFuncTable, "SMC Ultra Elite Enhanced Network Driver.") == ERROR) goto errorExit; if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd, &pDrvCtrl->enetAddr[0], 6, ETHERMTU, ULTRA_SPEED) == ERROR) goto errorExit; /* Perform memory allocation */ if (ultraMemInit (pDrvCtrl, 128) == ERROR) {#if (CPU_FAMILY==I80X86) /* Probably the bootrom case, try to get by with fewer clusters. */ if (ultraMemInit (pDrvCtrl, 8) == ERROR) goto errorExit;#else /* (CPU_FAMILY==I80X86) */ goto errorExit;#endif /* (CPU_FAMILY==I80X86) */ } /* Reconfigure the device */ ultraConfig (pDrvCtrl); DRV_LOG (DRV_DEBUG_LOAD, "ultraLoad: done\n", 1, 2, 3, 4, 5, 6); /* Set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX); return (&pDrvCtrl->endObj);errorExit: DRV_LOG (DRV_DEBUG_LOAD, "ultraLoad: errorExit\n", 1, 2, 3, 4, 5, 6);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -