Print this page
10135 picl plugins need smatch fixes
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/picl/plugins/common/devtree/picldevtree.c
+++ new/usr/src/cmd/picl/plugins/common/devtree/picldevtree.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 + * Copyright (c) 2018, Joyent, Inc.
28 + */
29 +
30 +/*
27 31 * PICL plug-in that creates device tree nodes for all platforms
28 32 */
29 33
30 34 #include <stdio.h>
31 35 #include <string.h>
32 36 #include <ctype.h>
33 37 #include <limits.h>
34 38 #include <stdlib.h>
35 39 #include <assert.h>
36 40 #include <alloca.h>
37 41 #include <unistd.h>
38 42 #include <stropts.h>
39 43 #include <syslog.h>
40 44 #include <libdevinfo.h>
41 45 #include <sys/dkio.h>
42 46 #include <sys/vtoc.h>
43 47 #include <sys/time.h>
44 48 #include <fcntl.h>
45 49 #include <picl.h>
46 50 #include <picltree.h>
47 51 #include <sys/types.h>
48 52 #include <sys/processor.h>
49 53 #include <kstat.h>
50 54 #include <sys/sysinfo.h>
51 55 #include <dirent.h>
52 56 #include <libintl.h>
53 57 #include <pthread.h>
54 58 #include <libnvpair.h>
55 59 #include <sys/utsname.h>
56 60 #include <sys/systeminfo.h>
57 61 #include <sys/obpdefs.h>
58 62 #include <sys/openpromio.h>
59 63 #include "picldevtree.h"
60 64
61 65 /*
62 66 * Plugin registration entry points
63 67 */
64 68 static void picldevtree_register(void);
65 69 static void picldevtree_init(void);
66 70 static void picldevtree_fini(void);
67 71
68 72 static void picldevtree_evhandler(const char *ename, const void *earg,
69 73 size_t size, void *cookie);
70 74
71 75 #pragma init(picldevtree_register)
72 76
73 77 /*
74 78 * Log message texts
75 79 */
76 80 #define DEVINFO_PLUGIN_INIT_FAILED gettext("SUNW_picldevtree failed!\n")
77 81 #define PICL_EVENT_DROPPED \
78 82 gettext("SUNW_picldevtree '%s' event dropped.\n")
79 83
80 84 /*
81 85 * Macro to get PCI device id (from IEEE 1275 spec)
82 86 */
83 87 #define PCI_DEVICE_ID(x) (((x) >> 11) & 0x1f)
84 88 /*
85 89 * Local variables
86 90 */
87 91 static picld_plugin_reg_t my_reg_info = {
88 92 PICLD_PLUGIN_VERSION_1,
89 93 PICLD_PLUGIN_CRITICAL,
90 94 "SUNW_picldevtree",
91 95 picldevtree_init,
92 96 picldevtree_fini
93 97 };
94 98
95 99 /*
96 100 * Debug enabling environment variable
97 101 */
98 102 #define SUNW_PICLDEVTREE_PLUGIN_DEBUG "SUNW_PICLDEVTREE_PLUGIN_DEBUG"
99 103 static int picldevtree_debug = 0;
100 104
101 105 static conf_entries_t *conf_name_class_map = NULL;
102 106 static builtin_map_t sun4u_map[] = {
103 107 /* MAX_NAMEVAL_SIZE */
104 108 { "SUNW,bpp", PICL_CLASS_PARALLEL},
105 109 { "parallel", PICL_CLASS_PARALLEL},
106 110 { "floppy", PICL_CLASS_FLOPPY},
107 111 { "memory", PICL_CLASS_MEMORY},
108 112 { "ebus", PICL_CLASS_EBUS},
109 113 { "i2c", PICL_CLASS_I2C},
110 114 { "usb", PICL_CLASS_USB},
111 115 { "isa", PICL_CLASS_ISA},
112 116 { "dma", PICL_CLASS_DMA},
113 117 { "keyboard", PICL_CLASS_KEYBOARD},
114 118 { "mouse", PICL_CLASS_MOUSE},
115 119 { "fan-control", PICL_CLASS_FAN_CONTROL},
116 120 { "sc", PICL_CLASS_SYSTEM_CONTROLLER},
117 121 { "dimm", PICL_CLASS_SEEPROM},
118 122 { "dimm-fru", PICL_CLASS_SEEPROM},
119 123 { "cpu", PICL_CLASS_SEEPROM},
120 124 { "cpu-fru", PICL_CLASS_SEEPROM},
121 125 { "flashprom", PICL_CLASS_FLASHPROM},
122 126 { "temperature", PICL_CLASS_TEMPERATURE_DEVICE},
123 127 { "motherboard", PICL_CLASS_SEEPROM},
124 128 { "motherboard-fru", PICL_CLASS_SEEPROM},
125 129 { "motherboard-fru-prom", PICL_CLASS_SEEPROM},
126 130 { "pmu", PICL_CLASS_PMU},
127 131 { "sound", PICL_CLASS_SOUND},
128 132 { "firewire", PICL_CLASS_FIREWIRE},
129 133 { "i2c-at34c02", PICL_CLASS_SEEPROM},
130 134 { "hardware-monitor", PICL_CLASS_HARDWARE_MONITOR},
131 135 { "", ""}
132 136 };
133 137 static builtin_map_t i86pc_map[] = {
134 138 /* MAX_NAMEVAL_SIZE */
135 139 { "cpus", PICL_CLASS_I86CPUS},
136 140 { "cpu", PICL_CLASS_CPU},
137 141 { "memory", PICL_CLASS_MEMORY},
138 142 { "asy", PICL_CLASS_SERIAL},
139 143 { "", ""}
140 144 };
141 145 static pname_type_map_t pname_type_map[] = {
142 146 { "reg", PICL_PTYPE_BYTEARRAY},
143 147 { "device_type", PICL_PTYPE_CHARSTRING},
144 148 { "ranges", PICL_PTYPE_BYTEARRAY},
145 149 { "status", PICL_PTYPE_CHARSTRING},
146 150 { "compatible", PICL_PTYPE_CHARSTRING},
147 151 { "interrupts", PICL_PTYPE_BYTEARRAY},
148 152 { "model", PICL_PTYPE_CHARSTRING},
149 153 { "address", PICL_PTYPE_BYTEARRAY},
150 154 { "vendor-id", PICL_PTYPE_UNSIGNED_INT},
151 155 { "device-id", PICL_PTYPE_UNSIGNED_INT},
152 156 { "revision-id", PICL_PTYPE_UNSIGNED_INT},
153 157 { "class-code", PICL_PTYPE_UNSIGNED_INT},
154 158 { "min-grant", PICL_PTYPE_UNSIGNED_INT},
155 159 { "max-latency", PICL_PTYPE_UNSIGNED_INT},
156 160 { "devsel-speed", PICL_PTYPE_UNSIGNED_INT},
157 161 { "subsystem-id", PICL_PTYPE_UNSIGNED_INT},
158 162 { "subsystem-vendor-id", PICL_PTYPE_UNSIGNED_INT},
159 163 { "assigned-addresses", PICL_PTYPE_BYTEARRAY},
160 164 { "configuration#", PICL_PTYPE_UNSIGNED_INT},
161 165 { "assigned-address", PICL_PTYPE_UNSIGNED_INT},
162 166 { "#address-cells", PICL_PTYPE_UNSIGNED_INT},
163 167 { "#size-cells", PICL_PTYPE_UNSIGNED_INT},
164 168 { "clock-frequency", PICL_PTYPE_UNSIGNED_INT},
165 169 { "scsi-initiator-id", PICL_PTYPE_UNSIGNED_INT},
166 170 { "differential", PICL_PTYPE_UNSIGNED_INT},
167 171 { "idprom", PICL_PTYPE_BYTEARRAY},
168 172 { "bus-range", PICL_PTYPE_BYTEARRAY},
169 173 { "alternate-reg", PICL_PTYPE_BYTEARRAY},
170 174 { "power-consumption", PICL_PTYPE_BYTEARRAY},
171 175 { "slot-names", PICL_PTYPE_BYTEARRAY},
172 176 { "burst-sizes", PICL_PTYPE_UNSIGNED_INT},
173 177 { "up-burst-sizes", PICL_PTYPE_UNSIGNED_INT},
174 178 { "slot-address-bits", PICL_PTYPE_UNSIGNED_INT},
175 179 { "eisa-slots", PICL_PTYPE_BYTEARRAY},
176 180 { "dma", PICL_PTYPE_BYTEARRAY},
177 181 { "slot-names-index", PICL_PTYPE_UNSIGNED_INT},
178 182 { "pnp-csn", PICL_PTYPE_UNSIGNED_INT},
179 183 { "pnp-data", PICL_PTYPE_BYTEARRAY},
180 184 { "description", PICL_PTYPE_CHARSTRING},
181 185 { "pnp-id", PICL_PTYPE_CHARSTRING},
182 186 { "max-frame-size", PICL_PTYPE_UNSIGNED_INT},
183 187 { "address-bits", PICL_PTYPE_UNSIGNED_INT},
184 188 { "local-mac-address", PICL_PTYPE_BYTEARRAY},
185 189 { "mac-address", PICL_PTYPE_BYTEARRAY},
186 190 { "character-set", PICL_PTYPE_CHARSTRING},
187 191 { "available", PICL_PTYPE_BYTEARRAY},
188 192 { "port-wwn", PICL_PTYPE_BYTEARRAY},
189 193 { "node-wwn", PICL_PTYPE_BYTEARRAY},
190 194 { "width", PICL_PTYPE_UNSIGNED_INT},
191 195 { "linebytes", PICL_PTYPE_UNSIGNED_INT},
192 196 { "height", PICL_PTYPE_UNSIGNED_INT},
193 197 { "banner-name", PICL_PTYPE_CHARSTRING},
194 198 { "reset-reason", PICL_PTYPE_CHARSTRING},
195 199 { "implementation#", PICL_PTYPE_UNSIGNED_INT},
196 200 { "version#", PICL_PTYPE_UNSIGNED_INT},
197 201 { "icache-size", PICL_PTYPE_UNSIGNED_INT},
198 202 { "icache-line-size", PICL_PTYPE_UNSIGNED_INT},
199 203 { "icache-associativity", PICL_PTYPE_UNSIGNED_INT},
200 204 { "l1-icache-size", PICL_PTYPE_UNSIGNED_INT},
201 205 { "l1-icache-line-size", PICL_PTYPE_UNSIGNED_INT},
202 206 { "l1-icache-associativity", PICL_PTYPE_UNSIGNED_INT},
203 207 { "#itlb-entries", PICL_PTYPE_UNSIGNED_INT},
204 208 { "dcache-size", PICL_PTYPE_UNSIGNED_INT},
205 209 { "dcache-line-size", PICL_PTYPE_UNSIGNED_INT},
206 210 { "dcache-associativity", PICL_PTYPE_UNSIGNED_INT},
207 211 { "l1-dcache-size", PICL_PTYPE_UNSIGNED_INT},
208 212 { "l1-dcache-line-size", PICL_PTYPE_UNSIGNED_INT},
209 213 { "l1-dcache-associativity", PICL_PTYPE_UNSIGNED_INT},
210 214 { "#dtlb-entries", PICL_PTYPE_UNSIGNED_INT},
211 215 { "ecache-size", PICL_PTYPE_UNSIGNED_INT},
212 216 { "ecache-line-size", PICL_PTYPE_UNSIGNED_INT},
213 217 { "ecache-associativity", PICL_PTYPE_UNSIGNED_INT},
214 218 { "l2-cache-size", PICL_PTYPE_UNSIGNED_INT},
215 219 { "l2-cache-line-size", PICL_PTYPE_UNSIGNED_INT},
216 220 { "l2-cache-associativity", PICL_PTYPE_UNSIGNED_INT},
217 221 { "l2-cache-sharing", PICL_PTYPE_BYTEARRAY},
218 222 { "mask#", PICL_PTYPE_UNSIGNED_INT},
219 223 { "manufacturer#", PICL_PTYPE_UNSIGNED_INT},
220 224 { "sparc-version", PICL_PTYPE_UNSIGNED_INT},
221 225 { "version", PICL_PTYPE_CHARSTRING},
222 226 { "cpu-model", PICL_PTYPE_UNSIGNED_INT},
223 227 { "memory-layout", PICL_PTYPE_BYTEARRAY},
224 228 { "#interrupt-cells", PICL_PTYPE_UNSIGNED_INT},
225 229 { "interrupt-map", PICL_PTYPE_BYTEARRAY},
226 230 { "interrupt-map-mask", PICL_PTYPE_BYTEARRAY}
227 231 };
228 232
229 233 #define PNAME_MAP_SIZE sizeof (pname_type_map) / sizeof (pname_type_map_t)
230 234
231 235 static builtin_map_t *builtin_map_ptr = NULL;
232 236 static int builtin_map_size = 0;
233 237 static char mach_name[SYS_NMLN];
234 238 static di_prom_handle_t ph = DI_PROM_HANDLE_NIL;
235 239 static int snapshot_stale;
236 240
237 241 /*
238 242 * UnitAddress mapping table
239 243 */
240 244 static unitaddr_func_t encode_default_unitaddr;
241 245 static unitaddr_func_t encode_optional_unitaddr;
242 246 static unitaddr_func_t encode_scsi_unitaddr;
243 247 static unitaddr_func_t encode_upa_unitaddr;
244 248 static unitaddr_func_t encode_gptwo_jbus_unitaddr;
245 249 static unitaddr_func_t encode_pci_unitaddr;
246 250
247 251 static unitaddr_map_t unitaddr_map_table[] = {
248 252 {PICL_CLASS_JBUS, encode_gptwo_jbus_unitaddr, 0},
249 253 {PICL_CLASS_GPTWO, encode_gptwo_jbus_unitaddr, 0},
250 254 {PICL_CLASS_PCI, encode_pci_unitaddr, 0},
251 255 {PICL_CLASS_PCIEX, encode_pci_unitaddr, 0},
252 256 {PICL_CLASS_UPA, encode_upa_unitaddr, 0},
253 257 {PICL_CLASS_SCSI, encode_scsi_unitaddr, 0},
254 258 {PICL_CLASS_SCSI2, encode_scsi_unitaddr, 0},
255 259 {PICL_CLASS_EBUS, encode_default_unitaddr, 2},
256 260 {PICL_CLASS_SBUS, encode_default_unitaddr, 2},
257 261 {PICL_CLASS_I2C, encode_default_unitaddr, 2},
258 262 {PICL_CLASS_USB, encode_default_unitaddr, 1},
259 263 {PICL_CLASS_PMU, encode_optional_unitaddr, 2},
260 264 {NULL, encode_default_unitaddr, 0}
261 265 };
262 266
263 267 static int add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh);
264 268 static int get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh,
265 269 char *unitaddr, size_t ualen);
266 270 static void set_pci_pciex_deviceid(picl_nodehdl_t plafh);
267 271
268 272 /*
269 273 * The mc event completion handler.
270 274 * The arguments are event name buffer and a packed nvlist buffer
271 275 * with the size specifying the size of unpacked nvlist. These
272 276 * buffers are deallcoated here.
273 277 *
274 278 * Also, if a memory controller node is being removed then destroy the
275 279 * PICL subtree associated with that memory controller.
276 280 */
277 281 static void
278 282 mc_completion_handler(char *ename, void *earg, size_t size)
279 283 {
280 284 picl_nodehdl_t mch;
281 285 nvlist_t *unpack_nvl;
282 286
283 287 if (strcmp(ename, PICLEVENT_MC_REMOVED) == 0 &&
284 288 nvlist_unpack(earg, size, &unpack_nvl, NULL) == 0) {
285 289 mch = NULL;
286 290 (void) nvlist_lookup_uint64(unpack_nvl,
287 291 PICLEVENTARG_NODEHANDLE, &mch);
288 292 if (mch != NULL) {
289 293 if (picldevtree_debug)
290 294 syslog(LOG_INFO,
291 295 "picldevtree: destroying_node:%llx\n",
292 296 mch);
293 297 (void) ptree_destroy_node(mch);
294 298 }
295 299 nvlist_free(unpack_nvl);
296 300 }
297 301
298 302 free(ename);
299 303 free(earg);
300 304 }
301 305
302 306 /*
303 307 * Functions to post memory controller change event
304 308 */
305 309 static int
306 310 post_mc_event(char *ename, picl_nodehdl_t mch)
307 311 {
308 312 nvlist_t *nvl;
309 313 size_t nvl_size;
310 314 char *pack_buf;
311 315 char *ev_name;
312 316
313 317 ev_name = strdup(ename);
314 318 if (ev_name == NULL)
315 319 return (-1);
316 320
317 321 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) {
318 322 free(ev_name);
319 323 return (-1);
320 324 }
321 325
322 326 pack_buf = NULL;
323 327 if (nvlist_add_uint64(nvl, PICLEVENTARG_NODEHANDLE, mch) ||
324 328 nvlist_pack(nvl, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) {
325 329 free(ev_name);
326 330 nvlist_free(nvl);
327 331 return (-1);
328 332 }
329 333
330 334 if (picldevtree_debug)
331 335 syslog(LOG_INFO,
332 336 "picldevtree: posting MC event ename:%s nodeh:%llx\n",
333 337 ev_name, mch);
334 338 if (ptree_post_event(ev_name, pack_buf, nvl_size,
335 339 mc_completion_handler) != PICL_SUCCESS) {
336 340 free(ev_name);
337 341 nvlist_free(nvl);
338 342 return (-1);
339 343 }
340 344 nvlist_free(nvl);
341 345 return (0);
342 346 }
343 347
344 348 /*
345 349 * Lookup a name in the name to class map tables
346 350 */
347 351 static int
348 352 lookup_name_class_map(char *classbuf, const char *nm)
349 353 {
350 354 conf_entries_t *ptr;
351 355 int i;
352 356
353 357 /*
354 358 * check name to class mapping in conf file
355 359 */
356 360 ptr = conf_name_class_map;
357 361
358 362 while (ptr != NULL) {
359 363 if (strcmp(ptr->name, nm) == 0) {
360 364 (void) strlcpy(classbuf, ptr->piclclass,
361 365 PICL_CLASSNAMELEN_MAX);
362 366 return (0);
363 367 }
364 368 ptr = ptr->next;
365 369 }
366 370
367 371 /*
368 372 * check name to class mapping in builtin table
369 373 */
370 374 if (builtin_map_ptr == NULL)
371 375 return (-1);
372 376
373 377 for (i = 0; i < builtin_map_size; ++i)
374 378 if (strcmp(builtin_map_ptr[i].name, nm) == 0) {
375 379 (void) strlcpy(classbuf, builtin_map_ptr[i].piclclass,
376 380 PICL_CLASSNAMELEN_MAX);
377 381 return (0);
378 382 }
379 383 return (-1);
380 384 }
381 385
382 386 /*
383 387 * Lookup a prop name in the pname to class map table
384 388 */
385 389 static int
386 390 lookup_pname_type_map(const char *pname, picl_prop_type_t *type)
387 391 {
388 392 int i;
389 393
390 394 for (i = 0; i < PNAME_MAP_SIZE; ++i)
391 395 if (strcmp(pname_type_map[i].pname, pname) == 0) {
392 396 *type = pname_type_map[i].type;
393 397 return (0);
394 398 }
395 399
396 400 return (-1);
397 401 }
398 402
399 403 /*
400 404 * Return the number of strings in the buffer
401 405 */
402 406 static int
403 407 get_string_count(char *strdat, int length)
404 408 {
405 409 int count;
406 410 char *lastnull;
407 411 char *nullptr;
408 412
409 413 count = 1;
410 414 for (lastnull = &strdat[length - 1], nullptr = strchr(strdat, '\0');
411 415 nullptr != lastnull; nullptr = strchr(nullptr+1, '\0'))
412 416 count++;
413 417
414 418 return (count);
415 419 }
416 420
417 421 /*
418 422 * Return 1 if the node has a "reg" property
419 423 */
420 424 static int
421 425 has_reg_prop(di_node_t dn)
422 426 {
423 427 int *pdata;
424 428 int dret;
425 429
426 430 dret = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, OBP_REG, &pdata);
427 431 if (dret > 0)
428 432 return (1);
429 433
430 434 if (!ph)
431 435 return (0);
432 436 dret = di_prom_prop_lookup_ints(ph, dn, OBP_REG, &pdata);
433 437 return (dret < 0 ? 0 : 1);
434 438 }
435 439
436 440 /*
437 441 * This function copies a PROM node's device_type property value into the
438 442 * buffer given by outbuf. The buffer size is PICL_CLASSNAMELEN_MAX.
439 443 *
440 444 * We reclassify device_type 'fru-prom' to PICL class 'seeprom'
441 445 * for FRUID support.
442 446 */
443 447 static int
444 448 get_device_type(char *outbuf, di_node_t dn)
445 449 {
446 450 char *pdata;
447 451 char *pdatap;
448 452 int dret;
449 453 int i;
450 454
451 455 dret = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, OBP_DEVICETYPE,
452 456 &pdata);
453 457 if (dret <= 0) {
454 458 if (!ph)
455 459 return (-1);
456 460
457 461 dret = di_prom_prop_lookup_strings(ph, dn, OBP_DEVICETYPE,
458 462 &pdata);
459 463 if (dret <= 0) {
460 464 return (-1);
461 465 }
462 466 }
463 467
464 468 if (dret != 1) {
465 469 /*
466 470 * multiple strings
467 471 */
468 472 pdatap = pdata;
469 473 for (i = 0; i < (dret - 1); ++i) {
470 474 pdatap += strlen(pdatap);
471 475 *pdatap = '-'; /* replace '\0' with '-' */
472 476 pdatap++;
473 477 }
474 478 }
475 479 if (strcasecmp(pdata, "fru-prom") == 0) {
476 480 /*
477 481 * Use PICL 'seeprom' class for fru-prom device types
478 482 */
479 483 (void) strlcpy(outbuf, PICL_CLASS_SEEPROM,
480 484 PICL_CLASSNAMELEN_MAX);
481 485 } else {
482 486 (void) strlcpy(outbuf, pdata, PICL_CLASSNAMELEN_MAX);
483 487 }
484 488 return (0);
485 489 }
486 490
487 491 /*
488 492 * Get the minor node name in the class buffer passed
489 493 */
490 494 static int
491 495 get_minor_class(char *classbuf, di_node_t dn)
492 496 {
493 497 di_minor_t mi_node;
494 498 char *mi_nodetype;
495 499 char *mi_name;
496 500
497 501 /* get minor node type */
498 502 mi_node = di_minor_next(dn, DI_MINOR_NIL);
499 503 if (mi_node == DI_MINOR_NIL)
500 504 return (-1);
501 505
502 506 mi_nodetype = di_minor_nodetype(mi_node);
503 507 if (mi_nodetype == NULL) { /* no type info, return name */
504 508 mi_name = di_minor_name(mi_node);
505 509 if (mi_name == NULL)
506 510 return (-1);
507 511 (void) strlcpy(classbuf, mi_name, PICL_CLASSNAMELEN_MAX);
508 512 return (0);
509 513 }
510 514
511 515 #define DDI_NODETYPE(x, y) (strncmp(x, y, (sizeof (y) - 1)) == 0)
512 516
513 517 /*
514 518 * convert the string to the picl class for non-peudo nodes
515 519 */
516 520 if (DDI_NODETYPE(mi_nodetype, DDI_PSEUDO))
517 521 return (-1);
518 522 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_WWN))
519 523 (void) strcpy(classbuf, PICL_CLASS_BLOCK);
520 524 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_CHAN))
521 525 (void) strcpy(classbuf, PICL_CLASS_BLOCK);
522 526 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_CD))
523 527 (void) strcpy(classbuf, PICL_CLASS_CDROM);
524 528 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_CD_CHAN))
525 529 (void) strcpy(classbuf, PICL_CLASS_CDROM);
526 530 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_FD))
527 531 (void) strcpy(classbuf, PICL_CLASS_FLOPPY);
528 532 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_FABRIC))
529 533 (void) strcpy(classbuf, PICL_CLASS_FABRIC);
530 534 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_SAS))
531 535 (void) strcpy(classbuf, PICL_CLASS_SAS);
532 536 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK))
533 537 (void) strcpy(classbuf, PICL_CLASS_BLOCK);
534 538 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_MOUSE))
535 539 (void) strcpy(classbuf, PICL_CLASS_MOUSE);
536 540 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_KEYBOARD))
537 541 (void) strcpy(classbuf, PICL_CLASS_KEYBOARD);
538 542 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_ATTACHMENT_POINT))
539 543 (void) strcpy(classbuf, PICL_CLASS_ATTACHMENT_POINT);
540 544 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_TAPE))
541 545 (void) strcpy(classbuf, PICL_CLASS_TAPE);
542 546 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_SCSI_ENCLOSURE))
543 547 (void) strcpy(classbuf, PICL_CLASS_SCSI);
544 548 else if (DDI_NODETYPE(mi_nodetype, DDI_NT_ENCLOSURE)) {
545 549 char *colon;
546 550
547 551 if ((colon = strchr(mi_nodetype, ':')) == NULL)
548 552 return (-1);
549 553 ++colon;
550 554 (void) strcpy(classbuf, colon);
551 555 } else { /* unrecognized type, return name */
552 556 mi_name = di_minor_name(mi_node);
553 557 if (mi_name == NULL)
554 558 return (-1);
555 559 (void) strlcpy(classbuf, mi_name, PICL_CLASSNAMELEN_MAX);
556 560 }
557 561 return (0);
558 562 }
559 563
560 564 /*
561 565 * Derive PICL class using the compatible property of the node
562 566 * We use the map table to map compatible property value to
563 567 * class.
564 568 */
565 569 static int
566 570 get_compatible_class(char *outbuf, di_node_t dn)
567 571 {
568 572 char *pdata;
569 573 char *pdatap;
570 574 int dret;
571 575 int i;
572 576
573 577 dret = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, OBP_COMPATIBLE,
574 578 &pdata);
575 579 if (dret <= 0) {
576 580 if (!ph)
577 581 return (-1);
578 582
579 583 dret = di_prom_prop_lookup_strings(ph, dn, OBP_COMPATIBLE,
580 584 &pdata);
581 585 if (dret <= 0) {
582 586 return (-1);
583 587 }
584 588 }
585 589
586 590 pdatap = pdata;
587 591 for (i = 0; i < dret; ++i) {
588 592 if (lookup_name_class_map(outbuf, pdatap) == 0)
589 593 return (0);
590 594 pdatap += strlen(pdatap);
591 595 pdatap++;
592 596 }
593 597 return (-1);
594 598 }
595 599
596 600 /*
597 601 * For a given device node find the PICL class to use. Returns NULL
598 602 * for non device node
599 603 */
600 604 static int
601 605 get_node_class(char *classbuf, di_node_t dn, const char *nodename)
602 606 {
603 607 if (get_device_type(classbuf, dn) == 0) {
604 608 if (di_nodeid(dn) == DI_PROM_NODEID) {
605 609 /*
606 610 * discard place holder nodes
607 611 */
608 612 if ((strcmp(classbuf, DEVICE_TYPE_BLOCK) == 0) ||
609 613 (strcmp(classbuf, DEVICE_TYPE_BYTE) == 0) ||
610 614 (strcmp(classbuf, DEVICE_TYPE_SES) == 0) ||
611 615 (strcmp(classbuf, DEVICE_TYPE_FP) == 0) ||
612 616 (strcmp(classbuf, DEVICE_TYPE_DISK) == 0))
613 617 return (-1);
614 618
615 619 return (0);
616 620 }
617 621 return (0); /* return device_type value */
618 622 }
619 623
620 624 if (get_compatible_class(classbuf, dn) == 0) {
621 625 return (0); /* derive class using compatible prop */
622 626 }
623 627
624 628 if (lookup_name_class_map(classbuf, nodename) == 0)
625 629 return (0); /* derive class using name prop */
626 630
627 631 if (has_reg_prop(dn)) { /* use default obp-device */
628 632 (void) strcpy(classbuf, PICL_CLASS_OBP_DEVICE);
629 633 return (0);
630 634 }
631 635
632 636 return (get_minor_class(classbuf, dn));
633 637 }
634 638
635 639 /*
636 640 * Add a table property containing nrows with one column
637 641 */
638 642 static int
639 643 add_string_list_prop(picl_nodehdl_t nodeh, char *name, char *strlist,
640 644 unsigned int nrows)
641 645 {
642 646 ptree_propinfo_t propinfo;
643 647 picl_prophdl_t proph;
644 648 picl_prophdl_t tblh;
645 649 int err;
646 650 unsigned int i;
647 651 unsigned int j;
648 652 picl_prophdl_t *proprow;
649 653 int len;
650 654
651 655 #define NCOLS_IN_STRING_TABLE 1
652 656
653 657 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
654 658 PICL_PTYPE_TABLE, PICL_READ, sizeof (picl_prophdl_t), name,
655 659 NULL, NULL);
656 660 if (err != PICL_SUCCESS)
657 661 return (err);
658 662
659 663 err = ptree_create_table(&tblh);
660 664 if (err != PICL_SUCCESS)
661 665 return (err);
662 666
663 667 err = ptree_create_and_add_prop(nodeh, &propinfo, &tblh, &proph);
664 668 if (err != PICL_SUCCESS)
665 669 return (err);
666 670
667 671 proprow = alloca(sizeof (picl_prophdl_t) * nrows);
668 672 if (proprow == NULL) {
669 673 (void) ptree_destroy_prop(proph);
670 674 return (PICL_FAILURE);
671 675 }
672 676
673 677 for (j = 0; j < nrows; ++j) {
674 678 len = strlen(strlist) + 1;
675 679 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
676 680 PICL_PTYPE_CHARSTRING, PICL_READ, len, name,
677 681 NULL, NULL);
678 682 if (err != PICL_SUCCESS)
679 683 break;
680 684 err = ptree_create_prop(&propinfo, strlist, &proprow[j]);
681 685 if (err != PICL_SUCCESS)
682 686 break;
683 687 strlist += len;
684 688 err = ptree_add_row_to_table(tblh, NCOLS_IN_STRING_TABLE,
685 689 &proprow[j]);
686 690 if (err != PICL_SUCCESS)
687 691 break;
688 692 }
689 693
690 694 if (err != PICL_SUCCESS) {
691 695 for (i = 0; i < j; ++i)
692 696 (void) ptree_destroy_prop(proprow[i]);
693 697 (void) ptree_delete_prop(proph);
694 698 (void) ptree_destroy_prop(proph);
695 699 return (err);
696 700 }
697 701
698 702 return (PICL_SUCCESS);
699 703 }
700 704
701 705 /*
702 706 * return 1 if this node has this property with the given value
703 707 */
704 708 static int
705 709 compare_string_propval(picl_nodehdl_t nodeh, const char *pname,
706 710 const char *pval)
707 711 {
708 712 char *pvalbuf;
709 713 int err;
710 714 int len;
711 715 ptree_propinfo_t pinfo;
712 716 picl_prophdl_t proph;
713 717
714 718 err = ptree_get_prop_by_name(nodeh, pname, &proph);
715 719 if (err != PICL_SUCCESS) /* prop doesn't exist */
716 720 return (0);
717 721
718 722 err = ptree_get_propinfo(proph, &pinfo);
719 723 if (pinfo.piclinfo.type != PICL_PTYPE_CHARSTRING)
720 724 return (0); /* not string prop */
721 725
722 726 len = strlen(pval) + 1;
723 727
724 728 pvalbuf = alloca(len);
725 729 if (pvalbuf == NULL)
726 730 return (0);
727 731
728 732 err = ptree_get_propval(proph, pvalbuf, len);
729 733 if ((err == PICL_SUCCESS) && (strcmp(pvalbuf, pval) == 0))
730 734 return (1); /* prop match */
731 735
732 736 return (0);
733 737 }
734 738
735 739 /*
736 740 * This function recursively searches the tree for a node that has
737 741 * the specified string property name and value
738 742 */
739 743 static int
740 744 find_node_by_string_prop(picl_nodehdl_t rooth, const char *pname,
741 745 const char *pval, picl_nodehdl_t *nodeh)
742 746 {
743 747 picl_nodehdl_t childh;
744 748 int err;
745 749
746 750 for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh,
747 751 sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
748 752 err = ptree_get_propval_by_name(childh, PICL_PROP_PEER, &childh,
749 753 sizeof (picl_nodehdl_t))) {
750 754 if (err != PICL_SUCCESS)
751 755 return (err);
752 756
753 757 if (compare_string_propval(childh, pname, pval)) {
754 758 *nodeh = childh;
755 759 return (PICL_SUCCESS);
756 760 }
757 761
758 762 if (find_node_by_string_prop(childh, pname, pval, nodeh) ==
759 763 PICL_SUCCESS)
760 764 return (PICL_SUCCESS);
761 765 }
762 766
763 767 return (PICL_FAILURE);
764 768 }
765 769
766 770 /*
767 771 * check if this is a string prop
768 772 * If the length is less than or equal to 4, assume it's not a string list.
769 773 * If there is any non-ascii or non-print char, it's not a string prop
770 774 * If \0 is in the first char or any two consecutive \0's exist,
771 775 * it's a bytearray prop.
772 776 * Return value: 0 means it's not a string prop, 1 means it's a string prop
773 777 */
774 778 static int
775 779 is_string_propval(unsigned char *pdata, int len)
776 780 {
777 781 int i;
778 782 int lastindex;
779 783 int prevnull = -1;
780 784
781 785 switch (len) {
782 786 case 1:
783 787 if (!isascii(pdata[0]) || !isprint(pdata[0]))
784 788 return (0);
785 789 return (1);
786 790 case 2:
787 791 case 3:
788 792 case 4:
789 793 lastindex = len;
790 794 if (pdata[len-1] == '\0')
791 795 lastindex = len - 1;
792 796
793 797 for (i = 0; i < lastindex; i++)
794 798 if (!isascii(pdata[i]) || !isprint(pdata[i]))
795 799 return (0);
796 800
797 801 return (1);
798 802
799 803 default:
800 804 if (len <= 0)
801 805 return (0);
802 806 for (i = 0; i < len; i++) {
803 807 if (!isascii(pdata[i]) || !isprint(pdata[i])) {
804 808 if (pdata[i] != '\0')
805 809 return (0);
806 810 /*
807 811 * if the null char is in the first char
808 812 * or two consecutive nulls' exist,
809 813 * it's a bytearray prop
810 814 */
811 815 if ((i == 0) || ((i - prevnull) == 1))
812 816 return (0);
813 817
814 818 prevnull = i;
815 819 }
816 820 }
817 821 break;
818 822 }
819 823
820 824 return (1);
821 825 }
822 826
823 827 /*
824 828 * This function counts the number of strings in the value buffer pdata
825 829 * and creates a property.
826 830 * If there is only one string in the buffer, pdata, a charstring property
827 831 * type is created and added.
828 832 * If there are more than one string in the buffer, pdata, then a table
829 833 * of charstrings is added.
830 834 */
831 835 static int
832 836 process_charstring_data(picl_nodehdl_t nodeh, char *pname, unsigned char *pdata,
833 837 int retval)
834 838 {
835 839 int err;
836 840 int strcount;
837 841 char *strdat;
838 842 ptree_propinfo_t propinfo;
839 843
840 844 /*
841 845 * append the null char at the end of string when there is
842 846 * no null terminator
843 847 */
844 848 if (pdata[retval - 1] != '\0') {
845 849 strdat = alloca(retval + 1);
846 850 (void) memcpy(strdat, pdata, retval);
847 851 strdat[retval] = '\0';
848 852 retval++;
849 853 } else {
850 854 strdat = alloca(retval);
851 855 (void) memcpy(strdat, pdata, retval);
852 856 }
853 857
854 858 /*
855 859 * If it's a string list, create a table prop
856 860 */
857 861 strcount = get_string_count(strdat, retval);
858 862 if (strcount > 1) {
859 863 err = add_string_list_prop(nodeh, pname,
860 864 strdat, strcount);
861 865 if (err != PICL_SUCCESS)
862 866 return (err);
863 867 } else {
864 868 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
865 869 PICL_PTYPE_CHARSTRING, PICL_READ,
866 870 strlen(strdat) + 1, pname, NULL,
867 871 NULL);
868 872 if (err != PICL_SUCCESS)
869 873 return (err);
870 874 (void) ptree_create_and_add_prop(nodeh, &propinfo,
871 875 strdat, NULL);
872 876 }
873 877 return (PICL_SUCCESS);
874 878 }
875 879
876 880 /*
877 881 * Add the OBP properties as properties of the PICL node
878 882 */
879 883 static int
880 884 add_openprom_props(picl_nodehdl_t nodeh, di_node_t di_node)
881 885 {
882 886 di_prom_prop_t promp;
883 887 char *pname;
884 888 unsigned char *pdata;
885 889 int retval;
886 890 ptree_propinfo_t propinfo;
887 891 int err;
888 892 picl_prop_type_t type;
889 893
890 894 if (!ph)
891 895 return (PICL_FAILURE);
892 896
893 897 for (promp = di_prom_prop_next(ph, di_node, DI_PROM_PROP_NIL);
894 898 promp != DI_PROM_PROP_NIL;
895 899 promp = di_prom_prop_next(ph, di_node, promp)) {
896 900
897 901 pname = di_prom_prop_name(promp);
898 902
899 903 retval = di_prom_prop_data(promp, &pdata);
900 904 if (retval < 0) {
901 905 return (PICL_SUCCESS);
902 906 }
903 907 if (retval == 0) {
904 908 err = ptree_init_propinfo(&propinfo,
905 909 PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID,
906 910 PICL_READ, (size_t)0, pname, NULL, NULL);
907 911 if (err != PICL_SUCCESS) {
908 912 return (err);
909 913 }
910 914 (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL,
911 915 NULL);
912 916 continue;
913 917 }
914 918
915 919 /*
916 920 * Get the prop type from pname map table
917 921 */
918 922 if (lookup_pname_type_map(pname, &type) == 0) {
919 923 if (type == PICL_PTYPE_CHARSTRING) {
920 924 err = process_charstring_data(nodeh, pname,
921 925 pdata, retval);
922 926 if (err != PICL_SUCCESS) {
923 927 return (err);
924 928 }
925 929 continue;
926 930 }
927 931
928 932 err = ptree_init_propinfo(&propinfo,
929 933 PTREE_PROPINFO_VERSION, type, PICL_READ,
930 934 retval, pname, NULL, NULL);
931 935 if (err != PICL_SUCCESS) {
932 936 return (err);
933 937 }
934 938 (void) ptree_create_and_add_prop(nodeh, &propinfo,
935 939 pdata, NULL);
936 940 } else if (!is_string_propval(pdata, retval)) {
937 941 switch (retval) {
938 942 case sizeof (uint8_t):
939 943 /*FALLTHROUGH*/
940 944 case sizeof (uint16_t):
941 945 /*FALLTHROUGH*/
942 946 case sizeof (uint32_t):
943 947 type = PICL_PTYPE_UNSIGNED_INT;
944 948 break;
945 949 default:
946 950 type = PICL_PTYPE_BYTEARRAY;
947 951 break;
948 952 }
949 953 err = ptree_init_propinfo(&propinfo,
950 954 PTREE_PROPINFO_VERSION, type, PICL_READ,
951 955 retval, pname, NULL, NULL);
952 956 if (err != PICL_SUCCESS) {
953 957 return (err);
954 958 }
955 959 (void) ptree_create_and_add_prop(nodeh, &propinfo,
956 960 pdata, NULL);
957 961 } else {
958 962 err = process_charstring_data(nodeh, pname, pdata,
959 963 retval);
960 964 if (err != PICL_SUCCESS) {
961 965 return (err);
962 966 }
963 967 }
964 968 }
965 969
966 970 return (PICL_SUCCESS);
967 971 }
968 972
969 973 static void
970 974 add_boolean_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val)
971 975 {
972 976 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
973 977 PICL_PTYPE_VOID, PICL_READ, (size_t)0, di_val, NULL, NULL);
974 978 (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL);
975 979 }
976 980
977 981 static void
978 982 add_uints_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val,
979 983 int *idata, int len)
980 984 {
981 985 if (len == 1)
982 986 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
983 987 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (int), di_val,
984 988 NULL, NULL);
985 989 else
986 990 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
987 991 PICL_PTYPE_BYTEARRAY, PICL_READ, len * sizeof (int), di_val,
988 992 NULL, NULL);
989 993
990 994 (void) ptree_create_and_add_prop(nodeh, &propinfo, idata, NULL);
991 995 }
992 996
993 997 static void
994 998 add_strings_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val,
995 999 char *sdata, int len)
996 1000 {
997 1001 if (len == 1) {
998 1002 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
999 1003 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(sdata) + 1, di_val,
1000 1004 NULL, NULL);
1001 1005 (void) ptree_create_and_add_prop(nodeh, &propinfo, sdata, NULL);
1002 1006 } else {
1003 1007 (void) add_string_list_prop(nodeh, di_val, sdata, len);
1004 1008 }
1005 1009 }
1006 1010
1007 1011 static void
1008 1012 add_bytes_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val,
1009 1013 unsigned char *bdata, int len)
1010 1014 {
1011 1015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1012 1016 PICL_PTYPE_BYTEARRAY, PICL_READ, len, di_val, NULL, NULL);
1013 1017 (void) ptree_create_and_add_prop(nodeh, &propinfo, bdata, NULL);
1014 1018 }
1015 1019
1016 1020 static const char *
1017 1021 path_state_name(di_path_state_t st)
1018 1022 {
1019 1023 switch (st) {
1020 1024 case DI_PATH_STATE_ONLINE:
1021 1025 return ("online");
1022 1026 case DI_PATH_STATE_STANDBY:
1023 1027 return ("standby");
1024 1028 case DI_PATH_STATE_OFFLINE:
1025 1029 return ("offline");
1026 1030 case DI_PATH_STATE_FAULT:
1027 1031 return ("faulted");
1028 1032 }
1029 1033 return ("unknown");
1030 1034 }
1031 1035
1032 1036 /*
1033 1037 * This function is the volatile property handler for the multipath node
1034 1038 * "State" property. It must locate the associated devinfo node in order to
1035 1039 * determine the current state. Since the devinfo node can have multiple
1036 1040 * paths the devfs_path is used to locate the correct path.
1037 1041 */
1038 1042 static int
1039 1043 get_path_state_name(ptree_rarg_t *rarg, void *vbuf)
1040 1044 {
1041 1045 int err;
1042 1046 picl_nodehdl_t parh;
1043 1047 char devfs_path[PATH_MAX];
1044 1048 di_node_t di_node;
1045 1049 di_node_t di_root;
1046 1050 di_path_t pi = DI_PATH_NIL;
1047 1051 picl_nodehdl_t mpnode;
1048 1052
1049 1053 (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE);
1050 1054
1051 1055 mpnode = rarg->nodeh;
1052 1056
1053 1057 /*
1054 1058 * The parent node represents the vHCI.
1055 1059 */
1056 1060 err = ptree_get_propval_by_name(mpnode, PICL_PROP_PARENT, &parh,
1057 1061 sizeof (picl_nodehdl_t));
1058 1062 if (err != PICL_SUCCESS) {
1059 1063 return (PICL_SUCCESS);
1060 1064 }
1061 1065
1062 1066 /*
1063 1067 * The PICL_PROP_DEVFS_PATH property will be used to locate the
1064 1068 * devinfo node for the vHCI driver.
1065 1069 */
1066 1070 err = ptree_get_propval_by_name(parh, PICL_PROP_DEVFS_PATH, devfs_path,
1067 1071 sizeof (devfs_path));
1068 1072 if (err != PICL_SUCCESS) {
1069 1073 return (PICL_SUCCESS);
1070 1074 }
1071 1075 /*
1072 1076 * Find the di_node for the vHCI driver. It will be used to scan
1073 1077 * the path information nodes.
1074 1078 */
1075 1079 di_root = di_init("/", DINFOCACHE);
1076 1080 if (di_root == DI_NODE_NIL) {
1077 1081 return (PICL_SUCCESS);
1078 1082 }
1079 1083 di_node = di_lookup_node(di_root, devfs_path);
1080 1084 if (di_node == DI_NODE_NIL) {
1081 1085 di_fini(di_root);
1082 1086 return (PICL_SUCCESS);
1083 1087 }
1084 1088
1085 1089 /*
1086 1090 * The devfs_path will be used below to match the
1087 1091 * proper path information node.
1088 1092 */
1089 1093 err = ptree_get_propval_by_name(mpnode, PICL_PROP_DEVFS_PATH,
1090 1094 devfs_path, sizeof (devfs_path));
1091 1095 if (err != PICL_SUCCESS) {
1092 1096 di_fini(di_root);
1093 1097 return (PICL_SUCCESS);
1094 1098 }
1095 1099
1096 1100 /*
1097 1101 * Scan the path information nodes looking for the matching devfs
1098 1102 * path. When found obtain the state information.
1099 1103 */
1100 1104 while ((pi = di_path_next_phci(di_node, pi)) != DI_PATH_NIL) {
1101 1105 char *di_path;
1102 1106 di_node_t phci_node = di_path_phci_node(pi);
1103 1107
1104 1108 if (phci_node == DI_PATH_NIL)
1105 1109 continue;
1106 1110
1107 1111 di_path = di_devfs_path(phci_node);
1108 1112 if (di_path) {
1109 1113 if (strcmp(di_path, devfs_path) != 0) {
1110 1114 di_devfs_path_free(di_path);
1111 1115 continue;
1112 1116 }
1113 1117 (void) strlcpy(vbuf, path_state_name(di_path_state(pi)),
1114 1118 MAX_STATE_SIZE);
1115 1119 di_devfs_path_free(di_path);
1116 1120 break;
1117 1121 }
1118 1122 }
1119 1123
1120 1124 di_fini(di_root);
1121 1125 return (PICL_SUCCESS);
1122 1126 }
1123 1127
1124 1128 static void
1125 1129 add_di_path_prop(picl_nodehdl_t nodeh, di_path_prop_t di_path_prop)
1126 1130 {
1127 1131 int di_ptype;
1128 1132 char *di_val;
1129 1133 ptree_propinfo_t propinfo;
1130 1134 int *idata;
1131 1135 char *sdata;
1132 1136 unsigned char *bdata;
1133 1137 int len;
1134 1138
1135 1139 di_ptype = di_path_prop_type(di_path_prop);
1136 1140 di_val = di_path_prop_name(di_path_prop);
1137 1141
1138 1142 switch (di_ptype) {
1139 1143 case DI_PROP_TYPE_BOOLEAN:
1140 1144 add_boolean_prop(nodeh, propinfo, di_val);
1141 1145 break;
1142 1146 case DI_PROP_TYPE_INT:
1143 1147 case DI_PROP_TYPE_INT64:
1144 1148 len = di_path_prop_ints(di_path_prop, &idata);
1145 1149 if (len < 0)
1146 1150 /* Received error, so ignore prop */
1147 1151 break;
1148 1152 add_uints_prop(nodeh, propinfo, di_val, idata, len);
1149 1153 break;
1150 1154 case DI_PROP_TYPE_STRING:
1151 1155 len = di_path_prop_strings(di_path_prop, &sdata);
1152 1156 if (len <= 0)
1153 1157 break;
1154 1158 add_strings_prop(nodeh, propinfo, di_val, sdata, len);
1155 1159 break;
1156 1160 case DI_PROP_TYPE_BYTE:
1157 1161 len = di_path_prop_bytes(di_path_prop, &bdata);
1158 1162 if (len < 0)
1159 1163 break;
1160 1164 add_bytes_prop(nodeh, propinfo, di_val, bdata, len);
1161 1165 break;
1162 1166 case DI_PROP_TYPE_UNKNOWN:
1163 1167 /*
1164 1168 * Unknown type, we'll try and guess what it should be.
1165 1169 */
1166 1170 len = di_path_prop_strings(di_path_prop, &sdata);
1167 1171 if ((len > 0) && (sdata[0] != 0)) {
1168 1172 add_strings_prop(nodeh, propinfo, di_val, sdata,
1169 1173 len);
1170 1174 break;
1171 1175 }
1172 1176 len = di_path_prop_ints(di_path_prop, &idata);
1173 1177 if (len > 0) {
1174 1178 add_uints_prop(nodeh, propinfo, di_val,
1175 1179 idata, len);
1176 1180 break;
1177 1181 }
1178 1182 len = di_path_prop_bytes(di_path_prop, &bdata);
1179 1183 if (len > 0)
1180 1184 add_bytes_prop(nodeh, propinfo,
1181 1185 di_val, bdata, len);
1182 1186 else if (len == 0)
1183 1187 add_boolean_prop(nodeh, propinfo,
1184 1188 di_val);
1185 1189 break;
1186 1190 case DI_PROP_TYPE_UNDEF_IT:
1187 1191 break;
1188 1192 default:
1189 1193 break;
1190 1194 }
1191 1195 }
1192 1196
1193 1197 /*
1194 1198 * Add nodes for path information (PSARC/1999/647, PSARC/2008/437)
1195 1199 */
1196 1200 static void
1197 1201 construct_mpath_node(picl_nodehdl_t parh, di_node_t di_node)
1198 1202 {
1199 1203 di_path_t pi = DI_PATH_NIL;
1200 1204
1201 1205 while ((pi = di_path_next_phci(di_node, pi)) != DI_PATH_NIL) {
1202 1206 di_node_t phci_node = di_path_phci_node(pi);
1203 1207 di_path_prop_t di_path_prop;
1204 1208 picl_nodehdl_t nodeh;
1205 1209 ptree_propinfo_t propinfo;
1206 1210 int err;
1207 1211 int instance;
1208 1212 char *di_val;
1209 1213
1210 1214 if (phci_node == DI_PATH_NIL)
1211 1215 continue;
1212 1216
1213 1217 err = ptree_create_and_add_node(parh, PICL_CLASS_MULTIPATH,
1214 1218 PICL_CLASS_MULTIPATH, &nodeh);
1215 1219 if (err != PICL_SUCCESS)
1216 1220 continue;
1217 1221
1218 1222 instance = di_instance(phci_node);
1219 1223 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1220 1224 PICL_PTYPE_INT, PICL_READ, sizeof (instance),
1221 1225 PICL_PROP_INSTANCE, NULL, NULL);
1222 1226 (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance,
1223 1227 NULL);
1224 1228
1225 1229 di_val = di_devfs_path(phci_node);
1226 1230 if (di_val) {
1227 1231 (void) ptree_init_propinfo(&propinfo,
1228 1232 PTREE_PROPINFO_VERSION,
1229 1233 PICL_PTYPE_CHARSTRING, PICL_READ,
1230 1234 strlen(di_val) + 1, PICL_PROP_DEVFS_PATH,
1231 1235 NULL, NULL);
1232 1236 (void) ptree_create_and_add_prop(nodeh,
1233 1237 &propinfo, di_val, NULL);
1234 1238 di_devfs_path_free(di_val);
1235 1239 }
1236 1240
1237 1241 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1238 1242 PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE),
1239 1243 MAX_STATE_SIZE, PICL_PROP_STATE, get_path_state_name, NULL);
1240 1244 (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL);
1241 1245
1242 1246 for (di_path_prop = di_path_prop_next(pi, DI_PROP_NIL);
1243 1247 di_path_prop != DI_PROP_NIL;
1244 1248 di_path_prop = di_path_prop_next(pi, di_path_prop)) {
1245 1249 add_di_path_prop(nodeh, di_path_prop);
1246 1250 }
1247 1251 }
1248 1252 }
1249 1253
1250 1254 /*
1251 1255 * Add properties provided by libdevinfo
1252 1256 */
1253 1257 static void
1254 1258 add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node)
1255 1259 {
1256 1260 int instance;
1257 1261 char *di_val;
1258 1262 di_prop_t di_prop;
1259 1263 int di_ptype;
1260 1264 ptree_propinfo_t propinfo;
1261 1265 char *sdata;
1262 1266 unsigned char *bdata;
1263 1267 int *idata;
1264 1268 int len;
1265 1269
1266 1270 instance = di_instance(di_node);
1267 1271 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1268 1272 PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE,
1269 1273 NULL, NULL);
1270 1274 (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL);
1271 1275
1272 1276 di_val = di_bus_addr(di_node);
1273 1277 if (di_val) {
1274 1278 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1275 1279 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1276 1280 PICL_PROP_BUS_ADDR, NULL, NULL);
1277 1281 (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1278 1282 NULL);
1279 1283 }
1280 1284
1281 1285 di_val = di_binding_name(di_node);
1282 1286 if (di_val) {
1283 1287 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1284 1288 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1285 1289 PICL_PROP_BINDING_NAME, NULL, NULL);
1286 1290 (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1287 1291 NULL);
1288 1292 }
1289 1293
1290 1294 di_val = di_driver_name(di_node);
1291 1295 if (di_val) {
1292 1296 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1293 1297 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1294 1298 PICL_PROP_DRIVER_NAME, NULL, NULL);
1295 1299 (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1296 1300 NULL);
1297 1301 }
1298 1302
1299 1303 di_val = di_devfs_path(di_node);
1300 1304 if (di_val) {
1301 1305 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1302 1306 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
1303 1307 PICL_PROP_DEVFS_PATH, NULL, NULL);
1304 1308 (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
1305 1309 NULL);
1306 1310 di_devfs_path_free(di_val);
1307 1311 }
1308 1312
1309 1313 for (di_prop = di_prop_next(di_node, DI_PROP_NIL);
1310 1314 di_prop != DI_PROP_NIL;
1311 1315 di_prop = di_prop_next(di_node, di_prop)) {
1312 1316
1313 1317 di_val = di_prop_name(di_prop);
1314 1318 di_ptype = di_prop_type(di_prop);
1315 1319
1316 1320 switch (di_ptype) {
1317 1321 case DI_PROP_TYPE_BOOLEAN:
1318 1322 add_boolean_prop(nodeh, propinfo, di_val);
1319 1323 break;
1320 1324 case DI_PROP_TYPE_INT:
1321 1325 len = di_prop_ints(di_prop, &idata);
1322 1326 if (len < 0)
1323 1327 /* Received error, so ignore prop */
1324 1328 break;
1325 1329 add_uints_prop(nodeh, propinfo, di_val, idata, len);
1326 1330 break;
1327 1331 case DI_PROP_TYPE_STRING:
1328 1332 len = di_prop_strings(di_prop, &sdata);
1329 1333 if (len < 0)
1330 1334 break;
1331 1335 add_strings_prop(nodeh, propinfo, di_val, sdata, len);
1332 1336 break;
1333 1337 case DI_PROP_TYPE_BYTE:
1334 1338 len = di_prop_bytes(di_prop, &bdata);
1335 1339 if (len < 0)
1336 1340 break;
1337 1341 add_bytes_prop(nodeh, propinfo, di_val, bdata, len);
1338 1342 break;
1339 1343 case DI_PROP_TYPE_UNKNOWN:
1340 1344 /*
1341 1345 * Unknown type, we'll try and guess what it should be.
1342 1346 */
1343 1347 len = di_prop_strings(di_prop, &sdata);
1344 1348 if ((len > 0) && (sdata[0] != 0)) {
1345 1349 add_strings_prop(nodeh, propinfo, di_val, sdata,
1346 1350 len);
1347 1351 break;
1348 1352 }
1349 1353 len = di_prop_ints(di_prop, &idata);
1350 1354 if (len > 0) {
1351 1355 add_uints_prop(nodeh, propinfo, di_val,
1352 1356 idata, len);
1353 1357 break;
1354 1358 }
1355 1359 len = di_prop_rawdata(di_prop, &bdata);
1356 1360 if (len > 0)
1357 1361 add_bytes_prop(nodeh, propinfo,
1358 1362 di_val, bdata, len);
1359 1363 else if (len == 0)
1360 1364 add_boolean_prop(nodeh, propinfo,
1361 1365 di_val);
1362 1366 break;
1363 1367 case DI_PROP_TYPE_UNDEF_IT:
1364 1368 break;
1365 1369 default:
1366 1370 break;
1367 1371 }
1368 1372 }
1369 1373 }
1370 1374
1371 1375 /*
1372 1376 * This function creates the /obp node in the PICL tree for OBP nodes
1373 1377 * without a device type class.
1374 1378 */
1375 1379 static int
1376 1380 construct_picl_openprom(picl_nodehdl_t rooth, picl_nodehdl_t *obph)
1377 1381 {
1378 1382 picl_nodehdl_t tmph;
1379 1383 int err;
1380 1384
1381 1385 err = ptree_create_and_add_node(rooth, PICL_NODE_OBP,
1382 1386 PICL_CLASS_PICL, &tmph);
1383 1387
1384 1388 if (err != PICL_SUCCESS)
1385 1389 return (err);
1386 1390 *obph = tmph;
1387 1391 return (PICL_SUCCESS);
1388 1392 }
1389 1393
1390 1394 /*
1391 1395 * This function creates the /platform node in the PICL tree and
1392 1396 * its properties. It sets the "platform-name" property to the
1393 1397 * platform name
1394 1398 */
1395 1399 static int
1396 1400 construct_picl_platform(picl_nodehdl_t rooth, di_node_t di_root,
1397 1401 picl_nodehdl_t *piclh)
1398 1402 {
1399 1403 int err;
1400 1404 picl_nodehdl_t plafh;
1401 1405 char *nodename;
1402 1406 char nodeclass[PICL_CLASSNAMELEN_MAX];
1403 1407 ptree_propinfo_t propinfo;
1404 1408 picl_prophdl_t proph;
1405 1409
1406 1410 nodename = di_node_name(di_root);
1407 1411 if (nodename == NULL)
1408 1412 return (PICL_FAILURE);
1409 1413
1410 1414 err = 0;
1411 1415 if (di_nodeid(di_root) == DI_PROM_NODEID ||
1412 1416 di_nodeid(di_root) == DI_SID_NODEID)
1413 1417 err = get_device_type(nodeclass, di_root);
1414 1418
1415 1419 if (err < 0)
1416 1420 (void) strcpy(nodeclass, PICL_CLASS_UPA); /* default */
1417 1421
1418 1422 err = ptree_create_and_add_node(rooth, PICL_NODE_PLATFORM,
1419 1423 nodeclass, &plafh);
1420 1424 if (err != PICL_SUCCESS)
1421 1425 return (err);
1422 1426
1423 1427 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1424 1428 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(nodename) + 1,
1425 1429 PICL_PROP_PLATFORM_NAME, NULL, NULL);
1426 1430 err = ptree_create_and_add_prop(plafh, &propinfo, nodename, &proph);
1427 1431 if (err != PICL_SUCCESS)
1428 1432 return (err);
1429 1433
1430 1434 (void) add_devinfo_props(plafh, di_root);
1431 1435
1432 1436 (void) add_openprom_props(plafh, di_root);
1433 1437
1434 1438 *piclh = plafh;
1435 1439
1436 1440 return (PICL_SUCCESS);
1437 1441 }
1438 1442
1439 1443 /*
1440 1444 * This function creates a node in /obp tree for the libdevinfo handle.
1441 1445 */
1442 1446 static int
1443 1447 construct_obp_node(picl_nodehdl_t parh, di_node_t dn, picl_nodehdl_t *chdh)
1444 1448 {
1445 1449 int err;
1446 1450 char *nodename;
1447 1451 char nodeclass[PICL_CLASSNAMELEN_MAX];
1448 1452 picl_nodehdl_t anodeh;
1449 1453
1450 1454 nodename = di_node_name(dn); /* PICL_PROP_NAME */
1451 1455 if (nodename == NULL)
1452 1456 return (PICL_FAILURE);
1453 1457
1454 1458 if (strcmp(nodename, "pseudo") == 0)
1455 1459 return (PICL_FAILURE);
1456 1460
1457 1461 if ((di_nodeid(dn) == DI_PROM_NODEID) &&
1458 1462 (get_device_type(nodeclass, dn) == 0))
1459 1463 return (PICL_FAILURE);
1460 1464
1461 1465 err = ptree_create_and_add_node(parh, nodename, nodename, &anodeh);
1462 1466 if (err != PICL_SUCCESS)
1463 1467 return (err);
1464 1468
1465 1469 add_devinfo_props(anodeh, dn);
1466 1470
1467 1471 (void) add_openprom_props(anodeh, dn);
1468 1472
1469 1473 *chdh = anodeh;
1470 1474
1471 1475 return (PICL_SUCCESS);
1472 1476 }
1473 1477
1474 1478 /*
1475 1479 * This function creates a PICL node in /platform tree for a device
1476 1480 */
1477 1481 static int
1478 1482 construct_devtype_node(picl_nodehdl_t parh, char *nodename,
1479 1483 char *nodeclass, di_node_t dn, picl_nodehdl_t *chdh)
1480 1484 {
1481 1485 int err;
1482 1486 picl_nodehdl_t anodeh;
1483 1487
1484 1488 err = ptree_create_and_add_node(parh, nodename, nodeclass, &anodeh);
1485 1489 if (err != PICL_SUCCESS)
1486 1490 return (err);
1487 1491
1488 1492 (void) add_devinfo_props(anodeh, dn);
1489 1493 (void) add_openprom_props(anodeh, dn);
1490 1494 construct_mpath_node(anodeh, dn);
1491 1495
1492 1496 *chdh = anodeh;
1493 1497 return (err);
1494 1498 }
1495 1499
1496 1500 /*
1497 1501 * Create a subtree of "picl" class nodes in /obp for these nodes
1498 1502 */
1499 1503 static int
1500 1504 construct_openprom_tree(picl_nodehdl_t nodeh, di_node_t dinode)
1501 1505 {
1502 1506 di_node_t cnode;
1503 1507 picl_nodehdl_t chdh;
1504 1508 int err;
1505 1509
1506 1510 err = construct_obp_node(nodeh, dinode, &chdh);
1507 1511 if (err != PICL_SUCCESS)
1508 1512 return (err);
1509 1513
1510 1514 for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL;
1511 1515 cnode = di_sibling_node(cnode))
1512 1516 (void) construct_openprom_tree(chdh, cnode);
1513 1517
1514 1518 return (PICL_SUCCESS);
1515 1519
1516 1520 }
1517 1521
1518 1522 /*
1519 1523 * Process the libdevinfo device tree and create nodes in /platform or /obp
1520 1524 * PICL tree.
1521 1525 *
1522 1526 * This routine traverses the immediate children of "dinode" device and
1523 1527 * determines the node class for that child. If it finds a valid class
1524 1528 * name, then it builds a PICL node under /platform subtree and calls itself
1525 1529 * recursively to construct the subtree for that child node. Otherwise, if
1526 1530 * the parent_class is NULL, then it constructs a node and subtree under /obp
1527 1531 * subtree.
1528 1532 *
1529 1533 * Note that we skip the children nodes that don't have a valid class name
1530 1534 * and the parent_class is non NULL to prevent creation of any placeholder
1531 1535 * nodes (such as sd,...).
1532 1536 */
1533 1537 static int
1534 1538 construct_devinfo_tree(picl_nodehdl_t plafh, picl_nodehdl_t obph,
1535 1539 di_node_t dinode, char *parent_class)
1536 1540 {
1537 1541 di_node_t cnode;
1538 1542 picl_nodehdl_t chdh;
1539 1543 char nodeclass[PICL_CLASSNAMELEN_MAX];
1540 1544 char *nodename;
1541 1545 int err;
1542 1546
1543 1547 err = PICL_SUCCESS;
1544 1548 for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL;
1545 1549 cnode = di_sibling_node(cnode)) {
1546 1550 nodename = di_node_name(cnode); /* PICL_PROP_NAME */
1547 1551 if (nodename == NULL)
1548 1552 continue;
1549 1553
1550 1554 err = get_node_class(nodeclass, cnode, nodename);
1551 1555
1552 1556 if (err == 0) {
1553 1557 err = construct_devtype_node(plafh, nodename,
1554 1558 nodeclass, cnode, &chdh);
1555 1559 if (err != PICL_SUCCESS)
1556 1560 return (err);
1557 1561 err = construct_devinfo_tree(chdh, obph, cnode,
1558 1562 nodeclass);
1559 1563 } else if (parent_class == NULL)
1560 1564 err = construct_openprom_tree(obph, cnode);
1561 1565 else
1562 1566 continue;
1563 1567 /*
1564 1568 * if parent_class is non NULL, skip the children nodes
1565 1569 * that don't have a valid device class - eliminates
1566 1570 * placeholder nodes (sd,...) from being created.
1567 1571 */
1568 1572 }
1569 1573
1570 1574 return (err);
1571 1575
1572 1576 }
1573 1577
1574 1578 /*
1575 1579 * This function is called from the event handler called from the daemon
1576 1580 * on PICL events.
1577 1581 *
1578 1582 * This routine traverses the children of the "dinode" device and
1579 1583 * creates a PICL node for each child not found in the PICL tree and
1580 1584 * invokes itself recursively to create a subtree for the newly created
1581 1585 * child node. It also checks if the node being created is a meory
1582 1586 * controller. If so, it posts PICLEVENT_MC_ADDED PICL event to the PICL
1583 1587 * framework.
1584 1588 */
1585 1589 static int
1586 1590 update_subtree(picl_nodehdl_t nodeh, di_node_t dinode)
1587 1591 {
1588 1592 di_node_t cnode;
1589 1593 picl_nodehdl_t chdh;
1590 1594 picl_nodehdl_t nh;
1591 1595 char *nodename;
1592 1596 char nodeclass[PICL_CLASSNAMELEN_MAX];
1593 1597 char *path_buf;
1594 1598 char buf[MAX_UNIT_ADDRESS_LEN];
1595 1599 char unitaddr[MAX_UNIT_ADDRESS_LEN];
1596 1600 char path_w_ua[MAXPATHLEN];
1597 1601 char path_wo_ua[MAXPATHLEN];
1598 1602 char *strp;
1599 1603 int gotit;
1600 1604 int err;
1601 1605
1602 1606 for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL;
1603 1607 cnode = di_sibling_node(cnode)) {
1604 1608 path_buf = di_devfs_path(cnode);
1605 1609 if (path_buf == NULL)
1606 1610 continue;
1607 1611
1608 1612 nodename = di_node_name(cnode);
1609 1613 if (nodename == NULL) {
1610 1614 di_devfs_path_free(path_buf);
1611 1615 continue;
1612 1616 }
1613 1617
1614 1618 err = get_node_class(nodeclass, cnode, nodename);
1615 1619
1616 1620 if (err < 0) {
1617 1621 di_devfs_path_free(path_buf);
1618 1622 continue;
1619 1623 }
1620 1624
1621 1625 /*
1622 1626 * this is quite complicated - both path_buf and any nodes
1623 1627 * already in the picl tree may, or may not, have the
1624 1628 * @<unit_addr> at the end of their names. So we must
1625 1629 * take path_buf and work out what the device path would
1626 1630 * be both with and without the unit_address, then search
1627 1631 * the picl tree for both forms.
1628 1632 */
1629 1633 if (((strp = strrchr(path_buf, '/')) != NULL) &&
1630 1634 strchr(strp, '@') == NULL) {
1631 1635 /*
1632 1636 * This is an unattached node - so the path is not
1633 1637 * unique. Need to find out which node it is.
1634 1638 * Find the unit_address from the OBP or devinfo
1635 1639 * properties.
1636 1640 */
1637 1641 err = ptree_create_node(nodename, nodeclass, &chdh);
1638 1642 if (err != PICL_SUCCESS)
1639 1643 return (err);
1640 1644
1641 1645 (void) add_devinfo_props(chdh, cnode);
1642 1646 (void) add_openprom_props(chdh, cnode);
1643 1647
1644 1648 err = get_unitaddr(nodeh, chdh, unitaddr,
1645 1649 sizeof (unitaddr));
1646 1650 if (err != PICL_SUCCESS)
1647 1651 return (err);
1648 1652 (void) ptree_destroy_node(chdh);
1649 1653 (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s@%s",
1650 1654 path_buf, unitaddr);
1651 1655 (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s",
1652 1656 path_buf);
1653 1657 } else {
1654 1658 /*
1655 1659 * this is an attached node - so the path is unique
1656 1660 */
1657 1661 (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s",
1658 1662 path_buf);
1659 1663 (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s",
1660 1664 path_buf);
1661 1665 strp = strrchr(path_wo_ua, '@');
1662 1666 *strp++ = '\0';
1663 1667 (void) snprintf(unitaddr, sizeof (unitaddr), "%s",
1664 1668 strp);
1665 1669 }
1666 1670 /*
1667 1671 * first look for node with unit address in devfs_path
1668 1672 */
1669 1673 if (ptree_find_node(nodeh, PICL_PROP_DEVFS_PATH,
1670 1674 PICL_PTYPE_CHARSTRING, path_w_ua, strlen(path_w_ua) + 1,
1671 1675 &nh) == PICL_SUCCESS) {
1672 1676 /*
1673 1677 * node already there - there's nothing we need to do
1674 1678 */
1675 1679 if (picldevtree_debug > 1)
1676 1680 syslog(LOG_INFO,
1677 1681 "update_subtree: path:%s node exists\n",
1678 1682 path_buf);
1679 1683 di_devfs_path_free(path_buf);
1680 1684 continue;
1681 1685 }
1682 1686 /*
1683 1687 * now look for node without unit address in devfs_path.
1684 1688 * This might be just one out of several
1685 1689 * nodes - need to check all siblings
1686 1690 */
1687 1691 err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD,
1688 1692 &chdh, sizeof (chdh));
1689 1693 if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND))
1690 1694 return (err);
1691 1695 gotit = 0;
1692 1696 while (err == PICL_SUCCESS) {
1693 1697 err = ptree_get_propval_by_name(chdh,
1694 1698 PICL_PROP_DEVFS_PATH, buf, sizeof (buf));
1695 1699 if (err != PICL_SUCCESS)
1696 1700 return (err);
1697 1701 if (strcmp(buf, path_wo_ua) == 0) {
1698 1702 err = ptree_get_propval_by_name(chdh,
1699 1703 PICL_PROP_UNIT_ADDRESS, buf, sizeof (buf));
1700 1704 if (err != PICL_SUCCESS)
1701 1705 return (err);
1702 1706 if (strcmp(buf, unitaddr) == 0) {
1703 1707 gotit = 1;
1704 1708 break;
1705 1709 }
1706 1710 }
1707 1711 err = ptree_get_propval_by_name(chdh,
1708 1712 PICL_PROP_PEER, &chdh, sizeof (chdh));
1709 1713 if (err != PICL_SUCCESS)
1710 1714 break;
1711 1715 }
1712 1716 if (gotit) {
1713 1717 /*
1714 1718 * node already there - there's nothing we need to do
1715 1719 */
1716 1720 if (picldevtree_debug > 1)
1717 1721 syslog(LOG_INFO,
1718 1722 "update_subtree: path:%s node exists\n",
1719 1723 path_buf);
1720 1724 di_devfs_path_free(path_buf);
1721 1725 continue;
1722 1726 }
1723 1727
1724 1728 #define IS_MC(x) (strcmp(x, PICL_CLASS_MEMORY_CONTROLLER) == 0 ? 1 : 0)
1725 1729
1726 1730 if (construct_devtype_node(nodeh, nodename, nodeclass, cnode,
1727 1731 &chdh) == PICL_SUCCESS) {
1728 1732 if (picldevtree_debug)
1729 1733 syslog(LOG_INFO,
1730 1734 "picldevtree: added node:%s path:%s\n",
1731 1735 nodename, path_buf);
1732 1736 if (IS_MC(nodeclass)) {
1733 1737 if (post_mc_event(PICLEVENT_MC_ADDED, chdh) !=
1734 1738 PICL_SUCCESS)
1735 1739 syslog(LOG_WARNING, PICL_EVENT_DROPPED,
1736 1740 PICLEVENT_MC_ADDED);
1737 1741 }
1738 1742
1739 1743 di_devfs_path_free(path_buf);
1740 1744 (void) update_subtree(chdh, cnode);
1741 1745 }
1742 1746 }
1743 1747
1744 1748 return (PICL_SUCCESS);
1745 1749
1746 1750 }
1747 1751
1748 1752 /*
1749 1753 * Check for a stale OBP node. EINVAL is returned from the openprom(7D) driver
1750 1754 * if the nodeid stored in the snapshot is not valid.
1751 1755 */
1752 1756 static int
1753 1757 check_stale_node(di_node_t node, void *arg)
1754 1758 {
1755 1759 di_prom_prop_t promp;
1756 1760
1757 1761 errno = 0;
1758 1762 promp = di_prom_prop_next(ph, node, DI_PROM_PROP_NIL);
1759 1763 if (promp == DI_PROM_PROP_NIL && errno == EINVAL) {
1760 1764 snapshot_stale = 1;
1761 1765 return (DI_WALK_TERMINATE);
1762 1766 }
↓ open down ↓ |
1726 lines elided |
↑ open up ↑ |
1763 1767 return (DI_WALK_CONTINUE);
1764 1768 }
1765 1769
1766 1770 /*
1767 1771 * Walk the snapshot and check the OBP properties of each node.
1768 1772 */
1769 1773 static int
1770 1774 is_snapshot_stale(di_node_t root)
1771 1775 {
1772 1776 snapshot_stale = 0;
1773 - di_walk_node(root, DI_WALK_CLDFIRST, NULL, check_stale_node);
1777 + (void) di_walk_node(root, DI_WALK_CLDFIRST, NULL, check_stale_node);
1774 1778 return (snapshot_stale);
1775 1779 }
1776 1780
1777 1781 /*
1778 1782 * This function processes the data from libdevinfo and creates nodes
1779 1783 * in the PICL tree.
1780 1784 */
1781 1785 static int
1782 1786 libdevinfo_init(picl_nodehdl_t rooth)
1783 1787 {
1784 1788 di_node_t di_root;
1785 1789 picl_nodehdl_t plafh;
1786 1790 picl_nodehdl_t obph;
1787 1791 int err;
1788 1792
1789 1793 /*
1790 1794 * Use DINFOCACHE so that we obtain all attributes for all
1791 1795 * device instances (without necessarily doing a load/attach
1792 1796 * of all drivers). Once the (on-disk) cache file is built, it
1793 1797 * exists over a reboot and can be read into memory at a very
1794 1798 * low cost.
1795 1799 */
1796 1800 if ((di_root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
1797 1801 return (PICL_FAILURE);
1798 1802
1799 1803 if ((ph = di_prom_init()) == NULL)
1800 1804 return (PICL_FAILURE);
1801 1805
1802 1806 /*
1803 1807 * Check if the snapshot cache contains stale OBP nodeid references.
1804 1808 * If it does release the snapshot and obtain a live snapshot from the
1805 1809 * kernel.
1806 1810 */
1807 1811 if (is_snapshot_stale(di_root)) {
1808 1812 syslog(LOG_INFO, "picld detected stale snapshot cache");
1809 1813 di_fini(di_root);
1810 1814 if ((di_root = di_init("/", DINFOCPYALL | DINFOFORCE)) ==
1811 1815 DI_NODE_NIL) {
1812 1816 return (PICL_FAILURE);
1813 1817 }
1814 1818 }
1815 1819
1816 1820 /*
1817 1821 * create platform PICL node using di_root node
1818 1822 */
1819 1823 err = construct_picl_platform(rooth, di_root, &plafh);
1820 1824 if (err != PICL_SUCCESS) {
1821 1825 di_fini(di_root);
1822 1826 return (PICL_FAILURE);
1823 1827 }
1824 1828
1825 1829 err = construct_picl_openprom(rooth, &obph);
1826 1830 if (err != PICL_SUCCESS) {
1827 1831 di_fini(di_root);
1828 1832 return (PICL_FAILURE);
1829 1833 }
1830 1834
1831 1835 (void) construct_devinfo_tree(plafh, obph, di_root, NULL);
1832 1836 if (ph) {
1833 1837 di_prom_fini(ph);
1834 1838 ph = NULL;
1835 1839 }
1836 1840 di_fini(di_root);
1837 1841 return (err);
1838 1842 }
1839 1843
1840 1844 /*
1841 1845 * This function returns the integer property value
1842 1846 */
1843 1847 static int
1844 1848 get_int_propval_by_name(picl_nodehdl_t nodeh, char *pname, int *ival)
1845 1849 {
1846 1850 int err;
1847 1851
1848 1852 err = ptree_get_propval_by_name(nodeh, pname, ival,
1849 1853 sizeof (int));
1850 1854
1851 1855 return (err);
1852 1856 }
1853 1857
1854 1858 /*
1855 1859 * This function returns the port ID (or CPU ID in the case of CMP cores)
1856 1860 * of the specific CPU node handle. If upa_portid exists, return its value.
1857 1861 * Otherwise, return portid/cpuid.
1858 1862 */
1859 1863 static int
1860 1864 get_cpu_portid(picl_nodehdl_t modh, int *id)
1861 1865 {
1862 1866 int err;
1863 1867
1864 1868 if (strcmp(mach_name, "sun4u") == 0 ||
1865 1869 strcmp(mach_name, "sun4v") == 0) {
1866 1870 err = get_int_propval_by_name(modh, OBP_PROP_UPA_PORTID, id);
1867 1871 if (err == PICL_SUCCESS)
1868 1872 return (err);
1869 1873 err = get_int_propval_by_name(modh, OBP_PROP_PORTID, id);
1870 1874 if (err == PICL_SUCCESS)
1871 1875 return (err);
1872 1876 return (get_int_propval_by_name(modh, OBP_PROP_CPUID, id));
1873 1877 }
1874 1878 if (strcmp(mach_name, "i86pc") == 0)
1875 1879 return (get_int_propval_by_name(modh, OBP_REG, id));
1876 1880
1877 1881 return (PICL_FAILURE);
1878 1882 }
1879 1883
1880 1884 /*
1881 1885 * This function is the volatile read access function of CPU state
1882 1886 * property
1883 1887 */
1884 1888 static int
1885 1889 get_pi_state(ptree_rarg_t *rarg, void *vbuf)
1886 1890 {
1887 1891 int id;
1888 1892 int err;
1889 1893
1890 1894 err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id);
1891 1895 if (err != PICL_SUCCESS)
1892 1896 return (err);
1893 1897
1894 1898 switch (p_online(id, P_STATUS)) {
1895 1899 case P_ONLINE:
1896 1900 (void) strlcpy(vbuf, PS_ONLINE, MAX_STATE_SIZE);
1897 1901 break;
1898 1902 case P_OFFLINE:
1899 1903 (void) strlcpy(vbuf, PS_OFFLINE, MAX_STATE_SIZE);
1900 1904 break;
1901 1905 case P_NOINTR:
1902 1906 (void) strlcpy(vbuf, PS_NOINTR, MAX_STATE_SIZE);
1903 1907 break;
1904 1908 case P_SPARE:
1905 1909 (void) strlcpy(vbuf, PS_SPARE, MAX_STATE_SIZE);
1906 1910 break;
1907 1911 case P_FAULTED:
1908 1912 (void) strlcpy(vbuf, PS_FAULTED, MAX_STATE_SIZE);
1909 1913 break;
1910 1914 case P_POWEROFF:
1911 1915 (void) strlcpy(vbuf, PS_POWEROFF, MAX_STATE_SIZE);
1912 1916 break;
1913 1917 default:
1914 1918 (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE);
1915 1919 break;
1916 1920 }
1917 1921 return (PICL_SUCCESS);
1918 1922 }
1919 1923
1920 1924 /*
1921 1925 * This function is the volatile read access function of CPU processor_type
1922 1926 * property
1923 1927 */
1924 1928 static int
1925 1929 get_processor_type(ptree_rarg_t *rarg, void *vbuf)
1926 1930 {
1927 1931 processor_info_t cpu_info;
1928 1932 int id;
1929 1933 int err;
1930 1934
1931 1935 err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id);
1932 1936 if (err != PICL_SUCCESS)
1933 1937 return (err);
1934 1938
1935 1939 if (processor_info(id, &cpu_info) >= 0) {
1936 1940 (void) strlcpy(vbuf, cpu_info.pi_processor_type, PI_TYPELEN);
1937 1941 }
1938 1942 return (PICL_SUCCESS);
1939 1943 }
1940 1944
1941 1945 /*
1942 1946 * This function is the volatile read access function of CPU fputypes
1943 1947 * property
1944 1948 */
1945 1949 static int
1946 1950 get_fputypes(ptree_rarg_t *rarg, void *vbuf)
1947 1951 {
1948 1952 processor_info_t cpu_info;
1949 1953 int id;
1950 1954 int err;
1951 1955
1952 1956 err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id);
1953 1957 if (err != PICL_SUCCESS)
1954 1958 return (err);
1955 1959
1956 1960 if (processor_info(id, &cpu_info) >= 0) {
1957 1961 (void) strlcpy(vbuf, cpu_info.pi_fputypes, PI_FPUTYPE);
1958 1962 }
1959 1963 return (PICL_SUCCESS);
1960 1964 }
1961 1965
1962 1966 /*
1963 1967 * This function is the volatile read access function of CPU StateBegin
1964 1968 * property. To minimize overhead, use kstat_chain_update() to refresh
1965 1969 * the kstat header info as opposed to invoking kstat_open() every time.
1966 1970 */
1967 1971 static int
1968 1972 get_pi_state_begin(ptree_rarg_t *rarg, void *vbuf)
1969 1973 {
1970 1974 int err;
1971 1975 int cpu_id;
1972 1976 static kstat_ctl_t *kc = NULL;
1973 1977 static pthread_mutex_t kc_mutex = PTHREAD_MUTEX_INITIALIZER;
1974 1978 kstat_t *kp;
1975 1979 kstat_named_t *kn;
1976 1980
1977 1981 err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &cpu_id);
1978 1982 if (err != PICL_SUCCESS)
1979 1983 return (err);
1980 1984
1981 1985 (void) pthread_mutex_lock(&kc_mutex);
1982 1986 if (kc == NULL)
1983 1987 kc = kstat_open();
1984 1988 else if (kstat_chain_update(kc) == -1) {
1985 1989 (void) kstat_close(kc);
1986 1990 kc = kstat_open();
1987 1991 }
1988 1992
1989 1993 if (kc == NULL) {
1990 1994 (void) pthread_mutex_unlock(&kc_mutex);
1991 1995 return (PICL_FAILURE);
1992 1996 }
1993 1997
1994 1998 /* Get the state_begin from kstat */
1995 1999 if ((kp = kstat_lookup(kc, KSTAT_CPU_INFO, cpu_id, NULL)) == NULL ||
1996 2000 kp->ks_type != KSTAT_TYPE_NAMED || kstat_read(kc, kp, 0) < 0) {
1997 2001 (void) pthread_mutex_unlock(&kc_mutex);
1998 2002 return (PICL_FAILURE);
1999 2003 }
2000 2004
2001 2005 kn = kstat_data_lookup(kp, KSTAT_STATE_BEGIN);
2002 2006 if (kn) {
2003 2007 *(uint64_t *)vbuf = (uint64_t)kn->value.l;
2004 2008 err = PICL_SUCCESS;
2005 2009 } else
2006 2010 err = PICL_FAILURE;
2007 2011
2008 2012 (void) pthread_mutex_unlock(&kc_mutex);
2009 2013 return (err);
2010 2014 }
2011 2015
2012 2016 /*
2013 2017 * This function adds CPU information to the CPU nodes
2014 2018 */
2015 2019 /* ARGSUSED */
2016 2020 static int
2017 2021 add_processor_info(picl_nodehdl_t cpuh, void *args)
2018 2022 {
2019 2023 int err;
2020 2024 int cpu_id;
2021 2025 ptree_propinfo_t propinfo;
2022 2026 ptree_propinfo_t pinfo;
2023 2027
2024 2028 err = get_cpu_portid(cpuh, &cpu_id);
2025 2029 if (err != PICL_SUCCESS)
2026 2030 return (PICL_WALK_CONTINUE);
2027 2031
2028 2032 /*
2029 2033 * Check to make sure that the CPU is still present, i.e. that it
2030 2034 * has not been DR'ed out of the system.
2031 2035 */
2032 2036 if (p_online(cpu_id, P_STATUS) == -1) {
2033 2037 if (picldevtree_debug)
2034 2038 syslog(LOG_INFO,
2035 2039 "picldevtree: cpu %d (%llx) does not exist - "
2036 2040 "deleting node\n", cpu_id, cpuh);
2037 2041
2038 2042 if (ptree_delete_node(cpuh) == PICL_SUCCESS)
2039 2043 (void) ptree_destroy_node(cpuh);
2040 2044
2041 2045 return (PICL_WALK_CONTINUE);
2042 2046 }
2043 2047
2044 2048 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2045 2049 PICL_PTYPE_INT, PICL_READ, sizeof (int), PICL_PROP_ID, NULL, NULL);
2046 2050 err = ptree_create_and_add_prop(cpuh, &propinfo, &cpu_id, NULL);
2047 2051 if (err != PICL_SUCCESS)
2048 2052 return (PICL_WALK_CONTINUE);
2049 2053
2050 2054 (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
2051 2055 PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), MAX_STATE_SIZE,
2052 2056 PICL_PROP_STATE, get_pi_state, NULL);
2053 2057 (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL);
2054 2058
2055 2059 (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
2056 2060 PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_TYPELEN,
2057 2061 PICL_PROP_PROCESSOR_TYPE, get_processor_type, NULL);
2058 2062 (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL);
2059 2063
2060 2064 (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
2061 2065 PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_FPUTYPE,
2062 2066 PICL_PROP_FPUTYPE, get_fputypes, NULL);
2063 2067 (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL);
2064 2068
2065 2069 (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
2066 2070 PICL_PTYPE_TIMESTAMP, PICL_READ|PICL_VOLATILE, sizeof (uint64_t),
2067 2071 PICL_PROP_STATE_BEGIN, get_pi_state_begin, NULL);
2068 2072 (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL);
2069 2073
2070 2074 return (PICL_WALK_CONTINUE);
2071 2075 }
2072 2076
2073 2077 /*
2074 2078 * This function sets up the "ID" property in every CPU nodes
2075 2079 * and adds processor info
2076 2080 */
2077 2081 static int
2078 2082 setup_cpus(picl_nodehdl_t plafh)
2079 2083 {
2080 2084 int err;
2081 2085
2082 2086 err = ptree_walk_tree_by_class(plafh, PICL_CLASS_CPU, NULL,
2083 2087 add_processor_info);
2084 2088
2085 2089 return (err);
2086 2090 }
2087 2091
2088 2092 /*
2089 2093 * This function format's the manufacture's information for FFB display
2090 2094 * devices
2091 2095 */
2092 2096 static void
2093 2097 fmt_manf_id(manuf_t manufid, int bufsz, char *outbuf)
2094 2098 {
2095 2099 /*
2096 2100 * Format the manufacturer's info. Note a small inconsistency we
2097 2101 * have to work around - Brooktree has it's part number in decimal,
2098 2102 * while Mitsubishi has it's part number in hex.
2099 2103 */
2100 2104 switch (manufid.fld.manf) {
2101 2105 case MANF_BROOKTREE:
2102 2106 (void) snprintf(outbuf, bufsz, "%s %d, version %d",
2103 2107 "Brooktree", manufid.fld.partno, manufid.fld.version);
2104 2108 break;
2105 2109
2106 2110 case MANF_MITSUBISHI:
2107 2111 (void) snprintf(outbuf, bufsz, "%s %x, version %d",
2108 2112 "Mitsubishi", manufid.fld.partno, manufid.fld.version);
2109 2113 break;
2110 2114
2111 2115 default:
2112 2116 (void) snprintf(outbuf, bufsz,
2113 2117 "JED code %d, Part num 0x%x, version %d",
2114 2118 manufid.fld.manf, manufid.fld.partno, manufid.fld.version);
2115 2119 }
2116 2120 }
2117 2121
2118 2122 /*
2119 2123 * If it's an ffb device, open ffb devices and return PICL_SUCCESS
2120 2124 */
2121 2125 static int
2122 2126 open_ffb_device(picl_nodehdl_t ffbh, int *fd)
2123 2127 {
2124 2128 DIR *dirp;
2125 2129 char devfs_path[PATH_MAX];
2126 2130 char dev_path[PATH_MAX];
2127 2131 char *devp;
2128 2132 struct dirent *direntp;
2129 2133 int err;
2130 2134 int tmpfd;
2131 2135
2132 2136 /* Get the devfs_path of the ffb devices */
2133 2137 err = ptree_get_propval_by_name(ffbh, PICL_PROP_DEVFS_PATH, devfs_path,
2134 2138 sizeof (devfs_path));
2135 2139 if (err != PICL_SUCCESS)
2136 2140 return (err);
2137 2141
2138 2142 /* Get the device node name */
2139 2143 devp = strrchr(devfs_path, '/');
2140 2144 if (devp == NULL)
2141 2145 return (PICL_FAILURE);
2142 2146 *devp = '\0';
2143 2147 ++devp;
2144 2148
2145 2149 /*
2146 2150 * Check if device node name has the ffb string
2147 2151 * If not, assume it's not a ffb device.
2148 2152 */
2149 2153 if (strstr(devp, FFB_NAME) == NULL)
2150 2154 return (PICL_FAILURE);
2151 2155
2152 2156 /*
2153 2157 * Get the parent path of the ffb device node.
2154 2158 */
2155 2159 (void) snprintf(dev_path, sizeof (dev_path), "%s/%s", "/devices",
2156 2160 devfs_path);
2157 2161
2158 2162 /*
2159 2163 * Since we don't know ffb's minor nodename,
2160 2164 * we need to search all the devices under its
2161 2165 * parent dir by comparing the node name
2162 2166 */
2163 2167 if ((dirp = opendir(dev_path)) == NULL)
2164 2168 return (PICL_FAILURE);
2165 2169
2166 2170 while ((direntp = readdir(dirp)) != NULL) {
2167 2171 if (strstr(direntp->d_name, devp) != NULL) {
2168 2172 (void) strcat(dev_path, "/");
2169 2173 (void) strcat(dev_path, direntp->d_name);
2170 2174 tmpfd = open(dev_path, O_RDWR);
2171 2175 if (tmpfd < 0)
2172 2176 continue;
2173 2177 *fd = tmpfd;
2174 2178 (void) closedir(dirp);
2175 2179 return (PICL_SUCCESS);
2176 2180 }
2177 2181 }
2178 2182
2179 2183 (void) closedir(dirp);
2180 2184 return (PICL_FAILURE);
2181 2185 }
2182 2186
2183 2187 /*
2184 2188 * This function recursively searches the tree for ffb display devices
2185 2189 * and add ffb config information
2186 2190 */
2187 2191 static int
2188 2192 add_ffb_config_info(picl_nodehdl_t rooth)
2189 2193 {
2190 2194 picl_nodehdl_t nodeh;
2191 2195 int err;
2192 2196 char piclclass[PICL_CLASSNAMELEN_MAX];
2193 2197 char manfidbuf[FFB_MANUF_BUFSIZE];
2194 2198 int fd;
2195 2199 int board_rev;
2196 2200 ffb_sys_info_t fsi;
2197 2201 ptree_propinfo_t pinfo;
2198 2202
2199 2203 for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh,
2200 2204 sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
2201 2205 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER,
2202 2206 &nodeh, sizeof (picl_nodehdl_t))) {
2203 2207
2204 2208 if (err != PICL_SUCCESS)
2205 2209 return (err);
2206 2210
2207 2211 err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
2208 2212 piclclass, PICL_CLASSNAMELEN_MAX);
2209 2213
2210 2214 if ((err == PICL_SUCCESS) &&
2211 2215 (strcmp(piclclass, PICL_CLASS_DISPLAY) == 0)) {
2212 2216
2213 2217 err = open_ffb_device(nodeh, &fd);
2214 2218 if ((err == PICL_SUCCESS) &&
2215 2219 (ioctl(fd, FFB_SYS_INFO, &fsi) >= 0)) {
2216 2220 (void) ptree_init_propinfo(&pinfo,
2217 2221 PTREE_PROPINFO_VERSION,
2218 2222 PICL_PTYPE_UNSIGNED_INT, PICL_READ,
2219 2223 sizeof (int), PICL_PROP_FFB_BOARD_REV,
2220 2224 NULL, NULL);
2221 2225 board_rev = fsi.ffb_strap_bits.fld.board_rev;
2222 2226 (void) ptree_create_and_add_prop(nodeh, &pinfo,
2223 2227 &board_rev, NULL);
2224 2228
2225 2229 fmt_manf_id(fsi.dac_version,
2226 2230 sizeof (manfidbuf), manfidbuf);
2227 2231 (void) ptree_init_propinfo(&pinfo,
2228 2232 PTREE_PROPINFO_VERSION,
2229 2233 PICL_PTYPE_CHARSTRING, PICL_READ,
2230 2234 strlen(manfidbuf) + 1,
2231 2235 PICL_PROP_FFB_DAC_VER, NULL, NULL);
2232 2236 (void) ptree_create_and_add_prop(nodeh, &pinfo,
2233 2237 manfidbuf, NULL);
2234 2238
2235 2239 fmt_manf_id(fsi.fbram_version,
2236 2240 sizeof (manfidbuf), manfidbuf);
2237 2241 (void) ptree_init_propinfo(&pinfo,
2238 2242 PTREE_PROPINFO_VERSION,
2239 2243 PICL_PTYPE_CHARSTRING, PICL_READ,
2240 2244 strlen(manfidbuf) + 1,
2241 2245 PICL_PROP_FFB_FBRAM_VER, NULL,
2242 2246 NULL);
2243 2247 (void) ptree_create_and_add_prop(nodeh, &pinfo,
2244 2248 manfidbuf, NULL);
2245 2249 (void) close(fd);
2246 2250 }
2247 2251 } else if (add_ffb_config_info(nodeh) != PICL_SUCCESS)
2248 2252 return (PICL_FAILURE);
2249 2253 }
2250 2254 return (PICL_SUCCESS);
2251 2255 }
2252 2256
2253 2257 static conf_entries_t *
2254 2258 free_conf_entries(conf_entries_t *list)
2255 2259 {
2256 2260 conf_entries_t *el;
2257 2261 conf_entries_t *del;
2258 2262
2259 2263 if (list == NULL)
2260 2264 return (NULL);
2261 2265 el = list;
2262 2266 while (el != NULL) {
2263 2267 del = el;
2264 2268 el = el->next;
2265 2269 free(del->name);
2266 2270 free(del->piclclass);
2267 2271 free(del);
2268 2272 }
2269 2273 return (el);
2270 2274 }
2271 2275
2272 2276 /*
2273 2277 * Reading config order: platform, common
2274 2278 */
2275 2279 static conf_entries_t *
2276 2280 read_conf_file(char *fname, conf_entries_t *list)
2277 2281 {
2278 2282 FILE *fp;
2279 2283 char lbuf[CONFFILE_LINELEN_MAX];
2280 2284 char *nametok;
2281 2285 char *classtok;
2282 2286 conf_entries_t *el;
2283 2287 conf_entries_t *ptr;
2284 2288
2285 2289 if (fname == NULL)
2286 2290 return (list);
2287 2291
2288 2292 fp = fopen(fname, "r");
2289 2293
2290 2294 if (fp == NULL)
2291 2295 return (list);
2292 2296
2293 2297 while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) {
2294 2298 if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n'))
2295 2299 continue;
2296 2300
2297 2301 nametok = strtok(lbuf, " \t\n");
2298 2302 if (nametok == NULL)
2299 2303 continue;
2300 2304
2301 2305 classtok = strtok(NULL, " \t\n");
2302 2306 if (classtok == NULL)
2303 2307 continue;
2304 2308
2305 2309 el = malloc(sizeof (conf_entries_t));
2306 2310 if (el == NULL)
2307 2311 break;
2308 2312 el->name = strdup(nametok);
2309 2313 el->piclclass = strdup(classtok);
2310 2314 if ((el->name == NULL) || (el->piclclass == NULL)) {
2311 2315 free(el);
2312 2316 return (list);
2313 2317 }
2314 2318 el->next = NULL;
2315 2319
2316 2320 /*
2317 2321 * Add it to the end of list
2318 2322 */
2319 2323 if (list == NULL)
2320 2324 list = el;
2321 2325 else {
2322 2326 ptr = list;
2323 2327 while (ptr->next != NULL)
2324 2328 ptr = ptr->next;
2325 2329 ptr->next = el;
2326 2330 }
2327 2331
2328 2332 }
2329 2333 (void) fclose(fp);
2330 2334 return (list);
2331 2335 }
2332 2336
2333 2337 /*
2334 2338 * Process the devtree conf file and set up the conf_name_class_map list
2335 2339 */
2336 2340 static void
2337 2341 process_devtree_conf_file(void)
2338 2342 {
2339 2343 char nmbuf[SYS_NMLN];
2340 2344 char pname[PATH_MAX];
2341 2345
2342 2346 conf_name_class_map = NULL;
2343 2347
2344 2348 if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
2345 2349 (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
2346 2350 (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX);
2347 2351 conf_name_class_map = read_conf_file(pname,
2348 2352 conf_name_class_map);
2349 2353 }
2350 2354
2351 2355 if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
2352 2356 (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
2353 2357 (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX);
2354 2358 conf_name_class_map = read_conf_file(pname,
2355 2359 conf_name_class_map);
2356 2360 }
2357 2361
2358 2362 (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
2359 2363 DEVTREE_CONFFILE_NAME);
2360 2364 conf_name_class_map = read_conf_file(pname, conf_name_class_map);
2361 2365 }
2362 2366
2363 2367 static asr_conf_entries_t *conf_name_asr_map = NULL;
2364 2368
2365 2369 static void
2366 2370 free_asr_conf_entries(asr_conf_entries_t *list) {
2367 2371 asr_conf_entries_t *el;
2368 2372 asr_conf_entries_t *del;
2369 2373
2370 2374 el = list;
2371 2375 while (el != NULL) {
2372 2376 del = el;
2373 2377 el = el->next;
2374 2378 if (del->name)
2375 2379 free(del->name);
2376 2380 if (del->address)
2377 2381 free(del->address);
2378 2382 if (del->status)
2379 2383 free(del->status);
2380 2384 if (del->piclclass)
2381 2385 free(del->piclclass);
2382 2386 if (del->props)
2383 2387 free(del->props);
2384 2388 free(del);
2385 2389 }
2386 2390 }
2387 2391
2388 2392 /*
2389 2393 * Reading config order: platform, common
2390 2394 */
2391 2395 static asr_conf_entries_t *
2392 2396 read_asr_conf_file(char *fname, asr_conf_entries_t *list)
2393 2397 {
2394 2398 FILE *fp;
2395 2399 char lbuf[CONFFILE_LINELEN_MAX];
2396 2400 char *nametok;
2397 2401 char *classtok;
2398 2402 char *statustok;
2399 2403 char *addresstok;
2400 2404 char *propstok;
2401 2405 asr_conf_entries_t *el;
2402 2406 asr_conf_entries_t *ptr;
2403 2407
2404 2408 if (fname == NULL)
2405 2409 return (list);
2406 2410
2407 2411 fp = fopen(fname, "r");
2408 2412 if (fp == NULL)
2409 2413 return (list);
2410 2414
2411 2415 while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) {
2412 2416 if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n'))
2413 2417 continue;
2414 2418
2415 2419 nametok = strtok(lbuf, " \t\n");
2416 2420 if (nametok == NULL)
2417 2421 continue;
2418 2422
2419 2423 classtok = strtok(NULL, " \t\n");
2420 2424 if (classtok == NULL)
2421 2425 continue;
2422 2426
2423 2427 statustok = strtok(NULL, " \t\n");
2424 2428 if (statustok == NULL)
2425 2429 continue;
2426 2430
2427 2431 addresstok = strtok(NULL, " \t\n");
2428 2432 if (addresstok == NULL)
2429 2433 continue;
2430 2434
2431 2435 /*
2432 2436 * props are optional
2433 2437 */
2434 2438 propstok = strtok(NULL, " \t\n");
2435 2439
2436 2440 el = malloc(sizeof (asr_conf_entries_t));
2437 2441 if (el == NULL)
2438 2442 break;
2439 2443 el->name = strdup(nametok);
2440 2444 el->piclclass = strdup(classtok);
2441 2445 el->status = strdup(statustok);
2442 2446 el->address = strdup(addresstok);
2443 2447 if (propstok != NULL)
2444 2448 el->props = strdup(propstok);
2445 2449 else
2446 2450 el->props = NULL;
2447 2451 if ((el->name == NULL) || (el->piclclass == NULL) ||
2448 2452 (el->address == NULL) || (el->status == NULL)) {
2449 2453 if (el->name)
2450 2454 free(el->name);
2451 2455 if (el->address)
2452 2456 free(el->address);
2453 2457 if (el->status)
2454 2458 free(el->status);
2455 2459 if (el->piclclass)
2456 2460 free(el->piclclass);
2457 2461 if (el->props)
2458 2462 free(el->props);
2459 2463 free(el);
2460 2464 break;
2461 2465 }
2462 2466 el->next = NULL;
2463 2467
2464 2468 /*
2465 2469 * Add it to the end of list
2466 2470 */
2467 2471 if (list == NULL)
2468 2472 list = el;
2469 2473 else {
2470 2474 ptr = list;
2471 2475 while (ptr->next != NULL)
2472 2476 ptr = ptr->next;
2473 2477 ptr->next = el;
2474 2478 }
2475 2479
2476 2480 }
2477 2481 (void) fclose(fp);
2478 2482 return (list);
2479 2483 }
2480 2484
2481 2485 /*
2482 2486 * Process the asr conf file
2483 2487 */
2484 2488 static void
2485 2489 process_asrtree_conf_file(void)
2486 2490 {
2487 2491 char nmbuf[SYS_NMLN];
2488 2492 char pname[PATH_MAX];
2489 2493
2490 2494 if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
2491 2495 (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
2492 2496 (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX);
2493 2497 conf_name_asr_map = read_asr_conf_file(pname,
2494 2498 conf_name_asr_map);
2495 2499 }
2496 2500
2497 2501 if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) {
2498 2502 (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
2499 2503 (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX);
2500 2504 conf_name_asr_map = read_asr_conf_file(pname,
2501 2505 conf_name_asr_map);
2502 2506 }
2503 2507
2504 2508 (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR,
2505 2509 ASRTREE_CONFFILE_NAME);
2506 2510 conf_name_asr_map = read_asr_conf_file(pname, conf_name_asr_map);
2507 2511 }
2508 2512
2509 2513 /*
2510 2514 * This function reads the export file list from ASR
2511 2515 */
2512 2516 static int
2513 2517 get_asr_export_list(char **exportlist, int *exportlistlen)
2514 2518 {
2515 2519 struct openpromio oppbuf;
2516 2520 struct openpromio *opp = &oppbuf;
2517 2521 int d;
2518 2522 int listsize;
2519 2523
2520 2524 d = open("/dev/openprom", O_RDWR);
2521 2525 if (d < 0)
2522 2526 return (0);
2523 2527
2524 2528 if (ioctl(d, OPROMEXPORTLEN, opp) == -1) {
2525 2529 (void) close(d);
2526 2530 return (0);
2527 2531 }
2528 2532 listsize = opp->oprom_size;
2529 2533 opp = (struct openpromio *)malloc(sizeof (struct openpromio) +
2530 2534 listsize);
2531 2535 if (opp == NULL) {
2532 2536 (void) close(d);
2533 2537 return (0);
2534 2538 }
2535 2539 (void) memset(opp, '\0', sizeof (struct openpromio) + listsize);
2536 2540 opp->oprom_size = listsize;
2537 2541 if (ioctl(d, OPROMEXPORT, opp) == -1) {
2538 2542 free(opp);
↓ open down ↓ |
755 lines elided |
↑ open up ↑ |
2539 2543 (void) close(d);
2540 2544 return (0);
2541 2545 }
2542 2546 *exportlist = malloc(listsize);
2543 2547 if (*exportlist == NULL) {
2544 2548 free(opp);
2545 2549 (void) close(d);
2546 2550 return (0);
2547 2551 }
2548 2552 (void) memcpy(*exportlist, opp->oprom_array, opp->oprom_size);
2549 - free(opp);
2550 2553 *exportlistlen = opp->oprom_size;
2554 + free(opp);
2551 2555 (void) close(d);
2552 2556 return (1);
2553 2557 }
2554 2558
2555 2559 /*
2556 2560 * Parses properties string, fills in triplet structure with first
2557 2561 * type, name, val triplet and returns pointer to next property.
2558 2562 * Returns NULL if no valid triplet found
2559 2563 * CAUTION: drops \0 characters over separator characters: if you
2560 2564 * want to parse the string twice, you'll have to take a copy.
2561 2565 */
2562 2566 static char *
2563 2567 parse_props_string(char *props, asr_prop_triplet_t *triplet)
2564 2568 {
2565 2569 char *prop_name;
2566 2570 char *prop_val;
2567 2571 char *prop_next;
2568 2572
2569 2573 prop_name = strchr(props, '?');
2570 2574 if (prop_name == NULL)
2571 2575 return (NULL);
2572 2576 *prop_name++ = '\0';
2573 2577 prop_val = strchr(prop_name, '=');
2574 2578 if (prop_val == NULL)
2575 2579 return (NULL);
2576 2580 *prop_val++ = '\0';
2577 2581 triplet->proptype = props;
2578 2582 triplet->propname = prop_name;
2579 2583 triplet->propval = prop_val;
2580 2584 prop_next = strchr(prop_val, ':');
2581 2585 if (prop_next == NULL)
2582 2586 return (prop_val - 1);
2583 2587 *prop_next++ = '\0';
2584 2588 return (prop_next);
2585 2589 }
2586 2590
2587 2591 static int
2588 2592 add_status_prop(picl_nodehdl_t chdh, char *status)
2589 2593 {
2590 2594 ptree_propinfo_t propinfo;
2591 2595 picl_prophdl_t proph;
2592 2596 int err;
2593 2597
2594 2598 err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2595 2599 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(status) + 1,
2596 2600 PICL_PROP_STATUS, NULL, NULL);
2597 2601 if (err != PICL_SUCCESS)
2598 2602 return (err);
2599 2603 err = ptree_create_and_add_prop(chdh, &propinfo, status, &proph);
2600 2604 return (err);
2601 2605 }
2602 2606
2603 2607 static void
2604 2608 create_asr_node(char *parent, char *child, char *unitaddr, char *class,
2605 2609 char *status, char *props)
2606 2610 {
2607 2611 char ptreepath[PATH_MAX];
2608 2612 char nodename[PICL_PROPNAMELEN_MAX];
2609 2613 char ua[MAX_UNIT_ADDRESS_LEN];
2610 2614 char *props_copy = NULL;
2611 2615 char *next;
2612 2616 char *prop_string;
2613 2617 boolean_t found = B_FALSE;
2614 2618 picl_nodehdl_t nodeh;
2615 2619 picl_nodehdl_t chdh;
2616 2620 asr_prop_triplet_t triple;
2617 2621 ptree_propinfo_t propinfo;
2618 2622 picl_prophdl_t proph;
2619 2623 int val;
2620 2624 int err;
2621 2625
2622 2626 (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX);
2623 2627 (void) strlcat(ptreepath, parent, PATH_MAX);
2624 2628
2625 2629 if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS)
2626 2630 return;
2627 2631 /*
2628 2632 * see if the required child node already exists
2629 2633 */
2630 2634 for (err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
2631 2635 sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
2632 2636 err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
2633 2637 sizeof (picl_nodehdl_t))) {
2634 2638 if (err != PICL_SUCCESS)
2635 2639 break;
2636 2640 err = ptree_get_propval_by_name(chdh, PICL_PROP_NAME,
2637 2641 (void *)nodename, PICL_PROPNAMELEN_MAX);
2638 2642 if (err != PICL_SUCCESS)
2639 2643 break;
2640 2644 if (strcmp(nodename, child) != 0)
2641 2645 continue;
2642 2646 /*
2643 2647 * found a candidate child node
2644 2648 */
2645 2649 if (unitaddr) {
2646 2650 /*
2647 2651 * does it match the required unit address?
2648 2652 */
2649 2653 err = ptree_get_propval_by_name(chdh,
2650 2654 PICL_PROP_UNIT_ADDRESS, ua, sizeof (ua));
2651 2655 if (err == PICL_PROPNOTFOUND)
2652 2656 continue;
2653 2657 if (err != PICL_SUCCESS)
2654 2658 break;
2655 2659 if (strcmp(unitaddr, ua) != 0)
2656 2660 continue;
2657 2661 }
2658 2662 if (props == NULL) {
2659 2663 next = "";
2660 2664 } else if (props_copy == NULL) {
2661 2665 props_copy = strdup(props);
2662 2666 if (props_copy == NULL)
2663 2667 return;
2664 2668 next = props_copy;
2665 2669 }
2666 2670 while ((next = parse_props_string(next, &triple)) != NULL) {
2667 2671 err = ptree_get_prop_by_name(chdh, triple.propname,
2668 2672 &proph);
2669 2673 if (err != PICL_SUCCESS)
2670 2674 break;
2671 2675 err = ptree_get_propinfo(proph, &propinfo);
2672 2676 if (err != PICL_SUCCESS)
2673 2677 break;
2674 2678 err = PICL_FAILURE;
2675 2679 switch (propinfo.piclinfo.type) {
2676 2680 case PICL_PTYPE_INT:
2677 2681 case PICL_PTYPE_UNSIGNED_INT:
2678 2682 if (strcmp(triple.proptype, "I") != 0)
2679 2683 break;
2680 2684 err = ptree_get_propval(proph, (void *)&val,
2681 2685 sizeof (val));
2682 2686 if (err != PICL_SUCCESS)
2683 2687 break;
2684 2688 if (val != atoi(triple.propval))
2685 2689 err = PICL_FAILURE;
2686 2690 break;
2687 2691 case PICL_PTYPE_CHARSTRING:
2688 2692 if (strcmp(triple.proptype, "S") != 0)
2689 2693 break;
2690 2694 prop_string = malloc(propinfo.piclinfo.size);
2691 2695 if (prop_string == NULL)
2692 2696 break;
2693 2697 err = ptree_get_propval(proph,
2694 2698 (void *)prop_string,
2695 2699 propinfo.piclinfo.size);
2696 2700 if (err != PICL_SUCCESS) {
2697 2701 free(prop_string);
2698 2702 break;
2699 2703 }
2700 2704 if (strcmp(prop_string, triple.propval) != 0)
2701 2705 err = PICL_FAILURE;
2702 2706 free(prop_string);
2703 2707 break;
2704 2708 default:
2705 2709 break;
2706 2710 }
2707 2711 if (err != PICL_SUCCESS) {
2708 2712 break;
2709 2713 }
2710 2714 }
2711 2715 if (next == NULL) {
2712 2716 found = B_TRUE;
2713 2717 break;
2714 2718 }
2715 2719 }
2716 2720 if (props_copy)
2717 2721 free(props_copy);
2718 2722 if (found) {
2719 2723 /*
2720 2724 * does the pre-existing node have a status property?
2721 2725 */
2722 2726 err = ptree_get_propval_by_name(chdh, PICL_PROP_STATUS,
2723 2727 ua, sizeof (ua));
2724 2728 if (err == PICL_PROPNOTFOUND)
2725 2729 (void) add_status_prop(chdh, status);
2726 2730 if (err != PICL_SUCCESS)
2727 2731 return;
2728 2732 if ((strcmp(ua, ASR_DISABLED) == 0) ||
2729 2733 (strcmp(ua, ASR_FAILED) == 0) ||
2730 2734 ((strcmp(status, ASR_DISABLED) != 0) &&
2731 2735 (strcmp(status, ASR_FAILED) != 0))) {
2732 2736 return;
2733 2737 }
2734 2738 /*
2735 2739 * more urgent status now, so replace existing value
2736 2740 */
2737 2741 err = ptree_get_prop_by_name(chdh, PICL_PROP_STATUS, &proph);
2738 2742 if (err != PICL_SUCCESS)
2739 2743 return;
2740 2744 (void) ptree_delete_prop(proph);
2741 2745 (void) ptree_destroy_prop(proph);
2742 2746 err = add_status_prop(chdh, status);
2743 2747 if (err != PICL_SUCCESS)
2744 2748 return;
2745 2749 return;
2746 2750 }
2747 2751
2748 2752 /*
2749 2753 * typical case, node needs adding together with a set of properties
2750 2754 */
2751 2755 if (ptree_create_and_add_node(nodeh, child, class, &chdh) ==
2752 2756 PICL_SUCCESS) {
2753 2757 (void) add_status_prop(chdh, status);
2754 2758 if (unitaddr) {
2755 2759 (void) ptree_init_propinfo(&propinfo,
2756 2760 PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING,
2757 2761 PICL_READ, strlen(unitaddr) + 1,
2758 2762 PICL_PROP_UNIT_ADDRESS, NULL, NULL);
2759 2763 (void) ptree_create_and_add_prop(chdh, &propinfo,
2760 2764 unitaddr, &proph);
2761 2765 (void) strlcpy(ptreepath, parent, PATH_MAX);
2762 2766 (void) strlcat(ptreepath, "/", PATH_MAX);
2763 2767 (void) strlcat(ptreepath, child, PATH_MAX);
2764 2768 (void) strlcat(ptreepath, "@", PATH_MAX);
2765 2769 (void) strlcat(ptreepath, unitaddr, PATH_MAX);
2766 2770 (void) ptree_init_propinfo(&propinfo,
2767 2771 PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING,
2768 2772 PICL_READ, strlen(ptreepath) + 1,
2769 2773 PICL_PROP_DEVFS_PATH, NULL, NULL);
2770 2774 (void) ptree_create_and_add_prop(chdh, &propinfo,
2771 2775 ptreepath, &proph);
2772 2776 }
2773 2777 next = props;
2774 2778 while ((next = parse_props_string(next, &triple)) != NULL) {
2775 2779 /*
2776 2780 * only handle int and string properties for
2777 2781 * simplicity
2778 2782 */
2779 2783 if (strcmp(triple.proptype, "I") == 0) {
2780 2784 (void) ptree_init_propinfo(&propinfo,
2781 2785 PTREE_PROPINFO_VERSION,
2782 2786 PICL_PTYPE_INT, PICL_READ,
2783 2787 sizeof (int), triple.propname, NULL, NULL);
2784 2788 val = atoi(triple.propval);
2785 2789 (void) ptree_create_and_add_prop(chdh,
2786 2790 &propinfo, &val, &proph);
2787 2791 } else {
2788 2792 (void) ptree_init_propinfo(&propinfo,
2789 2793 PTREE_PROPINFO_VERSION,
2790 2794 PICL_PTYPE_CHARSTRING, PICL_READ,
2791 2795 strlen(triple.propval) + 1,
2792 2796 triple.propname, NULL, NULL);
2793 2797 (void) ptree_create_and_add_prop(chdh,
2794 2798 &propinfo, triple.propval, &proph);
2795 2799 }
2796 2800 }
2797 2801 }
2798 2802 }
2799 2803
2800 2804 static void
2801 2805 add_asr_nodes()
2802 2806 {
2803 2807 char *asrexport;
2804 2808 int asrexportlen;
2805 2809 asr_conf_entries_t *c = NULL;
2806 2810 int i;
2807 2811 char *key;
2808 2812 char *child;
2809 2813 char *unitaddr;
2810 2814 uint16_t count;
2811 2815 int disabled;
2812 2816
2813 2817 if (get_asr_export_list(&asrexport, &asrexportlen) == 0)
2814 2818 return;
2815 2819 process_asrtree_conf_file();
2816 2820 if (conf_name_asr_map == NULL)
2817 2821 return;
2818 2822 i = 0;
2819 2823 while (i < asrexportlen) {
2820 2824 key = &asrexport[i];
2821 2825 i += strlen(key) + 1;
2822 2826 if (i >= asrexportlen)
2823 2827 break;
2824 2828
2825 2829 /*
2826 2830 * next byte tells us whether failed by diags or manually
2827 2831 * disabled
2828 2832 */
2829 2833 disabled = asrexport[i];
2830 2834 i++;
2831 2835 if (i >= asrexportlen)
2832 2836 break;
2833 2837
2834 2838 /*
2835 2839 * only type 1 supported
2836 2840 */
2837 2841 if (asrexport[i] != 1)
2838 2842 break;
2839 2843 i++;
2840 2844 if (i >= asrexportlen)
2841 2845 break;
2842 2846
2843 2847 /*
2844 2848 * next two bytes give size of reason string
2845 2849 */
2846 2850 count = (asrexport[i] << 8) | asrexport[i + 1];
2847 2851 i += count + 2;
2848 2852 if (i > asrexportlen)
2849 2853 break;
2850 2854
2851 2855 /*
2852 2856 * now look for key in conf file info
2853 2857 */
2854 2858 c = conf_name_asr_map;
2855 2859 while (c != NULL) {
2856 2860 if (strcmp(key, c->name) == 0) {
2857 2861 child = strrchr(c->address, '/');
2858 2862 *child++ = '\0';
2859 2863 unitaddr = strchr(child, '@');
2860 2864 if (unitaddr)
2861 2865 *unitaddr++ = '\0';
2862 2866 if (strcmp(c->status, ASR_DISABLED) == 0) {
2863 2867 create_asr_node(c->address, child,
2864 2868 unitaddr, c->piclclass, disabled ?
2865 2869 ASR_DISABLED : ASR_FAILED,
2866 2870 c->props);
2867 2871 } else {
2868 2872 create_asr_node(c->address, child,
2869 2873 unitaddr, c->piclclass, c->status,
2870 2874 c->props);
2871 2875 }
2872 2876 }
2873 2877 c = c->next;
2874 2878 }
2875 2879 }
2876 2880
2877 2881 free_asr_conf_entries(conf_name_asr_map);
2878 2882 free(asrexport);
2879 2883 }
2880 2884
2881 2885 /*
2882 2886 * This function adds information to the /platform node
2883 2887 */
2884 2888 static int
2885 2889 add_platform_info(picl_nodehdl_t plafh)
2886 2890 {
2887 2891 struct utsname uts_info;
2888 2892 int err;
2889 2893 ptree_propinfo_t propinfo;
2890 2894 picl_prophdl_t proph;
2891 2895
2892 2896 if (uname(&uts_info) < 0)
2893 2897 return (PICL_FAILURE);
2894 2898
2895 2899 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2896 2900 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.sysname) + 1,
2897 2901 PICL_PROP_SYSNAME, NULL, NULL);
2898 2902 err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.sysname,
2899 2903 &proph);
2900 2904 if (err != PICL_SUCCESS)
2901 2905 return (err);
2902 2906
2903 2907 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2904 2908 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.nodename) + 1,
2905 2909 PICL_PROP_NODENAME, NULL, NULL);
2906 2910 err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.nodename,
2907 2911 &proph);
2908 2912 if (err != PICL_SUCCESS)
2909 2913 return (err);
2910 2914
2911 2915 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2912 2916 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.release) + 1,
2913 2917 PICL_PROP_RELEASE, NULL, NULL);
2914 2918 err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.release,
2915 2919 &proph);
2916 2920 if (err != PICL_SUCCESS)
2917 2921 return (err);
2918 2922
2919 2923 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2920 2924 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.version) + 1,
2921 2925 PICL_PROP_VERSION, NULL, NULL);
2922 2926 err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.version,
2923 2927 &proph);
2924 2928 if (err != PICL_SUCCESS)
2925 2929 return (err);
2926 2930
2927 2931 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
2928 2932 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.machine) + 1,
2929 2933 PICL_PROP_MACHINE, NULL, NULL);
2930 2934 err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.machine,
2931 2935 &proph);
2932 2936 return (err);
2933 2937 }
2934 2938
2935 2939 /*
2936 2940 * Get first 32-bit value from the reg property
2937 2941 */
2938 2942 static int
2939 2943 get_first_reg_word(picl_nodehdl_t nodeh, uint32_t *regval)
2940 2944 {
2941 2945 int err;
2942 2946 uint32_t *regbuf;
2943 2947 picl_prophdl_t regh;
2944 2948 ptree_propinfo_t pinfo;
2945 2949
2946 2950 err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h);
2947 2951 if (err != PICL_SUCCESS) /* no reg property */
2948 2952 return (err);
2949 2953 err = ptree_get_propinfo(regh, &pinfo);
2950 2954 if (err != PICL_SUCCESS)
2951 2955 return (err);
2952 2956 if (pinfo.piclinfo.size < sizeof (uint32_t)) /* too small */
2953 2957 return (PICL_FAILURE);
2954 2958 regbuf = alloca(pinfo.piclinfo.size);
2955 2959 if (regbuf == NULL)
2956 2960 return (PICL_FAILURE);
2957 2961 err = ptree_get_propval(regh, regbuf, pinfo.piclinfo.size);
2958 2962 if (err != PICL_SUCCESS)
2959 2963 return (err);
2960 2964 *regval = *regbuf; /* get first 32-bit value */
2961 2965 return (PICL_SUCCESS);
2962 2966 }
2963 2967
2964 2968 /*
2965 2969 * Get device ID from the reg property
2966 2970 */
2967 2971 static int
2968 2972 get_device_id(picl_nodehdl_t nodeh, uint32_t *dev_id)
2969 2973 {
2970 2974 int err;
2971 2975 uint32_t regval;
2972 2976
2973 2977 err = get_first_reg_word(nodeh, ®val);
2974 2978 if (err != PICL_SUCCESS)
2975 2979 return (err);
2976 2980
2977 2981 *dev_id = PCI_DEVICE_ID(regval);
2978 2982 return (PICL_SUCCESS);
2979 2983 }
2980 2984
2981 2985 /*
2982 2986 * add Slot property for children of SBUS node
2983 2987 */
2984 2988 /* ARGSUSED */
2985 2989 static int
2986 2990 add_sbus_slots(picl_nodehdl_t pcih, void *args)
2987 2991 {
2988 2992 picl_nodehdl_t nodeh;
2989 2993 uint32_t slot;
2990 2994 int err;
2991 2995 ptree_propinfo_t pinfo;
2992 2996
2993 2997 for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
2994 2998 sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
2995 2999 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
2996 3000 sizeof (picl_nodehdl_t))) {
2997 3001 if (err != PICL_SUCCESS)
2998 3002 return (err);
2999 3003
3000 3004 if (get_first_reg_word(nodeh, &slot) != 0)
3001 3005 continue;
3002 3006 (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
3003 3007 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t),
3004 3008 PICL_PROP_SLOT, NULL, NULL);
3005 3009 (void) ptree_create_and_add_prop(nodeh, &pinfo, &slot, NULL);
3006 3010 }
3007 3011
3008 3012 return (PICL_WALK_CONTINUE);
3009 3013 }
3010 3014
3011 3015 /*
3012 3016 * This function creates a Slot property for SBUS child nodes
3013 3017 * which can be correlated with the slot they are plugged into
3014 3018 * on the motherboard.
3015 3019 */
3016 3020 static int
3017 3021 set_sbus_slot(picl_nodehdl_t plafh)
3018 3022 {
3019 3023 int err;
3020 3024
3021 3025 err = ptree_walk_tree_by_class(plafh, PICL_CLASS_SBUS, NULL,
3022 3026 add_sbus_slots);
3023 3027
3024 3028 return (err);
3025 3029 }
3026 3030
3027 3031 /*
3028 3032 * add DeviceID property for children of PCI/PCIEX node
3029 3033 */
3030 3034 /* ARGSUSED */
3031 3035 static int
3032 3036 add_pci_deviceids(picl_nodehdl_t pcih, void *args)
3033 3037 {
3034 3038 picl_nodehdl_t nodeh;
3035 3039 uint32_t dev_id;
3036 3040 int err;
3037 3041 ptree_propinfo_t pinfo;
3038 3042
3039 3043 for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh,
3040 3044 sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
3041 3045 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh,
3042 3046 sizeof (picl_nodehdl_t))) {
3043 3047 if (err != PICL_SUCCESS)
3044 3048 return (err);
3045 3049
3046 3050 if (get_device_id(nodeh, &dev_id) != 0)
3047 3051 continue;
3048 3052 (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
3049 3053 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t),
3050 3054 PICL_PROP_DEVICE_ID, NULL, NULL);
3051 3055 (void) ptree_create_and_add_prop(nodeh, &pinfo, &dev_id, NULL);
3052 3056 }
3053 3057
3054 3058 return (PICL_WALK_CONTINUE);
3055 3059 }
3056 3060
3057 3061 /*
3058 3062 * This function creates a DeviceID property for PCI/PCIEX child nodes
3059 3063 * which can be correlated with the slot they are plugged into
3060 3064 * on the motherboard.
3061 3065 */
3062 3066 static void
3063 3067 set_pci_pciex_deviceid(picl_nodehdl_t plafh)
3064 3068 {
3065 3069 (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCI, NULL,
3066 3070 add_pci_deviceids);
3067 3071
3068 3072 (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, NULL,
3069 3073 add_pci_deviceids);
3070 3074 }
3071 3075
3072 3076 /*
3073 3077 * Default UnitAddress encode function
3074 3078 */
3075 3079 static int
3076 3080 encode_default_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3077 3081 {
3078 3082 int i, len;
3079 3083
3080 3084 /*
3081 3085 * Encode UnitAddress as %a,%b,%c,...,%n
3082 3086 */
3083 3087 if (addrcells < 1)
3084 3088 return (-1);
3085 3089
3086 3090 len = snprintf(buf, sz, "%x", *regprop);
3087 3091 for (i = 1; i < addrcells && len < sz; i++)
3088 3092 len += snprintf(&buf[len], sz-len, ",%x", regprop[i]);
3089 3093
3090 3094 return ((len >= sz) ? -1 : 0);
3091 3095 }
3092 3096
3093 3097 /*
3094 3098 * UnitAddress encode function where the last component is not printed
3095 3099 * unless non-zero.
3096 3100 */
3097 3101 static int
3098 3102 encode_optional_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3099 3103 {
3100 3104 int retval;
3101 3105
3102 3106 /*
3103 3107 * Encode UnitAddress as %a,%b,%c,...,%n where the last component
3104 3108 * is printed only if non-zero.
3105 3109 */
3106 3110 if (addrcells > 1 && regprop[addrcells-1] == 0)
3107 3111 retval = encode_default_unitaddr(buf, sz, regprop, addrcells-1);
3108 3112 else
3109 3113 retval = encode_default_unitaddr(buf, sz, regprop, addrcells);
3110 3114
3111 3115 return (retval);
3112 3116 }
3113 3117
3114 3118
3115 3119 /*
3116 3120 * UnitAddress encode function for SCSI class of devices
3117 3121 */
3118 3122 static int
3119 3123 encode_scsi_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3120 3124 {
3121 3125 int len, retval;
3122 3126
3123 3127 /*
3124 3128 * #address-cells Format
3125 3129 * 2 second component printed only if non-zero
3126 3130 *
3127 3131 * 4 regprop: phys_hi phys_lo lun_hi lun_lo
3128 3132 * UnitAddr: w<phys_hi><phys_lo>,<lun_lo>
3129 3133 */
3130 3134
3131 3135 if (addrcells == 2) {
3132 3136 retval = encode_optional_unitaddr(buf, sz, regprop, addrcells);
3133 3137 } else if (addrcells == 4) {
3134 3138 len = snprintf(buf, sz, "w%08x%08x,%x", regprop[0], regprop[1],
3135 3139 regprop[3]);
3136 3140 retval = (len >= sz) ? -1 : 0;
3137 3141 } else
3138 3142 retval = -1;
3139 3143
3140 3144 return (retval);
3141 3145 }
3142 3146
3143 3147 /*
3144 3148 * UnitAddress encode function for UPA devices
3145 3149 */
3146 3150 static int
3147 3151 encode_upa_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3148 3152 {
3149 3153 int len;
3150 3154
3151 3155 if (addrcells != 2)
3152 3156 return (-1);
3153 3157
3154 3158 len = snprintf(buf, sz, "%x,%x", (regprop[0]/2)&0x1f, regprop[1]);
3155 3159 return ((len >= sz) ? -1 : 0);
3156 3160 }
3157 3161
3158 3162 /*
3159 3163 * UnitAddress encode function for GPTWO, JBUS devices
3160 3164 */
3161 3165 static int
3162 3166 encode_gptwo_jbus_unitaddr(char *buf, int sz, uint32_t *regprop,
3163 3167 uint_t addrcells)
3164 3168 {
3165 3169 uint32_t hi, lo;
3166 3170 int len, id, off;
3167 3171
3168 3172 if (addrcells != 2)
3169 3173 return (-1);
3170 3174
3171 3175 hi = regprop[0];
3172 3176 lo = regprop[1];
3173 3177
3174 3178 if (hi & 0x400) {
3175 3179 id = ((hi & 0x1) << 9) | (lo >> 23); /* agent id */
3176 3180 off = lo & 0x7fffff; /* config offset */
3177 3181 len = snprintf(buf, sz, "%x,%x", id, off);
3178 3182 } else {
3179 3183 len = snprintf(buf, sz, "m%x,%x", hi, lo);
3180 3184 }
3181 3185 return ((len >= sz) ? -1 : 0);
3182 3186 }
3183 3187
3184 3188 /*
3185 3189 * UnitAddress encode function for PCI devices
3186 3190 */
3187 3191 static int
3188 3192 encode_pci_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells)
3189 3193 {
3190 3194 typedef struct {
3191 3195 uint32_t n:1, /* relocatable */
3192 3196 p:1, /* prefetchable */
3193 3197 t:1, /* address region aliases */
3194 3198 zero:3, /* must be zero */
3195 3199 ss:2, /* address space type */
3196 3200 bus:8, /* bus number */
3197 3201 dev:5, /* device number */
3198 3202 fn:3, /* function number */
3199 3203 reg:8; /* register number */
3200 3204 uint32_t phys_hi; /* high physical address */
3201 3205 uint32_t phys_lo; /* low physical address */
3202 3206 } pci_addrcell_t;
3203 3207
3204 3208 pci_addrcell_t *p;
3205 3209 int len;
3206 3210
3207 3211 if (addrcells != 3)
3208 3212 return (-1);
3209 3213
3210 3214 p = (pci_addrcell_t *)regprop;
3211 3215 switch (p->ss) {
3212 3216 case 0: /* Config */
3213 3217 if (p->fn)
3214 3218 len = snprintf(buf, sz, "%x,%x", p->dev, p->fn);
3215 3219 else
3216 3220 len = snprintf(buf, sz, "%x", p->dev);
3217 3221 break;
3218 3222 case 1: /* IO */
3219 3223 len = snprintf(buf, sz, "i%x,%x,%x,%x", p->dev, p->fn, p->reg,
3220 3224 p->phys_lo);
3221 3225 break;
3222 3226 case 2: /* Mem32 */
3223 3227 len = snprintf(buf, sz, "m%x,%x,%x,%x", p->dev, p->fn, p->reg,
3224 3228 p->phys_lo);
3225 3229 break;
3226 3230 case 3: /* Mem64 */
3227 3231 len = snprintf(buf, sz, "x%x,%x,%x,%x%08x", p->dev, p->fn,
3228 3232 p->reg, p->phys_hi, p->phys_lo);
3229 3233 break;
3230 3234 }
3231 3235 return ((len >= sz) ? -1 : 0);
3232 3236 }
3233 3237
3234 3238 /*
3235 3239 * Get #address-cells property value
3236 3240 */
3237 3241 static uint_t
3238 3242 get_addrcells_prop(picl_nodehdl_t nodeh)
3239 3243 {
3240 3244 int len, err;
3241 3245 uint32_t addrcells;
3242 3246 ptree_propinfo_t pinfo;
3243 3247 picl_prophdl_t proph;
3244 3248
3245 3249 /*
3246 3250 * Get #address-cells property. If not present, use default value.
3247 3251 */
3248 3252 err = ptree_get_prop_by_name(nodeh, OBP_PROP_ADDRESS_CELLS, &proph);
3249 3253 if (err == PICL_SUCCESS)
3250 3254 err = ptree_get_propinfo(proph, &pinfo);
3251 3255
3252 3256 len = pinfo.piclinfo.size;
3253 3257 if (err == PICL_SUCCESS && len >= sizeof (uint8_t) &&
3254 3258 len <= sizeof (addrcells)) {
3255 3259 err = ptree_get_propval(proph, &addrcells, len);
3256 3260 if (err == PICL_SUCCESS) {
3257 3261 if (len == sizeof (uint8_t))
3258 3262 addrcells = *(uint8_t *)&addrcells;
3259 3263 else if (len == sizeof (uint16_t))
3260 3264 addrcells = *(uint16_t *)&addrcells;
3261 3265 } else
3262 3266 addrcells = DEFAULT_ADDRESS_CELLS;
3263 3267 } else
3264 3268 addrcells = DEFAULT_ADDRESS_CELLS;
3265 3269
3266 3270 return (addrcells);
3267 3271 }
3268 3272
3269 3273 /*
3270 3274 * Get UnitAddress mapping entry for a node
3271 3275 */
3272 3276 static unitaddr_map_t *
3273 3277 get_unitaddr_mapping(picl_nodehdl_t nodeh)
3274 3278 {
3275 3279 int err;
3276 3280 unitaddr_map_t *uamap;
3277 3281 char clname[PICL_CLASSNAMELEN_MAX];
3278 3282
3279 3283 /*
3280 3284 * Get my classname and locate a function to translate "reg" prop
3281 3285 * into "UnitAddress" prop for my children.
3282 3286 */
3283 3287 err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, clname,
3284 3288 sizeof (clname));
3285 3289 if (err != PICL_SUCCESS)
3286 3290 (void) strcpy(clname, ""); /* NULL class name */
3287 3291
3288 3292 for (uamap = &unitaddr_map_table[0]; uamap->class != NULL; uamap++)
3289 3293 if (strcmp(clname, uamap->class) == 0)
3290 3294 break;
3291 3295
3292 3296 return (uamap);
3293 3297 }
3294 3298
3295 3299 /*
3296 3300 * Add UnitAddress property to the specified node
3297 3301 */
3298 3302 static int
3299 3303 add_unitaddr_prop(picl_nodehdl_t nodeh, unitaddr_map_t *uamap, uint_t addrcells)
3300 3304 {
3301 3305 int regproplen, err;
3302 3306 uint32_t *regbuf;
3303 3307 picl_prophdl_t regh;
3304 3308 ptree_propinfo_t pinfo;
3305 3309 char unitaddr[MAX_UNIT_ADDRESS_LEN];
3306 3310
3307 3311 err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h);
3308 3312 if (err != PICL_SUCCESS)
3309 3313 return (err);
3310 3314
3311 3315 err = ptree_get_propinfo(regh, &pinfo);
3312 3316 if (err != PICL_SUCCESS)
3313 3317 return (PICL_FAILURE);
3314 3318
3315 3319 if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t)))
3316 3320 return (PICL_FAILURE);
3317 3321
3318 3322 regproplen = pinfo.piclinfo.size;
3319 3323 regbuf = alloca(regproplen);
3320 3324 if (regbuf == NULL)
3321 3325 return (PICL_FAILURE);
3322 3326
3323 3327 err = ptree_get_propval(regh, regbuf, regproplen);
3324 3328 if (err != PICL_SUCCESS || uamap->func == NULL ||
3325 3329 (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) ||
3326 3330 (uamap->func)(unitaddr, sizeof (unitaddr), regbuf,
3327 3331 addrcells) != 0) {
3328 3332 return (PICL_FAILURE);
3329 3333 }
3330 3334
3331 3335 err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
3332 3336 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(unitaddr)+1,
3333 3337 PICL_PROP_UNIT_ADDRESS, NULL, NULL);
3334 3338 if (err == PICL_SUCCESS)
3335 3339 err = ptree_create_and_add_prop(nodeh, &pinfo, unitaddr, NULL);
3336 3340
3337 3341 return (err);
3338 3342 }
3339 3343
3340 3344 /*
3341 3345 * work out UnitAddress property of the specified node
3342 3346 */
3343 3347 static int
3344 3348 get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh, char *unitaddr,
3345 3349 size_t ualen)
3346 3350 {
3347 3351 int regproplen, err;
3348 3352 uint32_t *regbuf;
3349 3353 picl_prophdl_t regh;
3350 3354 ptree_propinfo_t pinfo;
3351 3355 unitaddr_map_t *uamap;
3352 3356 uint32_t addrcells;
3353 3357
3354 3358 addrcells = get_addrcells_prop(parh);
3355 3359 uamap = get_unitaddr_mapping(parh);
3356 3360
3357 3361 err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h);
3358 3362 if (err != PICL_SUCCESS)
3359 3363 return (err);
3360 3364
3361 3365 err = ptree_get_propinfo(regh, &pinfo);
3362 3366 if (err != PICL_SUCCESS)
3363 3367 return (err);
3364 3368
3365 3369 if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t)))
3366 3370 return (PICL_FAILURE);
3367 3371
3368 3372 regproplen = pinfo.piclinfo.size;
3369 3373 regbuf = alloca(regproplen);
3370 3374 if (regbuf == NULL)
3371 3375 return (PICL_FAILURE);
3372 3376
3373 3377 err = ptree_get_propval(regh, regbuf, regproplen);
3374 3378 if (err != PICL_SUCCESS || uamap->func == NULL ||
3375 3379 (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) ||
3376 3380 (uamap->func)(unitaddr, ualen, regbuf, addrcells) != 0) {
3377 3381 return (PICL_FAILURE);
3378 3382 }
3379 3383 return (PICL_SUCCESS);
3380 3384 }
3381 3385
3382 3386 /*
3383 3387 * Add UnitAddress property to all children of the specified node
3384 3388 */
3385 3389 static int
3386 3390 add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh)
3387 3391 {
3388 3392 int err;
3389 3393 picl_nodehdl_t chdh;
3390 3394 unitaddr_map_t *uamap;
3391 3395 uint32_t addrcells;
3392 3396
3393 3397 /*
3394 3398 * Get #address-cells and unit address mapping entry for my
3395 3399 * node's class
3396 3400 */
3397 3401 addrcells = get_addrcells_prop(nodeh);
3398 3402 uamap = get_unitaddr_mapping(nodeh);
3399 3403
3400 3404 /*
3401 3405 * Add UnitAddress property to my children and their subtree
3402 3406 */
3403 3407 err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
3404 3408 sizeof (picl_nodehdl_t));
3405 3409
3406 3410 while (err == PICL_SUCCESS) {
3407 3411 (void) add_unitaddr_prop(chdh, uamap, addrcells);
3408 3412 (void) add_unitaddr_prop_to_subtree(chdh);
3409 3413
3410 3414 err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
3411 3415 sizeof (picl_nodehdl_t));
3412 3416 }
3413 3417
3414 3418 return (PICL_SUCCESS);
3415 3419 }
3416 3420
3417 3421 static int
3418 3422 update_memory_size_prop(picl_nodehdl_t plafh)
3419 3423 {
3420 3424 picl_nodehdl_t memh;
3421 3425 picl_prophdl_t proph;
3422 3426 ptree_propinfo_t pinfo;
3423 3427 int err, nspecs, snum, pval;
3424 3428 char *regbuf;
3425 3429 memspecs_t *mspecs;
3426 3430 uint64_t memsize;
3427 3431
3428 3432 /*
3429 3433 * check if the #size-cells of the platform node is 2
3430 3434 */
3431 3435 err = ptree_get_propval_by_name(plafh, OBP_PROP_SIZE_CELLS, &pval,
3432 3436 sizeof (pval));
3433 3437
3434 3438 if (err == PICL_PROPNOTFOUND)
3435 3439 pval = SUPPORTED_NUM_CELL_SIZE;
3436 3440 else if (err != PICL_SUCCESS)
3437 3441 return (err);
3438 3442
3439 3443 /*
3440 3444 * don't know how to handle other vals
3441 3445 */
3442 3446 if (pval != SUPPORTED_NUM_CELL_SIZE)
3443 3447 return (PICL_FAILURE);
3444 3448
3445 3449 err = ptree_get_node_by_path(MEMORY_PATH, &memh);
3446 3450 if (err != PICL_SUCCESS)
3447 3451 return (err);
3448 3452
3449 3453 /*
3450 3454 * Get the REG property to calculate the size of memory
3451 3455 */
3452 3456 err = ptree_get_prop_by_name(memh, OBP_REG, &proph);
3453 3457 if (err != PICL_SUCCESS)
3454 3458 return (err);
3455 3459
3456 3460 err = ptree_get_propinfo(proph, &pinfo);
3457 3461 if (err != PICL_SUCCESS)
3458 3462 return (err);
3459 3463
3460 3464 regbuf = alloca(pinfo.piclinfo.size);
3461 3465 if (regbuf == NULL)
3462 3466 return (PICL_FAILURE);
3463 3467
3464 3468 err = ptree_get_propval(proph, regbuf, pinfo.piclinfo.size);
3465 3469 if (err != PICL_SUCCESS)
3466 3470 return (err);
3467 3471
3468 3472 mspecs = (memspecs_t *)regbuf;
3469 3473 nspecs = pinfo.piclinfo.size / sizeof (memspecs_t);
3470 3474
3471 3475 memsize = 0;
3472 3476 for (snum = 0; snum < nspecs; ++snum)
3473 3477 memsize += mspecs[snum].size;
3474 3478
3475 3479 err = ptree_get_prop_by_name(memh, PICL_PROP_SIZE, &proph);
3476 3480 if (err == PICL_SUCCESS) {
3477 3481 err = ptree_update_propval(proph, &memsize, sizeof (memsize));
3478 3482 return (err);
3479 3483 }
3480 3484
3481 3485 /*
3482 3486 * Add the size property
3483 3487 */
3484 3488 (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION,
3485 3489 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (memsize),
3486 3490 PICL_PROP_SIZE, NULL, NULL);
3487 3491 err = ptree_create_and_add_prop(memh, &pinfo, &memsize, NULL);
3488 3492 return (err);
3489 3493 }
3490 3494
3491 3495 /*
3492 3496 * This function is executed as part of .init when the plugin is
3493 3497 * dlopen()ed
3494 3498 */
3495 3499 static void
3496 3500 picldevtree_register(void)
3497 3501 {
3498 3502 if (getenv(SUNW_PICLDEVTREE_PLUGIN_DEBUG))
3499 3503 picldevtree_debug = 1;
3500 3504 (void) picld_plugin_register(&my_reg_info);
3501 3505 }
3502 3506
3503 3507 /*
3504 3508 * This function is the init entry point of the plugin.
3505 3509 * It initializes the /platform tree based on libdevinfo
3506 3510 */
3507 3511 static void
3508 3512 picldevtree_init(void)
3509 3513 {
3510 3514 picl_nodehdl_t rhdl;
3511 3515 int err;
3512 3516 struct utsname utsname;
3513 3517 picl_nodehdl_t plafh;
3514 3518
3515 3519 if (uname(&utsname) < 0)
3516 3520 return;
3517 3521
3518 3522 (void) strcpy(mach_name, utsname.machine);
3519 3523
3520 3524 if (strcmp(mach_name, "sun4u") == 0) {
3521 3525 builtin_map_ptr = sun4u_map;
3522 3526 builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t);
3523 3527 } else if (strcmp(mach_name, "sun4v") == 0) {
3524 3528 builtin_map_ptr = sun4u_map;
3525 3529 builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t);
3526 3530 } else if (strcmp(mach_name, "i86pc") == 0) {
3527 3531 builtin_map_ptr = i86pc_map;
3528 3532 builtin_map_size = sizeof (i86pc_map) / sizeof (builtin_map_t);
3529 3533 } else {
3530 3534 builtin_map_ptr = NULL;
3531 3535 builtin_map_size = 0;
3532 3536 }
3533 3537
3534 3538 err = ptree_get_root(&rhdl);
3535 3539 if (err != PICL_SUCCESS) {
3536 3540 syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED);
3537 3541 return;
3538 3542 }
3539 3543
3540 3544 process_devtree_conf_file();
3541 3545
3542 3546 if (libdevinfo_init(rhdl) != PICL_SUCCESS) {
3543 3547 syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED);
3544 3548 return;
3545 3549 }
3546 3550
3547 3551 err = ptree_get_node_by_path(PLATFORM_PATH, &plafh);
3548 3552 if (err != PICL_SUCCESS)
3549 3553 return;
3550 3554
3551 3555 (void) add_unitaddr_prop_to_subtree(plafh);
3552 3556
3553 3557 add_asr_nodes();
3554 3558
3555 3559 (void) update_memory_size_prop(plafh);
3556 3560
3557 3561 (void) setup_cpus(plafh);
3558 3562
3559 3563 (void) add_ffb_config_info(plafh);
3560 3564
3561 3565 (void) add_platform_info(plafh);
3562 3566
3563 3567 set_pci_pciex_deviceid(plafh);
3564 3568
3565 3569 (void) set_sbus_slot(plafh);
3566 3570
3567 3571 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3568 3572 picldevtree_evhandler, NULL);
3569 3573 (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3570 3574 picldevtree_evhandler, NULL);
3571 3575 (void) ptree_register_handler(PICLEVENT_CPU_STATE_CHANGE,
3572 3576 picldevtree_evhandler, NULL);
3573 3577 (void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3574 3578 picldevtree_evhandler, NULL);
3575 3579 }
3576 3580
3577 3581 /*
3578 3582 * This function is the fini entry point of the plugin
3579 3583 */
3580 3584 static void
3581 3585 picldevtree_fini(void)
3582 3586 {
3583 3587 /* First unregister the event handlers */
3584 3588 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
3585 3589 picldevtree_evhandler, NULL);
3586 3590 (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED,
3587 3591 picldevtree_evhandler, NULL);
3588 3592 (void) ptree_unregister_handler(PICLEVENT_CPU_STATE_CHANGE,
3589 3593 picldevtree_evhandler, NULL);
3590 3594 (void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE,
3591 3595 picldevtree_evhandler, NULL);
3592 3596
3593 3597 conf_name_class_map = free_conf_entries(conf_name_class_map);
3594 3598 }
3595 3599
3596 3600 /*
3597 3601 * This function is the event handler of this plug-in.
3598 3602 *
3599 3603 * It processes the following events:
3600 3604 *
3601 3605 * PICLEVENT_SYSEVENT_DEVICE_ADDED
3602 3606 * PICLEVENT_SYSEVENT_DEVICE_REMOVED
3603 3607 * PICLEVENT_CPU_STATE_CHANGE
3604 3608 * PICLEVENT_DR_AP_STATE_CHANGE
3605 3609 */
3606 3610 /* ARGSUSED */
3607 3611 static void
3608 3612 picldevtree_evhandler(const char *ename, const void *earg, size_t size,
3609 3613 void *cookie)
3610 3614 {
3611 3615 char *devfs_path;
3612 3616 char ptreepath[PATH_MAX];
3613 3617 char dipath[PATH_MAX];
3614 3618 picl_nodehdl_t plafh;
3615 3619 picl_nodehdl_t nodeh;
3616 3620 nvlist_t *nvlp;
3617 3621
3618 3622 if ((earg == NULL) ||
3619 3623 (ptree_get_node_by_path(PLATFORM_PATH, &plafh) != PICL_SUCCESS))
3620 3624 return;
3621 3625
3622 3626 if (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) == 0) {
3623 3627 (void) setup_cpus(plafh);
3624 3628 if (picldevtree_debug > 1)
3625 3629 syslog(LOG_INFO, "picldevtree: event handler done\n");
3626 3630 return;
3627 3631 }
3628 3632
3629 3633 nvlp = NULL;
3630 3634 if (nvlist_unpack((char *)earg, size, &nvlp, NULL) ||
3631 3635 nvlist_lookup_string(nvlp, PICLEVENTARG_DEVFS_PATH, &devfs_path) ||
3632 3636 strlen(devfs_path) > (PATH_MAX - sizeof (PLATFORM_PATH))) {
3633 3637 syslog(LOG_INFO, PICL_EVENT_DROPPED, ename);
3634 3638 nvlist_free(nvlp);
3635 3639 return;
3636 3640 }
3637 3641
3638 3642 (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX);
3639 3643 (void) strlcat(ptreepath, devfs_path, PATH_MAX);
3640 3644 (void) strlcpy(dipath, devfs_path, PATH_MAX);
3641 3645 nvlist_free(nvlp);
3642 3646
3643 3647 if (picldevtree_debug)
3644 3648 syslog(LOG_INFO, "picldevtree: event handler invoked ename:%s "
3645 3649 "ptreepath:%s\n", ename, ptreepath);
3646 3650
3647 3651 if (strcmp(ename, PICLEVENT_CPU_STATE_CHANGE) == 0) {
3648 3652 goto done;
3649 3653 }
3650 3654 if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) {
3651 3655 di_node_t devnode;
3652 3656 char *strp;
3653 3657 picl_nodehdl_t parh;
3654 3658 char nodeclass[PICL_CLASSNAMELEN_MAX];
3655 3659 char *nodename;
3656 3660 int err;
3657 3661
3658 3662 /* If the node already exist, then nothing else to do here */
3659 3663 if (ptree_get_node_by_path(ptreepath, &nodeh) == PICL_SUCCESS)
3660 3664 return;
3661 3665
3662 3666 /* Skip if unable to find parent PICL node handle */
3663 3667 parh = plafh;
3664 3668 if (((strp = strrchr(ptreepath, '/')) != NULL) &&
3665 3669 (strp != strchr(ptreepath, '/'))) {
3666 3670 *strp = '\0';
3667 3671 if (ptree_get_node_by_path(ptreepath, &parh) !=
3668 3672 PICL_SUCCESS)
3669 3673 return;
3670 3674 }
3671 3675
3672 3676 /*
3673 3677 * If parent is the root node
3674 3678 */
3675 3679 if (parh == plafh) {
3676 3680 ph = di_prom_init();
3677 3681 devnode = di_init(dipath, DINFOCPYALL);
3678 3682 if (devnode == DI_NODE_NIL) {
3679 3683 if (ph != NULL) {
3680 3684 di_prom_fini(ph);
3681 3685 ph = NULL;
3682 3686 }
3683 3687 return;
3684 3688 }
3685 3689 nodename = di_node_name(devnode);
3686 3690 if (nodename == NULL) {
3687 3691 di_fini(devnode);
3688 3692 if (ph != NULL) {
3689 3693 di_prom_fini(ph);
3690 3694 ph = NULL;
3691 3695 }
3692 3696 return;
3693 3697 }
3694 3698
3695 3699 err = get_node_class(nodeclass, devnode, nodename);
3696 3700 if (err < 0) {
3697 3701 di_fini(devnode);
3698 3702 if (ph != NULL) {
3699 3703 di_prom_fini(ph);
3700 3704 ph = NULL;
3701 3705 }
3702 3706 return;
3703 3707 }
3704 3708 err = construct_devtype_node(plafh, nodename,
3705 3709 nodeclass, devnode, &nodeh);
3706 3710 if (err != PICL_SUCCESS) {
3707 3711 di_fini(devnode);
3708 3712 if (ph != NULL) {
3709 3713 di_prom_fini(ph);
3710 3714 ph = NULL;
3711 3715 }
3712 3716 return;
3713 3717 }
3714 3718 (void) update_subtree(nodeh, devnode);
3715 3719 (void) add_unitaddr_prop_to_subtree(nodeh);
3716 3720 if (ph != NULL) {
3717 3721 di_prom_fini(ph);
3718 3722 ph = NULL;
3719 3723 }
3720 3724 di_fini(devnode);
3721 3725 goto done;
3722 3726 }
3723 3727
3724 3728 /* kludge ... try without bus-addr first */
3725 3729 if ((strp = strrchr(dipath, '@')) != NULL) {
3726 3730 char *p;
3727 3731
3728 3732 p = strrchr(dipath, '/');
3729 3733 if (p != NULL && strp > p) {
3730 3734 *strp = '\0';
3731 3735 devnode = di_init(dipath, DINFOCPYALL);
3732 3736 if (devnode != DI_NODE_NIL)
3733 3737 di_fini(devnode);
3734 3738 *strp = '@';
3735 3739 }
3736 3740 }
3737 3741 /* Get parent devnode */
3738 3742 if ((strp = strrchr(dipath, '/')) != NULL)
3739 3743 *++strp = '\0';
3740 3744 devnode = di_init(dipath, DINFOCPYALL);
3741 3745 if (devnode == DI_NODE_NIL)
3742 3746 return;
3743 3747 ph = di_prom_init();
3744 3748 (void) update_subtree(parh, devnode);
3745 3749 (void) add_unitaddr_prop_to_subtree(parh);
3746 3750 if (ph) {
3747 3751 di_prom_fini(ph);
3748 3752 ph = NULL;
3749 3753 }
3750 3754 di_fini(devnode);
3751 3755 } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) {
3752 3756 char delclass[PICL_CLASSNAMELEN_MAX];
3753 3757 char *strp;
3754 3758
3755 3759 /*
3756 3760 * if final element of path doesn't have a unit address
3757 3761 * then it is not uniquely identifiable - cannot remove
3758 3762 */
3759 3763 if (((strp = strrchr(ptreepath, '/')) != NULL) &&
3760 3764 strchr(strp, '@') == NULL)
3761 3765 return;
3762 3766
3763 3767 /* skip if can't find the node */
3764 3768 if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS)
3765 3769 return;
3766 3770
3767 3771 if (ptree_delete_node(nodeh) != PICL_SUCCESS)
3768 3772 return;
3769 3773
3770 3774 if (picldevtree_debug)
3771 3775 syslog(LOG_INFO,
3772 3776 "picldevtree: deleted node nodeh:%llx\n", nodeh);
3773 3777 if ((ptree_get_propval_by_name(nodeh,
3774 3778 PICL_PROP_CLASSNAME, delclass, PICL_CLASSNAMELEN_MAX) ==
3775 3779 PICL_SUCCESS) && IS_MC(delclass)) {
3776 3780 if (post_mc_event(PICLEVENT_MC_REMOVED, nodeh) !=
3777 3781 PICL_SUCCESS)
3778 3782 syslog(LOG_WARNING, PICL_EVENT_DROPPED,
3779 3783 PICLEVENT_MC_REMOVED);
3780 3784 } else
3781 3785 (void) ptree_destroy_node(nodeh);
3782 3786 }
3783 3787 done:
3784 3788 (void) setup_cpus(plafh);
3785 3789 (void) add_ffb_config_info(plafh);
3786 3790 set_pci_pciex_deviceid(plafh);
3787 3791 (void) set_sbus_slot(plafh);
3788 3792 if (picldevtree_debug > 1)
3789 3793 syslog(LOG_INFO, "picldevtree: event handler done\n");
3790 3794 }
↓ open down ↓ |
1230 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX