/*========================================================================
**                       BME Debug Utilities
**      bmestat.c - show status of bme hardware 
**
**      Copyright (c) 2001, Ikanos Communications
**  This Ikanos Communication Inc. proprietary information must be
**  maintained in the strictest of confidence and may not be copied,
**  disclosed,or used without the express prior written consent of an
**  officer of Ikanos Communication Inc.
**=======================================================================*/

#include <stdio.h>
#include <stdlib.h>
#include "bme.h"
#include "bme_app.h"
#include "mem.h"

#include "bmeConfig.h"
#undef FMC_ADR_TX_STATUS_AND_CONFIGS    // mem.h redefines this - should 
					// remove it from mem.h & just use 
					// the define in frmhal.h 

#include "include/bitmask.h" 
#define   C_CODE    1 

#include "frmhal.h" 
#include "dfrmhal.h" 
#include "bmestat.h" 
#include "hostType.h" 

#define disp printf 

int host_mode_flag;

void
BmeTxStatus( int chNum, int dbgLevel)  
// shows BME TX Path status for debugging 
//   chNum:     ch for which status to be shown
//   dbgLevel:  controls how much info is shown
// currently dbgLevel is not used - to be implemented 
{
#if CPU == PPC860					
    if (host_mode_flag)
	initHostIO(0x2, BME_BASE_ADDR); 
#endif 

    // BmeTniStatus( chNum, dbgLevel);
    BmeXfifoStatus( chNum, dbgLevel); 
    BmeFmcStatus( chNum, dbgLevel); 
    BmeYfifoStatus( chNum, dbgLevel); 
    // BmeMapperStatus( chNum, dbgLevel); 
    BmeZfifoStatus( chNum, dbgLevel); 
    // BmeVbusTxStatus( chNum, dbgLevel); 
}

void
btx( int chNum) 
// Short Fn name ver of BmeTxStatus to reduce typing on console 
{
    BmeTxStatus( chNum, 0); 
}

void
BmeRxStatus( int chNum, int dbgLevel)  
// shows BME RX Path status for debugging 
//   chNum:     ch for which status to be shown
//   dbgLevel:  controls how much info is shown
// currently dbgLevel is not used - to be implemented 
{
#if CPU == PPC860					
    if (host_mode_flag)
	initHostIO(0x2, BME_BASE_ADDR);
#endif 

    // BmeVbusRxStatus( chNum, dbgLevel); 
    BmeAfifoStatus( chNum, dbgLevel); 
    // BmeRmcStatus( chNum, dbgLevel); 
    // BmeDmapStatus( chNum, dbgLevel); 
    BmeBfifoStatus( chNum, dbgLevel); 
    BmeDmcStatus( chNum, dbgLevel); 
    BmeCfifoStatus( chNum, dbgLevel); 
    // BmeRniStatus( chNum, dbgLevel); 
}

void
brx( int chNum) 
// Short Fn name ver of BmeRxStatus to reduce typing on console 
{
    BmeRxStatus( chNum, 0); 
}


//---------- Receive Path Status Functions ------------------------

void 
BmeAfifoStatus( int chNum, int dbgLevel) 
{
    BmeRdAfifoState( chNum, &Afifo);  
    BmeShowFifoStatus( chNum, "AFIFO", &Afifo); 
}

void 
BmeRdAfifoState( int chNum, BmeFifo_t *fifo) 
{
    u32  ca, cc, cd;  // cntxt regs a,c,d 

    ca = readPIO_SingleRegChannel((int *)CAFT_A, chNum);
    cc = readPIO_SingleRegChannel((int *)CAFT_C, chNum);
    cd = readPIO_SingleRegChannel((int *)CAFT_D, chNum);

    fifo->size = 128 << ((ca >> 3) & _4b); 
    fifo->start = (ADDRESS_AFIFO + (((ca >> 7) & _10b) << 7));
    fifo->rPtr = cc & _17b; 
    fifo->wPtr = cd & _17b; 
    // assuming no over/under flow, foll eq will calc used bytes 
    if (fifo->wPtr >= fifo->rPtr)
	fifo->used = fifo->wPtr - fifo->rPtr;
    else
	fifo->used = fifo->size - (fifo->rPtr - fifo->wPtr);
	
    fifo->wrap = 0; 
    if (cc & _bit17) 
        fifo->wrap |= 2;  // rd ptr wrapped 
    if (cd & _bit17) 
        fifo->wrap |= 1;  // wrt ptr wrapped 

    fifo->cfg = ca & _3b; 
    fifo->err = (ca >> 17) & _3b; 
    fifo->regA = ca; 
    fifo->regB = 0; 
    fifo->regC = cc; 
    fifo->regD = cd; 
}

