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