10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53343Srd117015 * Common Development and Distribution License (the "License"). 63343Srd117015 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 227442SMichael.Bergknoff@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * PICL plug-in that creates device tree nodes for all platforms 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <stdio.h> 310Sstevel@tonic-gate #include <string.h> 320Sstevel@tonic-gate #include <ctype.h> 330Sstevel@tonic-gate #include <limits.h> 340Sstevel@tonic-gate #include <stdlib.h> 350Sstevel@tonic-gate #include <assert.h> 360Sstevel@tonic-gate #include <alloca.h> 370Sstevel@tonic-gate #include <unistd.h> 380Sstevel@tonic-gate #include <stropts.h> 390Sstevel@tonic-gate #include <syslog.h> 400Sstevel@tonic-gate #include <libdevinfo.h> 410Sstevel@tonic-gate #include <sys/dkio.h> 420Sstevel@tonic-gate #include <sys/vtoc.h> 430Sstevel@tonic-gate #include <sys/time.h> 440Sstevel@tonic-gate #include <fcntl.h> 450Sstevel@tonic-gate #include <picl.h> 460Sstevel@tonic-gate #include <picltree.h> 470Sstevel@tonic-gate #include <sys/types.h> 480Sstevel@tonic-gate #include <sys/processor.h> 490Sstevel@tonic-gate #include <kstat.h> 500Sstevel@tonic-gate #include <sys/sysinfo.h> 510Sstevel@tonic-gate #include <dirent.h> 520Sstevel@tonic-gate #include <libintl.h> 530Sstevel@tonic-gate #include <pthread.h> 540Sstevel@tonic-gate #include <libnvpair.h> 550Sstevel@tonic-gate #include <sys/utsname.h> 560Sstevel@tonic-gate #include <sys/systeminfo.h> 570Sstevel@tonic-gate #include <sys/obpdefs.h> 580Sstevel@tonic-gate #include <sys/openpromio.h> 590Sstevel@tonic-gate #include "picldevtree.h" 600Sstevel@tonic-gate 610Sstevel@tonic-gate /* 620Sstevel@tonic-gate * Plugin registration entry points 630Sstevel@tonic-gate */ 640Sstevel@tonic-gate static void picldevtree_register(void); 650Sstevel@tonic-gate static void picldevtree_init(void); 660Sstevel@tonic-gate static void picldevtree_fini(void); 670Sstevel@tonic-gate 680Sstevel@tonic-gate static void picldevtree_evhandler(const char *ename, const void *earg, 690Sstevel@tonic-gate size_t size, void *cookie); 700Sstevel@tonic-gate 710Sstevel@tonic-gate #pragma init(picldevtree_register) 720Sstevel@tonic-gate 730Sstevel@tonic-gate /* 740Sstevel@tonic-gate * Log message texts 750Sstevel@tonic-gate */ 760Sstevel@tonic-gate #define DEVINFO_PLUGIN_INIT_FAILED gettext("SUNW_picldevtree failed!\n") 770Sstevel@tonic-gate #define PICL_EVENT_DROPPED \ 780Sstevel@tonic-gate gettext("SUNW_picldevtree '%s' event dropped.\n") 790Sstevel@tonic-gate 800Sstevel@tonic-gate /* 810Sstevel@tonic-gate * Macro to get PCI device id (from IEEE 1275 spec) 820Sstevel@tonic-gate */ 830Sstevel@tonic-gate #define PCI_DEVICE_ID(x) (((x) >> 11) & 0x1f) 840Sstevel@tonic-gate /* 850Sstevel@tonic-gate * Local variables 860Sstevel@tonic-gate */ 870Sstevel@tonic-gate static picld_plugin_reg_t my_reg_info = { 880Sstevel@tonic-gate PICLD_PLUGIN_VERSION_1, 890Sstevel@tonic-gate PICLD_PLUGIN_CRITICAL, 900Sstevel@tonic-gate "SUNW_picldevtree", 910Sstevel@tonic-gate picldevtree_init, 920Sstevel@tonic-gate picldevtree_fini 930Sstevel@tonic-gate }; 940Sstevel@tonic-gate 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * Debug enabling environment variable 970Sstevel@tonic-gate */ 980Sstevel@tonic-gate #define SUNW_PICLDEVTREE_PLUGIN_DEBUG "SUNW_PICLDEVTREE_PLUGIN_DEBUG" 990Sstevel@tonic-gate static int picldevtree_debug = 0; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate static conf_entries_t *conf_name_class_map = NULL; 1020Sstevel@tonic-gate static builtin_map_t sun4u_map[] = { 1030Sstevel@tonic-gate /* MAX_NAMEVAL_SIZE */ 1040Sstevel@tonic-gate { "SUNW,bpp", PICL_CLASS_PARALLEL}, 1050Sstevel@tonic-gate { "parallel", PICL_CLASS_PARALLEL}, 1060Sstevel@tonic-gate { "floppy", PICL_CLASS_FLOPPY}, 1070Sstevel@tonic-gate { "memory", PICL_CLASS_MEMORY}, 1080Sstevel@tonic-gate { "ebus", PICL_CLASS_EBUS}, 1090Sstevel@tonic-gate { "i2c", PICL_CLASS_I2C}, 1100Sstevel@tonic-gate { "usb", PICL_CLASS_USB}, 1110Sstevel@tonic-gate { "isa", PICL_CLASS_ISA}, 1120Sstevel@tonic-gate { "dma", PICL_CLASS_DMA}, 1130Sstevel@tonic-gate { "keyboard", PICL_CLASS_KEYBOARD}, 1140Sstevel@tonic-gate { "mouse", PICL_CLASS_MOUSE}, 1150Sstevel@tonic-gate { "fan-control", PICL_CLASS_FAN_CONTROL}, 1160Sstevel@tonic-gate { "sc", PICL_CLASS_SYSTEM_CONTROLLER}, 1170Sstevel@tonic-gate { "dimm", PICL_CLASS_SEEPROM}, 1180Sstevel@tonic-gate { "dimm-fru", PICL_CLASS_SEEPROM}, 1190Sstevel@tonic-gate { "cpu", PICL_CLASS_SEEPROM}, 1200Sstevel@tonic-gate { "cpu-fru", PICL_CLASS_SEEPROM}, 1210Sstevel@tonic-gate { "flashprom", PICL_CLASS_FLASHPROM}, 1220Sstevel@tonic-gate { "temperature", PICL_CLASS_TEMPERATURE_DEVICE}, 1230Sstevel@tonic-gate { "motherboard", PICL_CLASS_SEEPROM}, 1240Sstevel@tonic-gate { "motherboard-fru", PICL_CLASS_SEEPROM}, 1250Sstevel@tonic-gate { "motherboard-fru-prom", PICL_CLASS_SEEPROM}, 1260Sstevel@tonic-gate { "pmu", PICL_CLASS_PMU}, 1270Sstevel@tonic-gate { "sound", PICL_CLASS_SOUND}, 1280Sstevel@tonic-gate { "firewire", PICL_CLASS_FIREWIRE}, 1290Sstevel@tonic-gate { "i2c-at34c02", PICL_CLASS_SEEPROM}, 1300Sstevel@tonic-gate { "hardware-monitor", PICL_CLASS_HARDWARE_MONITOR}, 1310Sstevel@tonic-gate { "", ""} 1320Sstevel@tonic-gate }; 1330Sstevel@tonic-gate static builtin_map_t i86pc_map[] = { 1340Sstevel@tonic-gate /* MAX_NAMEVAL_SIZE */ 1350Sstevel@tonic-gate { "cpus", PICL_CLASS_I86CPUS}, 1360Sstevel@tonic-gate { "cpu", PICL_CLASS_CPU}, 1370Sstevel@tonic-gate { "memory", PICL_CLASS_MEMORY}, 1380Sstevel@tonic-gate { "asy", PICL_CLASS_SERIAL}, 1390Sstevel@tonic-gate { "", ""} 1400Sstevel@tonic-gate }; 1410Sstevel@tonic-gate static pname_type_map_t pname_type_map[] = { 1420Sstevel@tonic-gate { "reg", PICL_PTYPE_BYTEARRAY}, 1430Sstevel@tonic-gate { "device_type", PICL_PTYPE_CHARSTRING}, 1440Sstevel@tonic-gate { "ranges", PICL_PTYPE_BYTEARRAY}, 1450Sstevel@tonic-gate { "status", PICL_PTYPE_CHARSTRING}, 1460Sstevel@tonic-gate { "compatible", PICL_PTYPE_CHARSTRING}, 1470Sstevel@tonic-gate { "interrupts", PICL_PTYPE_BYTEARRAY}, 1480Sstevel@tonic-gate { "model", PICL_PTYPE_CHARSTRING}, 1490Sstevel@tonic-gate { "address", PICL_PTYPE_BYTEARRAY}, 1500Sstevel@tonic-gate { "vendor-id", PICL_PTYPE_UNSIGNED_INT}, 1510Sstevel@tonic-gate { "device-id", PICL_PTYPE_UNSIGNED_INT}, 1520Sstevel@tonic-gate { "revision-id", PICL_PTYPE_UNSIGNED_INT}, 1530Sstevel@tonic-gate { "class-code", PICL_PTYPE_UNSIGNED_INT}, 1540Sstevel@tonic-gate { "min-grant", PICL_PTYPE_UNSIGNED_INT}, 1550Sstevel@tonic-gate { "max-latency", PICL_PTYPE_UNSIGNED_INT}, 1560Sstevel@tonic-gate { "devsel-speed", PICL_PTYPE_UNSIGNED_INT}, 1570Sstevel@tonic-gate { "subsystem-id", PICL_PTYPE_UNSIGNED_INT}, 1580Sstevel@tonic-gate { "subsystem-vendor-id", PICL_PTYPE_UNSIGNED_INT}, 1590Sstevel@tonic-gate { "assigned-addresses", PICL_PTYPE_BYTEARRAY}, 1600Sstevel@tonic-gate { "configuration#", PICL_PTYPE_UNSIGNED_INT}, 1610Sstevel@tonic-gate { "assigned-address", PICL_PTYPE_UNSIGNED_INT}, 1620Sstevel@tonic-gate { "#address-cells", PICL_PTYPE_UNSIGNED_INT}, 1630Sstevel@tonic-gate { "#size-cells", PICL_PTYPE_UNSIGNED_INT}, 1640Sstevel@tonic-gate { "clock-frequency", PICL_PTYPE_UNSIGNED_INT}, 1650Sstevel@tonic-gate { "scsi-initiator-id", PICL_PTYPE_UNSIGNED_INT}, 1660Sstevel@tonic-gate { "differential", PICL_PTYPE_UNSIGNED_INT}, 1670Sstevel@tonic-gate { "idprom", PICL_PTYPE_BYTEARRAY}, 1680Sstevel@tonic-gate { "bus-range", PICL_PTYPE_BYTEARRAY}, 1690Sstevel@tonic-gate { "alternate-reg", PICL_PTYPE_BYTEARRAY}, 1700Sstevel@tonic-gate { "power-consumption", PICL_PTYPE_BYTEARRAY}, 1710Sstevel@tonic-gate { "slot-names", PICL_PTYPE_BYTEARRAY}, 1720Sstevel@tonic-gate { "burst-sizes", PICL_PTYPE_UNSIGNED_INT}, 1730Sstevel@tonic-gate { "up-burst-sizes", PICL_PTYPE_UNSIGNED_INT}, 1740Sstevel@tonic-gate { "slot-address-bits", PICL_PTYPE_UNSIGNED_INT}, 1750Sstevel@tonic-gate { "eisa-slots", PICL_PTYPE_BYTEARRAY}, 1760Sstevel@tonic-gate { "dma", PICL_PTYPE_BYTEARRAY}, 1770Sstevel@tonic-gate { "slot-names-index", PICL_PTYPE_UNSIGNED_INT}, 1780Sstevel@tonic-gate { "pnp-csn", PICL_PTYPE_UNSIGNED_INT}, 1790Sstevel@tonic-gate { "pnp-data", PICL_PTYPE_BYTEARRAY}, 1800Sstevel@tonic-gate { "description", PICL_PTYPE_CHARSTRING}, 1810Sstevel@tonic-gate { "pnp-id", PICL_PTYPE_CHARSTRING}, 1820Sstevel@tonic-gate { "max-frame-size", PICL_PTYPE_UNSIGNED_INT}, 1830Sstevel@tonic-gate { "address-bits", PICL_PTYPE_UNSIGNED_INT}, 1840Sstevel@tonic-gate { "local-mac-address", PICL_PTYPE_BYTEARRAY}, 1850Sstevel@tonic-gate { "mac-address", PICL_PTYPE_BYTEARRAY}, 1860Sstevel@tonic-gate { "character-set", PICL_PTYPE_CHARSTRING}, 1870Sstevel@tonic-gate { "available", PICL_PTYPE_BYTEARRAY}, 1880Sstevel@tonic-gate { "port-wwn", PICL_PTYPE_BYTEARRAY}, 1890Sstevel@tonic-gate { "node-wwn", PICL_PTYPE_BYTEARRAY}, 1900Sstevel@tonic-gate { "width", PICL_PTYPE_UNSIGNED_INT}, 1910Sstevel@tonic-gate { "linebytes", PICL_PTYPE_UNSIGNED_INT}, 1920Sstevel@tonic-gate { "height", PICL_PTYPE_UNSIGNED_INT}, 1930Sstevel@tonic-gate { "banner-name", PICL_PTYPE_CHARSTRING}, 1940Sstevel@tonic-gate { "reset-reason", PICL_PTYPE_CHARSTRING}, 1950Sstevel@tonic-gate { "implementation#", PICL_PTYPE_UNSIGNED_INT}, 1960Sstevel@tonic-gate { "version#", PICL_PTYPE_UNSIGNED_INT}, 1970Sstevel@tonic-gate { "icache-size", PICL_PTYPE_UNSIGNED_INT}, 1980Sstevel@tonic-gate { "icache-line-size", PICL_PTYPE_UNSIGNED_INT}, 1990Sstevel@tonic-gate { "icache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2000Sstevel@tonic-gate { "l1-icache-size", PICL_PTYPE_UNSIGNED_INT}, 2010Sstevel@tonic-gate { "l1-icache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2020Sstevel@tonic-gate { "l1-icache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2030Sstevel@tonic-gate { "#itlb-entries", PICL_PTYPE_UNSIGNED_INT}, 2040Sstevel@tonic-gate { "dcache-size", PICL_PTYPE_UNSIGNED_INT}, 2050Sstevel@tonic-gate { "dcache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2060Sstevel@tonic-gate { "dcache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2070Sstevel@tonic-gate { "l1-dcache-size", PICL_PTYPE_UNSIGNED_INT}, 2080Sstevel@tonic-gate { "l1-dcache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2090Sstevel@tonic-gate { "l1-dcache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2100Sstevel@tonic-gate { "#dtlb-entries", PICL_PTYPE_UNSIGNED_INT}, 2110Sstevel@tonic-gate { "ecache-size", PICL_PTYPE_UNSIGNED_INT}, 2120Sstevel@tonic-gate { "ecache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2130Sstevel@tonic-gate { "ecache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2140Sstevel@tonic-gate { "l2-cache-size", PICL_PTYPE_UNSIGNED_INT}, 2150Sstevel@tonic-gate { "l2-cache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2160Sstevel@tonic-gate { "l2-cache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2170Sstevel@tonic-gate { "l2-cache-sharing", PICL_PTYPE_BYTEARRAY}, 2180Sstevel@tonic-gate { "mask#", PICL_PTYPE_UNSIGNED_INT}, 2190Sstevel@tonic-gate { "manufacturer#", PICL_PTYPE_UNSIGNED_INT}, 2200Sstevel@tonic-gate { "sparc-version", PICL_PTYPE_UNSIGNED_INT}, 2210Sstevel@tonic-gate { "version", PICL_PTYPE_CHARSTRING}, 2220Sstevel@tonic-gate { "cpu-model", PICL_PTYPE_UNSIGNED_INT}, 2230Sstevel@tonic-gate { "memory-layout", PICL_PTYPE_BYTEARRAY}, 2240Sstevel@tonic-gate { "#interrupt-cells", PICL_PTYPE_UNSIGNED_INT}, 2250Sstevel@tonic-gate { "interrupt-map", PICL_PTYPE_BYTEARRAY}, 2260Sstevel@tonic-gate { "interrupt-map-mask", PICL_PTYPE_BYTEARRAY} 2270Sstevel@tonic-gate }; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate #define PNAME_MAP_SIZE sizeof (pname_type_map) / sizeof (pname_type_map_t) 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate static builtin_map_t *builtin_map_ptr = NULL; 2320Sstevel@tonic-gate static int builtin_map_size = 0; 2330Sstevel@tonic-gate static char mach_name[SYS_NMLN]; 2340Sstevel@tonic-gate static di_prom_handle_t ph = DI_PROM_HANDLE_NIL; 2357442SMichael.Bergknoff@Sun.COM static int snapshot_stale; 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate /* 2380Sstevel@tonic-gate * UnitAddress mapping table 2390Sstevel@tonic-gate */ 2400Sstevel@tonic-gate static unitaddr_func_t encode_default_unitaddr; 2410Sstevel@tonic-gate static unitaddr_func_t encode_optional_unitaddr; 2420Sstevel@tonic-gate static unitaddr_func_t encode_scsi_unitaddr; 2430Sstevel@tonic-gate static unitaddr_func_t encode_upa_unitaddr; 2440Sstevel@tonic-gate static unitaddr_func_t encode_gptwo_jbus_unitaddr; 2450Sstevel@tonic-gate static unitaddr_func_t encode_pci_unitaddr; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate static unitaddr_map_t unitaddr_map_table[] = { 2480Sstevel@tonic-gate {PICL_CLASS_JBUS, encode_gptwo_jbus_unitaddr, 0}, 2490Sstevel@tonic-gate {PICL_CLASS_GPTWO, encode_gptwo_jbus_unitaddr, 0}, 2500Sstevel@tonic-gate {PICL_CLASS_PCI, encode_pci_unitaddr, 0}, 251944Svenki {PICL_CLASS_PCIEX, encode_pci_unitaddr, 0}, 2520Sstevel@tonic-gate {PICL_CLASS_UPA, encode_upa_unitaddr, 0}, 2530Sstevel@tonic-gate {PICL_CLASS_SCSI, encode_scsi_unitaddr, 0}, 2540Sstevel@tonic-gate {PICL_CLASS_SCSI2, encode_scsi_unitaddr, 0}, 2550Sstevel@tonic-gate {PICL_CLASS_EBUS, encode_default_unitaddr, 2}, 2560Sstevel@tonic-gate {PICL_CLASS_SBUS, encode_default_unitaddr, 2}, 2570Sstevel@tonic-gate {PICL_CLASS_I2C, encode_default_unitaddr, 2}, 2580Sstevel@tonic-gate {PICL_CLASS_USB, encode_default_unitaddr, 1}, 2590Sstevel@tonic-gate {PICL_CLASS_PMU, encode_optional_unitaddr, 2}, 2600Sstevel@tonic-gate {NULL, encode_default_unitaddr, 0} 2610Sstevel@tonic-gate }; 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate static int add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh); 2640Sstevel@tonic-gate static int get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh, 2650Sstevel@tonic-gate char *unitaddr, size_t ualen); 266944Svenki static void set_pci_pciex_deviceid(picl_nodehdl_t plafh); 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate /* 2690Sstevel@tonic-gate * The mc event completion handler. 2700Sstevel@tonic-gate * The arguments are event name buffer and a packed nvlist buffer 2710Sstevel@tonic-gate * with the size specifying the size of unpacked nvlist. These 2720Sstevel@tonic-gate * buffers are deallcoated here. 2730Sstevel@tonic-gate * 2740Sstevel@tonic-gate * Also, if a memory controller node is being removed then destroy the 2750Sstevel@tonic-gate * PICL subtree associated with that memory controller. 2760Sstevel@tonic-gate */ 2770Sstevel@tonic-gate static void 2780Sstevel@tonic-gate mc_completion_handler(char *ename, void *earg, size_t size) 2790Sstevel@tonic-gate { 2800Sstevel@tonic-gate picl_nodehdl_t mch; 2810Sstevel@tonic-gate nvlist_t *unpack_nvl; 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_MC_REMOVED) == 0 && 2840Sstevel@tonic-gate nvlist_unpack(earg, size, &unpack_nvl, NULL) == 0) { 2850Sstevel@tonic-gate mch = NULL; 2860Sstevel@tonic-gate (void) nvlist_lookup_uint64(unpack_nvl, 2870Sstevel@tonic-gate PICLEVENTARG_NODEHANDLE, &mch); 2880Sstevel@tonic-gate if (mch != NULL) { 2890Sstevel@tonic-gate if (picldevtree_debug) 2900Sstevel@tonic-gate syslog(LOG_INFO, 2910Sstevel@tonic-gate "picldevtree: destroying_node:%llx\n", 2920Sstevel@tonic-gate mch); 2930Sstevel@tonic-gate (void) ptree_destroy_node(mch); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate nvlist_free(unpack_nvl); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate free(ename); 2990Sstevel@tonic-gate free(earg); 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate /* 3030Sstevel@tonic-gate * Functions to post memory controller change event 3040Sstevel@tonic-gate */ 3050Sstevel@tonic-gate static int 3060Sstevel@tonic-gate post_mc_event(char *ename, picl_nodehdl_t mch) 3070Sstevel@tonic-gate { 3080Sstevel@tonic-gate nvlist_t *nvl; 3090Sstevel@tonic-gate size_t nvl_size; 3100Sstevel@tonic-gate char *pack_buf; 3110Sstevel@tonic-gate char *ev_name; 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate ev_name = strdup(ename); 3140Sstevel@tonic-gate if (ev_name == NULL) 3150Sstevel@tonic-gate return (-1); 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) { 3180Sstevel@tonic-gate free(ev_name); 3190Sstevel@tonic-gate return (-1); 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate pack_buf = NULL; 3230Sstevel@tonic-gate if (nvlist_add_uint64(nvl, PICLEVENTARG_NODEHANDLE, mch) || 3240Sstevel@tonic-gate nvlist_pack(nvl, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) { 3250Sstevel@tonic-gate free(ev_name); 3260Sstevel@tonic-gate nvlist_free(nvl); 3270Sstevel@tonic-gate return (-1); 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate if (picldevtree_debug) 3310Sstevel@tonic-gate syslog(LOG_INFO, 3320Sstevel@tonic-gate "picldevtree: posting MC event ename:%s nodeh:%llx\n", 3330Sstevel@tonic-gate ev_name, mch); 3340Sstevel@tonic-gate if (ptree_post_event(ev_name, pack_buf, nvl_size, 3350Sstevel@tonic-gate mc_completion_handler) != PICL_SUCCESS) { 3360Sstevel@tonic-gate free(ev_name); 3370Sstevel@tonic-gate nvlist_free(nvl); 3380Sstevel@tonic-gate return (-1); 3390Sstevel@tonic-gate } 3400Sstevel@tonic-gate nvlist_free(nvl); 3410Sstevel@tonic-gate return (0); 3420Sstevel@tonic-gate } 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate /* 3450Sstevel@tonic-gate * Lookup a name in the name to class map tables 3460Sstevel@tonic-gate */ 3470Sstevel@tonic-gate static int 3480Sstevel@tonic-gate lookup_name_class_map(char *classbuf, const char *nm) 3490Sstevel@tonic-gate { 3500Sstevel@tonic-gate conf_entries_t *ptr; 3510Sstevel@tonic-gate int i; 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate /* 3540Sstevel@tonic-gate * check name to class mapping in conf file 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate ptr = conf_name_class_map; 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate while (ptr != NULL) { 3590Sstevel@tonic-gate if (strcmp(ptr->name, nm) == 0) { 3600Sstevel@tonic-gate (void) strlcpy(classbuf, ptr->piclclass, 3610Sstevel@tonic-gate PICL_CLASSNAMELEN_MAX); 3620Sstevel@tonic-gate return (0); 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate ptr = ptr->next; 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate /* 3680Sstevel@tonic-gate * check name to class mapping in builtin table 3690Sstevel@tonic-gate */ 3700Sstevel@tonic-gate if (builtin_map_ptr == NULL) 3710Sstevel@tonic-gate return (-1); 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate for (i = 0; i < builtin_map_size; ++i) 3740Sstevel@tonic-gate if (strcmp(builtin_map_ptr[i].name, nm) == 0) { 3750Sstevel@tonic-gate (void) strlcpy(classbuf, builtin_map_ptr[i].piclclass, 3760Sstevel@tonic-gate PICL_CLASSNAMELEN_MAX); 3770Sstevel@tonic-gate return (0); 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate return (-1); 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate /* 3830Sstevel@tonic-gate * Lookup a prop name in the pname to class map table 3840Sstevel@tonic-gate */ 3850Sstevel@tonic-gate static int 3860Sstevel@tonic-gate lookup_pname_type_map(const char *pname, picl_prop_type_t *type) 3870Sstevel@tonic-gate { 3880Sstevel@tonic-gate int i; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate for (i = 0; i < PNAME_MAP_SIZE; ++i) 3910Sstevel@tonic-gate if (strcmp(pname_type_map[i].pname, pname) == 0) { 3920Sstevel@tonic-gate *type = pname_type_map[i].type; 3930Sstevel@tonic-gate return (0); 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate return (-1); 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate /* 4000Sstevel@tonic-gate * Return the number of strings in the buffer 4010Sstevel@tonic-gate */ 4020Sstevel@tonic-gate static int 4030Sstevel@tonic-gate get_string_count(char *strdat, int length) 4040Sstevel@tonic-gate { 4050Sstevel@tonic-gate int count; 4060Sstevel@tonic-gate char *lastnull; 4070Sstevel@tonic-gate char *nullptr; 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate count = 1; 4100Sstevel@tonic-gate for (lastnull = &strdat[length - 1], nullptr = strchr(strdat, '\0'); 4110Sstevel@tonic-gate nullptr != lastnull; nullptr = strchr(nullptr+1, '\0')) 4120Sstevel@tonic-gate count++; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate return (count); 4150Sstevel@tonic-gate } 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate /* 4180Sstevel@tonic-gate * Return 1 if the node has a "reg" property 4190Sstevel@tonic-gate */ 4200Sstevel@tonic-gate static int 4210Sstevel@tonic-gate has_reg_prop(di_node_t dn) 4220Sstevel@tonic-gate { 4230Sstevel@tonic-gate int *pdata; 4240Sstevel@tonic-gate int dret; 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate dret = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, OBP_REG, &pdata); 4270Sstevel@tonic-gate if (dret > 0) 4280Sstevel@tonic-gate return (1); 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate if (!ph) 4310Sstevel@tonic-gate return (0); 4320Sstevel@tonic-gate dret = di_prom_prop_lookup_ints(ph, dn, OBP_REG, &pdata); 4330Sstevel@tonic-gate return (dret < 0 ? 0 : 1); 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate /* 4370Sstevel@tonic-gate * This function copies a PROM node's device_type property value into the 4380Sstevel@tonic-gate * buffer given by outbuf. The buffer size is PICL_CLASSNAMELEN_MAX. 4390Sstevel@tonic-gate * 4400Sstevel@tonic-gate * We reclassify device_type 'fru-prom' to PICL class 'seeprom' 4410Sstevel@tonic-gate * for FRUID support. 4420Sstevel@tonic-gate */ 4430Sstevel@tonic-gate static int 4440Sstevel@tonic-gate get_device_type(char *outbuf, di_node_t dn) 4450Sstevel@tonic-gate { 4460Sstevel@tonic-gate char *pdata; 4470Sstevel@tonic-gate char *pdatap; 4480Sstevel@tonic-gate int dret; 4490Sstevel@tonic-gate int i; 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate dret = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, OBP_DEVICETYPE, 4520Sstevel@tonic-gate &pdata); 4530Sstevel@tonic-gate if (dret <= 0) { 4540Sstevel@tonic-gate if (!ph) 4550Sstevel@tonic-gate return (-1); 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate dret = di_prom_prop_lookup_strings(ph, dn, OBP_DEVICETYPE, 4580Sstevel@tonic-gate &pdata); 4590Sstevel@tonic-gate if (dret <= 0) { 4600Sstevel@tonic-gate return (-1); 4610Sstevel@tonic-gate } 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate if (dret != 1) { 4650Sstevel@tonic-gate /* 4660Sstevel@tonic-gate * multiple strings 4670Sstevel@tonic-gate */ 4680Sstevel@tonic-gate pdatap = pdata; 4690Sstevel@tonic-gate for (i = 0; i < (dret - 1); ++i) { 4700Sstevel@tonic-gate pdatap += strlen(pdatap); 4710Sstevel@tonic-gate *pdatap = '-'; /* replace '\0' with '-' */ 4720Sstevel@tonic-gate pdatap++; 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate if (strcasecmp(pdata, "fru-prom") == 0) { 4760Sstevel@tonic-gate /* 4770Sstevel@tonic-gate * Use PICL 'seeprom' class for fru-prom device types 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate (void) strlcpy(outbuf, PICL_CLASS_SEEPROM, 4800Sstevel@tonic-gate PICL_CLASSNAMELEN_MAX); 4810Sstevel@tonic-gate } else { 4820Sstevel@tonic-gate (void) strlcpy(outbuf, pdata, PICL_CLASSNAMELEN_MAX); 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate return (0); 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate /* 4880Sstevel@tonic-gate * Get the minor node name in the class buffer passed 4890Sstevel@tonic-gate */ 4900Sstevel@tonic-gate static int 4910Sstevel@tonic-gate get_minor_class(char *classbuf, di_node_t dn) 4920Sstevel@tonic-gate { 4930Sstevel@tonic-gate di_minor_t mi_node; 4940Sstevel@tonic-gate char *mi_nodetype; 4950Sstevel@tonic-gate char *mi_name; 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate /* get minor node type */ 4980Sstevel@tonic-gate mi_node = di_minor_next(dn, DI_MINOR_NIL); 4990Sstevel@tonic-gate if (mi_node == DI_MINOR_NIL) 5000Sstevel@tonic-gate return (-1); 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate mi_nodetype = di_minor_nodetype(mi_node); 5030Sstevel@tonic-gate if (mi_nodetype == NULL) { /* no type info, return name */ 5040Sstevel@tonic-gate mi_name = di_minor_name(mi_node); 5050Sstevel@tonic-gate if (mi_name == NULL) 5060Sstevel@tonic-gate return (-1); 5070Sstevel@tonic-gate (void) strlcpy(classbuf, mi_name, PICL_CLASSNAMELEN_MAX); 5080Sstevel@tonic-gate return (0); 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate #define DDI_NODETYPE(x, y) (strncmp(x, y, (sizeof (y) - 1)) == 0) 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate /* 5140Sstevel@tonic-gate * convert the string to the picl class for non-peudo nodes 5150Sstevel@tonic-gate */ 5160Sstevel@tonic-gate if (DDI_NODETYPE(mi_nodetype, DDI_PSEUDO)) 5170Sstevel@tonic-gate return (-1); 5180Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_WWN)) 5190Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_BLOCK); 5200Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_CHAN)) 5210Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_BLOCK); 5220Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_CD)) 5230Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_CDROM); 5240Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_CD_CHAN)) 5250Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_CDROM); 5260Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_FD)) 5270Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_FLOPPY); 5280Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_FABRIC)) 5290Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_FABRIC); 5300Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK)) 5310Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_BLOCK); 5320Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_MOUSE)) 5330Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_MOUSE); 5340Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_KEYBOARD)) 5350Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_KEYBOARD); 5360Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_ATTACHMENT_POINT)) 5370Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_ATTACHMENT_POINT); 5380Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_TAPE)) 5390Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_TAPE); 5400Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_SCSI_ENCLOSURE)) 5410Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_SCSI); 5420Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_ENCLOSURE)) { 5430Sstevel@tonic-gate char *colon; 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate if ((colon = strchr(mi_nodetype, ':')) == NULL) 5460Sstevel@tonic-gate return (-1); 5470Sstevel@tonic-gate ++colon; 5480Sstevel@tonic-gate (void) strcpy(classbuf, colon); 5490Sstevel@tonic-gate } else { /* unrecognized type, return name */ 5500Sstevel@tonic-gate mi_name = di_minor_name(mi_node); 5510Sstevel@tonic-gate if (mi_name == NULL) 5520Sstevel@tonic-gate return (-1); 5530Sstevel@tonic-gate (void) strlcpy(classbuf, mi_name, PICL_CLASSNAMELEN_MAX); 5540Sstevel@tonic-gate } 5550Sstevel@tonic-gate return (0); 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate /* 5590Sstevel@tonic-gate * Derive PICL class using the compatible property of the node 5600Sstevel@tonic-gate * We use the map table to map compatible property value to 5610Sstevel@tonic-gate * class. 5620Sstevel@tonic-gate */ 5630Sstevel@tonic-gate static int 5640Sstevel@tonic-gate get_compatible_class(char *outbuf, di_node_t dn) 5650Sstevel@tonic-gate { 5660Sstevel@tonic-gate char *pdata; 5670Sstevel@tonic-gate char *pdatap; 5680Sstevel@tonic-gate int dret; 5690Sstevel@tonic-gate int i; 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate dret = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, OBP_COMPATIBLE, 5720Sstevel@tonic-gate &pdata); 5730Sstevel@tonic-gate if (dret <= 0) { 5740Sstevel@tonic-gate if (!ph) 5750Sstevel@tonic-gate return (-1); 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate dret = di_prom_prop_lookup_strings(ph, dn, OBP_COMPATIBLE, 5780Sstevel@tonic-gate &pdata); 5790Sstevel@tonic-gate if (dret <= 0) { 5800Sstevel@tonic-gate return (-1); 5810Sstevel@tonic-gate } 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate pdatap = pdata; 5850Sstevel@tonic-gate for (i = 0; i < dret; ++i) { 5860Sstevel@tonic-gate if (lookup_name_class_map(outbuf, pdatap) == 0) 5870Sstevel@tonic-gate return (0); 5880Sstevel@tonic-gate pdatap += strlen(pdatap); 5890Sstevel@tonic-gate pdatap++; 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate return (-1); 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate /* 5950Sstevel@tonic-gate * For a given device node find the PICL class to use. Returns NULL 5960Sstevel@tonic-gate * for non device node 5970Sstevel@tonic-gate */ 5980Sstevel@tonic-gate static int 5990Sstevel@tonic-gate get_node_class(char *classbuf, di_node_t dn, const char *nodename) 6000Sstevel@tonic-gate { 6010Sstevel@tonic-gate if (get_device_type(classbuf, dn) == 0) { 6020Sstevel@tonic-gate if (di_nodeid(dn) == DI_PROM_NODEID) { 6030Sstevel@tonic-gate /* 6040Sstevel@tonic-gate * discard place holder nodes 6050Sstevel@tonic-gate */ 6060Sstevel@tonic-gate if ((strcmp(classbuf, DEVICE_TYPE_BLOCK) == 0) || 6070Sstevel@tonic-gate (strcmp(classbuf, DEVICE_TYPE_BYTE) == 0) || 6080Sstevel@tonic-gate (strcmp(classbuf, DEVICE_TYPE_SES) == 0) || 6090Sstevel@tonic-gate (strcmp(classbuf, DEVICE_TYPE_FP) == 0) || 6100Sstevel@tonic-gate (strcmp(classbuf, DEVICE_TYPE_DISK) == 0)) 6110Sstevel@tonic-gate return (-1); 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate return (0); 6140Sstevel@tonic-gate } 6150Sstevel@tonic-gate return (0); /* return device_type value */ 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate if (get_compatible_class(classbuf, dn) == 0) { 6190Sstevel@tonic-gate return (0); /* derive class using compatible prop */ 6200Sstevel@tonic-gate } 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate if (lookup_name_class_map(classbuf, nodename) == 0) 6230Sstevel@tonic-gate return (0); /* derive class using name prop */ 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate if (has_reg_prop(dn)) { /* use default obp-device */ 6260Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_OBP_DEVICE); 6270Sstevel@tonic-gate return (0); 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate return (get_minor_class(classbuf, dn)); 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate /* 6340Sstevel@tonic-gate * Add a table property containing nrows with one column 6350Sstevel@tonic-gate */ 6360Sstevel@tonic-gate static int 6370Sstevel@tonic-gate add_string_list_prop(picl_nodehdl_t nodeh, char *name, char *strlist, 6380Sstevel@tonic-gate unsigned int nrows) 6390Sstevel@tonic-gate { 6400Sstevel@tonic-gate ptree_propinfo_t propinfo; 6410Sstevel@tonic-gate picl_prophdl_t proph; 6420Sstevel@tonic-gate picl_prophdl_t tblh; 6430Sstevel@tonic-gate int err; 6440Sstevel@tonic-gate unsigned int i; 6450Sstevel@tonic-gate unsigned int j; 6460Sstevel@tonic-gate picl_prophdl_t *proprow; 6470Sstevel@tonic-gate int len; 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate #define NCOLS_IN_STRING_TABLE 1 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 6520Sstevel@tonic-gate PICL_PTYPE_TABLE, PICL_READ, sizeof (picl_prophdl_t), name, 6530Sstevel@tonic-gate NULL, NULL); 6540Sstevel@tonic-gate if (err != PICL_SUCCESS) 6550Sstevel@tonic-gate return (err); 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate err = ptree_create_table(&tblh); 6580Sstevel@tonic-gate if (err != PICL_SUCCESS) 6590Sstevel@tonic-gate return (err); 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &propinfo, &tblh, &proph); 6620Sstevel@tonic-gate if (err != PICL_SUCCESS) 6630Sstevel@tonic-gate return (err); 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate proprow = alloca(sizeof (picl_prophdl_t) * nrows); 6660Sstevel@tonic-gate if (proprow == NULL) { 6670Sstevel@tonic-gate (void) ptree_destroy_prop(proph); 6680Sstevel@tonic-gate return (PICL_FAILURE); 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate for (j = 0; j < nrows; ++j) { 6720Sstevel@tonic-gate len = strlen(strlist) + 1; 6730Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 6740Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, len, name, 6750Sstevel@tonic-gate NULL, NULL); 6760Sstevel@tonic-gate if (err != PICL_SUCCESS) 6770Sstevel@tonic-gate break; 6780Sstevel@tonic-gate err = ptree_create_prop(&propinfo, strlist, &proprow[j]); 6790Sstevel@tonic-gate if (err != PICL_SUCCESS) 6800Sstevel@tonic-gate break; 6810Sstevel@tonic-gate strlist += len; 6820Sstevel@tonic-gate err = ptree_add_row_to_table(tblh, NCOLS_IN_STRING_TABLE, 6830Sstevel@tonic-gate &proprow[j]); 6840Sstevel@tonic-gate if (err != PICL_SUCCESS) 6850Sstevel@tonic-gate break; 6860Sstevel@tonic-gate } 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate if (err != PICL_SUCCESS) { 6890Sstevel@tonic-gate for (i = 0; i < j; ++i) 6900Sstevel@tonic-gate (void) ptree_destroy_prop(proprow[i]); 6910Sstevel@tonic-gate (void) ptree_delete_prop(proph); 6920Sstevel@tonic-gate (void) ptree_destroy_prop(proph); 6930Sstevel@tonic-gate return (err); 6940Sstevel@tonic-gate } 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate return (PICL_SUCCESS); 6970Sstevel@tonic-gate } 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate /* 7000Sstevel@tonic-gate * return 1 if this node has this property with the given value 7010Sstevel@tonic-gate */ 7020Sstevel@tonic-gate static int 7030Sstevel@tonic-gate compare_string_propval(picl_nodehdl_t nodeh, const char *pname, 7040Sstevel@tonic-gate const char *pval) 7050Sstevel@tonic-gate { 7060Sstevel@tonic-gate char *pvalbuf; 7070Sstevel@tonic-gate int err; 7080Sstevel@tonic-gate int len; 7090Sstevel@tonic-gate ptree_propinfo_t pinfo; 7100Sstevel@tonic-gate picl_prophdl_t proph; 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, pname, &proph); 7130Sstevel@tonic-gate if (err != PICL_SUCCESS) /* prop doesn't exist */ 7140Sstevel@tonic-gate return (0); 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 7170Sstevel@tonic-gate if (pinfo.piclinfo.type != PICL_PTYPE_CHARSTRING) 7180Sstevel@tonic-gate return (0); /* not string prop */ 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate len = strlen(pval) + 1; 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate pvalbuf = alloca(len); 7230Sstevel@tonic-gate if (pvalbuf == NULL) 7240Sstevel@tonic-gate return (0); 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate err = ptree_get_propval(proph, pvalbuf, len); 7270Sstevel@tonic-gate if ((err == PICL_SUCCESS) && (strcmp(pvalbuf, pval) == 0)) 7280Sstevel@tonic-gate return (1); /* prop match */ 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate return (0); 7310Sstevel@tonic-gate } 7320Sstevel@tonic-gate 7330Sstevel@tonic-gate /* 7340Sstevel@tonic-gate * This function recursively searches the tree for a node that has 7350Sstevel@tonic-gate * the specified string property name and value 7360Sstevel@tonic-gate */ 7370Sstevel@tonic-gate static int 7380Sstevel@tonic-gate find_node_by_string_prop(picl_nodehdl_t rooth, const char *pname, 7390Sstevel@tonic-gate const char *pval, picl_nodehdl_t *nodeh) 7400Sstevel@tonic-gate { 7410Sstevel@tonic-gate picl_nodehdl_t childh; 7420Sstevel@tonic-gate int err; 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh, 7450Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 7465028Sfw157321 err = ptree_get_propval_by_name(childh, PICL_PROP_PEER, &childh, 7475028Sfw157321 sizeof (picl_nodehdl_t))) { 7480Sstevel@tonic-gate if (err != PICL_SUCCESS) 7490Sstevel@tonic-gate return (err); 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate if (compare_string_propval(childh, pname, pval)) { 7520Sstevel@tonic-gate *nodeh = childh; 7530Sstevel@tonic-gate return (PICL_SUCCESS); 7540Sstevel@tonic-gate } 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate if (find_node_by_string_prop(childh, pname, pval, nodeh) == 7570Sstevel@tonic-gate PICL_SUCCESS) 7580Sstevel@tonic-gate return (PICL_SUCCESS); 7590Sstevel@tonic-gate } 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate return (PICL_FAILURE); 7620Sstevel@tonic-gate } 7630Sstevel@tonic-gate 7640Sstevel@tonic-gate /* 7650Sstevel@tonic-gate * check if this is a string prop 7660Sstevel@tonic-gate * If the length is less than or equal to 4, assume it's not a string list. 7670Sstevel@tonic-gate * If there is any non-ascii or non-print char, it's not a string prop 7680Sstevel@tonic-gate * If \0 is in the first char or any two consecutive \0's exist, 7690Sstevel@tonic-gate * it's a bytearray prop. 7700Sstevel@tonic-gate * Return value: 0 means it's not a string prop, 1 means it's a string prop 7710Sstevel@tonic-gate */ 7720Sstevel@tonic-gate static int 7730Sstevel@tonic-gate is_string_propval(unsigned char *pdata, int len) 7740Sstevel@tonic-gate { 7750Sstevel@tonic-gate int i; 7760Sstevel@tonic-gate int lastindex; 7770Sstevel@tonic-gate int prevnull = -1; 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate switch (len) { 7800Sstevel@tonic-gate case 1: 7810Sstevel@tonic-gate if (!isascii(pdata[0]) || !isprint(pdata[0])) 7820Sstevel@tonic-gate return (0); 7830Sstevel@tonic-gate return (1); 7840Sstevel@tonic-gate case 2: 7850Sstevel@tonic-gate case 3: 7860Sstevel@tonic-gate case 4: 7870Sstevel@tonic-gate lastindex = len; 7880Sstevel@tonic-gate if (pdata[len-1] == '\0') 7890Sstevel@tonic-gate lastindex = len - 1; 7900Sstevel@tonic-gate 7910Sstevel@tonic-gate for (i = 0; i < lastindex; i++) 7920Sstevel@tonic-gate if (!isascii(pdata[i]) || !isprint(pdata[i])) 7930Sstevel@tonic-gate return (0); 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate return (1); 7960Sstevel@tonic-gate 7970Sstevel@tonic-gate default: 7980Sstevel@tonic-gate if (len <= 0) 7990Sstevel@tonic-gate return (0); 8000Sstevel@tonic-gate for (i = 0; i < len; i++) { 8010Sstevel@tonic-gate if (!isascii(pdata[i]) || !isprint(pdata[i])) { 8020Sstevel@tonic-gate if (pdata[i] != '\0') 8030Sstevel@tonic-gate return (0); 8040Sstevel@tonic-gate /* 8050Sstevel@tonic-gate * if the null char is in the first char 8060Sstevel@tonic-gate * or two consecutive nulls' exist, 8070Sstevel@tonic-gate * it's a bytearray prop 8080Sstevel@tonic-gate */ 8090Sstevel@tonic-gate if ((i == 0) || ((i - prevnull) == 1)) 8100Sstevel@tonic-gate return (0); 8110Sstevel@tonic-gate 8120Sstevel@tonic-gate prevnull = i; 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate } 8150Sstevel@tonic-gate break; 8160Sstevel@tonic-gate } 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate return (1); 8190Sstevel@tonic-gate } 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate /* 8220Sstevel@tonic-gate * This function counts the number of strings in the value buffer pdata 8230Sstevel@tonic-gate * and creates a property. 8240Sstevel@tonic-gate * If there is only one string in the buffer, pdata, a charstring property 8250Sstevel@tonic-gate * type is created and added. 8260Sstevel@tonic-gate * If there are more than one string in the buffer, pdata, then a table 8270Sstevel@tonic-gate * of charstrings is added. 8280Sstevel@tonic-gate */ 8290Sstevel@tonic-gate static int 8300Sstevel@tonic-gate process_charstring_data(picl_nodehdl_t nodeh, char *pname, unsigned char *pdata, 8310Sstevel@tonic-gate int retval) 8320Sstevel@tonic-gate { 8330Sstevel@tonic-gate int err; 8340Sstevel@tonic-gate int strcount; 8350Sstevel@tonic-gate char *strdat; 8360Sstevel@tonic-gate ptree_propinfo_t propinfo; 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate /* 8390Sstevel@tonic-gate * append the null char at the end of string when there is 8400Sstevel@tonic-gate * no null terminator 8410Sstevel@tonic-gate */ 8420Sstevel@tonic-gate if (pdata[retval - 1] != '\0') { 8430Sstevel@tonic-gate strdat = alloca(retval + 1); 8440Sstevel@tonic-gate (void) memcpy(strdat, pdata, retval); 8450Sstevel@tonic-gate strdat[retval] = '\0'; 8460Sstevel@tonic-gate retval++; 8470Sstevel@tonic-gate } else { 8480Sstevel@tonic-gate strdat = alloca(retval); 8490Sstevel@tonic-gate (void) memcpy(strdat, pdata, retval); 8500Sstevel@tonic-gate } 8510Sstevel@tonic-gate 8520Sstevel@tonic-gate /* 8530Sstevel@tonic-gate * If it's a string list, create a table prop 8540Sstevel@tonic-gate */ 8550Sstevel@tonic-gate strcount = get_string_count(strdat, retval); 8560Sstevel@tonic-gate if (strcount > 1) { 8570Sstevel@tonic-gate err = add_string_list_prop(nodeh, pname, 8580Sstevel@tonic-gate strdat, strcount); 8590Sstevel@tonic-gate if (err != PICL_SUCCESS) 8600Sstevel@tonic-gate return (err); 8610Sstevel@tonic-gate } else { 8620Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 8630Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 8640Sstevel@tonic-gate strlen(strdat) + 1, pname, NULL, 8650Sstevel@tonic-gate NULL); 8660Sstevel@tonic-gate if (err != PICL_SUCCESS) 8670Sstevel@tonic-gate return (err); 8680Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, 8690Sstevel@tonic-gate strdat, NULL); 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate return (PICL_SUCCESS); 8720Sstevel@tonic-gate } 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate /* 8750Sstevel@tonic-gate * Add the OBP properties as properties of the PICL node 8760Sstevel@tonic-gate */ 8770Sstevel@tonic-gate static int 8780Sstevel@tonic-gate add_openprom_props(picl_nodehdl_t nodeh, di_node_t di_node) 8790Sstevel@tonic-gate { 8800Sstevel@tonic-gate di_prom_prop_t promp; 8810Sstevel@tonic-gate char *pname; 8820Sstevel@tonic-gate unsigned char *pdata; 8830Sstevel@tonic-gate int retval; 8840Sstevel@tonic-gate ptree_propinfo_t propinfo; 8850Sstevel@tonic-gate int err; 8860Sstevel@tonic-gate picl_prop_type_t type; 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate if (!ph) 8890Sstevel@tonic-gate return (PICL_FAILURE); 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate for (promp = di_prom_prop_next(ph, di_node, DI_PROM_PROP_NIL); 8920Sstevel@tonic-gate promp != DI_PROM_PROP_NIL; 8935028Sfw157321 promp = di_prom_prop_next(ph, di_node, promp)) { 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate pname = di_prom_prop_name(promp); 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate retval = di_prom_prop_data(promp, &pdata); 8980Sstevel@tonic-gate if (retval < 0) { 8990Sstevel@tonic-gate return (PICL_SUCCESS); 9000Sstevel@tonic-gate } 9010Sstevel@tonic-gate if (retval == 0) { 9020Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, 9030Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID, 9040Sstevel@tonic-gate PICL_READ, (size_t)0, pname, NULL, NULL); 9050Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9060Sstevel@tonic-gate return (err); 9070Sstevel@tonic-gate } 9080Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, 9090Sstevel@tonic-gate NULL); 9100Sstevel@tonic-gate continue; 9110Sstevel@tonic-gate } 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate /* 9140Sstevel@tonic-gate * Get the prop type from pname map table 9150Sstevel@tonic-gate */ 9160Sstevel@tonic-gate if (lookup_pname_type_map(pname, &type) == 0) { 9170Sstevel@tonic-gate if (type == PICL_PTYPE_CHARSTRING) { 9180Sstevel@tonic-gate err = process_charstring_data(nodeh, pname, 9190Sstevel@tonic-gate pdata, retval); 9200Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9210Sstevel@tonic-gate return (err); 9220Sstevel@tonic-gate } 9230Sstevel@tonic-gate continue; 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, 9270Sstevel@tonic-gate PTREE_PROPINFO_VERSION, type, PICL_READ, 9280Sstevel@tonic-gate retval, pname, NULL, NULL); 9290Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9300Sstevel@tonic-gate return (err); 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, 9330Sstevel@tonic-gate pdata, NULL); 9340Sstevel@tonic-gate } else if (!is_string_propval(pdata, retval)) { 9350Sstevel@tonic-gate switch (retval) { 9360Sstevel@tonic-gate case sizeof (uint8_t): 9370Sstevel@tonic-gate /*FALLTHROUGH*/ 9380Sstevel@tonic-gate case sizeof (uint16_t): 9390Sstevel@tonic-gate /*FALLTHROUGH*/ 9400Sstevel@tonic-gate case sizeof (uint32_t): 9410Sstevel@tonic-gate type = PICL_PTYPE_UNSIGNED_INT; 9420Sstevel@tonic-gate break; 9430Sstevel@tonic-gate default: 9440Sstevel@tonic-gate type = PICL_PTYPE_BYTEARRAY; 9450Sstevel@tonic-gate break; 9460Sstevel@tonic-gate } 9470Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, 9480Sstevel@tonic-gate PTREE_PROPINFO_VERSION, type, PICL_READ, 9490Sstevel@tonic-gate retval, pname, NULL, NULL); 9500Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9510Sstevel@tonic-gate return (err); 9520Sstevel@tonic-gate } 9530Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, 9540Sstevel@tonic-gate pdata, NULL); 9550Sstevel@tonic-gate } else { 9560Sstevel@tonic-gate err = process_charstring_data(nodeh, pname, pdata, 9570Sstevel@tonic-gate retval); 9580Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9590Sstevel@tonic-gate return (err); 9600Sstevel@tonic-gate } 9610Sstevel@tonic-gate } 9620Sstevel@tonic-gate } 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate return (PICL_SUCCESS); 9650Sstevel@tonic-gate } 9660Sstevel@tonic-gate 9673343Srd117015 static void 9683343Srd117015 add_boolean_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val) 9693343Srd117015 { 9703343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 9713343Srd117015 PICL_PTYPE_VOID, PICL_READ, (size_t)0, di_val, NULL, NULL); 9723343Srd117015 (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL); 9733343Srd117015 } 9743343Srd117015 9753343Srd117015 static void 9763343Srd117015 add_uints_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val, 9773343Srd117015 int *idata, int len) 9783343Srd117015 { 9793343Srd117015 if (len == 1) 9803343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 9813343Srd117015 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (int), di_val, 9823343Srd117015 NULL, NULL); 9833343Srd117015 else 9843343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 9853343Srd117015 PICL_PTYPE_BYTEARRAY, PICL_READ, len * sizeof (int), di_val, 9863343Srd117015 NULL, NULL); 9873343Srd117015 9883343Srd117015 (void) ptree_create_and_add_prop(nodeh, &propinfo, idata, NULL); 9893343Srd117015 } 9903343Srd117015 9913343Srd117015 static void 9923343Srd117015 add_strings_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val, 9933343Srd117015 char *sdata, int len) 9943343Srd117015 { 9953343Srd117015 if (len == 1) { 9963343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 9973343Srd117015 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(sdata) + 1, di_val, 9983343Srd117015 NULL, NULL); 9993343Srd117015 (void) ptree_create_and_add_prop(nodeh, &propinfo, sdata, NULL); 10003343Srd117015 } else { 10013343Srd117015 (void) add_string_list_prop(nodeh, di_val, sdata, len); 10023343Srd117015 } 10033343Srd117015 } 10043343Srd117015 10053343Srd117015 static void 10063343Srd117015 add_bytes_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val, 10073343Srd117015 unsigned char *bdata, int len) 10083343Srd117015 { 10093343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10103343Srd117015 PICL_PTYPE_BYTEARRAY, PICL_READ, len, di_val, NULL, NULL); 10113343Srd117015 (void) ptree_create_and_add_prop(nodeh, &propinfo, bdata, NULL); 10123343Srd117015 } 10133343Srd117015 10147834SMichael.Bergknoff@Sun.COM static const char * 10157834SMichael.Bergknoff@Sun.COM path_state_name(di_path_state_t st) 10167834SMichael.Bergknoff@Sun.COM { 10177834SMichael.Bergknoff@Sun.COM switch (st) { 10187834SMichael.Bergknoff@Sun.COM case DI_PATH_STATE_ONLINE: 10197834SMichael.Bergknoff@Sun.COM return ("online"); 10207834SMichael.Bergknoff@Sun.COM case DI_PATH_STATE_STANDBY: 10217834SMichael.Bergknoff@Sun.COM return ("standby"); 10227834SMichael.Bergknoff@Sun.COM case DI_PATH_STATE_OFFLINE: 10237834SMichael.Bergknoff@Sun.COM return ("offline"); 10247834SMichael.Bergknoff@Sun.COM case DI_PATH_STATE_FAULT: 10257834SMichael.Bergknoff@Sun.COM return ("faulted"); 10267834SMichael.Bergknoff@Sun.COM } 10277834SMichael.Bergknoff@Sun.COM return ("unknown"); 10287834SMichael.Bergknoff@Sun.COM } 10297834SMichael.Bergknoff@Sun.COM 10307834SMichael.Bergknoff@Sun.COM /* 10317834SMichael.Bergknoff@Sun.COM * This function is the volatile property handler for the multipath node 10327834SMichael.Bergknoff@Sun.COM * "State" property. It must locate the associated devinfo node in order to 10337834SMichael.Bergknoff@Sun.COM * determine the current state. Since the devinfo node can have multiple 10347834SMichael.Bergknoff@Sun.COM * paths the devfs_path is used to locate the correct path. 10357834SMichael.Bergknoff@Sun.COM */ 10367834SMichael.Bergknoff@Sun.COM static int 10377834SMichael.Bergknoff@Sun.COM get_path_state_name(ptree_rarg_t *rarg, void *vbuf) 10387834SMichael.Bergknoff@Sun.COM { 10397834SMichael.Bergknoff@Sun.COM int err; 10407834SMichael.Bergknoff@Sun.COM picl_nodehdl_t parh; 10417834SMichael.Bergknoff@Sun.COM char devfs_path[PATH_MAX]; 10427834SMichael.Bergknoff@Sun.COM di_node_t di_node; 10437834SMichael.Bergknoff@Sun.COM di_node_t di_root; 10447834SMichael.Bergknoff@Sun.COM di_path_t pi = DI_PATH_NIL; 10457834SMichael.Bergknoff@Sun.COM picl_nodehdl_t mpnode; 10467834SMichael.Bergknoff@Sun.COM 10477834SMichael.Bergknoff@Sun.COM (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE); 10487834SMichael.Bergknoff@Sun.COM 10497834SMichael.Bergknoff@Sun.COM mpnode = rarg->nodeh; 10507834SMichael.Bergknoff@Sun.COM 10517834SMichael.Bergknoff@Sun.COM /* 10527834SMichael.Bergknoff@Sun.COM * The parent node represents the vHCI. 10537834SMichael.Bergknoff@Sun.COM */ 10547834SMichael.Bergknoff@Sun.COM err = ptree_get_propval_by_name(mpnode, PICL_PROP_PARENT, &parh, 10557834SMichael.Bergknoff@Sun.COM sizeof (picl_nodehdl_t)); 10567834SMichael.Bergknoff@Sun.COM if (err != PICL_SUCCESS) { 10577834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 10587834SMichael.Bergknoff@Sun.COM } 10597834SMichael.Bergknoff@Sun.COM 10607834SMichael.Bergknoff@Sun.COM /* 10617834SMichael.Bergknoff@Sun.COM * The PICL_PROP_DEVFS_PATH property will be used to locate the 10627834SMichael.Bergknoff@Sun.COM * devinfo node for the vHCI driver. 10637834SMichael.Bergknoff@Sun.COM */ 10647834SMichael.Bergknoff@Sun.COM err = ptree_get_propval_by_name(parh, PICL_PROP_DEVFS_PATH, devfs_path, 10657834SMichael.Bergknoff@Sun.COM sizeof (devfs_path)); 10667834SMichael.Bergknoff@Sun.COM if (err != PICL_SUCCESS) { 10677834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 10687834SMichael.Bergknoff@Sun.COM } 10697834SMichael.Bergknoff@Sun.COM /* 10707834SMichael.Bergknoff@Sun.COM * Find the di_node for the vHCI driver. It will be used to scan 10717834SMichael.Bergknoff@Sun.COM * the path information nodes. 10727834SMichael.Bergknoff@Sun.COM */ 10737834SMichael.Bergknoff@Sun.COM di_root = di_init("/", DINFOCACHE); 10747834SMichael.Bergknoff@Sun.COM if (di_root == DI_NODE_NIL) { 10757834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 10767834SMichael.Bergknoff@Sun.COM } 10777834SMichael.Bergknoff@Sun.COM di_node = di_lookup_node(di_root, devfs_path); 10787834SMichael.Bergknoff@Sun.COM if (di_node == DI_NODE_NIL) { 10797834SMichael.Bergknoff@Sun.COM di_fini(di_root); 10807834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 10817834SMichael.Bergknoff@Sun.COM } 10827834SMichael.Bergknoff@Sun.COM 10837834SMichael.Bergknoff@Sun.COM /* 10847834SMichael.Bergknoff@Sun.COM * The devfs_path will be used below to match the 10857834SMichael.Bergknoff@Sun.COM * proper path information node. 10867834SMichael.Bergknoff@Sun.COM */ 10877834SMichael.Bergknoff@Sun.COM err = ptree_get_propval_by_name(mpnode, PICL_PROP_DEVFS_PATH, 10887834SMichael.Bergknoff@Sun.COM devfs_path, sizeof (devfs_path)); 10897834SMichael.Bergknoff@Sun.COM if (err != PICL_SUCCESS) { 10907834SMichael.Bergknoff@Sun.COM di_fini(di_root); 10917834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 10927834SMichael.Bergknoff@Sun.COM } 10937834SMichael.Bergknoff@Sun.COM 10947834SMichael.Bergknoff@Sun.COM /* 10957834SMichael.Bergknoff@Sun.COM * Scan the path information nodes looking for the matching devfs 10967834SMichael.Bergknoff@Sun.COM * path. When found obtain the state information. 10977834SMichael.Bergknoff@Sun.COM */ 10987834SMichael.Bergknoff@Sun.COM while ((pi = di_path_next_phci(di_node, pi)) != DI_PATH_NIL) { 10997834SMichael.Bergknoff@Sun.COM char *di_path; 11007834SMichael.Bergknoff@Sun.COM di_node_t phci_node = di_path_phci_node(pi); 11017834SMichael.Bergknoff@Sun.COM 11027834SMichael.Bergknoff@Sun.COM if (phci_node == DI_PATH_NIL) 11037834SMichael.Bergknoff@Sun.COM continue; 11047834SMichael.Bergknoff@Sun.COM 11057834SMichael.Bergknoff@Sun.COM di_path = di_devfs_path(phci_node); 11067834SMichael.Bergknoff@Sun.COM if (di_path) { 11077834SMichael.Bergknoff@Sun.COM if (strcmp(di_path, devfs_path) != 0) { 11087834SMichael.Bergknoff@Sun.COM di_devfs_path_free(di_path); 11097834SMichael.Bergknoff@Sun.COM continue; 11107834SMichael.Bergknoff@Sun.COM } 11117834SMichael.Bergknoff@Sun.COM (void) strlcpy(vbuf, path_state_name(di_path_state(pi)), 11127834SMichael.Bergknoff@Sun.COM MAX_STATE_SIZE); 11137834SMichael.Bergknoff@Sun.COM di_devfs_path_free(di_path); 11147834SMichael.Bergknoff@Sun.COM break; 11157834SMichael.Bergknoff@Sun.COM } 11167834SMichael.Bergknoff@Sun.COM } 11177834SMichael.Bergknoff@Sun.COM 11187834SMichael.Bergknoff@Sun.COM di_fini(di_root); 11197834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 11207834SMichael.Bergknoff@Sun.COM } 11217834SMichael.Bergknoff@Sun.COM 11227834SMichael.Bergknoff@Sun.COM static void 11237834SMichael.Bergknoff@Sun.COM add_di_path_prop(picl_nodehdl_t nodeh, di_path_prop_t di_path_prop) 11247834SMichael.Bergknoff@Sun.COM { 11257834SMichael.Bergknoff@Sun.COM int di_ptype; 11267834SMichael.Bergknoff@Sun.COM char *di_val; 11277834SMichael.Bergknoff@Sun.COM ptree_propinfo_t propinfo; 11287834SMichael.Bergknoff@Sun.COM int *idata; 11297834SMichael.Bergknoff@Sun.COM char *sdata; 11307834SMichael.Bergknoff@Sun.COM unsigned char *bdata; 11317834SMichael.Bergknoff@Sun.COM int len; 11327834SMichael.Bergknoff@Sun.COM 11337834SMichael.Bergknoff@Sun.COM di_ptype = di_path_prop_type(di_path_prop); 11347834SMichael.Bergknoff@Sun.COM di_val = di_path_prop_name(di_path_prop); 11357834SMichael.Bergknoff@Sun.COM 11367834SMichael.Bergknoff@Sun.COM switch (di_ptype) { 11377834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_BOOLEAN: 11387834SMichael.Bergknoff@Sun.COM add_boolean_prop(nodeh, propinfo, di_val); 11397834SMichael.Bergknoff@Sun.COM break; 11407834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_INT: 11417834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_INT64: 11427834SMichael.Bergknoff@Sun.COM len = di_path_prop_ints(di_path_prop, &idata); 11437834SMichael.Bergknoff@Sun.COM if (len < 0) 11447834SMichael.Bergknoff@Sun.COM /* Received error, so ignore prop */ 11457834SMichael.Bergknoff@Sun.COM break; 11467834SMichael.Bergknoff@Sun.COM add_uints_prop(nodeh, propinfo, di_val, idata, len); 11477834SMichael.Bergknoff@Sun.COM break; 11487834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_STRING: 11497834SMichael.Bergknoff@Sun.COM len = di_path_prop_strings(di_path_prop, &sdata); 11507834SMichael.Bergknoff@Sun.COM if (len <= 0) 11517834SMichael.Bergknoff@Sun.COM break; 11527834SMichael.Bergknoff@Sun.COM add_strings_prop(nodeh, propinfo, di_val, sdata, len); 11537834SMichael.Bergknoff@Sun.COM break; 11547834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_BYTE: 11557834SMichael.Bergknoff@Sun.COM len = di_path_prop_bytes(di_path_prop, &bdata); 11567834SMichael.Bergknoff@Sun.COM if (len < 0) 11577834SMichael.Bergknoff@Sun.COM break; 11587834SMichael.Bergknoff@Sun.COM add_bytes_prop(nodeh, propinfo, di_val, bdata, len); 11597834SMichael.Bergknoff@Sun.COM break; 11607834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_UNKNOWN: 11617834SMichael.Bergknoff@Sun.COM /* 11627834SMichael.Bergknoff@Sun.COM * Unknown type, we'll try and guess what it should be. 11637834SMichael.Bergknoff@Sun.COM */ 11647834SMichael.Bergknoff@Sun.COM len = di_path_prop_strings(di_path_prop, &sdata); 11657834SMichael.Bergknoff@Sun.COM if ((len > 0) && (sdata[0] != 0)) { 11667834SMichael.Bergknoff@Sun.COM add_strings_prop(nodeh, propinfo, di_val, sdata, 11677834SMichael.Bergknoff@Sun.COM len); 11687834SMichael.Bergknoff@Sun.COM break; 11697834SMichael.Bergknoff@Sun.COM } 11707834SMichael.Bergknoff@Sun.COM len = di_path_prop_ints(di_path_prop, &idata); 11717834SMichael.Bergknoff@Sun.COM if (len > 0) { 11727834SMichael.Bergknoff@Sun.COM add_uints_prop(nodeh, propinfo, di_val, 11737834SMichael.Bergknoff@Sun.COM idata, len); 11747834SMichael.Bergknoff@Sun.COM break; 11757834SMichael.Bergknoff@Sun.COM } 11767834SMichael.Bergknoff@Sun.COM len = di_path_prop_bytes(di_path_prop, &bdata); 11777834SMichael.Bergknoff@Sun.COM if (len > 0) 11787834SMichael.Bergknoff@Sun.COM add_bytes_prop(nodeh, propinfo, 11797834SMichael.Bergknoff@Sun.COM di_val, bdata, len); 11807834SMichael.Bergknoff@Sun.COM else if (len == 0) 11817834SMichael.Bergknoff@Sun.COM add_boolean_prop(nodeh, propinfo, 11827834SMichael.Bergknoff@Sun.COM di_val); 11837834SMichael.Bergknoff@Sun.COM break; 11847834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_UNDEF_IT: 11857834SMichael.Bergknoff@Sun.COM break; 11867834SMichael.Bergknoff@Sun.COM default: 11877834SMichael.Bergknoff@Sun.COM break; 11887834SMichael.Bergknoff@Sun.COM } 11897834SMichael.Bergknoff@Sun.COM } 11907834SMichael.Bergknoff@Sun.COM 11917834SMichael.Bergknoff@Sun.COM /* 11927834SMichael.Bergknoff@Sun.COM * Add nodes for path information (PSARC/1999/647, PSARC/2008/437) 11937834SMichael.Bergknoff@Sun.COM */ 11947834SMichael.Bergknoff@Sun.COM static void 11957834SMichael.Bergknoff@Sun.COM construct_mpath_node(picl_nodehdl_t parh, di_node_t di_node) 11967834SMichael.Bergknoff@Sun.COM { 11977834SMichael.Bergknoff@Sun.COM di_path_t pi = DI_PATH_NIL; 11987834SMichael.Bergknoff@Sun.COM 11997834SMichael.Bergknoff@Sun.COM while ((pi = di_path_next_phci(di_node, pi)) != DI_PATH_NIL) { 12007834SMichael.Bergknoff@Sun.COM di_node_t phci_node = di_path_phci_node(pi); 12017834SMichael.Bergknoff@Sun.COM di_path_prop_t di_path_prop; 12027834SMichael.Bergknoff@Sun.COM picl_nodehdl_t nodeh; 12037834SMichael.Bergknoff@Sun.COM ptree_propinfo_t propinfo; 12047834SMichael.Bergknoff@Sun.COM int err; 12057834SMichael.Bergknoff@Sun.COM int instance; 12067834SMichael.Bergknoff@Sun.COM char *di_val; 12077834SMichael.Bergknoff@Sun.COM 12087834SMichael.Bergknoff@Sun.COM if (phci_node == DI_PATH_NIL) 12097834SMichael.Bergknoff@Sun.COM continue; 12107834SMichael.Bergknoff@Sun.COM 12117834SMichael.Bergknoff@Sun.COM err = ptree_create_and_add_node(parh, PICL_CLASS_MULTIPATH, 12127834SMichael.Bergknoff@Sun.COM PICL_CLASS_MULTIPATH, &nodeh); 12137834SMichael.Bergknoff@Sun.COM if (err != PICL_SUCCESS) 12147834SMichael.Bergknoff@Sun.COM continue; 12157834SMichael.Bergknoff@Sun.COM 12167834SMichael.Bergknoff@Sun.COM instance = di_instance(phci_node); 12177834SMichael.Bergknoff@Sun.COM (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 12187834SMichael.Bergknoff@Sun.COM PICL_PTYPE_INT, PICL_READ, sizeof (instance), 12197834SMichael.Bergknoff@Sun.COM PICL_PROP_INSTANCE, NULL, NULL); 12207834SMichael.Bergknoff@Sun.COM (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, 12217834SMichael.Bergknoff@Sun.COM NULL); 12227834SMichael.Bergknoff@Sun.COM 12237834SMichael.Bergknoff@Sun.COM di_val = di_devfs_path(phci_node); 12247834SMichael.Bergknoff@Sun.COM if (di_val) { 12257834SMichael.Bergknoff@Sun.COM (void) ptree_init_propinfo(&propinfo, 12267834SMichael.Bergknoff@Sun.COM PTREE_PROPINFO_VERSION, 12277834SMichael.Bergknoff@Sun.COM PICL_PTYPE_CHARSTRING, PICL_READ, 12287834SMichael.Bergknoff@Sun.COM strlen(di_val) + 1, PICL_PROP_DEVFS_PATH, 12297834SMichael.Bergknoff@Sun.COM NULL, NULL); 12307834SMichael.Bergknoff@Sun.COM (void) ptree_create_and_add_prop(nodeh, 12317834SMichael.Bergknoff@Sun.COM &propinfo, di_val, NULL); 12327834SMichael.Bergknoff@Sun.COM di_devfs_path_free(di_val); 12337834SMichael.Bergknoff@Sun.COM } 12347834SMichael.Bergknoff@Sun.COM 12357834SMichael.Bergknoff@Sun.COM (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 12367834SMichael.Bergknoff@Sun.COM PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), 12377834SMichael.Bergknoff@Sun.COM MAX_STATE_SIZE, PICL_PROP_STATE, get_path_state_name, NULL); 12387834SMichael.Bergknoff@Sun.COM (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL); 12397834SMichael.Bergknoff@Sun.COM 12407834SMichael.Bergknoff@Sun.COM for (di_path_prop = di_path_prop_next(pi, DI_PROP_NIL); 12417834SMichael.Bergknoff@Sun.COM di_path_prop != DI_PROP_NIL; 12427834SMichael.Bergknoff@Sun.COM di_path_prop = di_path_prop_next(pi, di_path_prop)) { 12437834SMichael.Bergknoff@Sun.COM add_di_path_prop(nodeh, di_path_prop); 12447834SMichael.Bergknoff@Sun.COM } 12457834SMichael.Bergknoff@Sun.COM } 12467834SMichael.Bergknoff@Sun.COM } 12477834SMichael.Bergknoff@Sun.COM 12480Sstevel@tonic-gate /* 12490Sstevel@tonic-gate * Add properties provided by libdevinfo 12500Sstevel@tonic-gate */ 12510Sstevel@tonic-gate static void 12520Sstevel@tonic-gate add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node) 12530Sstevel@tonic-gate { 12540Sstevel@tonic-gate int instance; 12550Sstevel@tonic-gate char *di_val; 12560Sstevel@tonic-gate di_prop_t di_prop; 12570Sstevel@tonic-gate int di_ptype; 12580Sstevel@tonic-gate ptree_propinfo_t propinfo; 12593343Srd117015 char *sdata; 12603343Srd117015 unsigned char *bdata; 12613343Srd117015 int *idata; 12623343Srd117015 int len; 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate instance = di_instance(di_node); 12650Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 12660Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE, 12670Sstevel@tonic-gate NULL, NULL); 12680Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL); 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate di_val = di_bus_addr(di_node); 12710Sstevel@tonic-gate if (di_val) { 12720Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 12730Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 12740Sstevel@tonic-gate PICL_PROP_BUS_ADDR, NULL, NULL); 12750Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 12760Sstevel@tonic-gate NULL); 12770Sstevel@tonic-gate } 12780Sstevel@tonic-gate 12790Sstevel@tonic-gate di_val = di_binding_name(di_node); 12800Sstevel@tonic-gate if (di_val) { 12810Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 12820Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 12830Sstevel@tonic-gate PICL_PROP_BINDING_NAME, NULL, NULL); 12840Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 12850Sstevel@tonic-gate NULL); 12860Sstevel@tonic-gate } 12870Sstevel@tonic-gate 12880Sstevel@tonic-gate di_val = di_driver_name(di_node); 12890Sstevel@tonic-gate if (di_val) { 12900Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 12910Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 12920Sstevel@tonic-gate PICL_PROP_DRIVER_NAME, NULL, NULL); 12930Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 12940Sstevel@tonic-gate NULL); 12950Sstevel@tonic-gate } 12960Sstevel@tonic-gate 12970Sstevel@tonic-gate di_val = di_devfs_path(di_node); 12980Sstevel@tonic-gate if (di_val) { 12990Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 13000Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 13010Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, NULL, NULL); 13020Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 13030Sstevel@tonic-gate NULL); 13040Sstevel@tonic-gate di_devfs_path_free(di_val); 13050Sstevel@tonic-gate } 13060Sstevel@tonic-gate 13070Sstevel@tonic-gate for (di_prop = di_prop_next(di_node, DI_PROP_NIL); 13080Sstevel@tonic-gate di_prop != DI_PROP_NIL; 13095028Sfw157321 di_prop = di_prop_next(di_node, di_prop)) { 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate di_val = di_prop_name(di_prop); 13120Sstevel@tonic-gate di_ptype = di_prop_type(di_prop); 13133343Srd117015 13140Sstevel@tonic-gate switch (di_ptype) { 13150Sstevel@tonic-gate case DI_PROP_TYPE_BOOLEAN: 13163343Srd117015 add_boolean_prop(nodeh, propinfo, di_val); 13170Sstevel@tonic-gate break; 13183343Srd117015 case DI_PROP_TYPE_INT: 13190Sstevel@tonic-gate len = di_prop_ints(di_prop, &idata); 13200Sstevel@tonic-gate if (len < 0) 13213343Srd117015 /* Received error, so ignore prop */ 13220Sstevel@tonic-gate break; 13233343Srd117015 add_uints_prop(nodeh, propinfo, di_val, idata, len); 13243343Srd117015 break; 13253343Srd117015 case DI_PROP_TYPE_STRING: 13260Sstevel@tonic-gate len = di_prop_strings(di_prop, &sdata); 13270Sstevel@tonic-gate if (len < 0) 13280Sstevel@tonic-gate break; 13293343Srd117015 add_strings_prop(nodeh, propinfo, di_val, sdata, len); 13303343Srd117015 break; 13313343Srd117015 case DI_PROP_TYPE_BYTE: 13320Sstevel@tonic-gate len = di_prop_bytes(di_prop, &bdata); 13330Sstevel@tonic-gate if (len < 0) 13340Sstevel@tonic-gate break; 13353343Srd117015 add_bytes_prop(nodeh, propinfo, di_val, bdata, len); 13363343Srd117015 break; 13370Sstevel@tonic-gate case DI_PROP_TYPE_UNKNOWN: 13383343Srd117015 /* 13393343Srd117015 * Unknown type, we'll try and guess what it should be. 13403343Srd117015 */ 13413343Srd117015 len = di_prop_strings(di_prop, &sdata); 13423343Srd117015 if ((len > 0) && (sdata[0] != 0)) { 13433343Srd117015 add_strings_prop(nodeh, propinfo, di_val, sdata, 13443343Srd117015 len); 13453343Srd117015 break; 13463343Srd117015 } 13473343Srd117015 len = di_prop_ints(di_prop, &idata); 13483343Srd117015 if (len > 0) { 13493343Srd117015 add_uints_prop(nodeh, propinfo, di_val, 13503343Srd117015 idata, len); 13513343Srd117015 break; 13523343Srd117015 } 13533343Srd117015 len = di_prop_rawdata(di_prop, &bdata); 13543343Srd117015 if (len > 0) 13553343Srd117015 add_bytes_prop(nodeh, propinfo, 13563343Srd117015 di_val, bdata, len); 13573343Srd117015 else if (len == 0) 13583343Srd117015 add_boolean_prop(nodeh, propinfo, 13593343Srd117015 di_val); 13600Sstevel@tonic-gate break; 13610Sstevel@tonic-gate case DI_PROP_TYPE_UNDEF_IT: 13620Sstevel@tonic-gate break; 13630Sstevel@tonic-gate default: 13640Sstevel@tonic-gate break; 13650Sstevel@tonic-gate } 13660Sstevel@tonic-gate } 13670Sstevel@tonic-gate } 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate /* 13700Sstevel@tonic-gate * This function creates the /obp node in the PICL tree for OBP nodes 13710Sstevel@tonic-gate * without a device type class. 13720Sstevel@tonic-gate */ 13730Sstevel@tonic-gate static int 13740Sstevel@tonic-gate construct_picl_openprom(picl_nodehdl_t rooth, picl_nodehdl_t *obph) 13750Sstevel@tonic-gate { 13760Sstevel@tonic-gate picl_nodehdl_t tmph; 13770Sstevel@tonic-gate int err; 13780Sstevel@tonic-gate 13790Sstevel@tonic-gate err = ptree_create_and_add_node(rooth, PICL_NODE_OBP, 13800Sstevel@tonic-gate PICL_CLASS_PICL, &tmph); 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate if (err != PICL_SUCCESS) 13830Sstevel@tonic-gate return (err); 13840Sstevel@tonic-gate *obph = tmph; 13850Sstevel@tonic-gate return (PICL_SUCCESS); 13860Sstevel@tonic-gate } 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate /* 13890Sstevel@tonic-gate * This function creates the /platform node in the PICL tree and 13900Sstevel@tonic-gate * its properties. It sets the "platform-name" property to the 13910Sstevel@tonic-gate * platform name 13920Sstevel@tonic-gate */ 13930Sstevel@tonic-gate static int 13940Sstevel@tonic-gate construct_picl_platform(picl_nodehdl_t rooth, di_node_t di_root, 13950Sstevel@tonic-gate picl_nodehdl_t *piclh) 13960Sstevel@tonic-gate { 13970Sstevel@tonic-gate int err; 13980Sstevel@tonic-gate picl_nodehdl_t plafh; 13990Sstevel@tonic-gate char *nodename; 14000Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 14010Sstevel@tonic-gate ptree_propinfo_t propinfo; 14020Sstevel@tonic-gate picl_prophdl_t proph; 14030Sstevel@tonic-gate 14040Sstevel@tonic-gate nodename = di_node_name(di_root); 14050Sstevel@tonic-gate if (nodename == NULL) 14060Sstevel@tonic-gate return (PICL_FAILURE); 14070Sstevel@tonic-gate 14080Sstevel@tonic-gate err = 0; 14090Sstevel@tonic-gate if (di_nodeid(di_root) == DI_PROM_NODEID || 14100Sstevel@tonic-gate di_nodeid(di_root) == DI_SID_NODEID) 14110Sstevel@tonic-gate err = get_device_type(nodeclass, di_root); 14120Sstevel@tonic-gate 14130Sstevel@tonic-gate if (err < 0) 14140Sstevel@tonic-gate (void) strcpy(nodeclass, PICL_CLASS_UPA); /* default */ 14150Sstevel@tonic-gate 14160Sstevel@tonic-gate err = ptree_create_and_add_node(rooth, PICL_NODE_PLATFORM, 14170Sstevel@tonic-gate nodeclass, &plafh); 14180Sstevel@tonic-gate if (err != PICL_SUCCESS) 14190Sstevel@tonic-gate return (err); 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 14220Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(nodename) + 1, 14230Sstevel@tonic-gate PICL_PROP_PLATFORM_NAME, NULL, NULL); 14240Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, nodename, &proph); 14250Sstevel@tonic-gate if (err != PICL_SUCCESS) 14260Sstevel@tonic-gate return (err); 14270Sstevel@tonic-gate 14280Sstevel@tonic-gate (void) add_devinfo_props(plafh, di_root); 14290Sstevel@tonic-gate 14300Sstevel@tonic-gate (void) add_openprom_props(plafh, di_root); 14310Sstevel@tonic-gate 14320Sstevel@tonic-gate *piclh = plafh; 14330Sstevel@tonic-gate 14340Sstevel@tonic-gate return (PICL_SUCCESS); 14350Sstevel@tonic-gate } 14360Sstevel@tonic-gate 14370Sstevel@tonic-gate /* 14380Sstevel@tonic-gate * This function creates a node in /obp tree for the libdevinfo handle. 14390Sstevel@tonic-gate */ 14400Sstevel@tonic-gate static int 14410Sstevel@tonic-gate construct_obp_node(picl_nodehdl_t parh, di_node_t dn, picl_nodehdl_t *chdh) 14420Sstevel@tonic-gate { 14430Sstevel@tonic-gate int err; 14440Sstevel@tonic-gate char *nodename; 14450Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 14460Sstevel@tonic-gate picl_nodehdl_t anodeh; 14470Sstevel@tonic-gate 14480Sstevel@tonic-gate nodename = di_node_name(dn); /* PICL_PROP_NAME */ 14490Sstevel@tonic-gate if (nodename == NULL) 14500Sstevel@tonic-gate return (PICL_FAILURE); 14510Sstevel@tonic-gate 14520Sstevel@tonic-gate if (strcmp(nodename, "pseudo") == 0) 14530Sstevel@tonic-gate return (PICL_FAILURE); 14540Sstevel@tonic-gate 14550Sstevel@tonic-gate if ((di_nodeid(dn) == DI_PROM_NODEID) && 14560Sstevel@tonic-gate (get_device_type(nodeclass, dn) == 0)) 14570Sstevel@tonic-gate return (PICL_FAILURE); 14580Sstevel@tonic-gate 14590Sstevel@tonic-gate err = ptree_create_and_add_node(parh, nodename, nodename, &anodeh); 14600Sstevel@tonic-gate if (err != PICL_SUCCESS) 14610Sstevel@tonic-gate return (err); 14620Sstevel@tonic-gate 14630Sstevel@tonic-gate add_devinfo_props(anodeh, dn); 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate (void) add_openprom_props(anodeh, dn); 14660Sstevel@tonic-gate 14670Sstevel@tonic-gate *chdh = anodeh; 14680Sstevel@tonic-gate 14690Sstevel@tonic-gate return (PICL_SUCCESS); 14700Sstevel@tonic-gate } 14710Sstevel@tonic-gate 14720Sstevel@tonic-gate /* 14730Sstevel@tonic-gate * This function creates a PICL node in /platform tree for a device 14740Sstevel@tonic-gate */ 14750Sstevel@tonic-gate static int 14760Sstevel@tonic-gate construct_devtype_node(picl_nodehdl_t parh, char *nodename, 14770Sstevel@tonic-gate char *nodeclass, di_node_t dn, picl_nodehdl_t *chdh) 14780Sstevel@tonic-gate { 14790Sstevel@tonic-gate int err; 14800Sstevel@tonic-gate picl_nodehdl_t anodeh; 14810Sstevel@tonic-gate 14820Sstevel@tonic-gate err = ptree_create_and_add_node(parh, nodename, nodeclass, &anodeh); 14830Sstevel@tonic-gate if (err != PICL_SUCCESS) 14840Sstevel@tonic-gate return (err); 14850Sstevel@tonic-gate 14860Sstevel@tonic-gate (void) add_devinfo_props(anodeh, dn); 14870Sstevel@tonic-gate (void) add_openprom_props(anodeh, dn); 14887834SMichael.Bergknoff@Sun.COM construct_mpath_node(anodeh, dn); 14890Sstevel@tonic-gate 14900Sstevel@tonic-gate *chdh = anodeh; 14910Sstevel@tonic-gate return (err); 14920Sstevel@tonic-gate } 14930Sstevel@tonic-gate 14940Sstevel@tonic-gate /* 14950Sstevel@tonic-gate * Create a subtree of "picl" class nodes in /obp for these nodes 14960Sstevel@tonic-gate */ 14970Sstevel@tonic-gate static int 14980Sstevel@tonic-gate construct_openprom_tree(picl_nodehdl_t nodeh, di_node_t dinode) 14990Sstevel@tonic-gate { 15000Sstevel@tonic-gate di_node_t cnode; 15010Sstevel@tonic-gate picl_nodehdl_t chdh; 15020Sstevel@tonic-gate int err; 15030Sstevel@tonic-gate 15040Sstevel@tonic-gate err = construct_obp_node(nodeh, dinode, &chdh); 15050Sstevel@tonic-gate if (err != PICL_SUCCESS) 15060Sstevel@tonic-gate return (err); 15070Sstevel@tonic-gate 15080Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 15090Sstevel@tonic-gate cnode = di_sibling_node(cnode)) 15100Sstevel@tonic-gate (void) construct_openprom_tree(chdh, cnode); 15110Sstevel@tonic-gate 15120Sstevel@tonic-gate return (PICL_SUCCESS); 15130Sstevel@tonic-gate 15140Sstevel@tonic-gate } 15150Sstevel@tonic-gate 15160Sstevel@tonic-gate /* 15170Sstevel@tonic-gate * Process the libdevinfo device tree and create nodes in /platform or /obp 15180Sstevel@tonic-gate * PICL tree. 15190Sstevel@tonic-gate * 15200Sstevel@tonic-gate * This routine traverses the immediate children of "dinode" device and 15210Sstevel@tonic-gate * determines the node class for that child. If it finds a valid class 15220Sstevel@tonic-gate * name, then it builds a PICL node under /platform subtree and calls itself 15230Sstevel@tonic-gate * recursively to construct the subtree for that child node. Otherwise, if 15240Sstevel@tonic-gate * the parent_class is NULL, then it constructs a node and subtree under /obp 15250Sstevel@tonic-gate * subtree. 15260Sstevel@tonic-gate * 15270Sstevel@tonic-gate * Note that we skip the children nodes that don't have a valid class name 15280Sstevel@tonic-gate * and the parent_class is non NULL to prevent creation of any placeholder 15290Sstevel@tonic-gate * nodes (such as sd,...). 15300Sstevel@tonic-gate */ 15310Sstevel@tonic-gate static int 15320Sstevel@tonic-gate construct_devinfo_tree(picl_nodehdl_t plafh, picl_nodehdl_t obph, 15330Sstevel@tonic-gate di_node_t dinode, char *parent_class) 15340Sstevel@tonic-gate { 15350Sstevel@tonic-gate di_node_t cnode; 15360Sstevel@tonic-gate picl_nodehdl_t chdh; 15370Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 15380Sstevel@tonic-gate char *nodename; 15390Sstevel@tonic-gate int err; 15400Sstevel@tonic-gate 15410Sstevel@tonic-gate err = PICL_SUCCESS; 15420Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 15430Sstevel@tonic-gate cnode = di_sibling_node(cnode)) { 15440Sstevel@tonic-gate nodename = di_node_name(cnode); /* PICL_PROP_NAME */ 15450Sstevel@tonic-gate if (nodename == NULL) 15460Sstevel@tonic-gate continue; 15470Sstevel@tonic-gate 15480Sstevel@tonic-gate err = get_node_class(nodeclass, cnode, nodename); 15490Sstevel@tonic-gate 15500Sstevel@tonic-gate if (err == 0) { 15510Sstevel@tonic-gate err = construct_devtype_node(plafh, nodename, 15520Sstevel@tonic-gate nodeclass, cnode, &chdh); 15530Sstevel@tonic-gate if (err != PICL_SUCCESS) 15540Sstevel@tonic-gate return (err); 15550Sstevel@tonic-gate err = construct_devinfo_tree(chdh, obph, cnode, 15560Sstevel@tonic-gate nodeclass); 15570Sstevel@tonic-gate } else if (parent_class == NULL) 15580Sstevel@tonic-gate err = construct_openprom_tree(obph, cnode); 15590Sstevel@tonic-gate else 15600Sstevel@tonic-gate continue; 15610Sstevel@tonic-gate /* 15620Sstevel@tonic-gate * if parent_class is non NULL, skip the children nodes 15630Sstevel@tonic-gate * that don't have a valid device class - eliminates 15640Sstevel@tonic-gate * placeholder nodes (sd,...) from being created. 15650Sstevel@tonic-gate */ 15660Sstevel@tonic-gate } 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate return (err); 15690Sstevel@tonic-gate 15700Sstevel@tonic-gate } 15710Sstevel@tonic-gate 15720Sstevel@tonic-gate /* 15730Sstevel@tonic-gate * This function is called from the event handler called from the daemon 15740Sstevel@tonic-gate * on PICL events. 15750Sstevel@tonic-gate * 15760Sstevel@tonic-gate * This routine traverses the children of the "dinode" device and 15770Sstevel@tonic-gate * creates a PICL node for each child not found in the PICL tree and 15780Sstevel@tonic-gate * invokes itself recursively to create a subtree for the newly created 15790Sstevel@tonic-gate * child node. It also checks if the node being created is a meory 15800Sstevel@tonic-gate * controller. If so, it posts PICLEVENT_MC_ADDED PICL event to the PICL 15810Sstevel@tonic-gate * framework. 15820Sstevel@tonic-gate */ 15830Sstevel@tonic-gate static int 15840Sstevel@tonic-gate update_subtree(picl_nodehdl_t nodeh, di_node_t dinode) 15850Sstevel@tonic-gate { 15860Sstevel@tonic-gate di_node_t cnode; 15870Sstevel@tonic-gate picl_nodehdl_t chdh; 15880Sstevel@tonic-gate picl_nodehdl_t nh; 15890Sstevel@tonic-gate char *nodename; 15900Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 15910Sstevel@tonic-gate char *path_buf; 15920Sstevel@tonic-gate char buf[MAX_UNIT_ADDRESS_LEN]; 15930Sstevel@tonic-gate char unitaddr[MAX_UNIT_ADDRESS_LEN]; 15940Sstevel@tonic-gate char path_w_ua[MAXPATHLEN]; 15950Sstevel@tonic-gate char path_wo_ua[MAXPATHLEN]; 15960Sstevel@tonic-gate char *strp; 15970Sstevel@tonic-gate int gotit; 15980Sstevel@tonic-gate int err; 15990Sstevel@tonic-gate 16000Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 16010Sstevel@tonic-gate cnode = di_sibling_node(cnode)) { 16020Sstevel@tonic-gate path_buf = di_devfs_path(cnode); 16030Sstevel@tonic-gate if (path_buf == NULL) 16040Sstevel@tonic-gate continue; 16050Sstevel@tonic-gate 16060Sstevel@tonic-gate nodename = di_node_name(cnode); 16070Sstevel@tonic-gate if (nodename == NULL) { 16080Sstevel@tonic-gate di_devfs_path_free(path_buf); 16090Sstevel@tonic-gate continue; 16100Sstevel@tonic-gate } 16110Sstevel@tonic-gate 16120Sstevel@tonic-gate err = get_node_class(nodeclass, cnode, nodename); 16130Sstevel@tonic-gate 16140Sstevel@tonic-gate if (err < 0) { 16150Sstevel@tonic-gate di_devfs_path_free(path_buf); 16160Sstevel@tonic-gate continue; 16170Sstevel@tonic-gate } 16180Sstevel@tonic-gate 16190Sstevel@tonic-gate /* 16200Sstevel@tonic-gate * this is quite complicated - both path_buf and any nodes 16210Sstevel@tonic-gate * already in the picl tree may, or may not, have the 16220Sstevel@tonic-gate * @<unit_addr> at the end of their names. So we must 16230Sstevel@tonic-gate * take path_buf and work out what the device path would 16240Sstevel@tonic-gate * be both with and without the unit_address, then search 16250Sstevel@tonic-gate * the picl tree for both forms. 16260Sstevel@tonic-gate */ 16270Sstevel@tonic-gate if (((strp = strrchr(path_buf, '/')) != NULL) && 16280Sstevel@tonic-gate strchr(strp, '@') == NULL) { 16290Sstevel@tonic-gate /* 1630*8200STrevor.Thompson@Sun.COM * This is an unattached node - so the path is not 16310Sstevel@tonic-gate * unique. Need to find out which node it is. 1632*8200STrevor.Thompson@Sun.COM * Find the unit_address from the OBP or devinfo 1633*8200STrevor.Thompson@Sun.COM * properties. 16340Sstevel@tonic-gate */ 16350Sstevel@tonic-gate err = ptree_create_node(nodename, nodeclass, &chdh); 16360Sstevel@tonic-gate if (err != PICL_SUCCESS) 16370Sstevel@tonic-gate return (err); 1638*8200STrevor.Thompson@Sun.COM 1639*8200STrevor.Thompson@Sun.COM (void) add_devinfo_props(chdh, cnode); 16400Sstevel@tonic-gate (void) add_openprom_props(chdh, cnode); 1641*8200STrevor.Thompson@Sun.COM 16420Sstevel@tonic-gate err = get_unitaddr(nodeh, chdh, unitaddr, 16430Sstevel@tonic-gate sizeof (unitaddr)); 16440Sstevel@tonic-gate if (err != PICL_SUCCESS) 16450Sstevel@tonic-gate return (err); 16460Sstevel@tonic-gate (void) ptree_destroy_node(chdh); 16470Sstevel@tonic-gate (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s@%s", 16480Sstevel@tonic-gate path_buf, unitaddr); 16490Sstevel@tonic-gate (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s", 16500Sstevel@tonic-gate path_buf); 16510Sstevel@tonic-gate } else { 16520Sstevel@tonic-gate /* 16530Sstevel@tonic-gate * this is an attached node - so the path is unique 16540Sstevel@tonic-gate */ 16550Sstevel@tonic-gate (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s", 16560Sstevel@tonic-gate path_buf); 16570Sstevel@tonic-gate (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s", 16580Sstevel@tonic-gate path_buf); 16590Sstevel@tonic-gate strp = strrchr(path_wo_ua, '@'); 16600Sstevel@tonic-gate *strp++ = '\0'; 16610Sstevel@tonic-gate (void) snprintf(unitaddr, sizeof (unitaddr), "%s", 16620Sstevel@tonic-gate strp); 16630Sstevel@tonic-gate } 16640Sstevel@tonic-gate /* 16650Sstevel@tonic-gate * first look for node with unit address in devfs_path 16660Sstevel@tonic-gate */ 16670Sstevel@tonic-gate if (ptree_find_node(nodeh, PICL_PROP_DEVFS_PATH, 16680Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, path_w_ua, strlen(path_w_ua) + 1, 16690Sstevel@tonic-gate &nh) == PICL_SUCCESS) { 16700Sstevel@tonic-gate /* 16710Sstevel@tonic-gate * node already there - there's nothing we need to do 16720Sstevel@tonic-gate */ 16730Sstevel@tonic-gate if (picldevtree_debug > 1) 16740Sstevel@tonic-gate syslog(LOG_INFO, 16750Sstevel@tonic-gate "update_subtree: path:%s node exists\n", 16760Sstevel@tonic-gate path_buf); 16770Sstevel@tonic-gate di_devfs_path_free(path_buf); 16780Sstevel@tonic-gate continue; 16790Sstevel@tonic-gate } 16800Sstevel@tonic-gate /* 16810Sstevel@tonic-gate * now look for node without unit address in devfs_path. 16820Sstevel@tonic-gate * This might be just one out of several 16830Sstevel@tonic-gate * nodes - need to check all siblings 16840Sstevel@tonic-gate */ 16850Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, 16860Sstevel@tonic-gate &chdh, sizeof (chdh)); 16870Sstevel@tonic-gate if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND)) 16880Sstevel@tonic-gate return (err); 16890Sstevel@tonic-gate gotit = 0; 16900Sstevel@tonic-gate while (err == PICL_SUCCESS) { 16910Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 16920Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, buf, sizeof (buf)); 16930Sstevel@tonic-gate if (err != PICL_SUCCESS) 16940Sstevel@tonic-gate return (err); 16950Sstevel@tonic-gate if (strcmp(buf, path_wo_ua) == 0) { 16960Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 16970Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, buf, sizeof (buf)); 16980Sstevel@tonic-gate if (err != PICL_SUCCESS) 16990Sstevel@tonic-gate return (err); 17000Sstevel@tonic-gate if (strcmp(buf, unitaddr) == 0) { 17010Sstevel@tonic-gate gotit = 1; 17020Sstevel@tonic-gate break; 17030Sstevel@tonic-gate } 17040Sstevel@tonic-gate } 17050Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 17060Sstevel@tonic-gate PICL_PROP_PEER, &chdh, sizeof (chdh)); 17070Sstevel@tonic-gate if (err != PICL_SUCCESS) 17080Sstevel@tonic-gate break; 17090Sstevel@tonic-gate } 17100Sstevel@tonic-gate if (gotit) { 17110Sstevel@tonic-gate /* 17120Sstevel@tonic-gate * node already there - there's nothing we need to do 17130Sstevel@tonic-gate */ 17140Sstevel@tonic-gate if (picldevtree_debug > 1) 17150Sstevel@tonic-gate syslog(LOG_INFO, 17160Sstevel@tonic-gate "update_subtree: path:%s node exists\n", 17170Sstevel@tonic-gate path_buf); 17180Sstevel@tonic-gate di_devfs_path_free(path_buf); 17190Sstevel@tonic-gate continue; 17200Sstevel@tonic-gate } 17210Sstevel@tonic-gate 17220Sstevel@tonic-gate #define IS_MC(x) (strcmp(x, PICL_CLASS_MEMORY_CONTROLLER) == 0 ? 1 : 0) 17230Sstevel@tonic-gate 17240Sstevel@tonic-gate if (construct_devtype_node(nodeh, nodename, nodeclass, cnode, 17250Sstevel@tonic-gate &chdh) == PICL_SUCCESS) { 17260Sstevel@tonic-gate if (picldevtree_debug) 17270Sstevel@tonic-gate syslog(LOG_INFO, 17280Sstevel@tonic-gate "picldevtree: added node:%s path:%s\n", 17290Sstevel@tonic-gate nodename, path_buf); 17300Sstevel@tonic-gate if (IS_MC(nodeclass)) { 17310Sstevel@tonic-gate if (post_mc_event(PICLEVENT_MC_ADDED, chdh) != 17320Sstevel@tonic-gate PICL_SUCCESS) 17330Sstevel@tonic-gate syslog(LOG_WARNING, PICL_EVENT_DROPPED, 17340Sstevel@tonic-gate PICLEVENT_MC_ADDED); 17350Sstevel@tonic-gate } 17360Sstevel@tonic-gate 17370Sstevel@tonic-gate di_devfs_path_free(path_buf); 17380Sstevel@tonic-gate (void) update_subtree(chdh, cnode); 17390Sstevel@tonic-gate } 17400Sstevel@tonic-gate } 17410Sstevel@tonic-gate 17420Sstevel@tonic-gate return (PICL_SUCCESS); 17430Sstevel@tonic-gate 17440Sstevel@tonic-gate } 17450Sstevel@tonic-gate 17460Sstevel@tonic-gate /* 17477442SMichael.Bergknoff@Sun.COM * Check for a stale OBP node. EINVAL is returned from the openprom(7D) driver 17487442SMichael.Bergknoff@Sun.COM * if the nodeid stored in the snapshot is not valid. 17497442SMichael.Bergknoff@Sun.COM */ 17507442SMichael.Bergknoff@Sun.COM static int 17517442SMichael.Bergknoff@Sun.COM check_stale_node(di_node_t node, void *arg) 17527442SMichael.Bergknoff@Sun.COM { 17537442SMichael.Bergknoff@Sun.COM di_prom_prop_t promp; 17547442SMichael.Bergknoff@Sun.COM 17557442SMichael.Bergknoff@Sun.COM errno = 0; 17567442SMichael.Bergknoff@Sun.COM promp = di_prom_prop_next(ph, node, DI_PROM_PROP_NIL); 17577442SMichael.Bergknoff@Sun.COM if (promp == DI_PROM_PROP_NIL && errno == EINVAL) { 17587442SMichael.Bergknoff@Sun.COM snapshot_stale = 1; 17597442SMichael.Bergknoff@Sun.COM return (DI_WALK_TERMINATE); 17607442SMichael.Bergknoff@Sun.COM } 17617442SMichael.Bergknoff@Sun.COM return (DI_WALK_CONTINUE); 17627442SMichael.Bergknoff@Sun.COM } 17637442SMichael.Bergknoff@Sun.COM 17647442SMichael.Bergknoff@Sun.COM /* 17657442SMichael.Bergknoff@Sun.COM * Walk the snapshot and check the OBP properties of each node. 17667442SMichael.Bergknoff@Sun.COM */ 17677442SMichael.Bergknoff@Sun.COM static int 17687442SMichael.Bergknoff@Sun.COM is_snapshot_stale(di_node_t root) 17697442SMichael.Bergknoff@Sun.COM { 17707442SMichael.Bergknoff@Sun.COM snapshot_stale = 0; 17717442SMichael.Bergknoff@Sun.COM di_walk_node(root, DI_WALK_CLDFIRST, NULL, check_stale_node); 17727442SMichael.Bergknoff@Sun.COM return (snapshot_stale); 17737442SMichael.Bergknoff@Sun.COM } 17747442SMichael.Bergknoff@Sun.COM 17757442SMichael.Bergknoff@Sun.COM /* 17760Sstevel@tonic-gate * This function processes the data from libdevinfo and creates nodes 17770Sstevel@tonic-gate * in the PICL tree. 17780Sstevel@tonic-gate */ 17790Sstevel@tonic-gate static int 17800Sstevel@tonic-gate libdevinfo_init(picl_nodehdl_t rooth) 17810Sstevel@tonic-gate { 17820Sstevel@tonic-gate di_node_t di_root; 17830Sstevel@tonic-gate picl_nodehdl_t plafh; 17840Sstevel@tonic-gate picl_nodehdl_t obph; 17850Sstevel@tonic-gate int err; 17860Sstevel@tonic-gate 17875492Sarutz /* 17885492Sarutz * Use DINFOCACHE so that we obtain all attributes for all 17895492Sarutz * device instances (without necessarily doing a load/attach 17905492Sarutz * of all drivers). Once the (on-disk) cache file is built, it 17915492Sarutz * exists over a reboot and can be read into memory at a very 17925492Sarutz * low cost. 17935492Sarutz */ 17945492Sarutz if ((di_root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) 17950Sstevel@tonic-gate return (PICL_FAILURE); 17960Sstevel@tonic-gate 17970Sstevel@tonic-gate if ((ph = di_prom_init()) == NULL) 17980Sstevel@tonic-gate return (PICL_FAILURE); 17997442SMichael.Bergknoff@Sun.COM 18007442SMichael.Bergknoff@Sun.COM /* 18017442SMichael.Bergknoff@Sun.COM * Check if the snapshot cache contains stale OBP nodeid references. 18027442SMichael.Bergknoff@Sun.COM * If it does release the snapshot and obtain a live snapshot from the 18037442SMichael.Bergknoff@Sun.COM * kernel. 18047442SMichael.Bergknoff@Sun.COM */ 18057442SMichael.Bergknoff@Sun.COM if (is_snapshot_stale(di_root)) { 18067442SMichael.Bergknoff@Sun.COM syslog(LOG_INFO, "picld detected stale snapshot cache"); 18077442SMichael.Bergknoff@Sun.COM di_fini(di_root); 18087442SMichael.Bergknoff@Sun.COM if ((di_root = di_init("/", DINFOCPYALL | DINFOFORCE)) == 18097442SMichael.Bergknoff@Sun.COM DI_NODE_NIL) { 18107442SMichael.Bergknoff@Sun.COM return (PICL_FAILURE); 18117442SMichael.Bergknoff@Sun.COM } 18127442SMichael.Bergknoff@Sun.COM } 18137442SMichael.Bergknoff@Sun.COM 18140Sstevel@tonic-gate /* 18150Sstevel@tonic-gate * create platform PICL node using di_root node 18160Sstevel@tonic-gate */ 18170Sstevel@tonic-gate err = construct_picl_platform(rooth, di_root, &plafh); 18180Sstevel@tonic-gate if (err != PICL_SUCCESS) { 18190Sstevel@tonic-gate di_fini(di_root); 18200Sstevel@tonic-gate return (PICL_FAILURE); 18210Sstevel@tonic-gate } 18220Sstevel@tonic-gate 18230Sstevel@tonic-gate err = construct_picl_openprom(rooth, &obph); 18240Sstevel@tonic-gate if (err != PICL_SUCCESS) { 18250Sstevel@tonic-gate di_fini(di_root); 18260Sstevel@tonic-gate return (PICL_FAILURE); 18270Sstevel@tonic-gate } 18280Sstevel@tonic-gate 18290Sstevel@tonic-gate (void) construct_devinfo_tree(plafh, obph, di_root, NULL); 18300Sstevel@tonic-gate if (ph) { 18310Sstevel@tonic-gate di_prom_fini(ph); 18320Sstevel@tonic-gate ph = NULL; 18330Sstevel@tonic-gate } 18340Sstevel@tonic-gate di_fini(di_root); 18350Sstevel@tonic-gate return (err); 18360Sstevel@tonic-gate } 18370Sstevel@tonic-gate 18380Sstevel@tonic-gate /* 18390Sstevel@tonic-gate * This function returns the integer property value 18400Sstevel@tonic-gate */ 18410Sstevel@tonic-gate static int 18420Sstevel@tonic-gate get_int_propval_by_name(picl_nodehdl_t nodeh, char *pname, int *ival) 18430Sstevel@tonic-gate { 18440Sstevel@tonic-gate int err; 18450Sstevel@tonic-gate 18460Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, pname, ival, 18470Sstevel@tonic-gate sizeof (int)); 18480Sstevel@tonic-gate 18490Sstevel@tonic-gate return (err); 18500Sstevel@tonic-gate } 18510Sstevel@tonic-gate 18520Sstevel@tonic-gate /* 18530Sstevel@tonic-gate * This function returns the port ID (or CPU ID in the case of CMP cores) 18540Sstevel@tonic-gate * of the specific CPU node handle. If upa_portid exists, return its value. 18550Sstevel@tonic-gate * Otherwise, return portid/cpuid. 18560Sstevel@tonic-gate */ 18570Sstevel@tonic-gate static int 18580Sstevel@tonic-gate get_cpu_portid(picl_nodehdl_t modh, int *id) 18590Sstevel@tonic-gate { 18600Sstevel@tonic-gate int err; 18610Sstevel@tonic-gate 18625028Sfw157321 if (strcmp(mach_name, "sun4u") == 0 || 18635028Sfw157321 strcmp(mach_name, "sun4v") == 0) { 18640Sstevel@tonic-gate err = get_int_propval_by_name(modh, OBP_PROP_UPA_PORTID, id); 18650Sstevel@tonic-gate if (err == PICL_SUCCESS) 18660Sstevel@tonic-gate return (err); 18670Sstevel@tonic-gate err = get_int_propval_by_name(modh, OBP_PROP_PORTID, id); 18680Sstevel@tonic-gate if (err == PICL_SUCCESS) 18690Sstevel@tonic-gate return (err); 18700Sstevel@tonic-gate return (get_int_propval_by_name(modh, OBP_PROP_CPUID, id)); 18710Sstevel@tonic-gate } 18720Sstevel@tonic-gate if (strcmp(mach_name, "i86pc") == 0) 18730Sstevel@tonic-gate return (get_int_propval_by_name(modh, PICL_PROP_INSTANCE, id)); 18740Sstevel@tonic-gate 18750Sstevel@tonic-gate return (PICL_FAILURE); 18760Sstevel@tonic-gate } 18770Sstevel@tonic-gate 18780Sstevel@tonic-gate /* 18790Sstevel@tonic-gate * This function is the volatile read access function of CPU state 18800Sstevel@tonic-gate * property 18810Sstevel@tonic-gate */ 18820Sstevel@tonic-gate static int 18830Sstevel@tonic-gate get_pi_state(ptree_rarg_t *rarg, void *vbuf) 18840Sstevel@tonic-gate { 18850Sstevel@tonic-gate int id; 18860Sstevel@tonic-gate int err; 18870Sstevel@tonic-gate 18880Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 18890Sstevel@tonic-gate if (err != PICL_SUCCESS) 18900Sstevel@tonic-gate return (err); 18910Sstevel@tonic-gate 18920Sstevel@tonic-gate switch (p_online(id, P_STATUS)) { 18930Sstevel@tonic-gate case P_ONLINE: 18940Sstevel@tonic-gate (void) strlcpy(vbuf, PS_ONLINE, MAX_STATE_SIZE); 18950Sstevel@tonic-gate break; 18960Sstevel@tonic-gate case P_OFFLINE: 18970Sstevel@tonic-gate (void) strlcpy(vbuf, PS_OFFLINE, MAX_STATE_SIZE); 18980Sstevel@tonic-gate break; 18990Sstevel@tonic-gate case P_NOINTR: 19000Sstevel@tonic-gate (void) strlcpy(vbuf, PS_NOINTR, MAX_STATE_SIZE); 19010Sstevel@tonic-gate break; 19020Sstevel@tonic-gate case P_SPARE: 19030Sstevel@tonic-gate (void) strlcpy(vbuf, PS_SPARE, MAX_STATE_SIZE); 19040Sstevel@tonic-gate break; 19050Sstevel@tonic-gate case P_FAULTED: 19060Sstevel@tonic-gate (void) strlcpy(vbuf, PS_FAULTED, MAX_STATE_SIZE); 19070Sstevel@tonic-gate break; 19080Sstevel@tonic-gate case P_POWEROFF: 19090Sstevel@tonic-gate (void) strlcpy(vbuf, PS_POWEROFF, MAX_STATE_SIZE); 19100Sstevel@tonic-gate break; 19110Sstevel@tonic-gate default: 19120Sstevel@tonic-gate (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE); 19130Sstevel@tonic-gate break; 19140Sstevel@tonic-gate } 19150Sstevel@tonic-gate return (PICL_SUCCESS); 19160Sstevel@tonic-gate } 19170Sstevel@tonic-gate 19180Sstevel@tonic-gate /* 19190Sstevel@tonic-gate * This function is the volatile read access function of CPU processor_type 19200Sstevel@tonic-gate * property 19210Sstevel@tonic-gate */ 19220Sstevel@tonic-gate static int 19230Sstevel@tonic-gate get_processor_type(ptree_rarg_t *rarg, void *vbuf) 19240Sstevel@tonic-gate { 19250Sstevel@tonic-gate processor_info_t cpu_info; 19260Sstevel@tonic-gate int id; 19270Sstevel@tonic-gate int err; 19280Sstevel@tonic-gate 19290Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 19300Sstevel@tonic-gate if (err != PICL_SUCCESS) 19310Sstevel@tonic-gate return (err); 19320Sstevel@tonic-gate 19330Sstevel@tonic-gate if (processor_info(id, &cpu_info) >= 0) { 19340Sstevel@tonic-gate (void) strlcpy(vbuf, cpu_info.pi_processor_type, PI_TYPELEN); 19350Sstevel@tonic-gate } 19360Sstevel@tonic-gate return (PICL_SUCCESS); 19370Sstevel@tonic-gate } 19380Sstevel@tonic-gate 19390Sstevel@tonic-gate /* 19400Sstevel@tonic-gate * This function is the volatile read access function of CPU fputypes 19410Sstevel@tonic-gate * property 19420Sstevel@tonic-gate */ 19430Sstevel@tonic-gate static int 19440Sstevel@tonic-gate get_fputypes(ptree_rarg_t *rarg, void *vbuf) 19450Sstevel@tonic-gate { 19460Sstevel@tonic-gate processor_info_t cpu_info; 19470Sstevel@tonic-gate int id; 19480Sstevel@tonic-gate int err; 19490Sstevel@tonic-gate 19500Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 19510Sstevel@tonic-gate if (err != PICL_SUCCESS) 19520Sstevel@tonic-gate return (err); 19530Sstevel@tonic-gate 19540Sstevel@tonic-gate if (processor_info(id, &cpu_info) >= 0) { 19550Sstevel@tonic-gate (void) strlcpy(vbuf, cpu_info.pi_fputypes, PI_FPUTYPE); 19560Sstevel@tonic-gate } 19570Sstevel@tonic-gate return (PICL_SUCCESS); 19580Sstevel@tonic-gate } 19590Sstevel@tonic-gate 19600Sstevel@tonic-gate /* 19610Sstevel@tonic-gate * This function is the volatile read access function of CPU StateBegin 19620Sstevel@tonic-gate * property. To minimize overhead, use kstat_chain_update() to refresh 19630Sstevel@tonic-gate * the kstat header info as opposed to invoking kstat_open() every time. 19640Sstevel@tonic-gate */ 19650Sstevel@tonic-gate static int 19660Sstevel@tonic-gate get_pi_state_begin(ptree_rarg_t *rarg, void *vbuf) 19670Sstevel@tonic-gate { 19680Sstevel@tonic-gate int err; 19690Sstevel@tonic-gate int cpu_id; 19700Sstevel@tonic-gate static kstat_ctl_t *kc = NULL; 19710Sstevel@tonic-gate static pthread_mutex_t kc_mutex = PTHREAD_MUTEX_INITIALIZER; 19720Sstevel@tonic-gate kstat_t *kp; 19730Sstevel@tonic-gate kstat_named_t *kn; 19740Sstevel@tonic-gate 19750Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &cpu_id); 19760Sstevel@tonic-gate if (err != PICL_SUCCESS) 19770Sstevel@tonic-gate return (err); 19780Sstevel@tonic-gate 19790Sstevel@tonic-gate (void) pthread_mutex_lock(&kc_mutex); 19800Sstevel@tonic-gate if (kc == NULL) 19810Sstevel@tonic-gate kc = kstat_open(); 19820Sstevel@tonic-gate else if (kstat_chain_update(kc) == -1) { 19830Sstevel@tonic-gate (void) kstat_close(kc); 19840Sstevel@tonic-gate kc = kstat_open(); 19850Sstevel@tonic-gate } 19860Sstevel@tonic-gate 19870Sstevel@tonic-gate if (kc == NULL) { 19880Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 19890Sstevel@tonic-gate return (PICL_FAILURE); 19900Sstevel@tonic-gate } 19910Sstevel@tonic-gate 19920Sstevel@tonic-gate /* Get the state_begin from kstat */ 19930Sstevel@tonic-gate if ((kp = kstat_lookup(kc, KSTAT_CPU_INFO, cpu_id, NULL)) == NULL || 19940Sstevel@tonic-gate kp->ks_type != KSTAT_TYPE_NAMED || kstat_read(kc, kp, 0) < 0) { 19950Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 19960Sstevel@tonic-gate return (PICL_FAILURE); 19970Sstevel@tonic-gate } 19980Sstevel@tonic-gate 19990Sstevel@tonic-gate kn = kstat_data_lookup(kp, KSTAT_STATE_BEGIN); 20000Sstevel@tonic-gate if (kn) { 20010Sstevel@tonic-gate *(uint64_t *)vbuf = (uint64_t)kn->value.l; 20020Sstevel@tonic-gate err = PICL_SUCCESS; 20030Sstevel@tonic-gate } else 20040Sstevel@tonic-gate err = PICL_FAILURE; 20050Sstevel@tonic-gate 20060Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 20070Sstevel@tonic-gate return (err); 20080Sstevel@tonic-gate } 20090Sstevel@tonic-gate 20100Sstevel@tonic-gate /* 20110Sstevel@tonic-gate * This function adds CPU information to the CPU nodes 20120Sstevel@tonic-gate */ 20130Sstevel@tonic-gate /* ARGSUSED */ 20140Sstevel@tonic-gate static int 20150Sstevel@tonic-gate add_processor_info(picl_nodehdl_t cpuh, void *args) 20160Sstevel@tonic-gate { 20170Sstevel@tonic-gate int err; 20180Sstevel@tonic-gate int cpu_id; 20190Sstevel@tonic-gate ptree_propinfo_t propinfo; 20200Sstevel@tonic-gate ptree_propinfo_t pinfo; 20210Sstevel@tonic-gate 20220Sstevel@tonic-gate err = get_cpu_portid(cpuh, &cpu_id); 20230Sstevel@tonic-gate if (err != PICL_SUCCESS) 20240Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 2025*8200STrevor.Thompson@Sun.COM 2026*8200STrevor.Thompson@Sun.COM /* 2027*8200STrevor.Thompson@Sun.COM * Check to make sure that the CPU is still present, i.e. that it 2028*8200STrevor.Thompson@Sun.COM * has not been DR'ed out of the system. 2029*8200STrevor.Thompson@Sun.COM */ 2030*8200STrevor.Thompson@Sun.COM if (p_online(cpu_id, P_STATUS) == -1) { 2031*8200STrevor.Thompson@Sun.COM if (picldevtree_debug) 2032*8200STrevor.Thompson@Sun.COM syslog(LOG_INFO, 2033*8200STrevor.Thompson@Sun.COM "picldevtree: cpu %d (%llx) does not exist - " 2034*8200STrevor.Thompson@Sun.COM "deleting node\n", cpu_id, cpuh); 2035*8200STrevor.Thompson@Sun.COM 2036*8200STrevor.Thompson@Sun.COM if (ptree_delete_node(cpuh) == PICL_SUCCESS) 2037*8200STrevor.Thompson@Sun.COM (void) ptree_destroy_node(cpuh); 2038*8200STrevor.Thompson@Sun.COM 2039*8200STrevor.Thompson@Sun.COM return (PICL_WALK_CONTINUE); 2040*8200STrevor.Thompson@Sun.COM } 2041*8200STrevor.Thompson@Sun.COM 20420Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 20430Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (int), PICL_PROP_ID, NULL, NULL); 20440Sstevel@tonic-gate err = ptree_create_and_add_prop(cpuh, &propinfo, &cpu_id, NULL); 20450Sstevel@tonic-gate if (err != PICL_SUCCESS) 20460Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 20470Sstevel@tonic-gate 20480Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 20490Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), MAX_STATE_SIZE, 20500Sstevel@tonic-gate PICL_PROP_STATE, get_pi_state, NULL); 20510Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 20520Sstevel@tonic-gate 20530Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 20540Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_TYPELEN, 20550Sstevel@tonic-gate PICL_PROP_PROCESSOR_TYPE, get_processor_type, NULL); 20560Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 20570Sstevel@tonic-gate 20580Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 20590Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_FPUTYPE, 20600Sstevel@tonic-gate PICL_PROP_FPUTYPE, get_fputypes, NULL); 20610Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 20620Sstevel@tonic-gate 20630Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 20640Sstevel@tonic-gate PICL_PTYPE_TIMESTAMP, PICL_READ|PICL_VOLATILE, sizeof (uint64_t), 20650Sstevel@tonic-gate PICL_PROP_STATE_BEGIN, get_pi_state_begin, NULL); 20660Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 20670Sstevel@tonic-gate 20680Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 20690Sstevel@tonic-gate } 20700Sstevel@tonic-gate 20710Sstevel@tonic-gate /* 20720Sstevel@tonic-gate * This function sets up the "ID" property in every CPU nodes 20730Sstevel@tonic-gate * and adds processor info 20740Sstevel@tonic-gate */ 20750Sstevel@tonic-gate static int 20760Sstevel@tonic-gate setup_cpus(picl_nodehdl_t plafh) 20770Sstevel@tonic-gate { 20780Sstevel@tonic-gate int err; 20790Sstevel@tonic-gate 20800Sstevel@tonic-gate err = ptree_walk_tree_by_class(plafh, PICL_CLASS_CPU, NULL, 20810Sstevel@tonic-gate add_processor_info); 20820Sstevel@tonic-gate 20830Sstevel@tonic-gate return (err); 20840Sstevel@tonic-gate } 20850Sstevel@tonic-gate 20860Sstevel@tonic-gate /* 20870Sstevel@tonic-gate * This function format's the manufacture's information for FFB display 20880Sstevel@tonic-gate * devices 20890Sstevel@tonic-gate */ 20900Sstevel@tonic-gate static void 20910Sstevel@tonic-gate fmt_manf_id(manuf_t manufid, int bufsz, char *outbuf) 20920Sstevel@tonic-gate { 20930Sstevel@tonic-gate /* 20940Sstevel@tonic-gate * Format the manufacturer's info. Note a small inconsistency we 20950Sstevel@tonic-gate * have to work around - Brooktree has it's part number in decimal, 20960Sstevel@tonic-gate * while Mitsubishi has it's part number in hex. 20970Sstevel@tonic-gate */ 20980Sstevel@tonic-gate switch (manufid.fld.manf) { 20990Sstevel@tonic-gate case MANF_BROOKTREE: 21000Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, "%s %d, version %d", 21010Sstevel@tonic-gate "Brooktree", manufid.fld.partno, manufid.fld.version); 21020Sstevel@tonic-gate break; 21030Sstevel@tonic-gate 21040Sstevel@tonic-gate case MANF_MITSUBISHI: 21050Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, "%s %x, version %d", 21060Sstevel@tonic-gate "Mitsubishi", manufid.fld.partno, manufid.fld.version); 21070Sstevel@tonic-gate break; 21080Sstevel@tonic-gate 21090Sstevel@tonic-gate default: 21100Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, 21110Sstevel@tonic-gate "JED code %d, Part num 0x%x, version %d", 21120Sstevel@tonic-gate manufid.fld.manf, manufid.fld.partno, manufid.fld.version); 21130Sstevel@tonic-gate } 21140Sstevel@tonic-gate } 21150Sstevel@tonic-gate 21160Sstevel@tonic-gate /* 21170Sstevel@tonic-gate * If it's an ffb device, open ffb devices and return PICL_SUCCESS 21180Sstevel@tonic-gate */ 21190Sstevel@tonic-gate static int 21200Sstevel@tonic-gate open_ffb_device(picl_nodehdl_t ffbh, int *fd) 21210Sstevel@tonic-gate { 21220Sstevel@tonic-gate DIR *dirp; 21230Sstevel@tonic-gate char devfs_path[PATH_MAX]; 21240Sstevel@tonic-gate char dev_path[PATH_MAX]; 21250Sstevel@tonic-gate char *devp; 21260Sstevel@tonic-gate struct dirent *direntp; 21270Sstevel@tonic-gate int err; 21280Sstevel@tonic-gate int tmpfd; 21290Sstevel@tonic-gate 21300Sstevel@tonic-gate /* Get the devfs_path of the ffb devices */ 21310Sstevel@tonic-gate err = ptree_get_propval_by_name(ffbh, PICL_PROP_DEVFS_PATH, devfs_path, 21320Sstevel@tonic-gate sizeof (devfs_path)); 21330Sstevel@tonic-gate if (err != PICL_SUCCESS) 21340Sstevel@tonic-gate return (err); 21350Sstevel@tonic-gate 21360Sstevel@tonic-gate /* Get the device node name */ 21370Sstevel@tonic-gate devp = strrchr(devfs_path, '/'); 21380Sstevel@tonic-gate if (devp == NULL) 21390Sstevel@tonic-gate return (PICL_FAILURE); 21400Sstevel@tonic-gate *devp = '\0'; 21410Sstevel@tonic-gate ++devp; 21420Sstevel@tonic-gate 21430Sstevel@tonic-gate /* 21440Sstevel@tonic-gate * Check if device node name has the ffb string 21450Sstevel@tonic-gate * If not, assume it's not a ffb device. 21460Sstevel@tonic-gate */ 21470Sstevel@tonic-gate if (strstr(devp, FFB_NAME) == NULL) 21480Sstevel@tonic-gate return (PICL_FAILURE); 21490Sstevel@tonic-gate 21500Sstevel@tonic-gate /* 21510Sstevel@tonic-gate * Get the parent path of the ffb device node. 21520Sstevel@tonic-gate */ 21530Sstevel@tonic-gate (void) snprintf(dev_path, sizeof (dev_path), "%s/%s", "/devices", 21540Sstevel@tonic-gate devfs_path); 21550Sstevel@tonic-gate 21560Sstevel@tonic-gate /* 21570Sstevel@tonic-gate * Since we don't know ffb's minor nodename, 21580Sstevel@tonic-gate * we need to search all the devices under its 21590Sstevel@tonic-gate * parent dir by comparing the node name 21600Sstevel@tonic-gate */ 21610Sstevel@tonic-gate if ((dirp = opendir(dev_path)) == NULL) 21620Sstevel@tonic-gate return (PICL_FAILURE); 21630Sstevel@tonic-gate 21640Sstevel@tonic-gate while ((direntp = readdir(dirp)) != NULL) { 21650Sstevel@tonic-gate if (strstr(direntp->d_name, devp) != NULL) { 21660Sstevel@tonic-gate (void) strcat(dev_path, "/"); 21670Sstevel@tonic-gate (void) strcat(dev_path, direntp->d_name); 21680Sstevel@tonic-gate tmpfd = open(dev_path, O_RDWR); 21690Sstevel@tonic-gate if (tmpfd < 0) 21700Sstevel@tonic-gate continue; 21710Sstevel@tonic-gate *fd = tmpfd; 21720Sstevel@tonic-gate (void) closedir(dirp); 21730Sstevel@tonic-gate return (PICL_SUCCESS); 21740Sstevel@tonic-gate } 21750Sstevel@tonic-gate } 21760Sstevel@tonic-gate 21770Sstevel@tonic-gate (void) closedir(dirp); 21780Sstevel@tonic-gate return (PICL_FAILURE); 21790Sstevel@tonic-gate } 21800Sstevel@tonic-gate 21810Sstevel@tonic-gate /* 21820Sstevel@tonic-gate * This function recursively searches the tree for ffb display devices 21830Sstevel@tonic-gate * and add ffb config information 21840Sstevel@tonic-gate */ 21850Sstevel@tonic-gate static int 21860Sstevel@tonic-gate add_ffb_config_info(picl_nodehdl_t rooth) 21870Sstevel@tonic-gate { 21880Sstevel@tonic-gate picl_nodehdl_t nodeh; 21890Sstevel@tonic-gate int err; 21900Sstevel@tonic-gate char piclclass[PICL_CLASSNAMELEN_MAX]; 21910Sstevel@tonic-gate char manfidbuf[FFB_MANUF_BUFSIZE]; 21920Sstevel@tonic-gate int fd; 21930Sstevel@tonic-gate int board_rev; 21940Sstevel@tonic-gate ffb_sys_info_t fsi; 21950Sstevel@tonic-gate ptree_propinfo_t pinfo; 21960Sstevel@tonic-gate 21970Sstevel@tonic-gate for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh, 21980Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 21995028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, 22005028Sfw157321 &nodeh, sizeof (picl_nodehdl_t))) { 22010Sstevel@tonic-gate 22020Sstevel@tonic-gate if (err != PICL_SUCCESS) 22030Sstevel@tonic-gate return (err); 22040Sstevel@tonic-gate 22050Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 22060Sstevel@tonic-gate piclclass, PICL_CLASSNAMELEN_MAX); 22070Sstevel@tonic-gate 22080Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 22090Sstevel@tonic-gate (strcmp(piclclass, PICL_CLASS_DISPLAY) == 0)) { 22100Sstevel@tonic-gate 22110Sstevel@tonic-gate err = open_ffb_device(nodeh, &fd); 22120Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 22130Sstevel@tonic-gate (ioctl(fd, FFB_SYS_INFO, &fsi) >= 0)) { 22140Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 22150Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 22160Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, 22170Sstevel@tonic-gate sizeof (int), PICL_PROP_FFB_BOARD_REV, 22180Sstevel@tonic-gate NULL, NULL); 22190Sstevel@tonic-gate board_rev = fsi.ffb_strap_bits.fld.board_rev; 22200Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 22210Sstevel@tonic-gate &board_rev, NULL); 22220Sstevel@tonic-gate 22230Sstevel@tonic-gate fmt_manf_id(fsi.dac_version, 22240Sstevel@tonic-gate sizeof (manfidbuf), manfidbuf); 22250Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 22260Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 22270Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 22280Sstevel@tonic-gate strlen(manfidbuf) + 1, 22290Sstevel@tonic-gate PICL_PROP_FFB_DAC_VER, NULL, NULL); 22300Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 22310Sstevel@tonic-gate manfidbuf, NULL); 22320Sstevel@tonic-gate 22330Sstevel@tonic-gate fmt_manf_id(fsi.fbram_version, 22340Sstevel@tonic-gate sizeof (manfidbuf), manfidbuf); 22350Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 22360Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 22370Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 22380Sstevel@tonic-gate strlen(manfidbuf) + 1, 22390Sstevel@tonic-gate PICL_PROP_FFB_FBRAM_VER, NULL, 22400Sstevel@tonic-gate NULL); 22410Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 22420Sstevel@tonic-gate manfidbuf, NULL); 22430Sstevel@tonic-gate (void) close(fd); 22440Sstevel@tonic-gate } 22450Sstevel@tonic-gate } else if (add_ffb_config_info(nodeh) != PICL_SUCCESS) 22460Sstevel@tonic-gate return (PICL_FAILURE); 22470Sstevel@tonic-gate } 22480Sstevel@tonic-gate return (PICL_SUCCESS); 22490Sstevel@tonic-gate } 22500Sstevel@tonic-gate 22510Sstevel@tonic-gate static conf_entries_t * 22520Sstevel@tonic-gate free_conf_entries(conf_entries_t *list) 22530Sstevel@tonic-gate { 22540Sstevel@tonic-gate conf_entries_t *el; 22550Sstevel@tonic-gate conf_entries_t *del; 22560Sstevel@tonic-gate 22570Sstevel@tonic-gate if (list == NULL) 22580Sstevel@tonic-gate return (NULL); 22590Sstevel@tonic-gate el = list; 22600Sstevel@tonic-gate while (el != NULL) { 22610Sstevel@tonic-gate del = el; 22620Sstevel@tonic-gate el = el->next; 22630Sstevel@tonic-gate free(del->name); 22640Sstevel@tonic-gate free(del->piclclass); 22650Sstevel@tonic-gate free(del); 22660Sstevel@tonic-gate } 22670Sstevel@tonic-gate return (el); 22680Sstevel@tonic-gate } 22690Sstevel@tonic-gate 22700Sstevel@tonic-gate /* 22710Sstevel@tonic-gate * Reading config order: platform, common 22720Sstevel@tonic-gate */ 22730Sstevel@tonic-gate static conf_entries_t * 22740Sstevel@tonic-gate read_conf_file(char *fname, conf_entries_t *list) 22750Sstevel@tonic-gate { 22760Sstevel@tonic-gate FILE *fp; 22770Sstevel@tonic-gate char lbuf[CONFFILE_LINELEN_MAX]; 22780Sstevel@tonic-gate char *nametok; 22790Sstevel@tonic-gate char *classtok; 22800Sstevel@tonic-gate conf_entries_t *el; 22810Sstevel@tonic-gate conf_entries_t *ptr; 22820Sstevel@tonic-gate 22830Sstevel@tonic-gate if (fname == NULL) 22840Sstevel@tonic-gate return (list); 22850Sstevel@tonic-gate 22860Sstevel@tonic-gate fp = fopen(fname, "r"); 22870Sstevel@tonic-gate 22880Sstevel@tonic-gate if (fp == NULL) 22890Sstevel@tonic-gate return (list); 22900Sstevel@tonic-gate 22910Sstevel@tonic-gate while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) { 22920Sstevel@tonic-gate if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n')) 22930Sstevel@tonic-gate continue; 22940Sstevel@tonic-gate 22950Sstevel@tonic-gate nametok = strtok(lbuf, " \t\n"); 22960Sstevel@tonic-gate if (nametok == NULL) 22970Sstevel@tonic-gate continue; 22980Sstevel@tonic-gate 22990Sstevel@tonic-gate classtok = strtok(NULL, " \t\n"); 23000Sstevel@tonic-gate if (classtok == NULL) 23010Sstevel@tonic-gate continue; 23020Sstevel@tonic-gate 23030Sstevel@tonic-gate el = malloc(sizeof (conf_entries_t)); 23040Sstevel@tonic-gate if (el == NULL) 23050Sstevel@tonic-gate break; 23060Sstevel@tonic-gate el->name = strdup(nametok); 23070Sstevel@tonic-gate el->piclclass = strdup(classtok); 23080Sstevel@tonic-gate if ((el->name == NULL) || (el->piclclass == NULL)) { 23090Sstevel@tonic-gate free(el); 23100Sstevel@tonic-gate return (list); 23110Sstevel@tonic-gate } 23120Sstevel@tonic-gate el->next = NULL; 23130Sstevel@tonic-gate 23140Sstevel@tonic-gate /* 23150Sstevel@tonic-gate * Add it to the end of list 23160Sstevel@tonic-gate */ 23170Sstevel@tonic-gate if (list == NULL) 23180Sstevel@tonic-gate list = el; 23190Sstevel@tonic-gate else { 23200Sstevel@tonic-gate ptr = list; 23210Sstevel@tonic-gate while (ptr->next != NULL) 23220Sstevel@tonic-gate ptr = ptr->next; 23230Sstevel@tonic-gate ptr->next = el; 23240Sstevel@tonic-gate } 23250Sstevel@tonic-gate 23260Sstevel@tonic-gate } 23270Sstevel@tonic-gate (void) fclose(fp); 23280Sstevel@tonic-gate return (list); 23290Sstevel@tonic-gate } 23300Sstevel@tonic-gate 23310Sstevel@tonic-gate /* 23320Sstevel@tonic-gate * Process the devtree conf file and set up the conf_name_class_map list 23330Sstevel@tonic-gate */ 23340Sstevel@tonic-gate static void 23350Sstevel@tonic-gate process_devtree_conf_file(void) 23360Sstevel@tonic-gate { 23370Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 23380Sstevel@tonic-gate char pname[PATH_MAX]; 23390Sstevel@tonic-gate 23400Sstevel@tonic-gate conf_name_class_map = NULL; 23410Sstevel@tonic-gate 23420Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 23430Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 23440Sstevel@tonic-gate (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX); 23450Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, 23460Sstevel@tonic-gate conf_name_class_map); 23470Sstevel@tonic-gate } 23480Sstevel@tonic-gate 23490Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 23500Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 23510Sstevel@tonic-gate (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX); 23520Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, 23530Sstevel@tonic-gate conf_name_class_map); 23540Sstevel@tonic-gate } 23550Sstevel@tonic-gate 23560Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR, 23570Sstevel@tonic-gate DEVTREE_CONFFILE_NAME); 23580Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, conf_name_class_map); 23590Sstevel@tonic-gate } 23600Sstevel@tonic-gate 23610Sstevel@tonic-gate static asr_conf_entries_t *conf_name_asr_map = NULL; 23620Sstevel@tonic-gate 23630Sstevel@tonic-gate static void 23640Sstevel@tonic-gate free_asr_conf_entries(asr_conf_entries_t *list) { 23650Sstevel@tonic-gate asr_conf_entries_t *el; 23660Sstevel@tonic-gate asr_conf_entries_t *del; 23670Sstevel@tonic-gate 23680Sstevel@tonic-gate el = list; 23690Sstevel@tonic-gate while (el != NULL) { 23700Sstevel@tonic-gate del = el; 23710Sstevel@tonic-gate el = el->next; 23720Sstevel@tonic-gate if (del->name) 23730Sstevel@tonic-gate free(del->name); 23740Sstevel@tonic-gate if (del->address) 23750Sstevel@tonic-gate free(del->address); 23760Sstevel@tonic-gate if (del->status) 23770Sstevel@tonic-gate free(del->status); 23780Sstevel@tonic-gate if (del->piclclass) 23790Sstevel@tonic-gate free(del->piclclass); 23800Sstevel@tonic-gate if (del->props) 23810Sstevel@tonic-gate free(del->props); 23820Sstevel@tonic-gate free(del); 23830Sstevel@tonic-gate } 23840Sstevel@tonic-gate } 23850Sstevel@tonic-gate 23860Sstevel@tonic-gate /* 23870Sstevel@tonic-gate * Reading config order: platform, common 23880Sstevel@tonic-gate */ 23890Sstevel@tonic-gate static asr_conf_entries_t * 23900Sstevel@tonic-gate read_asr_conf_file(char *fname, asr_conf_entries_t *list) 23910Sstevel@tonic-gate { 23920Sstevel@tonic-gate FILE *fp; 23930Sstevel@tonic-gate char lbuf[CONFFILE_LINELEN_MAX]; 23940Sstevel@tonic-gate char *nametok; 23950Sstevel@tonic-gate char *classtok; 23960Sstevel@tonic-gate char *statustok; 23970Sstevel@tonic-gate char *addresstok; 23980Sstevel@tonic-gate char *propstok; 23990Sstevel@tonic-gate asr_conf_entries_t *el; 24000Sstevel@tonic-gate asr_conf_entries_t *ptr; 24010Sstevel@tonic-gate 24020Sstevel@tonic-gate if (fname == NULL) 24030Sstevel@tonic-gate return (list); 24040Sstevel@tonic-gate 24050Sstevel@tonic-gate fp = fopen(fname, "r"); 24060Sstevel@tonic-gate if (fp == NULL) 24070Sstevel@tonic-gate return (list); 24080Sstevel@tonic-gate 24090Sstevel@tonic-gate while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) { 24100Sstevel@tonic-gate if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n')) 24110Sstevel@tonic-gate continue; 24120Sstevel@tonic-gate 24130Sstevel@tonic-gate nametok = strtok(lbuf, " \t\n"); 24140Sstevel@tonic-gate if (nametok == NULL) 24150Sstevel@tonic-gate continue; 24160Sstevel@tonic-gate 24170Sstevel@tonic-gate classtok = strtok(NULL, " \t\n"); 24180Sstevel@tonic-gate if (classtok == NULL) 24190Sstevel@tonic-gate continue; 24200Sstevel@tonic-gate 24210Sstevel@tonic-gate statustok = strtok(NULL, " \t\n"); 24220Sstevel@tonic-gate if (statustok == NULL) 24230Sstevel@tonic-gate continue; 24240Sstevel@tonic-gate 24250Sstevel@tonic-gate addresstok = strtok(NULL, " \t\n"); 24260Sstevel@tonic-gate if (addresstok == NULL) 24270Sstevel@tonic-gate continue; 24280Sstevel@tonic-gate 24290Sstevel@tonic-gate /* 24300Sstevel@tonic-gate * props are optional 24310Sstevel@tonic-gate */ 24320Sstevel@tonic-gate propstok = strtok(NULL, " \t\n"); 24330Sstevel@tonic-gate 24340Sstevel@tonic-gate el = malloc(sizeof (asr_conf_entries_t)); 24350Sstevel@tonic-gate if (el == NULL) 24360Sstevel@tonic-gate break; 24370Sstevel@tonic-gate el->name = strdup(nametok); 24380Sstevel@tonic-gate el->piclclass = strdup(classtok); 24390Sstevel@tonic-gate el->status = strdup(statustok); 24400Sstevel@tonic-gate el->address = strdup(addresstok); 24410Sstevel@tonic-gate if (propstok != NULL) 24420Sstevel@tonic-gate el->props = strdup(propstok); 24430Sstevel@tonic-gate else 24440Sstevel@tonic-gate el->props = NULL; 24450Sstevel@tonic-gate if ((el->name == NULL) || (el->piclclass == NULL) || 24460Sstevel@tonic-gate (el->address == NULL) || (el->status == NULL)) { 24470Sstevel@tonic-gate if (el->name) 24480Sstevel@tonic-gate free(el->name); 24490Sstevel@tonic-gate if (el->address) 24500Sstevel@tonic-gate free(el->address); 24510Sstevel@tonic-gate if (el->status) 24520Sstevel@tonic-gate free(el->status); 24530Sstevel@tonic-gate if (el->piclclass) 24540Sstevel@tonic-gate free(el->piclclass); 24550Sstevel@tonic-gate if (el->props) 24560Sstevel@tonic-gate free(el->props); 24570Sstevel@tonic-gate free(el); 24580Sstevel@tonic-gate break; 24590Sstevel@tonic-gate } 24600Sstevel@tonic-gate el->next = NULL; 24610Sstevel@tonic-gate 24620Sstevel@tonic-gate /* 24630Sstevel@tonic-gate * Add it to the end of list 24640Sstevel@tonic-gate */ 24650Sstevel@tonic-gate if (list == NULL) 24660Sstevel@tonic-gate list = el; 24670Sstevel@tonic-gate else { 24680Sstevel@tonic-gate ptr = list; 24690Sstevel@tonic-gate while (ptr->next != NULL) 24700Sstevel@tonic-gate ptr = ptr->next; 24710Sstevel@tonic-gate ptr->next = el; 24720Sstevel@tonic-gate } 24730Sstevel@tonic-gate 24740Sstevel@tonic-gate } 24750Sstevel@tonic-gate (void) fclose(fp); 24760Sstevel@tonic-gate return (list); 24770Sstevel@tonic-gate } 24780Sstevel@tonic-gate 24790Sstevel@tonic-gate /* 24800Sstevel@tonic-gate * Process the asr conf file 24810Sstevel@tonic-gate */ 24820Sstevel@tonic-gate static void 24830Sstevel@tonic-gate process_asrtree_conf_file(void) 24840Sstevel@tonic-gate { 24850Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 24860Sstevel@tonic-gate char pname[PATH_MAX]; 24870Sstevel@tonic-gate 24880Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 24890Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 24900Sstevel@tonic-gate (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX); 24910Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, 24925028Sfw157321 conf_name_asr_map); 24930Sstevel@tonic-gate } 24940Sstevel@tonic-gate 24950Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 24960Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 24970Sstevel@tonic-gate (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX); 24980Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, 24995028Sfw157321 conf_name_asr_map); 25000Sstevel@tonic-gate } 25010Sstevel@tonic-gate 25020Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR, 25030Sstevel@tonic-gate ASRTREE_CONFFILE_NAME); 25040Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, conf_name_asr_map); 25050Sstevel@tonic-gate } 25060Sstevel@tonic-gate 25070Sstevel@tonic-gate /* 25080Sstevel@tonic-gate * This function reads the export file list from ASR 25090Sstevel@tonic-gate */ 25100Sstevel@tonic-gate static int 25110Sstevel@tonic-gate get_asr_export_list(char **exportlist, int *exportlistlen) 25120Sstevel@tonic-gate { 25130Sstevel@tonic-gate struct openpromio oppbuf; 25140Sstevel@tonic-gate struct openpromio *opp = &oppbuf; 25150Sstevel@tonic-gate int d; 25160Sstevel@tonic-gate int listsize; 25170Sstevel@tonic-gate 25180Sstevel@tonic-gate d = open("/dev/openprom", O_RDWR); 25190Sstevel@tonic-gate if (d < 0) 25200Sstevel@tonic-gate return (0); 25210Sstevel@tonic-gate 25220Sstevel@tonic-gate if (ioctl(d, OPROMEXPORTLEN, opp) == -1) { 25230Sstevel@tonic-gate (void) close(d); 25240Sstevel@tonic-gate return (0); 25250Sstevel@tonic-gate } 25260Sstevel@tonic-gate listsize = opp->oprom_size; 25270Sstevel@tonic-gate opp = (struct openpromio *)malloc(sizeof (struct openpromio) + 25280Sstevel@tonic-gate listsize); 25290Sstevel@tonic-gate if (opp == NULL) { 25300Sstevel@tonic-gate (void) close(d); 25310Sstevel@tonic-gate return (0); 25320Sstevel@tonic-gate } 25330Sstevel@tonic-gate (void) memset(opp, '\0', sizeof (struct openpromio) + listsize); 25340Sstevel@tonic-gate opp->oprom_size = listsize; 25350Sstevel@tonic-gate if (ioctl(d, OPROMEXPORT, opp) == -1) { 25360Sstevel@tonic-gate free(opp); 25370Sstevel@tonic-gate (void) close(d); 25380Sstevel@tonic-gate return (0); 25390Sstevel@tonic-gate } 25400Sstevel@tonic-gate *exportlist = malloc(listsize); 25410Sstevel@tonic-gate if (*exportlist == NULL) { 25420Sstevel@tonic-gate free(opp); 25430Sstevel@tonic-gate (void) close(d); 25440Sstevel@tonic-gate return (0); 25450Sstevel@tonic-gate } 25460Sstevel@tonic-gate (void) memcpy(*exportlist, opp->oprom_array, opp->oprom_size); 25470Sstevel@tonic-gate free(opp); 25480Sstevel@tonic-gate *exportlistlen = opp->oprom_size; 25490Sstevel@tonic-gate (void) close(d); 25500Sstevel@tonic-gate return (1); 25510Sstevel@tonic-gate } 25520Sstevel@tonic-gate 25530Sstevel@tonic-gate /* 25540Sstevel@tonic-gate * Parses properties string, fills in triplet structure with first 25550Sstevel@tonic-gate * type, name, val triplet and returns pointer to next property. 25560Sstevel@tonic-gate * Returns NULL if no valid triplet found 25570Sstevel@tonic-gate * CAUTION: drops \0 characters over separator characters: if you 25580Sstevel@tonic-gate * want to parse the string twice, you'll have to take a copy. 25590Sstevel@tonic-gate */ 25600Sstevel@tonic-gate static char * 25610Sstevel@tonic-gate parse_props_string(char *props, asr_prop_triplet_t *triplet) 25620Sstevel@tonic-gate { 25630Sstevel@tonic-gate char *prop_name; 25640Sstevel@tonic-gate char *prop_val; 25650Sstevel@tonic-gate char *prop_next; 25660Sstevel@tonic-gate 25670Sstevel@tonic-gate prop_name = strchr(props, '?'); 25680Sstevel@tonic-gate if (prop_name == NULL) 25690Sstevel@tonic-gate return (NULL); 25700Sstevel@tonic-gate *prop_name++ = '\0'; 25710Sstevel@tonic-gate prop_val = strchr(prop_name, '='); 25720Sstevel@tonic-gate if (prop_val == NULL) 25730Sstevel@tonic-gate return (NULL); 25740Sstevel@tonic-gate *prop_val++ = '\0'; 25750Sstevel@tonic-gate triplet->proptype = props; 25760Sstevel@tonic-gate triplet->propname = prop_name; 25770Sstevel@tonic-gate triplet->propval = prop_val; 25780Sstevel@tonic-gate prop_next = strchr(prop_val, ':'); 25790Sstevel@tonic-gate if (prop_next == NULL) 25800Sstevel@tonic-gate return (prop_val - 1); 25810Sstevel@tonic-gate *prop_next++ = '\0'; 25820Sstevel@tonic-gate return (prop_next); 25830Sstevel@tonic-gate } 25840Sstevel@tonic-gate 25850Sstevel@tonic-gate static int 25860Sstevel@tonic-gate add_status_prop(picl_nodehdl_t chdh, char *status) 25870Sstevel@tonic-gate { 25880Sstevel@tonic-gate ptree_propinfo_t propinfo; 25890Sstevel@tonic-gate picl_prophdl_t proph; 25900Sstevel@tonic-gate int err; 25910Sstevel@tonic-gate 25920Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 25930Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(status) + 1, 25940Sstevel@tonic-gate PICL_PROP_STATUS, NULL, NULL); 25950Sstevel@tonic-gate if (err != PICL_SUCCESS) 25960Sstevel@tonic-gate return (err); 25970Sstevel@tonic-gate err = ptree_create_and_add_prop(chdh, &propinfo, status, &proph); 25980Sstevel@tonic-gate return (err); 25990Sstevel@tonic-gate } 26000Sstevel@tonic-gate 26010Sstevel@tonic-gate static void 26020Sstevel@tonic-gate create_asr_node(char *parent, char *child, char *unitaddr, char *class, 26030Sstevel@tonic-gate char *status, char *props) 26040Sstevel@tonic-gate { 26050Sstevel@tonic-gate char ptreepath[PATH_MAX]; 26060Sstevel@tonic-gate char nodename[PICL_PROPNAMELEN_MAX]; 26070Sstevel@tonic-gate char ua[MAX_UNIT_ADDRESS_LEN]; 26080Sstevel@tonic-gate char *props_copy = NULL; 26090Sstevel@tonic-gate char *next; 26100Sstevel@tonic-gate char *prop_string; 26110Sstevel@tonic-gate boolean_t found = B_FALSE; 26120Sstevel@tonic-gate picl_nodehdl_t nodeh; 26130Sstevel@tonic-gate picl_nodehdl_t chdh; 26140Sstevel@tonic-gate asr_prop_triplet_t triple; 26150Sstevel@tonic-gate ptree_propinfo_t propinfo; 26160Sstevel@tonic-gate picl_prophdl_t proph; 26170Sstevel@tonic-gate int val; 26180Sstevel@tonic-gate int err; 26190Sstevel@tonic-gate 26200Sstevel@tonic-gate (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX); 26210Sstevel@tonic-gate (void) strlcat(ptreepath, parent, PATH_MAX); 26220Sstevel@tonic-gate 26230Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS) 26240Sstevel@tonic-gate return; 26250Sstevel@tonic-gate /* 26260Sstevel@tonic-gate * see if the required child node already exists 26270Sstevel@tonic-gate */ 26280Sstevel@tonic-gate for (err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 26290Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 26300Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 26315028Sfw157321 sizeof (picl_nodehdl_t))) { 26320Sstevel@tonic-gate if (err != PICL_SUCCESS) 26330Sstevel@tonic-gate break; 26340Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_NAME, 26350Sstevel@tonic-gate (void *)nodename, PICL_PROPNAMELEN_MAX); 26360Sstevel@tonic-gate if (err != PICL_SUCCESS) 26370Sstevel@tonic-gate break; 26380Sstevel@tonic-gate if (strcmp(nodename, child) != 0) 26390Sstevel@tonic-gate continue; 26400Sstevel@tonic-gate /* 26410Sstevel@tonic-gate * found a candidate child node 26420Sstevel@tonic-gate */ 26430Sstevel@tonic-gate if (unitaddr) { 26440Sstevel@tonic-gate /* 26450Sstevel@tonic-gate * does it match the required unit address? 26460Sstevel@tonic-gate */ 26470Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 26480Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, ua, sizeof (ua)); 26490Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 26500Sstevel@tonic-gate continue; 26510Sstevel@tonic-gate if (err != PICL_SUCCESS) 26520Sstevel@tonic-gate break; 26530Sstevel@tonic-gate if (strcmp(unitaddr, ua) != 0) 26540Sstevel@tonic-gate continue; 26550Sstevel@tonic-gate } 26560Sstevel@tonic-gate if (props == NULL) { 26570Sstevel@tonic-gate next = ""; 26580Sstevel@tonic-gate } else if (props_copy == NULL) { 26590Sstevel@tonic-gate props_copy = strdup(props); 26600Sstevel@tonic-gate if (props_copy == NULL) 26610Sstevel@tonic-gate return; 26620Sstevel@tonic-gate next = props_copy; 26630Sstevel@tonic-gate } 26640Sstevel@tonic-gate while ((next = parse_props_string(next, &triple)) != NULL) { 26650Sstevel@tonic-gate err = ptree_get_prop_by_name(chdh, triple.propname, 26660Sstevel@tonic-gate &proph); 26670Sstevel@tonic-gate if (err != PICL_SUCCESS) 26680Sstevel@tonic-gate break; 26690Sstevel@tonic-gate err = ptree_get_propinfo(proph, &propinfo); 26700Sstevel@tonic-gate if (err != PICL_SUCCESS) 26710Sstevel@tonic-gate break; 26720Sstevel@tonic-gate err = PICL_FAILURE; 26730Sstevel@tonic-gate switch (propinfo.piclinfo.type) { 26740Sstevel@tonic-gate case PICL_PTYPE_INT: 26750Sstevel@tonic-gate case PICL_PTYPE_UNSIGNED_INT: 26760Sstevel@tonic-gate if (strcmp(triple.proptype, "I") != 0) 26770Sstevel@tonic-gate break; 26780Sstevel@tonic-gate err = ptree_get_propval(proph, (void *)&val, 26790Sstevel@tonic-gate sizeof (val)); 26800Sstevel@tonic-gate if (err != PICL_SUCCESS) 26810Sstevel@tonic-gate break; 26820Sstevel@tonic-gate if (val != atoi(triple.propval)) 26830Sstevel@tonic-gate err = PICL_FAILURE; 26840Sstevel@tonic-gate break; 26850Sstevel@tonic-gate case PICL_PTYPE_CHARSTRING: 26860Sstevel@tonic-gate if (strcmp(triple.proptype, "S") != 0) 26870Sstevel@tonic-gate break; 26880Sstevel@tonic-gate prop_string = malloc(propinfo.piclinfo.size); 26890Sstevel@tonic-gate if (prop_string == NULL) 26900Sstevel@tonic-gate break; 26910Sstevel@tonic-gate err = ptree_get_propval(proph, 26920Sstevel@tonic-gate (void *)prop_string, 26930Sstevel@tonic-gate propinfo.piclinfo.size); 26940Sstevel@tonic-gate if (err != PICL_SUCCESS) { 26950Sstevel@tonic-gate free(prop_string); 26960Sstevel@tonic-gate break; 26970Sstevel@tonic-gate } 26980Sstevel@tonic-gate if (strcmp(prop_string, triple.propval) != 0) 26990Sstevel@tonic-gate err = PICL_FAILURE; 27000Sstevel@tonic-gate free(prop_string); 27010Sstevel@tonic-gate break; 27020Sstevel@tonic-gate default: 27030Sstevel@tonic-gate break; 27040Sstevel@tonic-gate } 27050Sstevel@tonic-gate if (err != PICL_SUCCESS) { 27060Sstevel@tonic-gate break; 27070Sstevel@tonic-gate } 27080Sstevel@tonic-gate } 27090Sstevel@tonic-gate if (next == NULL) { 27100Sstevel@tonic-gate found = B_TRUE; 27110Sstevel@tonic-gate break; 27120Sstevel@tonic-gate } 27130Sstevel@tonic-gate } 27140Sstevel@tonic-gate if (props_copy) 27150Sstevel@tonic-gate free(props_copy); 27160Sstevel@tonic-gate if (found) { 27170Sstevel@tonic-gate /* 27180Sstevel@tonic-gate * does the pre-existing node have a status property? 27190Sstevel@tonic-gate */ 27200Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_STATUS, 27210Sstevel@tonic-gate ua, sizeof (ua)); 27220Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 27230Sstevel@tonic-gate (void) add_status_prop(chdh, status); 27240Sstevel@tonic-gate if (err != PICL_SUCCESS) 27250Sstevel@tonic-gate return; 27260Sstevel@tonic-gate if ((strcmp(ua, ASR_DISABLED) == 0) || 27270Sstevel@tonic-gate (strcmp(ua, ASR_FAILED) == 0) || 27280Sstevel@tonic-gate ((strcmp(status, ASR_DISABLED) != 0) && 27290Sstevel@tonic-gate (strcmp(status, ASR_FAILED) != 0))) { 27300Sstevel@tonic-gate return; 27310Sstevel@tonic-gate } 27320Sstevel@tonic-gate /* 27330Sstevel@tonic-gate * more urgent status now, so replace existing value 27340Sstevel@tonic-gate */ 27350Sstevel@tonic-gate err = ptree_get_prop_by_name(chdh, PICL_PROP_STATUS, &proph); 27360Sstevel@tonic-gate if (err != PICL_SUCCESS) 27370Sstevel@tonic-gate return; 27380Sstevel@tonic-gate (void) ptree_delete_prop(proph); 27390Sstevel@tonic-gate (void) ptree_destroy_prop(proph); 27400Sstevel@tonic-gate err = add_status_prop(chdh, status); 27410Sstevel@tonic-gate if (err != PICL_SUCCESS) 27420Sstevel@tonic-gate return; 27430Sstevel@tonic-gate return; 27440Sstevel@tonic-gate } 27450Sstevel@tonic-gate 27460Sstevel@tonic-gate /* 27470Sstevel@tonic-gate * typical case, node needs adding together with a set of properties 27480Sstevel@tonic-gate */ 27490Sstevel@tonic-gate if (ptree_create_and_add_node(nodeh, child, class, &chdh) == 27500Sstevel@tonic-gate PICL_SUCCESS) { 27510Sstevel@tonic-gate (void) add_status_prop(chdh, status); 27520Sstevel@tonic-gate if (unitaddr) { 27530Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 27540Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, 27550Sstevel@tonic-gate PICL_READ, strlen(unitaddr) + 1, 27560Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL); 27570Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, &propinfo, 27580Sstevel@tonic-gate unitaddr, &proph); 27590Sstevel@tonic-gate (void) strlcpy(ptreepath, parent, PATH_MAX); 27600Sstevel@tonic-gate (void) strlcat(ptreepath, "/", PATH_MAX); 27610Sstevel@tonic-gate (void) strlcat(ptreepath, child, PATH_MAX); 27620Sstevel@tonic-gate (void) strlcat(ptreepath, "@", PATH_MAX); 27630Sstevel@tonic-gate (void) strlcat(ptreepath, unitaddr, PATH_MAX); 27640Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 27650Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, 27660Sstevel@tonic-gate PICL_READ, strlen(ptreepath) + 1, 27670Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, NULL, NULL); 27680Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, &propinfo, 27690Sstevel@tonic-gate ptreepath, &proph); 27700Sstevel@tonic-gate } 27710Sstevel@tonic-gate next = props; 27720Sstevel@tonic-gate while ((next = parse_props_string(next, &triple)) != NULL) { 27730Sstevel@tonic-gate /* 27740Sstevel@tonic-gate * only handle int and string properties for 27750Sstevel@tonic-gate * simplicity 27760Sstevel@tonic-gate */ 27770Sstevel@tonic-gate if (strcmp(triple.proptype, "I") == 0) { 27780Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 27790Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 27800Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, 27810Sstevel@tonic-gate sizeof (int), triple.propname, NULL, NULL); 27820Sstevel@tonic-gate val = atoi(triple.propval); 27830Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, 27840Sstevel@tonic-gate &propinfo, &val, &proph); 27850Sstevel@tonic-gate } else { 27860Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 27870Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 27880Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 27890Sstevel@tonic-gate strlen(triple.propval) + 1, 27905028Sfw157321 triple.propname, NULL, NULL); 27910Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, 27920Sstevel@tonic-gate &propinfo, triple.propval, &proph); 27930Sstevel@tonic-gate } 27940Sstevel@tonic-gate } 27950Sstevel@tonic-gate } 27960Sstevel@tonic-gate } 27970Sstevel@tonic-gate 27980Sstevel@tonic-gate static void 27990Sstevel@tonic-gate add_asr_nodes() 28000Sstevel@tonic-gate { 28010Sstevel@tonic-gate char *asrexport; 28020Sstevel@tonic-gate int asrexportlen; 28030Sstevel@tonic-gate asr_conf_entries_t *c = NULL; 28040Sstevel@tonic-gate int i; 28050Sstevel@tonic-gate char *key; 28060Sstevel@tonic-gate char *child; 28070Sstevel@tonic-gate char *unitaddr; 28080Sstevel@tonic-gate uint16_t count; 28090Sstevel@tonic-gate int disabled; 28100Sstevel@tonic-gate 28110Sstevel@tonic-gate if (get_asr_export_list(&asrexport, &asrexportlen) == 0) 28120Sstevel@tonic-gate return; 28130Sstevel@tonic-gate process_asrtree_conf_file(); 28140Sstevel@tonic-gate if (conf_name_asr_map == NULL) 28150Sstevel@tonic-gate return; 28160Sstevel@tonic-gate i = 0; 28170Sstevel@tonic-gate while (i < asrexportlen) { 28180Sstevel@tonic-gate key = &asrexport[i]; 28190Sstevel@tonic-gate i += strlen(key) + 1; 28200Sstevel@tonic-gate if (i >= asrexportlen) 28210Sstevel@tonic-gate break; 28220Sstevel@tonic-gate 28230Sstevel@tonic-gate /* 28240Sstevel@tonic-gate * next byte tells us whether failed by diags or manually 28250Sstevel@tonic-gate * disabled 28260Sstevel@tonic-gate */ 28270Sstevel@tonic-gate disabled = asrexport[i]; 28280Sstevel@tonic-gate i++; 28290Sstevel@tonic-gate if (i >= asrexportlen) 28300Sstevel@tonic-gate break; 28310Sstevel@tonic-gate 28320Sstevel@tonic-gate /* 28330Sstevel@tonic-gate * only type 1 supported 28340Sstevel@tonic-gate */ 28350Sstevel@tonic-gate if (asrexport[i] != 1) 28360Sstevel@tonic-gate break; 28370Sstevel@tonic-gate i++; 28380Sstevel@tonic-gate if (i >= asrexportlen) 28390Sstevel@tonic-gate break; 28400Sstevel@tonic-gate 28410Sstevel@tonic-gate /* 28420Sstevel@tonic-gate * next two bytes give size of reason string 28430Sstevel@tonic-gate */ 28440Sstevel@tonic-gate count = (asrexport[i] << 8) | asrexport[i + 1]; 28450Sstevel@tonic-gate i += count + 2; 28460Sstevel@tonic-gate if (i > asrexportlen) 28470Sstevel@tonic-gate break; 28480Sstevel@tonic-gate 28490Sstevel@tonic-gate /* 28500Sstevel@tonic-gate * now look for key in conf file info 28510Sstevel@tonic-gate */ 28520Sstevel@tonic-gate c = conf_name_asr_map; 28530Sstevel@tonic-gate while (c != NULL) { 28540Sstevel@tonic-gate if (strcmp(key, c->name) == 0) { 28550Sstevel@tonic-gate child = strrchr(c->address, '/'); 28560Sstevel@tonic-gate *child++ = '\0'; 28570Sstevel@tonic-gate unitaddr = strchr(child, '@'); 28580Sstevel@tonic-gate if (unitaddr) 28590Sstevel@tonic-gate *unitaddr++ = '\0'; 28600Sstevel@tonic-gate if (strcmp(c->status, ASR_DISABLED) == 0) { 28610Sstevel@tonic-gate create_asr_node(c->address, child, 28620Sstevel@tonic-gate unitaddr, c->piclclass, disabled ? 28630Sstevel@tonic-gate ASR_DISABLED : ASR_FAILED, 28640Sstevel@tonic-gate c->props); 28650Sstevel@tonic-gate } else { 28660Sstevel@tonic-gate create_asr_node(c->address, child, 28670Sstevel@tonic-gate unitaddr, c->piclclass, c->status, 28680Sstevel@tonic-gate c->props); 28690Sstevel@tonic-gate } 28700Sstevel@tonic-gate } 28710Sstevel@tonic-gate c = c->next; 28720Sstevel@tonic-gate } 28730Sstevel@tonic-gate } 28740Sstevel@tonic-gate 28750Sstevel@tonic-gate free_asr_conf_entries(conf_name_asr_map); 28760Sstevel@tonic-gate free(asrexport); 28770Sstevel@tonic-gate } 28780Sstevel@tonic-gate 28790Sstevel@tonic-gate /* 28800Sstevel@tonic-gate * This function adds information to the /platform node 28810Sstevel@tonic-gate */ 28820Sstevel@tonic-gate static int 28830Sstevel@tonic-gate add_platform_info(picl_nodehdl_t plafh) 28840Sstevel@tonic-gate { 28850Sstevel@tonic-gate struct utsname uts_info; 28860Sstevel@tonic-gate int err; 28870Sstevel@tonic-gate ptree_propinfo_t propinfo; 28880Sstevel@tonic-gate picl_prophdl_t proph; 28890Sstevel@tonic-gate 28900Sstevel@tonic-gate if (uname(&uts_info) < 0) 28910Sstevel@tonic-gate return (PICL_FAILURE); 28920Sstevel@tonic-gate 28930Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 28940Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.sysname) + 1, 28950Sstevel@tonic-gate PICL_PROP_SYSNAME, NULL, NULL); 28960Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.sysname, 28970Sstevel@tonic-gate &proph); 28980Sstevel@tonic-gate if (err != PICL_SUCCESS) 28990Sstevel@tonic-gate return (err); 29000Sstevel@tonic-gate 29010Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 29020Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.nodename) + 1, 29030Sstevel@tonic-gate PICL_PROP_NODENAME, NULL, NULL); 29040Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.nodename, 29050Sstevel@tonic-gate &proph); 29060Sstevel@tonic-gate if (err != PICL_SUCCESS) 29070Sstevel@tonic-gate return (err); 29080Sstevel@tonic-gate 29090Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 29100Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.release) + 1, 29110Sstevel@tonic-gate PICL_PROP_RELEASE, NULL, NULL); 29120Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.release, 29130Sstevel@tonic-gate &proph); 29140Sstevel@tonic-gate if (err != PICL_SUCCESS) 29150Sstevel@tonic-gate return (err); 29160Sstevel@tonic-gate 29170Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 29180Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.version) + 1, 29190Sstevel@tonic-gate PICL_PROP_VERSION, NULL, NULL); 29200Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.version, 29210Sstevel@tonic-gate &proph); 29220Sstevel@tonic-gate if (err != PICL_SUCCESS) 29230Sstevel@tonic-gate return (err); 29240Sstevel@tonic-gate 29250Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 29260Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.machine) + 1, 29270Sstevel@tonic-gate PICL_PROP_MACHINE, NULL, NULL); 29280Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.machine, 29290Sstevel@tonic-gate &proph); 29300Sstevel@tonic-gate return (err); 29310Sstevel@tonic-gate } 29320Sstevel@tonic-gate 29330Sstevel@tonic-gate /* 29340Sstevel@tonic-gate * Get first 32-bit value from the reg property 29350Sstevel@tonic-gate */ 29360Sstevel@tonic-gate static int 29370Sstevel@tonic-gate get_first_reg_word(picl_nodehdl_t nodeh, uint32_t *regval) 29380Sstevel@tonic-gate { 29390Sstevel@tonic-gate int err; 29400Sstevel@tonic-gate uint32_t *regbuf; 29410Sstevel@tonic-gate picl_prophdl_t regh; 29420Sstevel@tonic-gate ptree_propinfo_t pinfo; 29430Sstevel@tonic-gate 29440Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 29450Sstevel@tonic-gate if (err != PICL_SUCCESS) /* no reg property */ 29460Sstevel@tonic-gate return (err); 29470Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 29480Sstevel@tonic-gate if (err != PICL_SUCCESS) 29490Sstevel@tonic-gate return (err); 29500Sstevel@tonic-gate if (pinfo.piclinfo.size < sizeof (uint32_t)) /* too small */ 29510Sstevel@tonic-gate return (PICL_FAILURE); 29520Sstevel@tonic-gate regbuf = alloca(pinfo.piclinfo.size); 29530Sstevel@tonic-gate if (regbuf == NULL) 29540Sstevel@tonic-gate return (PICL_FAILURE); 29550Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, pinfo.piclinfo.size); 29560Sstevel@tonic-gate if (err != PICL_SUCCESS) 29570Sstevel@tonic-gate return (err); 29580Sstevel@tonic-gate *regval = *regbuf; /* get first 32-bit value */ 29590Sstevel@tonic-gate return (PICL_SUCCESS); 29600Sstevel@tonic-gate } 29610Sstevel@tonic-gate 29620Sstevel@tonic-gate /* 29630Sstevel@tonic-gate * Get device ID from the reg property 29640Sstevel@tonic-gate */ 29650Sstevel@tonic-gate static int 29660Sstevel@tonic-gate get_device_id(picl_nodehdl_t nodeh, uint32_t *dev_id) 29670Sstevel@tonic-gate { 29680Sstevel@tonic-gate int err; 29690Sstevel@tonic-gate uint32_t regval; 29700Sstevel@tonic-gate 29710Sstevel@tonic-gate err = get_first_reg_word(nodeh, ®val); 29720Sstevel@tonic-gate if (err != PICL_SUCCESS) 29730Sstevel@tonic-gate return (err); 29740Sstevel@tonic-gate 29750Sstevel@tonic-gate *dev_id = PCI_DEVICE_ID(regval); 29760Sstevel@tonic-gate return (PICL_SUCCESS); 29770Sstevel@tonic-gate } 29780Sstevel@tonic-gate 29790Sstevel@tonic-gate /* 29800Sstevel@tonic-gate * add Slot property for children of SBUS node 29810Sstevel@tonic-gate */ 29820Sstevel@tonic-gate /* ARGSUSED */ 29830Sstevel@tonic-gate static int 29840Sstevel@tonic-gate add_sbus_slots(picl_nodehdl_t pcih, void *args) 29850Sstevel@tonic-gate { 29860Sstevel@tonic-gate picl_nodehdl_t nodeh; 29870Sstevel@tonic-gate uint32_t slot; 29880Sstevel@tonic-gate int err; 29890Sstevel@tonic-gate ptree_propinfo_t pinfo; 29900Sstevel@tonic-gate 29910Sstevel@tonic-gate for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 29920Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 29935028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 29945028Sfw157321 sizeof (picl_nodehdl_t))) { 29950Sstevel@tonic-gate if (err != PICL_SUCCESS) 29960Sstevel@tonic-gate return (err); 29970Sstevel@tonic-gate 29980Sstevel@tonic-gate if (get_first_reg_word(nodeh, &slot) != 0) 29990Sstevel@tonic-gate continue; 30000Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 30010Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t), 30020Sstevel@tonic-gate PICL_PROP_SLOT, NULL, NULL); 30030Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, &slot, NULL); 30040Sstevel@tonic-gate } 30050Sstevel@tonic-gate 30060Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 30070Sstevel@tonic-gate } 30080Sstevel@tonic-gate 30090Sstevel@tonic-gate /* 30100Sstevel@tonic-gate * This function creates a Slot property for SBUS child nodes 30110Sstevel@tonic-gate * which can be correlated with the slot they are plugged into 30120Sstevel@tonic-gate * on the motherboard. 30130Sstevel@tonic-gate */ 30140Sstevel@tonic-gate static int 30150Sstevel@tonic-gate set_sbus_slot(picl_nodehdl_t plafh) 30160Sstevel@tonic-gate { 30170Sstevel@tonic-gate int err; 30180Sstevel@tonic-gate 30190Sstevel@tonic-gate err = ptree_walk_tree_by_class(plafh, PICL_CLASS_SBUS, NULL, 30200Sstevel@tonic-gate add_sbus_slots); 30210Sstevel@tonic-gate 30220Sstevel@tonic-gate return (err); 30230Sstevel@tonic-gate } 30240Sstevel@tonic-gate 30250Sstevel@tonic-gate /* 3026944Svenki * add DeviceID property for children of PCI/PCIEX node 30270Sstevel@tonic-gate */ 30280Sstevel@tonic-gate /* ARGSUSED */ 30290Sstevel@tonic-gate static int 30300Sstevel@tonic-gate add_pci_deviceids(picl_nodehdl_t pcih, void *args) 30310Sstevel@tonic-gate { 30320Sstevel@tonic-gate picl_nodehdl_t nodeh; 30330Sstevel@tonic-gate uint32_t dev_id; 30340Sstevel@tonic-gate int err; 30350Sstevel@tonic-gate ptree_propinfo_t pinfo; 30360Sstevel@tonic-gate 30370Sstevel@tonic-gate for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 30380Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 30395028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 30405028Sfw157321 sizeof (picl_nodehdl_t))) { 30410Sstevel@tonic-gate if (err != PICL_SUCCESS) 30420Sstevel@tonic-gate return (err); 30430Sstevel@tonic-gate 30440Sstevel@tonic-gate if (get_device_id(nodeh, &dev_id) != 0) 30450Sstevel@tonic-gate continue; 30460Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 30470Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t), 30480Sstevel@tonic-gate PICL_PROP_DEVICE_ID, NULL, NULL); 30490Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, &dev_id, NULL); 30500Sstevel@tonic-gate } 30510Sstevel@tonic-gate 30520Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 30530Sstevel@tonic-gate } 30540Sstevel@tonic-gate 30550Sstevel@tonic-gate /* 3056944Svenki * This function creates a DeviceID property for PCI/PCIEX child nodes 30570Sstevel@tonic-gate * which can be correlated with the slot they are plugged into 30580Sstevel@tonic-gate * on the motherboard. 30590Sstevel@tonic-gate */ 3060944Svenki static void 3061944Svenki set_pci_pciex_deviceid(picl_nodehdl_t plafh) 30620Sstevel@tonic-gate { 3063944Svenki (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCI, NULL, 30640Sstevel@tonic-gate add_pci_deviceids); 30650Sstevel@tonic-gate 3066944Svenki (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, NULL, 3067944Svenki add_pci_deviceids); 30680Sstevel@tonic-gate } 30690Sstevel@tonic-gate 30700Sstevel@tonic-gate /* 30710Sstevel@tonic-gate * Default UnitAddress encode function 30720Sstevel@tonic-gate */ 30730Sstevel@tonic-gate static int 30740Sstevel@tonic-gate encode_default_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 30750Sstevel@tonic-gate { 30760Sstevel@tonic-gate int i, len; 30770Sstevel@tonic-gate 30780Sstevel@tonic-gate /* 30790Sstevel@tonic-gate * Encode UnitAddress as %a,%b,%c,...,%n 30800Sstevel@tonic-gate */ 30810Sstevel@tonic-gate if (addrcells < 1) 30820Sstevel@tonic-gate return (-1); 30830Sstevel@tonic-gate 30840Sstevel@tonic-gate len = snprintf(buf, sz, "%x", *regprop); 30850Sstevel@tonic-gate for (i = 1; i < addrcells && len < sz; i++) 30860Sstevel@tonic-gate len += snprintf(&buf[len], sz-len, ",%x", regprop[i]); 30870Sstevel@tonic-gate 30880Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 30890Sstevel@tonic-gate } 30900Sstevel@tonic-gate 30910Sstevel@tonic-gate /* 30920Sstevel@tonic-gate * UnitAddress encode function where the last component is not printed 30930Sstevel@tonic-gate * unless non-zero. 30940Sstevel@tonic-gate */ 30950Sstevel@tonic-gate static int 30960Sstevel@tonic-gate encode_optional_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 30970Sstevel@tonic-gate { 30980Sstevel@tonic-gate int retval; 30990Sstevel@tonic-gate 31000Sstevel@tonic-gate /* 31010Sstevel@tonic-gate * Encode UnitAddress as %a,%b,%c,...,%n where the last component 31020Sstevel@tonic-gate * is printed only if non-zero. 31030Sstevel@tonic-gate */ 31040Sstevel@tonic-gate if (addrcells > 1 && regprop[addrcells-1] == 0) 31050Sstevel@tonic-gate retval = encode_default_unitaddr(buf, sz, regprop, addrcells-1); 31060Sstevel@tonic-gate else 31070Sstevel@tonic-gate retval = encode_default_unitaddr(buf, sz, regprop, addrcells); 31080Sstevel@tonic-gate 31090Sstevel@tonic-gate return (retval); 31100Sstevel@tonic-gate } 31110Sstevel@tonic-gate 31120Sstevel@tonic-gate 31130Sstevel@tonic-gate /* 31140Sstevel@tonic-gate * UnitAddress encode function for SCSI class of devices 31150Sstevel@tonic-gate */ 31160Sstevel@tonic-gate static int 31170Sstevel@tonic-gate encode_scsi_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 31180Sstevel@tonic-gate { 31190Sstevel@tonic-gate int len, retval; 31200Sstevel@tonic-gate 31210Sstevel@tonic-gate /* 31220Sstevel@tonic-gate * #address-cells Format 31230Sstevel@tonic-gate * 2 second component printed only if non-zero 31240Sstevel@tonic-gate * 31250Sstevel@tonic-gate * 4 regprop: phys_hi phys_lo lun_hi lun_lo 31260Sstevel@tonic-gate * UnitAddr: w<phys_hi><phys_lo>,<lun_lo> 31270Sstevel@tonic-gate */ 31280Sstevel@tonic-gate 31290Sstevel@tonic-gate if (addrcells == 2) { 31300Sstevel@tonic-gate retval = encode_optional_unitaddr(buf, sz, regprop, addrcells); 31310Sstevel@tonic-gate } else if (addrcells == 4) { 31320Sstevel@tonic-gate len = snprintf(buf, sz, "w%08x%08x,%x", regprop[0], regprop[1], 31330Sstevel@tonic-gate regprop[3]); 31340Sstevel@tonic-gate retval = (len >= sz) ? -1 : 0; 31350Sstevel@tonic-gate } else 31360Sstevel@tonic-gate retval = -1; 31370Sstevel@tonic-gate 31380Sstevel@tonic-gate return (retval); 31390Sstevel@tonic-gate } 31400Sstevel@tonic-gate 31410Sstevel@tonic-gate /* 31420Sstevel@tonic-gate * UnitAddress encode function for UPA devices 31430Sstevel@tonic-gate */ 31440Sstevel@tonic-gate static int 31450Sstevel@tonic-gate encode_upa_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 31460Sstevel@tonic-gate { 31470Sstevel@tonic-gate int len; 31480Sstevel@tonic-gate 31490Sstevel@tonic-gate if (addrcells != 2) 31500Sstevel@tonic-gate return (-1); 31510Sstevel@tonic-gate 31520Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", (regprop[0]/2)&0x1f, regprop[1]); 31530Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 31540Sstevel@tonic-gate } 31550Sstevel@tonic-gate 31560Sstevel@tonic-gate /* 31570Sstevel@tonic-gate * UnitAddress encode function for GPTWO, JBUS devices 31580Sstevel@tonic-gate */ 31590Sstevel@tonic-gate static int 31600Sstevel@tonic-gate encode_gptwo_jbus_unitaddr(char *buf, int sz, uint32_t *regprop, 31610Sstevel@tonic-gate uint_t addrcells) 31620Sstevel@tonic-gate { 31630Sstevel@tonic-gate uint32_t hi, lo; 31640Sstevel@tonic-gate int len, id, off; 31650Sstevel@tonic-gate 31660Sstevel@tonic-gate if (addrcells != 2) 31670Sstevel@tonic-gate return (-1); 31680Sstevel@tonic-gate 31690Sstevel@tonic-gate hi = regprop[0]; 31700Sstevel@tonic-gate lo = regprop[1]; 31710Sstevel@tonic-gate 31720Sstevel@tonic-gate if (hi & 0x400) { 31730Sstevel@tonic-gate id = ((hi & 0x1) << 9) | (lo >> 23); /* agent id */ 31740Sstevel@tonic-gate off = lo & 0x7fffff; /* config offset */ 31750Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", id, off); 31760Sstevel@tonic-gate } else { 31770Sstevel@tonic-gate len = snprintf(buf, sz, "m%x,%x", hi, lo); 31780Sstevel@tonic-gate } 31790Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 31800Sstevel@tonic-gate } 31810Sstevel@tonic-gate 31820Sstevel@tonic-gate /* 31830Sstevel@tonic-gate * UnitAddress encode function for PCI devices 31840Sstevel@tonic-gate */ 31850Sstevel@tonic-gate static int 31860Sstevel@tonic-gate encode_pci_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 31870Sstevel@tonic-gate { 31880Sstevel@tonic-gate typedef struct { 31890Sstevel@tonic-gate uint32_t n:1, /* relocatable */ 31900Sstevel@tonic-gate p:1, /* prefetchable */ 31910Sstevel@tonic-gate t:1, /* address region aliases */ 31920Sstevel@tonic-gate zero:3, /* must be zero */ 31930Sstevel@tonic-gate ss:2, /* address space type */ 31940Sstevel@tonic-gate bus:8, /* bus number */ 31950Sstevel@tonic-gate dev:5, /* device number */ 31960Sstevel@tonic-gate fn:3, /* function number */ 31970Sstevel@tonic-gate reg:8; /* register number */ 31980Sstevel@tonic-gate uint32_t phys_hi; /* high physical address */ 31990Sstevel@tonic-gate uint32_t phys_lo; /* low physical address */ 32000Sstevel@tonic-gate } pci_addrcell_t; 32010Sstevel@tonic-gate 32020Sstevel@tonic-gate pci_addrcell_t *p; 32030Sstevel@tonic-gate int len; 32040Sstevel@tonic-gate 32050Sstevel@tonic-gate if (addrcells != 3) 32060Sstevel@tonic-gate return (-1); 32070Sstevel@tonic-gate 32080Sstevel@tonic-gate p = (pci_addrcell_t *)regprop; 32090Sstevel@tonic-gate switch (p->ss) { 32100Sstevel@tonic-gate case 0: /* Config */ 32110Sstevel@tonic-gate if (p->fn) 32120Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", p->dev, p->fn); 32130Sstevel@tonic-gate else 32140Sstevel@tonic-gate len = snprintf(buf, sz, "%x", p->dev); 32150Sstevel@tonic-gate break; 32160Sstevel@tonic-gate case 1: /* IO */ 32170Sstevel@tonic-gate len = snprintf(buf, sz, "i%x,%x,%x,%x", p->dev, p->fn, p->reg, 32180Sstevel@tonic-gate p->phys_lo); 32190Sstevel@tonic-gate break; 32200Sstevel@tonic-gate case 2: /* Mem32 */ 32210Sstevel@tonic-gate len = snprintf(buf, sz, "m%x,%x,%x,%x", p->dev, p->fn, p->reg, 32220Sstevel@tonic-gate p->phys_lo); 32230Sstevel@tonic-gate break; 32240Sstevel@tonic-gate case 3: /* Mem64 */ 32250Sstevel@tonic-gate len = snprintf(buf, sz, "x%x,%x,%x,%x%08x", p->dev, p->fn, 32260Sstevel@tonic-gate p->reg, p->phys_hi, p->phys_lo); 32270Sstevel@tonic-gate break; 32280Sstevel@tonic-gate } 32290Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 32300Sstevel@tonic-gate } 32310Sstevel@tonic-gate 32320Sstevel@tonic-gate /* 32330Sstevel@tonic-gate * Get #address-cells property value 32340Sstevel@tonic-gate */ 32350Sstevel@tonic-gate static uint_t 32360Sstevel@tonic-gate get_addrcells_prop(picl_nodehdl_t nodeh) 32370Sstevel@tonic-gate { 32380Sstevel@tonic-gate int len, err; 32390Sstevel@tonic-gate uint32_t addrcells; 32400Sstevel@tonic-gate ptree_propinfo_t pinfo; 32410Sstevel@tonic-gate picl_prophdl_t proph; 32420Sstevel@tonic-gate 32430Sstevel@tonic-gate /* 32440Sstevel@tonic-gate * Get #address-cells property. If not present, use default value. 32450Sstevel@tonic-gate */ 32460Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_PROP_ADDRESS_CELLS, &proph); 32470Sstevel@tonic-gate if (err == PICL_SUCCESS) 32480Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 32490Sstevel@tonic-gate 32500Sstevel@tonic-gate len = pinfo.piclinfo.size; 32510Sstevel@tonic-gate if (err == PICL_SUCCESS && len >= sizeof (uint8_t) && 32520Sstevel@tonic-gate len <= sizeof (addrcells)) { 32530Sstevel@tonic-gate err = ptree_get_propval(proph, &addrcells, len); 32540Sstevel@tonic-gate if (err == PICL_SUCCESS) { 32550Sstevel@tonic-gate if (len == sizeof (uint8_t)) 32560Sstevel@tonic-gate addrcells = *(uint8_t *)&addrcells; 32570Sstevel@tonic-gate else if (len == sizeof (uint16_t)) 32580Sstevel@tonic-gate addrcells = *(uint16_t *)&addrcells; 32590Sstevel@tonic-gate } else 32600Sstevel@tonic-gate addrcells = DEFAULT_ADDRESS_CELLS; 32610Sstevel@tonic-gate } else 32620Sstevel@tonic-gate addrcells = DEFAULT_ADDRESS_CELLS; 32630Sstevel@tonic-gate 32640Sstevel@tonic-gate return (addrcells); 32650Sstevel@tonic-gate } 32660Sstevel@tonic-gate 32670Sstevel@tonic-gate /* 32680Sstevel@tonic-gate * Get UnitAddress mapping entry for a node 32690Sstevel@tonic-gate */ 32700Sstevel@tonic-gate static unitaddr_map_t * 32710Sstevel@tonic-gate get_unitaddr_mapping(picl_nodehdl_t nodeh) 32720Sstevel@tonic-gate { 32730Sstevel@tonic-gate int err; 32740Sstevel@tonic-gate unitaddr_map_t *uamap; 32750Sstevel@tonic-gate char clname[PICL_CLASSNAMELEN_MAX]; 32760Sstevel@tonic-gate 32770Sstevel@tonic-gate /* 32780Sstevel@tonic-gate * Get my classname and locate a function to translate "reg" prop 32790Sstevel@tonic-gate * into "UnitAddress" prop for my children. 32800Sstevel@tonic-gate */ 32810Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, clname, 32820Sstevel@tonic-gate sizeof (clname)); 32830Sstevel@tonic-gate if (err != PICL_SUCCESS) 32840Sstevel@tonic-gate (void) strcpy(clname, ""); /* NULL class name */ 32850Sstevel@tonic-gate 32860Sstevel@tonic-gate for (uamap = &unitaddr_map_table[0]; uamap->class != NULL; uamap++) 32870Sstevel@tonic-gate if (strcmp(clname, uamap->class) == 0) 32880Sstevel@tonic-gate break; 32890Sstevel@tonic-gate 32900Sstevel@tonic-gate return (uamap); 32910Sstevel@tonic-gate } 32920Sstevel@tonic-gate 32930Sstevel@tonic-gate /* 32940Sstevel@tonic-gate * Add UnitAddress property to the specified node 32950Sstevel@tonic-gate */ 32960Sstevel@tonic-gate static int 32970Sstevel@tonic-gate add_unitaddr_prop(picl_nodehdl_t nodeh, unitaddr_map_t *uamap, uint_t addrcells) 32980Sstevel@tonic-gate { 32990Sstevel@tonic-gate int regproplen, err; 33000Sstevel@tonic-gate uint32_t *regbuf; 33010Sstevel@tonic-gate picl_prophdl_t regh; 33020Sstevel@tonic-gate ptree_propinfo_t pinfo; 33030Sstevel@tonic-gate char unitaddr[MAX_UNIT_ADDRESS_LEN]; 33040Sstevel@tonic-gate 33050Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 33060Sstevel@tonic-gate if (err != PICL_SUCCESS) 33070Sstevel@tonic-gate return (err); 33080Sstevel@tonic-gate 33090Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 33100Sstevel@tonic-gate if (err != PICL_SUCCESS) 33110Sstevel@tonic-gate return (PICL_FAILURE); 33120Sstevel@tonic-gate 33130Sstevel@tonic-gate if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t))) 33140Sstevel@tonic-gate return (PICL_FAILURE); 33150Sstevel@tonic-gate 33160Sstevel@tonic-gate regproplen = pinfo.piclinfo.size; 33170Sstevel@tonic-gate regbuf = alloca(regproplen); 33180Sstevel@tonic-gate if (regbuf == NULL) 33190Sstevel@tonic-gate return (PICL_FAILURE); 33200Sstevel@tonic-gate 33210Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, regproplen); 33220Sstevel@tonic-gate if (err != PICL_SUCCESS || uamap->func == NULL || 33230Sstevel@tonic-gate (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) || 33240Sstevel@tonic-gate (uamap->func)(unitaddr, sizeof (unitaddr), regbuf, 33250Sstevel@tonic-gate addrcells) != 0) { 33260Sstevel@tonic-gate return (PICL_FAILURE); 33270Sstevel@tonic-gate } 33280Sstevel@tonic-gate 33290Sstevel@tonic-gate err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 33300Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(unitaddr)+1, 33310Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL); 33320Sstevel@tonic-gate if (err == PICL_SUCCESS) 33330Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &pinfo, unitaddr, NULL); 33340Sstevel@tonic-gate 33350Sstevel@tonic-gate return (err); 33360Sstevel@tonic-gate } 33370Sstevel@tonic-gate 33380Sstevel@tonic-gate /* 33390Sstevel@tonic-gate * work out UnitAddress property of the specified node 33400Sstevel@tonic-gate */ 33410Sstevel@tonic-gate static int 33420Sstevel@tonic-gate get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh, char *unitaddr, 33430Sstevel@tonic-gate size_t ualen) 33440Sstevel@tonic-gate { 33450Sstevel@tonic-gate int regproplen, err; 33460Sstevel@tonic-gate uint32_t *regbuf; 33470Sstevel@tonic-gate picl_prophdl_t regh; 33480Sstevel@tonic-gate ptree_propinfo_t pinfo; 33490Sstevel@tonic-gate unitaddr_map_t *uamap; 33500Sstevel@tonic-gate uint32_t addrcells; 33510Sstevel@tonic-gate 33520Sstevel@tonic-gate addrcells = get_addrcells_prop(parh); 33530Sstevel@tonic-gate uamap = get_unitaddr_mapping(parh); 33540Sstevel@tonic-gate 33550Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 33560Sstevel@tonic-gate if (err != PICL_SUCCESS) 33570Sstevel@tonic-gate return (err); 33580Sstevel@tonic-gate 33590Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 33600Sstevel@tonic-gate if (err != PICL_SUCCESS) 33610Sstevel@tonic-gate return (err); 33620Sstevel@tonic-gate 33630Sstevel@tonic-gate if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t))) 33640Sstevel@tonic-gate return (PICL_FAILURE); 33650Sstevel@tonic-gate 33660Sstevel@tonic-gate regproplen = pinfo.piclinfo.size; 33670Sstevel@tonic-gate regbuf = alloca(regproplen); 33680Sstevel@tonic-gate if (regbuf == NULL) 33690Sstevel@tonic-gate return (PICL_FAILURE); 33700Sstevel@tonic-gate 33710Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, regproplen); 33720Sstevel@tonic-gate if (err != PICL_SUCCESS || uamap->func == NULL || 33730Sstevel@tonic-gate (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) || 33740Sstevel@tonic-gate (uamap->func)(unitaddr, ualen, regbuf, addrcells) != 0) { 33750Sstevel@tonic-gate return (PICL_FAILURE); 33760Sstevel@tonic-gate } 33770Sstevel@tonic-gate return (PICL_SUCCESS); 33780Sstevel@tonic-gate } 33790Sstevel@tonic-gate 33800Sstevel@tonic-gate /* 33810Sstevel@tonic-gate * Add UnitAddress property to all children of the specified node 33820Sstevel@tonic-gate */ 33830Sstevel@tonic-gate static int 33840Sstevel@tonic-gate add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh) 33850Sstevel@tonic-gate { 33860Sstevel@tonic-gate int err; 33870Sstevel@tonic-gate picl_nodehdl_t chdh; 33880Sstevel@tonic-gate unitaddr_map_t *uamap; 33890Sstevel@tonic-gate uint32_t addrcells; 33900Sstevel@tonic-gate 33910Sstevel@tonic-gate /* 33920Sstevel@tonic-gate * Get #address-cells and unit address mapping entry for my 33930Sstevel@tonic-gate * node's class 33940Sstevel@tonic-gate */ 33950Sstevel@tonic-gate addrcells = get_addrcells_prop(nodeh); 33960Sstevel@tonic-gate uamap = get_unitaddr_mapping(nodeh); 33970Sstevel@tonic-gate 33980Sstevel@tonic-gate /* 33990Sstevel@tonic-gate * Add UnitAddress property to my children and their subtree 34000Sstevel@tonic-gate */ 34010Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 34020Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 34030Sstevel@tonic-gate 34040Sstevel@tonic-gate while (err == PICL_SUCCESS) { 34050Sstevel@tonic-gate (void) add_unitaddr_prop(chdh, uamap, addrcells); 34060Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(chdh); 34070Sstevel@tonic-gate 34080Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 34090Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 34100Sstevel@tonic-gate } 34110Sstevel@tonic-gate 34120Sstevel@tonic-gate return (PICL_SUCCESS); 34130Sstevel@tonic-gate } 34140Sstevel@tonic-gate 34150Sstevel@tonic-gate static int 34160Sstevel@tonic-gate update_memory_size_prop(picl_nodehdl_t plafh) 34170Sstevel@tonic-gate { 34180Sstevel@tonic-gate picl_nodehdl_t memh; 34190Sstevel@tonic-gate picl_prophdl_t proph; 34200Sstevel@tonic-gate ptree_propinfo_t pinfo; 34210Sstevel@tonic-gate int err, nspecs, snum, pval; 34220Sstevel@tonic-gate char *regbuf; 34230Sstevel@tonic-gate memspecs_t *mspecs; 34240Sstevel@tonic-gate uint64_t memsize; 34250Sstevel@tonic-gate 34260Sstevel@tonic-gate /* 34270Sstevel@tonic-gate * check if the #size-cells of the platform node is 2 34280Sstevel@tonic-gate */ 34290Sstevel@tonic-gate err = ptree_get_propval_by_name(plafh, OBP_PROP_SIZE_CELLS, &pval, 34305028Sfw157321 sizeof (pval)); 34310Sstevel@tonic-gate 34320Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 34330Sstevel@tonic-gate pval = SUPPORTED_NUM_CELL_SIZE; 34340Sstevel@tonic-gate else if (err != PICL_SUCCESS) 34350Sstevel@tonic-gate return (err); 34360Sstevel@tonic-gate 34370Sstevel@tonic-gate /* 34380Sstevel@tonic-gate * don't know how to handle other vals 34390Sstevel@tonic-gate */ 34400Sstevel@tonic-gate if (pval != SUPPORTED_NUM_CELL_SIZE) 34410Sstevel@tonic-gate return (PICL_FAILURE); 34420Sstevel@tonic-gate 34430Sstevel@tonic-gate err = ptree_get_node_by_path(MEMORY_PATH, &memh); 34440Sstevel@tonic-gate if (err != PICL_SUCCESS) 34450Sstevel@tonic-gate return (err); 34460Sstevel@tonic-gate 34470Sstevel@tonic-gate /* 34480Sstevel@tonic-gate * Get the REG property to calculate the size of memory 34490Sstevel@tonic-gate */ 34500Sstevel@tonic-gate err = ptree_get_prop_by_name(memh, OBP_REG, &proph); 34510Sstevel@tonic-gate if (err != PICL_SUCCESS) 34520Sstevel@tonic-gate return (err); 34530Sstevel@tonic-gate 34540Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 34550Sstevel@tonic-gate if (err != PICL_SUCCESS) 34560Sstevel@tonic-gate return (err); 34570Sstevel@tonic-gate 34580Sstevel@tonic-gate regbuf = alloca(pinfo.piclinfo.size); 34590Sstevel@tonic-gate if (regbuf == NULL) 34600Sstevel@tonic-gate return (PICL_FAILURE); 34610Sstevel@tonic-gate 34620Sstevel@tonic-gate err = ptree_get_propval(proph, regbuf, pinfo.piclinfo.size); 34630Sstevel@tonic-gate if (err != PICL_SUCCESS) 34640Sstevel@tonic-gate return (err); 34650Sstevel@tonic-gate 34660Sstevel@tonic-gate mspecs = (memspecs_t *)regbuf; 34670Sstevel@tonic-gate nspecs = pinfo.piclinfo.size / sizeof (memspecs_t); 34680Sstevel@tonic-gate 34690Sstevel@tonic-gate memsize = 0; 34700Sstevel@tonic-gate for (snum = 0; snum < nspecs; ++snum) 34710Sstevel@tonic-gate memsize += mspecs[snum].size; 34720Sstevel@tonic-gate 34730Sstevel@tonic-gate err = ptree_get_prop_by_name(memh, PICL_PROP_SIZE, &proph); 34740Sstevel@tonic-gate if (err == PICL_SUCCESS) { 34750Sstevel@tonic-gate err = ptree_update_propval(proph, &memsize, sizeof (memsize)); 34760Sstevel@tonic-gate return (err); 34770Sstevel@tonic-gate } 34780Sstevel@tonic-gate 34790Sstevel@tonic-gate /* 34800Sstevel@tonic-gate * Add the size property 34810Sstevel@tonic-gate */ 34820Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 34835028Sfw157321 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (memsize), 34845028Sfw157321 PICL_PROP_SIZE, NULL, NULL); 34850Sstevel@tonic-gate err = ptree_create_and_add_prop(memh, &pinfo, &memsize, NULL); 34860Sstevel@tonic-gate return (err); 34870Sstevel@tonic-gate } 34880Sstevel@tonic-gate 34890Sstevel@tonic-gate /* 34900Sstevel@tonic-gate * This function is executed as part of .init when the plugin is 34910Sstevel@tonic-gate * dlopen()ed 34920Sstevel@tonic-gate */ 34930Sstevel@tonic-gate static void 34940Sstevel@tonic-gate picldevtree_register(void) 34950Sstevel@tonic-gate { 34960Sstevel@tonic-gate if (getenv(SUNW_PICLDEVTREE_PLUGIN_DEBUG)) 34970Sstevel@tonic-gate picldevtree_debug = 1; 34980Sstevel@tonic-gate (void) picld_plugin_register(&my_reg_info); 34990Sstevel@tonic-gate } 35000Sstevel@tonic-gate 35010Sstevel@tonic-gate /* 35020Sstevel@tonic-gate * This function is the init entry point of the plugin. 35030Sstevel@tonic-gate * It initializes the /platform tree based on libdevinfo 35040Sstevel@tonic-gate */ 35050Sstevel@tonic-gate static void 35060Sstevel@tonic-gate picldevtree_init(void) 35070Sstevel@tonic-gate { 35080Sstevel@tonic-gate picl_nodehdl_t rhdl; 35090Sstevel@tonic-gate int err; 35100Sstevel@tonic-gate struct utsname utsname; 35110Sstevel@tonic-gate picl_nodehdl_t plafh; 35120Sstevel@tonic-gate 35130Sstevel@tonic-gate if (uname(&utsname) < 0) 35140Sstevel@tonic-gate return; 35150Sstevel@tonic-gate 35160Sstevel@tonic-gate (void) strcpy(mach_name, utsname.machine); 35170Sstevel@tonic-gate 35180Sstevel@tonic-gate if (strcmp(mach_name, "sun4u") == 0) { 35190Sstevel@tonic-gate builtin_map_ptr = sun4u_map; 35200Sstevel@tonic-gate builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t); 35213941Svenki } else if (strcmp(mach_name, "sun4v") == 0) { 35223941Svenki builtin_map_ptr = sun4u_map; 35233941Svenki builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t); 35240Sstevel@tonic-gate } else if (strcmp(mach_name, "i86pc") == 0) { 35250Sstevel@tonic-gate builtin_map_ptr = i86pc_map; 35260Sstevel@tonic-gate builtin_map_size = sizeof (i86pc_map) / sizeof (builtin_map_t); 35270Sstevel@tonic-gate } else { 35280Sstevel@tonic-gate builtin_map_ptr = NULL; 35290Sstevel@tonic-gate builtin_map_size = 0; 35300Sstevel@tonic-gate } 35310Sstevel@tonic-gate 35320Sstevel@tonic-gate err = ptree_get_root(&rhdl); 35330Sstevel@tonic-gate if (err != PICL_SUCCESS) { 35340Sstevel@tonic-gate syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED); 35350Sstevel@tonic-gate return; 35360Sstevel@tonic-gate } 35370Sstevel@tonic-gate 35380Sstevel@tonic-gate process_devtree_conf_file(); 35390Sstevel@tonic-gate 35400Sstevel@tonic-gate if (libdevinfo_init(rhdl) != PICL_SUCCESS) { 35410Sstevel@tonic-gate syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED); 35420Sstevel@tonic-gate return; 35430Sstevel@tonic-gate } 35440Sstevel@tonic-gate 35450Sstevel@tonic-gate err = ptree_get_node_by_path(PLATFORM_PATH, &plafh); 35460Sstevel@tonic-gate if (err != PICL_SUCCESS) 35470Sstevel@tonic-gate return; 35480Sstevel@tonic-gate 35490Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(plafh); 35500Sstevel@tonic-gate 35510Sstevel@tonic-gate add_asr_nodes(); 35520Sstevel@tonic-gate 35530Sstevel@tonic-gate (void) update_memory_size_prop(plafh); 35540Sstevel@tonic-gate 35550Sstevel@tonic-gate (void) setup_cpus(plafh); 35560Sstevel@tonic-gate 35570Sstevel@tonic-gate (void) add_ffb_config_info(plafh); 35580Sstevel@tonic-gate 35590Sstevel@tonic-gate (void) add_platform_info(plafh); 35600Sstevel@tonic-gate 3561944Svenki set_pci_pciex_deviceid(plafh); 35620Sstevel@tonic-gate 35630Sstevel@tonic-gate (void) set_sbus_slot(plafh); 35640Sstevel@tonic-gate 35650Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 35660Sstevel@tonic-gate picldevtree_evhandler, NULL); 35670Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 35680Sstevel@tonic-gate picldevtree_evhandler, NULL); 35695028Sfw157321 (void) ptree_register_handler(PICLEVENT_CPU_STATE_CHANGE, 35705028Sfw157321 picldevtree_evhandler, NULL); 3571*8200STrevor.Thompson@Sun.COM (void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE, 3572*8200STrevor.Thompson@Sun.COM picldevtree_evhandler, NULL); 35730Sstevel@tonic-gate } 35740Sstevel@tonic-gate 35750Sstevel@tonic-gate /* 35760Sstevel@tonic-gate * This function is the fini entry point of the plugin 35770Sstevel@tonic-gate */ 35780Sstevel@tonic-gate static void 35790Sstevel@tonic-gate picldevtree_fini(void) 35800Sstevel@tonic-gate { 35810Sstevel@tonic-gate /* First unregister the event handlers */ 35820Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 35830Sstevel@tonic-gate picldevtree_evhandler, NULL); 35840Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 35850Sstevel@tonic-gate picldevtree_evhandler, NULL); 35865028Sfw157321 (void) ptree_unregister_handler(PICLEVENT_CPU_STATE_CHANGE, 35875028Sfw157321 picldevtree_evhandler, NULL); 3588*8200STrevor.Thompson@Sun.COM (void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE, 3589*8200STrevor.Thompson@Sun.COM picldevtree_evhandler, NULL); 35900Sstevel@tonic-gate 35910Sstevel@tonic-gate conf_name_class_map = free_conf_entries(conf_name_class_map); 35920Sstevel@tonic-gate } 35930Sstevel@tonic-gate 35940Sstevel@tonic-gate /* 35950Sstevel@tonic-gate * This function is the event handler of this plug-in. 35960Sstevel@tonic-gate * 35970Sstevel@tonic-gate * It processes the following events: 35980Sstevel@tonic-gate * 35990Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_ADDED 36000Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_REMOVED 36015028Sfw157321 * PICLEVENT_CPU_STATE_CHANGE 3602*8200STrevor.Thompson@Sun.COM * PICLEVENT_DR_AP_STATE_CHANGE 36030Sstevel@tonic-gate */ 36040Sstevel@tonic-gate /* ARGSUSED */ 36050Sstevel@tonic-gate static void 36060Sstevel@tonic-gate picldevtree_evhandler(const char *ename, const void *earg, size_t size, 36070Sstevel@tonic-gate void *cookie) 36080Sstevel@tonic-gate { 36090Sstevel@tonic-gate char *devfs_path; 36100Sstevel@tonic-gate char ptreepath[PATH_MAX]; 36110Sstevel@tonic-gate char dipath[PATH_MAX]; 36120Sstevel@tonic-gate picl_nodehdl_t plafh; 36130Sstevel@tonic-gate picl_nodehdl_t nodeh; 36140Sstevel@tonic-gate nvlist_t *nvlp; 36150Sstevel@tonic-gate 3616*8200STrevor.Thompson@Sun.COM if ((earg == NULL) || 3617*8200STrevor.Thompson@Sun.COM (ptree_get_node_by_path(PLATFORM_PATH, &plafh) != PICL_SUCCESS)) 36180Sstevel@tonic-gate return; 36190Sstevel@tonic-gate 3620*8200STrevor.Thompson@Sun.COM if (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) == 0) { 3621*8200STrevor.Thompson@Sun.COM (void) setup_cpus(plafh); 3622*8200STrevor.Thompson@Sun.COM if (picldevtree_debug > 1) 3623*8200STrevor.Thompson@Sun.COM syslog(LOG_INFO, "picldevtree: event handler done\n"); 3624*8200STrevor.Thompson@Sun.COM return; 3625*8200STrevor.Thompson@Sun.COM } 3626*8200STrevor.Thompson@Sun.COM 36270Sstevel@tonic-gate nvlp = NULL; 3628*8200STrevor.Thompson@Sun.COM if (nvlist_unpack((char *)earg, size, &nvlp, NULL) || 36290Sstevel@tonic-gate nvlist_lookup_string(nvlp, PICLEVENTARG_DEVFS_PATH, &devfs_path) || 36300Sstevel@tonic-gate strlen(devfs_path) > (PATH_MAX - sizeof (PLATFORM_PATH))) { 36310Sstevel@tonic-gate syslog(LOG_INFO, PICL_EVENT_DROPPED, ename); 36320Sstevel@tonic-gate if (nvlp) 36330Sstevel@tonic-gate nvlist_free(nvlp); 36340Sstevel@tonic-gate return; 36350Sstevel@tonic-gate } 36360Sstevel@tonic-gate 36370Sstevel@tonic-gate (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX); 36380Sstevel@tonic-gate (void) strlcat(ptreepath, devfs_path, PATH_MAX); 36390Sstevel@tonic-gate (void) strlcpy(dipath, devfs_path, PATH_MAX); 36400Sstevel@tonic-gate nvlist_free(nvlp); 36410Sstevel@tonic-gate 36420Sstevel@tonic-gate if (picldevtree_debug) 36430Sstevel@tonic-gate syslog(LOG_INFO, "picldevtree: event handler invoked ename:%s " 36440Sstevel@tonic-gate "ptreepath:%s\n", ename, ptreepath); 36450Sstevel@tonic-gate 36465028Sfw157321 if (strcmp(ename, PICLEVENT_CPU_STATE_CHANGE) == 0) { 36475028Sfw157321 goto done; 36485028Sfw157321 } 36490Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) { 36500Sstevel@tonic-gate di_node_t devnode; 36510Sstevel@tonic-gate char *strp; 36520Sstevel@tonic-gate picl_nodehdl_t parh; 36530Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 36540Sstevel@tonic-gate char *nodename; 36550Sstevel@tonic-gate int err; 36560Sstevel@tonic-gate 36570Sstevel@tonic-gate /* If the node already exist, then nothing else to do here */ 36580Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) == PICL_SUCCESS) 36590Sstevel@tonic-gate return; 36600Sstevel@tonic-gate 36610Sstevel@tonic-gate /* Skip if unable to find parent PICL node handle */ 36620Sstevel@tonic-gate parh = plafh; 36630Sstevel@tonic-gate if (((strp = strrchr(ptreepath, '/')) != NULL) && 36640Sstevel@tonic-gate (strp != strchr(ptreepath, '/'))) { 36650Sstevel@tonic-gate *strp = '\0'; 36660Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &parh) != 36670Sstevel@tonic-gate PICL_SUCCESS) 36680Sstevel@tonic-gate return; 36690Sstevel@tonic-gate } 36700Sstevel@tonic-gate 36710Sstevel@tonic-gate /* 36720Sstevel@tonic-gate * If parent is the root node 36730Sstevel@tonic-gate */ 36740Sstevel@tonic-gate if (parh == plafh) { 36750Sstevel@tonic-gate ph = di_prom_init(); 36760Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 36770Sstevel@tonic-gate if (devnode == DI_NODE_NIL) { 36780Sstevel@tonic-gate if (ph != NULL) { 36790Sstevel@tonic-gate di_prom_fini(ph); 36800Sstevel@tonic-gate ph = NULL; 36810Sstevel@tonic-gate } 36820Sstevel@tonic-gate return; 36830Sstevel@tonic-gate } 36840Sstevel@tonic-gate nodename = di_node_name(devnode); 36850Sstevel@tonic-gate if (nodename == NULL) { 36860Sstevel@tonic-gate di_fini(devnode); 36870Sstevel@tonic-gate if (ph != NULL) { 36880Sstevel@tonic-gate di_prom_fini(ph); 36890Sstevel@tonic-gate ph = NULL; 36900Sstevel@tonic-gate } 36910Sstevel@tonic-gate return; 36920Sstevel@tonic-gate } 36930Sstevel@tonic-gate 36940Sstevel@tonic-gate err = get_node_class(nodeclass, devnode, nodename); 36950Sstevel@tonic-gate if (err < 0) { 36960Sstevel@tonic-gate di_fini(devnode); 36970Sstevel@tonic-gate if (ph != NULL) { 36980Sstevel@tonic-gate di_prom_fini(ph); 36990Sstevel@tonic-gate ph = NULL; 37000Sstevel@tonic-gate } 37010Sstevel@tonic-gate return; 37020Sstevel@tonic-gate } 37030Sstevel@tonic-gate err = construct_devtype_node(plafh, nodename, 37040Sstevel@tonic-gate nodeclass, devnode, &nodeh); 37050Sstevel@tonic-gate if (err != PICL_SUCCESS) { 37060Sstevel@tonic-gate di_fini(devnode); 37070Sstevel@tonic-gate if (ph != NULL) { 37080Sstevel@tonic-gate di_prom_fini(ph); 37090Sstevel@tonic-gate ph = NULL; 37100Sstevel@tonic-gate } 37110Sstevel@tonic-gate return; 37120Sstevel@tonic-gate } 37130Sstevel@tonic-gate (void) update_subtree(nodeh, devnode); 37140Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(nodeh); 37150Sstevel@tonic-gate if (ph != NULL) { 37160Sstevel@tonic-gate di_prom_fini(ph); 37170Sstevel@tonic-gate ph = NULL; 37180Sstevel@tonic-gate } 37190Sstevel@tonic-gate di_fini(devnode); 37200Sstevel@tonic-gate goto done; 37210Sstevel@tonic-gate } 37220Sstevel@tonic-gate 37230Sstevel@tonic-gate /* kludge ... try without bus-addr first */ 37240Sstevel@tonic-gate if ((strp = strrchr(dipath, '@')) != NULL) { 37250Sstevel@tonic-gate char *p; 37260Sstevel@tonic-gate 37270Sstevel@tonic-gate p = strrchr(dipath, '/'); 37280Sstevel@tonic-gate if (p != NULL && strp > p) { 37290Sstevel@tonic-gate *strp = '\0'; 37300Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 37310Sstevel@tonic-gate if (devnode != DI_NODE_NIL) 37320Sstevel@tonic-gate di_fini(devnode); 37330Sstevel@tonic-gate *strp = '@'; 37340Sstevel@tonic-gate } 37350Sstevel@tonic-gate } 37360Sstevel@tonic-gate /* Get parent devnode */ 37370Sstevel@tonic-gate if ((strp = strrchr(dipath, '/')) != NULL) 37380Sstevel@tonic-gate *++strp = '\0'; 37390Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 37400Sstevel@tonic-gate if (devnode == DI_NODE_NIL) 37410Sstevel@tonic-gate return; 37420Sstevel@tonic-gate ph = di_prom_init(); 37430Sstevel@tonic-gate (void) update_subtree(parh, devnode); 37440Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(parh); 37450Sstevel@tonic-gate if (ph) { 37460Sstevel@tonic-gate di_prom_fini(ph); 37470Sstevel@tonic-gate ph = NULL; 37480Sstevel@tonic-gate } 37490Sstevel@tonic-gate di_fini(devnode); 37500Sstevel@tonic-gate } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) { 37510Sstevel@tonic-gate char delclass[PICL_CLASSNAMELEN_MAX]; 37520Sstevel@tonic-gate char *strp; 37530Sstevel@tonic-gate 37540Sstevel@tonic-gate /* 37550Sstevel@tonic-gate * if final element of path doesn't have a unit address 37560Sstevel@tonic-gate * then it is not uniquely identifiable - cannot remove 37570Sstevel@tonic-gate */ 37580Sstevel@tonic-gate if (((strp = strrchr(ptreepath, '/')) != NULL) && 37590Sstevel@tonic-gate strchr(strp, '@') == NULL) 37600Sstevel@tonic-gate return; 37610Sstevel@tonic-gate 37620Sstevel@tonic-gate /* skip if can't find the node */ 37630Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS) 37640Sstevel@tonic-gate return; 37650Sstevel@tonic-gate 37660Sstevel@tonic-gate if (ptree_delete_node(nodeh) != PICL_SUCCESS) 37670Sstevel@tonic-gate return; 37680Sstevel@tonic-gate 37690Sstevel@tonic-gate if (picldevtree_debug) 37700Sstevel@tonic-gate syslog(LOG_INFO, 37710Sstevel@tonic-gate "picldevtree: deleted node nodeh:%llx\n", nodeh); 37720Sstevel@tonic-gate if ((ptree_get_propval_by_name(nodeh, 37730Sstevel@tonic-gate PICL_PROP_CLASSNAME, delclass, PICL_CLASSNAMELEN_MAX) == 37740Sstevel@tonic-gate PICL_SUCCESS) && IS_MC(delclass)) { 37750Sstevel@tonic-gate if (post_mc_event(PICLEVENT_MC_REMOVED, nodeh) != 37760Sstevel@tonic-gate PICL_SUCCESS) 37770Sstevel@tonic-gate syslog(LOG_WARNING, PICL_EVENT_DROPPED, 37780Sstevel@tonic-gate PICLEVENT_MC_REMOVED); 37790Sstevel@tonic-gate } else 37800Sstevel@tonic-gate (void) ptree_destroy_node(nodeh); 37810Sstevel@tonic-gate } 37820Sstevel@tonic-gate done: 37830Sstevel@tonic-gate (void) setup_cpus(plafh); 37840Sstevel@tonic-gate (void) add_ffb_config_info(plafh); 3785944Svenki set_pci_pciex_deviceid(plafh); 37860Sstevel@tonic-gate (void) set_sbus_slot(plafh); 37870Sstevel@tonic-gate if (picldevtree_debug > 1) 37880Sstevel@tonic-gate syslog(LOG_INFO, "picldevtree: event handler done\n"); 37890Sstevel@tonic-gate } 3790