void
BmeShowFifoStatus( int chNum, char *fifoName, BmeFifo_t *fifo) 
{
    if (fifo->err) { 

	disp( "\tERROR in %s :", fifoName); 

	if (fifo->err & 0x1) 
	    disp( " Under/Overflow_Err"); 
	if (fifo->err & 0x2) 
	    disp( " NotValid_Err"); 
	if (fifo->err & 0x4) 
	    disp( " SrcDest_Err");

	disp( " (%01x)\n\t", fifo->err); 
    } 

    disp( "\t%s  ch# %d  used= %05x  rd= %01x,%05x  wr= %01x,%05x\n", 
		fifoName, chNum, 
		fifo->used,  
		(fifo->wrap >> 1) & 0x1, fifo->rPtr, 
		fifo->wrap & 0x1, fifo->wPtr); 

    disp( "\t\tcfg= %01x  size= %05x  start= %08x\n", 
	   fifo->cfg, fifo->size, fifo->start);
}
       
void 
BmeBfifoStatus( int chNum, int dbgLevel) 
{
    BmeRdDMfifoState( chNum, &DMfifo);  
    BmeShowFifoStatus( chNum, "DMFIFO", &DMfifo); 

    BmeRdBFfifoState( chNum, &BFfifo);  
    BmeShowFifoStatus( chNum, "BFFIFO", &BFfifo); 

    BmeRdBIfifoState( chNum, &BIfifo);  
    BmeShowFifoStatus( chNum, "BIFIFO", &BIfifo); 

}

void 
BmeRdDMfifoState( int chNum, BmeFifo_t *fifo) 
{
    u32  ca; 

    ca = readPIO_SingleRegChannel((int *)CDMT, chNum);

    fifo->size = 8192; 			   // fixed size 
    fifo->start = (ADDRESS_BFIFODEMAPPER); // fixed loc for all ch. 
    fifo->rPtr = (ca >> 3) & _13b; 
    fifo->wPtr = (ca >> 17) & _13b; 
    if (fifo->wPtr >= fifo->rPtr)
	fifo->used = fifo->wPtr - fifo->rPtr;
    else
	fifo->used = fifo->size - (fifo->rPtr - fifo->wPtr);
	
    fifo->wrap = 0; 
    if (ca & _bit16) 
        fifo->wrap |= 2; 
    if (ca & _bit30) 
        fifo->wrap |= 1; 

    fifo->cfg = ca & _3b; 
    fifo->err = (ca >> 31) & _1b; 
    fifo->regA = ca; 
    fifo->regB = 0; 
    fifo->regC = 0; 
    fifo->regD = 0; 
}

void 
BmeRdBFfifoState( int chNum, BmeFifo_t *fifo) 
{
    u32  ca, cb; 

    ca = readPIO_SingleRegChannel((int *)CBFT_A, chNum);
    cb = readPIO_SingleRegChannel((int *)CBFT_B, chNum);

    // fifo->size = (((ca >> 3) & _3b) + 1) << 7; 
    fifo->size = 128 << ((ca >> 3) & _3b); 
    fifo->start = (ADDRESS_BFIFOFAST + (((ca >> 6) & _6b) << 7));
    fifo->rPtr = (cb & _13b); 
    fifo->wPtr = ((cb >> 14) & _13b); 
    if (fifo->wPtr >= fifo->rPtr)
	fifo->used = fifo->wPtr - fifo->rPtr;
    else
	fifo->used = fifo->size - (fifo->rPtr - fifo->wPtr);
	
    fifo->wrap = 0; 
    if (cb & _bit13) 
        fifo->wrap |= 2; 
    if (cb & _bit27) 
        fifo->wrap |= 1; 

    fifo->cfg = ca & _3b; 
    fifo->err = (ca >> 12) & _3b; 
    fifo->regA = ca; 
    fifo->regB = cb; 
}

void 
BmeRdBIfifoState( int chNum, BmeFifo_t *fifo) 
{
    u32  ca, cb, cc, cd;  

    ca = readPIO_SingleRegChannel((int *)CBIT_A, chNum);
    cb = readPIO_SingleRegChannel((int *)CBIT_B, chNum);
    cc = readPIO_SingleRegChannel((int *)CBIT_C, chNum);
    cd = readPIO_SingleRegChannel((int *)CBIT_D, chNum);

    // fifo->size = (((ca >> 3) & _4b) + 1) << 7; 
    fifo->size = 128 << ((ca >> 3) & _4b); 
    fifo->start = (ADDRESS_BFIFOINTERLEAVE + (((ca >> 7) & _10b) << 7));
    // fifo->rPtr = (cb & _16b) | ((cc & 0x1) << 16); 
    // fifo->wPtr = ((cb >> 16) & _16b) | ((cc & 0x2) << 16); 
    fifo->rPtr = (cb & _16b); 
    fifo->wPtr = ((cb >> 16) & _16b); 
    if (fifo->wPtr >= fifo->rPtr)
	fifo->used = fifo->wPtr - fifo->rPtr;
    else
	fifo->used = fifo->size - (fifo->rPtr - fifo->wPtr);
	
    fifo->wrap = 0; 
    if (cc & _bit0) 
        fifo->wrap |= 2; 
    if (cc & _bit1) 
        fifo->wrap |= 1; 

    fifo->cfg = ca & _3b; 
    fifo->err = (cc >> 2) & _3b; 
    fifo->regA = ca; 
    fifo->regB = cb; 
    fifo->regC = cc; 
    fifo->regD = cd; 
}

void
BmeDmcStatus( int chNum, int dbgLevel) 
{
    u16  buf[128]; 
    int  i; 

	if (host_mode_flag)
		initHostIO(0x2, BME_BASE_ADDR);
    
	readPIO_Regs( (int *)(ADDRESS_DEMAPPERCPU_DCACHE_PIO+DMC_ADR_TotalPktsRecd),
		   2, (int *)buf); 
    
    disp("\tDMC TotalPkts= %d  AclPtr= %04x  CurCh=%d  IdleCtr=%d\n", 
		  buf[0], buf[1], buf[2], buf[3]); 

    readPIO_Regs( (int *)(ADDRESS_DEMAPPERCPU_DCACHE_PIO+DMC_ADR_PKT_HDR_READ_IN), 
		   16/4, (int *)buf); 

    disp("\t  PktHdr:"); 
    for (i=0; i < 16/2; i++) 
	 disp( " %04x", buf[i]); 

    disp("\n"); 
}


