mb86960End.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:45k
源码类别:
VxWorks
开发平台:
C/C++
- /* mb86960End.c - END-style Fujitsu MB86960 Ethernet network interface driver */
- /* Copyright 1984-2002 Wind River Systems, Inc. */
- #include "copyright_wrs.h"
- /*
- modification history
- --------------------
- 01h,14jan02,dat Removing warnings from Diab compiler
- 01g,20sep01,dat Removing ANSI errors for diab compiler
- 01f,28aug00,stv corrected the handling of EIOCSFLAGS ioctl (SPR# 29423).
- 01e,02aug00,stv removed netMblkClChainFree() in Pollsend routine (SPR# 32885).
- 01d,27jan00,dat fixed use of NULL
- 01c,01dec99,stv freed mBlk chain before returning ERROR (SPR #28492).
- 01b,28mar99,jdi doc: added missing module title and fixed other format
- errors (SPR 26119).
- 01a,27feb99,db written from templateEnd.c and target/src/drv/netif/if_fn.c
- */
- /*
- DESCRIPTION
- This module implements the Fujitsu MB86960 NICE Ethernet network interface
- driver.
- This driver is non-generic and has only been run on the Fujitsu SPARClite
- Evaluation Board. It currently supports only unit number zero.
- The driver must be given several target-specific parameters, and some external
- support routines must be provided. These parameters, and the mechanisms used
- to communicate them to the driver, are detailed below.
- BOARD LAYOUT
- This device is on-board. No jumpering diagram is necessary.
- The MB86960 Network Interface Controller with Encoder/Decoder (NICE) chip is
- a highly integrated monolithic device which incorporates both network
- controller, complete with buffer management and Manchester encoder/decoder.
- TARGET-SPECIFIC PARAMETERS
- The format of the parameter string is:
- <unit>:<devBaseAddr>:<ivec>
- .IP <unit>
- A convenient holdover from the former model. It is only used in the
- string name for the driver.
- .IP <devBaseAddr>
- The base Address of the chip registers.
- .IP <ivec>
- This is the interrupt vector number of the hardware interrupt generated by
- this ethernet device. The driver uses intConnect() to attach an interrupt
- handler to this interrupt.
- EXTERNAL SUPPORT REQUIREMENTS
- This driver requires seven external support functions:
- .IP sys86960IntEnable()
- .CS
- void sysEnetIntEnable (int unit)
- .CE
- This routine provides a target-specific interface to enable Ethernet device
- interrupts for a given device unit. For this driver, value of unit must be 0.
- .IP sys86960IntDisable()
- .CS
- void sysEnetIntDisable (int unit)
- .CE
- This routine provides a target-specific interface to disable Ethernet device
- interrupts for a given device unit. For this driver, value of unit must be 0.
- .IP sysEnetAddrGet()
- .CS
- STATUS sysEnetAddrGet (int unit, char *enetAdrs)
- .CE
- This routine provides a target-specific interface to access a device Ethernet
- address. This routine should provide a six-byte Ethernet address in
- the <enetAdrs> parameter and return OK or ERROR.
- In this driver the macros SYS_OUT_SHORT and SYS_IN_SHORT which call
- bsp-specific functions to access the chip register.
- INCLUDES:
- end.h endLib.h etherMultiLib.h
- SEE ALSO: muxLib, endLib
- .I "Writing and Enhanced Network Driver"
- */
- /* includes */
- #include "vxWorks.h"
- #include "iv.h"
- #include "memLib.h"
- #include "intLib.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "netLib.h"
- #include "drv/end/mb86960End.h" /* Common defines. */
- #include "etherMultiLib.h" /* multicast stuff. */
- #include "end.h" /* Common END structures. */
- #include "endLib.h"
- #include "lstLib.h" /* Needed to maintain protocol list. */
- #include "logLib.h"
- #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 "m2Lib.h"
- /* Endian safe macro - MB86960_SWAP_SHORT */
- #if (_BYTE_ORDER == _BIG_ENDIAN)
- # define MB86960_SWAP_SHORT(x) (MSB(x) | LSB(x) << 8)
- #else
- # define MB86960_SWAP_SHORT(x) (x)
- #endif
- /*
- * 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->vector),
- rtn, (int)arg);
- }
- #endif
- /* Macro to disconnect interrupt handler from vector */
- #ifndef SYS_INT_DISCONNECT
- # define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)
- {
- *pResult = OK; /* HELP: need a real routine */
- }
- #endif
- /* Macro to enable the appropriate interrupt level */
- #ifndef SYS_INT_ENABLE
- # define SYS_INT_ENABLE(pDrvCtrl)
- {
- IMPORT STATUS sysEnetIntEnable(int);
- sysEnetIntEnable (pDrvCtrl->unit);
- }
- #endif
- #ifndef SYS_INT_DISABLE
- # define SYS_INT_DISABLE(pDrvCtrl)
- {
- IMPORT STATUS sysEnetIntDisable(int);
- sysEnetIntDisable (pDrvCtrl->unit);
- }
- #endif
- /* Macro to get the ethernet address from the BSP */
- #ifndef SYS_ENET_ADDR_GET
- # define SYS_ENET_ADDR_GET(pDrvCtrl, pRetCode)
- {
- IMPORT STATUS sysEnetAddrGet();
- *pRetCode = sysEnetAddrGet (pDrvCtrl->unit, (char *) &pDrvCtrl->enetAddr);
- }
- #endif
- /*
- * Macros to do a short (UINT16) access to the chip. Default
- * assumes a normal memory mapped device.
- */
- #ifndef SYS_OUT_SHORT
- # define SYS_OUT_SHORT(addr,value)
- {
- IMPORT void sysAsiSeth ();
- sysAsiSeth (addr, value);
- }
- #endif
- #ifndef SYS_IN_SHORT
- # define SYS_IN_SHORT(addr, var)
- {
- IMPORT u_short sysAsiGeth ();
- var = sysAsiGeth (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)
- /*
- * This will only work if there is only a single unit, for multiple
- * unit device drivers these should be integrated into the MB86960_END_CTRL
- * structure.
- */
- M_CL_CONFIG fnMclBlkCfg = /* network mbuf configuration table */
- {
- /*
- no. mBlks no. clBlks memArea memSize
- ----------- ---------- ------- -------
- */
- 0, 0, NULL, 0
- };
- CL_DESC fnClDescTbl [] = /* network cluster pool configuration table */
- {
- /*
- clusterSize num memArea memSize
- ----------- ---- ------- -------
- */
- {MB86960_BUFSIZ, 0, NULL, 0}
- };
- int fnClDescTblNumEnt = (NELEMENTS(fnClDescTbl));
- /* Definitions for the flags field */
- #define LS_PROMISCUOUS_FLAG 0x1
- #define LS_MEM_ALLOC_FLAG 0x2
- #define LS_PAD_USED_FLAG 0x4
- #define LS_RCV_HANDLING_FLAG 0x8
- #define LS_POLLING 0x20
- /***** DEBUG MACROS *****/
- #define 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_POLL_REDIR 0x10000
- #define DRV_DEBUG_LOG_NVRAM 0x20000
- #ifdef LOCAL
- #undef LOCAL
- #endif /* LOCAL */
- #define LOCAL
- int mb86960Debug = DRV_DEBUG_OFF;
- NET_POOL mb86960NetPool;
- #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
- if (mb86960Debug & FLG)
- logMsg(X0, X1, X2, X3, X4, X5, X6);
- #define DRV_PRINT(FLG,X)
- if (mb86960Debug & FLG) printf X;
- #else /*DRV_DEBUG*/
- #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
- #define DRV_PRINT(DBG_SW,X)
- #endif /*DRV_DEBUG*/
- #define MB86960_BUFS 100 /* Needs some work */
- /* forward static functions */
- LOCAL void mb86960Reset (MB86960_END_CTRL * pDrvCtrl);
- LOCAL void mb86960Int (MB86960_END_CTRL * pDrvCtrl);
- LOCAL void mb86960HandleRcvInt (MB86960_END_CTRL * pDrvCtrl);
- LOCAL STATUS mb86960Recv (MB86960_END_CTRL * pDrvCtrl,
- MB86960_RX_FRAME * pRxFrame);
- LOCAL BOOL mb86960RxMore (MB86960_END_CTRL * pDrvCtrl);
- LOCAL void mb86960Config (MB86960_END_CTRL * pDrvCtrl);
- /* END Specific interfaces. */
- /* This is the only externally visible interface. */
- END_OBJ * mb86960EndLoad (char * initString);
- LOCAL STATUS mb86960Start (MB86960_END_CTRL * pDrvCtrl);
- LOCAL STATUS mb86960Stop (MB86960_END_CTRL * pDrvCtrl);
- LOCAL STATUS mb86960Unload ();
- LOCAL int mb86960Ioctl (MB86960_END_CTRL * pDrvCtrl, int cmd,
- caddr_t data);
- LOCAL STATUS mb86960Send (MB86960_END_CTRL * pDrvCtrl,
- M_BLK_ID pBuf);
- LOCAL STATUS mb89680Transmit (MB86960_END_CTRL * pDrvCtrl,
- M_BLK_ID pMblk);
- LOCAL STATUS mb86960PacketGet (MB86960_END_CTRL * pDrvCtrl,
- MB86960_RX_FRAME * pRxFrame);
- LOCAL BOOL mb89680RxMore (MB86960_END_CTRL * pDrvCtrl);
- LOCAL void mb86960AddrFilterSet (MB86960_END_CTRL* pDrvCtrl, char * pAddr,
- BOOL bSet);
- LOCAL STATUS mb86960MCastAddrAdd (MB86960_END_CTRL * pDrvCtrl,
- char* pAddress);
- LOCAL STATUS mb86960MCastAddrDel (MB86960_END_CTRL * pDrvCtrl,
- char* pAddress);
- LOCAL STATUS mb86960MCastAddrGet (MB86960_END_CTRL * pDrvCtrl,
- MULTI_TABLE* pTable);
- LOCAL STATUS mb86960PollSend (MB86960_END_CTRL * pDrvCtrl, M_BLK_ID pBuf);
- LOCAL STATUS mb86960PollRcv (MB86960_END_CTRL * pDrvCtrl, M_BLK_ID pBuf);
- LOCAL STATUS mb86960PollStart (MB86960_END_CTRL * pDrvCtrl);
- LOCAL STATUS mb86960PollStop (MB86960_END_CTRL * pDrvCtrl);
- LOCAL STATUS mb86960InitParse (MB86960_END_CTRL *, char *);
- LOCAL STATUS mb86960MemInit ();
- LOCAL int mb86960HashIndex (char * pEnAddr);
- LOCAL STATUS mb86960HdrShow (struct ether_header * pHdr, char * msg);
- /*
- * Declare our function table. This is static across all driver
- * instances.
- */
- LOCAL NET_FUNCS mb86960FuncTable =
- {
- (FUNCPTR) mb86960Start, /* Function to start the device. */
- (FUNCPTR) mb86960Stop, /* Function to stop the device. */
- (FUNCPTR) mb86960Unload, /* Unloading function for the driver. */
- (FUNCPTR) mb86960Ioctl, /* Ioctl function for the driver. */
- (FUNCPTR) mb86960Send, /* Send function for the driver. */
- (FUNCPTR) mb86960MCastAddrAdd, /* Multicast address add func. */
- (FUNCPTR) mb86960MCastAddrDel, /* Multicast address delete func. */
- (FUNCPTR) mb86960MCastAddrGet, /* Multicast table retrieve func. */
- (FUNCPTR) mb86960PollSend, /* Polling send function. */
- (FUNCPTR) mb86960PollRcv, /* Polling receive function. */
- endEtherAddressForm, /* Put address info into a packet. */
- endEtherPacketDataGet, /* Get a pointer to packet data. */
- endEtherPacketAddrGet /* Get packet addresses. */
- };
- int overFlowCnt;
- int dropCnt;
- /*******************************************************************************
- *
- * mb86960EndLoad - initialize the driver and device
- *
- * This routine initializes the driver and puts the device to an operational
- * state.
- * All of the device specific parameters are passed in via the initString, which
- * expects a string of the following format:
- *
- * <unit>:<base_addr>:<int_vector>:<int_level>
- *
- * 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, "fn") 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 * mb86960EndLoad
- (
- char * pInitString /* String to be parsed by the driver. */
- )
- {
- MB86960_END_CTRL * pDrvCtrl;
- STATUS retCode;
- DRV_LOG (DRV_DEBUG_LOAD, "Loading nice...n", 1, 2, 3, 4, 5, 6);
- if (pInitString == NULL)
- return (NULL);
- if (pInitString[0] == EOS)
- {
- bcopy((char *)FN_DEV_NAME, pInitString, FN_DEV_NAME_LEN);
- return (0);
- }
- /* allocate the device structure */
- pDrvCtrl = (MB86960_END_CTRL *) calloc (sizeof(MB86960_END_CTRL), 1);
- if (pDrvCtrl == NULL)
- goto errorExit;
- /* parse the init string, filling in the device structure */
- if (mb86960InitParse (pDrvCtrl, pInitString) == ERROR)
- goto errorExit;
- /* Ask the BSP to provide the ethernet address. */
- SYS_ENET_ADDR_GET(pDrvCtrl, &retCode);
- if (retCode == ERROR)
- goto errorExit;
- /*
- * initialize the END and MIB2 parts of the structure
- * The M2 element must come from m2Lib.h
- * This template is set up for a DIX type ethernet device.
- */
- if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, FN_DEV_NAME,
- pDrvCtrl->unit, &mb86960FuncTable,
- "Fujitsu MB86960 Ethernet Enhanced Network Driver")
- == ERROR ||
- END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
- &pDrvCtrl->enetAddr[0], ENET_ADDR_LEN, ETHERMTU,
- MB86960_SPEED) == ERROR)
- goto errorExit;
- /* Perform memory allocation/distribution */
- if (mb86960MemInit (pDrvCtrl) == ERROR)
- goto errorExit;
- /* (re)initialize and configure the device */
- mb86960Reset (pDrvCtrl);
- mb86960Config (pDrvCtrl);
- /* set the flags to indicate readiness */
- END_OBJ_READY (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS
- | IFF_BROADCAST | IFF_MULTICAST));
- DRV_LOG (DRV_DEBUG_LOAD, "Done loading end...n", 1, 2, 3, 4, 5, 6);
- return (&pDrvCtrl->end);
- errorExit:
- mb86960Unload (pDrvCtrl);
- return (NULL);
- }
- /*******************************************************************************
- *
- * mb86960InitParse - parse the initialization string
- *
- * This routine parses the input string, filling in values in the
- * driver control structure.
- *
- * The initialization string format is: <unit>:<baseAddr>:<ivec>
- * .IP <unit>
- * Device unit number, a small integer. Must always be 0.
- * .IP <devBaseAddr>
- * Base address of the device register set.
- * .IP <ivec>
- * Interrupt vector number, used with sysIntConnect().
- *
- * RETURNS: OK or ERROR for invalid arguments.
- */
- STATUS mb86960InitParse
- (
- MB86960_END_CTRL * pDrvCtrl, /* device pointer */
- char * pInitString /* information string */
- )
- {
- char * tok;
- char * pHolder = NULL;
- /* Parse the initString */
- /* Unit number. */
- tok = strtok_r (pInitString, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- if ((pDrvCtrl->unit = atoi (tok)) != 0)
- return ERROR;
- /* Device Base Address. */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->devBaseAddr = (char *)strtoul (tok, NULL, 16);
- /* Interrupt vector. */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->vector = atoi (tok);
- DRV_LOG (DRV_DEBUG_LOAD, "Processed all arugmentsn", 1, 2, 3, 4, 5, 6);
- DRV_LOG (DRV_DEBUG_LOAD, "Address %p ivec %dn",
- (int ) pDrvCtrl->devBaseAddr, (int ) pDrvCtrl->vector,
- 3, 4, 5, 6);
- return OK;
- }
- /*******************************************************************************
- *
- * mb86960MemInit - initialize memory for the chip
- *
- * This routine is highly specific to the device.
- *
- * RETURNS: OK or ERROR.
- */
- STATUS mb86960MemInit
- (
- MB86960_END_CTRL * pDrvCtrl /* device to be initialized */
- )
- {
- /*
- * This is how we would set up and END netPool using netBufLib(1).
- * This code is pretty generic.
- */
- if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
- return (ERROR);
- fnMclBlkCfg.mBlkNum = MB86960_BUFS;
- fnClDescTbl[0].clNum = MB86960_BUFS;
- fnMclBlkCfg.clBlkNum = fnClDescTbl[0].clNum;
- /* Calculate the total memory for all the M-Blks and CL-Blks. */
- fnMclBlkCfg.memSize = (fnMclBlkCfg.mBlkNum * (MSIZE + sizeof (long))) +
- (fnMclBlkCfg.clBlkNum * (CL_BLK_SZ + sizeof(long)));
- if ((fnMclBlkCfg.memArea = (char *) memalign (sizeof(long),
- fnMclBlkCfg.memSize))
- == NULL)
- return (ERROR);
- /* Calculate the memory size of all the clusters. */
- fnClDescTbl[0].memSize = (fnClDescTbl[0].clNum * (MB86960_BUFSIZ + 8))
- + sizeof(int);
- /* Allocate the memory for the clusters from cache safe memory. */
- fnClDescTbl[0].memArea =
- (char *) memalign (sizeof(long), fnClDescTbl[0].memSize);
- if (fnClDescTbl[0].memArea == NULL)
- {
- DRV_LOG(DRV_DEBUG_LOAD,
- "system memory unavailablen", 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- /* Initialize the memory pool. */
- if (netPoolInit(pDrvCtrl->end.pNetPool, &fnMclBlkCfg,
- &fnClDescTbl[0], fnClDescTblNumEnt, NULL) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "Could not init bufferingn",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- #ifdef DRV_DEBUG
- mb86960NetPool = *pDrvCtrl->end.pNetPool;
- #endif
- /* Store the cluster pool id as others need it later. */
- pDrvCtrl->pClPoolId = clPoolIdGet (pDrvCtrl->end.pNetPool,
- sizeof(struct rx_frame), FALSE);
- DRV_LOG (DRV_DEBUG_LOAD, "Memory setup completen", 1, 2, 3, 4, 5, 6);
- return OK;
- }
- /*******************************************************************************
- *
- * mb86960Start - start the device
- *
- * This function calls BSP functions to connect interrupts and start the
- * device running in interrupt mode.
- *
- * RETURNS: OK or ERROR if ISR is not connected.
- *
- */
- LOCAL STATUS mb86960Start
- (
- MB86960_END_CTRL * pDrvCtrl /* device to be started */
- )
- {
- STATUS result;
- SYS_INT_CONNECT (pDrvCtrl, mb86960Int, (int)pDrvCtrl, &result);
- if (result == ERROR)
- return ERROR;
- DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
- /* Enable specific interrupts. */
- SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), NORM_INTRMASK);
- /* mark the interface -- up */
- END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
- SYS_INT_ENABLE (pDrvCtrl);
- DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
- return (OK);
- }
- /*******************************************************************************
- *
- * mb86960Int - handle controller interrupt
- *
- * This routine is called at interrupt level in response to an interrupt from
- * the controller.
- *
- * RETURNS: N/A.
- */
- LOCAL void mb86960Int
- (
- MB86960_END_CTRL * pDrvCtrl /* interrupting device */
- )
- {
- char * pDev; /* ptr to the device regs */
- u_short event;
- u_short reg;
- pDev = pDrvCtrl->devBaseAddr;
- SYS_IN_SHORT((pDev + NICE_STATUS), event);
- SYS_IN_SHORT((pDev + NICE_INTRMASK), reg);
- DRV_LOG (DRV_DEBUG_INT, "i=0x%x:n", event, 2, 3, 4, 5, 6);
- /* Handle receiver overflow event. */
- if (event & DLCR1_OVR_FLO)
- {
- overFlowCnt++; /* bump the counter */
- SYS_OUT_SHORT ((pDev + NICE_STATUS), DLCR1_OVR_FLO);
- return;
- }
- /* Handle the receiver event, only if it was enabled. */
- if ((reg & DLCR3_RX_PKT) && (event & DLCR1_RX_PKT))
- {
- SYS_OUT_SHORT ((pDev + NICE_INTRMASK), NO_RX_INTRMASK); /* disable */
- netJobAdd ((FUNCPTR)mb86960HandleRcvInt, (int)pDrvCtrl, 0,0,0,0);
- }
- /* ACK the interrupts */
- SYS_OUT_SHORT ((pDev + NICE_STATUS), event);
- }
- /*******************************************************************************
- *
- * mb86960HandleRcvInt - task level interrupt service for input packets
- *
- * This routine is called at task level indirectly by the interrupt
- * service routine to do any message received processing.
- *
- * RETURNS: N/A.
- */
- LOCAL void mb86960HandleRcvInt
- (
- MB86960_END_CTRL * pDrvCtrl /* interrupting device */
- )
- {
- char * pDev = pDrvCtrl->devBaseAddr;
- MB86960_RX_FRAME * pCluster;
- MB86960_RX_FRAME temp;
- STATUS retCode;
- pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;
- while (mb86960RxMore (pDrvCtrl))
- {
- /*
- * We implicitly are loaning here, if copying is necessary this
- * step may be skipped, but the data must be copied before being
- * passed up to the protocols.
- */
- pCluster = (MB86960_RX_FRAME *) netClusterGet(pDrvCtrl->end.pNetPool,
- pDrvCtrl->pClPoolId);
- if (pCluster == NULL)
- {
- dropCnt++;
- DRV_LOG (DRV_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
- mb86960PacketGet (pDrvCtrl, &temp);
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
- }
- else
- {
- retCode = mb86960PacketGet (pDrvCtrl, pCluster);
- if (retCode != ERROR)
- {
- (void) mb86960Recv (pDrvCtrl, pCluster);
- }
- else
- {
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
- break;
- }
- }
- }
- pDrvCtrl->flags &= ~LS_RCV_HANDLING_FLAG;
- /* Turn the receive interrupts on again. */
- SYS_OUT_SHORT ((pDev + NICE_INTRMASK), NORM_INTRMASK);
- }
- /*******************************************************************************
- *
- * mb86960RxMore - indicates more packets in the buffer
- *
- * This routine indicates that there are more packets left in the buffer
- *
- * RETURNS: TRUE or FALSE
- */
- LOCAL BOOL mb86960RxMore
- (
- MB86960_END_CTRL * pDrvCtrl /* interrupting device */
- )
- {
- u_short mode;
- char * pDev; /* ptr to the device regs */
- pDev = pDrvCtrl->devBaseAddr; /* get ptr to device */
- SYS_IN_SHORT ((pDev + NICE_MODE), mode);
- if (mode & DLCR5_BUF_EMPTY)
- return (FALSE);
- else
- return (TRUE);
- }
- /*******************************************************************************
- *
- * mb86960PacketGet - get next received message
- *
- * Get next received message. Returns NULL if none are ready.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960PacketGet
- (
- MB86960_END_CTRL * pDrvCtrl, /* device structure */
- MB86960_RX_FRAME * pRxFrame /* pointer to an rx frame struct */
- )
- {
- int loopy; /* loop counter */
- char * pDev; /* ptr to the device regs */
- u_short * pDest; /* ptr to destination */
- pDev = pDrvCtrl->devBaseAddr; /* get ptr to device */
- /* Fill our local copy of the Rx header from the device's buffer. */
- SYS_IN_SHORT((pDev + NICE_PORT), pRxFrame->rxHdr.status);
- SYS_IN_SHORT((pDev + NICE_PORT), pRxFrame->rxHdr.len);
- /* swap bytes if needed */
- pRxFrame->rxHdr.len = MB86960_SWAP_SHORT(pRxFrame->rxHdr.len);
- /* Clear the status bit for packet ready. */
- SYS_OUT_SHORT ((pDev + NICE_STATUS), DLCR1_RX_PKT);
- /* Sanity check the packet info. */
- if ((!(pRxFrame->rxHdr.status & RX_HDR_STAT_GOOD)) ||
- (pRxFrame->rxHdr.len < ETHERSMALL) ||
- (pRxFrame->rxHdr.len > (ETHERMTU + SIZEOF_ETHERHEADER)))
- {
- /* END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING)); */
- return (ERROR);
- }
- /* Fill our frame buffer from the device's buffer. */
- pDest = (u_short *) &pRxFrame->enetHdr; /* stuff ptr */
- for (loopy = pRxFrame->rxHdr.len; loopy > 0; loopy -= sizeof (u_short))
- {
- SYS_IN_SHORT((pDev + NICE_PORT), *pDest++);
- }
- return (OK);
- }
- /*******************************************************************************
- *
- * mb86960Recv - process the next incoming packet
- *
- * Handle one incoming packet. The packet is checked for errors.
- *
- * RETURNS: OK
- */
- LOCAL STATUS mb86960Recv
- (
- MB86960_END_CTRL * pDrvCtrl, /* device structure */
- MB86960_RX_FRAME * pCluster /* pointer to header structure */
- )
- {
- int len;
- M_BLK_ID pMblk;
- CL_BLK_ID pClBlk;
- len = pCluster->rxHdr.len; /* obtain data length */
- /* Grab a cluster block to marry to the cluster we received. */
- if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
- {
- netClFree (pDrvCtrl->end.pNetPool, (UINT8 *) pCluster);
- DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
- goto cleanRXD;
- }
- /*
- * OK we've got a spare, let's get an M_BLK_ID and marry it to the
- * one in the ring.
- */
- if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
- {
- netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
- netClFree (pDrvCtrl->end.pNetPool, (UINT8 *) pCluster);
- DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
- goto cleanRXD;
- }
- /* Add one to our unicast data. */
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
- /* Join the cluster to the MBlock */
- netClBlkJoin (pClBlk, (char *) pCluster, len, NULL, 0, 0, 0);
- netMblkClJoin (pMblk, pClBlk);
- pMblk->mBlkHdr.mData = (char *)MB86960_FRAME_DATA_ADDR_GET(pCluster);
- pMblk->mBlkHdr.mLen = len;
- pMblk->mBlkHdr.mFlags |= M_PKTHDR;
- pMblk->mBlkPktHdr.len = len;
- DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!n", 1, 2, 3, 4, 5, 6);
- /* Call the upper layer's receive routine. */
- END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
- cleanRXD:
- return (OK);
- }
- /*******************************************************************************
- *
- * mb86960Send - the driver send routine
- *
- * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
- * The buffer must already have the addressing information properly installed
- * in it. This is done by a higher layer. The last arguments are a free
- * routine to be called when the device is done with the buffer and a pointer
- * to the argument to pass to the free routine.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960Send
- (
- MB86960_END_CTRL * pDrvCtrl, /* device ptr */
- M_BLK_ID pMblk /* data to send */
- )
- {
- int oldLevel = 0;
- STATUS status;
- DRV_LOG(DRV_DEBUG_TX, "Begin mb86960Send pDrvCtrl %p pMblk %pn",
- (int ) pDrvCtrl, (int ) pMblk, 0, 0, 0, 0);
- if ((END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)) !=
- (IFF_UP | IFF_RUNNING))
- {
- DRV_LOG(DRV_DEBUG_TX, "Device is NOT UP and RUNNINGn", 0, 0,
- 0, 0, 0, 0);
- if (!(pDrvCtrl->flags & LS_POLLING))
- netMblkClChainFree (pMblk); /* free the given mBlk chain */
- errno = EINVAL;
- return (ERROR);
- }
- /*
- * Obtain exclusive access to transmitter. This is necessary because
- * we might have more than one stack transmitting at once.
- */
- if (!(pDrvCtrl->flags & LS_POLLING))
- semTake (pDrvCtrl->txSem, WAIT_FOREVER);
- /* place a transmit request */
- if (!(pDrvCtrl->flags & LS_POLLING))
- oldLevel = intLock (); /* now mb86960Int won't get confused */
- /* send packet out over interface */
- if ((status = mb89680Transmit (pDrvCtrl, pMblk)) == ERROR)
- {
- DRV_LOG(DRV_DEBUG_TX, "FAILED mb89680Transmitn", 1, 2, 3, 4, 5, 6);
- /* update statistics */
- END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1);
- if (!(pDrvCtrl->flags & LS_POLLING))
- {
- intUnlock (oldLevel); /* now mb86960Int won't get confused */
- semGive (pDrvCtrl->txSem);
- netMblkClChainFree (pMblk);
- }
- return (ERROR);
- }
- if (!(pDrvCtrl->flags & LS_POLLING))
- intUnlock (oldLevel); /* now mb86960Int won't get confused */
- /* Advance our management index */
- if (!(pDrvCtrl->flags & LS_POLLING))
- semGive (pDrvCtrl->txSem);
- /* Bump the statistic counter. */
- END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
- /*
- * Cleanup. The driver must either free the packet now or
- * set up a structure so it can be freed later after a transmit
- * interrupt occurs.
- */
- if (!(pDrvCtrl->flags & LS_POLLING))
- netMblkClChainFree (pMblk);
- return (OK);
- }
- /*******************************************************************************
- *
- * mb89680Transmit - kick start the transmitter after generic ether_output
- *
- * This routine is responsible for tranmitting packets over physical media.
- * The data to be sent out is held in a chain of mbufs. The data in each mbuf
- * fragment must be copied to the device's packet buffer.
- *
- * RETURNS: OK, or ERROR
- */
- LOCAL STATUS mb89680Transmit
- (
- MB86960_END_CTRL * pDrvCtrl, /* pointer to driver control struct */
- M_BLK_ID pMblk /* pointer to am Mblk */
- )
- {
- int pktLen; /* total length of packet */
- int dataLen; /* real length of data portion */
- int loopy; /* loop counter */
- char * nicePort; /* ptr to the nice buffer port */
- u_short * pSource; /* ptr to source of data byte */
- u_short temp;
- static char privateBuf [ETHERMTU];
- /* get ptr to the buffer port */
- nicePort = pDrvCtrl->devBaseAddr + NICE_PORT;
- /*
- * This driver maintains transmit resources internally. The
- * CPU cannot retrieve or examine them.
- */
- dataLen = netMblkToBufCopy (pMblk, privateBuf, NULL);
- /* Ensure we send a legal size frame. */
- pktLen = max (ETHERSMALL, dataLen);
- /* taking care of short packets, pad with 0s */
- if (dataLen < ETHERSMALL)
- for (loopy = dataLen; loopy < pktLen; loopy++)
- privateBuf [loopy] = 0;
- /* Tell the device the length; in little endian order */
- SYS_OUT_SHORT (nicePort, MB86960_SWAP_SHORT(pktLen));
- pSource = (u_short *)privateBuf;
- for (loopy = pktLen; loopy > 0 ; loopy -= sizeof (u_short))
- {
- SYS_OUT_SHORT (nicePort, *pSource);
- pSource++;
- }
- if (pktLen % sizeof (u_short)) /* packet size is odd */
- {
- unsigned short lastByte;
- lastByte = 0;
- ( (char *) (&lastByte))[0] = ((char *) (pSource))[0];
- SYS_OUT_SHORT (nicePort, lastByte);
- }
- /* See if transmitter is free and start it orelse wait. */
- FOREVER
- {
- SYS_IN_SHORT((pDrvCtrl->devBaseAddr + NICE_TRANSMIT), temp);
- if ((temp & (0x7f << 8)) == 0)
- break;
- }
- SYS_OUT_SHORT((pDrvCtrl->devBaseAddr + NICE_TRANSMIT), KICK_TRANSMIT);
- return (OK);
- }
- /*******************************************************************************
- *
- * mb86960Ioctl - the driver I/O control routine
- *
- * Process an ioctl request.
- *
- * RETURNS: A command specific response, usually OK or ERROR.
- */
- LOCAL int mb86960Ioctl
- (
- MB86960_END_CTRL * pDrvCtrl, /* device receiving command */
- int cmd, /* ioctl command code */
- caddr_t data /* command argument */
- )
- {
- int error = 0;
- long value;
- switch ((UINT)cmd)
- {
- case EIOCSADDR:
- if (data == NULL)
- return (EINVAL);
- bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
- END_HADDR_LEN(&pDrvCtrl->end));
- break;
- case EIOCGADDR:
- if (data == NULL)
- return (EINVAL);
- bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
- END_HADDR_LEN(&pDrvCtrl->end));
- break;
- case EIOCSFLAGS:
- value = (long)data;
- if (value < 0)
- {
- value = -value;
- value--;
- END_FLAGS_CLR (&pDrvCtrl->end, value);
- }
- else
- {
- END_FLAGS_SET (&pDrvCtrl->end, value);
- }
- mb86960Config (pDrvCtrl);
- break;
- case EIOCGFLAGS:
- *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
- break;
- case EIOCPOLLSTART:
- mb86960PollStart (pDrvCtrl);
- break;
- case EIOCPOLLSTOP:
- mb86960PollStop (pDrvCtrl);
- break;
- case EIOCMULTIADD:
- error = mb86960MCastAddrAdd (pDrvCtrl, (char *)data);
- break;
- case EIOCMULTIDEL:
- error = mb86960MCastAddrDel (pDrvCtrl, (char *)data);
- break;
- case EIOCMULTIGET:
- error = mb86960MCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data);
- break;
- case EIOCGMIB2:
- if (data == NULL)
- return (EINVAL);
- bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
- sizeof(pDrvCtrl->end.mib2Tbl));
- break;
- #if 0
- case EIOCGFBUF:
- if (data == NULL)
- return (EINVAL);
- *(int *)data = END_MIN_FBUF;
- break;
- #endif
- default:
- error = EINVAL;
- }
- return (error);
- }
- /******************************************************************************
- *
- * mb86960Reset - reset state initialization for the device
- *
- * This routine initializes the MB86960 device after a reset / reboot.
- * of addresses (added with the endAddrAdd() routine) and sets the
- * device's filter correctly.
- *
- * RETURNS: N/A.
- */
- LOCAL void mb86960Reset
- (
- MB86960_END_CTRL *pDrvCtrl /* device to be re-configured */
- )
- {
- /* Set promiscuous mode if it's asked for. */
- #if 0
- if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode on!n",
- 1, 2, 3, 4, 5, 6);
- }
- else
- {
- DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!n",
- 1, 2, 3, 4, 5, 6);
- }
- /* Set up address filter for multicasting. */
- if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0)
- {
- mb86960AddrFilterSet (pDrvCtrl);
- }
- #endif
- /* shutdown device completely */
- SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), 0);
- SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_STATUS), 0xffff);
- return;
- }
- /******************************************************************************
- *
- * mb86960Config - reconfigure the interface under us.
- *
- * Reconfigure the interface setting promiscuous mode, and changing the
- * multicast interface list.
- *
- * RETURNS: N/A.
- */
- LOCAL void mb86960Config
- (
- MB86960_END_CTRL * pDrvCtrl
- )
- {
- u_short temp; /* scratch pad */
- char * pDev = pDrvCtrl->devBaseAddr;
- /* initial setup of config register 1 */
- temp = (DLCR6_DISABLE_DLC | /* resets things */
- DLCR6_BIT_6 | /* just do it */
- DLCR6_SYS_BUS_16 | /* use 16 bits */
- DLCR6_BUF_BUS_16 | /* use 16 bits */
- DLCR6_TBS_4KB | /* Tx buf is 4kb */
- DLCR6_BS_16KB | /* total buf is 16k */
- DLCR7_CNF_NICE | /* normal NICE mode */
- DLCR7_PWRDN_OFF | /* normal power mode */
- DLCR7_BIT_4 | /* just do it */
- DLCR7_REG_BNK_DLC | /* map node ID regs */
- DLCR7_ENDIAN_LITTLE
- );
- SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);
- /* Mask off all interrupts and clear all event flags. */
- SYS_OUT_SHORT ((pDev + NICE_INTRMASK), 0);
- SYS_OUT_SHORT ((pDev + NICE_STATUS), 0xffff);
- /* Disable device interrupt at system level and clear any pended. */
- SYS_INT_DISABLE (pDrvCtrl);
- /* The secondary DLC register group is mapped in. Set the node ID. */
- SYS_OUT_SHORT ((pDev + NICE_ADDR1), (((u_short *) pDrvCtrl->enetAddr)[0]));
- SYS_OUT_SHORT ((pDev + NICE_ADDR2), (((u_short *) pDrvCtrl->enetAddr)[1]));
- SYS_OUT_SHORT ((pDev + NICE_ADDR3), (((u_short *) pDrvCtrl->enetAddr)[2]));
- /* Change register map. Select buffer memory register group. */
- SYS_IN_SHORT ((pDev + NICE_CONFIG), temp);
- temp &= ~DLCR7_REG_BNK; /* clear bank select bits */
- temp |= DLCR7_REG_BNK_HASH; /* add desired bits */
- SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);
- /* clear all bits in hash table array */
- SYS_OUT_SHORT ((pDev + NICE_HASH1), 0);
- SYS_OUT_SHORT ((pDev + NICE_HASH2), 0);
- SYS_OUT_SHORT ((pDev + NICE_HASH3), 0);
- SYS_OUT_SHORT ((pDev + NICE_HASH4), 0);
- temp &= ~DLCR7_REG_BNK; /* clear bank select bits */
- temp |= DLCR7_REG_BNK_BMR; /* add desired bits */
- SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);
- /*
- * Setup the receiver and transmitter modes. Note that in
- * order to enable multicast + hash table, the bit
- * DLCR5_AF1 must be set. The documentation for the
- * MB86960 says otherwise but is not correct
- */
- SYS_OUT_SHORT ((pDev + NICE_MODE), (DLCR4_LBC | DLCR5_BIT_2 | DLCR5_AF1));
- /* Enable the DLC. */
- SYS_IN_SHORT ((pDev + NICE_CONFIG), temp); /* get config reg */
- temp &= ~DLCR6_DISABLE_DLC; /* clear the disable bit */
- SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp); /* update config reg */
- /* set collision control drop packet after 16 collisions */
- SYS_OUT_SHORT ((pDev + NICE_TRANSMIT), (BMR11_MASK16 | BMR11_RST_TX16
- | BMR11_OPT_16_COLL));
- }
- /*******************************************************************************
- *
- * mb86960PollRcv - routine to receive a packet in polled mode.
- *
- * This routine is called by a user to try and get a packet from the
- * device.
- *
- * RETURNS: OK upon success. EAGAIN is returned when no packet is available.
- */
- LOCAL STATUS mb86960PollRcv
- (
- MB86960_END_CTRL * pDrvCtrl, /* device to be polled */
- M_BLK_ID pMblk /* ptr to buffer */
- )
- {
- STATUS retCode = OK;
- MB86960_RX_FRAME * pCluster;
- int len;
- if (mb86960RxMore (pDrvCtrl) == FALSE)
- return (EAGAIN);
- pCluster = (MB86960_RX_FRAME *) netClusterGet (pDrvCtrl->end.pNetPool,
- pDrvCtrl->pClPoolId);
- if (pCluster == NULL)
- {
- DRV_LOG (DRV_DEBUG_POLL_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
- return (EAGAIN);
- }
- retCode = mb86960PacketGet (pDrvCtrl, pCluster);
- if (retCode == OK)
- {
- len = pCluster->rxHdr.len;
- pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */
- pMblk->mBlkHdr.mLen = len; /* set the data len */
- pMblk->mBlkPktHdr.len = len; /* set the total len */
- bcopy ((char *)(char *) &pCluster->enetHdr,
- (char *)pMblk->mBlkHdr.mData, len);
- netClFree (pDrvCtrl->end.pNetPool, (UINT8 *)pCluster);
- END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
- }
- else
- retCode = EAGAIN;
- DRV_LOG (DRV_DEBUG_POLL_RX, "Received packetn", 1, 2, 3, 4, 5, 6);
- return (retCode);
- }
- /*******************************************************************************
- *
- * mb86960PollSend - routine to send a packet in polled mode.
- *
- * This routine is called by a user to try and send a packet on the
- * device.
- *
- * RETURNS: OK upon success. EAGAIN if device is busy.
- */
- LOCAL STATUS mb86960PollSend
- (
- MB86960_END_CTRL* pDrvCtrl, /* device to be polled */
- M_BLK_ID pMblk /* packet to send */
- )
- {
- return (mb86960Send (pDrvCtrl, pMblk));
- }
- /*****************************************************************************
- *
- * mb86960MCastAddrAdd - add a multicast address for the device
- *
- * This routine adds a multicast address to whatever the driver
- * is already listening for. It then resets the address filter.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960MCastAddrAdd
- (
- MB86960_END_CTRL * pDrvCtrl, /* device pointer */
- char * pAddress /* new address to add */
- )
- {
- int error;
- if ((error = etherMultiAdd (&pDrvCtrl->end.multiList,
- pAddress)) == ENETRESET)
- mb86960AddrFilterSet (pDrvCtrl, pAddress, TRUE);
- return (OK);
- }
- /*****************************************************************************
- *
- * mb86960MCastAddrDel - delete a multicast address for the device
- *
- * This routine removes a multicast address from whatever the driver
- * is listening for. It then resets the address filter.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960MCastAddrDel
- (
- MB86960_END_CTRL * pDrvCtrl, /* device pointer */
- char * pAddress /* address to be deleted */
- )
- {
- int error;
- if ((error = etherMultiDel (&pDrvCtrl->end.multiList,
- (char *)pAddress)) == ENETRESET)
- mb86960AddrFilterSet (pDrvCtrl, pAddress, FALSE);
- return (OK);
- }
- /*****************************************************************************
- *
- * mb86960MCastAddrGet - get the multicast address list for the device
- *
- * This routine gets the multicast list of whatever the driver
- * is already listening for.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960MCastAddrGet
- (
- MB86960_END_CTRL* pDrvCtrl, /* device pointer */
- MULTI_TABLE* pTable /* address table to be filled in */
- )
- {
- return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
- }
- /******************************************************************************
- *
- * mb86960AddrFilterSet - set the address filter for multicast addresses
- *
- * This routine goes through all of the multicast addresses on the list
- * of addresses (added with the MCastAddrAdd() routine) and sets the
- * device's filter correctly.
- *
- * NOMANUAL
- */
- LOCAL void mb86960AddrFilterSet
- (
- MB86960_END_CTRL* pDrvCtrl, /* device pointer */
- char * pAddr,
- BOOL bSet
- )
- {
- UINT16 nRegOffset;
- UINT16 nBitPosition;
- UINT16 nBitMask = 0x01;
- UINT16 index;
- char * pReg;
- UINT16 temp;
- char * pDev = pDrvCtrl->devBaseAddr;
- UINT16 saveConfig;
- /* get hash index for the address */
- index = mb86960HashIndex (pAddr);
- nRegOffset = index;
- nBitPosition= index;
- /* Find register and bit position */
- nBitPosition = nBitPosition & 0x0f; /* 4 LSB bits */
- nRegOffset >>= 4;
- nBitMask <<= nBitPosition;
- /* Change register map. Select hash memory register group. */
- SYS_IN_SHORT ((pDev + NICE_CONFIG), temp);
- saveConfig = temp;
- temp &= ~DLCR7_REG_BNK; /* clear bank select bits */
- temp |= DLCR7_REG_BNK_HASH; /* select hash table regs */
- temp |= DLCR6_DISABLE_DLC;
- SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);
- pReg = pDrvCtrl->devBaseAddr + NICE_HASH1 + nRegOffset*4;
- /* set the bit in bit array */
- nBitMask = MB86960_SWAP_SHORT(nBitMask);
- SYS_IN_SHORT(pReg, temp);
- if (bSet == TRUE)
- {
- temp |= nBitMask; /* set */
- }
- else
- {
- nBitMask = ~nBitMask; /* reset */
- temp &= nBitMask;
- }
- SYS_OUT_SHORT (pReg, temp);
- /* restore the configuration register */
- SYS_OUT_SHORT ((pDev + NICE_CONFIG), saveConfig);
- }
- /*******************************************************************************
- *
- * mb86960HashIndex - compute the hash index for an ethernet address
- *
- * RETURNS: hash index for an ethernet address.
- */
- LOCAL int mb86960HashIndex
- (
- char * pCp /* pointer to an ethernet address */
- )
- {
- char c;
- u_long crc;
- int len;
- int count;
- crc = 0xffffffff;
- for (len = 6; --len >= 0;)
- {
- c = *pCp++;
- for (count = 0; count < 8; count++)
- {
- if ((c & 0x01) ^ (crc & 0x01))
- {
- crc >>= 1;
- crc = crc ^ MB86960_CRC_POLY;
- }
- else
- {
- crc >>= 1;
- }
- c >>= 1;
- }
- }
- /* Just want the 6 most significant bits. */
- crc = crc >> 26;
- return (crc);
- }
- /*******************************************************************************
- *
- * mb86960Stop - stop the device
- *
- * This function calls BSP functions to disconnect interrupts and stop
- * the device from operating in interrupt mode.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960Stop
- (
- MB86960_END_CTRL * pDrvCtrl /* device to be stopped */
- )
- {
- STATUS result = OK;
- /* stop/disable the device. */
- SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), NO_RX_INTRMASK);
- SYS_INT_DISCONNECT (pDrvCtrl, mb86960Int, (int)pDrvCtrl, &result);
- if (result == ERROR)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "Could not diconnect interrupt!n",
- 1, 2, 3, 4, 5, 6);
- }
- else
- {
- END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
- }
- return (result);
- }
- /******************************************************************************
- *
- * mb86960Unload - unload a driver from the system
- *
- * This function first brings down the device, and then frees any
- * stuff that was allocated by the driver in the load function.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960Unload
- (
- MB86960_END_CTRL * pDrvCtrl /* device to be unloaded */
- )
- {
- END_OBJECT_UNLOAD (&pDrvCtrl->end);
- return (OK);
- }
- /*******************************************************************************
- *
- * mb86960PollStart - start polled mode operations
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960PollStart
- (
- MB86960_END_CTRL * pDrvCtrl /* device to be polled */
- )
- {
- int oldLevel;
- oldLevel = intLock (); /* disable ints during update */
- /* turn off interrupts */
- SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), 0);
- intUnlock (oldLevel); /* now mb86960Int won't get confused */
- pDrvCtrl->flags |= LS_POLLING;
- DRV_LOG (DRV_DEBUG_POLL, "STARTEDn", 1, 2, 3, 4, 5, 6);
- return (OK);
- }
- /*******************************************************************************
- *
- * mb86960PollStop - stop polled mode operations
- *
- * This function terminates polled mode operation. The device returns to
- * interrupt mode.
- *
- * The device interrupts are enabled, the current mode flag is switched
- * to indicate interrupt mode and the device is then reconfigured for
- * interrupt operation.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS mb86960PollStop
- (
- MB86960_END_CTRL * pDrvCtrl /* device to be changed */
- )
- {
- int oldLevel;
- oldLevel = intLock (); /* disable ints during register updates */
- /* Turn the receive interrupts on again. */
- SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), NORM_INTRMASK);
- intUnlock (oldLevel);
- pDrvCtrl->flags &= ~LS_POLLING;
- DRV_LOG (DRV_DEBUG_POLL, "STOPPEDn", 1, 2, 3, 4, 5, 6);
- return (OK);
- }