⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs8900a.c

📁 在ARM微处理器的环境下实现对网卡的设置和实现网卡IP地址的改变
💻 C
字号:
/*********************************************************************************************
* File:	cs8900a.c
* Author:	Embest
* Desc:	cs8900a ethernet chip driver
* History:	
*********************************************************************************************/
#include "2410lib.h"
#include "cs8900a.h"

/*------------------------------------------------------------------------------------------*/
/*	 								macro define						 				    */
/*------------------------------------------------------------------------------------------*/
#define MEM_BASE	0x18000000	// nGCS3 -> net chip select
#define IO_BASE		0x19000300	// A24 should be '1', the cs8900a's I/O base address is 0x300
#define MAX_COUNT	0x00100000

#define io_write(addr, val)	(*(volatile unsigned short *)(addr) = val)
#define io_read(addr)		((unsigned short)*(volatile unsigned short *)(addr))

/*------------------------------------------------------------------------------------------*/
/*	 								inline functions define                                 */
/*------------------------------------------------------------------------------------------*/
#ifdef MEM_MODE
inline void reg_write(unsigned short reg, unsigned short val)
{
	io_write((MEM_BASE+reg), val);
}
inline unsigned short reg_read(unsigned short reg)
{
	return io_read(MEM_BASE+reg);
}
#else // IO_MODE
void reg_write(unsigned short reg, unsigned short val)
{
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, reg);
	io_write(IO_BASE+IO_PACKETPAGE_DATA0, val);
}
unsigned short reg_read(unsigned short reg)
{
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, reg);
	return io_read(IO_BASE+IO_PACKETPAGE_DATA0);
}
#endif // MEM_MODE 

/*------------------------------------------------------------------------------------------*/
/*	 						        global variables                                        */
/*------------------------------------------------------------------------------------------*/
unsigned char mac_addr[6] = { 0x00,0x06,0x98,0x01,0x7E,0x8F};
unsigned char net_out_data[1536];
unsigned char net_in_data[1536];
int iReceiveData;
int iSendData;

/*********************************************************************************************
* name:		CS_Probe
* func:		probe 8019AS chip
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
int CS_Probe(void)
{
	unsigned short id, sign;

#ifdef NDEBUG
	while(1){
#endif	
	sign = io_read(IO_BASE+IO_PACKETPAGE_POINTER);

	io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_Identification);
	id = io_read(IO_BASE+IO_PACKETPAGE_DATA0);
#ifdef NDEBUG
	uart_printf("\rsign=0x%x, id=0x%x",sign,id);
	if(sign == ID_SIGNATURE || id == ID_CODE)
		uart_printf(" success");
	else
		uart_printf(" fail!!!");	
	}
#endif	
	
	if(sign != ID_SIGNATURE || id != ID_CODE)
		return 0;
	return 1;
}

/*********************************************************************************************
* name:		CS_SetupMemoryBase
* func:		setup  8019AS chip memory map base address 
* para:		unsigned int base   --  base address
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void CS_SetupMemoryBase(unsigned int base)
{
	unsigned short temp;
	// set memory map base address 
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_MemoryBaseAddress);
	io_write(IO_BASE+IO_PACKETPAGE_DATA0, base & 0xffff);
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_MemoryBaseAddress+2);
	io_write(IO_BASE+IO_PACKETPAGE_DATA0, base >> 16);

	// read bus control register 
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_BusCTL);
	temp = io_read(IO_BASE+IO_PACKETPAGE_DATA0);
	// enable memory map 
	temp |= MemoryE;
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_BusCTL);
	io_write(IO_BASE+IO_PACKETPAGE_DATA0, temp);
}

/*********************************************************************************************
* name:		CS_Reset
* func:		reset  8019AS chip 
* para:		unsigned int base   --  base address
* ret:		1: reset success; 0: reset fail
* modify:
* comment:		
*********************************************************************************************/
int CS_Reset(void)
{
	int i;
	unsigned short result;

	// software reset 
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_SelfCTL);
	io_write(IO_BASE+IO_PACKETPAGE_DATA0, RESET|SelfCTL_LOW);

	// while INITD bit set 
	for(i=0; i<MAX_COUNT; i++)
	{
		io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_SelfST);
		result = io_read(IO_BASE+IO_PACKETPAGE_DATA0);
		if(result & INITD) break;
	}
	if(i >= MAX_COUNT)
		return 0;

	// while SIBUSY bit clean 
	for(i=0; i<MAX_COUNT; i++)
	{
		io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_SelfST);
		result = io_read(IO_BASE+IO_PACKETPAGE_DATA0);
		if((result & SIBUSY) == 0) break;
	}
	if(i >= MAX_COUNT)
		return 0;

	return 1;
}

/*********************************************************************************************
* name:		CS_Identification
* func:		Identification  8019AS chip 
* para:		unsigned short *rev   --  pointer to return CS's identification
* ret:		id: CS's ID
* modify:
* comment:		
*********************************************************************************************/
unsigned short CS_Identification(unsigned short *rev)
{
	unsigned int id;

	id = reg_read(REG_Identification);
	*rev = reg_read(REG_Identification+2);

	return id;
}


/*********************************************************************************************
* name:		CS_SetupMacAddr
* func:		setup  8019AS chip's MAC
* para:		unsigned char *mac   --  pointer to MAC
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void CS_SetupMacAddr(unsigned char *mac)
{
	reg_write(REG_IA, *(unsigned short *)(mac));
	reg_write(REG_IA+2, *(unsigned short *)(mac+2));
	reg_write(REG_IA+4, *(unsigned short *)(mac+4));
}


/*********************************************************************************************
* name:		CS_EnableIrq
* func:		enable  8019AS chip's interrupt
* para:		int enable   --  0 or not
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void CS_EnableIrq(int enable)
{
	unsigned short temp;

	temp = reg_read(REG_BusCTL);

	if(enable)
	{
		temp |= EnableIRQ;
		reg_write(REG_InterruptNumber, INTRQ0);
	}
	else
	{
		temp &= ~EnableIRQ;
		reg_write(REG_InterruptNumber, ALL_INTRQ_HI);

		temp = reg_read(REG_ISQ);
		temp &= LOW_BITS_MASK;
		switch(temp)
		{
		case 0x04: reg_read(REG_RxEvent); break;
		case 0x08: reg_read(REG_TxEvent); break;
		case 0x0C: reg_read(REG_BufEvent); break;
		case 0x10: reg_read(REG_RxMISS); break;
		case 0x12: reg_read(REG_TxCOL); break;
		}
	}
}

/*********************************************************************************************
* name:		CS_Configuration
* func:		configure  8019AS chip
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void CS_Configuration(void)
{
	unsigned short temp;

	// configure LineCTL 
	temp = reg_read(REG_LineCTL);
	temp &= ~(AUIonly | AutoAUI_10BT);
	temp |= (SerRxON | SerTxON | ModBackOffE);
	reg_write(REG_LineCTL, temp);

	// configure RxCTL 
	reg_write(REG_RxCTL, RxOKA | IdividualA | BroadcastA | RxCTL_LOW);

	// configure RxCFG 
	reg_write(REG_RxCFG, RxCFG_LOW);

	// configure TxCFG 
	reg_write(REG_TxCFG, TxCFG_LOW);
}	
		

/*********************************************************************************************
* name:		CS_Init
* func:		initialize  8019AS chip
* para:		none
* ret:		1: initialize success; 0: initialize fail 
* modify:
* comment:		
*********************************************************************************************/
int CS_Init(void)
{
	unsigned short	 rev;
	CS_Probe();

	if(!CS_Reset())
	{
		uart_printf("  Reset CS8900A failed.\n");
		return 0;
	}
	uart_printf("  Reset CS8900A successful, ");

    #ifdef MEM_MODE
    	CS_SetupMemoryBase(MEM_BASE);
    #endif

	switch(rev)
	{
	case REV_B: uart_printf("  Rev B.\n"); break;
	case REV_C: uart_printf("  Rev C.\n"); break;
	case REV_D: uart_printf("  Rev D.\n"); break;
	case REV_F: uart_printf("  Rev F.\n"); break;
	}

	CS_SetupMacAddr(mac_addr);
	CS_EnableIrq(0);
	CS_Configuration();

	return 1;
}

