diff options
Diffstat (limited to 'sys/arch/macppc/stand/Locore.c')
-rw-r--r-- | sys/arch/macppc/stand/Locore.c | 593 |
1 files changed, 593 insertions, 0 deletions
diff --git a/sys/arch/macppc/stand/Locore.c b/sys/arch/macppc/stand/Locore.c new file mode 100644 index 00000000000..e43d875d36c --- /dev/null +++ b/sys/arch/macppc/stand/Locore.c @@ -0,0 +1,593 @@ +/* $OpenBSD: Locore.c,v 1.1 2001/09/01 15:39:02 drahn Exp $ */ +/* $NetBSD: Locore.c,v 1.1 1997/04/16 20:29:11 thorpej 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 <macppc/stand/openfirm.h> + +/* +#include "machine/cpu.h" +*/ + +static int (*openfirmware)(void *); + +static void setup __P((void)); + +#ifdef XCOFF_GLUE +asm (".text; .globl _entry; _entry: .long _start,0,0"); +#endif +asm(" + .text + .globl bat_init +bat_init: + + mfmsr 8 + li 0,0 + mtmsr 0 + isync + + mtibatu 0,0 + mtibatu 1,0 + mtibatu 2,0 + mtibatu 3,0 + mtdbatu 0,0 + mtdbatu 1,0 + mtdbatu 2,0 + mtdbatu 3,0 + + li 9,0x12 /* BATL(0, BAT_M, BAT_PP_RW) */ + mtibatl 0,9 + mtdbatl 0,9 + li 9,0x1ffe /* BATU(0, BAT_BL_256M, BAT_Vs) */ + mtibatu 0,9 + mtdbatu 0,9 + isync + + mtmsr 8 + isync + blr +"); + +__dead void +_start(vpd, res, openfirm, arg, argl) + void *vpd; + int res; + int (*openfirm)(void *); + char *arg; + int argl; +{ + extern char etext[]; + +#ifdef FIRMWORKSBUGS + syncicache((void *)RELOC, etext - (char *)RELOC); +#endif + bat_init(); + openfirmware = openfirm; /* Save entry to Open Firmware */ +#if 0 + patch_dec_intr(); +#endif + setup(); + main(arg, argl); + exit(); +} + +#if 0 +void handle_decr_intr(); +__asm ( " .globl handle_decr_intr\n" + " .type handle_decr_intr@function\n" + "handle_decr_intr:\n" + " rfi\n"); + + +patch_dec_intr() +{ + int time; + unsigned int *decr_intr = (unsigned int *)0x900; + unsigned int br_instr; + + /* this hack is to prevent unexected Decrementer Exceptions + * when Apple openfirmware enables interrupts + */ + time = 0x40000000; + asm("mtdec %0" :: "r"(time)); + /* we assume that handle_decr_intr is in the first 128 Meg */ + br_instr = (18 << 23) | (unsigned int)handle_decr_intr; + *decr_intr = br_instr; + + + +} +#endif +__dead void +_rtt() +{ + static struct { + char *name; + int nargs; + int nreturns; + } args = { + "exit", + 0, + 0 + }; + + openfirmware(&args); + while (1); /* just in case */ +} + +int +OF_finddevice(name) + char *name; +{ + static struct { + char *name; + int nargs; + int nreturns; + 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(ihandle) + int ihandle; +{ + static struct { + 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(handle, prop, buf, buflen) + int handle; + char *prop; + void *buf; + int buflen; +{ + static struct { + char *name; + int nargs; + int nreturns; + int phandle; + 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(handle, prop, buf, len) + int handle; + char *prop; + void *buf; + int len; +{ + static struct { + char *name; + int nargs; + int nreturns; + int phandle; + 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(dname) + char *dname; +{ + static struct { + char *name; + int nargs; + int nreturns; + char *dname; + int handle; + } args = { + "open", + 1, + 1, + }; + + args.dname = dname; + if (openfirmware(&args) == -1) + return -1; + return args.handle; +} + +void +OF_close(handle) + int handle; +{ + static struct { + char *name; + int nargs; + int nreturns; + int handle; + } args = { + "close", + 1, + 0, + }; + + args.handle = handle; + openfirmware(&args); +} + +int +OF_write(handle, addr, len) + int handle; + void *addr; + int len; +{ + static struct { + char *name; + int nargs; + int nreturns; + int ihandle; + void *addr; + int len; + int actual; + } args = { + "write", + 3, + 1, + }; + + args.ihandle = handle; + args.addr = addr; + args.len = len; + if (openfirmware(&args) == -1) + return -1; + return args.actual; +} + +int +OF_read(handle, addr, len) + int handle; + void *addr; + int len; +{ + static struct { + char *name; + int nargs; + int nreturns; + int ihandle; + void *addr; + int len; + int actual; + } args = { + "read", + 3, + 1, + }; + + args.ihandle = handle; + args.addr = addr; + args.len = len; + if (openfirmware(&args) == -1) + return -1; + return args.actual; +} + +int +OF_seek(handle, pos) + int handle; + u_quad_t pos; +{ + static struct { + char *name; + int nargs; + int nreturns; + int handle; + int poshi; + int poslo; + int status; + } args = { + "seek", + 3, + 1, + }; + + args.handle = handle; + args.poshi = (int)(pos >> 32); + args.poslo = (int)pos; + if (openfirmware(&args) == -1) + return -1; + return args.status; +} + +void * +OF_claim(virt, size, align) + void *virt; + u_int size; + u_int align; +{ + static struct { + char *name; + int nargs; + int nreturns; + void *virt; + u_int size; + u_int align; + void *baseaddr; + } args = { + "claim", + 3, + 1, + }; + +/* +#ifdef FIRMWORKSBUGS +*/ +#if 0 + /* + * Bug with Firmworks OFW + */ + if (virt) + return virt; +#endif + args.virt = virt; + args.size = size; + args.align = align; + if (openfirmware(&args) == -1) + return (void *)-1; + if (virt != 0) { + return virt; + } + return args.baseaddr; +} + +void +OF_release(virt, size) + void *virt; + u_int size; +{ + static struct { + char *name; + int nargs; + int nreturns; + void *virt; + u_int size; + } args = { + "release", + 2, + 0, + }; + + args.virt = virt; + args.size = size; + openfirmware(&args); +} + +int +OF_milliseconds() +{ + static struct { + char *name; + int nargs; + int nreturns; + int ms; + } args = { + "milliseconds", + 0, + 1, + }; + + openfirmware(&args); + return args.ms; +} + +#ifdef __notyet__ +void +OF_chain(virt, size, entry, arg, len) + void *virt; + u_int size; + void (*entry)(); + void *arg; + u_int len; +{ + static struct { + char *name; + int nargs; + int nreturns; + void *virt; + u_int size; + void (*entry)(); + void *arg; + u_int len; + } args = { + "chain", + 5, + 0, + }; + + args.virt = virt; + args.size = size; + args.entry = entry; + args.arg = arg; + args.len = len; + openfirmware(&args); +} +#else +void +OF_chain(virt, size, entry, arg, len) + void *virt; + u_int size; + void (*entry)(); + void *arg; + u_int len; +{ + /* + * This is a REALLY dirty hack till the firmware gets this going + OF_release(virt, size); + */ + entry(0, 0, openfirmware, arg, len); +} +#endif + +int +#ifdef __STDC__ +OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...) +#else +OF_call_method(method, ihandle, nargs, nreturns, va_alist) + char *method; + int ihandle; + int nargs; + int nreturns; + va_dcl +#endif +{ + va_list ap; + static struct { + char *name; + int nargs; + int nreturns; + char *method; + int ihandle; + int args_n_results[12]; + } args = { + "call-method", + 2, + 1, + }; + int *ip, n; + + if (nargs > 6) + return -1; + args.nargs = nargs + 2; + args.nreturns = nreturns + 1; + args.method = method; + args.ihandle = ihandle; + va_start(ap, nreturns); + for (ip = args.args_n_results + (n = nargs); --n >= 0;) + *--ip = va_arg(ap, int); + + if (openfirmware(&args) == -1) + return -1; + if (args.args_n_results[nargs]) + return args.args_n_results[nargs]; + for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) + *va_arg(ap, int *) = *--ip; + va_end(ap); + return 0; +} + +static int stdin; +static int stdout; + +static void +setup() +{ + int chosen; + + if ((chosen = OF_finddevice("/chosen")) == -1) + _rtt(); + if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin) + || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != + sizeof(stdout)) + _rtt(); +} + +void +putchar(c) + int c; +{ + char ch = c; + + if (c == '\n') + putchar('\r'); + OF_write(stdout, &ch, 1); +} + +int +getchar() +{ + unsigned char ch = '\0'; + int l; + + while ((l = OF_read(stdin, &ch, 1)) != 1) + if (l != -2 && l != 0) + return -1; + return ch; +} |