NetBSD-5.0.2/sys/arch/shark/stand/ofwboot/Locore.c

Compare this file to the similar file:
Show the results in this format:

/*	$NetBSD: Locore.c,v 1.3 2005/12/11 12:19:05 christos Exp $	*/

/*
 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
 * Copyright (C) 1995, 1996 TooLs GmbH.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <lib/libsa/stand.h>

#include <machine/cpu.h>

#include <arm/armreg.h>

#include "cache.h"
#include "extern.h"
#include "openfirm.h"

static int (*openfirmware_entry)(void *);
static int openfirmware(void *);

void startup(int (*)(void *), char *, int);
static void setup(void);

void (*cache_syncI)(void);

void abort(void);
void abort(void)
{

	/* Stupid compiler (__dead). */
	for (;;)
		continue;
}

static int
openfirmware(arg)
	void *arg;
{

	(*openfirmware_entry)(arg);
	return 0;
}

static vaddr_t
ofw_getcleaninfo(void)
{
	int cpu, vclean;

	if ((cpu = OF_finddevice("/cpu")) == -1)
		panic("no /cpu from OFW");

	if (OF_getprop(cpu, "d-cache-flush-address", &vclean,
		       sizeof(vclean)) != sizeof(vclean)) {
		printf("WARNING: no OFW d-cache-flush-address property\n");
		return (RELOC);
	}

	return (of_decode_int((unsigned char *)&vclean));
}

void
startup(int (*openfirm)(void *), char *arg, int argl)
{
	u_int cputype = cpufunc_id() & CPU_ID_CPU_MASK;

	openfirmware_entry = openfirm;
	setup();

	/*
	 * Determine the CPU type, and set up the appropriate
	 * I$ sync routine.
	 */
	if (cputype == CPU_ID_SA110 || cputype == CPU_ID_SA1100 ||
	    cputype == CPU_ID_SA1110) {
		extern vaddr_t sa110_cache_clean_addr;
		cache_syncI = sa110_cache_syncI;
		sa110_cache_clean_addr = ofw_getcleaninfo();
	} else {
		printf("WARNING: no I$ sync routine for CPU 0x%x\n",
		    cputype);
	}

	main();
	OF_exit();
}

int
of_decode_int(const u_char *p)
{
	unsigned int i = *p++ << 8;
	i = (i + *p++) << 8;
	i = (i + *p++) << 8;
	return (i + *p);
}

__dead void
OF_exit(void)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
	} args = {
		"exit",
		0,
		0
	};

	openfirmware(&args);
	for (;;);			/* just in case */
}

int
OF_finddevice(const char *name)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		const char *device;
		int phandle;
	} args = {
		"finddevice",
		1,
		1,
	};	
	
	args.device = name;
	if (openfirmware(&args) == -1)
		return -1;
	return args.phandle;
}

int
OF_instance_to_package(int ihandle)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int ihandle;
		int phandle;
	} args = {
		"instance-to-package",
		1,
		1,
	};
	
	args.ihandle = ihandle;
	if (openfirmware(&args) == -1)
		return -1;
	return args.phandle;
}

int
OF_getprop(int handle, const char *prop, void *buf, int buflen)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int phandle;
		const char *prop;
		void *buf;
		int buflen;
		int size;
	} args = {
		"getprop",
		4,
		1,
	};
	
	args.phandle = handle;
	args.prop = prop;
	args.buf = buf;
	args.buflen = buflen;
	if (openfirmware(&args) == -1)
		return -1;
	return args.size;
}

#ifdef	__notyet__	/* Has a bug on FirePower */
int
OF_setprop(int handle, const char *prop, void *buf, int len)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int phandle;
		const char *prop;
		void *buf;
		int len;
		int size;
	} args = {
		"setprop",
		4,
		1,
	};
	
	args.phandle = handle;
	args.prop = prop;
	args.buf = buf;
	args.len = len;
	if (openfirmware(&args) == -1)
		return -1;
	return args.size;
}
#endif

int
OF_open(char *dname)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		char *dname;
		int handle;
	} args = {
		"open",
		1,
		1,
	};
	
#ifdef OFW_DEBUG
	printf("OF_open(%s) -> ", dname);
#endif
	args.dname = dname;
	if (openfirmware(&args) == -1 ||
	    args.handle == 0) {
#ifdef OFW_DEBUG
		printf("lose\n");
#endif
		return -1;
	}
#ifdef OFW_DEBUG
	printf("%d\n", args.handle);
#endif
	return args.handle;
}

void
OF_close(int handle)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int handle;
	} args = {
		"close",
		1,
		0,
	};
	
#ifdef OFW_DEBUG
	printf("OF_close(%d)\n", handle);
#endif
	args.handle = handle;
	openfirmware(&args);
}

