www.pudn.com > e041tcpipc51.rar > ethernet.c


#include  
#include  
#include  
#include  
#include "reg_ne2k.h" 
#include "ethernet.h" 
sbit HW_RESET=0xb4; 
BYTE mymac[MACLEN]; 
typedef struct {                    /*  NIC hardware packet header */ 
    BYTE stat;                      /*  Error status */ 
    BYTE next;                      /*  Pointer to next block */ 
    WORD len;                       /*  Length of this frame incl. CRC */ 
} NICHDR; 
NICHDR nichdr; 
 
void delay_ms(int number); 
void resetnic(); 
void getnic(WORD addr,BYTE buf[],WORD len); 
void putnic(WORD addr,BYTE buf[],WORD len); 
BYTE nicwrap(BYTE page); 
 
//*************************************************** 
//		接收数据包,将8019中的数据包读入指定的数据包缓冲区pkt,帧头读入nichdr结构中 
//		全局变量 nichdr	 
//      全局变量 next_packet 
//      返回:如果接收到数据包,返回数据包长度len,(该长度为减去校验和长度)  
//            否则  : 0 
//      get packet into buffer,return length (excel  CRC ),or 0 if no available 
//*************************************************** 
WORD get_ethernet(void *efp) 		 
{ 
	WORD current_offset; 
	BYTE curr_page; 
	BYTE bnry; 
	if (EN0_ISR &0x10) resetnic();      
									/* Get the Receive Page, CURR */ 
		EN_CMD = EN_NODMA + EN_PAGE1 + EN_START;   
		curr_page = EN1_CURPAG; 
		EN_CMD = EN_NODMA + EN_PAGE0 + EN_START; 
		bnry=EN0_BOUNDARY+1;		/* Get the BOUNDARY Register  */ 
		if (bnry>RX_STOP_PG)  bnry=RX_START_PG; 
		/* Remove one frame from the ring.  Boundary is always a page behind. */ 
//		if (curr_page==0) return (0); 
		if (bnry!=curr_page) 
	    { 
			current_offset = (WORD)(bnry << 8); 
			/* Get the header of this packet */ 
			memset(&nichdr,0xee,sizeof(nichdr)); 
			getnic(current_offset, (BYTE *)&nichdr,sizeof(nichdr)); 
			nichdr.len=(nichdr.len/256)+((nichdr.len %256)<<8); 
						//keil c 在结构中使用该方法时,编译器编译的不正确(keil c bug) 
//			nichdr.len=(nichdr.len>>8)&0xff+(nichdr.len&0xff)<<8; 
			if ((nichdr.stat &0x01) && nichdr.len>=MINFRAMEC  && nichdr.len<=MAXFRAMEC) 
				getnic(current_offset+sizeof(nichdr),(BYTE *)efp,nichdr.len-sizeof(nichdr)); 
			if (nichdr.next>=RX_START_PG && nichdr.next>8); 
 		putnic(TX_START_PG<<8,(BYTE *)efp,len); 
 		EN_CMD=EN_NODMA+EN_PAGE0+EN_TRANS; 
	 } 
	 return(len); 
} 
//************************************************************* 
//      reset nic (ne2000 compact 8019as) 
//************************************************************* 
void resetnic() 
{ 
    HW_RESET = 1;           /* Hardware RESET.   when EN_RESET = 0; is Software  */ 
    delay_ms(10); 
    HW_RESET = 0; 
	delay_ms(10);     
 
    EN_CMD = EN_PAGE0 + EN_NODMA + EN_STOP; /* 00001010B: PS1 PS0 RD2 RD1 RD0 TXP STA STP */ 
    delay_ms(4); 
//    EN0_DCFG = ENDCFG_FT10 + ENDCFG_BMS + ENDCFG_BOS;   /*  ?FIFO treshold 8byte !!,normal operation, byte transfer mode selection */ 
    						/* Clear the remote	byte count registers. */ 
    EN0_DCFG = ENDCFG_FT10 + ENDCFG_BMS; 
    EN0_RCNTHI = 0x00; 			/* MSB remote byte count reg */ 
    EN0_RCNTLO = 0x00; 			/* LSB remote byte count reg */ 
 
    EN0_RXCR = E8390_RXOFF; 	/* RX configuration reg    Monitor mode (no packet receive) */ 
    EN0_TXCR = E8390_TXOFF; 	/* TX configuration reg    set internal loopback mode  */ 
     
    EN0_TPSR = NE_START_PG; 
    EN0_STARTPG = RX_START_PG ; /* DMA START PAGE 46h */  
                                /* Starting page of ring buffer. First page of Rx ring buffer 46h*/ 
    EN0_STOPPG = NE_STOP_PG;    /* Ending page +1 of ring buffer */ 
    EN0_BOUNDARY = RX_START_PG;	/* Boundary page of ring buffer */ 
    EN0_ISR = 0xff; 			/* INTerrupt stauts reg */ 
    EN0_IMR = 0; 				/* INTerrupt mask reg = Disable all Interrupt */ 
     
     
    EN_CMD = EN_PAGE1 + EN_NODMA+EN_STOP; 
    delay_ms(4);  
    EN1_PAR0 = mymac[0]; 
    EN1_PAR1 = mymac[1]; 
    EN1_PAR2 = mymac[2]; 
    EN1_PAR3 = mymac[3]; 
    EN1_PAR4 = mymac[4]; 
    EN1_PAR5 = mymac[5]; 
    /* Initialize the multicast list to accept-all.  If we enable multicast 
	   the higher levels can do the filtering. multicast filter mask array (8 bytes) */ 
    EN1_MAR0 = 0xff;   
    EN1_MAR1 = 0xff; 
    EN1_MAR2 = 0xff; 
    EN1_MAR3 = 0xff; 
    EN1_MAR4 = 0xff; 
    EN1_MAR5 = 0xff; 
    EN1_MAR6 = 0xff; 
    EN1_MAR7 = 0xff; 
     
    EN1_CURR = RX_START_PG + 1; /* RX_CURR_PG; Current memory page = RX_CURR_PG  ? */ 
   
    EN_CMD = EN_PAGE0 + EN_NODMA ;  /* 00001010B: PS1 PS0 RD2 RD1 RD0 TXP STA STP */ 
     
    EN0_RXCR = ENRXCR_RXCONFIG;      /* rx on(broadcasts, no multicast,errors   04*/ 
    EN0_TXCR = ENTXCR_TXCONFIG;      /* xmit on. */ 
     
    EN0_ISR = 0xff; 	 /* Individual bits are cleared by writing a "1" into it. */ 
    					 /* It must be cleared after power up. */ 
    					  
    EN0_IMR = ENISR_ALL; /* INTerrupt mask reg */ 
     
	EN_CMD = EN_PAGE0 + EN_NODMA + EN_START; 
} 
//******************************************* 
//  get a packet form a given address in NIC's RAM 
//  DMA READ 
// 
//******************************************* 
void getnic(WORD addr, BYTE buf[],WORD len) 
{ 
	EN0_ISR=ENISR_RDC;			//clear remote dma interrupt flag 
  	EN0_RCNTLO = (BYTE)(len&0xff);			// read length low 
	EN0_RCNTHI = (BYTE)(len>>8);			// read length high 
	EN0_RSARLO=(BYTE)(addr &0xff);			// read address low 
	EN0_RSARHI=(BYTE)(addr>>8);				// read address high 
	EN_CMD=EN_RREAD+EN_START+EN_PAGE0;		// do dma read 
	while (len--) 
		*buf++=EN_DATA; 
} 
	 
//******************************************* 
//  put a packet into a given address in NIC's RAM 
//  DMA Write 
// 
//******************************************* 
void putnic(WORD addr, BYTE buf[],WORD len) 
{ 
	len+=len&0x01; 
	EN0_ISR=ENISR_RDC;			//clear remote dma interrupt flag 
	EN0_RCNTLO = (BYTE)(len&0xff); 
	EN0_RCNTHI = (BYTE)(len>>8); 
	EN0_RSARLO=(BYTE)(addr &0xff); 
	EN0_RSARHI=(BYTE)(addr>>8); 
	EN_CMD=EN_RWRITE+EN_START+EN_PAGE0; 
	while (len--) 
		EN_DATA=*buf++; 
	len=10000; 
	while ((len && (EN0_ISR & ENISR_RDC))==0)	 
			len--; 
} 
//*************************************** 
//    wrap an rx page number 
//***************************************	 
BYTE nicwrap(BYTE page) 
{ 
	if (page>=RX_STOP_PG) 
		page+=RX_START_PG-RX_STOP_PG; 
	else   if(pagee.ptype = pcol; 
        memcpy(efp->e.dest, dest, MACLEN); 
	    memcpy(efp->e.srce, srce, MACLEN); 
        dlen += sizeof(ETHERHDR); 
    	return(dlen); 
} 
 
 
/* Do TCP-style checksum. Improved algorithm is from RFC 1071 */ 
WORD csum(void *dp, WORD count) 
{ 
    register LWORD total=0L; 
    register WORD n, *p, carries; 
 
    n = count / 2; 
    p = (WORD *)dp; 
    while (n--) 
        total += *p++; 
    if (count & 1) 
        total += (*(BYTE *)p)<<8; 
    while ((carries=(WORD)(total>>16))!=0) 
        total = (total & 0xffffL) + carries; 
    return((WORD)total); 
}