//zzc: 2005-2-6 currently not support network simulation on Cygwin
#ifndef __CYGWIN__
/*
	skyeye-ne2k.c - skyeye ne2k nic simulator
	Copyright (C) 2003 Skyeye Develop Group
	for help please send mail to <skyeye-developer@lists.sf.linuxforum.net> 
	
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
*/

/* 04/27/2003	add net option support
 * 				chenyu <chenyu@hpclab.cs.tsinghua.edu.cn>
 * 02/25/2003 	initial version
 *				yangye <yangye@163.net> 		
 */
 
//#include <linux/if.h>
#include <net/if.h>
#include <linux/if_tun.h>
//#include <sys/types.h>
//#include <sys/stat.h>
//#include <fcntl.h>
#include <sys/ioctl.h>
#include <armdefs.h>
#include <clps7110.h>
#define extern
#include "skyeye-ne2k.h"
#undef extern




//if you don't want to the debug info,just commit below two line
//#define DEBUG 1
//#define DEBUG_NETDATA 1
#undef DEBUG
#undef DEBUG_NETDATA
//#define DEBUG_NETDATA
#if DEBUG
#define DBG_PRINT(a...) fprintf(stderr, ##a)
#else
#define DBG_PRINT(a...)
#endif

#define DBG_PRINT1 printf

/*set netcard interrupt  bit*/
#define SET_NET_INT() *state->mach_io.instr |= *state->mach_io.net_int
/*clear netcard interrupt bit*/
#define UNSET_NET_INT() *state->mach_io.instr &= ~(*state->mach_io.net_int);


/*
#define DEVTAP "/dev/net/tun"

#define MACADDR0 0x0
#define MACADDR1 0x01
#define MACADDR2 0x02
#define MACADDR3 0x03
#define MACADDR4 0x04
#define MACADDR5 0x05
*/

extern int skyeye_net_maxfd;

extern void update_int(ARMul_State *state);