void
BmeDmcCmdLog( ) 
// shows dmc cmd log 
{
    u16  buf[DMC_RX_ACL_CMD_BUF_SIZE/2]; 
    u16  aclCmdAdr, adr; 
    int  i, bufNum, curBuf, bytesInCurBuf; 

	if (host_mode_flag)
		initHostIO(0x2, BME_BASE_ADDR);
	
    readPIO_Regs( (int *)(ADDRESS_DEMAPPERCPU_DCACHE_PIO+DMC_ADR_TotalPktsRecd),
		   2, (int *)buf); 
    
    disp("\tDMC TotalPkts= %d  AclPtr= %04x  CurCh=%d  IdleCtr=%d\n", 
		  buf[0], buf[1], buf[2], buf[3]); 

    aclCmdAdr = buf[1]; 
    curBuf = (aclCmdAdr - DMC_ADR_RX_ACL_CMD_BUFS) / DMC_RX_ACL_CMD_BUF_SIZE;
    bytesInCurBuf = (aclCmdAdr - (curBuf * DMC_RX_ACL_CMD_BUF_SIZE)); 

    bufNum = 0; 
    adr = DMC_ADR_RX_ACL_CMD_BUFS; 

    while (bufNum < DMC_RX_ACL_CMD_BUF_NUM) { 
	if ((adr >= 16*1024) || ((adr +  DMC_RX_ACL_CMD_BUF_SIZE) >= 16*1024)) { 
	    disp( "\t*** ERROR in DmcCmdLog\n");
	    break;
	}
	readPIO_Regs( (int *)(ADDRESS_DEMAPPERCPU_DCACHE_PIO+adr), 
			  DMC_RX_ACL_CMD_BUF_SIZE/4, (int *)buf); 

        disp("\t  ----  DMC CmdBuf %d  --------\n", bufNum); 

        for (i=0; i < DMC_RX_ACL_CMD_BUF_SIZE/2; i+= 4) { 

	     if ((bufNum == curBuf) && (i >= bytesInCurBuf/2)) 
	         break; 
	     disp( "\t\t%04x  %04x  %04x  %04x\n", 
				buf[i], buf[i+1], buf[i+2], buf[i+3]); 
	     if (buf[i] == 0xFFFF) 
	         break; 
        } 
	bufNum++ ; 
	adr += DMC_RX_ACL_CMD_BUF_SIZE; 
    } 

    disp("\t  ----------------------------\n"); 
}

void 
BmeRdCfifoState( int chNum, BmeFifo_t *fifo) 
{
    u32  ca, cb; 

    if ((chNum & 0x1) == 0) { 
        ca = readPIO_SingleRegChannel((int *)CCFT0_A, chNum);
        cb = readPIO_SingleRegChannel((int *)CCFT0_B, chNum);
        fifo->start = (ADDRESS_CFIFOBANKA + (((ca >> 6) & _7b) << 7));
    } else { 
        ca = readPIO_SingleRegChannel((int *)CCFT1_A, chNum);
        cb = readPIO_SingleRegChannel((int *)CCFT1_B, chNum);
        fifo->start = (ADDRESS_CFIFOBANKB + (((ca >> 6) & _7b) << 7));
    } 

    // fifo->size = (((ca >> 3) & _3b) + 1) << 7; 
    fifo->size = 128 << ((ca >> 3) & _3b); 
    fifo->rPtr = (cb & _14b); 
    fifo->wPtr = ((cb >> 15) & _14b); 
    if (fifo->wPtr >= fifo->rPtr)
	fifo->used = fifo->wPtr - fifo->rPtr;
    else
	fifo->used = fifo->size - (fifo->rPtr - fifo->wPtr);
	
    fifo->wrap = 0; 
    if (cb & _bit14) 
        fifo->wrap |= 2; 
    if (cb & _bit29) 
        fifo->wrap |= 1; 

    fifo->cfg = ca & _3b; 
    fifo->err = (ca >> 12) & _3b; 
    fifo->regA = ca; 
    fifo->regB = cb; 
}

void 
BmeCfifoStatus( int chNum, int dbgLevel) 
{
    BmeRdCfifoState( chNum, &CFfifo);  
    BmeShowFifoStatus( chNum, "CFFIFO", &CFfifo); 

}

//---------- Transmit Path Status Functions ------------------------

void 
BmeXfifoStatus( int chNum, int dbgLevel) 
{
    BmeRdXFfifoState( chNum, &XFfifo);  
    BmeShowFifoStatus( chNum, "XFFIFO", &XFfifo); 

    // BmeRdXIfifoState( chNum, &XIfifo);  
    // BmeShowFifoStatus( chNum, "XIFIFO", &XIfifo); 
}

void 
BmeYfifoStatus( int chNum, int dbgLevel) 
{
    // BmeRdYfifoState( chNum, &YFfifo);  
    // BmeShowFifoStatus( chNum, "YFFIFO", &YFfifo); 
    //
    
    BmeRdYIfifoState( chNum, &YIfifo);  
    BmeShowFifoStatus( chNum, "YIFIFO", &YIfifo); 
}

