1/*
2 * Copyright (C) 1996 The Australian National University.
3 * Copyright (C) 1996 Fujitsu Laboratories Limited
4 * Copyright (C) 1997 Michael A. Griffith (grif@acm.org)
5 * Copyright (C) 1997 Sun Weenie (ko@ko.reno.nv.us)
6 * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
7 *
8 * This software may be distributed under the terms of the Gnu
9 * Public License version 2 or later
10 *
11 * fake a really simple Sun prom for the SUN4
12 */
13
14#include <linux/kernel.h>
15#include <linux/string.h>
16#include <asm/oplib.h>
17#include <asm/idprom.h>
18#include <asm/machines.h>
19#include <asm/sun4prom.h>
20#include <asm/asi.h>
21#include <asm/contregs.h>
22#include <linux/init.h>
23
24static struct linux_romvec sun4romvec;
25static struct idprom sun4_idprom;
26
27struct property {
28	char *name;
29	char *value;
30	int length;
31};
32
33struct node {
34	int level;
35	struct property *properties;
36};
37
38struct property null_properties = { NULL, NULL, -1 };
39
40struct property root_properties[] = {
41	{"device_type", "cpu", 4},
42	{"idprom", (char *)&sun4_idprom, sizeof(struct idprom)},
43	{NULL, NULL, -1}
44};
45
46struct node nodes[] = {
47	{ 0, &null_properties },
48	{ 0, root_properties },
49	{ -1,&null_properties }
50};
51
52
53static int no_nextnode(int node)
54{
55	if (nodes[node].level == nodes[node+1].level)
56		return node+1;
57	return -1;
58}
59
60static int no_child(int node)
61{
62	if (nodes[node].level == nodes[node+1].level-1)
63		return node+1;
64	return -1;
65}
66
67static struct property *find_property(int node,char *name)
68{
69	struct property *prop = &nodes[node].properties[0];
70	while (prop && prop->name) {
71		if (strcmp(prop->name,name) == 0) return prop;
72		prop++;
73	}
74	return NULL;
75}
76
77static int no_proplen(int node,char *name)
78{
79	struct property *prop = find_property(node,name);
80	if (prop) return prop->length;
81	return -1;
82}
83
84static int no_getprop(int node,char *name,char *value)
85{
86	struct property *prop = find_property(node,name);
87	if (prop) {
88		memcpy(value,prop->value,prop->length);
89		return 1;
90	}
91	return -1;
92}
93
94static int no_setprop(int node,char *name,char *value,int len)
95{
96	return -1;
97}
98
99static char *no_nextprop(int node,char *name)
100{
101	struct property *prop = find_property(node,name);
102	if (prop) return prop[1].name;
103	return NULL;
104}
105
106static struct linux_nodeops sun4_nodeops = {
107	no_nextnode,
108	no_child,
109	no_proplen,
110	no_getprop,
111	no_setprop,
112	no_nextprop
113};
114
115static int synch_hook;
116
117struct linux_romvec * __init sun4_prom_init(void)
118{
119	int i;
120	unsigned char x;
121	char *p;
122
123	p = (char *)&sun4_idprom;
124	for (i = 0; i < sizeof(sun4_idprom); i++) {
125		__asm__ __volatile__ ("lduba [%1] %2, %0" : "=r" (x) :
126				      "r" (AC_IDPROM + i), "i" (ASI_CONTROL));
127		*p++ = x;
128	}
129
130	memset(&sun4romvec,0,sizeof(sun4romvec));
131
132	sun4_romvec = (linux_sun4_romvec *) SUN4_PROM_VECTOR;
133
134	sun4romvec.pv_romvers = 40;
135	sun4romvec.pv_nodeops = &sun4_nodeops;
136	sun4romvec.pv_reboot = sun4_romvec->reboot;
137	sun4romvec.pv_abort = sun4_romvec->abortentry;
138	sun4romvec.pv_halt = sun4_romvec->exittomon;
139	sun4romvec.pv_synchook = (void (**)(void))&synch_hook;
140	sun4romvec.pv_setctxt = sun4_romvec->setcxsegmap;
141	sun4romvec.pv_v0bootargs = sun4_romvec->bootParam;
142	sun4romvec.pv_nbgetchar = sun4_romvec->mayget;
143	sun4romvec.pv_nbputchar = sun4_romvec->mayput;
144	sun4romvec.pv_stdin = sun4_romvec->insource;
145	sun4romvec.pv_stdout = sun4_romvec->outsink;
146
147	/*
148	 * We turn on the LEDs to let folks without monitors or
149	 * terminals know we booted.   Nothing too fancy now.  They
150	 * are all on, except for LED 5, which blinks.   When we
151	 * have more time, we can teach the penguin to say "By your
152	 * command" or "Activating turbo boost, Michael". :-)
153	 */
154	sun4_romvec->setLEDs(NULL);
155
156	printk("PROMLIB: Old Sun4 boot PROM monitor %s, romvec version %d\n",
157		sun4_romvec->monid,
158		sun4_romvec->romvecversion);
159
160	return &sun4romvec;
161}
162