INT32U  tapif_fd;
ne2k_t rtl8019;
INT16U  remote_read_offset;
INT8U  remote_read_page;
INT16U  remote_read_count;
INT16U  remote_write_offset;
INT8U  remote_write_page;
INT16U  remote_write_count;
INT8U across_bound_flag;

 
void write_cr(int nic_index, ARMul_State *state,INT8U data)
{
  INT8U startpage;
  INT16U packet_len;
  INT16U rtl8019_len;
  
  DBG_PRINT("write_cr begin: data %d\n", data);
  
  // Validate remote-DMA (RD2,RD1,RD0 not allowed to be 000) 
  if (((data & 0x38) == 0x00))  {//wrong command
     DBG_PRINT("write_cr: wrong command\n");
     return;
  }
  //yangye 2003-1-22
  //notice: CMD_SEND is not one bit (00011000)
  //data & CMD_SEND is wrong
  if (((data & 0x18) == CMD_SEND) && ((data & CMD_NODMA) ==0)){  //SEND PACKET command
    DBG_PRINT("write_cr: send packet command\n");
    if(rtl8019.RBCR1 == 0x0F){
    	rtl8019.RSAR0 = 0;
    	rtl8019.RSAR1 = rtl8019.BNRY;
	//yangye 2003-1-24
	//the read length must +4 (8019 frame header) !
	//low 8 bit of real packet length
	rtl8019.RBCR0 = rtl8019.NICRam[rtl8019.BNRY - 64].PageRam[2];
        //high 8 bit of real packet length
   	rtl8019.RBCR1 = rtl8019.NICRam[rtl8019.BNRY - 64].PageRam[3];
    	//real length + 4 = 8019 frame length
	rtl8019_len = (((INT16U)rtl8019.RBCR1 <<8) | rtl8019.RBCR0) + 4 ;
	rtl8019.RBCR0 = (INT8U)(rtl8019_len & 0xFF) ;  //low
	rtl8019.RBCR1 = (INT8U)(rtl8019_len >>8);       //high
	remote_read_offset = 0;
   	remote_read_page = rtl8019.RSAR1 -64;   // RSAR1 - 0x40;
   	remote_read_count = rtl8019_len;	
    }
  }
  
  
  if (data & CMD_XMIT){  // XMIT command
    DBG_PRINT("write_cr: xmit command\n");
    startpage = (rtl8019.TPSR - 64);  //tpsr - 0x40
    packet_len = (((INT16U)rtl8019.TBCR1 << 8) | (rtl8019.TBCR0));
    
    //chy 2003-04-26:chage for multi net support,but not complete !!!
    //now skyeye support multi cards input,
    //but ne2k.[ch] ..._armio also will change to support muti card output.
    //now i assume skyeye only support one card, but in the future will support more nics.
    //so the first available nic's index must be 0, but in the future, this will change 
    //now nic_index==0
    //tapif_output(state,startpage, packet_len);
    skyeye_net_output(0,state,startpage, packet_len);
    
    /* to do: add count and tx error interrupt here */
    //chy 2003-01-20 should prouduce the ISR_TXE error,but now ...???
    
    /**** send a interrupt to CPU here! ****/
    //chy 2003-01-14 
    //chy 2003-01-20 add test rtl8019.ISR&rtl8019.IMR
    rtl8019.ISR |= ISR_PTX;         //tx success int
    if((ISR_PTX & rtl8019.IMR)){
       //state->io->intsr|=AT91_EXT0;
       //update_int(state);
	//modified by ksh
       //*state->interrupt |= AT91_EXT0;
//	*state->interrupt |= EINT1;
	SET_NET_INT();
				
       skyeye_config.mach->mach_update_int(state);
    }
  }

  if ((data & CMD_WRITE) && ((data & CMD_NODMA) ==0)){  //remote dma write 
    remote_write_page = rtl8019.RSAR1 -64;   // RSAR1 - 0x40
    remote_write_offset = 0;
    remote_write_count = (((INT16U)rtl8019.RBCR1 <<8) | rtl8019.RBCR0);
    if (remote_write_count >1700){   //   should not >1.6k ethernet packet  
      return;
      DBG_PRINT("remote write length error!");
    }
  }
  
  rtl8019.CR = data;
 
  DBG_PRINT("write_cr: end\n");
}
  	
  	
void remote_write(ARMul_State *state, INT8U data)
{
   
  DBG_PRINT("remote_write begin: data %d\n",data);
  if (rtl8019.CR & CMD_WRITE){  //in remote write mode
  
    rtl8019.NICRam[remote_write_page].PageRam[remote_write_offset] = data;
    
    if (++remote_write_offset > 255){
    	remote_write_offset = 0;
    	remote_write_page++;
     	}
    
    if(--remote_write_count == 0){   // remote write finished
      rtl8019.CR &= (~CMD_WRITE);  //clear dma command in CR
      rtl8019.CR |=  CMD_NODMA;
      
      
      /*** send CPU a interrupt here !***/
      // chy 2003-01-14
      //chy 2003-01-20 add test rtl8019.ISR&rtl8019.IMR
      rtl8019.ISR |= ISR_RDC;  // remote write finished int

      if((ISR_RDC & rtl8019.IMR)){
       //state->io->intsr|=AT91_EXT0;
       //update_int(state);
      // *state->interrupt |= AT91_EXT0;
	
			
	SET_NET_INT();
       skyeye_config.mach->mach_update_int(state);
      }
		  
     }
     //chy 2002-01-17 correct ???
     DBG_PRINT("remote write end\n");
     return;
  }

  DBG_PRINT("remote write error: not in remote write mode!");
}