/*********************************************************************************************
* name:		CS_Close
* func:		close  8019AS chip
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void CS_Close(void)
{
	CS_EnableIrq(0);

	reg_read(REG_RxEvent);
	reg_read(REG_TxEvent);

	// cleanup LineCTL 
	reg_write(REG_LineCTL, LineCTL_LOW);

	// cleanup RxCTL 
	reg_write(REG_RxCTL, RxCTL_LOW);

	// cleanup RxCFG 
	reg_write(REG_RxCFG, RxCFG_LOW);

	// cleanup TxCFG 
	reg_write(REG_TxCFG, TxCFG_LOW);
}


/*********************************************************************************************
* name:		CS_ReceivePacket
* func:		receive packet
* para:		unsigned int tms    --  periods
* ret:		return the frame's length
* modify:
* comment:		
*********************************************************************************************/
int CS_ReceivePacket(unsigned int tms)
{
	int i, length;
	unsigned short *buf;

	tms *= 50;
	while(tms)
	{
		unsigned short temp = reg_read(REG_ISQ);
		temp = reg_read(REG_RxEvent);
		if(temp & RxOK) break;
		tms --;
	}

	if(tms == 0)
		return 0;

	// Discard RxStatus 
	reg_read(REG_RxStatus);
	// Read the frame's length.	
	length = reg_read(REG_RxLength);

	// Read frame 
	buf = (unsigned short *)net_in_data;
	for(i=0; i<length; i+=2)
		*buf++ = io_read(IO_BASE+IO_RX_TX_DATA0);

	return length;
}

/*********************************************************************************************
* name:		CS_TransmitPacket
* func:		Transmit packet
* para:		unsigned char *data --  data to be transmit
*           int length          --  length of data
* ret:		1: success  0: fail
* modify:
* comment:		
*********************************************************************************************/
int CS_TransmitPacket(unsigned char *data, int length)
{
	int i;
	unsigned short *buf;

	// Send Command
    #ifdef MEM_MODE
    	reg_write(REG_TxCommand, TxStart | TxCMD_LOW);
    	reg_write(REG_TxLength, (unsigned short)length);
    #else
    	io_write(IO_BASE+IO_TX_COMMAND, TxStart | TxCMD_LOW);
    	io_write(IO_BASE+IO_TX_LENGTH, (unsigned short)length);
    #endif


	// Wait 
	for(i = 0; i < MAX_COUNT; i++)
	{
		unsigned short temp = reg_read(REG_BusST);
		if(temp & Rdy4TxNOW) break;
	} 

	if(i >= MAX_COUNT)
		return 0;

	buf = (unsigned short *)data;
	for(i=0; i<length; i+=2)
		io_write(IO_BASE+IO_RX_TX_DATA0, *buf++);

	iSendData = 0;

	return 1;
}


/*********************************************************************************************
* name:		NicInit
* func:		initialize CS8900A chip
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void NicInit(void)
{
	CS_Init();
	// delay some times
    delay(100);
}

/*********************************************************************************************
* name:		NicClose
* func:		close CS8900A chip
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void NicClose(void)
{
	// close ethernet
	CS_Close();
}

/*********************************************************************************************
* name:		NicReset
* func:		Reset CS8900A chip
* para:		none
* ret:		0: success 		-1: fail
* modify:
* comment:		
*********************************************************************************************/
int NicReset(void)
{
	if(CS_Reset())
		return 0;

	return -1;
}

/*********************************************************************************************
* name:		EtherOutput
* func:		output data through ethernet CS8900A chip
* para:		data -- data pointer
*			len	  -- data length
* ret:		0: success 		-1: fail
* modify:
* comment:		
*********************************************************************************************/
int EtherOutput(unsigned char *dmac, char* data, unsigned short len)
{
	int i;

    for(i=0; i<6; i++)
    	data[i] = dmac[i];
	for(i=0; i<6; i++)
    	data[6+i] =  mac_addr[i];

	len += 14;
    if(len < 60 )
    	len = 60;
    if(len > 1518 )
	{
		uart_printf("  Cann't send data more than 1518 bytes!\n");
		return -1;
   }

	if(!CS_TransmitPacket(data, len))
    	return -1;

	iSendData = 0;
	
    return 0;
}

/*********************************************************************************************
* name:		EtherInput
* func:		get data from ethernet CS8900A chip
* para:		tms -- timeout value
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
int EtherInput(unsigned short tms)
{
	int length = CS_ReceivePacket(tms);


	// Check frame length 
	if(length < 60 || length > 1518)
		return 0;

	iReceiveData = 1;

	return length;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -