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 14 #include <asm/openprom.h> 15 #include <asm/oplib.h> 16 #include <asm/ldc.h> 17 18 /* Return the child of node 'node' or zero if no this node has no 19 * direct descendent. 20 */ 21 inline int __prom_getchild(int node) 22 { 23 return p1275_cmd ("child", P1275_INOUT(1, 1), node); 24 } 25 26 inline int prom_getchild(int node) 27 { 28 int cnode; 29 30 if(node == -1) return 0; 31 cnode = __prom_getchild(node); 32 if(cnode == -1) return 0; 33 return (int)cnode; 34 } 35 36 inline int prom_getparent(int node) 37 { 38 int cnode; 39 40 if(node == -1) return 0; 41 cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node); 42 if(cnode == -1) return 0; 43 return (int)cnode; 44 } 45 46 /* Return the next sibling of node 'node' or zero if no more siblings 47 * at this level of depth in the tree. 48 */ 49 inline int __prom_getsibling(int node) 50 { 51 return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node); 52 } 53 54 inline int prom_getsibling(int node) 55 { 56 int sibnode; 57 58 if (node == -1) 59 return 0; 60 sibnode = __prom_getsibling(node); 61 if (sibnode == -1) 62 return 0; 63 64 return sibnode; 65 } 66 67 /* Return the length in bytes of property 'prop' at node 'node'. 68 * Return -1 on error. 69 */ 70 inline int prom_getproplen(int node, const char *prop) 71 { 72 if((!node) || (!prop)) return -1; 73 return p1275_cmd ("getproplen", 74 P1275_ARG(1,P1275_ARG_IN_STRING)| 75 P1275_INOUT(2, 1), 76 node, prop); 77 } 78 79 /* Acquire a property 'prop' at node 'node' and place it in 80 * 'buffer' which has a size of 'bufsize'. If the acquisition 81 * was successful the length will be returned, else -1 is returned. 82 */ 83 inline int prom_getproperty(int node, const char *prop, 84 char *buffer, int bufsize) 85 { 86 int plen; 87 88 plen = prom_getproplen(node, prop); 89 if ((plen > bufsize) || (plen == 0) || (plen == -1)) { 90 return -1; 91 } else { 92 /* Ok, things seem all right. */ 93 return p1275_cmd(prom_getprop_name, 94 P1275_ARG(1,P1275_ARG_IN_STRING)| 95 P1275_ARG(2,P1275_ARG_OUT_BUF)| 96 P1275_INOUT(4, 1), 97 node, prop, buffer, P1275_SIZE(plen)); 98 } 99 } 100 101 /* Acquire an integer property and return its value. Returns -1 102 * on failure. 103 */ 104 inline int prom_getint(int node, const char *prop) 105 { 106 int intprop; 107 108 if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1) 109 return intprop; 110 111 return -1; 112 } 113 114 /* Acquire an integer property, upon error return the passed default 115 * integer. 116 */ 117 118 int prom_getintdefault(int node, const char *property, int deflt) 119 { 120 int retval; 121 122 retval = prom_getint(node, property); 123 if(retval == -1) return deflt; 124 125 return retval; 126 } 127 128 /* Acquire a boolean property, 1=TRUE 0=FALSE. */ 129 int prom_getbool(int node, const char *prop) 130 { 131 int retval; 132 133 retval = prom_getproplen(node, prop); 134 if(retval == -1) return 0; 135 return 1; 136 } 137 138 /* Acquire a property whose value is a string, returns a null 139 * string on error. The char pointer is the user supplied string 140 * buffer. 141 */ 142 void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size) 143 { 144 int len; 145 146 len = prom_getproperty(node, prop, user_buf, ubuf_size); 147 if(len != -1) return; 148 user_buf[0] = 0; 149 return; 150 } 151 152 153 /* Does the device at node 'node' have name 'name'? 154 * YES = 1 NO = 0 155 */ 156 int prom_nodematch(int node, const char *name) 157 { 158 char namebuf[128]; 159 prom_getproperty(node, "name", namebuf, sizeof(namebuf)); 160 if(strcmp(namebuf, name) == 0) return 1; 161 return 0; 162 } 163 164 /* Search siblings at 'node_start' for a node with name 165 * 'nodename'. Return node if successful, zero if not. 166 */ 167 int prom_searchsiblings(int node_start, const char *nodename) 168 { 169 170 int thisnode, error; 171 char promlib_buf[128]; 172 173 for(thisnode = node_start; thisnode; 174 thisnode=prom_getsibling(thisnode)) { 175 error = prom_getproperty(thisnode, "name", promlib_buf, 176 sizeof(promlib_buf)); 177 /* Should this ever happen? */ 178 if(error == -1) continue; 179 if(strcmp(nodename, promlib_buf)==0) return thisnode; 180 } 181 182 return 0; 183 } 184 185 /* Return the first property type for node 'node'. 186 * buffer should be at least 32B in length 187 */ 188 inline char *prom_firstprop(int node, char *buffer) 189 { 190 *buffer = 0; 191 if(node == -1) return buffer; 192 p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)| 193 P1275_INOUT(3, 0), 194 node, (char *) 0x0, buffer); 195 return buffer; 196 } 197 198 /* Return the property type string after property type 'oprop' 199 * at node 'node' . Returns NULL string if no more 200 * property types for this node. 201 */ 202 inline char *prom_nextprop(int node, const char *oprop, char *buffer) 203 { 204 char buf[32]; 205 206 if(node == -1) { 207 *buffer = 0; 208 return buffer; 209 } 210 if (oprop == buffer) { 211 strcpy (buf, oprop); 212 oprop = buf; 213 } 214 p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)| 215 P1275_ARG(2,P1275_ARG_OUT_32B)| 216 P1275_INOUT(3, 0), 217 node, oprop, buffer); 218 return buffer; 219 } 220 221 int 222 prom_finddevice(const char *name) 223 { 224 if (!name) 225 return 0; 226 return p1275_cmd(prom_finddev_name, 227 P1275_ARG(0,P1275_ARG_IN_STRING)| 228 P1275_INOUT(1, 1), 229 name); 230 } 231 232 int prom_node_has_property(int node, const char *prop) 233 { 234 char buf [32]; 235 236 *buf = 0; 237 do { 238 prom_nextprop(node, buf, buf); 239 if(!strcmp(buf, prop)) 240 return 1; 241 } while (*buf); 242 return 0; 243 } 244 245 /* Set property 'pname' at node 'node' to value 'value' which has a length 246 * of 'size' bytes. Return the number of bytes the prom accepted. 247 */ 248 int 249 prom_setprop(int node, const char *pname, char *value, int size) 250 { 251 if (size == 0) 252 return 0; 253 if ((pname == 0) || (value == 0)) 254 return 0; 255 256 #ifdef CONFIG_SUN_LDOMS 257 if (ldom_domaining_enabled) { 258 ldom_set_var(pname, value); 259 return 0; 260 } 261 #endif 262 return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)| 263 P1275_ARG(2,P1275_ARG_IN_BUF)| 264 P1275_INOUT(4, 1), 265 node, pname, value, P1275_SIZE(size)); 266 } 267 268 inline int prom_inst2pkg(int inst) 269 { 270 int node; 271 272 node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst); 273 if (node == -1) return 0; 274 return node; 275 } 276 277 /* Return 'node' assigned to a particular prom 'path' 278 * FIXME: Should work for v0 as well 279 */ 280 int 281 prom_pathtoinode(const char *path) 282 { 283 int node, inst; 284 285 inst = prom_devopen (path); 286 if (inst == 0) return 0; 287 node = prom_inst2pkg (inst); 288 prom_devclose (inst); 289 if (node == -1) return 0; 290 return node; 291 } 292 293 int prom_ihandle2path(int handle, char *buffer, int bufsize) 294 { 295 return p1275_cmd("instance-to-path", 296 P1275_ARG(1,P1275_ARG_OUT_BUF)| 297 P1275_INOUT(3, 1), 298 handle, buffer, P1275_SIZE(bufsize)); 299 } 300