INT8U remote_read(ARMul_State *state)    //only support "SEND PACKET " command
{
  INT8U data;
  
  DBG_PRINT("remote read begin\n");
  
  if( rtl8019.CR & CMD_SEND){  //in remote write mode
    
    data = rtl8019.NICRam[remote_read_page].PageRam[remote_read_offset];
    
    if (++remote_read_offset > 255){
    	remote_read_offset = 0;
    	remote_read_page++;
    	if (++rtl8019.BNRY >= rtl8019.PSTOP){  //read point out of bound
    	  rtl8019.BNRY = rtl8019.PSTART;
	  //yangye 2003-1-21
	  //bnry acrossed PSTOP
	  across_bound_flag = 0;
	}
    }
    
    if(--remote_read_count == 0){   // remote write finished
      rtl8019.CR &= (~CMD_SEND);  //clear dma command
      //yangye 2003-1-23
      // not & , should be |
      rtl8019.CR |=  CMD_NODMA;  
	//yangye 2003-1-21
	//set BNRY = the page has beed read +1
	//so BNRY point to CURR or next packet
	if (++rtl8019.BNRY >= rtl8019.PSTOP){  //read point out of bound
		 rtl8019.BNRY = rtl8019.PSTART;
		 across_bound_flag = 0;
	}	
      /*** send CPU a interrupt here !***/
      //chy 2003-01-14
      //chy 2003-01-20 add test rtl8019.ISR&rtl8019.IMR
	rtl8019.ISR |= ISR_RDC;    //remote read finished int
	if((ISR_RDC & rtl8019.IMR)){
	  //state->io->intsr|=AT91_EXT0;
	  //update_int(state);
       	  //*state->interrupt |= AT91_EXT0;
	SET_NET_INT();

          skyeye_config.mach->mach_update_int(state);
	}		  
    }
    DBG_PRINT("remote read end:data %d\n",data);
    return data;
  }
    
}

void nic_reset(int nic_index)
{
INT8U tmp;
int i;
//init PROM 
if(skyeye_config.net[nic_index].state==1){
  rtl8019.PROM[0]  = (INT8U) skyeye_config.net[nic_index].macaddr[0];//MACADDR0;
  rtl8019.PROM[1]  = (INT8U) skyeye_config.net[nic_index].macaddr[0];//MACADDR0;
  rtl8019.PROM[2]  = (INT8U) skyeye_config.net[nic_index].macaddr[1];//MACADDR1;
  rtl8019.PROM[3]  = (INT8U) skyeye_config.net[nic_index].macaddr[1];//MACADDR1;
  rtl8019.PROM[4]  = (INT8U) skyeye_config.net[nic_index].macaddr[2];//MACADDR2;
  rtl8019.PROM[5]  = (INT8U) skyeye_config.net[nic_index].macaddr[2];//MACADDR2;
  rtl8019.PROM[6]  = (INT8U) skyeye_config.net[nic_index].macaddr[3];//MACADDR3;
  rtl8019.PROM[7]  = (INT8U) skyeye_config.net[nic_index].macaddr[3];//MACADDR3;
  rtl8019.PROM[8]  = (INT8U) skyeye_config.net[nic_index].macaddr[4];//MACADDR4;
  rtl8019.PROM[9]  = (INT8U) skyeye_config.net[nic_index].macaddr[4];//MACADDR4;
  rtl8019.PROM[10] = (INT8U) skyeye_config.net[nic_index].macaddr[5];//MACADDR5;
  rtl8019.PROM[11] = (INT8U) skyeye_config.net[nic_index].macaddr[5];//MACADDR5;
  
  rtl8019.PAR0=rtl8019.PROM[0];
  rtl8019.PAR1=rtl8019.PROM[2];
  rtl8019.PAR2=rtl8019.PROM[4];
  rtl8019.PAR3=rtl8019.PROM[6];
  rtl8019.PAR4=rtl8019.PROM[8];
  rtl8019.PAR5=rtl8019.PROM[10];
  
}else{
  printf("nic_reset:error skyeye_config.net[%d].state=%d\n",nic_index, skyeye_config.net[nic_index].state);
  exit(-1);
}

  //init Registers
  rtl8019.CR = 0x21;   //nic Stopped
  rtl8019.PSTART = 0;
  rtl8019.PSTOP = 0;
  rtl8019.BNRY = 0;
  rtl8019.TPSR = 0;
  rtl8019.TBCR0 = 0;
  rtl8019.TBCR1 = 0;
  rtl8019.ISR =   0;  
  rtl8019.RSAR0 = 0;
  rtl8019.RSAR1 = 0;
  rtl8019.RBCR0 = 0;
  rtl8019.RBCR1 = 0;
  rtl8019.RCR = 0;
  rtl8019.TCR = 0;
  rtl8019.DCR = 0x84;  //set long addr bit
  rtl8019.IMR = 0;
  rtl8019.CURR = 0;

  //init nic RAM
  tmp = 64;           //0x40,first page
  for(i=0;i<32;i++){
     rtl8019.NICRam[i].PageNumber = tmp++;
  }
}

INT8U nic_read(int nic_index, ARMul_State *state, INT8U offset)  
{
  //DBG_PRINT("nic read begin: offset %x, rtl8019.ISR %x\n",offset,rtl8019.ISR);
   if (offset == 0x10){   //remote read
        return remote_read(state);
   	}
   if (offset == 0x1f){  //reset
	nic_reset(nic_index);
	return 0;
   }
  if ((rtl8019.CR >> 6) ==0){  //read page0
  	switch (offset){
		case 0x00:  //CR
	  	  return rtl8019.CR;
	 
		case 0x03:  //BNRY
	  	  return rtl8019.BNRY;
		
		case 0x07:  // ISR
	  	  return rtl8019.ISR;
  	}
  } //end  if page0

   if ((rtl8019.CR >>6) == 1){  //read page1
   	switch (offset){
   		case 0x00:  //CR
   		  return rtl8019.CR;;

   		case 0x01:  //PAR0 - PAR5 ,MAC addr
   		  return rtl8019.PAR0;

   		case 0x02:
   		  return rtl8019.PAR1;
   		  
   		case 0x03:
   		  return rtl8019.PAR2;

   		case 0x04:
   		  return rtl8019.PAR3;

   		case 0x05:
   		  return rtl8019.PAR4;

   		case 0x06:
   		  return rtl8019.PAR5;

   		case 0x07:  //CURR
   		  return rtl8019.CURR;
   		}
   	}//end if PAGE1

   if ((rtl8019.CR >>6) == 2){  //read page2
   	switch (offset){
   		case 0x00:  //CR
   		  return rtl8019.CR;

   		case 0x01:  //PSTART
   		  return rtl8019.PSTART;

   		case 0x02:  //PSTOP
   		  return rtl8019.PSTOP;

   		case 0x04:  //TPSR
   		  return rtl8019.TPSR;

   		case 0x0C:  //RCR
   		  return rtl8019.RCR;

   		case 0x0D:  //TCR
   		  return rtl8019.TCR;

   		case 0x0E:  //DCR
   		  return rtl8019.DCR;

   		case 0x0F:  //IMR
   		  return rtl8019.IMR;
   		}
   	}//end if page2
   
   return 0;
	  
}


