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

📄 cs8900a.c

📁 Embest EudKit-II教学系统配Samsung S3C44B0处理器的部分测试程序。
💻 C
字号:
/*********************************************************************************************
* File:	cs8900a.c
* Author:	Embest
* Desc:	cs8900a ethernet chip driver
* History:	
*********************************************************************************************/
#include "cs8900a.h"


#define MEM_BASE	0x06000000
#define IO_BASE		0x07000300
#define MAX_COUNT	0x00100000


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


#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 */
inline 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);
}
inline 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 */


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;


int CS_Probe(void)
{
	unsigned short id, sign;

	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);

	if(sign != ID_SIGNATURE || id != ID_CODE)
		return 0;

	return 1;
}


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);
}


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;
}


unsigned short CS_Identification(unsigned short *rev)
{
	unsigned int id;

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

	return id;
}


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));
}


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;
		}
	}
}


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);
}	
		

int CS_Init(void)
{
	unsigned short id, 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

	id = CS_Identification(&rev);
	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;
}


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);
}


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);
#ifdef MEM_MODE

#else
//	*(volatile unsigned char *)(IO_BASE+IO_RX_TX_DATA0); // only for the EduKit-II Ver200412 board.
#endif

	/* 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;
}


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;
}


/*
* extern functions
*/
/*********************************************************************************************
* 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 + -