// Copyright (C) 2013 Nick Johnson <nickbjohnson4224 at gmail.com>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
// 
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include <stdbool.h>

#include "../include/pinion.h"
#include "../internal.h"

//////////////////////////////////////////////////////////////////////////////
// API function page_get
//
// Gets the virtual to physical mapping and page flags for a given virtual
// address in the current thread's active page table.
//
// vaddr - virtual address
//
// Returns a structure containing the mapped-to physical address and the
// effective page flags. This call cannot fail.
//

// TODO LIST
//
// When multiple pagetable support is added, this needs to reference the 
// current thread's pagetable instead of just the root one.

struct __PINION_page_content apilogic_page_get(__PINION_virtaddr vaddr) {

	struct __PINION_page_content page = {
	
		// get virtual->physical translation
		pcx_get_trans(NULL, vaddr),

		// used for accumulating cooked page flags 
		0
	};

	// get page flags
	uint64_t raw_flags = pcx_get_flags(NULL, vaddr);

	// convert page flags
	if (raw_flags & PF_VALID) {
		page.flags |= __PINION_PAGE_VALID;

		if (raw_flags & PF_PRES) {
			if (!(raw_flags & PF_NREAD)) page.flags |= __PINION_PAGE_READ;
			if (raw_flags & PF_WRITE)    page.flags |= __PINION_PAGE_WRITE;
			if (!(raw_flags & PF_NX))    page.flags |= __PINION_PAGE_EXEC;
			if (raw_flags & PF_USER)     page.flags |= __PINION_PAGE_USER;
			if (raw_flags & PF_PWT)      page.flags |= __PINION_PAGE_WRITE_THROUGH;
			if (raw_flags & PF_PCD)      page.flags |= __PINION_PAGE_CACHE_DISABLE;
		}

		if (raw_flags & PF_ACCS)  page.flags |= __PINION_PAGE_ACCESSED;
		if (raw_flags & PF_DIRTY) page.flags |= __PINION_PAGE_DIRTY;
	}

	return page;
}