void nic_write(int nic_index, ARMul_State *state,INT8U offset, INT8U data) //offset should be 00-0f, 10 or 1f
{
   //DBG_PRINT("nic write begin: offset %x, data %x\n",offset,data);
   
   if (offset == 0x10){   //remote write
	remote_write(state,data);
   	return;
   }
   if (offset == 0x1f){  //reset
	nic_reset(nic_index);
	return;
   	}
   if ((rtl8019.CR >> 6) ==0){  //write page0
  	switch (offset){
		case 0x00:  //CR
	  	  write_cr(nic_index,state,data);
		  break;

	  	case 0x01:  //PSTART
	  	  rtl8019.PSTART = data;
		  break;

	  	case 0x02: //PSTOP
	  	  rtl8019.PSTOP = data;
		  break;

	  	case 0x03: //BNRY
	  	  rtl8019.BNRY = data;
		  break;

	  	case 0x04: //TPSR
	  	  rtl8019.TPSR = data;
		  break;

	  	case 0x05: //TBCR0
	  	  rtl8019.TBCR0 = data;
		  break;

	        case 0x06: //TBCR1
	  	  rtl8019.TBCR1 = data;
		  break;

	  	case 0x07: //ISR  (write means clear)
	  	  rtl8019.ISR = (rtl8019.ISR & (~data));
		  UNSET_NET_INT();				
		  break;

	  	case 0x08: //RSAR0
	  	  rtl8019.RSAR0 = data;
		  break;

	  	case 0x09: //RSAR1
	  	  rtl8019.RSAR1 = data;
		  break;

	  	case 0x0a: //RBCR0
	  	  rtl8019.RBCR0 = data;
		  break;

	  	case 0x0b: //RBCR1
	  	  rtl8019.RBCR1 = data;
		  break;

	  	case 0x0c: //RCR
	  	  rtl8019.RCR = data;
		  break;

	  	case 0x0d: //TCR
	  	  rtl8019.TCR = data;
		  break;

	  	case 0x0e: //DCR
	  	  rtl8019.DCR = data;
		  break;

	  	case 0x0f: //IMR
	  	  rtl8019.IMR = data;
		  break;
  		}
	return;
       }//end if page0

	  	  
   if ((rtl8019.CR >>6) == 1){  //write page1
   	switch (offset){
   		case 0x00: //CR
   		  write_cr(nic_index, state,data);
		  break;

   		case 0x01:  //PAR0 - PAR5 ,MAC addr
   		  rtl8019.PAR0 = data;
		  break;

   		case 0x02:
   		  rtl8019.PAR1 = data;
   		  break;

   		case 0x03:
   		  rtl8019.PAR2 = data;
		  break;

   		case 0x04:
   		  rtl8019.PAR3 = data;
		  break;

   		case 0x05:
   		  rtl8019.PAR4 = data;
		  break;

   		case 0x06:
   		  rtl8019.PAR5 = data;
		  break;

   		case 0x07:  //CURR
   		  rtl8019.CURR = data;
		  break;
	}
	return;
   }//end if page1

   //yangye 2003-1-21
   //add write page2 ,only CR
   if((rtl8019.CR >>6) == 2){   //write page2
     if(offset == 0x00){
       write_cr(nic_index,state,data);
       return;
     }
   } //end if page2
   DBG_PRINT("error write page or error write register\n");
   return;
}

//chy 2003-04-26: support multi nic
void nic_init(void)
{ int i,ret;
  for(i=0;i<NET_MAXNICNUM_PER_HOST;i++){
    if(skyeye_config.net[i].state==1){
        ret=skyeye_config.net[i].net_init(i, skyeye_config.net[i].macaddr,skyeye_config.net[i].hostip);
	DBG_PRINT("get called!");
	if(ret>0){
	   skyeye_config.net[i].fd=ret;
	   if(skyeye_net_maxfd<skyeye_config.net[i].fd)
	           skyeye_net_maxfd=skyeye_config.net[i].fd;
	}
	nic_reset(i);
     }
   }
 }

