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

📄 emac.c

📁 一个网卡的应用
💻 C
字号:
#include "at91rm9200.h"
#include "emac.h"
#include "routine.h"
#include "uart.h"

static rbd_list rbdl[LISTLENGTH];				//receive buffer descriptor list
static unsigned int recv_buf[LISTLENGTH][MAXFRAME];		//receive buffer
static unsigned char send_buf[MAXFRAME];			//buffer for packet to be sent

static unsigned char local_mac[6];				//local mac
static unsigned char local_ip[4];				//local ip
static unsigned char server_mac[6];				//server mac
static unsigned char server_ip[4];				//server ip
static unsigned char target_mac[6];				//target mac
static unsigned char target_ip[4];				//target ip

static void set_local_mac(  emac_reg_p emac ) {
	local_mac[0] = 0x00;
	local_mac[1] = 0x11;
	local_mac[2] = 0xd8;
	local_mac[3] = 0xe8;
	local_mac[4] = 0x34;
	local_mac[5] = 0x2c;

	emac->eth_sa1l = local_mac[5] | (local_mac[4]<<8) | (local_mac[3]<<16) | (local_mac[2]<<24);
	emac->eth_sa1h = local_mac[1] | (local_mac[0]<<8);	
}

static void set_local_ip( ) {
	local_ip[0] = 0xac;
	local_ip[1] = 0x10;
	local_ip[2] = 0x64;
	local_ip[3] = 0xf1;
}

static void set_server_ip( ){
	server_ip[0] = 0xac;
	server_ip[1] = 0x10;
	server_ip[2] = 0x64;
	server_ip[3] = 0xe9;
}

static unsigned mii_readPhy(emac_reg_p emac, unsigned char reg){
	unsigned value = 0x60020000 | (reg<<18);
	
	emac->eth_ctl |= EMAC_MPE;
	emac->eth_man = value;
	while( !(emac->eth_sr&EMAC_IDLE) );
	emac->eth_ctl &= ~EMAC_MPE;
	return (unsigned)(emac->eth_man&0xffff);
}

static void get_link_speed( emac_reg_p emac ){
	unsigned short value;
	unsigned int update;

	value = mii_readPhy(emac, MII_STATUS2);

	if( !( value & 0x400 ) )
		return;
	if( value & 0x4000 ) 
		update |= EMAC_SPD;
	if( value & 0x200 )
		update |= EMAC_FD;
	emac->eth_cfg = emac->eth_cfg & ~( EMAC_SPD | EMAC_FD ) | update;
}

static void emac_configure() {
	int i;

	emac_reg_p emac = (emac_reg_s *)EMAC_BASE;

	for(i=0; i<LISTLENGTH; i++){			//setup recv buf pointers
		rbdl[i].address = (unsigned) ( recv_buf[i] );
		rbdl[i].size = 0;
	}
	rbdl[i-1].address |= 0x2;

	emac->eth_ctl = 0;
	if( !(emac->eth_sr & EMAC_LINK) )
		get_link_speed( emac );
	set_local_mac( emac );
	set_local_ip();
	set_server_ip();
	emac->eth_rbqp = (unsigned) rbdl;

	emac->eth_rsr |= (EMAC_BNA | EMAC_REC | EMAC_OVR);
	emac->eth_cfg |= EMAC_CAF;
	emac->eth_cfg = ( emac->eth_cfg & ~(EMAC_CLK) ) | EMAC_CLK_32;
	emac->eth_ctl |= (EMAC_TE | EMAC_RE);
	emac->eth_tar = (unsigned)send_buf;
}

void emac_init() {
	unsigned temp;
	arp_packet * arp = (arp_packet *) send_buf;
	pio_reg_p pioa = (pio_reg_s *)PIOA_BASE;
	pio_reg_p piob = (pio_reg_s *)PIOB_BASE;
	pmc_reg_p pmc  = (pmc_reg_s *)PMC_BASE;

	pmc->pmc_pcer = ( (unsigned) 0x1<<ID_EMAC);

	temp = 0x1ff80;
	pioa->pio_asr |= temp;
	pioa->pio_bsr &= ~temp;
	pioa->pio_pdr = temp;

	temp = 0xff000;
	pioa->pio_asr &= ~temp;
	pioa->pio_bsr |= temp;
	pioa->pio_pdr = temp;

	p_memset( (char*)arp->stuff, 0, 6 );
	emac_configure();
}

