Lynx framebuffers multidomain implementation.
[linux/elbrus.git] / drivers / mcst / prom / e90_prom.c
blob0762b8775655e9886dd72aa5206643bf0e90e6a6
2 #include <linux/types.h>
3 #include <linux/string.h>
4 #include <linux/ctype.h>
5 #include <linux/mm.h>
6 #include <asm/sbus.h>
7 #include <asm-l/tree_entry.h>
8 #include <linux/of.h>
10 #undef DEBUG
11 #define DEBUG
12 #undef DEBUG
14 #ifdef DEBUG
15 #define dbg(fmt, args...) prom_printf( fmt "\n", ## args)
16 #else
17 #define dbg(fmt, args...)
18 #endif
19 #define info(fmt, args...) prom_printf(KERN_INFO fmt "\n", ## args)
21 #ifdef __e2k__
22 #define prom_printf printk
23 #endif
26 int prom_getchild(int node)
28 struct tree_entry *e = get_te_by_node(node);
29 return e->child ? (int) e->child->node : 0;
31 EXPORT_SYMBOL(prom_getchild);
33 /* Acquire a property 'prop' at node 'node' and place it in
34 * 'buffer' which has a size of 'bufsize'. If the acquisition
35 * was successful the length will be returned, else -1 is returned.
37 int prom_getproperty(int node, const char *prop, char *buffer, int bufsize)
39 struct tree_entry *e;
40 int i;
41 if (node == 0)
42 return -1;
43 e = get_te_by_node(node);
44 for (i = 0; e->prop[i].name && i < MAX_PROPERTY; i++) {
45 if (strcmp(prop, e->prop[i].name) == 0) {
46 int size =
47 e->prop[i].size <
48 bufsize ? e->prop[i].size : bufsize;
49 memcpy(buffer, e->prop[i].value, size);
50 return size;
53 dbg("property '%s' at node '%s' not found.", prop,
54 (char *) e->prop[ATTRIB_NAME].value);
55 return -1;
57 EXPORT_SYMBOL(prom_getproperty);
59 int of_getintprop_default(struct device_node *np, const char *name, int def)
61 struct property *prop;
62 int len;
64 prop = of_find_property(np, name, &len);
65 if (!prop || len != 4)
66 return def;
67 return *(int *) prop->value;
69 EXPORT_SYMBOL(of_getintprop_default);
71 int prom_node_has_property(int node, char *prop)
73 dbg("Fboot warning: prom_node_has_property called");
74 return 0;
77 /* Return the length in bytes of property 'prop' at node 'node'.
78 * Return -1 on error.
80 int prom_getproplen(int node, const char *prop)
82 struct tree_entry *e;
83 int i;
84 if (node == 0)
85 return -1;
86 e = get_te_by_node(node);
87 for (i = 0; e->prop[i].name && i < MAX_PROPERTY; i++) {
88 if (!strcmp(prop, e->prop[i].name))
89 return e->prop[i].size;
91 dbg("property '%s' at node '%s' not found.", prop,
92 (char *) e->prop[ATTRIB_NAME].value);
93 return -1;
95 EXPORT_SYMBOL(prom_getproplen);
97 /* Set property 'pname' at node 'node' to value 'value' which has a length
98 * of 'size' bytes. Return the number of bytes the prom accepted.
100 int prom_setprop(int node, const char *pname, char *value, int size)
102 struct tree_entry *e;
103 int i;
105 if(size == 0) return 0;
106 if((pname == 0) || (value == 0) || (node == 0)) return 0;
107 e = get_te_by_node(node);
108 for (i = 0; i < MAX_PROPERTY; i++) {
109 if (e->prop[i].name == NULL) {
110 break;
113 if (i >= MAX_PROPERTY) {
114 return 0;
116 e->prop[i].name = kmalloc(strlen(pname) + 1, GFP_KERNEL);
117 if (!e->prop[i].name) {
118 return 0;
120 memcpy((char *)e->prop[i].name, (char *)pname, strlen(pname) + 1);
122 e->prop[i].value = kmalloc(size, GFP_KERNEL);
123 if (!e->prop[i].value) {
124 kfree(e->prop[i].name);
125 e->prop[i].name = NULL;
126 return 0;
128 memcpy(e->prop[i].value, value, size);
129 e->prop[i].size = size;
131 return size;
133 EXPORT_SYMBOL(prom_setprop);
135 /* Return the first property name for node 'node'. */
136 /* buffer is unused argument, but as v9 uses it, we need to have the same interface */
137 char * prom_firstprop(int node, char *bufer)
139 struct tree_entry *e;
140 if (node == 0 || node == -1)
141 return "";
142 e = get_te_by_node(node);
143 return (char *)(e->prop[0].name ? e->prop[0].name : "");
145 EXPORT_SYMBOL(prom_firstprop);
148 /* Return the property type string after property type 'oprop'
149 * at node 'node' . Returns empty string if no more
150 * property types for this node.
152 char * prom_nextprop(int node, char *oprop, char *buffer)
154 struct tree_entry *e;
155 int i;
156 if (node == 0 || node == -1)
157 return "";
158 e = get_te_by_node(node);
159 for (i = 0; i < MAX_PROPERTY; i++) {
160 if (!e->prop[i].name)
161 return "";
162 if (!strcmp(e->prop[i].name, oprop)) {
163 break;
166 if (i >= (MAX_PROPERTY - 1)) {
167 return "";
169 if (e->prop[i + 1].name == NULL) {
170 return "";
172 return (char *)e->prop[i + 1].name;
174 EXPORT_SYMBOL(prom_nextprop);
176 /* Search siblings at 'node_start' for a node with name
177 * 'nodename'. Return node if successful, zero if not.
179 int prom_searchsiblings(int node_start, char *nodename)
181 struct tree_entry *e;
183 if (node_start == 0)
184 return 0;
185 e = get_te_by_node(node_start);
186 for (; e; e = e->sibling) {
187 int i;
188 for (i = 0; e->prop[i].name && i < MAX_PROPERTY; i++) {
189 if (!strcmp("name", e->prop[i].name)) {
190 if (!strcmp(nodename, e->prop[i].value))
191 return e->node;
192 else
193 break;
197 dbg("sibling '%s' at node '%s' not found.\n", nodename,
198 (char *)(get_te_by_node(node_start)->prop[ATTRIB_NAME].value));
199 return 0;
201 EXPORT_SYMBOL(prom_searchsiblings);
203 /* Return the next sibling of node 'node' or zero if no more siblings
204 * at this level of depth in the tree.
206 int prom_getsibling(int node)
208 struct tree_entry *e = (struct tree_entry *) node;
209 extern struct tree_entry *sbus_root_node;
210 if (node == 0) {
211 return sbus_root_node->node;
213 e = get_te_by_node(node);
214 return e->sibling ? e->sibling->node : 0;
216 EXPORT_SYMBOL(prom_getsibling);
218 /* Acquire an integer property and return its value. Returns -1
219 * on failure.
221 int prom_getint(int node, char *prop)
223 int intprop;
224 if (prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) !=
226 return intprop;
228 return -1;
230 EXPORT_SYMBOL(prom_getint);
232 /* Acquire a boolean property, 1=TRUE 0=FALSE. */
233 int prom_getbool(int node, char *prop)
235 int retval;
237 retval = prom_getproplen(node, prop);
238 if (retval == -1)
239 return 0;
240 return 1;
245 /* Acquire an integer property, upon error return the passed default
246 * integer.
248 int prom_getintdefault(int node, char *property, int deflt)
250 int res = prom_getint(node, property);
251 return res == -1 ? deflt : res;
253 EXPORT_SYMBOL(prom_getintdefault);
254 /* Acquire a property whose value is a string, returns a null
255 * string on error. The char pointer is the user supplied string
256 * buffer.
258 void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
260 int len;
261 len = prom_getproperty(node, prop, user_buf, ubuf_size);
262 if (len != -1)
263 return;
264 user_buf[0] = 0;
265 return;
267 EXPORT_SYMBOL(prom_getstring);
269 /* Adjust register values based upon the ranges parameters. */
270 static void
271 prom_adjust_regs(struct linux_prom_registers *regp, int nregs,
272 struct linux_prom_ranges *rangep, int nranges)
274 int regc, rngc;
276 for (regc = 0; regc < nregs; regc++) {
277 for (rngc = 0; rngc < nranges; rngc++)
278 if (regp[regc].which_io ==
279 rangep[rngc].ot_child_space)
280 break; /* Fount it */
281 if (rngc == nranges) /* oops */
282 prom_printf
283 ("adjust_regs: Could not find range with matching bus type...\n");
284 regp[regc].which_io = rangep[rngc].ot_parent_space;
285 regp[regc].phys_addr -= rangep[rngc].ot_child_base;
286 regp[regc].phys_addr += rangep[rngc].ot_parent_base;
290 static void
291 prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
292 struct linux_prom_ranges *ranges2, int nranges2)
294 int rng1c, rng2c;
296 for (rng1c = 0; rng1c < nranges1; rng1c++) {
297 for (rng2c = 0; rng2c < nranges2; rng2c++)
298 if (ranges1[rng1c].ot_parent_space ==
299 ranges2[rng2c].ot_child_space
300 && ranges1[rng1c].ot_parent_base >=
301 ranges2[rng2c].ot_child_base
302 && ranges2[rng2c].ot_child_base +
303 ranges2[rng2c].or_size -
304 ranges1[rng1c].ot_parent_base > 0U)
305 break;
306 if (rng2c == nranges2) /* oops */
307 prom_printf
308 ("adjust_ranges: Could not find matching bus type...\n");
309 else if (ranges1[rng1c].ot_parent_base +
310 ranges1[rng1c].or_size >
311 ranges2[rng2c].ot_child_base +
312 ranges2[rng2c].or_size)
313 ranges1[rng1c].or_size =
314 ranges2[rng2c].ot_child_base +
315 ranges2[rng2c].or_size -
316 ranges1[rng1c].ot_parent_base;
317 ranges1[rng1c].ot_parent_space =
318 ranges2[rng2c].ot_parent_space;
319 ranges1[rng1c].ot_parent_base +=
320 ranges2[rng2c].ot_parent_base;
326 void prom_apply_generic_ranges(int node, int parent,
327 struct linux_prom_registers *regs,
328 int nregs)
330 int success;
331 int num_ranges;
332 struct linux_prom_ranges ranges[PROMREG_MAX];
334 success = prom_getproperty(node, "ranges",
335 (char *) ranges, sizeof(ranges));
336 if (success != -1) {
337 num_ranges = (success / sizeof(struct linux_prom_ranges));
338 if (parent) {
339 struct linux_prom_ranges
340 parent_ranges[PROMREG_MAX];
341 int num_parent_ranges;
343 success = prom_getproperty(parent, "ranges",
344 (char *) parent_ranges,
345 sizeof(parent_ranges));
346 if (success != -1) {
347 num_parent_ranges =
348 (success /
349 sizeof(struct linux_prom_ranges));
350 prom_adjust_ranges(ranges, num_ranges,
351 parent_ranges,
352 num_parent_ranges);
355 prom_adjust_regs(regs, nregs, ranges, num_ranges);