void  tapif_input(int tapif_fd, ARMul_State *state)
{
  //yangye 2003-1-24
  //rtl8019_len = packet_len + 4
  INT16U packet_len, rtl8019_len;
  INT8U buf[1600];
  INT8U *bufptr;
  //yangye 2003-1-22
  // i is used from 0 to 256!!! ,must be 16bit long!! 
  INT16U i,j,len;
  
  
  DBG_PRINT("tapif_input begin\n");

  if (rtl8019.CR & CMD_STOP){  //nic in stop mode 
    return;
  }


  //yangye 2003-1-22
  //init the first 60 bytes to 0 for pad 
  //for(i=0;i<60;i++)
  //  buf[i] = 0;

  //read from tapif to buf (begin from buf[4])
  packet_len = read(tapif_fd, &buf[4], sizeof(buf));
  rtl8019_len = packet_len + 4;
  //yangye 2003-1-22
  //pad packet length to 60 bytes
  //yangye 2003-1-24
  //commit this to solve checksum error problem
  //if(packet_len < 60)
  //  packet_len = 60;

// print the debug info of net input data
#ifdef DEBUG_NETDATA
{
  INT8U *bptr;
 int t,m;
 bptr=&buf[0];
 t=m=0;
 fprintf(stderr,"net data (len %d) from tapif\n",packet_len);
   
  if(packet_len<=0){
      fprintf(stderr," no data\n");
  }
   
  while(t<rtl8019_len){
    fprintf(stderr," 0x%2x ",bptr[t]);
    t++;m++;
     if(m>=10){
       fprintf(stderr,"\n");
       m=0;
     }
   }
   fprintf(stderr,"\n");
   }
  
#endif
 
//yangye 2003-1-21
 //wrong : the length stored in 8019 frame header is real length of ethernet packet
 //no need to +4
 // packet_len += 4;      //8019 frame header length is 4 bytes!
  
 //add 8019 frame header
  buf[0] = 0x10;      //don't use this bit , no meaning
  buf[1] = 0x50;      //don't use this bit,  no meaning
  //here we should save packet_len , not rtl8019_len
  buf[2] = (packet_len & 0xFF);    //low 8 bit
  buf[3] = (INT8U)(packet_len >>8); //high 8 bit
  bufptr = &buf[0];      // now buf is a 8019 frame, not a ethernet frame.

  //verify MAC addr of the packet
  //yangye 2003-1-19
  //verify broadcast packet
  //chy 2003-01-20
  //if (buf[4]==buf[5]==buf[6]==buf[7]==buf[8]==buf[9]==0xFF){
  if (buf[4]==0xff&&buf[5]==0xff&&buf[6]==0xff&&buf[7]==0xff&&buf[8]==0xff&&buf[9]==0xff){
    //chy 2003-01-20
    DBG_PRINT(" tapif_input: is a broadcast address!!!\n");
  }
   //buf[4] - buf[9] is destnation MAC addr
  else if ((rtl8019.PAR0 != buf[4]) || (rtl8019.PAR1 != buf[5]) || (rtl8019.PAR2 != buf[6]) || (rtl8019.PAR3 != buf[7]) || (rtl8019.PAR4 != buf[8]) || (rtl8019.PAR5 != buf[9])){
	DBG_PRINT(stderr,"tapif_input: is a wrong destnation address!!!\n");
	DBG_PRINT("tapif_input: %x %x %x %x %x %x\n",buf[4],buf[5],buf[6],buf[7],buf[8],buf[9]);
	DBG_PRINT("tapif_input: %x %x %x %x %x %x\n",rtl8019.PAR0,rtl8019.PAR1,rtl8019.PAR2,rtl8019.PAR3,rtl8019.PAR4,rtl8019.PAR5);
        return;
  }
 	
   //write buf to NICRam,rtl8019.CURR is write page pointer
  while (rtl8019_len > 256){
     for(i=0;i<=255;i++){
       rtl8019.NICRam[rtl8019.CURR - 64].PageRam[i] = *bufptr++;
     }
     rtl8019_len -= 256;
     rtl8019.CURR++;
     if (rtl8019.CURR >= rtl8019.PSTOP){   //write pointer out of bounds
       rtl8019.CURR = rtl8019.PSTART;
       //yangye 2003-1-21
       //add across_bound_flag to see if CURR has acrossed PSTOP
       across_bound_flag = 1;
     	}
     if ((rtl8019.CURR >= rtl8019.BNRY) && (across_bound_flag == 1)){    //write pointer get to read pointer
       across_bound_flag = 0;
       DBG_PRINT(" nic ram overflowed!");
       /*raise a overflow int here! */
       //chy 2003-01-20 add test rtl8019.ISR&rtl8019.IMR
       rtl8019.ISR |= ISR_OVW;
     if((ISR_OVW & rtl8019.IMR)){
          //state->io->intsr|=AT91_EXT0;
          //update_int(state);
       	  //*state->interrupt |= AT91_EXT0;
						 //modified by ksh
	SET_NET_INT();
				
       	  skyeye_config.mach->mach_update_int(state);
     }
     DBG_PRINT("tapif_input err end!!!!\n");
     return;
     }
  } //while (rtl8019_len > 256)

  // then input the left <256 bytes
  for (i=0;i<rtl8019_len;i++){
    rtl8019.NICRam[rtl8019.CURR - 64].PageRam[i] = *bufptr++;
  }
 
 //yangye 2003-1-21
 //CURR point to next blank page
 rtl8019.CURR++;
 if (rtl8019.CURR >= rtl8019.PSTOP){   //write pointer out of bounds
      rtl8019.CURR = rtl8019.PSTART;
      //yangye 2003-1-21
      //add bound_flag to see if CURR has acrossed PSTOP
     across_bound_flag = 1;           
 }
 if ((rtl8019.CURR >= rtl8019.BNRY) && (across_bound_flag ==1)){    //write pointer get to read pointer
   across_bound_flag = 0;   
   DBG_PRINT(" nic ram overflowed!");
   /* to do : raise a overflow interrupt here! */
   rtl8019.ISR |= ISR_OVW;
   if((ISR_OVW & rtl8019.IMR)){
     //state->io->intsr|=AT91_EXT0;
     //update_int(state);
      // *state->interrupt |= AT91_EXT0;
	SET_NET_INT();

       skyeye_config.mach->mach_update_int(state);
   }

   DBG_PRINT("tapif_input err end!!!!\n");
   return;
  }
  
 //} //for //test!!!


 //get packet from tap compelete 
 //now raise interrput

  /*** send CPU a rx interrupt here! *****/
    //chy 2003-01-14
    //chy 2003-01-20 add test rtl8019.ISR&rtl8019.IMR
 rtl8019.ISR |= ISR_PRX;   //got packet int
 if((ISR_PRX & rtl8019.IMR)){
       //state->io->intsr|=AT91_EXT0;
       //update_int(state);
       //*state->interrupt |= AT91_EXT0;
	SET_NET_INT();
			
       skyeye_config.mach->mach_update_int(state);
    }
  DBG_PRINT("tapif_input end\n");
}

