//#include "8000A.h"
#include "var.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
中斷使用注意事項
_asm cli
GetTimeDate();
_asm sti

Because you read nvram in the timer ISR, nvram and the time/date are
both read from the RTC chip, it can not be interrupted.

EEPROM and RTC/nvram and LED5 using the same clock signal, so these functions
also can not be interrupted by other functions.

*/

#define BUFSIZE 1024       /* read/write buffer size */
#define SERVICE 10000      /* define the service port for Server */
#define SOCKETS 32         /* define the maximum number of sockets */
#define QLEN    SOCKETS-1  /* maximum connection queue length */

int es;       /* flag to run ES (service loop) */
fd_set rfds;  /* set of socket file descriptors for reading */

typedef struct socket_state {
  int                active;  /* socket is active */
  int                init;    /* socket just initiated */
  struct sockaddr_in sin;     /* client address */
} socket_state;
socket_state sst[SOCKETS];    /* sockets state table */

extern int errno;
extern long ET_TOUT;    /* basic timeout value */

int plugInSlot[8]={0,0,0,0,0,0,0,0};

void endTest(void);
int NetInit(int port);
int eraseFlag=0,needConfigIP=1;
void HotPlugFunction(void);
int HotPlug_GetEventInfo(void);
int HighRamMode;
extern int bNeedDisableHighRam;
void doServer(void);
int Ethernet_Connect(unsigned char *cRemoteIP,int iRemoteTCPPort,long lConnect_Timeout);
void killsockets(void);
int SlotNo=4;

unsigned char ID_8K_Table[256]=
{// 000,001 ,002 , 003, 004, 005, 006, 007, 008, 009, 00a, 00b, 00c, 00d, 00e, 00f
	255,255 ,255 , 17 ,255 , 24 ,255 ,255 , 14 ,255 ,255 ,255 ,255 , 90 , 91 , 92 ,	//00
	60 , 68 , 52 , 58 , 57 , 54 , 55 , 51 , 53 , 64 , 65 , 66 , 56 , 63 , 50 , 69 , //10
	172,112 ,142 ,142 ,255 ,114 ,144 , 41 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //20
	72 , 73 , 93 ,255 ,255 ,255 ,255 , 77 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //30
	255,255 ,114 ,255 , 94 , 94 , 54 ,255 , 48 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //40
	81 ,255 , 92 , 94 ,255 , 94 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //50
	255, 80 , 46 ,255 , 88 ,114 ,255 , 67 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //60
	255, 84 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //70
	255,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //80
	255,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //90
	255,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //a0
	255,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //b0
	255,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //c0
	255,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //d0
	255,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 , //e0
	255,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255   //f0
																                    //
};

    
//進行 Hot Swap 時加入。[2007,1,27] by Kevin    
unsigned char Check_8KID(int iSlot)
{   
    //每個 8K Module 的 ID 都是擺在 input 第一個位置。
    
    int index;
    index=inp(SlotAddr[iSlot]);
  //  printCom1("8K[%d] %02X\n",iSlot,index);
    return ID_8K_Table[index];
}    

/*************************************************************************
 * killsockets
 * clear, shutdown, and close all sockets
 *************************************************************************/
void killsockets()
{
  int i;
  FD_ZERO( &rfds );  /* clear FD set */

  for (i = 0; i < SOCKETS; i++) {
	if (sst[i].active) {       /* if socket lives, kill it */
	  shutdown( i, 0 );
	  closesocket( i );
	}
  }
}
/*************************************************************************
 * do_echo
 *
 * when client is connected, do echo here  or process message
 * Add the user process program here.
 *************************************************************************/
int do_echo( int skt )
{
  int i, cc, err=0;
  char buf[BUFSIZE];

  if (sst[skt].init)
  {
	sst[skt].init = 0;/* socket is just initiated */
	return err;
  }

   //err = cc = readsocket( skt, buf, strlen(buf)/*sizeof(buf)*/ );
  err = cc = recv( skt, buf, sizeof(buf),0 );// Read Socket data
  buf[cc] = '\0';
 if (err == 0)/* disconnected */
  {
	 shutdown( skt, 0 );//shutdown socket
	 closesocket( skt );//close socket
	 FD_CLR( skt, &rfds );//clear setting
	 sst[skt].active = 0;
	 return err;
  }

  if (err < 0)/* read error */
  {
	shutdown( skt, 0 );//shutdown socket
	closesocket( skt );//close socket
	FD_CLR( skt, &rfds );//clear setting
	sst[skt].active = 0;
	return err;
  }
//This send back is not necessary for every one
//_____________________________________________________
 err= send(skt,buf,cc,0);//echo string
 if(err < 0)
 {               /* write error */
	printf( "echo write error %d\n\r", err );
	shutdown( skt, 0 );
	closesocket( skt );
	FD_CLR( skt, &rfds );
	sst[skt].active = 0;
	return err;
 }
//_____________________________________________________
//force to terminal this program
 if (!strcmp("down", buf))
 {  /* shutdown echo server */
	es = 0;
	printf( "Server is Terminal\n\r");
	return err;
 }
// *************************************************************************/
 //err = User_Program(skt,buf,cc);
// *************************************************************************/
 return err;
}

int iSocket;
void InitPlug(void);
int main(void)
{
	char c;
	int i;
	InitLib();
	NetStart(); // for TCP IP Test
    InstallCom1(115200L,8,0,1);	
    InstallCom(1, 115200L,8, 0, 1);   
    InstallCom(2, 115200L,8, 0, 1);   
    InstallCom(3, 115200L,8, 0, 1); 
    InstallCom(4, 115200L,8, 0, 1);     
    InstallCom_DMA_0(115200,8,0,1);
    //printf("Start iPAC-8000 QC Program\n");
    //DisableWDT();
    InitPlug();
    InstallModulePlugIsr(HotPlugFunction);
    
    //NetInit(10000);
	if(bNeedDisableHighRam) {
		HighRamMode=GetHighRamMode();
		DisableHighRam();
	}
	

		        
    if(eraseFlag==1)
    {
    	for(i=0;i<7;i++)
    	{
    		printf("Erase flash %04X\n",(i+8)*0x1000);
    		//FlashErase((i+8)*0x1000); 
    	}
    }
    DisableWDT();
    for(;;)
    {
    	if(TestTicks()==1)
    		endTest();
    		
		if (IsCom1()) 
		{
		 	c=ReadCom1(); 
		 	if ((c=='q') || (c=='Q')) 
		 	{		 		
				endTest();		 			
		 	}
		 	
		}  
		if(bNeedDisableHighRam) {
			SetHighRam(HighRamMode);
		}   		          	
    
	}
 	
    
	
	return 0;	
}

void endTest(void)
{
			 		
	RestoreCom_1();
	RestoreCom_0();
	RestoreCom_2();
	RestoreCom_3();
	RestoreCom_4();
	Nterm();
	exit(0);
	return;
}

unsigned char cIP_Net[4];     
unsigned char cGateway_Net[4];     
unsigned char cMask_Net[4];     
unsigned char cIP_Net2[4];     
unsigned char cGateway_Net2[4];     
unsigned char cMask_Net2[4];  

int NetInit(int port)
{
  struct sockaddr_in ssin; /* client Internet endpoing address */
  int sin_len;             /* length of sockaddr_in */
  int s;                   /* master socket for listenning */
  int ss;                  /* slave socket got from accept */
  int type, protocol, err=0;

  int rc;                  /* return code of selectsocket */
  int i,ret,ver,SlotType;
  char str[2048];
//  unsigned long far *IntVectMain=(unsigned long far *)0x00000000L;

  struct timeval   seltime;
  
  	
	if(needConfigIP==1)
	{
		cIP_Net[0]=10;
		cIP_Net[1]=0;
		cIP_Net[2]=8;
		cIP_Net[3]=199;
		SetIp(cIP_Net);
		
		cIP_Net2[0]=10;
		cIP_Net2[1]=0;
		cIP_Net2[2]=8;
		cIP_Net2[3]=200;		
		SetIp2(cIP_Net2);
		
		cMask_Net[0]=255;
		cMask_Net[1]=255;
		cMask_Net[2]=255;
		cMask_Net[3]=0;
		SetMask(cMask_Net);

		cMask_Net2[0]=255;
		cMask_Net2[1]=255;
		cMask_Net2[2]=255;
		cMask_Net2[3]=0;	
		SetMask2(cMask_Net2);	
		
		cGateway_Net[0]=10;
		cGateway_Net[1]=0;
		cGateway_Net[2]=8;
		cGateway_Net[3]=254;
		SetGateway(cGateway_Net);

		cGateway_Net2[0]=10;
		cGateway_Net2[1]=0;
		cGateway_Net2[2]=8;
		cGateway_Net2[3]=254;
		SetGateway2(cGateway_Net2);
	}						
		
			
	GetIp(cIP_Net);
	printf("IP1[%d.%d.%d.%d]\n",cIP_Net[0],cIP_Net[1],cIP_Net[2],cIP_Net[3]);
	GetMask(cMask_Net);
	printf("Mask1[%d.%d.%d.%d]\n",cMask_Net[0],cMask_Net[1],cMask_Net[2],cMask_Net[3]);
	GetGateway(cGateway_Net);
	printf("Gateway1[%d.%d.%d.%d]\n",cGateway_Net[0],cGateway_Net[1],cGateway_Net[2],cGateway_Net[3]);
	
	printf("\n\n**********************\n\n");
	
	GetIp2(cIP_Net2);
	printf("IP2[%d.%d.%d.%d]\n",cIP_Net2[0],cIP_Net2[1],cIP_Net2[2],cIP_Net2[3]);
	GetMask2(cMask_Net2);
	printf("Mask2[%d.%d.%d.%d]\n",cMask_Net2[0],cMask_Net2[1],cMask_Net2[2],cMask_Net2[3]);
	GetGateway2(cGateway_Net2);
	printf("Gateway2[%d.%d.%d.%d]\n",cGateway_Net2[0],cGateway_Net2[1],cGateway_Net2[2],cGateway_Net2[3]);	
	
	
	  type = SOCK_STREAM;  /* TCP/IP */
	  protocol = 0;        /* always 0 */
	  err = s = socket( PF_INET, type, protocol );
	  if (s < 0)
	  {
		printf( "can't create socket! error %d\n\r", err );
		Nterm();
		return err;
	  }
		printf( "create socket seccessful!\n\r");
	  /********************************
	   * addressing for master socket *
	   ********************************/
	  memset( &sst[s].sin, 0, sizeof(sst[s].sin) ); /* bzero is a unix system call */
	  sst[s].sin.sin_family = AF_INET;
	  sst[s].sin.sin_addr.s_addr = 0; /* INADDR_ANY is a 32bits zero value */
	  sst[s].sin.sin_port = htons( SERVICE );
	
	  /*******************
	   * bind the socket *
	   *******************/
	  err = bind( s, (struct sockaddr *)&sst[s].sin, sizeof(sst[s].sin) );
	  if (err < 0)
	  {
		printf( "can't bind to port %d, error %d\n\r", SERVICE, err );
		closesocket( s );
		Nterm();
		return err;
	  }
		printf( "bind to port %d seccessful!\n\r",SERVICE);
	
	  /******************
	   * make listening *
	   ******************/
	  err = listen( s, QLEN );
	  if (type == SOCK_STREAM && err < 0)
	  {
		closesocket( s );
		Nterm();
		return err;
	  }
		printf( "Now Listening!\n\r");
	
	  /**********
	   * select *
	   **********/
	  FD_ZERO( &rfds );
	  es = 1;
	  for (i = 0; i < SOCKETS; i++)
	  {
		sst[i].active = 0;
		sst[i].init   = 0;
	  }
	  sst[s].active = 1;  /* master socket is active */
	  sin_len = sizeof( ssin );
	  seltime.tv_sec=0;
	  seltime.tv_usec=0;
	 	
	  Portinit( "*" ); 
	printCom1("Connect to server.\n\r");	    
      iSocket=Ethernet_Connect("10.0.8.118", 10000, 2000);//TCP port=10000, Timeout=2000 ms.
      if(iSocket>=0)
      {
         printCom1("Connect ok, socket=%d\n\r", iSocket);
         strcpy(str,"19dddddddddd");
         err=send( iSocket, str, strlen(str), 0 );//send connection message to client
      }
      else
      {
         printCom1("Connect error %d.\n\r",iSocket);
      }	  
	  
	  return 0;
}
  struct sockaddr_in ssin; /* client Internet endpoing address */
  int sin_len;             /* length of sockaddr_in */
  int s;                   /* master socket for listenning */
  int ss;                  /* slave socket got from accept */
  int type, protocol, err=0;
char Message1[]="connected successful.";
void doServer(void)
{
  


  int rc;                  /* return code of selectsocket */
  int i,ret,ver,SlotType;

//  unsigned long far *IntVectMain=(unsigned long far *)0x00000000L;

  struct timeval   seltime;
  seltime.tv_sec=0;
  seltime.tv_usec=0;  
   // printf( "11111\n\r" );
	for (i = 0; i < SOCKETS; i++)
	{
		if (sst[i].active)
		{  /* re-join active sockets */
			FD_SET( i, &rfds );
		}
	}
	rc = selectsocket( SOCKETS, &rfds, NULL, NULL, &seltime  );//check the socket come in
	if (rc < 0)
	{
	   printf( "selectsocket error %d\n\r", rc );
	   return;
	}
	//if( !rc )//no socket come in , continue waitting
	//   continue;
	//some sockets come in
	//printf( "222222\n\r" );
	for (i = 0; i < SOCKETS; i++)
	{  /* scan all possible sockets */
		if (FD_ISSET(i, &rfds))
		{
			if (i == s)
			{  /* master socket */
				memset( &ssin, 0, sizeof(ssin) );
				err = ss = accept( s, (struct sockaddr *)&ssin, &sin_len );
				if (err < 0)
				{
					printf( "accept error %d\n\r", err );
					return;
				}
				else
				{
					printf( "accept ok %d\n\r", err );
				}
				//err=send( ss, Message1, strlen(Message1), 0 );//send connection message to client
				FD_SET( ss, &rfds );//set the setting
				sst[ss].active = 1;//active
				sst[ss].init   = 1;
				memcpy( &sst[ss].sin, &ssin, sin_len );
			}
			else
			{       /* slave socket */
				do_echo( i );//The client connection is accept and distribution to socket i
							//So the user can read the message(may be command string or other)
							//from the socket i.
							//remember each clinet connection If it is accept by this server
							//will cause one socket. So the maximun socket (connection) is 31.
							//In the other word, This server can be connected by 31 client maximun.
							//for the detail to read string,please refer to function "do_echo()".
			}
		}
	}
	//printf( "33333333\n\r" );
  /* service loop */
  //killsockets();//will end the program
 // Nterm();//close ethernet
}	


int Ethernet_Connect(unsigned char *cRemoteIP,int iRemoteTCPPort,long lConnect_Timeout)
{
    /*
    cRemoteIP: Remote IP address, for example: "192.168.255.1"
    iRemoteTCPPort: Remote TCP port number
    lConnect_Timeout: timeout (unit: ms)
    
    Return: >=0  :ok, return socket number
             <0  :error, return -1.
    */
    extern int errno;
    int iSocketNumber,iRet;
    unsigned long lStartTimeTick;
    int iTemp;
    
    struct sockaddr_in sktRemoteServer;  
    
    iSocketNumber=socket(PF_INET,SOCK_STREAM,0);   
    if(iSocketNumber>=0)
    {    
        YIELD();
        memset(&sktRemoteServer, 0, sizeof(sktRemoteServer)); /* bzero is a unix system call */
        sktRemoteServer.sin_family = AF_INET;          
        sktRemoteServer.sin_addr.s_addr = inet_addr(cRemoteIP);
        sktRemoteServer.sin_port = htons( iRemoteTCPPort );    
        YIELD();
        
        SOCKET_NOBLOCK(iSocketNumber);   /*Set Non-blocking mode*/
        ET_TOUT=300L;  //300ms, ET_TOUT has less than 800ms (WatchDog reboot time)
        iRet=connect(iSocketNumber, (struct sockaddr *)&sktRemoteServer, sizeof(sktRemoteServer));
        if(iRet) /* unsuccessful connection not 0 */
        {       
            lStartTimeTick=GetTimeTicks();
            
            if(errno==EINPROGRESS)
            {
                while((GetTimeTicks()-lStartTimeTick)<lConnect_Timeout)
                {
                   // RefreshWDT();
                    YIELD();
                    if(SOCKET_ISOPEN(iSocketNumber)) 
                    {
                        ET_TOUT=300L;
                        iTemp=iSocketNumber;
                        break; 
                    }
                    else
                    {
                        //printCom1("Open socket error\n\r");
                        iTemp=-1;
                    }
                }
                if(iTemp==-1)
                    closesocket(iSocketNumber);    
                iSocketNumber=iTemp;
            }
            else
            {
                closesocket(iSocketNumber);
                iSocketNumber=-2; 
            }
        }
    }
    else
        iSocketNumber=-3;

    if(iSocketNumber>=0)
    {
        SOCKET_BLOCK(iSocketNumber);
        return iSocketNumber;     
    }
    else
    {
        //RefreshWDT(); 
        return iSocketNumber;
    }
} 

unsigned long t6;
int Ethernet_Receive(int iSocket,char *cInBuf,int iMaxLen,int iTimeout)
{
    /*
    iSocket: Socket number
    *cInBuf: Buffer to store received data
    iMaxLen: Max length to receive
    iTimeout: timeout to receive data (unit: ms)
    
    Return:  >0 : ok, return received data length.
            <=0 : error, doesn't receive any data.
    */
    int iLength;
    char str[2048];
    
    SOCKET_RXTOUT(iSocket, iTimeout); //set the receive timeout for a connection//
    iLength= recv(iSocket,cInBuf,iMaxLen,0); //MSG_OOB
    
    SOCKET_BLOCK(iSocket);
    YIELD();
    if (iLength>=0)
    {
        cInBuf[iLength]=0;
        printf("cInBuf[%d] %s \n",iLength,cInBuf);
		iLength=0;
			sprintf(str,"19dddddddddd");
    		err=send( iSocket, str, strlen(str), 0 );//send connection message to client 
    		YIELD();
    		printf("send[%d] %s \n",err,str);      		
    }
     
    return iLength;
}

//unsigned long plugEventTime;

static unsigned char prePlug=0;
static unsigned char curPlug=0;
static unsigned char slotPlug;
//static unsigned char ioChanged=0;

unsigned long plugStableTime=1000;
unsigned long plugInTime[8]={0,0,0,0,0,0,0,0};
unsigned long plugOutTime[8]={0,0,0,0,0,0,0,0};

void HotPlugFunction(void)
{
    /*
    When plugin or plug-out a module, the function is called.
    GetInfoOfModulePlugEvent is used to get basic and necessary information.
    UpdateModulePlugEvent is used to finish further module detection and recognization.
    */
    //plugEventTime= GetTimeTicks();
    printf("\nHotPlugFunction\n");
    HotPlug_GetEventInfo();
    
}


int HotPlug_GetEventInfo(void)
{
    /*
    Get information of module plug event.
    
    Following global variables will be updated and then used in UpdateModulePlugEvent.
        1. gcOldModule
        2. gcCurrentModule
        3. gcChangedModule
        4. giPlugSlot
        5. giPlugAction
        6. glPlugTimeTicks
        
    return: 0=no event
            1=event happend.    
    */
    unsigned char mask[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
    int slot,i;
    unsigned char changedSlot,plugIn,plugOut,iReset,k8;
    curPlug=~(inp(0x9004));
	//printf("Plug %02X\n",curPlug);
	
	if(curPlug!=prePlug)
	{
		
		
	    changedSlot=prePlug^curPlug;
	    plugIn  =changedSlot&curPlug;
	    plugOut =changedSlot&prePlug;
	    
	    //插入 slot 0, changedSlot will be 1
	   // printf("\nchanged %02X  In %02X Out %02X \n",changedSlot,plugIn,plugOut);
	    
	    for(slot=0;slot < SlotNo; slot++)
	    {
	        if(mask[slot]==changedSlot)
	        {
	        //Update to the global variable;
		        if(plugOut)
		        {
		            //giPlugSlot=slot;
		           // giPlugAction=0; //Plugged Out
		           	slotPlug=slot;
                	ModuleName[slotPlug] = 0xFF;
                	ModuleType[slotPlug] = 0;
                	ModuleFullName[slotPlug][0]=0;
                	
                	
                	iReset=inp(0x9004); //0x9004=Insert Pin, 0=module insert, 1=no module.
                	outp(0x901B,iReset);//0x901B=Reset Pin,1=reset, 0=don't reset.	
                	plugInSlot[slot]=0;
                	//Enqueue(slotPlug, Q);	           
	            	printf("slot[%d] plugOut Flag \n",slotPlug);
		            break;
		        }
		        if(plugIn)
		        {
		            //giPlugSlot=slot;
		            //giPlugAction=1; //Plugged In
		           // ioChanged=1;
		           	plugInTime[slot]=GetTimeTicks();
		            slotPlug=slot;	
		            outp(0x901B,inp(0x9004));//0x901B=Reset Pin,1=reset, 0=don't reset.
		            plugInSlot[slotPlug]=1;
		            
		            printf("plugIn[%d]\n",slotPlug);
		            	
		          //  Enqueue(slotPlug, Q);
		          //  printf("slot[%d] plugIn flag %u\n",slotPlug,AutoConfigFlag);
		            //Delay(700);
		            //Add87kCmd_0(slot,-1,"$00M",DoUpdateConfig);
		            //printf("slot[%d] plugIn\n",slot);
		            //Add87kCmd_0(slot,-1,"$00M",DoUpdateConfig);
		            break;
		        }
		        
		    }
	    } 	
	    prePlug=curPlug;
	    //ShowPlug();	
		//UpdateSlotIO();
	}
    return 0;
}

void InitPlug(void)
{
	//Q = CreateQueue(SlotNo);	
	int s,i;
	unsigned char mask[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
	unsigned short cnt;
	unsigned char k8;

	prePlug=curPlug=~(inp(0x9004)); // prePlug 紀錄先前插入底板模組的狀態,他只紀錄有哪些slot 有插入模組,至於插哪些模組他不知道
	for(i=0;i<8;i++)
	{
		if(curPlug & mask[i])
			plugInSlot[i]=1;
		else
			plugInSlot[i]=0;
	}
	printf("plug status %02X\n",prePlug);
	// curPlug can know which slot have detect an I/O, so I must use this to recognize the valid I/O
	// deal with detected I/O only.

	
}