/* 
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
 */
#include <stdarg.h>
#include <stddef.h>
#include <asm/pdc.h>
#include "bootloader.h"
#undef PAGE0
#define	PAGE0	((struct zeropage *)0x00000000)


#define DEFAULT_W 0x2
#define DEFAULT_E 0x1
#define PDC_PSW 21
#define PDC_RETURN_MASK 0
#define PDC_RETURN_DEFAULTS 1
#define PDC_SET_DEFAULTS 2
#define PDC_STABLE 10

void die(const char *s)
{
    puts(s);
    puts("\n");
}

static int firmware_is_wide;
static long long mem_pdc;

void
firmware_init(int started_wide)
{
    mem_pdc = PAGE0->mem_pdc;
    mem_pdc |= (unsigned long long) PAGE0->mem_pdc_hi << 32;

    firmware_is_wide = started_wide;
}

/* pdc_result[] is big enough for either narrow or wide calls */
static unsigned pdc_result[64] __attribute__ ((aligned (8)));
static char iodc_string[128]   __attribute__ ((aligned (64)));

struct wide_stack {
	unsigned long long arg0;
	unsigned long long arg1;
	unsigned long long arg2;
	unsigned long long arg3;
	unsigned long long arg4;
	unsigned long long arg5;
	unsigned long long arg6;
	unsigned long long arg7;
	unsigned long long arg8;
	unsigned long long arg9;
	unsigned long long arg10;
	unsigned long long arg11;
	unsigned long long arg12;
	unsigned long long arg13;
	unsigned long long frame_marker[2];	/* rp, previous sp */
	unsigned long long sp;
	/* in reality, there's nearly 8k of stack after this */
};

static int
firmware_call(unsigned long long fn, ...)
{
    va_list args;
    int r;

    if (firmware_is_wide)
    {
	extern struct wide_stack real_stack;
	extern unsigned int real64_call_asm(unsigned long long *,
					    unsigned long long *, 
					    unsigned long long);

	va_start(args, fn);
	real_stack.arg0 = va_arg(args, unsigned long);
	real_stack.arg1 = va_arg(args, unsigned long);
	real_stack.arg2 = va_arg(args, unsigned long);
	real_stack.arg3 = va_arg(args, unsigned long);
	real_stack.arg4 = va_arg(args, unsigned long);
	real_stack.arg5 = va_arg(args, unsigned long);
	real_stack.arg6 = va_arg(args, unsigned long);
	real_stack.arg7 = va_arg(args, unsigned long);
	real_stack.arg8 = va_arg(args, unsigned long);
	real_stack.arg9 = va_arg(args, unsigned long);
	real_stack.arg10 = va_arg(args, unsigned long);
	real_stack.arg11 = va_arg(args, unsigned long);
	real_stack.arg12 = va_arg(args, unsigned long);
	real_stack.arg13 = va_arg(args, unsigned long);
	va_end(args);

	r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn);
    }
    else
    {
	typedef int (*firmware_entry)();
	unsigned long arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
	    arg9, arg10, arg11, arg12, arg13;

	va_start(args, fn);
	arg0 = va_arg(args, unsigned long);
	arg1 = va_arg(args, unsigned long);
	arg2 = va_arg(args, unsigned long);
	arg3 = va_arg(args, unsigned long);
	arg4 = va_arg(args, unsigned long);
	arg5 = va_arg(args, unsigned long);
	arg6 = va_arg(args, unsigned long);
	arg7 = va_arg(args, unsigned long);
	arg8 = va_arg(args, unsigned long);
	arg9 = va_arg(args, unsigned long);
	arg10 = va_arg(args, unsigned long);
	arg11 = va_arg(args, unsigned long);
	arg12 = va_arg(args, unsigned long);
	arg13 = va_arg(args, unsigned long);
	va_end(args);

	r = (*(firmware_entry) (unsigned int) fn) (arg0, arg1, arg2, arg3, arg4,
	    arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
    }

    return r;
}

void
convert_from_wide(unsigned *retbuf)
{
    if (firmware_is_wide)
    {
	*retbuf = *(unsigned long long *)retbuf;
    }
}

/* flag=true means enable default wide mode.
 */
