diff options
Diffstat (limited to 'arch/sparc/prom/sun4prom.c')
-rw-r--r-- | arch/sparc/prom/sun4prom.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/arch/sparc/prom/sun4prom.c b/arch/sparc/prom/sun4prom.c new file mode 100644 index 0000000..69ca735 --- /dev/null +++ b/arch/sparc/prom/sun4prom.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 1996 The Australian National University. + * Copyright (C) 1996 Fujitsu Laboratories Limited + * Copyright (C) 1997 Michael A. Griffith (grif@acm.org) + * Copyright (C) 1997 Sun Weenie (ko@ko.reno.nv.us) + * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * This software may be distributed under the terms of the Gnu + * Public License version 2 or later + * + * fake a really simple Sun prom for the SUN4 + */ + +#include <linux/kernel.h> +#include <linux/string.h> +#include <asm/oplib.h> +#include <asm/idprom.h> +#include <asm/machines.h> +#include <asm/sun4prom.h> +#include <asm/asi.h> +#include <asm/contregs.h> +#include <linux/init.h> + +static struct linux_romvec sun4romvec; +static struct idprom sun4_idprom; + +struct property { + char *name; + char *value; + int length; +}; + +struct node { + int level; + struct property *properties; +}; + +struct property null_properties = { NULL, NULL, -1 }; + +struct property root_properties[] = { + {"device_type", "cpu", 4}, + {"idprom", (char *)&sun4_idprom, sizeof(struct idprom)}, + {NULL, NULL, -1} +}; + +struct node nodes[] = { + { 0, &null_properties }, + { 0, root_properties }, + { -1,&null_properties } +}; + + +static int no_nextnode(int node) +{ + if (nodes[node].level == nodes[node+1].level) + return node+1; + return -1; +} + +static int no_child(int node) +{ + if (nodes[node].level == nodes[node+1].level-1) + return node+1; + return -1; +} + +static struct property *find_property(int node,char *name) +{ + struct property *prop = &nodes[node].properties[0]; + while (prop && prop->name) { + if (strcmp(prop->name,name) == 0) return prop; + prop++; + } + return NULL; +} + +static int no_proplen(int node,char *name) +{ + struct property *prop = find_property(node,name); + if (prop) return prop->length; + return -1; +} + +static int no_getprop(int node,char *name,char *value) +{ + struct property *prop = find_property(node,name); + if (prop) { + memcpy(value,prop->value,prop->length); + return 1; + } + return -1; +} + +static int no_setprop(int node,char *name,char *value,int len) +{ + return -1; +} + +static char *no_nextprop(int node,char *name) +{ + struct property *prop = find_property(node,name); + if (prop) return prop[1].name; + return NULL; +} + +static struct linux_nodeops sun4_nodeops = { + no_nextnode, + no_child, + no_proplen, + no_getprop, + no_setprop, + no_nextprop +}; + +static int synch_hook; + +struct linux_romvec * __init sun4_prom_init(void) +{ + int i; + unsigned char x; + char *p; + + p = (char *)&sun4_idprom; + for (i = 0; i < sizeof(sun4_idprom); i++) { + __asm__ __volatile__ ("lduba [%1] %2, %0" : "=r" (x) : + "r" (AC_IDPROM + i), "i" (ASI_CONTROL)); + *p++ = x; + } + + memset(&sun4romvec,0,sizeof(sun4romvec)); + + sun4_romvec = (linux_sun4_romvec *) SUN4_PROM_VECTOR; + + sun4romvec.pv_romvers = 40; + sun4romvec.pv_nodeops = &sun4_nodeops; + sun4romvec.pv_reboot = sun4_romvec->reboot; + sun4romvec.pv_abort = sun4_romvec->abortentry; + sun4romvec.pv_halt = sun4_romvec->exittomon; + sun4romvec.pv_synchook = (void (**)(void))&synch_hook; + sun4romvec.pv_setctxt = sun4_romvec->setcxsegmap; + sun4romvec.pv_v0bootargs = sun4_romvec->bootParam; + sun4romvec.pv_nbgetchar = sun4_romvec->mayget; + sun4romvec.pv_nbputchar = sun4_romvec->mayput; + sun4romvec.pv_stdin = sun4_romvec->insource; + sun4romvec.pv_stdout = sun4_romvec->outsink; + + /* + * We turn on the LEDs to let folks without monitors or + * terminals know we booted. Nothing too fancy now. They + * are all on, except for LED 5, which blinks. When we + * have more time, we can teach the penguin to say "By your + * command" or "Activating turbo boost, Michael". :-) + */ + sun4_romvec->setLEDs(0x0); + + printk("PROMLIB: Old Sun4 boot PROM monitor %s, romvec version %d\n", + sun4_romvec->monid, + sun4_romvec->romvecversion); + + return &sun4romvec; +} |