/*
 * arch/i386/task.c
 *
 * This file handles the task related architecture-dependent parts 
 * KLIB for i386 based systems.
 *
 * Copyright 1999 Silicon Graphics, Inc. All rights reserved.
 */
#include <klib.h>

#define DUMP_MAGIC_NUMBER   	0xa8190173618f23edULL  /* dump magic number */
#define DUMP_MAGIC_LIVE     	0xa8190173618f23cdULL  /* live magic number */
#define DUMP_ASM_MAGIC_NUMBER   0xdeaddeadULL  /* magic number */

kaddr_t deftask = (kaddr_t)NULL;

/* 
 * kl_set_deftask()
 */
k_error_t
kl_set_deftask(kaddr_t task)
{
	void *tsp = 0;

	kl_reset_error();
	if (task) {
		tsp = kl_alloc_block(TASK_STRUCT_SZ, K_TEMP);
		if (tsp) {
			kl_get_task_struct(task, 2, tsp);
			if (!KL_ERROR) {
				deftask = task;
			}
			kl_free_block(tsp);
		}
	} else {
		deftask = 0;
	}
	return(KL_ERROR);
}

/* 
 * kl_parent_pid()
 */
int
kl_parent_pid(void *tsp)
{
	int ppid;
	kaddr_t parent;
	void *tpp;

	parent = kl_kaddr(tsp, "task_struct", "p_pptr");
	if (parent) {
		tpp = kl_alloc_block(TASK_STRUCT_SZ, K_TEMP);
		if (!tpp) {
			return(-1);
		}
		GET_BLOCK(parent, TASK_STRUCT_SZ, tpp);
		if (KL_ERROR) {
			return(-1);
		}
		ppid = (uint64_t)KL_UINT(tpp, "task_struct", "pid");
		kl_free_block(tpp);
		return(ppid);
	}
	return(-1);
}

/*
 * kl_pid_to_task()
 */
kaddr_t
kl_pid_to_task(kaddr_t pid)
{
	kaddr_t addr;
	syment_t *sp;
	void *tsp;

	if ((sp = kl_lkup_symname("init_task_union"))) {
		if (!(tsp = kl_alloc_block(TASK_STRUCT_SZ, K_TEMP))) {
			return((kaddr_t)NULL);
		}
		addr = sp->s_addr;
		do {
			if (kl_get_task_struct(addr, 2, tsp)) {
				break;
			}
			if (KL_UINT(tsp, "task_struct", "pid") == pid) {
				kl_free_block(tsp);
				return(addr);
			}
			addr = kl_kaddr(tsp, "task_struct", "next_task");
		} while (addr != sp->s_addr);
		kl_free_block(tsp);
	}
	KL_ERROR = KLE_PID_NOT_FOUND;
	return((kaddr_t)NULL);
}

/* 
 * kl_get_task_struct()
 */
k_error_t
kl_get_task_struct(kaddr_t value, int mode, void *tsp)
{
	kaddr_t addr;

	kl_reset_error();
	if (!tsp) {
		KL_ERROR = KLE_NULL_BUFF;
	} else {
		if (mode == 1) {
			addr = kl_pid_to_task(value);
		} else if (mode == 2) {
			addr = value;
		} else {
			KL_ERROR = KLE_BAD_TASK_STRUCT;
		}
	}
	if (!KL_ERROR) {
		GET_BLOCK(addr, TASK_STRUCT_SZ, tsp);
	}
	return(KL_ERROR);
}