int
pdc_default_width(int wide)
{
    int r;
    int mask;

    /* Ask firmware which default PSW bits we're allowed to set */

    r = firmware_call(mem_pdc, PDC_PSW, PDC_RETURN_MASK, pdc_result);
    convert_from_wide(pdc_result);
    switch(r)
    {
    case 0:		/* PDC call worked */
	mask = pdc_result[0];
	if (wide && ((mask & DEFAULT_W) == 0))
	{
	    die("Firmware does not allow selection of default wide mode.\n"
	    	"Are you trying to boot a 64-bit kernel on a 32-bit box?");
	    return 1;
	}
	/* get the current default bit settings */
	firmware_call(mem_pdc, PDC_PSW, PDC_RETURN_DEFAULTS, pdc_result);
	convert_from_wide(pdc_result);
	if (wide)
	{
	    if ((mask & DEFAULT_W) == 0) {
		die("Firmware does not allow selection of default wide mode.\n"
		    "Are you trying to boot a 64-bit kernel on a 32-bit box?");
		return 1;
	    }
	    pdc_result[0] |= DEFAULT_W;
	}
	else
	{
	    pdc_result[0] &= ~DEFAULT_W;
	}
	pdc_result[0] &= ~DEFAULT_E;
	/* Ask firmware to set the W bit appropriately */
	r = firmware_call(mem_pdc, PDC_PSW, PDC_SET_DEFAULTS, pdc_result[0]);
	if (r < 0)
	{
	    printf("PDC_SET_DEFAULTS returns error %d\n", r);
	    die("Requested default wide/narrow mode not set");
	    return 1;
	}
	if (0) printf("Set default PSW W bit to %d\n", wide);
	break;
    case -2:	/* unsupported PDC call */
    default:
	/* assume that when this fails, it's an older machine which */
	/* doesn't support wide mode */
	if (wide)
	{
	    die("Can't select default wide mode, PDC_PSW call does not work");
	    return 1;
	}
	else /* narrow */
	{
	    if (0) printf("Warning: narrow mode requested, PDC_PSW call fails\n");
	}
	break;
    }
    return 0;
}

int
pdc_os_bits()
{
    int r;
    int osbits = 0x2;	/* default to 32-bit OS */

    r = firmware_call(mem_pdc, PDC_MODEL, PDC_MODEL_CAPABILITIES, pdc_result);
    convert_from_wide(pdc_result);
    if (r < 0)
    {
	if (0) printf("Annoyance: Firmware does not support PDC_MODEL_CAPABILITIES call\n");
    }
    else
    {
	osbits = pdc_result[0];
	/* printf("Firmware OS bits = %d\n", osbits); */
    }

    return osbits;
}

int
pdc_cons_duplex()
{
    return (PAGE0->mem_cons.cl_class == CL_DUPLEX);
}

int
pdc_iodc_cin(char *buf, int size)
{
    int r;

    struct pz_device *in = pdc_cons_duplex() ?
				&PAGE0->mem_cons : &PAGE0->mem_kbd;

    r = firmware_call(in->iodc_io,
		in->hpa, ENTRY_IO_CIN,
		in->spa, in->dp.layers,
		pdc_result, 0, iodc_string, size, 0);

    if (r >= 0)
    {
	convert_from_wide(pdc_result);
	memcpy(buf, iodc_string, pdc_result[0]);
	return pdc_result[0];		/* count */
    }

    return r;				/* r < 0; error */
}

void
pdc_iodc_cout(const char *s, int size)
{
    int r;

    if (s[0] == 0)
	/* this test is usually the one to catch overwriting palo with kernel */
	asm("\npdc_iodc_cout_test1fail: b,n .");

    memcpy(iodc_string, s, size);

    if (s[0] != iodc_string[0] || s[0] == 0)
	asm("\npdc_iodc_cout_test2fail: b,n .");

    r = firmware_call(PAGE0->mem_cons.iodc_io,
		PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
		PAGE0->mem_cons.spa, PAGE0->mem_cons.dp.layers,
		pdc_result, 0, iodc_string, size, 0);

    if (r != 0)
	while (1);
}

int
pdc_iodc_bootin(unsigned devaddr, char *memaddr, unsigned size)
{
    int r;

    r = firmware_call(PAGE0->mem_boot.iodc_io,
		    PAGE0->mem_boot.hpa, ENTRY_IO_BOOTIN,
		    PAGE0->mem_boot.spa, PAGE0->mem_boot.dp.layers,
		    pdc_result, devaddr, memaddr, size, size);

    if (r == 3)	/* EOF */
    {
	return 0;			/* count = 0 at EOF */
    }
    else if (r >= 0)
    {
	convert_from_wide(pdc_result);
	return pdc_result[0];		/* count */
    }
    return r;				/* r < 0; error */
}

int
pdc_read_conspath(unsigned char *memaddr)
{
    int r;
    
    r = firmware_call(mem_pdc, PDC_STABLE, 0, 96, memaddr, 8);

    if (r >= 0)
    {
	convert_from_wide(pdc_result);
	return pdc_result[0];		/* count */
    }
    return r;				/* r < 0; error */
}