INT8U tapif_output(int tapif_fd, ARMul_State *state,INT8U startpage,INT16U packet_len)
{
  INT8U buf[1600];
  INT8U *bufptr;
  INT8U curr_page;
  //yangye 2003-1-22
  //i must be 16 bit long!
  INT16U i,len;
  DBG_PRINT("tapif_output begin\n");

  if (rtl8019.CR & CMD_STOP){  //nic in stop mode 
    return;
  }

 // read packet into buf
  bufptr = &buf[0];
  curr_page = startpage;
  len = packet_len;

  while (len > 256){
     for(i=0;i<=255;i++){
      *bufptr++ = rtl8019.NICRam[curr_page].PageRam[i];
   	}
     len -= 256;
     curr_page++;
  }
  for (i=0;i<len;i++){
  	*bufptr++ = rtl8019.NICRam[curr_page].PageRam[i];
  }

#ifdef DEBUG_NETDATA
{
  INT8U *bptr;
  int i,j,k;
  bptr=&buf[0];
  i=j=0;
  fprintf(stderr,"net data (len %d) to tapif\n",packet_len);
  while(i<packet_len){
    fprintf(stderr," 0x%2x ",bptr[i]);
    i++;j++;
    if(j>=10){
      fprintf(stderr,"\n");
      j=0;
    }

  }
  fprintf(stderr,"\n");
}
#endif

  // write buf to tapif
  if(write(tapif_fd, buf, packet_len) == -1) {
    fprintf(stderr,"write to tapif error in skyeye-ne2k.c\n");
    return -1;
  }
  DBG_PRINT("tapif_output end\n");
  return 0;
}

//zzc:#endif __CYGWIN__
#endif
