/* ------------------------------------------------------------------------------
 *                                                                      
 *                  I N T E L   P R O P R I E T A R Y                   
 *                                                                      
 *     COPYRIGHT (c)  1998-1999 BY  INTEL  CORPORATION.  ALL RIGHTS          
 *     RESERVED.   NO  PART  OF THIS PROGRAM  OR  PUBLICATION  MAY      
 *     BE  REPRODUCED,   TRANSMITTED,   TRANSCRIBED,   STORED  IN  A    
 *     RETRIEVAL SYSTEM, OR TRANSLATED INTO ANY LANGUAGE OR COMPUTER    
 *     LANGUAGE IN ANY FORM OR BY ANY MEANS, ELECTRONIC, MECHANICAL,    
 *     MAGNETIC,  OPTICAL,  CHEMICAL, MANUAL, OR OTHERWISE,  WITHOUT    
 *     THE PRIOR WRITTEN PERMISSION OF :                                
 *                                                                      
 *                        INTEL  CORPORATION                            
 *                                                                     
 *                     2200 MISSION COLLEGE BLVD                        
 *                                                                      
 *               SANTA  CLARA,  CALIFORNIA  95052-8119                  
 *                                                                      
 *------------------------------------------------------------------------------*/

/* rtm_console.c
 * register console functions so they can be called at the transactor cmd line
 *
 *
 * system: SA1200
 * subsystem: RTM
 * author: Don Hooper 1/29/98
 * revisions:
 * $History rtm_console.c $
 * 
 * 
 */ 

/*=================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rtm.h"
#include "rtm_cfg.h"
#include "endian.h"
#include "rtm_console.h"
#include "hal_sram.h"
#include "hal_sdram.h"
#include "packet_gen.h"
#include "ambaio.h"

#if defined(BUILD_DLL)
#include "xact_dll.h"
#else
#include "xact.h"
#endif

// pointer to hal interface
static SdramUnit* sdram;
static SramUnit* sram;

#if (IOSTYLE!=HARDWARE)
extern unsigned int AMBAIO_InitDone;
#endif


int rt_init()
{

// note: because ueng driver must run AMBAIO, we init the AMBAIO here
#if (IOSTYLE != HARDWARE)
// initialize ambaio

    AMBAIO_InitDone = 0;

	ambaIoInit();
	char *spin="|/-|\\";
	int i =0;
	while(AMBAIO_InitDone == 0){
		if(i > 4) i = 0;
        printf("		Init AmbaIO:	%c\n", spin[i++]);
        XACT_ExecuteCommandStr("go 1");
    }
#endif

	// get sdram pointer
	sdram = SDRAM_Attach();
	return(RTM_Init());
}

int rt_load_ucfile(char *fnam)
{
	return(RTM_InitULookup(fnam));
}


/*-----------------------------------------------------------------
	route_add
	Add a route to the route table, using string and int argument types 
	returns: return value of RTM_RtAdd
	modifies: Route Table
	see also: rtm.cpp RTM_RtAdd
  -----------------------------------------------------------------*/
extern "C" int								// RTM_SUCCESS or RTM_FAIL
route_add(
			 char *dest,			// string ip destination, e.g. "1.1.1.1"
			 char *netmask,			// string netmask, e.g., "255.255.0.0"
			 char *gateway,			// string next hop gateway, e.g., "255.255.0.0"
			 int itf,				// physical interface id (output	port number)
			 int gateway_da_hi32,	// next hop MAC DA 48:16
			 int gateway_da_lo16)	// next hop MAC DA 15:0
{
	int i;
    struct RTM_AddInfo add_info;
	
	add_info.itf = itf;
	add_info.gateway_da_hi32 = gateway_da_hi32;
	add_info.gateway_da_lo16 = gateway_da_lo16;
	add_info.destination = inet_addr(dest);
	add_info.netmask = inet_addr(netmask);
	add_info.gateway = inet_addr(gateway);
	
	// set rest of route info to 0
	for (i = 0; i<SIZE_OF_REST_ROUTE_ENTRY;i++){
		add_info.rest[i] = 0;
	}

	// add_info.rt_info[1] = add_info.gateway;

	return(RTM_RtAdd(&add_info));
}
// same as route_add, but gateway is 0, for testing pruposes
extern "C" int rt_add(char *dest, char *netmask, int itf)
{
	return route_add(dest, netmask, "", itf, 0, 0);
}


