/*
 * SPAPR base RTAS calls
 *
 * Borrowed heavily from QEMU's spapr_rtas.c
 * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
 *
 * Modifications copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "kvm/kvm.h"
#include "kvm/kvm-cpu.h"
#include "kvm/util.h"
#include "kvm/term.h"
#include "libfdt.h"

#include "spapr.h"

#include <stdio.h>
#include <assert.h>

#define TOKEN_BASE      0x2000
#define TOKEN_MAX       0x100

#define RTAS_CONSOLE

static struct rtas_call {
	const char *name;
	spapr_rtas_fn fn;
} rtas_table[TOKEN_MAX];

struct rtas_call *rtas_next = rtas_table;


static void rtas_display_character(struct kvm_cpu *vcpu,
                                   uint32_t token, uint32_t nargs,
                                   target_ulong args,
                                   uint32_t nret, target_ulong rets)
{
	char c = rtas_ld(vcpu->kvm, args, 0);
	term_putc(CONSOLE_HV, &c, 1, 0);
	rtas_st(vcpu->kvm, rets, 0, 0);
}

#ifdef RTAS_CONSOLE
static void rtas_put_term_char(struct kvm_cpu *vcpu,
			       uint32_t token, uint32_t nargs,
			       target_ulong args,
			       uint32_t nret, target_ulong rets)
{
	char c = rtas_ld(vcpu->kvm, args, 0);
	term_putc(CONSOLE_HV, &c, 1, 0);
	rtas_st(vcpu->kvm, rets, 0, 0);
}

static void rtas_get_term_char(struct kvm_cpu *vcpu,
			       uint32_t token, uint32_t nargs,
			       target_ulong args,
			       uint32_t nret, target_ulong rets)
{
	int c;
	if (term_readable(CONSOLE_HV, 0) &&
	    (c = term_getc(CONSOLE_HV, 0)) >= 0) {
		rtas_st(vcpu->kvm, rets, 0, 0);
		rtas_st(vcpu->kvm, rets, 1, c);
	} else {
		rtas_st(vcpu->kvm, rets, 0, -2);
	}
}
#endif

static void rtas_get_time_of_day(struct kvm_cpu *vcpu,
                                 uint32_t token, uint32_t nargs,
                                 target_ulong args,
                                 uint32_t nret, target_ulong rets)
{
	struct tm tm;
	time_t tnow;

	if (nret != 8) {
		rtas_st(vcpu->kvm, rets, 0, -3);
		return;
	}

	tnow = time(NULL);
	/* Guest time is currently not offset in any way. */
	gmtime_r(&tnow, &tm);

	rtas_st(vcpu->kvm, rets, 0, 0); /* Success */
	rtas_st(vcpu->kvm, rets, 1, tm.tm_year + 1900);
	rtas_st(vcpu->kvm, rets, 2, tm.tm_mon + 1);
	rtas_st(vcpu->kvm, rets, 3, tm.tm_mday);
	rtas_st(vcpu->kvm, rets, 4, tm.tm_hour);
	rtas_st(vcpu->kvm, rets, 5, tm.tm_min);
	rtas_st(vcpu->kvm, rets, 6, tm.tm_sec);
	rtas_st(vcpu->kvm, rets, 7, 0);
}

static void rtas_set_time_of_day(struct kvm_cpu *vcpu,
                                 uint32_t token, uint32_t nargs,
                                 target_ulong args,
                                 uint32_t nret, target_ulong rets)
{
	pr_warning("%s called; TOD set ignored.\n", __FUNCTION__);
}

static void rtas_power_off(struct kvm_cpu *vcpu,
                           uint32_t token, uint32_t nargs, target_ulong args,
                           uint32_t nret, target_ulong rets)
{
	if (nargs != 2 || nret != 1) {
		rtas_st(vcpu->kvm, rets, 0, -3);
		return;
	}
	kvm_cpu__reboot();
}

static void rtas_query_cpu_stopped_state(struct kvm_cpu *vcpu,
                                         uint32_t token, uint32_t nargs,
                                         target_ulong args,
                                         uint32_t nret, target_ulong rets)
{
	if (nargs != 1 || nret != 2) {
		rtas_st(vcpu->kvm, rets, 0, -3);
		return;
	}

	/*
	 * Can read id = rtas_ld(vcpu->kvm, args, 0), but
	 * we currently start all CPUs.  So just return true.
	 */
	rtas_st(vcpu->kvm, rets, 0, 0);
	rtas_st(vcpu->kvm, rets, 1, 2);
}

static void rtas_start_cpu(struct kvm_cpu *vcpu,
                           uint32_t token, uint32_t nargs,
                           target_ulong args,
                           uint32_t nret, target_ulong rets)
{
	die(__FUNCTION__);
}

target_ulong spapr_rtas_call(struct kvm_cpu *vcpu,
                             uint32_t token, uint32_t nargs, target_ulong args,
                             uint32_t nret, target_ulong rets)
{
	if ((token >= TOKEN_BASE)
	    && ((token - TOKEN_BASE) < TOKEN_MAX)) {
		struct rtas_call *call = rtas_table + (token - TOKEN_BASE);

		if (call->fn) {
			call->fn(vcpu, token, nargs, args, nret, rets);
			return H_SUCCESS;
		}
	}

	/*
	 * HACK: Some Linux early debug code uses RTAS display-character,
	 * but assumes the token value is 0xa (which it is on some real
	 * machines) without looking it up in the device tree.  This
	 * special case makes this work
	 */
	if (token == 0xa) {
		rtas_display_character(vcpu, 0xa, nargs, args, nret, rets);
		return H_SUCCESS;
	}

	hcall_dprintf("Unknown RTAS token 0x%x\n", token);
	rtas_st(vcpu->kvm, rets, 0, -3);
	return H_PARAMETER;
}

void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
{
	assert(rtas_next < (rtas_table + TOKEN_MAX));

	rtas_next->name = name;
	rtas_next->fn = fn;

	rtas_next++;
}

/*
 * This is called from the context of an open /rtas node, in order to add
 * properties for the rtas call tokens.
 */
int spapr_rtas_fdt_setup(struct kvm *kvm, void *fdt)
{
	int ret;
	int i;

	for (i = 0; i < TOKEN_MAX; i++) {
		struct rtas_call *call = &rtas_table[i];

		if (!call->fn) {
			continue;
		}

		ret = fdt_property_cell(fdt, call->name, i + TOKEN_BASE);

		if (ret < 0) {
			pr_warning("Couldn't add rtas token for %s: %s\n",
				   call->name, fdt_strerror(ret));
			return ret;
		}

	}
	return 0;
}

void register_core_rtas(void)
{
	spapr_rtas_register("display-character", rtas_display_character);
	spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
	spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
	spapr_rtas_register("power-off", rtas_power_off);
	spapr_rtas_register("query-cpu-stopped-state",
			    rtas_query_cpu_stopped_state);
	spapr_rtas_register("start-cpu", rtas_start_cpu);
#ifdef RTAS_CONSOLE
	/* These are unused: We do console I/O via hcalls, not rtas. */
	spapr_rtas_register("put-term-char", rtas_put_term_char);
	spapr_rtas_register("get-term-char", rtas_get_term_char);
#endif
}
