/*******************************************************
 *
 * COPYRIGHT (C) FUJITSU,LTD. 2001 ALL RIGHTS RESERVED.
 * 
 * Created by T.INDOH <indou.takao@jp.fujitsu.com>
 *
 *******************************************************/


string
lkstdump_opt() 
{ 
	return ""; 
}

string
lkstdump_usage() 
{ 
	return "output_file [CPU_ID [BUFFER_ID]]\n"; 
}

static void
lkstdump_showusage()
{
	printf("usage : lkstdump %s\n", lkstdump_usage());
}

string
lkstdump_help()
{
	return 
"This command extracts lkst trace buffer,\n" +
"and saves trace data to file specified by the argument ""output_file""." +
"CPU_ID specifies ID of CPU to be saved, and BUFFER_ID specifies ID of buffer.";
}


int 
lkstdump()
{
	int buffer_id;
	int buffer_id_max;
	int buffer_id_void;
	int buffer_size;
	int* p_int;
	char* p_char;
	char* addr_lkst_header;
	char* addr_lkst_cpu_header;
	char* addr_evbuf;
	int i,j,k;
	int cpu;

	if ( argc>3 ) {
		lkstdump_showusage();
		return 1;
	}
	buffer_id = -1;
	cpu = -1;
	/* get CPU & buffer ID */
	if (argc >= 3) {
		if ( !isDigitStr(argv[2]) ) {
			lkstdump_showusage();
			return 1;
		}
		cpu = atoi(argv[2]);
	}
	if (argc == 4){
		if ( !isDigitStr(argv[3]) ){
			lkstdump_showusage();
			return 1;
		}
		buffer_id = atoi(argv[3]);
	}
	buffer_id_max = lkst_getvalue_buffer_id_max();
	buffer_id_void = lkst_getvalue_buffer_id_void();

	addr_lkst_header = (char *)lkst;
	if( lkst_check_and_init((int)addr_lkst_header) ) {
		printf("Error : internal error - lkst structure not found.\n");
		return 1;
	}

	/* open output file */
	if(argc >= 2) {
		if(lkst_open_write_file(argv[1])) {
			return 1;
		}
	}
	else {
		lkstdump_showusage();
		return 1;
	}


	addr_lkst_cpu_header = (char *)lkst_cpu;
	if( lkst_check_and_init_cpu((int)addr_lkst_cpu_header) ) {
		printf("Error : internal error - lkst cpu structure not found.\n");
		return 1;
	}

	/* set lkst data */
	p_int = (int*)(addr_lkst_header + lkst_getoffset_lkst_h_tvsec());
	lkst_setdata_lkst_h_tvsec(p_int[0]);

	p_int = (int*)(addr_lkst_header + lkst_getoffset_lkst_h_tvusec());
	lkst_setdata_lkst_h_tvusec(p_int[0]);

	p_int = (int*)(addr_lkst_header + lkst_getoffset_lkst_h_tsc());
	lkst_setdata_lkst_h_tsc_l(p_int[0]);
	lkst_setdata_lkst_h_tsc_h(p_int[1]);

	p_int = (int*)(addr_lkst_header + lkst_getoffset_lkst_h_cpu_freq());
	lkst_setdata_lkst_h_cpu_freq_l(p_int[0]);
	lkst_setdata_lkst_h_cpu_freq_h(0);

	p_int = (int*)(addr_lkst_header + lkst_getoffset_lkst_h_cmos_flag());
	lkst_setdata_lkst_h_cmos_flag(p_int[0]);

	lkst_setdata_buffer_id(buffer_id);

	if ((cpu < 0) || (cpu == 255)) {
		/*get address of static buffer */
		p_int = (int *)(addr_lkst_header + 
				lkst_getoffset_lkst_h_sbuf_body());
		/* get size of static buffer */
		buffer_size = lkst_getvalue_sbuf_size();

		/* copy buffer to lkstdumplib */
		lkst_alloc_buffer(buffer_size *
				  lkst_getvalue_evrec_size());
		printf("static buffer");
		lkst_copy_buffer_pointer((int)p_int, 
					 (int)buffer_size*
					 lkst_getvalue_evrec_size());
			
		/* write buffer in the lkstdumplib */
		lkst_write_buffer_file();
		lkst_release_buffer();
		printf(" write(%d records)\n", buffer_size);
	}
	
	/* for each cpus */
	for (k = 0; k < lkst_getvalue_cpu_max(); k++ ) {
		
		if((cpu >= 0)&&(cpu != k))
			continue;
		
		for (i = 0; i <= buffer_id_max; i++) {

			/* get bufferp of buffer */
			p_int = (int*)(addr_lkst_cpu_header + 
				       lkst_getoffset_lkst_cpu_h()*k + 
				       lkst_getoffset_lkst_cpu_h_bufferp(i));
			
			if(((buffer_id >= 0)&&(buffer_id != i))||
			   (p_int[0] == 0))
				continue;
			
			addr_evbuf = (char*)p_int[0];
			
			/* get id of buffer */
			p_char = (char*)(addr_evbuf + 
					 lkst_getoffset_evbuf_id());
			if (p_char[0] >= buffer_id_void) continue;
			
			/* get size of buffer */
			p_int = (int*)(addr_evbuf +
				       lkst_getoffset_evbuf_size());
			buffer_size = p_int[0];
			
			/* get body of buffer */
			p_char = addr_evbuf + lkst_getoffset_evbuf_body();
			
			/* copy buffer to lkstdumplib */
			p_int = (int*)(addr_evbuf +
				       lkst_getoffset_evbuf_body());
			lkst_alloc_buffer(buffer_size *
					  lkst_getvalue_evrec_size());
			printf("cpu[%d].buffer[%d]", k, i);
			lkst_copy_buffer_pointer((int)p_int, 
						 (int)buffer_size*
						 lkst_getvalue_evrec_size());
			
			/* write buffer in the lkstdumplib */
			lkst_write_buffer_file();
			lkst_release_buffer();
			printf(" write(%d records)\n", buffer_size);
		}
	}
	lkst_close_write_file();
		
	return 0;
}