/*-----------------------------------------------------------------
	route_lookup
	Get a route from the route table. 
	This can be called from an .ind file.
	returns: physical interface number
	see also: rtm.cpp
	modifies:
  -----------------------------------------------------------------*/
int									// interface number
route_lookup(
			 char *destination)		// string ip destination, e.g. "1.1.1.1"
{
	uint route_loc;
	uint val;
	
	route_loc = RTM_RtLookup(destination);
	sdram->read(route_loc, &val);

    return(val);					// first word in route entry is the interface
}

extern "C" int rt_lookup(char *dest)
{
	return route_lookup(dest);
}


/*-----------------------------------------------------------------
	route_delete
	Delete a route from the route table, using simple argument types 
	returns: return value of RTM_RtDelete
	modifies: Route Table
	see also: rtm.cpp RTM_RtDelete
  -----------------------------------------------------------------*/
extern "C" int
route_delete(
			 char *dest,		// string ip destination, e.g. "1.1.1.1"
			 char *netmask)		// string netmask, e.g., "255.255.0.0"
{
    struct RTM_DeleteInfo del_info;
	
	del_info.destination = inet_addr(dest);
	del_info.netmask = inet_addr(netmask);

	return(RTM_RtDelete(&del_info));
}
extern "C" int rt_delete(char *dest, char *netmask)
{
	return(route_delete(dest, netmask));
}


unsigned int trie_ptr(unsigned int block, unsigned int leaf)
{
	unsigned int val;

	sram = SRAM_Attach();
	sram->read(RTM_config.trie_base + block + leaf, &val);
	return(val);
}

unsigned int trie_pref(unsigned int block, unsigned int pref, unsigned int idx)
{
	switch (pref){
	case 1: 
		return(RTM_config.trie_info[block].prefix1[idx]);
		break;
	case 2:
		return(RTM_config.trie_info[block].prefix2[idx]);
		break;
	default:
		return(RTM_config.trie_info[block].prefix3[idx]);
	}
	return(0);
}

int rt_hi256_show()
{
	int i, addr;
	unsigned int val;

	for (i=0;i<256;i++){
		addr = RTM_config.hi256_base+i;
		sram->read(addr, &val);
		if (val){
#if (IOSTYLE != HARDWARE)
			XACT_printf("Hi256 sram address %x entry = %x, mask = %x\n", addr, val, RTM_config.hi256_info.mask[i]);
#else
			printf("Hi256 sram address %x entry = %x, mask = %x\n", addr, val, RTM_config.hi256_info.mask[i]);
#endif
		}
	}
	return(RTM_SUCCESS);
}

int rt_hi64k_show()
{
	int i, addr;
	unsigned int val;

	for (i=0;i<65536;i++){
		addr = RTM_config.hi64k_base+i;
		sram->read(addr, &val);
		if (val){
#if (IOSTYLE != HARDWARE)
			XACT_printf("Hi64k sram address %x entry = %x\n", addr, val);
#else
			printf("Hi64k sram address %x entry = %x\n", addr, val);
#endif
		}
	}
	return(RTM_SUCCESS);
}