void 
BmeZfifoStatus( int chNum, int dbgLevel) 
{
    BmeRdZfifoState( chNum, &Zfifo);  
    BmeShowFifoStatus( chNum, "ZFIFO", &Zfifo); 
}

void
BmeFmcStatus( int chNum, int dbgLevel) 
{
    u16  buf[128]; 
    FrmTxStatus_t  *stat; 
    u16  aclPtr; 
    int  n; 

    readPIO_Regs( (int *)(ADDRESS_FRAMER_DCACHE_PIO+FmcStatusAdr(chNum)), 
		   64/4, (int *)buf); 
    stat = (FrmTxStatus_t  *)buf; 

    readPIO_Regs( (int *)(ADDRESS_FRAMER_DCACHE_PIO+FMC_ADR_frmAclCmdAdr), 
		   1, (int *)&n); 
    aclPtr = (n >> 16) & 0xFFFF; 

    disp("\tFMC  ch# %d  FrmNum= %d  State= %d  AclPtr= %04x  lastChgFrm=%d\n", 
		  chNum, stat->fullFrmNum, stat->chState, 
		  aclPtr, stat->lastStateChgFrmNum);
}

void 
BmeRdXFfifoState( int chNum, BmeFifo_t *fifo) 
{
    u32  ca, cb; 

    ca = readPIO_SingleRegChannel((int *)XFIFOF_CXFT_A, chNum);
    cb = readPIO_SingleRegChannel((int *)XFIFOF_CXFT_B, chNum);
    fifo->start = (ADDRESS_XFIFO_FAST + (((ca >> 6) & _7b) << 7));

    fifo->size = 128 << ((ca >> 3) & _3b); 
    fifo->rPtr = (cb & _14b); 
    fifo->wPtr = ((cb >> 15) & _14b); 
    if (fifo->wPtr >= fifo->rPtr)
	fifo->used = fifo->wPtr - fifo->rPtr;
    else
	fifo->used = fifo->size - (fifo->rPtr - fifo->wPtr);
	
    fifo->wrap = 0; 
    if (cb & _bit14) 
        fifo->wrap |= 2; 
    if (cb & _bit29) 
        fifo->wrap |= 1; 

    fifo->cfg = ca & _3b; 
    fifo->err = (ca >> 13) & _3b; 
    fifo->regA = ca; 
    fifo->regB = cb; 
}

void 
BmeRdYIfifoState( int chNum, BmeFifo_t *fifo) 
{
    u32  ca, cb, cc, cd; 

    ca = readPIO_SingleRegChannel((int *)YFIFO_CYFT_A, chNum);
    cb = readPIO_SingleRegChannel((int *)YFIFO_CYFT_B, chNum);
    cc = readPIO_SingleRegChannel((int *)YFIFO_CYFT_C, chNum);
    cd = readPIO_SingleRegChannel((int *)YFIFO_CYFT_D, chNum);

    fifo->start = (ADDRESS_YFIFO_INTERLEAVE + (((ca >> 7) & _12b) << 7));
    fifo->size = 128 << ((ca >> 3) & _4b); 
    fifo->rPtr = (cb & _16b); 
    fifo->wPtr = ((cb >> 16) & _16b); 
    if (fifo->wPtr >= fifo->rPtr)
	fifo->used = fifo->wPtr - fifo->rPtr;
    else
	fifo->used = fifo->size - (fifo->rPtr - fifo->wPtr);
	
    fifo->wrap = 0; 
    if (cc & _bit0) 
        fifo->wrap |= 2; 
    if (cc & _bit1) 
        fifo->wrap |= 1; 

    fifo->cfg = ca & _3b; 
    fifo->err = (cc >> 2) & _3b; 
    fifo->regA = ca; 
    fifo->regB = cb; 
    fifo->regC = cc; 
    fifo->regD = cd; 
}

