Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | ||
24 | static struct linux_romvec sun4romvec; | |
25 | static struct idprom sun4_idprom; | |
26 | ||
27 | struct property { | |
28 | char *name; | |
29 | char *value; | |
30 | int length; | |
31 | }; | |
32 | ||
33 | struct node { | |
34 | int level; | |
35 | struct property *properties; | |
36 | }; | |
37 | ||
38 | struct property null_properties = { NULL, NULL, -1 }; | |
39 | ||
40 | struct property root_properties[] = { | |
41 | {"device_type", "cpu", 4}, | |
42 | {"idprom", (char *)&sun4_idprom, sizeof(struct idprom)}, | |
43 | {NULL, NULL, -1} | |
44 | }; | |
45 | ||
46 | struct node nodes[] = { | |
47 | { 0, &null_properties }, | |
48 | { 0, root_properties }, | |
49 | { -1,&null_properties } | |
50 | }; | |
51 | ||
52 | ||
53 | static int no_nextnode(int node) | |
54 | { | |
55 | if (nodes[node].level == nodes[node+1].level) | |
56 | return node+1; | |
57 | return -1; | |
58 | } | |
59 | ||
60 | static 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 | ||
67 | static 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 | ||
77 | static 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 | ||
84 | static 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 | ||
94 | static int no_setprop(int node,char *name,char *value,int len) | |
95 | { | |
96 | return -1; | |
97 | } | |
98 | ||
99 | static 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 | ||
106 | static 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 | ||
115 | static int synch_hook; | |
116 | ||
117 | struct 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 | */ | |
3c51f196 | 154 | sun4_romvec->setLEDs(NULL); |
1da177e4 LT |
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 | } |