int rt_trie_show(int block)
{
#if (IOSTYLE != HARDWARE)
	XACT_printf("Trie Block %x, population %d\n", block, RTM_config.trie_info[block].population);
	XACT_printf("0-7:\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\n",
		trie_ptr(block,0), trie_ptr(block,1), trie_ptr(block,2), trie_ptr(block,3), 
		trie_ptr(block,4), trie_ptr(block,5), trie_ptr(block,6), trie_ptr(block,7)); 
	XACT_printf("8-15:\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\n",
		trie_ptr(block,8), trie_ptr(block,9), trie_ptr(block,10), trie_ptr(block,11), 
		trie_ptr(block,12), trie_ptr(block,13), trie_ptr(block,14), trie_ptr(block,15)); 
	XACT_printf("pref3:\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\n",
		trie_pref(block,3,0), trie_pref(block,3,1), trie_pref(block,3,2), trie_pref(block,3,3), 
		trie_pref(block,3,4), trie_pref(block,3,5), trie_pref(block,3,6), trie_pref(block,3,7)); 
	XACT_printf("pref2:\t%x\t%x\t%x\t%x\n", 
		trie_pref(block,2,0), trie_pref(block,2,1), trie_pref(block,2,2), trie_pref(block,2,3));
	XACT_printf("pref1:\t%x\t%x\n", 
		trie_pref(block,1,0), trie_pref(block,1,1));
#else
	printf("Trie Block %x, population %d\n", block, RTM_config.trie_info[block].population);
	printf("0-7:\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\n",
		trie_ptr(block,0), trie_ptr(block,1), trie_ptr(block,2), trie_ptr(block,3), 
		trie_ptr(block,4), trie_ptr(block,5), trie_ptr(block,6), trie_ptr(block,7)); 
	printf("8-15:\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\n",
		trie_ptr(block,8), trie_ptr(block,9), trie_ptr(block,10), trie_ptr(block,11), 
		trie_ptr(block,12), trie_ptr(block,13), trie_ptr(block,14), trie_ptr(block,15)); 
	printf("pref3:\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\n",
		trie_pref(block,3,0), trie_pref(block,3,1), trie_pref(block,3,2), trie_pref(block,3,3), 
		trie_pref(block,3,4), trie_pref(block,3,5), trie_pref(block,3,6), trie_pref(block,3,7)); 
	printf("pref2:\t%x\t%x\t%x\t%x\n", 
		trie_pref(block,2,0), trie_pref(block,2,1), trie_pref(block,2,2), trie_pref(block,2,3));
	printf("pref1:\t%x\t%x\n", 
		trie_pref(block,1,0), trie_pref(block,1,1));

#endif
	return(RTM_SUCCESS);
}
int rt_ent_show(int route_table_index)
{
	uint route_loc = RTM_config.route_table_base + route_table_index;
	uint itf, dest, mask, gateway, mac_hi32, mac_lo16;

	sdram->read(route_loc, &itf);
	sdram->read(route_loc+1, &mac_hi32);
	sdram->read(route_loc+2, &mac_lo16);
	sdram->read(route_loc+3, &dest);
	sdram->read(route_loc+4, &mask);
	sdram->read(route_loc+5, &gateway);
#if (IOSTYLE != HARDWARE)
	XACT_printf("Route Entry: port %d    dest mac %.4x%.2x    dest ip %x    netmask %x    gateway ip %x\n",
		itf, mac_hi32, mac_lo16, ntohl(dest), ntohl(mask), ntohl(gateway));
#else
	printf("Route Entry: port %d    dest mac %.4x%.2x    dest ip %x    netmask %x    gateway ip %x\n",
		itf, mac_hi32, mac_lo16, ntohl(dest), ntohl(mask), ntohl(gateway));
#endif
	return(RTM_SUCCESS);
}

int rt_ent_info(char *destination)
{
	uint route_loc;

	route_loc = RTM_RtLookup(destination);

	return(rt_ent_show(route_loc - RTM_config.route_table_base));
}

/*-----------------------------------------------------------------
	rt_help
	description: list RTM functions
	returns:
	uses:
	modifies:
  -----------------------------------------------------------------*/
int rt_help()
{
#if (IOSTYLE != HARDWARE)
	XACT_printf("\n");
	XACT_printf("*** RTM command-line functions:\n\n");
	XACT_printf("rt_init();                                 // initialize RTM table structures\n");
	XACT_printf("rt_load_ucfile(char *uof_file);            // load uc file and insert shared variables\n");
	XACT_printf("rt_ent_info(char *ipda);                   // show route entry\n");
	XACT_printf("rt_ent_show(int route_table_index);        // show route entry\n");
	XACT_printf("rt_hi256_show();                           // show hi256 entries\n");
	XACT_printf("rt_hi64k_show();                           // show hi64k entries\n");
	XACT_printf("rt_trie_show(int trie_block_iindex);       // show trie block\n");
	XACT_printf("route_add(char *ipda, char *netmask, char *next_hop, int fwd_port, int da_hi32, int da_lo16);	// insert route entry\n");
	XACT_printf("route_lookup(char *ipda);                  // lookup forwarding port\n");
	XACT_printf("route_delete(char *ipda, char *netmask);   // delete route entry\n");
#else
	printf("\n");
	printf("*** RTM command-line functions:\n\n");
	printf("rt_init();                                 // initialize RTM table structures\n");
	printf("rt_load_ucfile(char *uof_file);            // load uc file and insert shared variables\n");
	printf("rt_ent_info(char *ipda);                   // show route entry\n");
	printf("rt_ent_show(int route_table_index);        // show route entry\n");
	printf("rt_hi256_show();                           // show hi256 entries\n");
	printf("rt_hi64k_show();                           // show hi64k entries\n");
	printf("rt_trie_show(int trie_block_index);        // show trie block\n");
	printf("route_add(char *ipda, char *netmask, char *next_hop, int fwd_port, int da_hi32, int da_lo16);	// insert route entry\n");
	printf("route_lookup(char *ipda);                  // lookup forwarding port\n");
	printf("route_delete(char *ipda, char *netmask);   // delete route entry\n");
#endif
	return(1);
}

/* FOREIGN MODEL INITIALIZE

  instructions
	1. define ext_model_port as a compiler switch when compiling safe_xact
	2. "													   " rtm_registration
 */

/* functions called by transactor to foreign model */

int IO_Read(unsigned int addr)
{
	unsigned int *val = 0;
#if (IOSTYLE != HARDWARE)
	AMBAIO_AutoRead32("",addr, val);
#endif

	return(*val);
}

int IO_Write(unsigned int addr, unsigned int val)
{
#if (IOSTYLE != HARDWARE)
	AMBAIO_AutoWrite32("",(unsigned int)addr, (unsigned int)val);
#endif
	return(val);
}


/* this routine will be called to initialize the foreign model after */
/* the transactor "init" command has successfully executed.  Returning 0 */
/* will result in a transactor error. */
#if (IOSTYLE != HARDWARE)
#ifndef STANDALONE
int rtm_model_initialize()
#else
int foreign_model_initialize()
#endif
{
	if (!XACT_register_console_function("rt_help", rt_help, 0, 0) ){
            fprintf(stderr,"XACT_register_console_function() rt_help failed\n");
			return(0);
	}
	if (!XACT_register_console_function("rt_init", rt_init, 0, 0) ){
		fprintf(stderr,"XACT_register_console_function() rt_init failed\n");
		return(0);
	}
	if (!XACT_register_console_function("rt_load_ucfile", rt_load_ucfile, 1, 0) ){
		fprintf(stderr,"XACT_register_console_function() rt_load_ucfile failed\n");
		return(0);
	}
	if (!XACT_register_console_function("rt_add", rt_add, 2, 1) ){
		fprintf(stderr,"XACT_register_console_function() rt_add failed\n");
		return(0);
	}
	if (!XACT_register_console_function("route_add", route_add, 3, 3) ){
		fprintf(stderr,"XACT_register_console_function() route_add failed\n");
		return(0);
	}
	if (!XACT_register_console_function("rt_lookup", rt_lookup, 1, 0) ){
		fprintf(stderr,"XACT_register_console_function() rt_lookup failed\n");
		return(0);
	}
	if (!XACT_register_console_function("route_lookup", route_lookup, 1, 0) ){
		fprintf(stderr,"XACT_register_console_function() route_lookup failed\n");
		return(0);
	}
	if (!XACT_register_console_function("rt_delete", rt_delete, 2, 0) ){
		fprintf(stderr,"XACT_register_console_function() rt_delete failed\n");
		return(0);
	}
	if (!XACT_register_console_function("route_delete", route_delete, 2, 0) ){
		fprintf(stderr,"XACT_register_console_function() route_delete failed\n");
		return(0);
	}	if (!XACT_register_console_function("rt_trie_show", rt_trie_show, 0, 1) ){
		fprintf(stderr,"XACT_register_console_function() rt_trie_show failed\n");
		return(0);
	}
	if (!XACT_register_console_function("rt_ent_info", rt_ent_info, 1, 0) ){
		fprintf(stderr,"XACT_register_console_function() rt_ent_info failed\n");
		return(0);
	}
	if (!XACT_register_console_function("rt_ent_show", rt_ent_show, 0, 1) ){
		fprintf(stderr,"XACT_register_console_function() rt_ent_show failed\n");
		return(0);
	}
	if (!XACT_register_console_function("rt_hi256_show", rt_hi256_show, 0, 0) ){
		fprintf(stderr,"XACT_register_console_function() rt_hi256_show failed\n");
		return(0);
	}
	if (!XACT_register_console_function("rt_hi64k_show", rt_hi64k_show, 0, 0) ){
		fprintf(stderr,"XACT_register_console_function() rt_hi64k_show failed\n");
		return(0);
	}
#ifdef STANDALONE
	// from hal_1200/hal_sram


	if (!XACT_register_console_function("SRAM_Write", SRAM_Write, 0, 2) ){
		fprintf(stderr,"XACT_register_console_function() SRAM_Write failed\n");
		return(0);
	}
	if (!XACT_register_console_function("SRAM_Read", SRAM_Read, 0, 1) ){
		fprintf(stderr,"XACT_register_console_function() SRAM_Read failed\n");
		return(0);
	}
	// from hal_1200/hal_sdram
	if (!XACT_register_console_function("SDRAM_Write", SDRAM_Write, 0, 2) ){
		fprintf(stderr,"XACT_register_console_function() SDRAM_Write failed\n");
		return(0);
	}
	if (!XACT_register_console_function("SDRAM_Read", SDRAM_Read, 0, 1) ){
		fprintf(stderr,"XACT_register_console_function() SDRAM_Read failed\n");
		return(0);
	}
	if (!XACT_register_console_function("IO_Write", IO_Write, 0, 2) ){
		fprintf(stderr,"XACT_register_console_function() IO_Write failed\n");
		return(0);
	}
	if (!XACT_register_console_function("IO_Read", IO_Read, 0, 1) ){
		fprintf(stderr,"XACT_register_console_function() IO_Read failed\n");
		return(0);
	}

	pkgen_model_initialize();
	fdrive_model_initialize();
	fmon_model_initialize();

#endif	// STANDALONE
	return(1);
}


