197403Sobrien/* $NetBSD: Locore.c,v 1.3 2005/12/11 12:19:05 christos Exp $ */ 297403Sobrien 397403Sobrien/* 497403Sobrien * Copyright (C) 1995, 1996 Wolfgang Solfrank. 597403Sobrien * Copyright (C) 1995, 1996 TooLs GmbH. 697403Sobrien * All rights reserved. 797403Sobrien * 897403Sobrien * Redistribution and use in source and binary forms, with or without 997403Sobrien * modification, are permitted provided that the following conditions 1097403Sobrien * are met: 1197403Sobrien * 1. Redistributions of source code must retain the above copyright 1297403Sobrien * notice, this list of conditions and the following disclaimer. 1397403Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1497403Sobrien * notice, this list of conditions and the following disclaimer in the 1597403Sobrien * documentation and/or other materials provided with the distribution. 1697403Sobrien * 3. All advertising materials mentioning features or use of this software 1797403Sobrien * must display the following acknowledgement: 1897403Sobrien * This product includes software developed by TooLs GmbH. 1997403Sobrien * 4. The name of TooLs GmbH may not be used to endorse or promote products 2097403Sobrien * derived from this software without specific prior written permission. 2197403Sobrien * 2297403Sobrien * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 2397403Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2497403Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2597403Sobrien * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2697403Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2797403Sobrien * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2897403Sobrien * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2997403Sobrien * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 3097403Sobrien * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 3197403Sobrien * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3297403Sobrien */ 3397403Sobrien 3497403Sobrien#include <lib/libsa/stand.h> 3597403Sobrien 3697403Sobrien#include <machine/cpu.h> 3797403Sobrien 3897403Sobrien#include <arm/armreg.h> 3997403Sobrien 4097403Sobrien#include "cache.h" 4197403Sobrien#include "extern.h" 4297403Sobrien#include "openfirm.h" 4397403Sobrien 4497403Sobrienstatic int (*openfirmware_entry)(void *); 4597403Sobrienstatic int openfirmware(void *); 4697403Sobrien 4797403Sobrienvoid startup(int (*)(void *), char *, int); 4897403Sobrienstatic void setup(void); 4997403Sobrien 5097403Sobrienvoid (*cache_syncI)(void); 5197403Sobrien 5297403Sobrienvoid abort(void); 5397403Sobrienvoid abort(void) 5497403Sobrien{ 5597403Sobrien 5697403Sobrien /* Stupid compiler (__dead). */ 5797403Sobrien for (;;) 5897403Sobrien continue; 5997403Sobrien} 6097403Sobrien 6197403Sobrienstatic int 6297403Sobrienopenfirmware(void *arg) 6397403Sobrien{ 6497403Sobrien 6597403Sobrien (*openfirmware_entry)(arg); 6697403Sobrien return 0; 6797403Sobrien} 6897403Sobrien 6997403Sobrienstatic vaddr_t 7097403Sobrienofw_getcleaninfo(void) 7197403Sobrien{ 7297403Sobrien int cpu, vclean; 7397403Sobrien 7497403Sobrien if ((cpu = OF_finddevice("/cpu")) == -1) 7597403Sobrien panic("no /cpu from OFW"); 7697403Sobrien 7797403Sobrien if (OF_getprop(cpu, "d-cache-flush-address", &vclean, 7897403Sobrien sizeof(vclean)) != sizeof(vclean)) { 7997403Sobrien printf("WARNING: no OFW d-cache-flush-address property\n"); 8097403Sobrien return (RELOC); 8197403Sobrien } 8297403Sobrien 8397403Sobrien return (of_decode_int((unsigned char *)&vclean)); 8497403Sobrien} 8597403Sobrien 8697403Sobrienvoid 8797403Sobrienstartup(int (*openfirm)(void *), char *arg, int argl) 8897403Sobrien{ 8997403Sobrien u_int cputype = cpufunc_id() & CPU_ID_CPU_MASK; 9097403Sobrien 9197403Sobrien openfirmware_entry = openfirm; 9297403Sobrien setup(); 9397403Sobrien 9497403Sobrien /* 9597403Sobrien * Determine the CPU type, and set up the appropriate 9697403Sobrien * I$ sync routine. 9797403Sobrien */ 9897403Sobrien if (cputype == CPU_ID_SA110 || cputype == CPU_ID_SA1100 || 9997403Sobrien cputype == CPU_ID_SA1110) { 10097403Sobrien extern vaddr_t sa110_cache_clean_addr; 10197403Sobrien cache_syncI = sa110_cache_syncI; 10297403Sobrien sa110_cache_clean_addr = ofw_getcleaninfo(); 10397403Sobrien } else { 10497403Sobrien printf("WARNING: no I$ sync routine for CPU 0x%x\n", 10597403Sobrien cputype); 10697403Sobrien } 10797403Sobrien 10897403Sobrien main(); 10997403Sobrien OF_exit(); 11097403Sobrien} 11197403Sobrien 11297403Sobrienint 11397403Sobrienof_decode_int(const u_char *p) 11497403Sobrien{ 11597403Sobrien unsigned int i = *p++ << 8; 11697403Sobrien i = (i + *p++) << 8; 11797403Sobrien i = (i + *p++) << 8; 11897403Sobrien return (i + *p); 11997403Sobrien} 12097403Sobrien 12197403Sobrien__dead void 12297403SobrienOF_exit(void) 12397403Sobrien{ 12497403Sobrien static struct { 12597403Sobrien const char *name; 12697403Sobrien int nargs; 12797403Sobrien int nreturns; 12897403Sobrien } args = { 12997403Sobrien "exit", 13097403Sobrien 0, 13197403Sobrien 0 13297403Sobrien }; 13397403Sobrien 13497403Sobrien openfirmware(&args); 13597403Sobrien for (;;); /* just in case */ 13697403Sobrien} 13797403Sobrien 13897403Sobrienint 13997403SobrienOF_finddevice(const char *name) 14097403Sobrien{ 14197403Sobrien static struct { 14297403Sobrien const char *name; 14397403Sobrien int nargs; 14497403Sobrien int nreturns; 14597403Sobrien const char *device; 14697403Sobrien int phandle; 14797403Sobrien } args = { 14897403Sobrien "finddevice", 14997403Sobrien 1, 15097403Sobrien 1, 15197403Sobrien }; 15297403Sobrien 15397403Sobrien args.device = name; 15497403Sobrien if (openfirmware(&args) == -1) 15597403Sobrien return -1; 15697403Sobrien return args.phandle; 15797403Sobrien} 15897403Sobrien 15997403Sobrienint 16097403SobrienOF_instance_to_package(int ihandle) 16197403Sobrien{ 16297403Sobrien static struct { 16397403Sobrien const char *name; 16497403Sobrien int nargs; 16597403Sobrien int nreturns; 16697403Sobrien int ihandle; 16797403Sobrien int phandle; 16897403Sobrien } args = { 16997403Sobrien "instance-to-package", 17097403Sobrien 1, 17197403Sobrien 1, 17297403Sobrien }; 17397403Sobrien 17497403Sobrien args.ihandle = ihandle; 17597403Sobrien if (openfirmware(&args) == -1) 17697403Sobrien return -1; 17797403Sobrien return args.phandle; 17897403Sobrien} 17997403Sobrien 18097403Sobrienint 18197403SobrienOF_getprop(int handle, const char *prop, void *buf, int buflen) 18297403Sobrien{ 18397403Sobrien static struct { 18497403Sobrien const char *name; 18597403Sobrien int nargs; 18697403Sobrien int nreturns; 18797403Sobrien int phandle; 18897403Sobrien const char *prop; 18997403Sobrien void *buf; 19097403Sobrien int buflen; 19197403Sobrien int size; 19297403Sobrien } args = { 19397403Sobrien "getprop", 19497403Sobrien 4, 19597403Sobrien 1, 19697403Sobrien }; 19797403Sobrien 19897403Sobrien args.phandle = handle; 19997403Sobrien args.prop = prop; 20097403Sobrien args.buf = buf; 20197403Sobrien args.buflen = buflen; 20297403Sobrien if (openfirmware(&args) == -1) 20397403Sobrien return -1; 20497403Sobrien return args.size; 20597403Sobrien} 20697403Sobrien 20797403Sobrien#ifdef __notyet__ /* Has a bug on FirePower */ 20897403Sobrienint 20997403SobrienOF_setprop(int handle, const char *prop, void *buf, int len) 21097403Sobrien{ 21197403Sobrien static struct { 21297403Sobrien const char *name; 21397403Sobrien int nargs; 21497403Sobrien int nreturns; 21597403Sobrien int phandle; 21697403Sobrien const char *prop; 21797403Sobrien void *buf; 21897403Sobrien int len; 21997403Sobrien int size; 22097403Sobrien } args = { 22197403Sobrien "setprop", 22297403Sobrien 4, 22397403Sobrien 1, 22497403Sobrien }; 22597403Sobrien 22697403Sobrien args.phandle = handle; 22797403Sobrien args.prop = prop; 22897403Sobrien args.buf = buf; 22997403Sobrien args.len = len; 23097403Sobrien if (openfirmware(&args) == -1) 23197403Sobrien return -1; 23297403Sobrien return args.size; 23397403Sobrien} 23497403Sobrien#endif 23597403Sobrien 23697403Sobrienint 23797403SobrienOF_open(char *dname) 23897403Sobrien{ 23997403Sobrien static struct { 24097403Sobrien const char *name; 24197403Sobrien int nargs; 24297403Sobrien int nreturns; 24397403Sobrien char *dname; 24497403Sobrien int handle; 24597403Sobrien } args = { 24697403Sobrien "open", 24797403Sobrien 1, 24897403Sobrien 1, 24997403Sobrien }; 25097403Sobrien 25197403Sobrien#ifdef OFW_DEBUG 25297403Sobrien printf("OF_open(%s) -> ", dname); 25397403Sobrien#endif 25497403Sobrien args.dname = dname; 25597403Sobrien if (openfirmware(&args) == -1 || 25697403Sobrien args.handle == 0) { 25797403Sobrien#ifdef OFW_DEBUG 25897403Sobrien printf("lose\n"); 25997403Sobrien#endif 26097403Sobrien return -1; 26197403Sobrien } 26297403Sobrien#ifdef OFW_DEBUG 26397403Sobrien printf("%d\n", args.handle); 26497403Sobrien#endif 26597403Sobrien return args.handle; 26697403Sobrien} 26797403Sobrien 26897403Sobrienvoid 26997403SobrienOF_close(int handle) 27097403Sobrien{ 27197403Sobrien static struct { 27297403Sobrien const char *name; 27397403Sobrien int nargs; 27497403Sobrien int nreturns; 27597403Sobrien int handle; 27697403Sobrien } args = { 27797403Sobrien "close", 27897403Sobrien 1, 27997403Sobrien 0, 28097403Sobrien }; 28197403Sobrien 28297403Sobrien#ifdef OFW_DEBUG 28397403Sobrien printf("OF_close(%d)\n", handle); 28497403Sobrien#endif 28597403Sobrien args.handle = handle; 28697403Sobrien openfirmware(&args); 28797403Sobrien} 28897403Sobrien 28997403Sobrienint 29097403SobrienOF_write(int handle, void *addr, int len) 29197403Sobrien{ 29297403Sobrien static struct { 29397403Sobrien const char *name; 29497403Sobrien int nargs; 29597403Sobrien int nreturns; 29697403Sobrien int ihandle; 29797403Sobrien void *addr; 29897403Sobrien int len; 29997403Sobrien int actual; 30097403Sobrien } args = { 30197403Sobrien "write", 30297403Sobrien 3, 30397403Sobrien 1, 30497403Sobrien }; 30597403Sobrien 30697403Sobrien#ifdef OFW_DEBUG 30797403Sobrien if (len != 1) 30897403Sobrien printf("OF_write(%d, %x, %x) -> ", handle, addr, len); 30997403Sobrien#endif 31097403Sobrien args.ihandle = handle; 31197403Sobrien args.addr = addr; 31297403Sobrien args.len = len; 31397403Sobrien if (openfirmware(&args) == -1) { 31497403Sobrien#ifdef OFW_DEBUG 31597403Sobrien printf("lose\n"); 31697403Sobrien#endif 31797403Sobrien return -1; 31897403Sobrien } 31997403Sobrien#ifdef OFW_DEBUG 32097403Sobrien if (len != 1) 32197403Sobrien printf("%x\n", args.actual); 32297403Sobrien#endif 32397403Sobrien return args.actual; 32497403Sobrien} 32597403Sobrien 32697403Sobrienint 32797403SobrienOF_read(int handle, void *addr, int len) 32897403Sobrien{ 32997403Sobrien static struct { 33097403Sobrien const char *name; 33197403Sobrien int nargs; 33297403Sobrien int nreturns; 33397403Sobrien int ihandle; 33497403Sobrien void *addr; 33597403Sobrien int len; 33697403Sobrien int actual; 33797403Sobrien } args = { 33897403Sobrien "read", 33997403Sobrien 3, 34097403Sobrien 1, 34197403Sobrien }; 34297403Sobrien 34397403Sobrien#ifdef OFW_DEBUG 34497403Sobrien if (len != 1) 34597403Sobrien printf("OF_read(%d, %x, %x) -> ", handle, addr, len); 34697403Sobrien#endif 34797403Sobrien args.ihandle = handle; 34897403Sobrien args.addr = addr; 34997403Sobrien args.len = len; 35097403Sobrien if (openfirmware(&args) == -1) { 35197403Sobrien#ifdef OFW_DEBUG 35297403Sobrien printf("lose\n"); 35397403Sobrien#endif 35497403Sobrien return -1; 35597403Sobrien } 35697403Sobrien#ifdef OFW_DEBUG 35797403Sobrien if (len != 1) 35897403Sobrien printf("%x\n", args.actual); 35997403Sobrien#endif 36097403Sobrien return args.actual; 36197403Sobrien} 36297403Sobrien 36397403Sobrienint 36497403SobrienOF_seek(int handle, u_quad_t pos) 36597403Sobrien{ 36697403Sobrien static struct { 36797403Sobrien const char *name; 36897403Sobrien int nargs; 36997403Sobrien int nreturns; 37097403Sobrien int handle; 37197403Sobrien int poshi; 37297403Sobrien int poslo; 37397403Sobrien int status; 37497403Sobrien } args = { 37597403Sobrien "seek", 37697403Sobrien 3, 37797403Sobrien 1, 37897403Sobrien }; 37997403Sobrien 38097403Sobrien#ifdef OFW_DEBUG 38197403Sobrien printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos); 38297403Sobrien#endif 38397403Sobrien args.handle = handle; 38497403Sobrien args.poshi = (int)(pos >> 32); 38597403Sobrien args.poslo = (int)pos; 38697403Sobrien if (openfirmware(&args) == -1) { 38797403Sobrien#ifdef OFW_DEBUG 38897403Sobrien printf("lose\n"); 38997403Sobrien#endif 39097403Sobrien return -1; 39197403Sobrien } 39297403Sobrien#ifdef OFW_DEBUG 39397403Sobrien printf("%d\n", args.status); 39497403Sobrien#endif 39597403Sobrien return args.status; 39697403Sobrien} 39797403Sobrien 39897403Sobrienvoid * 39997403SobrienOF_claim(void *virt, u_int size, u_int align) 40097403Sobrien{ 40197403Sobrien static struct { 40297403Sobrien const char *name; 40397403Sobrien int nargs; 40497403Sobrien int nreturns; 40597403Sobrien void *virt; 40697403Sobrien u_int size; 40797403Sobrien u_int align; 40897403Sobrien void *baseaddr; 40997403Sobrien } args = { 41097403Sobrien "claim", 41197403Sobrien 3, 41297403Sobrien 1, 41397403Sobrien }; 41497403Sobrien 41597403Sobrien#ifdef OFW_DEBUG 41697403Sobrien printf("OF_claim(%x, %x, %x) -> ", virt, size, align); 41797403Sobrien#endif 41897403Sobrien args.virt = virt; 41997403Sobrien args.size = size; 42097403Sobrien args.align = align; 42197403Sobrien if (openfirmware(&args) == -1) { 42297403Sobrien#ifdef OFW_DEBUG 42397403Sobrien printf("lose\n"); 42497403Sobrien#endif 42597403Sobrien return (void *)-1; 42697403Sobrien } 42797403Sobrien#ifdef OFW_DEBUG 42897403Sobrien printf("%x\n", args.baseaddr); 42997403Sobrien#endif 43097403Sobrien return args.baseaddr; 43197403Sobrien} 43297403Sobrien 43397403Sobrienvoid 43497403SobrienOF_release(void *virt, u_int size) 43597403Sobrien{ 43697403Sobrien static struct { 43797403Sobrien const char *name; 43897403Sobrien int nargs; 43997403Sobrien int nreturns; 44097403Sobrien void *virt; 44197403Sobrien u_int size; 44297403Sobrien } args = { 44397403Sobrien "release", 44497403Sobrien 2, 44597403Sobrien 0, 44697403Sobrien }; 44797403Sobrien 44897403Sobrien#ifdef OFW_DEBUG 44997403Sobrien printf("OF_release(%x, %x)\n", virt, size); 45097403Sobrien#endif 45197403Sobrien args.virt = virt; 45297403Sobrien args.size = size; 45397403Sobrien openfirmware(&args); 45497403Sobrien} 45597403Sobrien 45697403Sobrienint 45797403SobrienOF_milliseconds(void) 45897403Sobrien{ 45997403Sobrien static struct { 46097403Sobrien const char *name; 46197403Sobrien int nargs; 46297403Sobrien int nreturns; 46397403Sobrien int ms; 46497403Sobrien } args = { 46597403Sobrien "milliseconds", 46697403Sobrien 0, 46797403Sobrien 1, 46897403Sobrien }; 46997403Sobrien 47097403Sobrien openfirmware(&args); 47197403Sobrien return args.ms; 47297403Sobrien} 47397403Sobrien 47497403Sobrienvoid 47597403SobrienOF_chain(void *virt, u_int size, void (*entry)(int (*)(void *), void *, u_int), 47697403Sobrien void *arg, u_int len) 47797403Sobrien{ 47897403Sobrien struct { 47997403Sobrien const char *name; 48097403Sobrien int nargs; 48197403Sobrien int nreturns; 48297403Sobrien void *virt; 48397403Sobrien u_int size; 48497403Sobrien void (*entry)(int (*)(void *), void *, u_int); 48597403Sobrien void *arg; 48697403Sobrien u_int len; 48797403Sobrien } args; 48897403Sobrien 48997403Sobrien args.name = "chain"; 49097403Sobrien args.nargs = 5; 49197403Sobrien args.nreturns = 0; 49297403Sobrien args.virt = virt; 49397403Sobrien args.size = size; 49497403Sobrien args.entry = entry; 49597403Sobrien args.arg = arg; 49697403Sobrien args.len = len; 49797403Sobrien#if 1 49897403Sobrien openfirmware(&args); 49997403Sobrien#else 50097403Sobrien entry(openfirmware_entry, arg, len); 50197403Sobrien#endif 50297403Sobrien} 50397403Sobrien 50497403Sobrienstatic int stdin; 50597403Sobrienstatic int stdout; 50697403Sobrien 50797403Sobrienstatic void 50897403Sobriensetup(void) 50997403Sobrien{ 51097403Sobrien u_char buf[sizeof(int)]; 51197403Sobrien int chosen; 51297403Sobrien 51397403Sobrien if ((chosen = OF_finddevice("/chosen")) == -1) 51497403Sobrien OF_exit(); 51597403Sobrien 51697403Sobrien if (OF_getprop(chosen, "stdin", buf, sizeof(buf)) != sizeof(buf)) 51797403Sobrien OF_exit(); 51897403Sobrien stdin = of_decode_int(buf); 51997403Sobrien 52097403Sobrien if (OF_getprop(chosen, "stdout", buf, sizeof(buf)) != sizeof(buf)) 52197403Sobrien OF_exit(); 52297403Sobrien stdout = of_decode_int(buf); 52397403Sobrien} 52497403Sobrien 52597403Sobrienvoid 52697403Sobrienputchar(int c) 52797403Sobrien{ 52897403Sobrien char ch = c; 52997403Sobrien 53097403Sobrien if (c == '\n') 53197403Sobrien putchar('\r'); 53297403Sobrien OF_write(stdout, &ch, 1); 53397403Sobrien} 53497403Sobrien 53597403Sobrienint 53697403Sobriengetchar(void) 53797403Sobrien{ 53897403Sobrien unsigned char ch = '\0'; 53997403Sobrien int l; 54097403Sobrien 54197403Sobrien while ((l = OF_read(stdin, &ch, 1)) != 1) 54297403Sobrien if (l != -2 && l != 0) 54397403Sobrien return -1; 54497403Sobrien return ch; 54597403Sobrien} 54697403Sobrien