ns83902End.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:65k
源码类别:
VxWorks
开发平台:
C/C++
- /* ns83902End.c - National Semiconductor DP83902A ST-NIC */
- /* Copyright 1998-2002 Wind River Systems, Inc. */
- /* Copyright 1998-2000 Hitachi ULSI Systems Co.,LTD.,All Rights Reserved */
- /*
- modification history
- --------------------
- 01j,24apr02,h_k changed dummy read to read from pDrvCtrl->ioPort (SPR #74019).
- 01i,25mar02,h_k changed overrun handling to be done in ISR and transmit
- buffer taking from a static data (SPR #74019).
- 01h,14jan02,dat Removing warnings from Diab compiler
- 01g,10oct01,dat SPR 70829, driver used fp register - fixed., removed warnings,
- fixed casts for netClFree, fixed macros
- 01f,03oct00,zl ns83902Send() frees the Mblk chain in non-polled mode only.
- 01e,23may00,zl minor code cleanup.
- 01d,29apr00,zl redone TX interrupts, register read/write.
- 01c,21apr00,zl call netMblkClChainFree only if TX succeeds, use TX interrupts
- instead of polling.
- 01b,10apr00,zl renamed file to ns83902End.c
- 01a,20sep99,zl written based on nicMsEnd.c and nicEvbEnd.c
- */
- /*
- This module implements the National Semiconductor dp83902A ST-NIC Ethernet
- network interface driver.
- This driver is moderately generic. The driver must be given several
- target-specific parameters. These parameters, and the mechanisms used
- to communicate them to the driver, are detailed below.
- The driver supports big-endian or little-endian architectures.
- EXTERNAL INTERFACE
- The only external interface is the ns83902EndLoad() routine, which expects
- the <initString> parameter as input. This parameter passes in a
- colon-delimited string of the format:
- "<baseAdrs>:<intVec>:<intLvl>:<dmaPort>:<bufSize>:<options>"
- The ns83902EndLoad() function uses strtok() to parse the string.
- TARGET-SPECIFIC PARAMETERS
- .IP "unit"
- A convenient holdover from the former model. This parameter is used only
- in the string name for the driver.
- .IP "baseAdrs"
- Base address at which the NIC hardware device registers are located.
- .IP "vecNum"
- This is the interrupt vector number of the hardware interrupt generated by
- this Ethernet device.
- .IP "intLvl"
- This parameter defines the level of the hardware interrupt.
- .IP "dmaPort"
- Address of the DMA port used to transfer data to the host CPU.
- .IP "bufSize"
- Size of the NIC buffer memory in bytes.
- .IP "options"
- Target specific options:
- bit0 - wide (0: byte, 1: word)
- bit1 - register interval (0: 1byte, 1: 2 bytes)
- EXTERNAL SUPPORT REQUIREMENTS
- This driver requires four external support functions, and provides a hook
- function:
- .iP "void sysLanIntEnable (int level)" "" 9 -1
- This routine provides a target-specific interface for enabling Ethernet device
- interrupts at a specified interrupt level.
- .iP "void sysLanIntDisable (void)" "" 9 -1
- This routine provides a target-specific interface for disabling Ethernet device
- interrupts.
- .iP "STATUS sysEnetAddrGet (int unit, char *enetAdrs)" "" 9 -1
- This routine provides a target-specific interface for accessing a device
- Ethernet address.
- .iP "sysNs83902DelayCount" "" 9 -1
- This variable is used to introduce at least a 4 bus cycle (BSCK) delay between
- successive NIC chip selects.
- SYSTEM RESOURCE USAGE
- This driver requires the following system resources:
- - one mutual exclusion semaphore
- - one interrupt vector
- SEE ALSO: muxLib,
- .I "DP83902A ST-NIC Serial Interface Controller for Twisted Pair"
- */
- /* configurations */
- #undef NS83902_INSTRUMENT /* instrument the driver */
- #undef NS83902_DEBUG /* log debug messages */
- /* includes */
- #include "vxWorks.h"
- #include "iv.h"
- #include "vme.h"
- #include "net/mbuf.h"
- #include "net/unixLib.h"
- #include "net/protosw.h"
- #include "sys/socket.h"
- #include "sys/ioctl.h"
- #include "errno.h"
- #include "memLib.h"
- #include "intLib.h"
- #include "net/route.h"
- #include "iosLib.h"
- #include "errnoLib.h"
- #include "logLib.h"
- #include "cacheLib.h"
- #include "netLib.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "sysLib.h"
- #include "etherLib.h"
- #include "net/systm.h"
- #include "sys/times.h"
- #include "net/if_subr.h"
- #include "drv/end/ns83902End.h"
- #undef ETHER_MAP_IP_MULTICAST
- #include "etherMultiLib.h"
- #include "end.h"
- #include "endLib.h"
- #include "lstLib.h"
- #include "semLib.h"
- /* defines */
- #define NS83902_DEV_NAME "nic"
- #define NS83902_DEV_NAME_LEN 4
- #define NS83902_EADR_LEN 6
- #define NS83902_SPEED 10000000 /* 10Mbps or 100Mbps */
- #define NS83902_CRC_POLY 0x04c11db7
- #define IMR_DISABLE 0
- #define IMR_ENABLE (IMR_PRXE | IMR_OVWE | IMR_PTXE | IMR_TXEE)
- #define IMR_RX_DISABLE (IMR_OVWE | IMR_PTXE | IMR_TXEE)
- /* debug macros */
- #ifdef NS83902_DEBUG
- #ifdef LOCAL
- #undef LOCAL
- #define LOCAL
- #endif
- #define NS83902_DEBUG_OFF 0x0000
- #define NS83902_DEBUG_RX 0x0001
- #define NS83902_DEBUG_TX 0x0002
- #define NS83902_DEBUG_INT 0x0004
- #define NS83902_DEBUG_POLL (NS83902_DEBUG_POLL_RX | NS83902_DEBUG_POLL_TX)
- #define NS83902_DEBUG_POLL_RX 0x0008
- #define NS83902_DEBUG_POLL_TX 0x0010
- #define NS83902_DEBUG_LOAD 0x0020
- #define NS83902_DEBUG_IOCTL 0x0040
- #define NS83902_DEBUG_POLL_REDIR 0x10000
- #define NS83902_DEBUG_LOG_NVRAM 0x20000
- #define NS83902_DEBUG_MB 0x40000
- #define NS83902_DEBUG_TMP 0x80000
- int ns83902Debug = NS83902_DEBUG_OFF;
- NET_POOL ns83902NetPool; /* global for easy access of end.pNetPool */
- void * ns83902EndDevice; /* global for easy access of the device */
- CL_POOL_ID ns83902ClPoolId; /* global for easy access to cluster pool */
- SEM_ID ns83902DmaSemId; /* global for easy access to sem ID */
- #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
- if (ns83902Debug & FLG)
- logMsg(X0, X1, X2, X3, X4, X5, X6);
- #else /* NS83902_DEBUG */
- #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
- #endif /* NS83902_DEBUG */
- /*
- * Default macro definitions for BSP interface.
- * These macros can be redefined in a wrapper file, to generate
- * a new module with an optimized interface.
- */
- #ifndef SYS_INT_CONNECT
- #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)
- do {
- *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),
- rtn, (int)arg);
- } while (0)
- #endif /* SYS_INT_CONNECT */
- #ifndef SYS_INT_DISCONNECT
- #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)
- do {
- *pResult = OK;
- } while (0)
- #endif /* SYS_INT_DISCONNECT */
- #ifndef SYS_INT_ENABLE
- #define SYS_INT_ENABLE(pDrvCtrl)
- do {
- IMPORT void sysLanIntEnable(int);
- sysLanIntEnable (pDrvCtrl->ilevel);
- } while (0)
- #endif /* SYS_INT_ENABLE */
- #ifndef SYS_INT_DISABLE
- #define SYS_INT_DISABLE(pDrvCtrl)
- do {
- IMPORT STATUS sysLanIntDisable(int);
- sysLanIntDisable(pDrvCtrl->ilevel);
- } while (0)
- #endif /*SYS_INT_DISABLE*/
- #ifndef SYS_ENET_ADDR_GET
- #define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress)
- do {
- IMPORT STATUS sysEnetAddrGet (int, char*);
- sysEnetAddrGet (pDrvCtrl->unit, pAddress);
- } while (0)
- #endif /* SYS_ENET_ADDR_GET */
- #ifndef SYS_NS83902_DELAY
- #define SYS_NS83902_DELAY()
- do {
- IMPORT UINT32 sysNs83902DelayCount;
- volatile UINT32 cx = 0;
- for (cx = 0; cx < sysNs83902DelayCount; cx++)
- /* spin */ ;
- } while (0)
- #endif /* SYS_NS83902_DELAY */
- #ifndef SYS_MS_DELAY
- #define SYS_MS_DELAY(delay)
- do {
- IMPORT void sysMsDelay (UINT);
- sysMsDelay (delay);
- } while (0)
- #endif /* SYS_MS_DELAY */
- #ifndef SYS_IN_SHORT
- #define SYS_IN_SHORT(pDrvCtrl,addr,data)
- do {
- ((data) = *((volatile USHORT *)(addr)));
- } while (0)
- #endif /* SYS_IN_SHORT*/
- #ifndef SYS_OUT_SHORT
- #define SYS_OUT_SHORT(pDrvCtrl,addr,value)
- do {
- *((volatile USHORT *)(addr)) = (value);
- } while (0)
- #endif /* SYS_OUT_SHORT */
- #ifndef SYS_IN_BYTE
- #define SYS_IN_BYTE(pDrvCtrl, addr, data)
- do {
- ((data) = *((volatile UCHAR *)(addr)));
- } while (0)
- #endif /* SYS_IN_BYTE */
- #ifndef SYS_OUT_BYTE
- #define SYS_OUT_BYTE(pDrvCtrl, addr, value)
- do {
- *((volatile UCHAR *)(addr)) = (value);
- } while (0)
- #endif /* SYS_OUT_BYTE */
- /* Setting/Getting on-chip registers */
- #define NS83902_CR_GET(pDrvCtrl, value)
- do {
- SYS_IN_BYTE ((pDrvCtrl),
- ((pDrvCtrl)->pNic +
- (NS83902_CR) * (pDrvCtrl)->regInterval),
- (value));
- SYS_NS83902_DELAY();
- } while (0)
- #define NS83902_CR_SET(pDrvCtrl, value)
- do {
- SYS_OUT_BYTE ((pDrvCtrl),
- ((pDrvCtrl)->pNic +
- (NS83902_CR) * (pDrvCtrl)->regInterval),
- (value));
- SYS_NS83902_DELAY();
- } while (0)
- #define NS83902_REG_GET(pDrvCtrl, reg, value, page)
- (value = ns83902RegRead (pDrvCtrl, reg, page))
- #define NS83902_REG_SET(pDrvCtrl, reg, value, page)
- (ns83902RegSet (pDrvCtrl, reg, value, page))
- /* Macros for dealing with flags */
- #define DRV_FLAGS_SET(setBits)
- (pDrvCtrl->flags |= (setBits))
- #define DRV_FLAGS_ISSET(setBits)
- (pDrvCtrl->flags & (setBits))
- #define DRV_FLAGS_CLR(clrBits)
- (pDrvCtrl->flags &= ~(clrBits))
- #define DRV_FLAGS_GET()
- (pDrvCtrl->flags)
- #define NS83902_IS_IN_POLL_MODE()
- ((DRV_FLAGS_GET() & NS83902_FLAG_POLL) == NS83902_FLAG_POLL)
- #define NS83902_SEM_TAKE(pDrvCtrl, timeout)
- semTake ((pDrvCtrl)->endObj.txSem, timeout)
- #define NS83902_SEM_GIVE(pDrvCtrl)
- semGive((pDrvCtrl)->endObj.txSem)
- /* 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)
- #define END_FLAGS_ISSET(pEnd, setBits)
- ((pEnd)->flags & (setBits))
- /*
- * Macros for read and write descriptors.
- *
- */
- #define NS83902_RX_BUF_SZ sizeof(NS83902_RX_FRAME)
- #define NS83902_RX_HDR_SZ sizeof(NS83902_RX_HDR)
- #define NS83902_ETH_CRC_LEN 4
- /* typedefs */
- typedef struct rx_hdr
- {
- #if (_BYTE_ORDER == _BIG_ENDIAN)
- UINT8 nextRxPage; /* page next pkt starts at */
- UINT8 status; /* status of packet */
- #else
- UINT8 status; /* status of packet */
- UINT8 nextRxPage; /* page next pkt starts at */
- #endif
- UINT16 count; /* frame length */
- } NS83902_RX_HDR;
- typedef struct rx_frame
- {
- UINT16 pad1;
- NS83902_RX_HDR rxHdr; /* receive status header */
- ENET_HDR enetHdr; /* ethernet header */
- UINT8 data[ETHERMTU]; /* frame data */
- } NS83902_RX_FRAME;
- typedef char* NS83902_CLUSTER;
- typedef struct ns83902_end_device /* driver control structure */
- {
- END_OBJ endObj; /* The class we inherit from. */
- END_ERR lastError; /* Last error passed to muxError */
- int unit; /* unit number */
- int rringSize; /* RMD ring size */
- UCHAR enetAddr[NS83902_EADR_LEN]; /* ethernet address */
- char* pNic; /* address of NIC chip */
- char* ioPort; /* port address of remote DMA */
- NS83902_CLUSTER pCluster; /* Rx frame memory */
- CL_POOL_ID pClPoolId; /* cluster pool */
- int regInterval; /* address diff of adjacent regs */
- BOOL wide; /* I/O port is 16 bit (when TRUE) */
- int ivec; /* interrupt vector */
- int ilevel; /* interrupt level */
- UINT8 regPage; /* current register page */
- UINT8 txStartPage; /* ptr to Tx start buffer */
- UINT8 rxStartPage; /* ptr to Rx start buffer */
- UINT8 rxStopPage; /* ptr to Rx stop buffer */
- UINT8 nextPage; /* ptr to next page */
- NS83902_DRV_FLAG flags; /* device specific flags */
- BOOL rxHandling; /* rcv task is scheduled */
- BOOL txBlocked; /* to implement flow control */
- BOOL rxOvw; /* overwrite warning */
- BOOL txResend; /* resend need at overwrite */
- } NS83902_END_DEVICE;
- /* network buffers configuration */
- M_CL_CONFIG ns83902MclBlkConfig = /* network mbuf configuration table */
- {
- /*
- no. mBlks no. clBlks memArea memSize
- --------- ---------- ------- -------
- */
- 0, 0, NULL, 0
- };
- CL_DESC ns83902ClDescTbl [] = /* cluster pool configuration table */
- {
- /*
- clSize num memArea memSize
- ------ ---- ------- -------
- */
- {0, 0, NULL, 0}
- };
- int ns83902ClDescTblNumEnt = (NELEMENTS(ns83902ClDescTbl));
- /* globals */
- #ifdef NS83902_INSTRUMENT
- UINT32 ns83902TxTimeout = 0; /* number of transmit time-out */
- UINT32 ns83902TxError = 0; /* number of transmit errors */
- UINT32 ns83902RestartNb = 0; /* number of restart due to ring overflow */
- UINT32 ns83902InitNb = 0; /* number of time device is re-initialized */
- UINT32 ns83902TxNb = 0; /* number of transmitted packets */
- UINT32 ns83902IntNb = 0; /* number of receive interrupt */
- UINT32 ns83902Len = 0; /* lenght of the current received packet */
- UINT32 ns83902HdrStat = 0; /* status byte of the current received packet */
- UINT32 ns83902NextPage = 0; /* page pointer to the next received packet */
- UINT32 ns83902CurrentPage = 0; /* start page of the current packet */
- #endif
- /* forward declarations */
- LOCAL void ns83902MARSet (NS83902_END_DEVICE* pDrvCtrl, UINT8 index,
- BOOL bSet);
- LOCAL STATUS ns83902AddrFilterSet (NS83902_END_DEVICE *pDrvCtrl,
- char* pAddr, BOOL bSet);
- LOCAL int ns83902HashIndex (char* eAddr);
- LOCAL void ns83902Int (NS83902_END_DEVICE* pDrvCtrl);
- LOCAL void ns83902Restart (NS83902_END_DEVICE *pDrvCtrl, UINT8 cr);
- LOCAL void ns83902HandleInt (NS83902_END_DEVICE *pDrvCtrl);
- LOCAL void ns83902Recv (NS83902_END_DEVICE *pDrvCtrl,
- NS83902_CLUSTER pCluster);
- LOCAL NS83902_CLUSTER ns83902ReadFrame (NS83902_END_DEVICE* pDrvCtrl);
- LOCAL void ns83902Config (NS83902_END_DEVICE* pDrvCtrl);
- LOCAL STATUS ns83902PktBufRead (NS83902_END_DEVICE *pDrvCtrl, UINT32
- ns83902BufAddr, UINT32 len, char *pData);
- LOCAL STATUS ns83902Transmit (NS83902_END_DEVICE *pDrvCtrl, M_BLK* pMblk);
- LOCAL void ns83902ReadPort (NS83902_END_DEVICE* pDrvCtrl,
- char *pBuf, int len);
- LOCAL void ns83902WritePort (NS83902_END_DEVICE* pDrvCtrl,
- char *pBuf, int len);
- LOCAL STATUS ns83902InitParse (NS83902_END_DEVICE* pDrvCtrl,
- char * initString);
- LOCAL STATUS ns83902InitMem (NS83902_END_DEVICE* pDrvCtrl);
- LOCAL void ns83902EnetAddrGet (NS83902_END_DEVICE* pDrvCtrl, char* addr);
- LOCAL void ns83902RegSet (NS83902_END_DEVICE* pDrvCtrl, int reg,
- int value, int page);
- LOCAL UINT8 ns83902RegRead (NS83902_END_DEVICE* pDrvCtrl, int reg,
- int page);
- /* END Specific interfaces. */
- END_OBJ * ns83902EndLoad (char *initString);
- LOCAL STATUS ns83902Unload (NS83902_END_DEVICE* pDrvCtrl);
- LOCAL STATUS ns83902Start (NS83902_END_DEVICE* pDrvCtrl);
- LOCAL STATUS ns83902Stop (NS83902_END_DEVICE* pDrvCtrl);
- LOCAL int ns83902Ioctl (NS83902_END_DEVICE* pDrvCtrl, int cmd,
- caddr_t data);
- LOCAL STATUS ns83902Send (NS83902_END_DEVICE* pDrvCtrl, M_BLK *pMblk);
- LOCAL STATUS ns83902MCastAddrAdd (NS83902_END_DEVICE *pDrvCtrl,
- char* pAddress);
- LOCAL STATUS ns83902MCastAddrDel (NS83902_END_DEVICE *pDrvCtrl,
- char* pAddress);
- LOCAL STATUS ns83902MCastAddrGet (NS83902_END_DEVICE *pDrvCtrl,
- MULTI_TABLE *pTable);
- LOCAL STATUS ns83902PollSend (NS83902_END_DEVICE *pDrvCtrl, M_BLK *pMblk);
- LOCAL STATUS ns83902PollReceive (NS83902_END_DEVICE *pDrvCtrl, M_BLK *pMblk);
- LOCAL STATUS ns83902PollStart (NS83902_END_DEVICE *pDrvCtrl);
- LOCAL STATUS ns83902PollStop (NS83902_END_DEVICE *pDrvCtrl);
- /*
- * Declare our function table. This is static across all driver
- * instances.
- */
- LOCAL NET_FUNCS ns83902FuncTable =
- {
- (FUNCPTR)ns83902Start, /* Function to start the device. */
- (FUNCPTR)ns83902Stop, /* Function to stop the device. */
- (FUNCPTR)ns83902Unload, /* Unloading function */
- (FUNCPTR)ns83902Ioctl, /* Ioctl function */
- (FUNCPTR)ns83902Send, /* Send function */
- (FUNCPTR)ns83902MCastAddrAdd, /* Multicast address add */
- (FUNCPTR)ns83902MCastAddrDel, /* Multicast address delete */
- (FUNCPTR)ns83902MCastAddrGet, /* Multicast table retrieve */
- (FUNCPTR)ns83902PollSend, /* Polling send function */
- (FUNCPTR)ns83902PollReceive, /* Polling receive function */
- endEtherAddressForm, /* Put address info into a packet. */
- endEtherPacketDataGet, /* Get a pointer to packet data. */
- endEtherPacketAddrGet, /* Get packet addresses. */
- NULL /* Bind function */
- };
- /******************************************************************************
- *
- * ns83902EndLoad - 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>.
- * 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, "ln") 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* ns83902EndLoad
- (
- char* initString /* string to be parsed */
- )
- {
- NS83902_END_DEVICE *pDrvCtrl;
- DRV_LOG (NS83902_DEBUG_LOAD, "Loading ns83902End...n", 1, 2, 3, 4, 5, 6);
- if (initString == NULL)
- return (NULL);
- if (initString[0] == ' ')
- {
- bcopy((char *)NS83902_DEV_NAME, initString, NS83902_DEV_NAME_LEN);
- return (0);
- }
- /* allocate the device structure */
- pDrvCtrl = (NS83902_END_DEVICE *)calloc (sizeof (NS83902_END_DEVICE), 1);
- if (pDrvCtrl == NULL)
- goto errorExit;
- /* parse the init string, filling in the device structure */
- if (ns83902InitParse (pDrvCtrl, initString) == ERROR)
- goto errorExit;
- /* Have the BSP hand us our address. */
- ns83902EnetAddrGet (pDrvCtrl, (char*) &(pDrvCtrl->enetAddr));
- DRV_LOG (NS83902_DEBUG_LOAD, "ENET Addr: %x:%x:%x:%x:%x:%x n",
- pDrvCtrl->enetAddr[0], pDrvCtrl->enetAddr[1],
- pDrvCtrl->enetAddr[2], pDrvCtrl->enetAddr[3],
- pDrvCtrl->enetAddr[4], pDrvCtrl->enetAddr[5]);
- /* initialize the END and MIB2 parts of the structure */
- if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, NS83902_DEV_NAME,
- pDrvCtrl->unit, &ns83902FuncTable,
- "ST-NIC Enhanced Network Driver") == ERROR
- || END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
- &pDrvCtrl->enetAddr[0], NS83902_EADR_LEN, ETHERMTU,
- NS83902_SPEED)
- == ERROR)
- goto errorExit;
- /* set buffer address; reserve 8 pages for TX */
- pDrvCtrl->txStartPage = 0;
- pDrvCtrl->rxStartPage = pDrvCtrl->txStartPage + 8;
- pDrvCtrl->nextPage = pDrvCtrl->rxStartPage;
- /* size of the whole ring */
- pDrvCtrl->rringSize = pDrvCtrl->rxStopPage - pDrvCtrl->rxStartPage + 1;
- /* Perform memory allocation */
- if (ns83902InitMem (pDrvCtrl) == ERROR)
- {
- DRV_LOG (NS83902_DEBUG_LOAD, "Error in InitMem...n", 1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- /* set the flags to indicate readiness */
- END_OBJ_READY (&pDrvCtrl->endObj,
- IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
- DRV_LOG (NS83902_DEBUG_LOAD, "Done loading ns83902End...n", 1, 2, 3, 4, 5, 6);
- /* save the device address */
- #ifdef NS83902_DEBUG
- ns83902EndDevice = pDrvCtrl;
- ns83902DmaSemId = pDrvCtrl->endObj.txSem;
- #endif
- return (&pDrvCtrl->endObj);
- errorExit:
- ns83902Unload (pDrvCtrl);
- return NULL;
- }
- /*******************************************************************************
- *
- * ns83902InitParse - parse the initialization string
- *
- * Parse the input string and fill in values in the driver control structure.
- *
- * RETURNS: OK, or ERROR if any arguments are invalid.
- */
- LOCAL STATUS ns83902InitParse
- (
- NS83902_END_DEVICE * pDrvCtrl,
- char * initString
- )
- {
- char * tok;
- char * pHolder = NULL;
- long address;
- UINT8 options;
- /* Parse the initString */
- /* Unit number. */
- tok = strtok_r (initString, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->unit = atoi (tok);
- /* NIC address. */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- address = strtoul (tok, NULL, 16);
- pDrvCtrl->pNic = (char*) address;
- /* Interrupt vector. */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->ivec = atoi (tok);
- /* Interrupt level. */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->ilevel = atoi (tok);
- /* Remote DMA I/O address. */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->ioPort = (char *) strtoul (tok, NULL, 16);
- /* Get ring buffer size in pages */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- pDrvCtrl->rxStopPage = strtoul (tok, NULL, 16) / NS83902_PAGE_SIZE;
- /* Get target options */
- tok = strtok_r (NULL, ":", &pHolder);
- if (tok == NULL)
- return ERROR;
- options = strtoul (tok, NULL, 16);
- pDrvCtrl->wide = options & NS83902_WIDE_MASK;
- pDrvCtrl->regInterval = 1 << ((options & NS83902_INTERVAL_MASK) >> 1);
- DRV_LOG (NS83902_DEBUG_LOAD, "Processed all arugmentsn", 1, 2, 3, 4, 5, 6);
- DRV_LOG (NS83902_DEBUG_LOAD, "Address %p Lvl %u Vec %d Port %p Ring %p n",
- (int)pDrvCtrl->pNic, pDrvCtrl->ilevel, pDrvCtrl->ivec,
- (int)pDrvCtrl->ioPort, pDrvCtrl->rxStopPage, 6);
- DRV_LOG (NS83902_DEBUG_LOAD, "Transfer width: %s n",
- (int)(pDrvCtrl->wide ? "word":"byte"), 2, 3, 4, 5, 6);
- DRV_LOG (NS83902_DEBUG_LOAD, "Register interval: %d n",
- pDrvCtrl->regInterval, 2, 3, 4, 5, 6);
- return OK;
- }
- /*******************************************************************************
- *
- * ns83902InitMem - initialize memory for NIC chip
- *
- * Using data in the control structure, setup and initialize the memory
- * areas needed. If the memory address is not already specified, then allocate
- * cache safe memory.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS ns83902InitMem
- (
- NS83902_END_DEVICE * pDrvCtrl /* device to be initialized */
- )
- {
- /* allocate netpool */
- if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
- return (ERROR);
- /* Set number of M-Blks and CL-Blks*/
- ns83902MclBlkConfig.mBlkNum = pDrvCtrl->rringSize;
- ns83902MclBlkConfig.clBlkNum= pDrvCtrl->rringSize / 2;
- ns83902ClDescTbl[0].clNum = ns83902MclBlkConfig.clBlkNum;
- /* Calculate the total memory for all the M-Blks and CL-Blks. */
- ns83902MclBlkConfig.memSize = ns83902MclBlkConfig.mBlkNum *
- (MSIZE + sizeof (long)) +
- ns83902MclBlkConfig.clBlkNum *
- (CL_BLK_SZ + sizeof(long));
- /* allocate memory for M-Blks and CL-Blks */
- ns83902MclBlkConfig.memArea = (char *) memalign (sizeof(long),
- ns83902MclBlkConfig.memSize);
- if (ns83902MclBlkConfig.memArea == NULL)
- return (ERROR);
- /* Calculate the memory size of all the clusters. */
- ns83902ClDescTbl[0].clSize = NS83902_RX_BUF_SZ;
- ns83902ClDescTbl[0].memSize = sizeof(long) + ns83902ClDescTbl[0].clNum *
- (ns83902ClDescTbl[0].clSize + 8);
- /* Allocate memory for clusters */
- ns83902ClDescTbl[0].memArea = (char *) memalign (sizeof(long),
- ns83902ClDescTbl[0].memSize);
- if (ns83902ClDescTbl[0].memArea == NULL)
- {
- DRV_LOG (NS83902_DEBUG_LOAD, "system memory unavailablen",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- /* Save clusters start address for later use */
- pDrvCtrl->pCluster = (NS83902_CLUSTER) ns83902ClDescTbl[0].memArea;
- /* Initialize the net buffer pool with buffers */
- if (netPoolInit (pDrvCtrl->endObj.pNetPool, &ns83902MclBlkConfig,
- &ns83902ClDescTbl[0], ns83902ClDescTblNumEnt, NULL) == ERROR)
- {
- DRV_LOG (NS83902_DEBUG_LOAD, "Could not init bufferingn",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- /* Store the cluster pool id as others need it later. */
- pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool,
- NS83902_RX_BUF_SZ, FALSE);
- if (pDrvCtrl->pClPoolId == NULL)
- return (ERROR);
- #ifdef NS83902_DEBUG
- ns83902NetPool = *pDrvCtrl->endObj.pNetPool;
- ns83902ClPoolId = pDrvCtrl->pClPoolId;
- #endif
- return (OK);
- }
- /*******************************************************************************
- *
- * ns83902Start - start the device
- *
- * This function calls BSP functions to connect interrupts and start the
- * device running in interrupt mode.
- *
- * RETURNS: OK or ERROR
- *
- */
- LOCAL STATUS ns83902Start
- (
- NS83902_END_DEVICE *pDrvCtrl
- )
- {
- STATUS result;
- /* Clear statuses */
- pDrvCtrl->rxHandling = FALSE;
- pDrvCtrl->txBlocked = FALSE;
- pDrvCtrl->rxOvw = FALSE;
- pDrvCtrl->txResend = FALSE;
- /* reset the device */
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
- /* connect interrupt handler */
- SYS_INT_CONNECT (pDrvCtrl, ns83902Int, (int)pDrvCtrl, &result);
- if (result == ERROR)
- return ERROR;
- DRV_LOG (NS83902_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
- /* device config */
- ns83902Config (pDrvCtrl);
- /* mark the interface -- up */
- END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
- SYS_INT_ENABLE (pDrvCtrl);
- DRV_LOG (NS83902_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
- return (OK);
- }
- /*******************************************************************************
- *
- * ns83902Config - configure the NIC chip and program address
- *
- * This routine follows the algorythm in the ST-NIC manual for enabling
- * a NIC device on an active network. Essentially, this routine initializes
- * the NIC device.
- *
- * RETURNS: N/A.
- */
- LOCAL void ns83902Config
- (
- NS83902_END_DEVICE * pDrvCtrl /* device to be configured */
- )
- {
- UCHAR* pEnetAddr = pDrvCtrl->enetAddr;
- UCHAR dcr;
- /* Page 0 */
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
- /* Enable broadcast, Endian, Word Size */
- #if (_BYTE_ORDER == _BIG_ENDIAN)
- dcr = DCR_NOTLS | DCR_FIFO8 | DCR_BOS;
- #else
- dcr = DCR_NOTLS | DCR_FIFO8;
- #endif
- if (pDrvCtrl->wide == TRUE)
- dcr |= DCR_WTS;
- NS83902_REG_SET (pDrvCtrl, NS83902_DCR, dcr, CR_RPAGE0);
- /* Clear the remote byte count reg. */
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 0, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0);
- /* Set to monitor and loopback mode */
- NS83902_REG_SET (pDrvCtrl, NS83902_RCR, RCR_MON, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE1, CR_RPAGE0);
- /* Accept Broadcast */
- NS83902_REG_SET (pDrvCtrl, NS83902_RCR, (RCR_AB | RCR_AM), CR_RPAGE0);
- /* Set the transmit page and receive page */
- NS83902_REG_SET (pDrvCtrl, NS83902_PSTART, pDrvCtrl->rxStartPage, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_PSTOP, pDrvCtrl->rxStopPage, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_TPSR, pDrvCtrl->txStartPage, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, pDrvCtrl->rxStopPage - 1, CR_RPAGE0);
- /* Clear the pending interrupts and mask. */
- NS83902_REG_SET (pDrvCtrl, NS83902_ISR, 0xff, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);
- /* set MAC Address */
- NS83902_REG_SET (pDrvCtrl, NS83902_PAR0, pEnetAddr [0], CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_PAR1, pEnetAddr [1], CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_PAR2, pEnetAddr [2], CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_PAR3, pEnetAddr [3], CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_PAR4, pEnetAddr [4], CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_PAR5, pEnetAddr [5], CR_RPAGE1);
- /* Initialize the multicast list to accept all. */
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR0, 0x00, CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR1, 0x00, CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR2, 0x00, CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR3, 0x00, CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR4, 0x00, CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR5, 0x00, CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR6, 0x00, CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR7, 0x00, CR_RPAGE1);
- NS83902_REG_SET (pDrvCtrl, NS83902_CURR, pDrvCtrl->rxStartPage, CR_RPAGE1);
- /* Page 0 */
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
- /* set the interrupt mask */
- NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_ENABLE, CR_RPAGE0);
- /* Start */
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_ABORT | CR_STA, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE0, CR_RPAGE0);
- }
- /*******************************************************************************
- *
- * ns83902EnetAddrGet - get the Ethernet address.
- *
- * Get ethernet address from the BSP.
- *
- * RETURNS: N/A.
- */
- LOCAL void ns83902EnetAddrGet
- (
- NS83902_END_DEVICE* pDrvCtrl,
- char* addr
- )
- {
- #if _BYTE_ORDER == _BIG_ENDIAN
- /* For big endian we need to swap byte order */
- int i;
- char bytes[6];
- SYS_ENET_ADDR_GET (pDrvCtrl, bytes);
- for (i=0; i<6; i++)
- *addr++ = bytes[5-i];
- #else /* _BYTE_ORDER == _LITTLE_ENDIAN */
- /* Little endian is in correct order */
- SYS_ENET_ADDR_GET (pDrvCtrl, addr);
- #endif /* _BYTE_ORDER == _BIG_ENDIAN */
- }
- /*******************************************************************************
- *
- * ns83902WritePort - write to the DMA port
- *
- * RETURNS: N/A.
- */
- LOCAL void ns83902WritePort
- (
- NS83902_END_DEVICE* pDrvCtrl,
- char * pBuf,
- int len
- )
- {
- int ix;
- UINT16 * pWide;
- if (pDrvCtrl->wide == TRUE)
- {
- len = (++len) >> 1;
- pWide = (UINT16 *) pBuf;
- for (ix = 0 ; ix < len; ix++)
- {
- SYS_OUT_SHORT (pDrvCtrl, pDrvCtrl->ioPort, *pWide++);
- SYS_NS83902_DELAY();
- }
- }
- else
- {
- for (ix = 0 ; ix < len; ix++)
- {
- SYS_OUT_BYTE (pDrvCtrl, pDrvCtrl->ioPort, *pBuf++);
- SYS_NS83902_DELAY();
- }
- }
- }
- /*******************************************************************************
- *
- * ns83902ReadPort - read the DMA port
- *
- * RETURNS: N/A.
- */
- LOCAL void ns83902ReadPort
- (
- NS83902_END_DEVICE* pDrvCtrl,
- char * pBuf,
- int len
- )
- {
- int ix;
- UINT16 * pWide;
- if (pDrvCtrl->wide == TRUE)
- {
- len = (++len) >> 1;
- pWide = (UINT16 *) pBuf;
- for (ix = 0 ; ix < len; ix++)
- {
- SYS_IN_SHORT (pDrvCtrl, pDrvCtrl->ioPort, *pWide++);
- }
- }
- else
- {
- for (ix = 0 ; ix < len; ix++)
- {
- SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, *pBuf++);
- }
- }
- }
- /*******************************************************************************
- *
- * ns83902PktBufRead - read data from the NIC receive ring buffer
- *
- * This routine gets exclusive access to the remote DMA, and gets data from
- * the NIC's receive ring buffer.
- *
- * RETURNS: OK, or ERROR if obtaining the requested bytes encountered an error.
- */
- LOCAL STATUS ns83902PktBufRead
- (
- NS83902_END_DEVICE* pDrvCtrl,
- UINT32 ns83902BufAddr,
- UINT32 len,
- char* pData
- )
- {
- /* Exclusive DMA access */
- if (!NS83902_IS_IN_POLL_MODE())
- NS83902_SEM_TAKE (pDrvCtrl, WAIT_FOREVER);
- DRV_LOG (NS83902_DEBUG_RX,
- "ns83902Receive: ns83902BufAddr:%u pData:%p len:%dn",
- ns83902BufAddr, (int)pData, len, 4, 5, 6);
- /* Set up remote read DMA transfer */
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, LSB(len), CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, MSB(len), CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, LSB(ns83902BufAddr), CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, MSB(ns83902BufAddr), CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RREAD, CR_RPAGE0);
- /* Get data through DMA port */
- ns83902ReadPort (pDrvCtrl, pData, len);
- if (!NS83902_IS_IN_POLL_MODE())
- NS83902_SEM_GIVE (pDrvCtrl);
- return (OK);
- }
- /*******************************************************************************
- *
- * ns83902ReadFrame - read a packet off the interface ring buffer into a cluster
- *
- * Allocates a new cluster from the cluster pool, and reads the frame from the
- * device into the cluster.
- *
- * RETURNS: a cluster or NULL if any error
- */
- LOCAL NS83902_CLUSTER ns83902ReadFrame
- (
- NS83902_END_DEVICE* pDrvCtrl
- )
- {
- NS83902_RX_FRAME* pRx;
- NS83902_CLUSTER pRetCluster = NULL;
- UINT32 frameAddress;
- UINT16 len; /* len of Rx pkt */
- UINT8 bnry;
- UINT8 rsr;
- UINT8 cur;
- /* Check receive status */
- NS83902_REG_GET (pDrvCtrl, NS83902_RSR, rsr, CR_RPAGE0);
- if ((rsr & RSR_PRX) != RSR_PRX)
- return (pRetCluster);
- NS83902_REG_GET (pDrvCtrl, NS83902_CURR, cur, CR_RPAGE1);
- if (!(END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) ||
- (pDrvCtrl->nextPage == cur))
- return (pRetCluster);
- DRV_LOG (NS83902_DEBUG_RX, "Start Read!n", 1, 2, 3, 4, 5, 6);
- /*
- * There is work to be done.
- * First we copy the NIC receive status header from the NIC buffer
- * into our local area. This is done so that we can obtain the length
- * of the packet before copying out the rest of it. Note that the length
- * field in the NIC header includes the Ethernet header, the data, and
- * the 4 byte FCS field.
- */
- /* Get a cluster */
- if ((pRx = (NS83902_RX_FRAME*) netClusterGet (pDrvCtrl->endObj.pNetPool,
- pDrvCtrl->pClPoolId)) == NULL)
- {
- pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
- muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);
- DRV_LOG (NS83902_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
- return (pRetCluster);
- }
- /* read header */
- DRV_LOG (NS83902_DEBUG_RX, "ns83902PktBufRead : Reading Headern",
- 1, 2, 3, 4, 5, 6);
- if (ns83902PktBufRead (pDrvCtrl, pDrvCtrl->nextPage << 8,
- (NS83902_RX_HDR_SZ), (char *) &pRx->rxHdr) == ERROR)
- {
- DRV_LOG (NS83902_DEBUG_RX,
- "ns83902PktBufRead could not read packet headern",
- 0, 0, 0, 0, 0, 0);
- netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
- return (pRetCluster);
- }
- /* Calculate real length */
- len = pRx->rxHdr.count;
- #if (_BYTE_ORDER == _BIG_ENDIAN)
- len = ((len >> 8) & 0x00ff) + ((len << 8) & 0xff00) - NS83902_ETH_CRC_LEN;
- #else
- len = len - NS83902_ETH_CRC_LEN;
- #endif
- /* write back value to rxHdr */
- pRx->rxHdr.count = len;
- /* Current frame address and next page */
- frameAddress = (pDrvCtrl->nextPage << 8) + NS83902_RX_HDR_SZ;
- pDrvCtrl->nextPage = pRx->rxHdr.nextRxPage;
- /* valid frame checks */
- #ifdef NS83902_INSTRUMENT
- ns83902Len = len;
- ns83902HdrStat = pRx->rxHdr.status;
- ns83902NextPage = pRx->rxHdr.nextRxPage;
- ns83902CurrentPage = cur;
- #endif
- /* check for critical error; should never happen */
- if (pDrvCtrl->nextPage < pDrvCtrl->rxStartPage ||
- pDrvCtrl->nextPage >= pDrvCtrl->rxStopPage )
- {
- /* Can't recover, restart */
- #ifdef NS83902_INSTRUMENT
- ns83902InitNb++;
- #endif
- ns83902Config (pDrvCtrl);
- pDrvCtrl->nextPage = pDrvCtrl->rxStartPage;
- /* mark the interface up */
- END_FLAGS_SET (&pDrvCtrl->endObj,
- (IFF_UP | IFF_RUNNING | IFF_MULTICAST | IFF_BROADCAST));
- netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
- return (pRetCluster);
- }
- /*
- * If the packet's receive status byte indicates an error the packet is
- * discarded and the receive page pointers are updated to point to the
- * next packet.
- */
- if ((len < 60) || (len > 1514) ||
- ((pRx->rxHdr.status & ~RSR_PHY) != RSR_PRX))
- {
- DRV_LOG (NS83902_DEBUG_RX,
- "ns83902Rcv receive error: statusHeader=0x%x nextRxPage=%d
- currentPage=%d len=%d IntNb=%dn",
- pRx->rxHdr.status, pRx->rxHdr.nextRxPage, cur, len,
- ns83902IntNb, 0);
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
- /* update boundary pointer */
- if (pDrvCtrl->nextPage == pDrvCtrl->rxStartPage)
- bnry = pDrvCtrl->rxStopPage;
- else
- bnry = pDrvCtrl->nextPage - 1;
- NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, bnry, CR_RPAGE0);
- netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
- return (pRetCluster);
- }
- /* copy Ethernet packet section of the frame */
- DRV_LOG (NS83902_DEBUG_RX, "ns83902PktBufRead : Reading Framen",
- 1, 2, 3, 4, 5, 6);
- if (ns83902PktBufRead (pDrvCtrl, frameAddress, len,
- (char *) &pRx->enetHdr) == ERROR)
- {
- DRV_LOG (NS83902_DEBUG_RX, "ns83902Recv: Could not read packet datan",
- 1, 2, 3, 4, 5, 6);
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
- netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
- }
- else
- {
- /* Successfully got a frame */
- pRetCluster = (NS83902_CLUSTER) pRx;
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
- }
- /* update boundary pointer */
- if (pDrvCtrl->nextPage == pDrvCtrl->rxStartPage)
- bnry = pDrvCtrl->rxStopPage;
- else
- bnry = pDrvCtrl->nextPage - 1;
- NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, bnry, CR_RPAGE0);
- DRV_LOG (NS83902_DEBUG_RX, "End Read!n", 1, 2, 3, 4, 5, 6);
- return (pRetCluster);
- }
- /*******************************************************************************
- *
- * ns83902Recv - read a packet off the interface ring buffer
- *
- * ns83902Recv copies packets from local memory into an mbuf and hands it to
- * the next higher layer (IP or etherInputHook).
- *
- * RETURNS: TRUE, or FALSE if the packet reception encountered errors.
- */
- LOCAL void ns83902Recv
- (
- NS83902_END_DEVICE* pDrvCtrl,
- NS83902_CLUSTER pCluster
- )
- {
- NS83902_RX_FRAME* pRx = (NS83902_RX_FRAME*) pCluster;
- CL_BLK_ID pClBlk;
- M_BLK_ID pMblk;
- UINT32 len = pRx->rxHdr.count;
- /* Process frame received */
- if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL)
- {
- pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
- muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);
- DRV_LOG (NS83902_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
- netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pCluster);
- END_ERR_ADD (&pDrvCtrl->endObj, 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->endObj.pNetPool, M_DONTWAIT, MT_DATA)) ==
- NULL)
- {
- netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk);
- netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pCluster);
- DRV_LOG (NS83902_DEBUG_MB, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
- goto cleanRXD;
- }
- END_ERR_ADD (&pDrvCtrl->endObj, 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 *)&pRx->enetHdr;
- 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 */
- /* Call the upper layer's receive routine. */
- END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);
- cleanRXD:
- return;
- }
- /*******************************************************************************
- *
- * ns83902Restart - restart chip after receive ring buffer overflow
- *
- * This routine is called from an isr handler that deals with a receive DMA
- * overflow condition. It gets access to the remote DMA, cleans up NIC
- * registers and defers work to task context to empty the receive ring buffers.
- *
- * RETURNS: N/A.
- */
- LOCAL void ns83902Restart
- (
- NS83902_END_DEVICE* pDrvCtrl,
- UINT8 cr
- )
- {
- UINT8 isr;
- #ifdef NS83902_INSTRUMENT
- ns83902RestartNb++;
- #endif
- /* Buffer ring overflow algorithm */
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
- /* wait at least 1.6 mSec */
- SYS_MS_DELAY (2);
- /* Remove packets from buffer */
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 0, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0);
- NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);
- if ((cr & CR_TXP) && (!(isr & (ISR_TXE | ISR_PTX))))
- pDrvCtrl->txResend = TRUE;
- NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE1, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_ABORT | CR_STA, CR_RPAGE0);
- END_FLAGS_SET (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);
- pDrvCtrl->rxOvw = TRUE;
- if (pDrvCtrl->rxHandling == FALSE)
- {
- pDrvCtrl->rxHandling = TRUE;
- netJobAdd ((FUNCPTR) ns83902HandleInt, (int) pDrvCtrl, 0, 0, 0, 0);
- }
- }
- /*******************************************************************************
- *
- * ns83902HandleInt - deferred receive interrupt handler
- *
- * This function handles the received frames from the device. It runs in the
- * context of the netTask, which was triggered by a received packet interrupt.
- * It resends any packet that was in the midst of transmission when the overflow
- * hit.
- * Actual processing of the packet is done by calling ns83902Recv().
- *
- * RETURNS: N/A.
- */
- LOCAL void ns83902HandleInt
- (
- NS83902_END_DEVICE* pDrvCtrl
- )
- {
- NS83902_CLUSTER pCluster;
- /* empties the receive ring buffer of its packets */
- pDrvCtrl->rxHandling = TRUE;
- while ((pCluster = ns83902ReadFrame (pDrvCtrl)) != NULL)
- ns83902Recv (pDrvCtrl, pCluster);
- pDrvCtrl->rxHandling = FALSE;
- if (pDrvCtrl->rxOvw == TRUE)
- {
- /* Reset overflow bit */
- NS83902_REG_SET (pDrvCtrl, NS83902_ISR, ISR_OVW, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE0, CR_RPAGE0);
- /* If resend needed, issue transmit command */
- if (pDrvCtrl->txResend == TRUE)
- {
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STA | CR_TXP | CR_ABORT,
- CR_RPAGE0);
- pDrvCtrl->txResend = FALSE;
- }
- pDrvCtrl->rxOvw = FALSE;
- }
- /* Re-enable interrupts */
- NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_ENABLE, CR_RPAGE0);
- }
- /*******************************************************************************
- *
- * ns83902Int - The driver's interrupt handler
- *
- * This function clears the cause of the device interrupt(s) and then acts
- * on the individual possible causes. The primary goal of this routine is to
- * minimize the time spent in it. This is accomplished by deferring processing
- * to the netTask via the netJobAdd() function.
- *
- * Note that in case the receiver overruns, we promptly mark the interface as
- * "down" and leave error handling to task-level. This is in case netTask
- * is in the midst of DMA activity, we must allow it to complete. The receive
- * handler will give up when it discovers the interface is down, which will
- * then allow netTask to run our OVW handler. This provides orderly error
- * recovery.
- *
- * RETURNS: N/A.
- */
- LOCAL void ns83902Int
- (
- NS83902_END_DEVICE* pDrvCtrl
- )
- {
- UINT8 isr; /* copy of NS83902_ISR */
- UINT8 cr; /* copy of NS83902_CR */
- /* Check if interface is up and running */
- if ((END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) !=
- (IFF_UP | IFF_RUNNING))
- return;
- #ifdef NS83902_INSTRUMENT
- ns83902IntNb++;
- #endif
- DRV_LOG (NS83902_DEBUG_INT, "Inside INTn", 1, 2, 3, 4, 5, 6);
- /* Read and clear ISR */
- NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);
- /* handle transmit interrupts */
- if (isr & (ISR_PTX | ISR_TXE))
- {
- UINT8 tsr;
- NS83902_REG_GET (pDrvCtrl, NS83902_TSR, tsr, CR_RPAGE0);
- DRV_LOG (NS83902_DEBUG_TX, "ns83902Tx Interrupt TSR=%d n", tsr,
- 2, 3, 4, 5, 6);
- if ((tsr & TSR_PTX) == 0)
- {
- /* PTX zero, something went wrong */
- if (tsr & TSR_ABT)
- {
- #ifdef NS83902_INSTRUMENT
- ns83902TxTimeout++;
- #endif
- DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Aborted n",
- 1, 2, 3, 4, 5, 6);
- }
- if (tsr & TSR_FU)
- {
- DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit FIFO Underrun n",
- 1, 2, 3, 4, 5, 6);
- }
- /* Notify upper layers about the error */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
- pDrvCtrl->lastError.errCode = END_ERR_WARN;
- pDrvCtrl->lastError.pMesg = "Transmit error";
- netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,
- (int) &pDrvCtrl->lastError, 0, 0, 0);
- DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Errorn", 0, 0, 0, 0, 0, 0);
- #ifdef NS83902_INSTRUMENT
- ns83902TxError++;
- #endif
- }
- if (tsr & TSR_CRS)
- {
- DRV_LOG (NS83902_DEBUG_TX, "%s%d - no carriern", (int)NS83902_DEV_NAME,
- pDrvCtrl->unit, 3, 4, 5, 6);
- }
- #if 0 /* no collision statistics for END drivers? */
- if (tsr & TSR_COL)
- {
- UINT8 ncr;
- NS83902_REG_GET (pDrvCtrl, NS83902_NCR, ncr, CR_RPAGE0);
- END_ERR_ADD (pEndObj, MIB2_COLLISIONS, ncr);
- }
- #endif
- if (pDrvCtrl->txBlocked == TRUE)
- {
- pDrvCtrl->txBlocked = FALSE;
- netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj, 0, 0, 0, 0);
- }
- }
- /* handle receiver overrun */
- if (isr & ISR_OVW)
- {
- /* disable interrupts */
- NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);
- NS83902_CR_GET (pDrvCtrl, cr);
- /* mark the interface down */
- END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING);
- ns83902Restart (pDrvCtrl, cr);
- return;
- }
- /* handle packet received */
- if (isr & ISR_PRX)
- if (pDrvCtrl->rxHandling == FALSE)
- {
- pDrvCtrl->rxHandling = TRUE;
- /* disable receive interrupts and defer work to task context */
- NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_RX_DISABLE, CR_RPAGE0);
- netJobAdd ((FUNCPTR) ns83902HandleInt, (int) pDrvCtrl, 0, 0, 0, 0);
- }
- }
- /*******************************************************************************
- *
- * ns83902Send - the driver's actual output routine
- *
- * This routine accepts outgoing packets from the snd queue, and then
- * gains exclusive access to the DMA (through a mutex semaphore),
- * then calls ns83902Transmit() to send the packet out onto the interface.
- *
- * RETURNS: OK, or ERROR if the packet could not be transmitted.
- */
- LOCAL STATUS ns83902Send
- (
- NS83902_END_DEVICE* pDrvCtrl,
- M_BLK* pMblk
- )
- {
- int status;
- DRV_LOG (NS83902_DEBUG_TX, "Begin ns83902Send pDrvCtrl %p pMblk %pn",
- (int)pDrvCtrl, (int)pMblk, 3, 4, 5, 6);
- if ((END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) !=
- (IFF_UP | IFF_RUNNING))
- {
- DRV_LOG (NS83902_DEBUG_TX, "Device is NOT UP and RUNNINGn",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- /* send packet out over interface */
- if ((status = ns83902Transmit (pDrvCtrl, pMblk)) == OK)
- {
- /* Success, free the Mblk chain */
- if (!NS83902_IS_IN_POLL_MODE())
- netMblkClChainFree (pMblk);
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
- }
- else
- {
- DRV_LOG (NS83902_DEBUG_TX, "FAILED ns83902Transmitn", 0, 0, 0, 0, 0, 0);
- /* update statistics */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
- #ifdef NS83902_INSTRUMENT
- ns83902TxError++;
- #endif
- }
- DRV_LOG (NS83902_DEBUG_TX, "End ns83902Send n", 0, 0, 0, 0, 0, 0);
- #ifdef NS83902_INSTRUMENT
- ns83902TxNb++;
- #endif
- return status;
- }
- /*******************************************************************************
- *
- * ns83902Transmit - send data over the NIC network interface
- *
- * This routine transfers data to the NIC device via the remote DMA, and
- * then signal for a transmission.
- *
- * RETURNS: OK, or ERROR if the transmitter signalled an error.
- */
- LOCAL STATUS ns83902Transmit
- (
- NS83902_END_DEVICE* pDrvCtrl,
- M_BLK* pMblk
- )
- {
- int status = OK;
- int txLen = 0;
- UINT8 cr;
- LOCAL UINT8 txData[ETHERMTU + ENET_HDR_REAL_SIZ];
- int cnt;
- USHORT dummyRead;
- /* Get exclusive access to DMA */
- if (!NS83902_IS_IN_POLL_MODE())
- NS83902_SEM_TAKE (pDrvCtrl, WAIT_FOREVER);
- txLen = netMblkToBufCopy (pMblk, txData, NULL);
- txLen = max (txLen, ETHERSMALL);
- /* Check if we are ready to transmit */
- NS83902_CR_GET (pDrvCtrl, cr);
- if (cr & CR_TXP)
- {
- DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit: waiting for TX_IN_PROGRESSn",
- 1, 2, 3, 4, 5, 6);
- /* Wait for end of TX */
- cnt = 100; /* timeout 100 mSec */
- while ((cr & CR_TXP) && (cnt-- > 0))
- {
- SYS_MS_DELAY (1);
- NS83902_CR_GET (pDrvCtrl, cr);
- }
- }
- /* If still not ready, bail */
- NS83902_CR_GET (pDrvCtrl, cr);
- if (cr & CR_TXP)
- {
- DRV_LOG (NS83902_DEBUG_TX, "Not Ready to transmit!n", 1, 2, 3, 4, 5, 6);
- pDrvCtrl->txBlocked = TRUE; /* transmitter not ready */
- if (!NS83902_IS_IN_POLL_MODE())
- NS83902_SEM_GIVE (pDrvCtrl);
- return (END_ERR_BLOCK);
- }
- /* Dummy read with RBCR > 1 before (see DP83902 manual) */
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 2, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, 0, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, LSB(pDrvCtrl->txStartPage),
- CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RREAD, CR_RPAGE0);
- if (pDrvCtrl->wide == TRUE)
- {
- SYS_IN_SHORT (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);
- }
- else
- {
- SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);
- SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);
- }
- /* Set up remote DMA transfer */
- NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, 0, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, LSB(pDrvCtrl->txStartPage),
- CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, LSB(txLen), CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, MSB(txLen), CR_RPAGE0);
- /* Start remote DMA transfer */
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RWRITE, CR_RPAGE0);
- /* write data to the DMA port */
- ns83902WritePort (pDrvCtrl, txData, txLen);
- /* Se up local DMA */
- NS83902_REG_SET (pDrvCtrl, NS83902_TPSR, pDrvCtrl->txStartPage, CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_TBCR0, LSB(txLen), CR_RPAGE0);
- NS83902_REG_SET (pDrvCtrl, NS83902_TBCR1, MSB(txLen), CR_RPAGE0);
- DRV_LOG (NS83902_DEBUG_TX, "Sending %d bytes from %p n", txLen,
- (int)txData, 3, 4, 5, 6);
- /* Start transmission while preserving DMA command bits */
- NS83902_CR_GET (pDrvCtrl, cr);
- NS83902_REG_SET (pDrvCtrl, NS83902_CR,
- CR_TXP | (cr & (CR_RWRITE | CR_RREAD | CR_ABORT)),
- CR_RPAGE0);
- /* Release Semaphore */
- if (!NS83902_IS_IN_POLL_MODE())
- {
- NS83902_SEM_GIVE (pDrvCtrl);
- }
- else
- {
- UINT8 tsr;
- UINT8 isr;
- FOREVER
- {
- NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);
- if ((isr & (ISR_PTX | ISR_TXE)) != 0)
- break;
- }
- /* Check for errors */
- NS83902_REG_GET (pDrvCtrl, NS83902_TSR, tsr, CR_RPAGE0);
- if ((tsr & TSR_PTX) == 0)
- {
- /* PTX zero, something went wrong */
- status = ERROR;
- if (tsr & TSR_ABT)
- {
- #ifdef NS83902_INSTRUMENT
- ns83902TxTimeout++;
- #endif
- DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Aborted n",
- 1, 2, 3, 4, 5, 6);
- }
- if (tsr & TSR_FU)
- {
- DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit FIFO Underrun n",
- 1, 2, 3, 4, 5, 6);
- }
- }
- if (tsr & TSR_CRS)
- {
- logMsg ("%s%d - no carriern", (int)NS83902_DEV_NAME, pDrvCtrl->unit,
- 3, 4, 5, 6);
- }
- #if 0 /* no collision statistics for END drivers? */
- if (tsr & TSR_COL)
- {
- UINT8 ncr;
- NS83902_REG_GET (pDrvCtrl, NS83902_NCR, ncr, CR_RPAGE0);
- END_ERR_ADD (pEndObj, MIB2_COLLISIONS, ncr);
- }
- #endif
- /* Clear transmit flags in ISR */
- NS83902_REG_SET (pDrvCtrl, NS83902_ISR, (ISR_PTX | ISR_TXE), CR_RPAGE0);
- }
- return (status);
- }
- /*******************************************************************************
- *
- * ns83902Ioctl - the driver's I/O control routine
- *
- * Perform device-specific commands.
- *
- * RETURNS: 0, or EINVAL if the command 'cmd' is not supported.
- */
- LOCAL int ns83902Ioctl
- (
- NS83902_END_DEVICE* pDrvCtrl,
- int cmd,
- caddr_t data
- )
- {
- int error = 0;
- long value;
- int saveFlags;
- DRV_LOG (NS83902_DEBUG_LOAD, "ns83902Ioctl Command %dn",
- cmd, 2, 3, 4, 5, 6);
- switch ((UINT)cmd)
- {
- case EIOCSADDR:
- if (data == NULL)
- return (EINVAL);
- bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),
- END_HADDR_LEN(&pDrvCtrl->endObj));
- ns83902Config (pDrvCtrl); /* HELP Will it work? */
- break;
- case EIOCGADDR:
- if (data == NULL)
- return (EINVAL);
- bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data,
- END_HADDR_LEN(&pDrvCtrl->endObj));
- break;
- case EIOCSFLAGS:
- value = (long) data;
- if( value < 0 )
- {
- value = -value;
- value--;
- END_FLAGS_CLR (&pDrvCtrl->endObj, value);
- }
- else
- {
- END_FLAGS_SET (&pDrvCtrl->endObj, value);
- }
- saveFlags = DRV_FLAGS_GET();
- if (DRV_FLAGS_GET() != saveFlags &&
- (END_FLAGS_GET(&pDrvCtrl->endObj) & IFF_UP))
- {
- END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING);
- ns83902Config( pDrvCtrl );
- }
- break;
- case EIOCGFLAGS:
- if (data == NULL)
- error = EINVAL;
- else
- *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj);
- break;
- case EIOCMULTIADD: /* move to mux */
- error = ns83902MCastAddrAdd (pDrvCtrl, (char *)data);
- break;
- case EIOCMULTIDEL: /* move to mux */
- error = ns83902MCastAddrDel (pDrvCtrl, (char *)data);
- break;
- case EIOCMULTIGET: /* move to mux */
- error = ns83902MCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data);
- break;
- case EIOCPOLLSTART: /* move to mux */
- error = ns83902PollStart (pDrvCtrl);
- break;
- case EIOCPOLLSTOP: /* move to mux */
- error = ns83902PollStop (pDrvCtrl);
- break;
- case EIOCGMIB2:
- if (data == NULL)
- return (EINVAL);
- bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
- sizeof(pDrvCtrl->endObj.mib2Tbl));
- break;
- default:
- error = EINVAL;
- }
- return (error);
- }
- /*******************************************************************************
- *
- * ns83902Stop - 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 ns83902Stop
- (
- NS83902_END_DEVICE* pDrvCtrl
- )
- {
- STATUS result = OK;
- END_FLAGS_CLR (&pDrvCtrl->endObj,IFF_UP | IFF_RUNNING );
- /* Stop the device. */
- NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0);
- /* disable all interrupts */
- NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);
- /* Disable LAN interrupts */
- SYS_INT_DISABLE (pDrvCtrl);
- /* disconnect interrupt */
- SYS_INT_DISCONNECT (pDrvCtrl, ns83902Int, (int)pDrvCtrl, &result);
- if (result == ERROR)
- {
- DRV_LOG (NS83902_DEBUG_TMP, "Could not diconnect interrupt!n",
- 1, 2, 3, 4, 5, 6);
- }
- return (result);
- }
- /******************************************************************************
- *
- * ns83902Unload - 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.
- */
- LOCAL STATUS ns83902Unload
- (
- NS83902_END_DEVICE* pDrvCtrl
- )
- {
- if (pDrvCtrl != NULL)
- {
- END_OBJECT_UNLOAD (&pDrvCtrl->endObj);
- /* free resources */
- if (pDrvCtrl->pCluster != NULL)
- free (pDrvCtrl->pCluster);
- }
- return (OK);
- }
- /*******************************************************************************
- *
- * ns83902MCastAddrAdd - add a multicast address
- *
- *
- * RETURNS: OK on success, ERROR otherwise.
- */
- LOCAL STATUS ns83902MCastAddrAdd
- (
- NS83902_END_DEVICE* pDrvCtrl,
- char * pAddr
- )
- {
- int retVal;
- DRV_LOG (NS83902_DEBUG_IOCTL, "MCastAddrAddn", 0, 0, 0, 0, 0, 0);
- retVal = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddr);
- if (retVal == ENETRESET)
- return ns83902AddrFilterSet (pDrvCtrl, pAddr, TRUE);
- return ((retVal == OK) ? OK : ERROR);
- }
- /*******************************************************************************
- *
- * ns83902MCastAddrDel - remove a multicast address
- *
- *
- * RETURNS: OK on success, ERROR otherwise.
- */
- LOCAL STATUS ns83902MCastAddrDel
- (
- NS83902_END_DEVICE* pDrvCtrl,
- char * pAddr
- )
- {
- int retVal;
- DRV_LOG (NS83902_DEBUG_IOCTL, "MCastAddrDeln", 0, 0, 0, 0, 0, 0);
- retVal = etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr);
- if (retVal == ENETRESET)
- return ns83902AddrFilterSet (pDrvCtrl, pAddr, FALSE);
- return ((retVal == OK) ? OK : ERROR);
- }
- /*******************************************************************************
- *
- * ns83902MCastAddrGet - retreive current multicast address list
- *
- *
- * RETURNS: OK on success; otherwise ERROR.
- */
- LOCAL STATUS ns83902MCastAddrGet
- (
- NS83902_END_DEVICE* pDrvCtrl,
- MULTI_TABLE * pTable
- )
- {
- DRV_LOG (NS83902_DEBUG_IOCTL, "MCastAddrGetn", 0, 0, 0, 0, 0, 0);
- return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable));
- }
- /*******************************************************************************
- *
- * ns83902PollStart - starting polling mode
- *
- * RETURNS: OK, always.
- */
- LOCAL STATUS ns83902PollStart
- (
- NS83902_END_DEVICE* pDrvCtrl
- )
- {
- int intLevel;
- DRV_LOG (NS83902_DEBUG_POLL, "S ", 0, 0, 0, 0, 0, 0);
- intLevel = intLock();
- /* disable all interrupts */
- NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);
- DRV_FLAGS_SET (NS83902_FLAG_POLL);
- intUnlock (intLevel);
- return (OK);
- }
- /*******************************************************************************
- *
- * ns83902PollStop - stop polling mode
- *
- * RETURNS: OK, always.
- */
- LOCAL STATUS ns83902PollStop
- (
- NS83902_END_DEVICE* pDrvCtrl
- )
- {
- int intLevel;
- intLevel = intLock();
- /* enable interrupts */
- NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_ENABLE, CR_RPAGE0);
- DRV_FLAGS_CLR(NS83902_FLAG_POLL);
- DRV_LOG (NS83902_DEBUG_POLL, "s", 0, 0, 0, 0, 0, 0);
- intUnlock (intLevel);
- return (OK);
- }
- /*******************************************************************************
- *
- * ns83902PollSend - send a packet in polled mode
- *
- * RETURNS: OK on success, EAGAIN on failure
- */
- LOCAL STATUS ns83902PollSend
- (
- NS83902_END_DEVICE* pDrvCtrl,
- M_BLK* pMblk
- )
- {
- return (ns83902Send (pDrvCtrl, pMblk));
- }
- /*******************************************************************************
- *
- * ns83902PollReceive - get a packet in polled mode
- *
- * RETURNS: OK on success, EAGAIN on failure.
- */
- LOCAL STATUS ns83902PollReceive
- (
- NS83902_END_DEVICE* pDrvCtrl,
- M_BLK* pMblk
- )
- {
- STATUS nRetValue = OK;
- NS83902_CLUSTER pCluster;
- int len;
- DRV_LOG (NS83902_DEBUG_POLL, "Start Poll Read!n", 1, 2, 3, 4, 5, 6);
- if ((pCluster = ns83902ReadFrame (pDrvCtrl)) == NULL)
- nRetValue = EAGAIN;
- else
- {
- NS83902_RX_FRAME* pRx = (NS83902_RX_FRAME*)pCluster;
- len = pRx->rxHdr.count;
- 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 */
- pMblk->mBlkHdr.mData += 2;
- bcopy ((char *)&pRx->enetHdr, (char *)pMblk->mBlkHdr.mData, len);
- netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx);
- }
- DRV_LOG (NS83902_DEBUG_POLL, "End Poll Read!n", 1, 2, 3, 4, 5, 6);
- return nRetValue;
- }
- /*******************************************************************************
- *
- * ns83902HashIndex - compute the hash index for an ethernet address
- *
- * RETURNS: hash index for an ethernet address.
- */
- LOCAL int ns83902HashIndex
- (
- char * eAddr
- )
- {
- UINT8 eAddrByte;
- int index; /* hash index - return value */
- int byte; /* loop - counter */
- int bit; /* loop - counter */
- UINT crc = 0xffffffff;
- UINT8 msb;
- for (byte=0; byte<6; byte++)
- {
- eAddrByte = eAddr[byte];
- for (bit=0; bit<8; bit++)
- {
- msb = crc >> 31;
- crc <<= 1;
- if (msb ^ (eAddrByte & 0x1))
- {
- crc ^= NS83902_CRC_POLY;
- crc |= 0x1;
- }
- eAddrByte >>= 1;
- }
- }
- /* Just want the 6 most significant bits. */
- index = crc >> 26 ;
- return index;
- }
- /******************************************************************************
- *
- * ns83902AddrFilterSet - 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 STATUS ns83902AddrFilterSet
- (
- NS83902_END_DEVICE* pDrvCtrl,
- char* pAddr,
- BOOL bSet
- )
- {
- UINT8 nHashIndex;
- /* get hash index for the address */
- nHashIndex = ns83902HashIndex (pAddr);
- /* Turn on the corresponding bit in the filter. */
- ns83902MARSet (pDrvCtrl, nHashIndex, bSet);
- return OK;
- }
- /*******************************************************************************
- *
- * ns83902MARSet - sets/resets the MAR for the specified hash index
- *
- * This routine sets/resets the MAR bit for the specified hash index
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL void ns83902MARSet
- (
- NS83902_END_DEVICE* pDrvCtrl,
- UINT8 index, /* hash index */
- BOOL bSet /* Set/Reset */
- )
- {
- UINT8 nRegOffset = index;
- UINT8 nBitPosition = index;
- UINT8 nBitMask = (UINT8)0x01;
- UINT8 nValue;
- /* Find register and bit position */
- nBitPosition = nBitPosition & 0x07; /* 3 LSB bits */
- nBitMask <<= nBitPosition;
- nRegOffset >>= 3; /* next 3 bits */
- /* set the bit in bit array*/
- NS83902_REG_GET (pDrvCtrl, NS83902_MAR0 + nRegOffset, nValue, CR_RPAGE1);
- DRV_LOG (NS83902_DEBUG_LOAD, "Hash Index:%d MAR Offset:%d value:%dn",
- index, nRegOffset, nValue, 4, 5, 6);
- if (bSet)
- {
- nValue |= nBitMask; /* set */
- }
- else
- {
- nBitMask = ~nBitMask; /* reset */
- nValue &= nBitMask;
- }
- NS83902_REG_SET (pDrvCtrl, NS83902_MAR0 + nRegOffset, nValue, CR_RPAGE1);
- DRV_LOG (NS83902_DEBUG_LOAD, "Hash Index:%d MAR Offset:%d value:%dn",
- index, nRegOffset, nValue, 4, 5, 6);
- }
- /*******************************************************************************
- *
- * ns83902RegRead - read the current value of a NIC register
- *
- * This routine reads the register values of a NIC register
- *
- * RETURNS: register value.
- */
- LOCAL UINT8 ns83902RegRead
- (
- NS83902_END_DEVICE* pDrvCtrl,
- int reg,
- int page
- )
- {
- UINT8 value;
- int oldLevel = intLock();
- if ((pDrvCtrl)->regPage != (page))
- {
- /* Set the register page */
- UINT8 cr;
- (pDrvCtrl)->regPage = (page);
- NS83902_CR_GET ((pDrvCtrl), cr);
- NS83902_CR_SET ((pDrvCtrl), (cr & !CR_PAGE_MASK) | (page));
- }
- SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->pNic + reg * pDrvCtrl->regInterval,value);
- SYS_NS83902_DELAY();
- intUnlock (oldLevel);
- return (value);
- }
- /*******************************************************************************
- *
- * ns83902RegSet - set a NIC register
- *
- * This routine reads and displays the register values of the NIC registers
- *
- * RETURNS: N/A.
- */
- LOCAL void ns83902RegSet
- (
- NS83902_END_DEVICE* pDrvCtrl,
- int reg,
- int value,
- int page
- )
- {
- int oldLevel = intLock();
- if (pDrvCtrl->regPage != page)
- {
- /* Set the page */
- UINT8 cr;
- pDrvCtrl->regPage = page;
- NS83902_CR_GET (pDrvCtrl, cr);
- NS83902_CR_SET (pDrvCtrl, ((cr & !CR_PAGE_MASK) | page));
- }
- SYS_OUT_BYTE (pDrvCtrl, pDrvCtrl->pNic + reg * pDrvCtrl->regInterval, value);
- SYS_NS83902_DELAY();
- intUnlock (oldLevel);
- }
- #ifdef NS83902_DEBUG
- /*******************************************************************************
- *
- * ns83902RegShow - prints the current value of the NIC registers
- *
- * This routine reads and displays the register values of the NIC registers
- *
- * RETURNS: N/A.
- */
- void ns83902RegShow
- (
- NS83902_END_DEVICE* pDrvCtrl
- )
- {
- UINT8 value;
- NS83902_CR_GET (pDrvCtrl, value);
- printf ("CR: 0x%x n", value);
- NS83902_REG_GET (pDrvCtrl, NS83902_CLDA0, value, CR_RPAGE0);
- printf ("CLDA0: 0x%x n", value);
- NS83902_REG_GET (pDrvCtrl, NS83902_CLDA1, value, CR_RPAGE0);
- printf ("CLDA1: 0x%x n", value);
- NS83902_REG_GET (pDrvCtrl, NS83902_BNRY, value, CR_RPAGE0);
- printf ("BNRY: 0x%x n", value);
- NS83902_REG_GET (pDrvCtrl, NS83902_TSR, value, CR_RPAGE0);
- printf ("TSR: 0x%x n", value);
- NS83902_REG_GET (pDrvCtrl, NS83902_ISR, value, CR_RPAGE0);
- printf ("ISR: 0x%x n", value);
- NS83902_REG_GET (pDrvCtrl, NS83902_CRDA0, value, CR_RPAGE0);
- printf ("CRDA0: 0x%x n", value);
- NS83902_REG_GET (pDrvCtrl, NS83902_CRDA1, value, CR_RPAGE0);
- printf ("CRDA1: 0x%x n", value);
- NS83902_REG_GET (pDrvCtrl, NS83902_RSR, value, CR_RPAGE0);
- printf ("RSR: 0x%x n", value);
- }
- #endif