/*
 * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
 */
#include <lcrash.h>

static kaddr_t memory_map;

/*
 * vtop_banner()
 */
void
vtop_banner(FILE *ofp, int flags)
{
	print_banner(ofp, "%>     VADDR%>      KADDR%>      PADDR%      PFN%",
		     flags);
}

/*
 * print_addr()
 */
void
print_addr(kaddr_t vaddr, kaddr_t kaddr, paddr_t paddr, int pfn, FILE *ofp)
{
	print_value(ofp, "", ADDR64(vaddr), 8, ADDR_FLG);
	print_value(ofp, " ", ADDR64(kaddr), 8, ADDR_FLG);
	print_value(ofp, " ", ADDR64(paddr), 8, ADDR_FLG);
	print_value(ofp, " ", INT64(pfn), 8, SIGNED_FLG);
	fprintf(ofp,"\n");
}

/*
 * vtop_cmd() -- Run the 'vtop' command.
 */
int
vtop_cmd(command_t *cmd)
{
	int i, mode, pfn, vaddr_cnt = 0, first_time = TRUE;
	kaddr_t vaddr, kaddr;
	paddr_t paddr;
	uint64_t value;
	void *mmp = (struct mm_struct *)NULL;

	mmp = kl_alloc_block(MM_STRUCT_SZ, K_TEMP);
	if (KL_ERROR) {
		return(1);
	}

	if (memory_map) {
		GET_BLOCK(memory_map, MM_STRUCT_SZ, mmp);
	} else {
		kl_readmem(KL_INIT_MM, MM_STRUCT_SZ, mmp);
	}
	if (KL_ERROR) {
		kl_free_block(mmp);
		return(1);
	}

	for (i = 0; i < cmd->nargs; i++) {
		kl_get_value(cmd->args[i], &mode, 0, &value);
		if (!KL_ERROR) {
			if (first_time || (cmd->flags & (C_FULL|C_NEXT))) {
				vtop_banner(cmd->ofp, BANNER|SMAJOR);
				first_time = FALSE;
			}
			if (mode == 1) {
				/*  Treat value as PFN 
				 */ 
				vaddr = KL_PAGE_OFFSET + 
					(value << KL_PAGE_SHIFT);	
			} else {
				vaddr = value;
			}
			if(!kl_virtop(vaddr, mmp, &paddr)) {
				pfn = ((kaddr_t)paddr >> KL_PAGE_SHIFT);
				kaddr = (kaddr_t)paddr + KL_PAGE_OFFSET;
				print_addr(vaddr, kaddr, paddr, pfn, cmd->ofp);
				vaddr_cnt++;
			}
		} 
		if (KL_ERROR) {
			fprintf(KL_ERRORFP, "Invalid vaddr value : %s "
				"(error=0x%"FMT64"x)", cmd->args[i], KL_ERROR);
		}
	}
	if (mmp) {
		kl_free_block(mmp);
	}
	if (vaddr_cnt) {
		vtop_banner(cmd->ofp, SMAJOR);
	}
	return(0);
}

#define _VTOP_USAGE "[-m map_pointer] [-w outfile] vaddr_list"

/*
 * vtop_usage() -- Print the usage string for the 'vtop' command.
 */
void
vtop_usage(command_t *cmd)
{
	CMD_USAGE(cmd, _VTOP_USAGE);
}

/*
 * vtop_help() -- Print the help information for the 'vtop' command.
 */
void
vtop_help(command_t *cmd)
{
	CMD_HELP(cmd, _VTOP_USAGE,
        "Display the virtual to physical memory mapping for each entry "
	"in vaddr_list. Entries in addr_list can in the form of a physical "
	"address, virtual address, or page number (following a '#'). "
	"When the -m command line option is specified, treat the "
	"accompanying parameter as an mm_struct pointer to use when "
	"determining memory mapping.");
}

/*
 * vtop_parse() -- Parse the command line arguments for 'vtop'.
 */
int
vtop_parse(command_t *cmd)
{
	int mode;
	option_t *op;
	uint64_t value;

	memory_map = 0;
	if (set_cmd_flags(cmd, (C_TRUE|C_WRITE), "m:")) {
		return(1);
	}
	op = cmd->options;
        while (op) {
                switch(op->op_char) {
			case 'm':
				kl_get_value(op->op_arg, &mode, 0, &value);
				if (KL_ERROR) {
					return(1);
				}
				memory_map = (kaddr_t)value;
		}
		op = op->op_next;
	}
	return(0);
}

/*
 * vtop_complete() -- Complete arguments of 'vtop' command.
 */
char *
vtop_complete(command_t *cmd)
{
	char *ret;

	/* complete standard options (for example, -w option) arguments
	 */
	if ((ret = complete_standard_options(cmd)) != NOT_COMPLETED) {
		return(ret);
	}
	fprintf(cmd->ofp, "\n");
	vtop_usage(cmd);
	return(DRAW_NEW_ENTIRE_LINE);
}