void arp_frame( int op ) {
	arp_packet * arp = (arp_packet *) send_buf;
	emac_reg_p emac = (emac_reg_s *)EMAC_BASE;
	p_memcpy( (char*)local_mac, (char*)arp->srcAddr, 6 );
	arp->frameLen = SWAP16( TYPE_ARP );
	arp->hardware = SWAP16(1);
	arp->protocol = SWAP16(TYPE_IP);
	arp->hlen = 6;
	arp->plen = 4;
	p_memcpy( (char *)local_mac, (char *)(arp->sendHA), 6);
	p_memcpy( (char *)local_ip, (char *)arp->sendIP, 4);
	if( op == REQUEST ) {
		p_memset( (char*)arp->dstAddr, 0xff, 6);
		arp->operation = SWAP16(1);
		p_memset( (char *)arp->targetHA, 0, 6);
		p_memcpy( (char *)server_ip, (char *)arp->targetIP, 4);
	}
	else if( op == REPLY ) {
		p_memcpy( (char*)target_mac, (char*)arp->dstAddr, 6 );
		arp->operation = SWAP16(2);
		p_memcpy( (char*)target_mac, (char*)arp->targetHA, 6 );
		p_memcpy( (char*)target_ip, (char*)arp->targetIP, 4 );
	}
}

void send_packet( ) {
	emac_reg_p emac = (emac_reg_s *)EMAC_BASE;

	while( !(emac->eth_tsr & EMAC_BNQ) );
	emac->eth_tsr |= EMAC_COMP;
	emac->eth_tar = (unsigned)send_buf;
	emac->eth_tcr = 0x40;
}

static void delay_millis( ) {
	int i, max;
	
	for( i=0; i<FCOUNT; i++ );
}

static void format_string( char *str, char* mac ) {
	int i, j;
	for( i=0; i<6; i++ ) {
		*str = ASCII_HI( mac[i] );
		str++;
		*str = ASCII_LO( mac[i] );
		str++;
		if( i==5 )
			*str = '\0';
		else {
			*str = '.';
			str++;
		}
	}
}

void emac_test() {
	int i, frame;
	emac_reg_p emac = (emac_reg_s *)EMAC_BASE;
	arp_packet * arp;
	char mac[18];

	put_s( "arp test begin.\r\n" );
	arp_frame( REQUEST );
	send_packet();
	while(1) {
//		put_s( "." );
		delay_millis( 1 );
		for(frame=-1, i=0; i<LISTLENGTH; i++) {
			if( rbdl[i].address & 0x1 ) {
				frame = i;
				emac->eth_rsr |= 0x2;
				break;
			}
		}
		if( frame<0 )
			continue;
		put_s( "got a frame.\r\n" );
		arp = (arp_packet*) ( rbdl[frame].address & 0xfffffffc );
		if( arp->frameLen == SWAP16( TYPE_ARP ) ) {
			if( p_memcmp( (char*)arp->targetIP, (char*)local_ip, 4 ) ) {
				if( arp->operation == SWAP16( REQUEST ) ) {
					p_memcpy( (char*)arp->sendHA, target_mac, 6 );
					p_memcpy( (char*)arp->sendIP, target_ip, 6 );
					put_s( "mac:\t" );
					format_string( (char*) mac, (char*)target_mac );
					put_s( "\r\n" );
					arp_frame( REPLY );
					send_packet();
				}
				if( arp->operation == SWAP16( REPLY ) ) {
					p_memcpy( (char*)arp->sendHA, server_mac, 6 );
					format_string( (char*)mac, (char*)server_mac );
					break;
				}
			}
		}
		
	}
	put_s( "The MAC for AC.10.64.E9 is:\t" );
	put_s( (char*) mac );
	put_s( "emac test end.\r\n" );
}

⌨️ 快捷键说明

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