cs8900aEnd.c
上传用户:ske666
上传日期:2022-03-30
资源大小:371k
文件大小:53k
- /* cs8900aEnd.c - cs8900a Enhanced Network Driver (END) */
- /*
- DESCRIPTION
- TODO - Describe the chip being used completely, even if it provides more
- features than ethernet.
- TODO - Describe the device's full ethernet capabilities, even if this driver
- doesn't or can't utilize all of them. Describe the features that the driver
- does implement and any restrictions on their use.
- TODO - Describe all macros that can be used to customize this driver. All
- accesses to chip registers should be done through redefineable macros.
- In this example driver the macros cs8900a_OUT_SHORT and cs8900a_IN_SHORT
- are sample macros to read/write data to a mock device. If a device
- communicates through formatted control blocks in shared memory, the
- accesses to those control blocks should also be through redefinable
- macros.
- TODO - The following information describes the procedure an end user would
- follow to integrate this new END device into a new BSP. The procedure
- needs to be well documented.
- This driver is easily customized for a BSP by modifying global pointers
- to routines. The routine pointers are declared below. The code below
- indicates the default values for each routine as well. By modifying
- these global pointer values, the BSP can change the behaviour of the driver.
- .CS
- IMPORT STATUS (*cs8900aIntConnectRtn)(int level, FUNCTPR pFunc, int arg);
- IMPORT STATUS (*cs8900aIntDisconnectRtn)(int level, FUNCTPR pFunc, int arg);
- IMPORT STATUS (*cs8900aIntEnableRtn) (int level);
- IMPORT STATUS (*cs8900aEnetAddrGetRtn)(int unit, char *pResult);
- IMPORT STATUS (*cs8900aOutShortRtn)(UINT addr, UINT value);
- IMPORT STATUS (*cs8900aInShortRtn)(UINT addr, USHORT *pData);
-
- cs8900aIntConnectRtn = intConnect; /@ must not be NULL @/
- cs8900aIntDisconnectRtn = NULL;
- cs8900aIntEnableRtn = NULL;
- cs8900aEndAddrGetRtn = NULL;
- cs8900aOutShortRtn = NULL;
- cs8900aInShortRtn = NULL;
- .CE
- Excecpt for cs8900aIntConnectRtn and cs8900aIntEnableRtn, a NULL value
- will result in the driver taking a default action. For the int disconnect
- function the default action is to do nothing at all. For the short in and out
- routines, the default is to assume memory mapped device registers and to
- access them directly. The default ethernet address get routine
- provides an invalid ethernet address of all zeros (0:0:0:0:0:0).
- If the BSP is willing to accept these default values no action at all
- is needed. To change the default value, the BSP should create an appropriate
- routine and set the address into the global value before first use. This
- would normally be done at function sysHwInit2() time.
- For Tornado 3.0 you need to pay attention to virtual physical address
- translations which are important. Use the cache lib macros to to
- proper VIRT_TO_PHYS translation as part of generating the physical DMA
- address for the device. Avoid the use of PHYS_TO_VIRT translation as
- it can be very time consuming. If at all possible, the driver should
- cache the virtual address of each data buffer used for DMA.
- Prior to VxWorks AE 1.1, the muxLib function muxDevUnload() did a free
- of the actual END_OBJ structure that was malloc'd during the driver
- load routine. Starting with VxWorks AE 1.1, this behaviour can be
- changed. If the second argument to END_OBJ_INIT points to the END_OBJ
- then muxLib will free it during muxDevUnload. If not, then muxDevUnload
- will not free the allocated space. Under this situation, it is assumed
- that the driver unload routine has free'd the space itself. This preserves
- backward compatibility with older drivers that always specified the second
- argument to END_OBJ_INIT() as a pointer to the END_OBJ structure. This
- cs8900a has been changed to use the new behaviour instead.
- INCLUDES:
- end.h endLib.h etherMultiLib.h
- SEE ALSO: muxLib, endLib
- .I "Writing and Enhanced Network Driver"
- */
- /* includes */
- #include "vxWorks.h"
- #include "stdlib.h"
- #include "cacheLib.h"
- #include "intLib.h"
- #include "end.h" /* Common END structures. */
- #include "endLib.h"
- #include "lstLib.h" /* Needed to maintain protocol list. */
- #include "iv.h"
- #include "semLib.h"
- #include "logLib.h"
- #include "netLib.h"
- #include "stdio.h"
- #include "sysLib.h"
- #include "errno.h"
- #include "errnoLib.h"
- #include "memLib.h"
- #include "iosLib.h"
- #undef ETHER_MAP_IP_MULTICAST
- #include "etherMultiLib.h" /* multicast stuff. */
- #include "net/mbuf.h"
- #include "net/unixLib.h"
- #include "net/protosw.h"
- #include "net/systm.h"
- #include "net/if_subr.h"
- #include "net/route.h"
- #include "netinet/if_ether.h"
- #include "sys/socket.h"
- #include "sys/ioctl.h"
- #include "sys/times.h"
- #include "string.h"
- /* addition. */
- #include "cs8900a.h"
- #include "s3c2410x.h"
- /* Maximum number of CS8900 chips */
- #define MAXUNITS 1
- /* read one byte from I/O space */
- #ifndef CS_IN_BYTE
- #define CS_IN_BYTE(reg,pAddr) (*(pAddr) = *((volatile UCHAR*)(reg)))
- #endif /*CS_IN_BYTE*/
- /* read a short (16bits) from I/O */
- #ifndef CS_IN_WORD
- #define CS_IN_WORD(reg,pAddr) (*((volatile USHORT*)(pAddr))) = *((volatile USHORT*)(reg)))
- #endif /*CS_IN_WORD*/
- /* write a short to I/O space */
- #ifndef CS_OUT_WORD
- #define CS_OUT_WORD(reg,data) (*((volatile USHORT*)(reg)) = data)
- #endif /*CS_OUT_WORD*/
- /* enable interrupt level */
- #ifndef CS_INT_ENABLE
- #define CS_INT_ENABLE(level,pResult) (*pResult = intEnable(level))
- #endif /*CS_INT_ENABLE*/
- /* connect routine to intr. vector */
- #ifndef CS_INT_CONNECT
- #define CS_INT_CONNECT(ivec,rtn,arg,pResult) (*pResult = intConnect(ivec,rtn,arg))
- #endif /*CS_INT_CONNECT*/
- IMPORT int endMultiLstCnt (END_OBJ* pEnd);
- /* defines */
- #define DRV_NAME "cs"
- #define DRV_NAME_LEN (sizeof(DRV_NAME) + 1)
- #define DRV_DESC "Cirrus Logic CS8900A END driver"
- #define DRV_DESC_LEN (sizeof(DRV_DESC) + 1)
- #define TASK_CS_INT_PRI (54)
- /* Configuration items */
- #ifndef ETHERMTU
- #define ETHERMTU (1500)
- #endif
- #define END_BUFSIZ (ETHERMTU + SIZEOF_ETHERHEADER + 6)
- #define EH_SIZE (14)
- #define END_SPEED_10M 10000000 /* 10Mbs */
- #define END_SPEED_100M 100000000 /* 100Mbs */
- #define END_SPEED END_SPEED_10M
- /*
- * Default macro definitions for BSP interface.
- * These macros can be redefined in a wrapper file, to generate
- * a new module with an optimized interface.
- */
- /* A shortcut for getting the hardware address from the MIB II stuff. */
- #define END_HADDR(pEnd) ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
- #define END_HADDR_LEN(pEnd) ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
- /* typedefs */
- /* mac address mask */
- typedef struct struct_mac_address
- {
- USHORT i_g : 1;
- USHORT u_l : 1;
- USHORT val15_2 : 14;
- UINT val47_16;
- }STRUCT_MAC_ADDRESS;
- /* The definition of the driver control structure */
- typedef struct end_device{
- END_OBJ end; /* The class we inherit from. */
- int unit; /* unit number */
- int ivec; /* interrupt vector */
- int ilevel; /* interrupt level */
- char* pShMem; /* real ptr to shared memory */
- long flags; /* Our local flags. */
- USHORT enetAddr[3]; /* ethernet address */
- CACHE_FUNCS* pCacheFuncs; /* cache function pointers */
- FUNCPTR freeRtn[128]; /* Array of free routines. */
- /* struct free_args freeData[128]; Array of free arguments */
- /* the free routines. */
- CL_POOL_ID pClPoolId; /* cluster pool */
- BOOL rxHandling; /* rcv task is scheduled */
- /* chip */
- USHORT io_addr; /* The io base of the cs8900a. */
- UINT mem_addr; /* The mem base of the cs8900a. */
- USHORT chip_int_num; /* The cs8900a intrX(0..3) */
- USHORT chip_dma_num; /* The cs8900a dmaX(0..2) */
- UINT media_type; /* The media type in software. */
- BOOL in_memory_mode; /* The flag of mode.(io(false) or memory(true)) */
- BOOL resetting;
- UINT rx_depth;
- UINT max_rx_depth;
- UINT max_tx_depth;
- UINT loan_count;
- STRUCT_MAC_ADDRESS * p_mac_adr;
- }END_DEVICE;
- typedef struct self_pkg_buf
- {
- char * p_char;
- int len;
- }self_pkg_buf, * p_self_pkg_buf;
- /*
- * This will only work if there is only a single unit, for multiple
- * unit device drivers these should be integrated into the END_DEVICE
- * structure.
- */
- /* -------------------------------- no. mBlks no. clBlks memArea memSize */
- /* network mbuf configuration table --------- ---------- ------- ------- */
- M_CL_CONFIG cs8900aMclBlkConfig = { 0, 0, NULL, 0};
- /* ---------------------------------------- clusterSize num memArea memSize */
- /* network cluster pool configuration table ----------- --- ------- --------- */
- CL_DESC cs8900aClDescTbl [] = {{ 0, 0, NULL, 0 }};
- int cs8900aClDescTblNumEnt = (NELEMENTS(cs8900aClDescTbl));
- /* Definitions for the flags field */
- #define cs8900a_PROMISCUOUS 0x1
- #define cs8900a_POLLING 0x2
- #define cs8900a_MIN_FBUF (1536) /* min first buffer size */
- /* DEBUG MACROS */
- #ifdef DEBUG
- #define LOGMSG(x,a,b,c,d,e,f) if(endDebug){logMsg(x,a,b,c,d,e,f);}
- #else
- #define LOGMSG(x,a,b,c,d,e,f)
- #endif /* ENDDEBUG */
- #undef DRV_DEBUG
- #ifdef DRV_DEBUG
- #define DRV_DEBUG_OFF 0x0000
- #define DRV_DEBUG_RX 0x0001
- #define DRV_DEBUG_TX 0x0002
- #define DRV_DEBUG_INT 0x0004
- #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
- #define DRV_DEBUG_POLL_RX 0x0008
- #define DRV_DEBUG_POLL_TX 0x0010
- #define DRV_DEBUG_LOAD 0x0020
- #define DRV_DEBUG_IOCTL 0x0040
- #define DRV_DEBUG_POLL_REDIR 0x10000
- #define DRV_DEBUG_LOG_NVRAM 0x20000
- int cs8900aDebug = 0x00;
- int cs8900aTxInts = 0;
- #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) if(cs8900aDebug & FLG)logMsg(X0, X1, X2, X3, X4, X5, X6);
- #define DRV_PRINT(FLG,X) if(cs8900aDebug & 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*/
- /* LOCALS */
- /* forward static functions */
- LOCAL void cs8900aReset(END_DEVICE *pDrvCtrl);
- LOCAL void cs8900aRecv(END_DEVICE * pDrvCtrl, char * pNewCluster, int len);
- LOCAL void cs8900aConfig(END_DEVICE *pDrvCtrl);
- /* END Specific interfaces. */
- /* This is the only externally visible interface. */
- END_OBJ* cs8900aLoad(char* initString, void* p_v);
- LOCAL STATUS cs8900aStart(END_DEVICE* pDrvCtrl);
- LOCAL STATUS cs8900aStop(END_DEVICE* pDrvCtrl);
- LOCAL int cs8900aIoctl(END_DEVICE* pDrvCtrl, int cmd, caddr_t data);
- LOCAL STATUS cs8900aUnload(END_DEVICE* pDrvCtrl);
- LOCAL STATUS cs8900aSend(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
- LOCAL void cs8900aInt(END_DEVICE* pDrvCtrl);
- LOCAL STATUS cs8900aMCastAdd(END_DEVICE* pDrvCtrl, char* pAddress);
- LOCAL STATUS cs8900aMCastDel(END_DEVICE* pDrvCtrl, char* pAddress);
- LOCAL STATUS cs8900aMCastGet(END_DEVICE* pDrvCtrl, MULTI_TABLE* pTable);
- LOCAL STATUS cs8900aPollStart(END_DEVICE* pDrvCtrl);
- LOCAL STATUS cs8900aPollStop(END_DEVICE* pDrvCtrl);
- LOCAL STATUS cs8900aPollSend(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
- LOCAL STATUS cs8900aPollRcv(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);
- LOCAL void cs8900aAddrFilterSet(END_DEVICE *pDrvCtrl);
- LOCAL STATUS cs8900aMemInit();
- void cs_pp_w(END_DEVICE* pDrvCtrl, USHORT offset, USHORT value);
- USHORT cs_pp_r(END_DEVICE* pDrvCtrl, USHORT offset);
- void cs_chip_generate_interrupt(END_DEVICE * pDrvCtrl);
- int cs_chip_get_rx_miss_num(END_DEVICE * pDrvCtrl);
- int cs_chip_get_tx_col_num(END_DEVICE * pDrvCtrl);
- STATUS cs_chip_int_disable(END_DEVICE * pDrvCtrl);
- STATUS cs_chip_int_enable(END_DEVICE * pDrvCtrl);
- STATUS cs_chip_loop_set(END_DEVICE * pDrvCtrl, int val);
- void cs_chip_rx_frame_drop(END_DEVICE * pDrvCtrl, int num);
- STATUS cs_chip_select_rx_frame_type(END_DEVICE * pDrvCtrl, USHORT type_mask, int val);
- STATUS cs_chip_self_reset(END_DEVICE * pDrvCtrl);
- STATUS cs_chip_set_full_duplex(END_DEVICE * pDrvCtrl, int val);
- STATUS cs_chip_set_link_dep(END_DEVICE * pDrvCtrl, int val);
- STATUS cs_chip_set_tx_crc(END_DEVICE * pDrvCtrl, int val);
- STATUS cs_chip_to_mem_mode(END_DEVICE * pDrvCtrl, int flag);
- STATUS cs_chip_tx_force_terminate(END_DEVICE * pDrvCtrl, int val);
- STATUS cs_chip_send_frame(END_DEVICE * pDrvCtrl, USHORT * p_src_buf, int length);
- STATUS cs_soft_end_init(END_DEVICE * pDrvCtrl);
- int cs8900a_pin_enable(void);
- int cs8900a_pin_disable(void);
- STATUS cs_chip_event_enable(END_DEVICE * pDrvCtrl);
- STATUS mask32_change_bsp(int* dist32, int num, int len, int src);
- /*
- * Declare our function table. This is static across all device
- * instances.
- */
- STATUS endEtherPacketDataGet1(void *g,void *h)
- {
- printf("wowowowon");
- }
- LOCAL NET_FUNCS cs8900aFuncTable =
- {
- (FUNCPTR) cs8900aStart, /* Function to start the device. */
- (FUNCPTR) cs8900aStop, /* Function to stop the device. */
- (FUNCPTR) cs8900aUnload, /* Unloading function for the driver. */
- (FUNCPTR) cs8900aIoctl, /* Ioctl function for the driver. */
- (FUNCPTR) cs8900aSend, /* Send function for the driver. */
- (FUNCPTR) cs8900aMCastAdd, /* Multicast add function for the driver. */
- (FUNCPTR) cs8900aMCastDel, /* Multicast delete function for the driver. */
- (FUNCPTR) cs8900aMCastGet, /* Multicast retrieve function for the driver. */
- (FUNCPTR) cs8900aPollSend, /* Polling send function */
- (FUNCPTR) cs8900aPollRcv, /* Polling receive function */
- endEtherAddressForm, /* put address info into a NET_BUFFER */
- endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
- endEtherPacketAddrGet /* Get packet addresses. */
- };
- END_DEVICE * p_end_device;
- int display_net_event = 0;
- /*
- * cs8900aLoad - 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 the initString.
- *
- * The string contains the target specific parameters like this:
- *
- * "register addr:int vector:int level:shmem addr:shmem size:shmem width"
- *
- * 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 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 empty.
- */
-
- /*typedef struct BOOT_PARAMS */
-
- /*{*/
-
- /*char bootDev [BOOT_DEV_LEN]; boot device code */
-
- /*char hostName [BOOT_HOST_LEN]; name of host */
-
- /*char targetName [BOOT_HOST_LEN]; name of target */
-
- /*char ead [BOOT_ADDR_LEN]; ethernet internet addr */
-
- /*char bad [BOOT_ADDR_LEN]; backplane internet addr */
-
- /*char had [BOOT_ADDR_LEN]; host internet addr */
-
- /*char gad [BOOT_ADDR_LEN]; gateway internet addr */
-
- /*char bootFile [BOOT_FILE_LEN]; name of boot file */
-
- /*char startupScript [BOOT_FILE_LEN]; name of startup script file */
-
- /*char usr [BOOT_USR_LEN]; user name */
-
- /*char passwd [BOOT_PASSWORD_LEN]; password */
-
- /*char other [BOOT_OTHER_LEN]; available for applications */
-
- /*int procNum; processor number */
-
- /*int unitNum; network device unit number */
-
- /*int flags; configuration flags */
-
- /*} BOOT_PARAMS;*/
-
- END_OBJ* cs8900aLoad
- (
- char* initString, /* String to be parsed by the driver. */
- void* p_v
- )
- {
- END_DEVICE *pDrvCtrl;
- DRV_LOG(DRV_DEBUG_LOAD, "Loading cs8900a...n", 1, 2, 3, 4, 5, 6);
- if(initString == NULL)
- {
- DRV_LOG(DRV_DEBUG_LOAD, "cs8900aLoad: NULL initStrrn",0,0,0,0,0,0);
- return NULL;
- }
-
- if(initString[0] == EOS)
- {
- bcopy((char *)DRV_NAME, initString, DRV_NAME_LEN);
- return NULL;
- }
- /* else initString is not blank, pass two ... */
- /* allocate the device structure */
- pDrvCtrl = (END_DEVICE*)calloc(1,sizeof(END_DEVICE));
- if(pDrvCtrl == NULL) goto errorExit;
- cs_soft_end_init(pDrvCtrl);
- /*
- * initialize the END and MIB2 parts of the structure
- * The M2 element must come from m2Lib.h
- * This cs8900a is set up for a DIX type ethernet device.
- */
- if( (END_OBJ_INIT(&pDrvCtrl->end, (DEV_OBJ*)pDrvCtrl, DRV_NAME, pDrvCtrl->unit,
- &cs8900aFuncTable,DRV_DESC) == ERROR)
- ||
- (END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
- (UCHAR*)&(pDrvCtrl->enetAddr[0]), 6, ETHERMTU,END_SPEED) == ERROR))
- {
- goto errorExit;
- }
- /* Perform memory allocation/distribution */
- if(cs8900aMemInit(pDrvCtrl) == ERROR) goto errorExit;
- /* reset and reconfigure the device */
- cs8900aReset(pDrvCtrl);
- cs8900aConfig(pDrvCtrl);
- /* set the flags to indicate readiness */
- END_OBJ_READY(&pDrvCtrl->end, IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST);
- DRV_LOG(DRV_DEBUG_LOAD, "Done loading cs8900a...", 1, 2, 3, 4, 5, 6);
- p_end_device = pDrvCtrl;
- pDrvCtrl->p_mac_adr = (void *)(pDrvCtrl->enetAddr);
- return (&(pDrvCtrl->end));
- errorExit:
- if(pDrvCtrl != NULL) free((char *)pDrvCtrl);
- p_end_device = NULL;
- return NULL;
- }
- /*
- * cs8900aMemInit - initialize memory for the chip
- *
- * This routine is highly specific to the device.
- *
- * Design choices available:
- *
- * Use default system buffers, or create device specific buffer pools.
- *
- * Use contiguous buffers for device frame descriptors and the data, or
- * use descriptor buffers separate from the data buffers.
- *
- * Use the same buffering scheme for Rx and Tx, or each side uses it's
- * own buffering scheme.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS cs8900aMemInit
- (
- END_DEVICE * pDrvCtrl /* device to be initialized */
- )
- {
- /* Set up an END netPool using netBufLib(1). */
- cs8900aMclBlkConfig.mBlkNum = 128;
- cs8900aClDescTbl[0].clNum = 128;
- cs8900aClDescTbl[0].clSize = 2048;
- cs8900aMclBlkConfig.clBlkNum = cs8900aClDescTbl[0].clNum;
- /* Calculate the total memory for all the M-Blks and CL-Blks. */
- cs8900aMclBlkConfig.memSize = ((cs8900aMclBlkConfig.mBlkNum * (MSIZE + sizeof (long)))
- + (cs8900aMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long))));
- /* allocate mbuf/Cluster blocks from normal memory */
- cs8900aMclBlkConfig.memArea = (char *)memalign(sizeof(long),cs8900aMclBlkConfig.memSize);
- if(cs8900aMclBlkConfig.memArea == NULL)return ERROR;
- /* Calculate the memory size of all the clusters. */
- cs8900aClDescTbl[0].memSize = (cs8900aClDescTbl[0].clNum * (cs8900aClDescTbl[0].clSize + 8));
- /* Allocate the memory for the clusters from cache safe memory. */
- cs8900aClDescTbl[0].memArea = (char*)cacheDmaMalloc(cs8900aClDescTbl[0].memSize);
- if(cs8900aClDescTbl[0].memArea == NULL)
- {
- DRV_LOG(DRV_DEBUG_LOAD, "system memory unavailablen", 1, 2, 3, 4, 5, 6);
- return ERROR;
- }
- /* TODO - allocate and initialize any shared memory areas */
- if((pDrvCtrl->end.pNetPool = malloc(sizeof(NET_POOL))) == NULL) return ERROR;
- /* Initialize the memory pool. */
- if(netPoolInit(
- pDrvCtrl->end.pNetPool,
- &cs8900aMclBlkConfig,
- &cs8900aClDescTbl[0],
- cs8900aClDescTblNumEnt,
- NULL) == ERROR)
- {
- DRV_LOG(DRV_DEBUG_LOAD, "Could not init bufferingn", 1, 2, 3, 4, 5, 6);
- return ERROR;
- }
- DRV_LOG(DRV_DEBUG_LOAD, "Memory setup completen", 1, 2, 3, 4, 5, 6);
- return OK;
- }
- /*
- * cs8900aStart - 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 cs8900aStart
- (
- END_DEVICE* pDrvCtrl /* device ID */
- )
- {
- /* TODO - start the device, enabling interrupts */
- /* enable pins for net interrupt. */
- cs8900a_pin_enable();
- /* clear any interrupt. */
- while(cs_pp_r(pDrvCtrl, CS_PKTPG_ISQ) != 0);
- cs_chip_int_enable(pDrvCtrl);
- /* install isr. */
- if(intConnect(INUM_TO_IVEC(pDrvCtrl->ivec), cs8900aInt, (int)pDrvCtrl) == ERROR)
- {
- return ERROR;
- }
-
- DRV_LOG(DRV_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
- /* enable interrupt. */
- intEnable(pDrvCtrl->ilevel);
- DRV_LOG(DRV_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
- END_FLAGS_SET(&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
- return OK;
- }
- /*
- * cs8900aInt - handle controller interrupt
- *
- * This routine is called at interrupt level in response to an interrupt from
- * the controller.
- *
- * RETURNS: N/A.
- */
- void cs8900aInt(END_DEVICE * pDrvCtrl)
- {
- USHORT stat = 0;
- int recv_len = 0;
- volatile char * p_char = NULL;
- /*volatile unsigned int * p_src = (volatile unsigned int *)(CS_CHIP_MEM_BASE + CS_PKTPG_RX_FRAME);*/
- volatile char * p_src = (char *)(CS_CHIP_MEM_BASE + CS_PKTPG_RX_FRAME);
- volatile char temp_char1, temp_char2;
- int i;
- DRV_LOG(DRV_DEBUG_INT, "Got an interrupt!n", 1, 2, 3, 4, 5, 6);
- /*logMsg("cs8900aInt come here!!!n",0,0,0,0,0,0);*/
- while(1)
- {
- /* Read the device status register */
- stat = *((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_ISQ));
- if(stat == 0)
- {
- break;
- }
- else
- {
- ;
- }
- switch(stat & CS_REG_NUM_MASK)
- {
- case CS_REG_NUM_RX_EVENT:
- if(CS_RX_EVENT_CRC_ERR & stat)
- {
- if(display_net_event) printf("recv-data CRC error!n");
- cs_chip_rx_frame_drop(pDrvCtrl, 1);
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- break;
- }
- if(CS_RX_EVENT_RUNT & stat)
- {
- if(display_net_event) printf("error, recv-data too short!n");
- cs_chip_rx_frame_drop(pDrvCtrl, 1);
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- break;
- }
- if(CS_RX_EVENT_X_DATA & stat)
- {
- if(display_net_event) printf("error, recv-data too long!n");
- cs_chip_rx_frame_drop(pDrvCtrl, 1);
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- break;
- }
- if(CS_RX_EVENT_RX_OK & stat)
- {
- pDrvCtrl->rxHandling = TRUE;
- p_char = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->end.pNetPool->clTbl[0]);
- if(p_char != NULL)
- {
- /*recv_len = *((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_RX_LENGTH));*/
-
- recv_len = cs_pp_r(pDrvCtrl, CS_PKTPG_RX_LENGTH);
-
- logMsg("recv_len = %d n",recv_len,0,0,0,0,0);
- #if 0
-
- for(i = recv_len-2; i < recv_len;i+=2)
- {
- logMsg(" 0x%x n",*((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_RX_FRAME + i)),0,0,0,0,0);
- }
-
- logMsg("receive endn",0,0,0,0,0,0);
-
- bcopyBytes((char *)p_src, (char *)(p_char), recv_len);
- #endif
- /* The chip is ready for transmission now */
- /* Copy the frame to the chip to start transmission */
- #if 1
- for(i = 0; i < recv_len; i+=2)
- {
- *((USHORT *)p_char+(i+2)/2) = *((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_RX_FRAME + i));
- /*printf(" : 0x%x",p_src_buf[count/2]);*/
- }
-
- #endif
- //recv_len += 2;
- }
- /*netJobAdd ((FUNCPTR)cs8900aRecv, (int)pDrvCtrl, (int)p_char,recv_len,0,0);*/
- netJobAdd ((FUNCPTR)cs8900aRecv, (END_DEVICE *)pDrvCtrl, (char*)p_char,recv_len,0,0);
- }
- break;
- case CS_REG_NUM_TX_EVENT:
- if(CS_TX_EVENT_JABBER & stat);
- if(CS_TX_EVENT_LOSS_CRS & stat);
- if(CS_TX_EVENT_OUT_WIN & stat);
- if(CS_TX_EVENT_SQE_ERR & stat);
- if(CS_TX_EVENT_TX_OK & stat)
- {logMsg("TX_OK!!!n",0,0,0,0,0,0);
-
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- if(display_net_event) printf("tx_okn");
- }
- break;
- case CS_REG_NUM_BUF_EVENT:
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- break;
- case CS_REG_NUM_RX_MISS:
- if(display_net_event) printf("Warning, net-rx miss!n");
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- break;
- case CS_REG_NUM_TX_COL:
- if(display_net_event) printf("Warning, net-tx collision!n");
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- break;
- default:;
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- }
- }
- return ;
- }
- /*
- * cs8900aRecv - process the next incoming packet
- *
- * Handle one incoming packet. The packet is checked for errors.
- *
- * RETURNS: N/A.
- */
- LOCAL void cs8900aRecv
- (
- END_DEVICE * pDrvCtrl, /* device structure */
- char* pNewCluster,
- int len
- )
- {
- char * temp_buf = NULL;
- int temp_count = 0;
- M_BLK_ID pMblk;
- CL_BLK_ID pClBlk;
- int i = 0;
- pDrvCtrl->rxHandling = TRUE;
- /* TODO - Packet must be checked for errors. */
- END_ERR_ADD(&pDrvCtrl->end, MIB2_IN_UCAST, +1);
- /*
- * 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.
- */
- /* pDrvCtrl->pClPoolId); */
- /*logMsg("cs8900aRecv come here!!!n",0,0,0,0,0,0);*/
- if(pNewCluster == NULL)
- {
- DRV_LOG(DRV_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
- END_ERR_ADD(&pDrvCtrl->end, MIB2_IN_ERRS, +1);
- goto cleanRXD;
- }
- /* Grab a cluster block to marry to the cluster we received. */
- if(((pClBlk = netClBlkGet(pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
- ||(len <= 0))
- {
- netClFree(pDrvCtrl->end.pNetPool, (UCHAR *)pNewCluster);
- 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;
- }
- if((pMblk = mBlkGet(pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
- {
- netClBlkFree(pDrvCtrl->end.pNetPool, pClBlk);
- netClFree(pDrvCtrl->end.pNetPool, (UCHAR *)pNewCluster);
- 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;
- }
- /* Join the cluster to the MBlock */
- netClBlkJoin(pClBlk, pNewCluster, len, NULL, 0, 0, 0);
- netMblkClJoin(pMblk, pClBlk);
- /* TODO - Invalidate any RFD dma buffers */
- pMblk->mBlkHdr.mLen = len;
- pMblk->mBlkHdr.mFlags |= M_PKTHDR;
- pMblk->mBlkPktHdr.len = len;
- pMblk->mBlkHdr.mData += 2; //在截取出IP层数据后必须保证mData是字对齐,因为在IP层数据
- //截取后要进行数据类型的转换,而在这之前可以不要求mData
- //是字对齐,因为在MAC层数据中,不会进行数据结构类型的转换
-
- #if 0
- printf("begin n");
- printf("len = %d n",len);
- for(i=0 ; i<len ;i++)
- {
- printf(" 0x%x ",*((unsigned char*)pMblk->mBlkHdr.mData+i));
- /*printf(" 0x%x ",*(pNewCluster+i));*/
- }
- printf("n end n");
- #endif
- DRV_LOG(DRV_DEBUG_RX, "Calling upper layer!n", 1, 2, 3, 4, 5, 6);
- /* TODO - Done with processing, clean up and pass it up. */
- /* Call the upper layer's receive routine. */
- END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- cleanRXD:
- pDrvCtrl->rxHandling = FALSE;
- *((volatile unsigned int *)(0x560000A4))=(*((volatile unsigned int *)(0x560000A4)))&(~(1<<9));
- return;
- }
- /*
- * cs8900aSend - 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, ERROR, or END_ERR_BLOCK.
- */
- LOCAL STATUS cs8900aSend
- (
- END_DEVICE* pDrvCtrl, /* device ptr */
- M_BLK_ID pMblk /* data to send */
- )
- {
- static UCHAR p_src_buf[CS_CHIP_FRAME_BUF_SIZE];
- int old_level = 0;
- int length = 0;
- STATUS tx_status = ERROR;
- if(pDrvCtrl->resetting) return END_ERR_BLOCK;
- if(!(pDrvCtrl->flags & cs8900a_POLLING))
- {
- END_TX_SEM_TAKE(&pDrvCtrl->end, WAIT_FOREVER);
- }
- /* Get data from Mblk to tx buffer. */
- length = netMblkToBufCopy(pMblk, (char*)p_src_buf, NULL);
- /* lock interrupt. */
- if(!(pDrvCtrl->flags & cs8900a_POLLING))
- {
- old_level = intLock();
- }
- /* transmit it. */
- tx_status = cs_chip_send_frame(pDrvCtrl, (USHORT *)p_src_buf, length);
- /* unlock interrupt. */
- if(!(pDrvCtrl->flags & cs8900a_POLLING))
- {
- intUnlock (old_level);
- }
- if(!(pDrvCtrl->flags & cs8900a_POLLING))
- {
- END_TX_SEM_GIVE(&pDrvCtrl->end);
- }
- /* Bump the statistics counters. */
- END_ERR_ADD(&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
- if(tx_status == ERROR)
- {
- /* transmit failed. */
- return END_ERR_BLOCK;
- }
- /*
- * Cleanup. If the driver copied the data from the mblks to a different
- * buffer, then free the mblks now. Otherwise, free the mblk chain
- * after the device is finished with the TFD.
- */
- netMblkClChainFree(pMblk);
- return OK;
- }
- /*
- * cs8900aIoctl - the driver I/O control routine
- *
- * Process an ioctl request.
- *
- * RETURNS: A command specific response, usually OK or ERROR.
- */
- LOCAL int cs8900aIoctl
- (
- END_DEVICE* pDrvCtrl, /* device receiving command */
- int cmd, /* ioctl command code */
- caddr_t data /* command argument */
- )
- {
- int error = 0;
- long value;
- switch((unsigned)cmd)
- {
- case EIOCSADDR: /* set MAC address */
- if (data == NULL) return EINVAL;
- bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end), END_HADDR_LEN(&pDrvCtrl->end));
- break;
- case EIOCGADDR: /* get MAC address */
- if(data == NULL) return EINVAL;
- bcopy((char *)END_HADDR(&pDrvCtrl->end), (char *)data, END_HADDR_LEN(&pDrvCtrl->end));
- break;
- case EIOCSFLAGS: /* set (or clear) flags */
- value = (long)data;
- if(value < 0)
- {
- value = -value;
- value--;
- END_FLAGS_CLR(&pDrvCtrl->end, value);
- }
- else
- {
- END_FLAGS_SET(&pDrvCtrl->end, value);
- }
- cs8900aConfig (pDrvCtrl);
- break;
- case EIOCGFLAGS: /* get flags */
- *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
- break;
- case EIOCPOLLSTART: /* Begin polled operation */
- cs8900aPollStart(pDrvCtrl);
- break;
- case EIOCPOLLSTOP: /* End polled operation */
- cs8900aPollStop(pDrvCtrl);
- break;
- case EIOCGMIB2233:
- case EIOCGMIB2: /* return MIB information */
- if(data == NULL) return EINVAL;
- bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data, sizeof(pDrvCtrl->end.mib2Tbl));
- break;
- case EIOCGFBUF: /* return minimum First Buffer for chaining */
- if(data == NULL) return EINVAL;
- *(int *)data = cs8900a_MIN_FBUF;
- break;
- case EIOCGHDRLEN:
- if(data == NULL) return EINVAL;
- *(int *)data = EH_SIZE;
- break;
- default: /* unknown request */
- error = EINVAL;
- }
- return error;
- }
- /*
- * cs8900aConfig - reconfigure the interface under us.
- *
- * Reconfigure the interface setting promiscuous mode, and changing the
- * multicast interface list.
- *
- * RETURNS: N/A.
- */
- LOCAL void cs8900aConfig
- (
- END_DEVICE* pDrvCtrl /* device to be re-configured */
- )
- {
- /* Set promiscuous mode if it's asked for. */
- if(END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
- {
- DRV_LOG(DRV_DEBUG_IOCTL, "Setting promiscuous mode on!n", 1, 2, 3, 4, 5, 6);
- }
- else
- {
- DRV_LOG(DRV_DEBUG_IOCTL, "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)
- {
- cs8900aAddrFilterSet(pDrvCtrl);
- }
- /* TODO - initialise the hardware according to flags */
- cs_pp_w(pDrvCtrl, CS_PKTPG_IO_BASE, pDrvCtrl->io_addr); /* io base. */
- cs_pp_w(pDrvCtrl, CS_PKTPG_MEM_BASE, (USHORT)((pDrvCtrl->mem_addr)&0xFFFF)); /* memory base.*/
- cs_pp_w(pDrvCtrl, CS_PKTPG_MEM_BASE+2, (USHORT)((pDrvCtrl->mem_addr)>>16));
- cs_pp_w(pDrvCtrl, CS_PKTPG_INT_NUM, pDrvCtrl->chip_int_num); /* interrupt pin. */
- cs_pp_w(pDrvCtrl, CS_PKTPG_DMA_NUM, pDrvCtrl->chip_dma_num); /* Turn off the dma. */
- cs_chip_to_mem_mode(pDrvCtrl, 1);
- cs_chip_event_enable(pDrvCtrl);
- /* receive style. */
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_RX_CTL,
- CS_RX_CTL_RX_OK_A | CS_RX_CTL_ALL_FRAME_A | CS_RX_CTL_BCAST_A | CS_RX_CTL_IND_A);
- /* select 10baseT, and turn on rx/tx. */
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_LINE_CTL,
- CS_LINE_CTL_10BASET | CS_LINE_CTL_TX_ON | CS_LINE_CTL_RX_ON);
- /* full duplex mode. */
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TEST_CTL,
- CS_TEST_CTL_FDX | CS_TEST_CTL_DIS_LT);
- /* led. */
- cs_pp_w(pDrvCtrl, CS_PKTPG_SELF_CTL, 0);
- return;
- }
- /*
- * cs8900aAddrFilterSet - set the address filter for multicast addresses
- *
- * This routine goes through all of the multicast addresses on the list
- * of addresses (added with the endAddrAdd() routine) and sets the
- * device's filter correctly.
- *
- * RETURNS: N/A.
- */
- LOCAL void cs8900aAddrFilterSet
- (
- END_DEVICE* pDrvCtrl /* device to be updated */
- )
- {
- ETHER_MULTI* pCurr;
- pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
- while(pCurr != NULL)
- {
- /* TODO - set up the multicast list */
- pCurr = END_MULTI_LST_NEXT(pCurr);
- }
- /* TODO - update the device filter list */
- /* Address Filter Register. */
- cs_pp_w(pDrvCtrl, CS_PKTPG_IND_ADDR, pDrvCtrl->enetAddr[0]);
- cs_pp_w(pDrvCtrl, CS_PKTPG_IND_ADDR+2, pDrvCtrl->enetAddr[1]);
- cs_pp_w(pDrvCtrl, CS_PKTPG_IND_ADDR+4, pDrvCtrl->enetAddr[2]);
- }
- /*
- * cs8900aPollRcv - routine to receive a packet in polled mode.
- *
- * Polled mode operation takes place without any kernel or other OS
- * services available. Use extreme care to insure that this code does not
- * call any kernel services. Polled mode is only for WDB system mode use.
- * Kernel services, semaphores, tasks, etc, are not available during WDB
- * system mode.
- *
- * The WDB agent polls the device constantly looking for new data. Typically
- * the device has a ring of RFDs to receive incoming packets. This routine
- * examines the ring for any new data and copies it to the provided mblk.
- * The concern here is to keep the device supplied with empty buffers at all
- * time.
- *
- * RETURNS: OK upon success. EAGAIN is returned when no packet is available.
- * A return of ERROR indicates a hardware fault or no support for polled mode
- * at all.
- */
- LOCAL STATUS cs8900aPollRcv
- (
- END_DEVICE* pDrvCtrl, /* device to be polled */
- M_BLK_ID pMblk /* ptr to buffer */
- )
- {
- USHORT stat = 0;
- int len = 0;
- int i = 0;
- /* Upper layer must provide a valid buffer. */
- if((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
- {
- return EAGAIN;
- }
- /* TODO - Invalidate any inbound RFD DMA buffers */
- /* TODO - clear any status bits that may be set. */
- stat = cs_pp_r(pDrvCtrl, CS_PKTPG_ISQ);
- if(!(stat & CS_RX_EVENT_RX_OK)) return EAGAIN;
-
- /* TODO - Check packet and device for errors */
- /* Get packet and length from device buffer/descriptor */
- stat = cs_pp_r(pDrvCtrl, CS_PKTPG_RX_STATUS);
- if(stat & CS_RX_EVENT_RX_OK)
- {
- len = cs_pp_r(pDrvCtrl, CS_PKTPG_RX_LENGTH);
- /* TODO - Process device packet into net buffer */
- /* bcopy(pPacket, pMblk->m_data, len); */
-
- for(i = 0; i < (len / 2); i++)
- {
- ((USHORT *)(pMblk->m_data+2))[i] =
- cs_pp_r(pDrvCtrl, CS_PKTPG_RX_FRAME + (i * 2));
- }
-
- pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */
- pMblk->mBlkHdr.mLen = len+2; /* set the data len */
- pMblk->mBlkPktHdr.len = len+2; /* set the total len */
-
- }
- /*
- * TODO - Done with this packet, clean up device. If needed
- * setup a new RFD/buffer for incoming packets
- */
-
- return OK;
- }
- /*
- * cs8900aPollSend - routine to send a packet in polled mode.
- *
- * Polled mode operation takes place without any kernel or other OS
- * services available. Use extreme care to insure that this code does not
- * call any kernel services. Polled mode is only for WDB system mode use.
- * Kernel services, semaphores, tasks, etc, are not available during WDB
- * system mode.
- *
- * A typical implementation is to set aside a fixed buffer for polled send
- * operation. Copy the mblk data to the buffer and pass the fixed buffer
- * to the device. Performance is not a consideration for polled operations.
- *
- * An alternate implementation is a synchronous one. The routine accepts
- * user data but does not return until the data has actually been sent. If an
- * error occurs, the routine returns EAGAIN and the user will retry the request.
- *
- * If the device returns OK, then the data has been sent and the user may free
- * the associated mblk. The driver never frees the mblk in polled mode.
- * The calling routine will free the mblk upon success.
- *
- * RETURNS: OK upon success. EAGAIN if device is busy or no resources.
- * A return of ERROR indicates a hardware fault or no support for polled mode
- * at all.
- */
- LOCAL STATUS cs8900aPollSend
- (
- END_DEVICE* pDrvCtrl, /* device to be polled */
- M_BLK_ID pMblk /* packet to send */
- )
- {
- static UCHAR p_src_buf[CS_CHIP_FRAME_BUF_SIZE];
- int length = 0;
- STATUS tx_status = ERROR;
- /* reset? */
- if(pDrvCtrl->resetting)
- {
- return EAGAIN;
- }
- /* Get data from Mblk to tx buffer. */
- length = netMblkToBufCopy(pMblk, p_src_buf, NULL);
- /* transmit it. */
- tx_status = cs_chip_send_frame(pDrvCtrl, (USHORT *)p_src_buf, length);
-
- END_ERR_ADD(&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
- if(tx_status == ERROR)
- {
- return EAGAIN;
- }
- netMblkClChainFree(pMblk);
- return OK;
- }
- /*
- * cs8900aMCastAdd - 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 cs8900aMCastAdd
- (
- END_DEVICE* pDrvCtrl, /* device pointer */
- char* pAddress /* new address to add */
- )
- {
- int error;
- if((error = etherMultiAdd(&pDrvCtrl->end.multiList, pAddress)) == ENETRESET)
- {
- cs8900aConfig(pDrvCtrl);
- }
- return OK;
- }
- /*
- * cs8900aMCastDel - 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 cs8900aMCastDel
- (
- END_DEVICE* pDrvCtrl, /* device pointer */
- char* pAddress /* address to be deleted */
- )
- {
- int error;
- if((error = etherMultiDel(&pDrvCtrl->end.multiList, (char*)pAddress)) == ENETRESET)
- {
- cs8900aConfig(pDrvCtrl);
- }
- return OK;
- }
- /*
- * cs8900aMCastGet - 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 cs8900aMCastGet
- (
- END_DEVICE* pDrvCtrl, /* device pointer */
- MULTI_TABLE* pTable /* address table to be filled in */
- )
- {
- return(etherMultiGet(&pDrvCtrl->end.multiList, pTable));
- }
- /*
- * cs8900aStop - 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 cs8900aStop
- (
- END_DEVICE* pDrvCtrl /* device to be stopped */
- )
- {
- END_FLAGS_CLR(&pDrvCtrl->end, IFF_UP | IFF_RUNNING);
- /* TODO - stop/disable the device. */
- if(intDisable(pDrvCtrl->ilevel) == ERROR)
- {
- DRV_LOG(DRV_DEBUG_LOAD, "Could not disconnect interrupt!n", 1, 2, 3, 4, 5, 6);
- return ERROR;
- }
- /* disable the interrupt input pin of cs. */
- cs8900a_pin_disable();
- cs_chip_int_disable(pDrvCtrl);
- return OK;
- }
- /*
- * cs8900aUnload - 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 cs8900aUnload
- (
- END_DEVICE* pDrvCtrl /* device to be unloaded */
- )
- {
- if(pDrvCtrl == NULL) return ERROR;
-
- END_OBJECT_UNLOAD(&pDrvCtrl->end);
- /* stop it. */
- cs8900aStop(pDrvCtrl);
- /* reset it. */
- cs8900aReset(pDrvCtrl);
- /* TODO - Free any special allocated memory */
- if(pDrvCtrl->end.pNetPool)
- {
- netPoolDelete(pDrvCtrl->end.pNetPool);
- free(pDrvCtrl->end.pNetPool);
- pDrvCtrl->end.pNetPool = (NET_POOL_ID)0;
- }
- if(cs8900aClDescTbl[0].memArea)
- {
- free(cs8900aClDescTbl[0].memArea);
- cs8900aClDescTbl[0].memArea = (char *)0;
- }
- if(cs8900aMclBlkConfig.memArea)
- {
- free(cs8900aMclBlkConfig.memArea);
- cs8900aMclBlkConfig.memArea = (char *)0;
- }
- /* New: free the END_OBJ structure allocated during cs8900aLoad() */
- cfree((char *)pDrvCtrl);
- pDrvCtrl = NULL;
- return OK;
- }
- /*
- * cs8900aPollStart - start polled mode operations
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS cs8900aPollStart
- (
- END_DEVICE* pDrvCtrl /* device to be polled */
- )
- {
- int oldLevel;
- oldLevel = intLock(); /* disable ints during update */
- /* TODO - turn off interrupts */
- pDrvCtrl->flags |= cs8900a_POLLING;
- intUnlock(oldLevel); /* now cs8900aInt won't get confused */
- DRV_LOG(DRV_DEBUG_POLL, "STARTEDn", 1, 2, 3, 4, 5, 6);
- cs8900aConfig(pDrvCtrl); /* reconfigure device */
- cs_chip_int_disable(pDrvCtrl);
- return OK;
- }
- /*
- * cs8900aPollStop - 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 cs8900aPollStop
- (
- END_DEVICE* pDrvCtrl /* device to be polled */
- )
- {
- int oldLevel;
- oldLevel = intLock(); /* disable ints during register updates */
- /* TODO - re-enable interrupts */
- pDrvCtrl->flags &= ~cs8900a_POLLING;
- intUnlock(oldLevel);
- cs8900aConfig(pDrvCtrl);
- DRV_LOG(DRV_DEBUG_POLL, "STOPPEDn", 1, 2, 3, 4, 5, 6);
- return OK;
- }
- /*
- * cs8900aReset - reset device
- *
- * RETURNS: N/A.
- */
- LOCAL void cs8900aReset
- (
- END_DEVICE* pDrvCtrl
- )
- {
- int intState;
- if(pDrvCtrl->unit != 0) return;
- pDrvCtrl->resetting = TRUE;
- /* chip reset. */
- intState = intLock();
-
- cs_chip_self_reset(pDrvCtrl);
- intUnlock(intState);
-
- /* TODO - reset all device counters/pointers, etc. */
- cs_soft_end_init(pDrvCtrl);
- pDrvCtrl->resetting = FALSE;
- return;
- }
- /* Addition. */
- /*
- * cs8900a_pin_enable - Enable the pin for the interrupt of cs8900a.
- *
- * RETURNS: status(int).
- */
- int cs8900a_pin_enable(void)/*GPGCON EINT9*/
- {
- mask32_change_bsp(
- (int*)0x56000060, /* GPGCON of s3c2410x */
- (int)2, /* start bit0 */
- (int)2, /* change length 2, bit0..1 */
- (int)2 /* Value is 2 for EINT0. */
- );
- mask32_change_bsp(
- (int*)0x5600008C, /* EXTINT0 of s3c2410x */
- (int)4, /* start bit0 */
- (int)3, /* change length 3, bit0..2 */
- (int)4 /* Value is 4, that rise edge triggered for EINT0. */
- /* (int)1 Value is 1, that high level triggered for EINT0. */
- );
- mask32_change_bsp(
- (int*)0x56000068, /* GPFUP of s3c2410x */
- (int)1, /* start bit0 */
- (int)1, /* change length 1, bit0 */
- (int)1 /* Value is 1 for disable EINT0's pull-up. */
- );
- mask32_change_bsp(
- (int*)0x560000A4, /* GPFUP of s3c2410x */
- (int)9, /* start bit0 */
- (int)1, /* change length 1, bit0 */
- (int)0 /* Value is 1 for disable EINT0's pull-up. */
- );
- mask32_change_bsp(
- (int*)0x560000A8, /* GPFUP of s3c2410x */
- (int)9, /* start bit0 */
- (int)1, /* change length 1, bit0 */
- (int)1 /* Value is 1 for disable EINT0's pull-up. */
- );
- #if 0
- mask32_change_bsp(
- (int*)0x4A000008, /* GPFUP of s3c2410x */
- (int)5, /* start bit0 */
- (int)1, /* change length 1, bit0 */
- (int)0 /* Value is 1 for disable EINT0's pull-up. */
- );
- mask32_change_bsp(
- (int*)0x4A000000, /* GPFUP of s3c2410x */
- (int)5, /* start bit0 */
- (int)1, /* change length 1, bit0 */
- (int)1 /* Value is 1 for disable EINT0's pull-up. */
- );
- mask32_change_bsp(
- (int*)0x4A000010, /* GPFUP of s3c2410x */
- (int)5, /* start bit0 */
- (int)1, /* change length 1, bit0 */
- (int)1 /* Value is 1 for disable EINT0's pull-up. */
- );
- #endif
-
- return 0;
- }
- /*
- * cs8900a_pin_disable - Disable the pin for the interrupt of cs8900a.
- *
- * RETURNS: status(int).
- */
- int cs8900a_pin_disable(void)
- {
- mask32_change_bsp(
- (int*)0x56000060, /* GPFCON of s3c2410x */
- (int)2, /* start bit0 */
- (int)2, /* change length 2, bit0..1 */
- (int)0 /* Value is 0 for input. */
- );
- mask32_change_bsp(
- (int*)0x5600008c, /* EXTINT0 of s3c2410x */
- (int)4, /* start bit0 */
- (int)3, /* change length 3, bit0..2 */
- (int)0 /* Value is 4, that low level triggered for EINT0. */
- );
- return 0;
- }
- /*
- * cs_pp_r - reads a word from the PacketPage
- *
- * This routine reads a word from the PacketPage at the specified offset.
- *
- * RETURNS: a word in the offset
- */
- USHORT cs_pp_r(END_DEVICE * pDrvCtrl, USHORT offset)
- {
- volatile USHORT temp_ushort = 0;
- if(pDrvCtrl->in_memory_mode == TRUE)
- {
- /* in memory mode */
- temp_ushort = *((volatile USHORT *)((pDrvCtrl->mem_addr) + CS_CHIP_MEM_BASE + offset));
- return temp_ushort;
- }
- else
- {
- /* in io mode */
- *((volatile USHORT *)((pDrvCtrl->io_addr) + CS_CHIP_IO_BASE + CS_PORT_PKTPG_PTR)) = offset;
- temp_ushort = *((volatile USHORT *)((pDrvCtrl->io_addr) + CS_CHIP_IO_BASE + CS_PORT_PKTPG_DATA));
- return temp_ushort;
- }
- }
- /*
- * cs_pp_w - writes a value to the PacketPage
- *
- * This routine writes a value to the PacketPage at the specified offset.
- *
- * RETURNS: N/A
- */
- void cs_pp_w(END_DEVICE * pDrvCtrl, USHORT offset, USHORT value)
- {
- if(pDrvCtrl->in_memory_mode == TRUE)
- {
- /* in memory mode */
- *((volatile USHORT *)((pDrvCtrl->mem_addr) + CS_CHIP_MEM_BASE + offset)) = value;
- }
- else
- {
- /* in io mode */
- *((volatile USHORT *)((pDrvCtrl->io_addr) + CS_CHIP_IO_BASE + CS_PORT_PKTPG_PTR)) = offset;
- *((volatile USHORT *)((pDrvCtrl->io_addr) + CS_CHIP_IO_BASE + CS_PORT_PKTPG_DATA)) = value;
- }
- return;
- }
- /* add by phoenix 左移位 修改位长 值 */
- STATUS mask32_change_bsp(int* dist32, int num, int len, int src)
- {
- UINT32 tempUINT32;
- tempUINT32 = *dist32;
- if(len <= 0) return ERROR;
- if((num+len) > 32) return ERROR;
- tempUINT32 = ((tempUINT32&(~(((1<<len)-1)<<num)))|((src&((1<<len)-1))<<num));
- *dist32 = tempUINT32;
- return OK;
- }
- /* cs_chip_rx_frame_drop - delete some receive frame. */
- void cs_chip_rx_frame_drop(END_DEVICE * pDrvCtrl, int num)
- {
- while(num--)
- {
- cs_pp_w(pDrvCtrl,CS_PKTPG_RX_CFG,
- ((cs_pp_r(pDrvCtrl,CS_PKTPG_RX_CFG)) | CS_RX_CFG_SKIP));
- }
- return;
- }
- /* cs_generate_interrupt - generate a software interrupt for test. */
- void cs_chip_generate_interrupt(END_DEVICE* pDrvCtrl)
- {
- cs_pp_w(pDrvCtrl,CS_PKTPG_BUF_CFG,
- ((cs_pp_r(pDrvCtrl,CS_PKTPG_BUF_CFG)) | CS_BUF_CFG_SW_INT));
- return;
- }
- /* cs_get_rx_miss_num - get the miss number of receive frames. */
- int cs_chip_get_rx_miss_num(END_DEVICE* pDrvCtrl)
- {
- int temp_int;
- temp_int = cs_pp_r(pDrvCtrl,CS_PKTPG_RX_MISS);
- temp_int = (temp_int >> 6) & 0x03ff;
- return temp_int;
- }
- /* cs_get_tx_col_num - get the collision number of transmit frames. */
- int cs_chip_get_tx_col_num(END_DEVICE* pDrvCtrl)
- {
- int temp_int;
- temp_int = cs_pp_r(pDrvCtrl,CS_PKTPG_TX_COL);
- temp_int = (temp_int >> 6) & 0x03ff;
- return temp_int;
- }
- /* cs_chip_to_mem_mode - set the cs to memory mode. */
- STATUS cs_chip_to_mem_mode(END_DEVICE* pDrvCtrl, int flag)
- {
- pDrvCtrl->in_memory_mode = FALSE;
- if(flag)
- {
- cs_pp_w(pDrvCtrl, CS_PKTPG_BUS_CTL,
- cs_pp_r(pDrvCtrl, CS_PKTPG_BUS_CTL) | CS_BUS_CTL_MEM_MODE);
- pDrvCtrl->in_memory_mode = TRUE;
- }
- else
- {
- cs_pp_w(pDrvCtrl, CS_PKTPG_BUS_CTL,
- cs_pp_r(pDrvCtrl, CS_PKTPG_BUS_CTL) & (~CS_BUS_CTL_MEM_MODE));
- pDrvCtrl->in_memory_mode = FALSE;
- }
- return OK;
- }
- /* cs_chip_self_reset - cs chip reset by software command. */
- STATUS cs_chip_self_reset(END_DEVICE* pDrvCtrl)
- {
- const int reset_time = 5;
- int wait_count = 0;
- if (cs_pp_r(pDrvCtrl,CS_PKTPG_EISA_NUM) != CS_EISA_NUM_CRYSTAL)
- {
- printf("CS_PKTPG_EISA_NUM Errorn");
- }
- if ((cs_pp_r(pDrvCtrl,CS_PKTPG_PRODUCT_ID) & 0xe0ff)!= 0x0000)
- {
- printf("Product ID Errorn");
- }
- /* do reset. */
- cs_pp_w(pDrvCtrl, CS_PKTPG_SELF_CTL,
- cs_pp_r(pDrvCtrl, CS_PKTPG_SELF_CTL) | CS_SELF_CTL_RESET);
- /* wait for reset finish. */
- while(!(cs_pp_r(pDrvCtrl, CS_PKTPG_SELF_ST) & CS_SELF_ST_INIT_DONE))
- {
- taskDelay(reset_time);
- if((wait_count++) >= CS_MAXLOOP) return ERROR;
- }
- return OK;
- }
- /* cs_chip_int_enable - interrupt enable for cs chip. */
- STATUS cs_chip_int_enable(END_DEVICE * pDrvCtrl)
- {
- /* set the master interrupt enable bit in cs chip. 0x0116 = 0x8017*/
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_BUS_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_BUS_CTL)) | CS_BUS_CTL_INT_ENBL);
- return OK;
- }
- /* cs_chip_event_enable - interrupt enable for cs chip. */
- STATUS cs_chip_event_enable(END_DEVICE * pDrvCtrl)
- {
- /* enable > data, < data, CRC_err, and Rx_OK interrupt. 0x0102 = 0x7103*/
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_RX_CFG, (cs_pp_r(pDrvCtrl, CS_PKTPG_RX_CFG)) | CS_RX_CFG_ALL_IE);
- /* enable all of the tx interrupt. 0x0106 = 0x8fc7*/
- cs_pp_w(pDrvCtrl, CS_PKTPG_TX_CFG, CS_TX_CFG_ALL_IE);
- /* enable Rx miss and Tx underrun interrupt. 0x010a = 0x070b*/
- cs_pp_w(pDrvCtrl, CS_PKTPG_BUF_CFG,
- CS_BUF_CFG_RX_MISS_IE | CS_BUF_CFG_TX_UNDR_IE | CS_BUF_CFG_RDY4TX_IE);
- return OK;
- }
- /* cs_chip_int_disable - interrupt disable for cs chip. */
- STATUS cs_chip_int_disable(END_DEVICE * pDrvCtrl)
- {
- /* clear the master interrupt enable bit in cs chip. */
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_BUS_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_BUS_CTL)) & (~CS_BUS_CTL_INT_ENBL));
- return OK;
- }
- /* cs_chip_event_disable - interrupt disable for cs chip. */
- STATUS cs_chip_event_disable(END_DEVICE * pDrvCtrl)
- {
- /* disable all of Rx interrupt. 0x0102 = ~0x7103*/
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_RX_CFG, (cs_pp_r(pDrvCtrl, CS_PKTPG_RX_CFG)) & (~CS_RX_CFG_ALL_IE));
- /* disable all of Tx interrupt. 0x0106 = 0x0007*/
- cs_pp_w(pDrvCtrl, CS_PKTPG_TX_CFG, 0);
- /* disable buffer interrupt. 0x010a = 0x0013*/
- cs_pp_w(pDrvCtrl, CS_PKTPG_BUF_CFG, 0);
- return OK;
- }
- /* cs_chip_select_rx_frame_type - select the receiver frame type. */
- STATUS cs_chip_select_rx_frame_type(END_DEVICE * pDrvCtrl,USHORT type_mask,int val)
- {
- /* clear this bit. */
- if(val == 0)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_RX_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_RX_CTL)) & (~type_mask));
- return OK;
- }
- /* set this bit. */
- if(val == 1)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_RX_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_RX_CTL)) | type_mask);
- return OK;
- }
- return ERROR;
- }
- /* cs_chip_loop_set - on or off cs chip loop. */
- STATUS cs_chip_loop_set(END_DEVICE * pDrvCtrl, int val)
- {
- if(val == 1)
- {
- cs_chip_set_full_duplex(pDrvCtrl, 1);
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TEST_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_TEST_CTL))
- | CS_TEST_CTL_ENDEC_LP | CS_TEST_CTL_FDX);
- return OK;
- }
- if(val == 0)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TEST_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_TEST_CTL)) & (~CS_TEST_CTL_ENDEC_LP));
- return OK;
- }
- return ERROR;
- }
- /* cs_chip_set_full_duplex - set cs rx/tx mode to full duplex or half duplex. */
- STATUS cs_chip_set_full_duplex(END_DEVICE * pDrvCtrl, int val)
- {
- if(val == 1)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TEST_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_TEST_CTL)) | CS_TEST_CTL_FDX);
- return OK;
- }
- if(val == 0)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TEST_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_TEST_CTL)) & (~CS_TEST_CTL_FDX));
- return OK;
- }
- return ERROR;
- }
- /* cs_chip_set_link_dep - set cs run depend on link or independ. */
- STATUS cs_chip_set_link_dep(END_DEVICE * pDrvCtrl, int val)
- {
- if(val == 1)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TEST_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_TEST_CTL)) | CS_TEST_CTL_DIS_LT);
- return OK;
- }
- if(val == 0)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TEST_CTL, (cs_pp_r(pDrvCtrl, CS_PKTPG_TEST_CTL)) & (~CS_TEST_CTL_DIS_LT));
- return OK;
- }
- return ERROR;
- }
- /* cs_chip_tx_force_terminate - force terminate tx frame for cs chip. */
- STATUS cs_chip_tx_force_terminate(END_DEVICE * pDrvCtrl,int val)
- {
- if(val == 1)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TX_CMD, (cs_pp_r(pDrvCtrl, CS_PKTPG_TX_CMD)) | CS_TX_CMD_FORCE);
- return OK;
- }
- if(val == 0)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TX_CMD, (cs_pp_r(pDrvCtrl, CS_PKTPG_TX_CMD)) & (~CS_TX_CMD_FORCE));
- return OK;
- }
- return ERROR;
- }
- /* cs_chip_set_tx_crc - on or off tx CRC. */
- STATUS cs_chip_set_tx_crc(END_DEVICE * pDrvCtrl, int val)
- {
- if(val == 0)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TX_CMD, (cs_pp_r(pDrvCtrl, CS_PKTPG_TX_CMD)) | CS_TX_CMD_NO_CRC);
- return OK;
- }
- if(val == 1)
- {
- cs_pp_w(pDrvCtrl,
- CS_PKTPG_TX_CMD, (cs_pp_r(pDrvCtrl, CS_PKTPG_TX_CMD)) & (~CS_TX_CMD_NO_CRC));
- return OK;
- }
- return ERROR;
- }
- /* cs_chip_send_frame - send one frame to cs chip. */
- STATUS cs_chip_send_frame(END_DEVICE * pDrvCtrl, USHORT * p_src_buf, int length)
- {
- USHORT bus_status = 0;
- int count = 0;
- int i;
- unsigned char * p_src_buffer = (unsigned char *)p_src_buf;
- if(length > 0)
- {
- /* Request that the transmit be started after all data has been copied */
- *((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_TX_CMD)) = CS_TX_CMD_START_ALL+0x9;
- /* TODO - initiate device transmit. */
- *((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_TX_LENGTH)) = length;
- /* Read the busStatus register which indicates success of the request */
- bus_status = *((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_BUS_ST));
- if((!(bus_status & CS_BUS_ST_TX_BID_ERR)) && (bus_status & CS_BUS_ST_RDY4TXNOW))
- {
-
- /* The chip is ready for transmission now */
- /* Copy the frame to the chip to start transmission */
- for(count = 0; count < length; count+=2)
- {
- *((USHORT *)(CS_CHIP_MEM_BASE + CS_PKTPG_TX_FRAME + count)) = p_src_buf[count/2];
- }
- /*logMsg("transimite finish!!n",0,0,0,0,0,0);*/
- return OK;
- }
- else
- {
- logMsg("the chip tx buffer unuse!!n",0,0,0,0,0,0);
- /* the chip tx buffer unuse. */
- if(display_net_event)printf("Error, the tx buffer is invalid!!!n");
- return ERROR;
- }
- }
- else
- {
- /* null frame. */
- if(display_net_event)printf("Error, the length of tx frame less 0!!!n");
- return ERROR;
- }
- }
- /* cs_soft_end_init - initialize the END_DEVICE. */
- STATUS cs_soft_end_init(END_DEVICE * pDrvCtrl)
- {
- pDrvCtrl->chip_dma_num = CS_INIT_DMA_NUM;
- pDrvCtrl->chip_int_num = CS_INIT_INT_NUM;
- pDrvCtrl->ilevel = CS_INIT_VECT;
- pDrvCtrl->ivec = CS_INIT_VECT;
- pDrvCtrl->io_addr = CS_CHIP_IO_OFFSET;
- pDrvCtrl->mem_addr = CS_CHIP_MEM_OFFSET;
- pDrvCtrl->enetAddr[2] = (USHORT)0x0F66;
- pDrvCtrl->enetAddr[1] = (USHORT)0x5544;
- pDrvCtrl->enetAddr[0] = (USHORT)0x3322;
- pDrvCtrl->media_type = CS_MEDIA_10BASET;
- pDrvCtrl->in_memory_mode = FALSE;
- pDrvCtrl->resetting = FALSE;
- return OK;
- }