int
OF_write(int handle, void *addr, int len)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int ihandle;
		void *addr;
		int len;
		int actual;
	} args = {
		"write",
		3,
		1,
	};

#ifdef OFW_DEBUG
	if (len != 1)
		printf("OF_write(%d, %x, %x) -> ", handle, addr, len);
#endif
	args.ihandle = handle;
	args.addr = addr;
	args.len = len;
	if (openfirmware(&args) == -1) {
#ifdef OFW_DEBUG
		printf("lose\n");
#endif
		return -1;
	}
#ifdef OFW_DEBUG
	if (len != 1)
		printf("%x\n", args.actual);
#endif
	return args.actual;
}

int
OF_read(int handle, void *addr, int len)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int ihandle;
		void *addr;
		int len;
		int actual;
	} args = {
		"read",
		3,
		1,
	};

#ifdef OFW_DEBUG
	if (len != 1)
		printf("OF_read(%d, %x, %x) -> ", handle, addr, len);
#endif
	args.ihandle = handle;
	args.addr = addr;
	args.len = len;
	if (openfirmware(&args) == -1) {
#ifdef OFW_DEBUG
		printf("lose\n");
#endif
		return -1;
	}
#ifdef OFW_DEBUG
	if (len != 1)
		printf("%x\n", args.actual);
#endif
	return args.actual;
}

int
OF_seek(int handle, u_quad_t pos)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int handle;
		int poshi;
		int poslo;
		int status;
	} args = {
		"seek",
		3,
		1,
	};
	
#ifdef OFW_DEBUG
	printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
#endif
	args.handle = handle;
	args.poshi = (int)(pos >> 32);
	args.poslo = (int)pos;
	if (openfirmware(&args) == -1) {
#ifdef OFW_DEBUG
		printf("lose\n");
#endif
		return -1;
	}
#ifdef OFW_DEBUG
	printf("%d\n", args.status);
#endif
	return args.status;
}

void *
OF_claim(void *virt, u_int size, u_int align)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		void *virt;
		u_int size;
		u_int align;
		void *baseaddr;
	} args = {
		"claim",
		3,
		1,
	};

#ifdef OFW_DEBUG
	printf("OF_claim(%x, %x, %x) -> ", virt, size, align);
#endif
	args.virt = virt;
	args.size = size;
	args.align = align;
	if (openfirmware(&args) == -1) {
#ifdef OFW_DEBUG
		printf("lose\n");
#endif
		return (void *)-1;
	}
#ifdef OFW_DEBUG
	printf("%x\n", args.baseaddr);
#endif
	return args.baseaddr;
}

void
OF_release(void *virt, u_int size)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		void *virt;
		u_int size;
	} args = {
		"release",
		2,
		0,
	};
	
#ifdef OFW_DEBUG
	printf("OF_release(%x, %x)\n", virt, size);
#endif
	args.virt = virt;
	args.size = size;
	openfirmware(&args);
}

int
OF_milliseconds(void)
{
	static struct {
		const char *name;
		int nargs;
		int nreturns;
		int ms;
	} args = {
		"milliseconds",
		0,
		1,
	};
	
	openfirmware(&args);
	return args.ms;
}

void
OF_chain(void *virt, u_int size, void (*entry)(int (*)(void *), void *, u_int),
    void *arg, u_int len)
{
	struct {
		const char *name;
		int nargs;
		int nreturns;
		void *virt;
		u_int size;
		void (*entry)(int (*)(void *), void *, u_int);
		void *arg;
		u_int len;
	} args;

	args.name = "chain";
	args.nargs = 5;
	args.nreturns = 0;
	args.virt = virt;
	args.size = size;
	args.entry = entry;
	args.arg = arg;
	args.len = len;
#if 1
	openfirmware(&args);
#else
	entry(openfirmware_entry, arg, len);
#endif
}

static int stdin;
static int stdout;

static void
setup(void)
{
	u_char buf[sizeof(int)];
	int chosen;

	if ((chosen = OF_finddevice("/chosen")) == -1)
		OF_exit();

	if (OF_getprop(chosen, "stdin", buf, sizeof(buf)) != sizeof(buf))
		OF_exit();
	stdin = of_decode_int(buf);

	if (OF_getprop(chosen, "stdout", buf, sizeof(buf)) != sizeof(buf))
		OF_exit();
	stdout = of_decode_int(buf);
}

void
putchar(int c)
{
	char ch = c;

	if (c == '\n')
		putchar('\r');
	OF_write(stdout, &ch, 1);
}

int
getchar(void)
{
	unsigned char ch = '\0';
	int l;

	while ((l = OF_read(stdin, &ch, 1)) != 1)
		if (l != -2 && l != 0)
			return -1;
	return ch;
}