void 
BmeRdZfifoState( int chNum, BmeFifo_t *fifo) 
{
    u32  ca, cc, cd;  // cntxt regs a,c,d 

    ca = readPIO_SingleRegChannel((int *)ZFIFO_CZFT_A, chNum);
    cc = readPIO_SingleRegChannel((int *)ZFIFO_CZFT_C, chNum);
    cd = readPIO_SingleRegChannel((int *)ZFIFO_CZFT_D, chNum);

    fifo->size = 128 << ((ca >> 3) & _4b); 
    fifo->start = (ADDRESS_ZFIFO + (((ca >> 7) & _10b) << 7));
    fifo->rPtr = cc & _17b; 
    fifo->wPtr = cd & _17b; 
    // assuming no over/under flow, foll eq will calc used bytes 
    if (fifo->wPtr >= fifo->rPtr)
	fifo->used = fifo->wPtr - fifo->rPtr;
    else
	fifo->used = fifo->size - (fifo->rPtr - fifo->wPtr);
	
    fifo->wrap = 0; 
    if (cc & _bit17) 
        fifo->wrap |= 2; 
    if (cd & _bit17) 
        fifo->wrap |= 1; 

    fifo->cfg = ca & _3b; 
    fifo->err = (ca >> 17) & _3b; 
    fifo->regA = ca; 
    fifo->regB = 0; 
    fifo->regC = cc; 
    fifo->regD = cd; 
}

typedef enum {
	XFIFO_FAST = 0,
	XFIFO_INTV,
	YFIFO_INTV,
	YFIFO_TO,
	FMC_ICACHE,
	FMC_DCACHE
} BME_MEM_TYPES;


void DmcRdMemTest( )
{
	int  i;
	int  ptoneWptr[16];

	for (i = 0; i < 16; i++) { 
		ptoneWptr[i] = hostPIO_read(ADDRESS_DEMAPPERCPU_DCACHE_PIO+DMC_ADR_PTONE_WRT_PTR); 
	} 
	for (i = 0; i < 16; i++) { 
		printf( "ptoneWptr[%d] = %08x\n", i, ptoneWptr[i]); 
	} 
	
}


void dump_mem(int start_addr, int nbytes, int access_mode, int out_mode)
{
	char 	*mem = (char *)malloc(nbytes*sizeof(char));
	char	file_name[100];
	int	i;
	int	num_ints=0;
	unsigned int acc;
	int 	*p = (int *)mem;
	FILE	*out;
		
	acc = 0;
	if(mem == NULL) {
		printf("\n cannot alloc mem");
		exit(1);
	}
	
	if (host_mode_flag)
		initHostIO(0x2, BME_BASE_ADDR);
	
	if(access_mode == 1) //PIO
	{
		num_ints = (nbytes+3)>>2;
		readPIO_Regs((u32 *)start_addr, num_ints, p);		
	} else // DMA
	{
		if(host_mode_flag)
			hostReadBMEMemories(mem, (char *)start_addr, nbytes, 1, 0, 0);
	}	
	
	if(out_mode == 0) {
		for(i=0;i<num_ints;i++) {
			if(i%4==0)
				printf("\n0x%08x: ", start_addr+i*sizeof(int));
			printf("0x%08x  ",  p[i]);
			acc += (p[i] >> 16) & 0xffff; 
			acc += (p[i] & 0xffff);
		}
		printf("\n\t\t Mem Value Sum = %d\n", acc); 
		if(i%20 == 0)
			iposDelay();
	} else
	{
		sprintf(file_name, "/tgtsvr/0x%8x_%d.txt", start_addr, nbytes);
		if((out = fopen(file_name, "wt"))==NULL) {
			printf("\n cannot open %s", file_name);
			exit(1);
		}
		
		for(i=0;i<num_ints;i++) {
			if(i%4==0)
				fprintf(out, "\n0x%08x: ", start_addr+i*4*sizeof(int));
			fprintf(out, "0x%08x  ",  p[i]);
			if(i%20 == 0)
				iposDelay();
		}		
	}
}
	