/* this routine will be called prior to each transactor simulation event */
/* It can be used to deposit state values into the transactor model prior */
/* to simulating the next event.  Returning 0 results in an error. */
#ifdef STANDALONE 
int foreign_model_pre_sim()
{
	return(1);
}

/* this routine will be called subsequent to each transactor simulation event. */
/* It can be used to query transactor simulation state, in order to copy it */
/* into the foreign model simulator. */
int foreign_model_post_sim()
{
	return(1);
}

/* this routine will be called just prior to exiting the simulator. */
/* The routine allows the foreign model to clean up, close files, etc */
/* before shutting down the program. */
int foreign_model_exit()
{
    return(1);
}

/* this routine will be called just after reseting the simulator. */
/* The routine allows the foreign model to reset itself to stay */
/* in sync with the simulator. */
int foreign_model_reset()
{
    AMBAIO_ResetAllChips();
	return(1);
}


#if defined(BUILD_DLL)
/*-----------------------------------------------------------------
    GetForeignModelFunctions

    This function is exported as the sole entry point into the DLL version
    of this package.  The Developer Workbench calls it in order to get the
    foreign model entry points for the transactor.  The Workbench thens
    registers these entry points with the transactor.
    
     returns: 
        uses: 
    modifies: 
*/
#if defined(__cplusplus)
extern "C"
#endif
__declspec(dllexport) void __cdecl
GetForeignModelFunctions(
    int (**ForeignModelInitialize)(),
    int (**ForeignModelPreSim)(),
    int (**ForeignModelPostSim)(),
    int (**ForeignModelExit)(),
    int (**ForeignModelReset)())
{
    *ForeignModelInitialize = foreign_model_initialize;
    *ForeignModelPreSim = foreign_model_pre_sim;
    *ForeignModelPostSim = foreign_model_post_sim;
    *ForeignModelExit = foreign_model_exit;
    *ForeignModelReset = foreign_model_reset;
}
#endif      // #if defined(BUILD_DLL)
#endif		// STANDALONE
#endif		// IOSTYLE != HARDWARE
