/* Access I/O port for CC/NET */

#include    <stdio.h>
#include    <sys/io.h>
/*#include     <asm/io.h>*/ 
#include	<string.h>
#include	"ErrCode.h"

//-----Test result place----
#define LOGDIR	"/tmp/"
#define LOGEXT	".log"

//-----I/O Address-----
#define BASE_ADDR	0xe800

#define ADDR_TX_LDT	0x00	//lower 32bitData
#define ADDR_TX_UDT	0x04	//upper 32bitData
#define ADDR_TX_CTL	0x08	//Control
#define ADDR_TX_STA 0x0C	//Status
#define ADDR_TX_MAR	0x10	//Master mode Address
#define ADDR_TX_FPR	0x14	//Frame preset
#define ADDR_TX_FCR	0x18	//Frame count register
#define ADDR_TX_CNT	0x1C	//FIFO count

#define ADDR_RX_LDT	0x20	//lower 32bitData
#define ADDR_RX_UDT	0x24	//upper 32bitData
#define ADDR_RX_CTL	0x28	//Control
#define ADDR_RX_STA 0x2C	//Status
#define ADDR_RX_MAR	0x30	//Master mode Address
#define ADDR_RX_FPR	0x34	//Frame preset
#define ADDR_RX_FCR	0x38	//Frame count register
#define ADDR_RX_CNT	0x3C	//FIFO count

#define ADDR_SYSTEM	0x40	//system



//-----64bit frame-----
struct FRAME
{
	unsigned long code, data;
};


//-----Dataway status-----
struct DATAWAYSTAT
{
	unsigned char N;
	unsigned char A;
	unsigned char F;
	unsigned char Q;
	unsigned char X;
	unsigned char Z;
	unsigned char C;
	unsigned char I;
	unsigned char B;
};


/* Error log file creation */
int create_logfile(char* pszFName, char* pszMsg)
{
	char szPathNameExt[0xFF];
	memset(szPathNameExt, 0x00, sizeof(szPathNameExt) );
	
	if ( strlen(LOGDIR)+strlen(pszFName)+strlen(LOGEXT)+1 > 0xFF ) return ERR_FNAME;
	strcpy( szPathNameExt, LOGDIR );
	strcat( szPathNameExt, pszFName );
	strcat( szPathNameExt, LOGEXT );
	
	FILE* fp;
	fp = fopen(szPathNameExt, "a");
	fprintf( fp, pszMsg );
	fclose(fp);
	
	return NO_ERR;
}


/* for TestModule... (special function) */
int DecTM(struct DATAWAYSTAT* dataway, unsigned long data)
{
	dataway->N = (data & 0x0000001F) +1;
	dataway->F = (data & 0x000003E0)>>5;
	dataway->A = (data & 0x00003C00)>>10;
	dataway->Q = (data & 0x00010000)>>16;
	dataway->X = (data & 0x00020000)>>17;
	dataway->Z = (data & 0x00040000)>>18;
	dataway->C = (data & 0x00080000)>>19;
	dataway->I = (data & 0x00100000)>>20;
	dataway->B = (data & 0x00200000)>>21;
	
	return 0;
}


//-------I/O address directly access--------
/* dump */
int dump_reg()
{
	printf("Tx Data(Lower)\t0x%08x", inl(BASE_ADDR+ADDR_TX_LDT) );
	printf("Tx Data(Upper)\t0x%08x", inl(BASE_ADDR+ADDR_TX_UDT) );
	printf("Tx Control reg.\t0x%08x", inl(BASE_ADDR+ADDR_TX_CTL) );
	printf("Tx Status reg.\t0x%08x", inl(BASE_ADDR+ADDR_TX_STA) );
	printf("Tx Master Mode addr.\t0x%08x", inl(BASE_ADDR+ADDR_TX_MAR) );
	printf("Tx Frame Preset cnt.\t0x%08x", inl(BASE_ADDR+ADDR_TX_FPR) );
	printf("Tx Frame Count reg.\t0x%08x", inl(BASE_ADDR+ADDR_TX_FCR) );
	printf("Tx FIFO Counter\t0x%08x", inl(BASE_ADDR+ADDR_TX_CNT) );
	
	printf("Rx Data(Lower)\t0x%08x", inl(BASE_ADDR+ADDR_RX_LDT) );
	printf("Rx Data(Upper)\t0x%08x", inl(BASE_ADDR+ADDR_RX_UDT) );
	printf("Rx Control reg.\t0x%08x", inl(BASE_ADDR+ADDR_RX_CTL) );
	printf("Rx Status reg.\t0x%08x", inl(BASE_ADDR+ADDR_RX_STA) );
	printf("Rx Master Mode addr.\t0x%08x", inl(BASE_ADDR+ADDR_RX_MAR) );
	printf("Rx Frame Preset cnt.\t0x%08x", inl(BASE_ADDR+ADDR_RX_FPR) );
	printf("Rx Frame Count reg.\t0x%08x", inl(BASE_ADDR+ADDR_RX_FCR) );
	printf("Rx FIFO Counter\t0x%08x", inl(BASE_ADDR+ADDR_RX_CNT) );

	printf("System reg.\t0x%08x", inl(BASE_ADDR+ADDR_SYSTEM) );
	
	return NO_ERR;
}


/*Tx a frame */
int put_frame(struct FRAME cmd)
{
	if ( iopl(3) )	return ERR_PRIV;
	
	outl( cmd.data, BASE_ADDR+ADDR_TX_LDT );
	outl( cmd.code, BASE_ADDR+ADDR_TX_UDT );
	
	unsigned char wcnt=0;
	while (++wcnt)
	{
		if (inl(BASE_ADDR+ADDR_TX_STA)&0x00000001 )	return NO_ERR;
		if (inl(BASE_ADDR+ADDR_TX_STA)&0x00000002 ) break;
	}

	return ERR_TXTOUT;
}


/* Rx a frame */
int get_frame(struct FRAME* rpl)
{
	if ( iopl(3) )	return ERR_PRIV;

	if ( (inl(BASE_ADDR+ADDR_RX_CNT)&0xffffff) < 2 ) return ERR_EMP;

	rpl->data = inl( BASE_ADDR+ADDR_RX_LDT );
	rpl->code = inl( BASE_ADDR+ADDR_RX_UDT );
	
//	if ( (inl(BASE_ADDR+ADDR_RX_STA)&0x00000001)==0 ) return ERR_EMP;
	

	return NO_ERR;
}





