1/* 2 * tree.c: Basic device tree traversal/scanning for the Linux 3 * prom library. 4 * 5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 6 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 7 */ 8 9#include <linux/string.h> 10#include <linux/types.h> 11#include <linux/kernel.h> 12#include <linux/sched.h> 13#include <linux/module.h> 14 15#include <asm/openprom.h> 16#include <asm/oplib.h> 17#include <asm/ldc.h> 18 19static int prom_node_to_node(const char *type, int node) 20{ 21 unsigned long args[5]; 22 23 args[0] = (unsigned long) type; 24 args[1] = 1; 25 args[2] = 1; 26 args[3] = (unsigned int) node; 27 args[4] = (unsigned long) -1; 28 29 p1275_cmd_direct(args); 30 31 return (int) args[4]; 32} 33 34/* Return the child of node 'node' or zero if no this node has no 35 * direct descendent. 36 */ 37inline int __prom_getchild(int node) 38{ 39 return prom_node_to_node("child", node); 40} 41 42inline int prom_getchild(int node) 43{ 44 int cnode; 45 46 if (node == -1) 47 return 0; 48 cnode = __prom_getchild(node); 49 if (cnode == -1) 50 return 0; 51 return cnode; 52} 53EXPORT_SYMBOL(prom_getchild); 54 55inline int prom_getparent(int node) 56{ 57 int cnode; 58 59 if (node == -1) 60 return 0; 61 cnode = prom_node_to_node("parent", node); 62 if (cnode == -1) 63 return 0; 64 return cnode; 65} 66 67/* Return the next sibling of node 'node' or zero if no more siblings 68 * at this level of depth in the tree. 69 */ 70inline int __prom_getsibling(int node) 71{ 72 return prom_node_to_node(prom_peer_name, node); 73} 74 75inline int prom_getsibling(int node) 76{ 77 int sibnode; 78 79 if (node == -1) 80 return 0; 81 sibnode = __prom_getsibling(node); 82 if (sibnode == -1) 83 return 0; 84 85 return sibnode; 86} 87EXPORT_SYMBOL(prom_getsibling); 88 89/* Return the length in bytes of property 'prop' at node 'node'. 90 * Return -1 on error. 91 */ 92inline int prom_getproplen(int node, const char *prop) 93{ 94 unsigned long args[6]; 95 96 if (!node || !prop) 97 return -1; 98 99 args[0] = (unsigned long) "getproplen"; 100 args[1] = 2; 101 args[2] = 1; 102 args[3] = (unsigned int) node; 103 args[4] = (unsigned long) prop; 104 args[5] = (unsigned long) -1; 105 106 p1275_cmd_direct(args); 107 108 return (int) args[5]; 109} 110EXPORT_SYMBOL(prom_getproplen); 111 112/* Acquire a property 'prop' at node 'node' and place it in 113 * 'buffer' which has a size of 'bufsize'. If the acquisition 114 * was successful the length will be returned, else -1 is returned. 115 */ 116inline int prom_getproperty(int node, const char *prop, 117 char *buffer, int bufsize) 118{ 119 unsigned long args[8]; 120 int plen; 121 122 plen = prom_getproplen(node, prop); 123 if ((plen > bufsize) || (plen == 0) || (plen == -1)) 124 return -1; 125 126 args[0] = (unsigned long) prom_getprop_name; 127 args[1] = 4; 128 args[2] = 1; 129 args[3] = (unsigned int) node; 130 args[4] = (unsigned long) prop; 131 args[5] = (unsigned long) buffer; 132 args[6] = bufsize; 133 args[7] = (unsigned long) -1; 134 135 p1275_cmd_direct(args); 136 137 return (int) args[7]; 138} 139EXPORT_SYMBOL(prom_getproperty); 140 141/* Acquire an integer property and return its value. Returns -1 142 * on failure. 143 */ 144inline int prom_getint(int node, const char *prop) 145{ 146 int intprop; 147 148 if (prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1) 149 return intprop; 150 151 return -1; 152} 153EXPORT_SYMBOL(prom_getint); 154 155/* Acquire an integer property, upon error return the passed default 156 * integer. 157 */ 158 159int prom_getintdefault(int node, const char *property, int deflt) 160{ 161 int retval; 162 163 retval = prom_getint(node, property); 164 if (retval == -1) 165 return deflt; 166 167 return retval; 168} 169EXPORT_SYMBOL(prom_getintdefault); 170 171/* Acquire a boolean property, 1=TRUE 0=FALSE. */ 172int prom_getbool(int node, const char *prop) 173{ 174 int retval; 175 176 retval = prom_getproplen(node, prop); 177 if (retval == -1) 178 return 0; 179 return 1; 180} 181EXPORT_SYMBOL(prom_getbool); 182 183/* Acquire a property whose value is a string, returns a null 184 * string on error. The char pointer is the user supplied string 185 * buffer. 186 */ 187void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size) 188{ 189 int len; 190 191 len = prom_getproperty(node, prop, user_buf, ubuf_size); 192 if (len != -1) 193 return; 194 user_buf[0] = 0; 195} 196EXPORT_SYMBOL(prom_getstring); 197 198/* Does the device at node 'node' have name 'name'? 199 * YES = 1 NO = 0 200 */ 201int prom_nodematch(int node, const char *name) 202{ 203 char namebuf[128]; 204 prom_getproperty(node, "name", namebuf, sizeof(namebuf)); 205 if (strcmp(namebuf, name) == 0) 206 return 1; 207 return 0; 208} 209 210/* Search siblings at 'node_start' for a node with name 211 * 'nodename'. Return node if successful, zero if not. 212 */ 213int prom_searchsiblings(int node_start, const char *nodename) 214{ 215 216 int thisnode, error; 217 char promlib_buf[128]; 218 219 for(thisnode = node_start; thisnode; 220 thisnode=prom_getsibling(thisnode)) { 221 error = prom_getproperty(thisnode, "name", promlib_buf, 222 sizeof(promlib_buf)); 223 /* Should this ever happen? */ 224 if(error == -1) continue; 225 if(strcmp(nodename, promlib_buf)==0) return thisnode; 226 } 227 228 return 0; 229} 230EXPORT_SYMBOL(prom_searchsiblings); 231 232static const char *prom_nextprop_name = "nextprop"; 233 234/* Return the first property type for node 'node'. 235 * buffer should be at least 32B in length 236 */ 237inline char *prom_firstprop(int node, char *buffer) 238{ 239 unsigned long args[7]; 240 241 *buffer = 0; 242 if (node == -1) 243 return buffer; 244 245 args[0] = (unsigned long) prom_nextprop_name; 246 args[1] = 3; 247 args[2] = 1; 248 args[3] = (unsigned int) node; 249 args[4] = 0; 250 args[5] = (unsigned long) buffer; 251 args[6] = (unsigned long) -1; 252 253 p1275_cmd_direct(args); 254 255 return buffer; 256} 257EXPORT_SYMBOL(prom_firstprop); 258 259/* Return the property type string after property type 'oprop' 260 * at node 'node' . Returns NULL string if no more 261 * property types for this node. 262 */ 263inline char *prom_nextprop(int node, const char *oprop, char *buffer) 264{ 265 unsigned long args[7]; 266 char buf[32]; 267 268 if (node == -1) { 269 *buffer = 0; 270 return buffer; 271 } 272 if (oprop == buffer) { 273 strcpy (buf, oprop); 274 oprop = buf; 275 } 276 277 args[0] = (unsigned long) prom_nextprop_name; 278 args[1] = 3; 279 args[2] = 1; 280 args[3] = (unsigned int) node; 281 args[4] = (unsigned long) oprop; 282 args[5] = (unsigned long) buffer; 283 args[6] = (unsigned long) -1; 284 285 p1275_cmd_direct(args); 286 287 return buffer; 288} 289EXPORT_SYMBOL(prom_nextprop); 290 291int 292prom_finddevice(const char *name) 293{ 294 unsigned long args[5]; 295 296 if (!name) 297 return 0; 298 args[0] = (unsigned long) "finddevice"; 299 args[1] = 1; 300 args[2] = 1; 301 args[3] = (unsigned long) name; 302 args[4] = (unsigned long) -1; 303 304 p1275_cmd_direct(args); 305 306 return (int) args[4]; 307} 308EXPORT_SYMBOL(prom_finddevice); 309 310int prom_node_has_property(int node, const char *prop) 311{ 312 char buf [32]; 313 314 *buf = 0; 315 do { 316 prom_nextprop(node, buf, buf); 317 if (!strcmp(buf, prop)) 318 return 1; 319 } while (*buf); 320 return 0; 321} 322EXPORT_SYMBOL(prom_node_has_property); 323 324/* Set property 'pname' at node 'node' to value 'value' which has a length 325 * of 'size' bytes. Return the number of bytes the prom accepted. 326 */ 327int 328prom_setprop(int node, const char *pname, char *value, int size) 329{ 330 unsigned long args[8]; 331 332 if (size == 0) 333 return 0; 334 if ((pname == 0) || (value == 0)) 335 return 0; 336 337#ifdef CONFIG_SUN_LDOMS 338 if (ldom_domaining_enabled) { 339 ldom_set_var(pname, value); 340 return 0; 341 } 342#endif 343 args[0] = (unsigned long) "setprop"; 344 args[1] = 4; 345 args[2] = 1; 346 args[3] = (unsigned int) node; 347 args[4] = (unsigned long) pname; 348 args[5] = (unsigned long) value; 349 args[6] = size; 350 args[7] = (unsigned long) -1; 351 352 p1275_cmd_direct(args); 353 354 return (int) args[7]; 355} 356EXPORT_SYMBOL(prom_setprop); 357 358inline int prom_inst2pkg(int inst) 359{ 360 unsigned long args[5]; 361 int node; 362 363 args[0] = (unsigned long) "instance-to-package"; 364 args[1] = 1; 365 args[2] = 1; 366 args[3] = (unsigned int) inst; 367 args[4] = (unsigned long) -1; 368 369 p1275_cmd_direct(args); 370 371 node = (int) args[4]; 372 if (node == -1) 373 return 0; 374 return node; 375} 376 377int prom_ihandle2path(int handle, char *buffer, int bufsize) 378{ 379 unsigned long args[7]; 380 381 args[0] = (unsigned long) "instance-to-path"; 382 args[1] = 3; 383 args[2] = 1; 384 args[3] = (unsigned int) handle; 385 args[4] = (unsigned long) buffer; 386 args[5] = bufsize; 387 args[6] = (unsigned long) -1; 388 389 p1275_cmd_direct(args); 390 391 return (int) args[6]; 392} 393