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