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 1014*7834SMichael.Bergknoff@Sun.COM static const char * 1015*7834SMichael.Bergknoff@Sun.COM path_state_name(di_path_state_t st) 1016*7834SMichael.Bergknoff@Sun.COM { 1017*7834SMichael.Bergknoff@Sun.COM switch (st) { 1018*7834SMichael.Bergknoff@Sun.COM case DI_PATH_STATE_ONLINE: 1019*7834SMichael.Bergknoff@Sun.COM return ("online"); 1020*7834SMichael.Bergknoff@Sun.COM case DI_PATH_STATE_STANDBY: 1021*7834SMichael.Bergknoff@Sun.COM return ("standby"); 1022*7834SMichael.Bergknoff@Sun.COM case DI_PATH_STATE_OFFLINE: 1023*7834SMichael.Bergknoff@Sun.COM return ("offline"); 1024*7834SMichael.Bergknoff@Sun.COM case DI_PATH_STATE_FAULT: 1025*7834SMichael.Bergknoff@Sun.COM return ("faulted"); 1026*7834SMichael.Bergknoff@Sun.COM } 1027*7834SMichael.Bergknoff@Sun.COM return ("unknown"); 1028*7834SMichael.Bergknoff@Sun.COM } 1029*7834SMichael.Bergknoff@Sun.COM 1030*7834SMichael.Bergknoff@Sun.COM /* 1031*7834SMichael.Bergknoff@Sun.COM * This function is the volatile property handler for the multipath node 1032*7834SMichael.Bergknoff@Sun.COM * "State" property. It must locate the associated devinfo node in order to 1033*7834SMichael.Bergknoff@Sun.COM * determine the current state. Since the devinfo node can have multiple 1034*7834SMichael.Bergknoff@Sun.COM * paths the devfs_path is used to locate the correct path. 1035*7834SMichael.Bergknoff@Sun.COM */ 1036*7834SMichael.Bergknoff@Sun.COM static int 1037*7834SMichael.Bergknoff@Sun.COM get_path_state_name(ptree_rarg_t *rarg, void *vbuf) 1038*7834SMichael.Bergknoff@Sun.COM { 1039*7834SMichael.Bergknoff@Sun.COM int err; 1040*7834SMichael.Bergknoff@Sun.COM picl_nodehdl_t parh; 1041*7834SMichael.Bergknoff@Sun.COM char devfs_path[PATH_MAX]; 1042*7834SMichael.Bergknoff@Sun.COM di_node_t di_node; 1043*7834SMichael.Bergknoff@Sun.COM di_node_t di_root; 1044*7834SMichael.Bergknoff@Sun.COM di_path_t pi = DI_PATH_NIL; 1045*7834SMichael.Bergknoff@Sun.COM picl_nodehdl_t mpnode; 1046*7834SMichael.Bergknoff@Sun.COM 1047*7834SMichael.Bergknoff@Sun.COM (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE); 1048*7834SMichael.Bergknoff@Sun.COM 1049*7834SMichael.Bergknoff@Sun.COM mpnode = rarg->nodeh; 1050*7834SMichael.Bergknoff@Sun.COM 1051*7834SMichael.Bergknoff@Sun.COM /* 1052*7834SMichael.Bergknoff@Sun.COM * The parent node represents the vHCI. 1053*7834SMichael.Bergknoff@Sun.COM */ 1054*7834SMichael.Bergknoff@Sun.COM err = ptree_get_propval_by_name(mpnode, PICL_PROP_PARENT, &parh, 1055*7834SMichael.Bergknoff@Sun.COM sizeof (picl_nodehdl_t)); 1056*7834SMichael.Bergknoff@Sun.COM if (err != PICL_SUCCESS) { 1057*7834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 1058*7834SMichael.Bergknoff@Sun.COM } 1059*7834SMichael.Bergknoff@Sun.COM 1060*7834SMichael.Bergknoff@Sun.COM /* 1061*7834SMichael.Bergknoff@Sun.COM * The PICL_PROP_DEVFS_PATH property will be used to locate the 1062*7834SMichael.Bergknoff@Sun.COM * devinfo node for the vHCI driver. 1063*7834SMichael.Bergknoff@Sun.COM */ 1064*7834SMichael.Bergknoff@Sun.COM err = ptree_get_propval_by_name(parh, PICL_PROP_DEVFS_PATH, devfs_path, 1065*7834SMichael.Bergknoff@Sun.COM sizeof (devfs_path)); 1066*7834SMichael.Bergknoff@Sun.COM if (err != PICL_SUCCESS) { 1067*7834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 1068*7834SMichael.Bergknoff@Sun.COM } 1069*7834SMichael.Bergknoff@Sun.COM /* 1070*7834SMichael.Bergknoff@Sun.COM * Find the di_node for the vHCI driver. It will be used to scan 1071*7834SMichael.Bergknoff@Sun.COM * the path information nodes. 1072*7834SMichael.Bergknoff@Sun.COM */ 1073*7834SMichael.Bergknoff@Sun.COM di_root = di_init("/", DINFOCACHE); 1074*7834SMichael.Bergknoff@Sun.COM if (di_root == DI_NODE_NIL) { 1075*7834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 1076*7834SMichael.Bergknoff@Sun.COM } 1077*7834SMichael.Bergknoff@Sun.COM di_node = di_lookup_node(di_root, devfs_path); 1078*7834SMichael.Bergknoff@Sun.COM if (di_node == DI_NODE_NIL) { 1079*7834SMichael.Bergknoff@Sun.COM di_fini(di_root); 1080*7834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 1081*7834SMichael.Bergknoff@Sun.COM } 1082*7834SMichael.Bergknoff@Sun.COM 1083*7834SMichael.Bergknoff@Sun.COM /* 1084*7834SMichael.Bergknoff@Sun.COM * The devfs_path will be used below to match the 1085*7834SMichael.Bergknoff@Sun.COM * proper path information node. 1086*7834SMichael.Bergknoff@Sun.COM */ 1087*7834SMichael.Bergknoff@Sun.COM err = ptree_get_propval_by_name(mpnode, PICL_PROP_DEVFS_PATH, 1088*7834SMichael.Bergknoff@Sun.COM devfs_path, sizeof (devfs_path)); 1089*7834SMichael.Bergknoff@Sun.COM if (err != PICL_SUCCESS) { 1090*7834SMichael.Bergknoff@Sun.COM di_fini(di_root); 1091*7834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 1092*7834SMichael.Bergknoff@Sun.COM } 1093*7834SMichael.Bergknoff@Sun.COM 1094*7834SMichael.Bergknoff@Sun.COM /* 1095*7834SMichael.Bergknoff@Sun.COM * Scan the path information nodes looking for the matching devfs 1096*7834SMichael.Bergknoff@Sun.COM * path. When found obtain the state information. 1097*7834SMichael.Bergknoff@Sun.COM */ 1098*7834SMichael.Bergknoff@Sun.COM while ((pi = di_path_next_phci(di_node, pi)) != DI_PATH_NIL) { 1099*7834SMichael.Bergknoff@Sun.COM char *di_path; 1100*7834SMichael.Bergknoff@Sun.COM di_node_t phci_node = di_path_phci_node(pi); 1101*7834SMichael.Bergknoff@Sun.COM 1102*7834SMichael.Bergknoff@Sun.COM if (phci_node == DI_PATH_NIL) 1103*7834SMichael.Bergknoff@Sun.COM continue; 1104*7834SMichael.Bergknoff@Sun.COM 1105*7834SMichael.Bergknoff@Sun.COM di_path = di_devfs_path(phci_node); 1106*7834SMichael.Bergknoff@Sun.COM if (di_path) { 1107*7834SMichael.Bergknoff@Sun.COM if (strcmp(di_path, devfs_path) != 0) { 1108*7834SMichael.Bergknoff@Sun.COM di_devfs_path_free(di_path); 1109*7834SMichael.Bergknoff@Sun.COM continue; 1110*7834SMichael.Bergknoff@Sun.COM } 1111*7834SMichael.Bergknoff@Sun.COM (void) strlcpy(vbuf, path_state_name(di_path_state(pi)), 1112*7834SMichael.Bergknoff@Sun.COM MAX_STATE_SIZE); 1113*7834SMichael.Bergknoff@Sun.COM di_devfs_path_free(di_path); 1114*7834SMichael.Bergknoff@Sun.COM break; 1115*7834SMichael.Bergknoff@Sun.COM } 1116*7834SMichael.Bergknoff@Sun.COM } 1117*7834SMichael.Bergknoff@Sun.COM 1118*7834SMichael.Bergknoff@Sun.COM di_fini(di_root); 1119*7834SMichael.Bergknoff@Sun.COM return (PICL_SUCCESS); 1120*7834SMichael.Bergknoff@Sun.COM } 1121*7834SMichael.Bergknoff@Sun.COM 1122*7834SMichael.Bergknoff@Sun.COM static void 1123*7834SMichael.Bergknoff@Sun.COM add_di_path_prop(picl_nodehdl_t nodeh, di_path_prop_t di_path_prop) 1124*7834SMichael.Bergknoff@Sun.COM { 1125*7834SMichael.Bergknoff@Sun.COM int di_ptype; 1126*7834SMichael.Bergknoff@Sun.COM char *di_val; 1127*7834SMichael.Bergknoff@Sun.COM ptree_propinfo_t propinfo; 1128*7834SMichael.Bergknoff@Sun.COM int *idata; 1129*7834SMichael.Bergknoff@Sun.COM char *sdata; 1130*7834SMichael.Bergknoff@Sun.COM unsigned char *bdata; 1131*7834SMichael.Bergknoff@Sun.COM int len; 1132*7834SMichael.Bergknoff@Sun.COM 1133*7834SMichael.Bergknoff@Sun.COM di_ptype = di_path_prop_type(di_path_prop); 1134*7834SMichael.Bergknoff@Sun.COM di_val = di_path_prop_name(di_path_prop); 1135*7834SMichael.Bergknoff@Sun.COM 1136*7834SMichael.Bergknoff@Sun.COM switch (di_ptype) { 1137*7834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_BOOLEAN: 1138*7834SMichael.Bergknoff@Sun.COM add_boolean_prop(nodeh, propinfo, di_val); 1139*7834SMichael.Bergknoff@Sun.COM break; 1140*7834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_INT: 1141*7834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_INT64: 1142*7834SMichael.Bergknoff@Sun.COM len = di_path_prop_ints(di_path_prop, &idata); 1143*7834SMichael.Bergknoff@Sun.COM if (len < 0) 1144*7834SMichael.Bergknoff@Sun.COM /* Received error, so ignore prop */ 1145*7834SMichael.Bergknoff@Sun.COM break; 1146*7834SMichael.Bergknoff@Sun.COM add_uints_prop(nodeh, propinfo, di_val, idata, len); 1147*7834SMichael.Bergknoff@Sun.COM break; 1148*7834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_STRING: 1149*7834SMichael.Bergknoff@Sun.COM len = di_path_prop_strings(di_path_prop, &sdata); 1150*7834SMichael.Bergknoff@Sun.COM if (len <= 0) 1151*7834SMichael.Bergknoff@Sun.COM break; 1152*7834SMichael.Bergknoff@Sun.COM add_strings_prop(nodeh, propinfo, di_val, sdata, len); 1153*7834SMichael.Bergknoff@Sun.COM break; 1154*7834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_BYTE: 1155*7834SMichael.Bergknoff@Sun.COM len = di_path_prop_bytes(di_path_prop, &bdata); 1156*7834SMichael.Bergknoff@Sun.COM if (len < 0) 1157*7834SMichael.Bergknoff@Sun.COM break; 1158*7834SMichael.Bergknoff@Sun.COM add_bytes_prop(nodeh, propinfo, di_val, bdata, len); 1159*7834SMichael.Bergknoff@Sun.COM break; 1160*7834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_UNKNOWN: 1161*7834SMichael.Bergknoff@Sun.COM /* 1162*7834SMichael.Bergknoff@Sun.COM * Unknown type, we'll try and guess what it should be. 1163*7834SMichael.Bergknoff@Sun.COM */ 1164*7834SMichael.Bergknoff@Sun.COM len = di_path_prop_strings(di_path_prop, &sdata); 1165*7834SMichael.Bergknoff@Sun.COM if ((len > 0) && (sdata[0] != 0)) { 1166*7834SMichael.Bergknoff@Sun.COM add_strings_prop(nodeh, propinfo, di_val, sdata, 1167*7834SMichael.Bergknoff@Sun.COM len); 1168*7834SMichael.Bergknoff@Sun.COM break; 1169*7834SMichael.Bergknoff@Sun.COM } 1170*7834SMichael.Bergknoff@Sun.COM len = di_path_prop_ints(di_path_prop, &idata); 1171*7834SMichael.Bergknoff@Sun.COM if (len > 0) { 1172*7834SMichael.Bergknoff@Sun.COM add_uints_prop(nodeh, propinfo, di_val, 1173*7834SMichael.Bergknoff@Sun.COM idata, len); 1174*7834SMichael.Bergknoff@Sun.COM break; 1175*7834SMichael.Bergknoff@Sun.COM } 1176*7834SMichael.Bergknoff@Sun.COM len = di_path_prop_bytes(di_path_prop, &bdata); 1177*7834SMichael.Bergknoff@Sun.COM if (len > 0) 1178*7834SMichael.Bergknoff@Sun.COM add_bytes_prop(nodeh, propinfo, 1179*7834SMichael.Bergknoff@Sun.COM di_val, bdata, len); 1180*7834SMichael.Bergknoff@Sun.COM else if (len == 0) 1181*7834SMichael.Bergknoff@Sun.COM add_boolean_prop(nodeh, propinfo, 1182*7834SMichael.Bergknoff@Sun.COM di_val); 1183*7834SMichael.Bergknoff@Sun.COM break; 1184*7834SMichael.Bergknoff@Sun.COM case DI_PROP_TYPE_UNDEF_IT: 1185*7834SMichael.Bergknoff@Sun.COM break; 1186*7834SMichael.Bergknoff@Sun.COM default: 1187*7834SMichael.Bergknoff@Sun.COM break; 1188*7834SMichael.Bergknoff@Sun.COM } 1189*7834SMichael.Bergknoff@Sun.COM } 1190*7834SMichael.Bergknoff@Sun.COM 1191*7834SMichael.Bergknoff@Sun.COM /* 1192*7834SMichael.Bergknoff@Sun.COM * Add nodes for path information (PSARC/1999/647, PSARC/2008/437) 1193*7834SMichael.Bergknoff@Sun.COM */ 1194*7834SMichael.Bergknoff@Sun.COM static void 1195*7834SMichael.Bergknoff@Sun.COM construct_mpath_node(picl_nodehdl_t parh, di_node_t di_node) 1196*7834SMichael.Bergknoff@Sun.COM { 1197*7834SMichael.Bergknoff@Sun.COM di_path_t pi = DI_PATH_NIL; 1198*7834SMichael.Bergknoff@Sun.COM 1199*7834SMichael.Bergknoff@Sun.COM while ((pi = di_path_next_phci(di_node, pi)) != DI_PATH_NIL) { 1200*7834SMichael.Bergknoff@Sun.COM di_node_t phci_node = di_path_phci_node(pi); 1201*7834SMichael.Bergknoff@Sun.COM di_path_prop_t di_path_prop; 1202*7834SMichael.Bergknoff@Sun.COM picl_nodehdl_t nodeh; 1203*7834SMichael.Bergknoff@Sun.COM ptree_propinfo_t propinfo; 1204*7834SMichael.Bergknoff@Sun.COM int err; 1205*7834SMichael.Bergknoff@Sun.COM int instance; 1206*7834SMichael.Bergknoff@Sun.COM char *di_val; 1207*7834SMichael.Bergknoff@Sun.COM 1208*7834SMichael.Bergknoff@Sun.COM if (phci_node == DI_PATH_NIL) 1209*7834SMichael.Bergknoff@Sun.COM continue; 1210*7834SMichael.Bergknoff@Sun.COM 1211*7834SMichael.Bergknoff@Sun.COM err = ptree_create_and_add_node(parh, PICL_CLASS_MULTIPATH, 1212*7834SMichael.Bergknoff@Sun.COM PICL_CLASS_MULTIPATH, &nodeh); 1213*7834SMichael.Bergknoff@Sun.COM if (err != PICL_SUCCESS) 1214*7834SMichael.Bergknoff@Sun.COM continue; 1215*7834SMichael.Bergknoff@Sun.COM 1216*7834SMichael.Bergknoff@Sun.COM instance = di_instance(phci_node); 1217*7834SMichael.Bergknoff@Sun.COM (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1218*7834SMichael.Bergknoff@Sun.COM PICL_PTYPE_INT, PICL_READ, sizeof (instance), 1219*7834SMichael.Bergknoff@Sun.COM PICL_PROP_INSTANCE, NULL, NULL); 1220*7834SMichael.Bergknoff@Sun.COM (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, 1221*7834SMichael.Bergknoff@Sun.COM NULL); 1222*7834SMichael.Bergknoff@Sun.COM 1223*7834SMichael.Bergknoff@Sun.COM di_val = di_devfs_path(phci_node); 1224*7834SMichael.Bergknoff@Sun.COM if (di_val) { 1225*7834SMichael.Bergknoff@Sun.COM (void) ptree_init_propinfo(&propinfo, 1226*7834SMichael.Bergknoff@Sun.COM PTREE_PROPINFO_VERSION, 1227*7834SMichael.Bergknoff@Sun.COM PICL_PTYPE_CHARSTRING, PICL_READ, 1228*7834SMichael.Bergknoff@Sun.COM strlen(di_val) + 1, PICL_PROP_DEVFS_PATH, 1229*7834SMichael.Bergknoff@Sun.COM NULL, NULL); 1230*7834SMichael.Bergknoff@Sun.COM (void) ptree_create_and_add_prop(nodeh, 1231*7834SMichael.Bergknoff@Sun.COM &propinfo, di_val, NULL); 1232*7834SMichael.Bergknoff@Sun.COM di_devfs_path_free(di_val); 1233*7834SMichael.Bergknoff@Sun.COM } 1234*7834SMichael.Bergknoff@Sun.COM 1235*7834SMichael.Bergknoff@Sun.COM (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 1236*7834SMichael.Bergknoff@Sun.COM PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), 1237*7834SMichael.Bergknoff@Sun.COM MAX_STATE_SIZE, PICL_PROP_STATE, get_path_state_name, NULL); 1238*7834SMichael.Bergknoff@Sun.COM (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL); 1239*7834SMichael.Bergknoff@Sun.COM 1240*7834SMichael.Bergknoff@Sun.COM for (di_path_prop = di_path_prop_next(pi, DI_PROP_NIL); 1241*7834SMichael.Bergknoff@Sun.COM di_path_prop != DI_PROP_NIL; 1242*7834SMichael.Bergknoff@Sun.COM di_path_prop = di_path_prop_next(pi, di_path_prop)) { 1243*7834SMichael.Bergknoff@Sun.COM add_di_path_prop(nodeh, di_path_prop); 1244*7834SMichael.Bergknoff@Sun.COM } 1245*7834SMichael.Bergknoff@Sun.COM } 1246*7834SMichael.Bergknoff@Sun.COM } 1247*7834SMichael.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); 1488*7834SMichael.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 /* 16300Sstevel@tonic-gate * this is an unattached node - so the path is not 16310Sstevel@tonic-gate * unique. Need to find out which node it is. 16320Sstevel@tonic-gate * Find the unit_address from the obp properties. 16330Sstevel@tonic-gate */ 16340Sstevel@tonic-gate err = ptree_create_node(nodename, nodeclass, &chdh); 16350Sstevel@tonic-gate if (err != PICL_SUCCESS) 16360Sstevel@tonic-gate return (err); 16370Sstevel@tonic-gate (void) add_openprom_props(chdh, cnode); 16380Sstevel@tonic-gate err = get_unitaddr(nodeh, chdh, unitaddr, 16390Sstevel@tonic-gate sizeof (unitaddr)); 16400Sstevel@tonic-gate if (err != PICL_SUCCESS) 16410Sstevel@tonic-gate return (err); 16420Sstevel@tonic-gate (void) ptree_destroy_node(chdh); 16430Sstevel@tonic-gate (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s@%s", 16440Sstevel@tonic-gate path_buf, unitaddr); 16450Sstevel@tonic-gate (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s", 16460Sstevel@tonic-gate path_buf); 16470Sstevel@tonic-gate } else { 16480Sstevel@tonic-gate /* 16490Sstevel@tonic-gate * this is an attached node - so the path is unique 16500Sstevel@tonic-gate */ 16510Sstevel@tonic-gate (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s", 16520Sstevel@tonic-gate path_buf); 16530Sstevel@tonic-gate (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s", 16540Sstevel@tonic-gate path_buf); 16550Sstevel@tonic-gate strp = strrchr(path_wo_ua, '@'); 16560Sstevel@tonic-gate *strp++ = '\0'; 16570Sstevel@tonic-gate (void) snprintf(unitaddr, sizeof (unitaddr), "%s", 16580Sstevel@tonic-gate strp); 16590Sstevel@tonic-gate } 16600Sstevel@tonic-gate /* 16610Sstevel@tonic-gate * first look for node with unit address in devfs_path 16620Sstevel@tonic-gate */ 16630Sstevel@tonic-gate if (ptree_find_node(nodeh, PICL_PROP_DEVFS_PATH, 16640Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, path_w_ua, strlen(path_w_ua) + 1, 16650Sstevel@tonic-gate &nh) == PICL_SUCCESS) { 16660Sstevel@tonic-gate /* 16670Sstevel@tonic-gate * node already there - there's nothing we need to do 16680Sstevel@tonic-gate */ 16690Sstevel@tonic-gate if (picldevtree_debug > 1) 16700Sstevel@tonic-gate syslog(LOG_INFO, 16710Sstevel@tonic-gate "update_subtree: path:%s node exists\n", 16720Sstevel@tonic-gate path_buf); 16730Sstevel@tonic-gate di_devfs_path_free(path_buf); 16740Sstevel@tonic-gate continue; 16750Sstevel@tonic-gate } 16760Sstevel@tonic-gate /* 16770Sstevel@tonic-gate * now look for node without unit address in devfs_path. 16780Sstevel@tonic-gate * This might be just one out of several 16790Sstevel@tonic-gate * nodes - need to check all siblings 16800Sstevel@tonic-gate */ 16810Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, 16820Sstevel@tonic-gate &chdh, sizeof (chdh)); 16830Sstevel@tonic-gate if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND)) 16840Sstevel@tonic-gate return (err); 16850Sstevel@tonic-gate gotit = 0; 16860Sstevel@tonic-gate while (err == PICL_SUCCESS) { 16870Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 16880Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, buf, sizeof (buf)); 16890Sstevel@tonic-gate if (err != PICL_SUCCESS) 16900Sstevel@tonic-gate return (err); 16910Sstevel@tonic-gate if (strcmp(buf, path_wo_ua) == 0) { 16920Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 16930Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, buf, sizeof (buf)); 16940Sstevel@tonic-gate if (err != PICL_SUCCESS) 16950Sstevel@tonic-gate return (err); 16960Sstevel@tonic-gate if (strcmp(buf, unitaddr) == 0) { 16970Sstevel@tonic-gate gotit = 1; 16980Sstevel@tonic-gate break; 16990Sstevel@tonic-gate } 17000Sstevel@tonic-gate } 17010Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 17020Sstevel@tonic-gate PICL_PROP_PEER, &chdh, sizeof (chdh)); 17030Sstevel@tonic-gate if (err != PICL_SUCCESS) 17040Sstevel@tonic-gate break; 17050Sstevel@tonic-gate } 17060Sstevel@tonic-gate if (gotit) { 17070Sstevel@tonic-gate /* 17080Sstevel@tonic-gate * node already there - there's nothing we need to do 17090Sstevel@tonic-gate */ 17100Sstevel@tonic-gate if (picldevtree_debug > 1) 17110Sstevel@tonic-gate syslog(LOG_INFO, 17120Sstevel@tonic-gate "update_subtree: path:%s node exists\n", 17130Sstevel@tonic-gate path_buf); 17140Sstevel@tonic-gate di_devfs_path_free(path_buf); 17150Sstevel@tonic-gate continue; 17160Sstevel@tonic-gate } 17170Sstevel@tonic-gate 17180Sstevel@tonic-gate #define IS_MC(x) (strcmp(x, PICL_CLASS_MEMORY_CONTROLLER) == 0 ? 1 : 0) 17190Sstevel@tonic-gate 17200Sstevel@tonic-gate if (construct_devtype_node(nodeh, nodename, nodeclass, cnode, 17210Sstevel@tonic-gate &chdh) == PICL_SUCCESS) { 17220Sstevel@tonic-gate if (picldevtree_debug) 17230Sstevel@tonic-gate syslog(LOG_INFO, 17240Sstevel@tonic-gate "picldevtree: added node:%s path:%s\n", 17250Sstevel@tonic-gate nodename, path_buf); 17260Sstevel@tonic-gate if (IS_MC(nodeclass)) { 17270Sstevel@tonic-gate if (post_mc_event(PICLEVENT_MC_ADDED, chdh) != 17280Sstevel@tonic-gate PICL_SUCCESS) 17290Sstevel@tonic-gate syslog(LOG_WARNING, PICL_EVENT_DROPPED, 17300Sstevel@tonic-gate PICLEVENT_MC_ADDED); 17310Sstevel@tonic-gate } 17320Sstevel@tonic-gate 17330Sstevel@tonic-gate di_devfs_path_free(path_buf); 17340Sstevel@tonic-gate (void) update_subtree(chdh, cnode); 17350Sstevel@tonic-gate } 17360Sstevel@tonic-gate } 17370Sstevel@tonic-gate 17380Sstevel@tonic-gate return (PICL_SUCCESS); 17390Sstevel@tonic-gate 17400Sstevel@tonic-gate } 17410Sstevel@tonic-gate 17420Sstevel@tonic-gate /* 17437442SMichael.Bergknoff@Sun.COM * Check for a stale OBP node. EINVAL is returned from the openprom(7D) driver 17447442SMichael.Bergknoff@Sun.COM * if the nodeid stored in the snapshot is not valid. 17457442SMichael.Bergknoff@Sun.COM */ 17467442SMichael.Bergknoff@Sun.COM static int 17477442SMichael.Bergknoff@Sun.COM check_stale_node(di_node_t node, void *arg) 17487442SMichael.Bergknoff@Sun.COM { 17497442SMichael.Bergknoff@Sun.COM di_prom_prop_t promp; 17507442SMichael.Bergknoff@Sun.COM 17517442SMichael.Bergknoff@Sun.COM errno = 0; 17527442SMichael.Bergknoff@Sun.COM promp = di_prom_prop_next(ph, node, DI_PROM_PROP_NIL); 17537442SMichael.Bergknoff@Sun.COM if (promp == DI_PROM_PROP_NIL && errno == EINVAL) { 17547442SMichael.Bergknoff@Sun.COM snapshot_stale = 1; 17557442SMichael.Bergknoff@Sun.COM return (DI_WALK_TERMINATE); 17567442SMichael.Bergknoff@Sun.COM } 17577442SMichael.Bergknoff@Sun.COM return (DI_WALK_CONTINUE); 17587442SMichael.Bergknoff@Sun.COM } 17597442SMichael.Bergknoff@Sun.COM 17607442SMichael.Bergknoff@Sun.COM /* 17617442SMichael.Bergknoff@Sun.COM * Walk the snapshot and check the OBP properties of each node. 17627442SMichael.Bergknoff@Sun.COM */ 17637442SMichael.Bergknoff@Sun.COM static int 17647442SMichael.Bergknoff@Sun.COM is_snapshot_stale(di_node_t root) 17657442SMichael.Bergknoff@Sun.COM { 17667442SMichael.Bergknoff@Sun.COM snapshot_stale = 0; 17677442SMichael.Bergknoff@Sun.COM di_walk_node(root, DI_WALK_CLDFIRST, NULL, check_stale_node); 17687442SMichael.Bergknoff@Sun.COM return (snapshot_stale); 17697442SMichael.Bergknoff@Sun.COM } 17707442SMichael.Bergknoff@Sun.COM 17717442SMichael.Bergknoff@Sun.COM /* 17720Sstevel@tonic-gate * This function processes the data from libdevinfo and creates nodes 17730Sstevel@tonic-gate * in the PICL tree. 17740Sstevel@tonic-gate */ 17750Sstevel@tonic-gate static int 17760Sstevel@tonic-gate libdevinfo_init(picl_nodehdl_t rooth) 17770Sstevel@tonic-gate { 17780Sstevel@tonic-gate di_node_t di_root; 17790Sstevel@tonic-gate picl_nodehdl_t plafh; 17800Sstevel@tonic-gate picl_nodehdl_t obph; 17810Sstevel@tonic-gate int err; 17820Sstevel@tonic-gate 17835492Sarutz /* 17845492Sarutz * Use DINFOCACHE so that we obtain all attributes for all 17855492Sarutz * device instances (without necessarily doing a load/attach 17865492Sarutz * of all drivers). Once the (on-disk) cache file is built, it 17875492Sarutz * exists over a reboot and can be read into memory at a very 17885492Sarutz * low cost. 17895492Sarutz */ 17905492Sarutz if ((di_root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) 17910Sstevel@tonic-gate return (PICL_FAILURE); 17920Sstevel@tonic-gate 17930Sstevel@tonic-gate if ((ph = di_prom_init()) == NULL) 17940Sstevel@tonic-gate return (PICL_FAILURE); 17957442SMichael.Bergknoff@Sun.COM 17967442SMichael.Bergknoff@Sun.COM /* 17977442SMichael.Bergknoff@Sun.COM * Check if the snapshot cache contains stale OBP nodeid references. 17987442SMichael.Bergknoff@Sun.COM * If it does release the snapshot and obtain a live snapshot from the 17997442SMichael.Bergknoff@Sun.COM * kernel. 18007442SMichael.Bergknoff@Sun.COM */ 18017442SMichael.Bergknoff@Sun.COM if (is_snapshot_stale(di_root)) { 18027442SMichael.Bergknoff@Sun.COM syslog(LOG_INFO, "picld detected stale snapshot cache"); 18037442SMichael.Bergknoff@Sun.COM di_fini(di_root); 18047442SMichael.Bergknoff@Sun.COM if ((di_root = di_init("/", DINFOCPYALL | DINFOFORCE)) == 18057442SMichael.Bergknoff@Sun.COM DI_NODE_NIL) { 18067442SMichael.Bergknoff@Sun.COM return (PICL_FAILURE); 18077442SMichael.Bergknoff@Sun.COM } 18087442SMichael.Bergknoff@Sun.COM } 18097442SMichael.Bergknoff@Sun.COM 18100Sstevel@tonic-gate /* 18110Sstevel@tonic-gate * create platform PICL node using di_root node 18120Sstevel@tonic-gate */ 18130Sstevel@tonic-gate err = construct_picl_platform(rooth, di_root, &plafh); 18140Sstevel@tonic-gate if (err != PICL_SUCCESS) { 18150Sstevel@tonic-gate di_fini(di_root); 18160Sstevel@tonic-gate return (PICL_FAILURE); 18170Sstevel@tonic-gate } 18180Sstevel@tonic-gate 18190Sstevel@tonic-gate err = construct_picl_openprom(rooth, &obph); 18200Sstevel@tonic-gate if (err != PICL_SUCCESS) { 18210Sstevel@tonic-gate di_fini(di_root); 18220Sstevel@tonic-gate return (PICL_FAILURE); 18230Sstevel@tonic-gate } 18240Sstevel@tonic-gate 18250Sstevel@tonic-gate (void) construct_devinfo_tree(plafh, obph, di_root, NULL); 18260Sstevel@tonic-gate if (ph) { 18270Sstevel@tonic-gate di_prom_fini(ph); 18280Sstevel@tonic-gate ph = NULL; 18290Sstevel@tonic-gate } 18300Sstevel@tonic-gate di_fini(di_root); 18310Sstevel@tonic-gate return (err); 18320Sstevel@tonic-gate } 18330Sstevel@tonic-gate 18340Sstevel@tonic-gate /* 18350Sstevel@tonic-gate * This function returns the integer property value 18360Sstevel@tonic-gate */ 18370Sstevel@tonic-gate static int 18380Sstevel@tonic-gate get_int_propval_by_name(picl_nodehdl_t nodeh, char *pname, int *ival) 18390Sstevel@tonic-gate { 18400Sstevel@tonic-gate int err; 18410Sstevel@tonic-gate 18420Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, pname, ival, 18430Sstevel@tonic-gate sizeof (int)); 18440Sstevel@tonic-gate 18450Sstevel@tonic-gate return (err); 18460Sstevel@tonic-gate } 18470Sstevel@tonic-gate 18480Sstevel@tonic-gate /* 18490Sstevel@tonic-gate * This function returns the port ID (or CPU ID in the case of CMP cores) 18500Sstevel@tonic-gate * of the specific CPU node handle. If upa_portid exists, return its value. 18510Sstevel@tonic-gate * Otherwise, return portid/cpuid. 18520Sstevel@tonic-gate */ 18530Sstevel@tonic-gate static int 18540Sstevel@tonic-gate get_cpu_portid(picl_nodehdl_t modh, int *id) 18550Sstevel@tonic-gate { 18560Sstevel@tonic-gate int err; 18570Sstevel@tonic-gate 18585028Sfw157321 if (strcmp(mach_name, "sun4u") == 0 || 18595028Sfw157321 strcmp(mach_name, "sun4v") == 0) { 18600Sstevel@tonic-gate err = get_int_propval_by_name(modh, OBP_PROP_UPA_PORTID, id); 18610Sstevel@tonic-gate if (err == PICL_SUCCESS) 18620Sstevel@tonic-gate return (err); 18630Sstevel@tonic-gate err = get_int_propval_by_name(modh, OBP_PROP_PORTID, id); 18640Sstevel@tonic-gate if (err == PICL_SUCCESS) 18650Sstevel@tonic-gate return (err); 18660Sstevel@tonic-gate return (get_int_propval_by_name(modh, OBP_PROP_CPUID, id)); 18670Sstevel@tonic-gate } 18680Sstevel@tonic-gate if (strcmp(mach_name, "i86pc") == 0) 18690Sstevel@tonic-gate return (get_int_propval_by_name(modh, PICL_PROP_INSTANCE, id)); 18700Sstevel@tonic-gate 18710Sstevel@tonic-gate return (PICL_FAILURE); 18720Sstevel@tonic-gate } 18730Sstevel@tonic-gate 18740Sstevel@tonic-gate /* 18750Sstevel@tonic-gate * This function is the volatile read access function of CPU state 18760Sstevel@tonic-gate * property 18770Sstevel@tonic-gate */ 18780Sstevel@tonic-gate static int 18790Sstevel@tonic-gate get_pi_state(ptree_rarg_t *rarg, void *vbuf) 18800Sstevel@tonic-gate { 18810Sstevel@tonic-gate int id; 18820Sstevel@tonic-gate int err; 18830Sstevel@tonic-gate 18840Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 18850Sstevel@tonic-gate if (err != PICL_SUCCESS) 18860Sstevel@tonic-gate return (err); 18870Sstevel@tonic-gate 18880Sstevel@tonic-gate switch (p_online(id, P_STATUS)) { 18890Sstevel@tonic-gate case P_ONLINE: 18900Sstevel@tonic-gate (void) strlcpy(vbuf, PS_ONLINE, MAX_STATE_SIZE); 18910Sstevel@tonic-gate break; 18920Sstevel@tonic-gate case P_OFFLINE: 18930Sstevel@tonic-gate (void) strlcpy(vbuf, PS_OFFLINE, MAX_STATE_SIZE); 18940Sstevel@tonic-gate break; 18950Sstevel@tonic-gate case P_NOINTR: 18960Sstevel@tonic-gate (void) strlcpy(vbuf, PS_NOINTR, MAX_STATE_SIZE); 18970Sstevel@tonic-gate break; 18980Sstevel@tonic-gate case P_SPARE: 18990Sstevel@tonic-gate (void) strlcpy(vbuf, PS_SPARE, MAX_STATE_SIZE); 19000Sstevel@tonic-gate break; 19010Sstevel@tonic-gate case P_FAULTED: 19020Sstevel@tonic-gate (void) strlcpy(vbuf, PS_FAULTED, MAX_STATE_SIZE); 19030Sstevel@tonic-gate break; 19040Sstevel@tonic-gate case P_POWEROFF: 19050Sstevel@tonic-gate (void) strlcpy(vbuf, PS_POWEROFF, MAX_STATE_SIZE); 19060Sstevel@tonic-gate break; 19070Sstevel@tonic-gate default: 19080Sstevel@tonic-gate (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE); 19090Sstevel@tonic-gate break; 19100Sstevel@tonic-gate } 19110Sstevel@tonic-gate return (PICL_SUCCESS); 19120Sstevel@tonic-gate } 19130Sstevel@tonic-gate 19140Sstevel@tonic-gate /* 19150Sstevel@tonic-gate * This function is the volatile read access function of CPU processor_type 19160Sstevel@tonic-gate * property 19170Sstevel@tonic-gate */ 19180Sstevel@tonic-gate static int 19190Sstevel@tonic-gate get_processor_type(ptree_rarg_t *rarg, void *vbuf) 19200Sstevel@tonic-gate { 19210Sstevel@tonic-gate processor_info_t cpu_info; 19220Sstevel@tonic-gate int id; 19230Sstevel@tonic-gate int err; 19240Sstevel@tonic-gate 19250Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 19260Sstevel@tonic-gate if (err != PICL_SUCCESS) 19270Sstevel@tonic-gate return (err); 19280Sstevel@tonic-gate 19290Sstevel@tonic-gate if (processor_info(id, &cpu_info) >= 0) { 19300Sstevel@tonic-gate (void) strlcpy(vbuf, cpu_info.pi_processor_type, PI_TYPELEN); 19310Sstevel@tonic-gate } 19320Sstevel@tonic-gate return (PICL_SUCCESS); 19330Sstevel@tonic-gate } 19340Sstevel@tonic-gate 19350Sstevel@tonic-gate /* 19360Sstevel@tonic-gate * This function is the volatile read access function of CPU fputypes 19370Sstevel@tonic-gate * property 19380Sstevel@tonic-gate */ 19390Sstevel@tonic-gate static int 19400Sstevel@tonic-gate get_fputypes(ptree_rarg_t *rarg, void *vbuf) 19410Sstevel@tonic-gate { 19420Sstevel@tonic-gate processor_info_t cpu_info; 19430Sstevel@tonic-gate int id; 19440Sstevel@tonic-gate int err; 19450Sstevel@tonic-gate 19460Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 19470Sstevel@tonic-gate if (err != PICL_SUCCESS) 19480Sstevel@tonic-gate return (err); 19490Sstevel@tonic-gate 19500Sstevel@tonic-gate if (processor_info(id, &cpu_info) >= 0) { 19510Sstevel@tonic-gate (void) strlcpy(vbuf, cpu_info.pi_fputypes, PI_FPUTYPE); 19520Sstevel@tonic-gate } 19530Sstevel@tonic-gate return (PICL_SUCCESS); 19540Sstevel@tonic-gate } 19550Sstevel@tonic-gate 19560Sstevel@tonic-gate /* 19570Sstevel@tonic-gate * This function is the volatile read access function of CPU StateBegin 19580Sstevel@tonic-gate * property. To minimize overhead, use kstat_chain_update() to refresh 19590Sstevel@tonic-gate * the kstat header info as opposed to invoking kstat_open() every time. 19600Sstevel@tonic-gate */ 19610Sstevel@tonic-gate static int 19620Sstevel@tonic-gate get_pi_state_begin(ptree_rarg_t *rarg, void *vbuf) 19630Sstevel@tonic-gate { 19640Sstevel@tonic-gate int err; 19650Sstevel@tonic-gate int cpu_id; 19660Sstevel@tonic-gate static kstat_ctl_t *kc = NULL; 19670Sstevel@tonic-gate static pthread_mutex_t kc_mutex = PTHREAD_MUTEX_INITIALIZER; 19680Sstevel@tonic-gate kstat_t *kp; 19690Sstevel@tonic-gate kstat_named_t *kn; 19700Sstevel@tonic-gate 19710Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &cpu_id); 19720Sstevel@tonic-gate if (err != PICL_SUCCESS) 19730Sstevel@tonic-gate return (err); 19740Sstevel@tonic-gate 19750Sstevel@tonic-gate (void) pthread_mutex_lock(&kc_mutex); 19760Sstevel@tonic-gate if (kc == NULL) 19770Sstevel@tonic-gate kc = kstat_open(); 19780Sstevel@tonic-gate else if (kstat_chain_update(kc) == -1) { 19790Sstevel@tonic-gate (void) kstat_close(kc); 19800Sstevel@tonic-gate kc = kstat_open(); 19810Sstevel@tonic-gate } 19820Sstevel@tonic-gate 19830Sstevel@tonic-gate if (kc == NULL) { 19840Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 19850Sstevel@tonic-gate return (PICL_FAILURE); 19860Sstevel@tonic-gate } 19870Sstevel@tonic-gate 19880Sstevel@tonic-gate /* Get the state_begin from kstat */ 19890Sstevel@tonic-gate if ((kp = kstat_lookup(kc, KSTAT_CPU_INFO, cpu_id, NULL)) == NULL || 19900Sstevel@tonic-gate kp->ks_type != KSTAT_TYPE_NAMED || kstat_read(kc, kp, 0) < 0) { 19910Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 19920Sstevel@tonic-gate return (PICL_FAILURE); 19930Sstevel@tonic-gate } 19940Sstevel@tonic-gate 19950Sstevel@tonic-gate kn = kstat_data_lookup(kp, KSTAT_STATE_BEGIN); 19960Sstevel@tonic-gate if (kn) { 19970Sstevel@tonic-gate *(uint64_t *)vbuf = (uint64_t)kn->value.l; 19980Sstevel@tonic-gate err = PICL_SUCCESS; 19990Sstevel@tonic-gate } else 20000Sstevel@tonic-gate err = PICL_FAILURE; 20010Sstevel@tonic-gate 20020Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 20030Sstevel@tonic-gate return (err); 20040Sstevel@tonic-gate } 20050Sstevel@tonic-gate 20060Sstevel@tonic-gate /* 20070Sstevel@tonic-gate * This function adds CPU information to the CPU nodes 20080Sstevel@tonic-gate */ 20090Sstevel@tonic-gate /* ARGSUSED */ 20100Sstevel@tonic-gate static int 20110Sstevel@tonic-gate add_processor_info(picl_nodehdl_t cpuh, void *args) 20120Sstevel@tonic-gate { 20130Sstevel@tonic-gate int err; 20140Sstevel@tonic-gate int cpu_id; 20150Sstevel@tonic-gate ptree_propinfo_t propinfo; 20160Sstevel@tonic-gate ptree_propinfo_t pinfo; 20170Sstevel@tonic-gate 20180Sstevel@tonic-gate err = get_cpu_portid(cpuh, &cpu_id); 20190Sstevel@tonic-gate if (err != PICL_SUCCESS) 20200Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 20210Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 20220Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (int), PICL_PROP_ID, NULL, NULL); 20230Sstevel@tonic-gate err = ptree_create_and_add_prop(cpuh, &propinfo, &cpu_id, NULL); 20240Sstevel@tonic-gate if (err != PICL_SUCCESS) 20250Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 20260Sstevel@tonic-gate 20270Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 20280Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), MAX_STATE_SIZE, 20290Sstevel@tonic-gate PICL_PROP_STATE, get_pi_state, NULL); 20300Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 20310Sstevel@tonic-gate 20320Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 20330Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_TYPELEN, 20340Sstevel@tonic-gate PICL_PROP_PROCESSOR_TYPE, get_processor_type, NULL); 20350Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 20360Sstevel@tonic-gate 20370Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 20380Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_FPUTYPE, 20390Sstevel@tonic-gate PICL_PROP_FPUTYPE, get_fputypes, NULL); 20400Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 20410Sstevel@tonic-gate 20420Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 20430Sstevel@tonic-gate PICL_PTYPE_TIMESTAMP, PICL_READ|PICL_VOLATILE, sizeof (uint64_t), 20440Sstevel@tonic-gate PICL_PROP_STATE_BEGIN, get_pi_state_begin, NULL); 20450Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 20460Sstevel@tonic-gate 20470Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 20480Sstevel@tonic-gate } 20490Sstevel@tonic-gate 20500Sstevel@tonic-gate /* 20510Sstevel@tonic-gate * This function sets up the "ID" property in every CPU nodes 20520Sstevel@tonic-gate * and adds processor info 20530Sstevel@tonic-gate */ 20540Sstevel@tonic-gate static int 20550Sstevel@tonic-gate setup_cpus(picl_nodehdl_t plafh) 20560Sstevel@tonic-gate { 20570Sstevel@tonic-gate int err; 20580Sstevel@tonic-gate 20590Sstevel@tonic-gate err = ptree_walk_tree_by_class(plafh, PICL_CLASS_CPU, NULL, 20600Sstevel@tonic-gate add_processor_info); 20610Sstevel@tonic-gate 20620Sstevel@tonic-gate return (err); 20630Sstevel@tonic-gate } 20640Sstevel@tonic-gate 20650Sstevel@tonic-gate /* 20660Sstevel@tonic-gate * This function format's the manufacture's information for FFB display 20670Sstevel@tonic-gate * devices 20680Sstevel@tonic-gate */ 20690Sstevel@tonic-gate static void 20700Sstevel@tonic-gate fmt_manf_id(manuf_t manufid, int bufsz, char *outbuf) 20710Sstevel@tonic-gate { 20720Sstevel@tonic-gate /* 20730Sstevel@tonic-gate * Format the manufacturer's info. Note a small inconsistency we 20740Sstevel@tonic-gate * have to work around - Brooktree has it's part number in decimal, 20750Sstevel@tonic-gate * while Mitsubishi has it's part number in hex. 20760Sstevel@tonic-gate */ 20770Sstevel@tonic-gate switch (manufid.fld.manf) { 20780Sstevel@tonic-gate case MANF_BROOKTREE: 20790Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, "%s %d, version %d", 20800Sstevel@tonic-gate "Brooktree", manufid.fld.partno, manufid.fld.version); 20810Sstevel@tonic-gate break; 20820Sstevel@tonic-gate 20830Sstevel@tonic-gate case MANF_MITSUBISHI: 20840Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, "%s %x, version %d", 20850Sstevel@tonic-gate "Mitsubishi", manufid.fld.partno, manufid.fld.version); 20860Sstevel@tonic-gate break; 20870Sstevel@tonic-gate 20880Sstevel@tonic-gate default: 20890Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, 20900Sstevel@tonic-gate "JED code %d, Part num 0x%x, version %d", 20910Sstevel@tonic-gate manufid.fld.manf, manufid.fld.partno, manufid.fld.version); 20920Sstevel@tonic-gate } 20930Sstevel@tonic-gate } 20940Sstevel@tonic-gate 20950Sstevel@tonic-gate /* 20960Sstevel@tonic-gate * If it's an ffb device, open ffb devices and return PICL_SUCCESS 20970Sstevel@tonic-gate */ 20980Sstevel@tonic-gate static int 20990Sstevel@tonic-gate open_ffb_device(picl_nodehdl_t ffbh, int *fd) 21000Sstevel@tonic-gate { 21010Sstevel@tonic-gate DIR *dirp; 21020Sstevel@tonic-gate char devfs_path[PATH_MAX]; 21030Sstevel@tonic-gate char dev_path[PATH_MAX]; 21040Sstevel@tonic-gate char *devp; 21050Sstevel@tonic-gate struct dirent *direntp; 21060Sstevel@tonic-gate int err; 21070Sstevel@tonic-gate int tmpfd; 21080Sstevel@tonic-gate 21090Sstevel@tonic-gate /* Get the devfs_path of the ffb devices */ 21100Sstevel@tonic-gate err = ptree_get_propval_by_name(ffbh, PICL_PROP_DEVFS_PATH, devfs_path, 21110Sstevel@tonic-gate sizeof (devfs_path)); 21120Sstevel@tonic-gate if (err != PICL_SUCCESS) 21130Sstevel@tonic-gate return (err); 21140Sstevel@tonic-gate 21150Sstevel@tonic-gate /* Get the device node name */ 21160Sstevel@tonic-gate devp = strrchr(devfs_path, '/'); 21170Sstevel@tonic-gate if (devp == NULL) 21180Sstevel@tonic-gate return (PICL_FAILURE); 21190Sstevel@tonic-gate *devp = '\0'; 21200Sstevel@tonic-gate ++devp; 21210Sstevel@tonic-gate 21220Sstevel@tonic-gate /* 21230Sstevel@tonic-gate * Check if device node name has the ffb string 21240Sstevel@tonic-gate * If not, assume it's not a ffb device. 21250Sstevel@tonic-gate */ 21260Sstevel@tonic-gate if (strstr(devp, FFB_NAME) == NULL) 21270Sstevel@tonic-gate return (PICL_FAILURE); 21280Sstevel@tonic-gate 21290Sstevel@tonic-gate /* 21300Sstevel@tonic-gate * Get the parent path of the ffb device node. 21310Sstevel@tonic-gate */ 21320Sstevel@tonic-gate (void) snprintf(dev_path, sizeof (dev_path), "%s/%s", "/devices", 21330Sstevel@tonic-gate devfs_path); 21340Sstevel@tonic-gate 21350Sstevel@tonic-gate /* 21360Sstevel@tonic-gate * Since we don't know ffb's minor nodename, 21370Sstevel@tonic-gate * we need to search all the devices under its 21380Sstevel@tonic-gate * parent dir by comparing the node name 21390Sstevel@tonic-gate */ 21400Sstevel@tonic-gate if ((dirp = opendir(dev_path)) == NULL) 21410Sstevel@tonic-gate return (PICL_FAILURE); 21420Sstevel@tonic-gate 21430Sstevel@tonic-gate while ((direntp = readdir(dirp)) != NULL) { 21440Sstevel@tonic-gate if (strstr(direntp->d_name, devp) != NULL) { 21450Sstevel@tonic-gate (void) strcat(dev_path, "/"); 21460Sstevel@tonic-gate (void) strcat(dev_path, direntp->d_name); 21470Sstevel@tonic-gate tmpfd = open(dev_path, O_RDWR); 21480Sstevel@tonic-gate if (tmpfd < 0) 21490Sstevel@tonic-gate continue; 21500Sstevel@tonic-gate *fd = tmpfd; 21510Sstevel@tonic-gate (void) closedir(dirp); 21520Sstevel@tonic-gate return (PICL_SUCCESS); 21530Sstevel@tonic-gate } 21540Sstevel@tonic-gate } 21550Sstevel@tonic-gate 21560Sstevel@tonic-gate (void) closedir(dirp); 21570Sstevel@tonic-gate return (PICL_FAILURE); 21580Sstevel@tonic-gate } 21590Sstevel@tonic-gate 21600Sstevel@tonic-gate /* 21610Sstevel@tonic-gate * This function recursively searches the tree for ffb display devices 21620Sstevel@tonic-gate * and add ffb config information 21630Sstevel@tonic-gate */ 21640Sstevel@tonic-gate static int 21650Sstevel@tonic-gate add_ffb_config_info(picl_nodehdl_t rooth) 21660Sstevel@tonic-gate { 21670Sstevel@tonic-gate picl_nodehdl_t nodeh; 21680Sstevel@tonic-gate int err; 21690Sstevel@tonic-gate char piclclass[PICL_CLASSNAMELEN_MAX]; 21700Sstevel@tonic-gate char manfidbuf[FFB_MANUF_BUFSIZE]; 21710Sstevel@tonic-gate int fd; 21720Sstevel@tonic-gate int board_rev; 21730Sstevel@tonic-gate ffb_sys_info_t fsi; 21740Sstevel@tonic-gate ptree_propinfo_t pinfo; 21750Sstevel@tonic-gate 21760Sstevel@tonic-gate for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh, 21770Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 21785028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, 21795028Sfw157321 &nodeh, sizeof (picl_nodehdl_t))) { 21800Sstevel@tonic-gate 21810Sstevel@tonic-gate if (err != PICL_SUCCESS) 21820Sstevel@tonic-gate return (err); 21830Sstevel@tonic-gate 21840Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 21850Sstevel@tonic-gate piclclass, PICL_CLASSNAMELEN_MAX); 21860Sstevel@tonic-gate 21870Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 21880Sstevel@tonic-gate (strcmp(piclclass, PICL_CLASS_DISPLAY) == 0)) { 21890Sstevel@tonic-gate 21900Sstevel@tonic-gate err = open_ffb_device(nodeh, &fd); 21910Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 21920Sstevel@tonic-gate (ioctl(fd, FFB_SYS_INFO, &fsi) >= 0)) { 21930Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 21940Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 21950Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, 21960Sstevel@tonic-gate sizeof (int), PICL_PROP_FFB_BOARD_REV, 21970Sstevel@tonic-gate NULL, NULL); 21980Sstevel@tonic-gate board_rev = fsi.ffb_strap_bits.fld.board_rev; 21990Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 22000Sstevel@tonic-gate &board_rev, NULL); 22010Sstevel@tonic-gate 22020Sstevel@tonic-gate fmt_manf_id(fsi.dac_version, 22030Sstevel@tonic-gate sizeof (manfidbuf), manfidbuf); 22040Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 22050Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 22060Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 22070Sstevel@tonic-gate strlen(manfidbuf) + 1, 22080Sstevel@tonic-gate PICL_PROP_FFB_DAC_VER, NULL, NULL); 22090Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 22100Sstevel@tonic-gate manfidbuf, NULL); 22110Sstevel@tonic-gate 22120Sstevel@tonic-gate fmt_manf_id(fsi.fbram_version, 22130Sstevel@tonic-gate sizeof (manfidbuf), manfidbuf); 22140Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 22150Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 22160Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 22170Sstevel@tonic-gate strlen(manfidbuf) + 1, 22180Sstevel@tonic-gate PICL_PROP_FFB_FBRAM_VER, NULL, 22190Sstevel@tonic-gate NULL); 22200Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 22210Sstevel@tonic-gate manfidbuf, NULL); 22220Sstevel@tonic-gate (void) close(fd); 22230Sstevel@tonic-gate } 22240Sstevel@tonic-gate } else if (add_ffb_config_info(nodeh) != PICL_SUCCESS) 22250Sstevel@tonic-gate return (PICL_FAILURE); 22260Sstevel@tonic-gate } 22270Sstevel@tonic-gate return (PICL_SUCCESS); 22280Sstevel@tonic-gate } 22290Sstevel@tonic-gate 22300Sstevel@tonic-gate static conf_entries_t * 22310Sstevel@tonic-gate free_conf_entries(conf_entries_t *list) 22320Sstevel@tonic-gate { 22330Sstevel@tonic-gate conf_entries_t *el; 22340Sstevel@tonic-gate conf_entries_t *del; 22350Sstevel@tonic-gate 22360Sstevel@tonic-gate if (list == NULL) 22370Sstevel@tonic-gate return (NULL); 22380Sstevel@tonic-gate el = list; 22390Sstevel@tonic-gate while (el != NULL) { 22400Sstevel@tonic-gate del = el; 22410Sstevel@tonic-gate el = el->next; 22420Sstevel@tonic-gate free(del->name); 22430Sstevel@tonic-gate free(del->piclclass); 22440Sstevel@tonic-gate free(del); 22450Sstevel@tonic-gate } 22460Sstevel@tonic-gate return (el); 22470Sstevel@tonic-gate } 22480Sstevel@tonic-gate 22490Sstevel@tonic-gate /* 22500Sstevel@tonic-gate * Reading config order: platform, common 22510Sstevel@tonic-gate */ 22520Sstevel@tonic-gate static conf_entries_t * 22530Sstevel@tonic-gate read_conf_file(char *fname, conf_entries_t *list) 22540Sstevel@tonic-gate { 22550Sstevel@tonic-gate FILE *fp; 22560Sstevel@tonic-gate char lbuf[CONFFILE_LINELEN_MAX]; 22570Sstevel@tonic-gate char *nametok; 22580Sstevel@tonic-gate char *classtok; 22590Sstevel@tonic-gate conf_entries_t *el; 22600Sstevel@tonic-gate conf_entries_t *ptr; 22610Sstevel@tonic-gate 22620Sstevel@tonic-gate if (fname == NULL) 22630Sstevel@tonic-gate return (list); 22640Sstevel@tonic-gate 22650Sstevel@tonic-gate fp = fopen(fname, "r"); 22660Sstevel@tonic-gate 22670Sstevel@tonic-gate if (fp == NULL) 22680Sstevel@tonic-gate return (list); 22690Sstevel@tonic-gate 22700Sstevel@tonic-gate while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) { 22710Sstevel@tonic-gate if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n')) 22720Sstevel@tonic-gate continue; 22730Sstevel@tonic-gate 22740Sstevel@tonic-gate nametok = strtok(lbuf, " \t\n"); 22750Sstevel@tonic-gate if (nametok == NULL) 22760Sstevel@tonic-gate continue; 22770Sstevel@tonic-gate 22780Sstevel@tonic-gate classtok = strtok(NULL, " \t\n"); 22790Sstevel@tonic-gate if (classtok == NULL) 22800Sstevel@tonic-gate continue; 22810Sstevel@tonic-gate 22820Sstevel@tonic-gate el = malloc(sizeof (conf_entries_t)); 22830Sstevel@tonic-gate if (el == NULL) 22840Sstevel@tonic-gate break; 22850Sstevel@tonic-gate el->name = strdup(nametok); 22860Sstevel@tonic-gate el->piclclass = strdup(classtok); 22870Sstevel@tonic-gate if ((el->name == NULL) || (el->piclclass == NULL)) { 22880Sstevel@tonic-gate free(el); 22890Sstevel@tonic-gate return (list); 22900Sstevel@tonic-gate } 22910Sstevel@tonic-gate el->next = NULL; 22920Sstevel@tonic-gate 22930Sstevel@tonic-gate /* 22940Sstevel@tonic-gate * Add it to the end of list 22950Sstevel@tonic-gate */ 22960Sstevel@tonic-gate if (list == NULL) 22970Sstevel@tonic-gate list = el; 22980Sstevel@tonic-gate else { 22990Sstevel@tonic-gate ptr = list; 23000Sstevel@tonic-gate while (ptr->next != NULL) 23010Sstevel@tonic-gate ptr = ptr->next; 23020Sstevel@tonic-gate ptr->next = el; 23030Sstevel@tonic-gate } 23040Sstevel@tonic-gate 23050Sstevel@tonic-gate } 23060Sstevel@tonic-gate (void) fclose(fp); 23070Sstevel@tonic-gate return (list); 23080Sstevel@tonic-gate } 23090Sstevel@tonic-gate 23100Sstevel@tonic-gate /* 23110Sstevel@tonic-gate * Process the devtree conf file and set up the conf_name_class_map list 23120Sstevel@tonic-gate */ 23130Sstevel@tonic-gate static void 23140Sstevel@tonic-gate process_devtree_conf_file(void) 23150Sstevel@tonic-gate { 23160Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 23170Sstevel@tonic-gate char pname[PATH_MAX]; 23180Sstevel@tonic-gate 23190Sstevel@tonic-gate conf_name_class_map = NULL; 23200Sstevel@tonic-gate 23210Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 23220Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 23230Sstevel@tonic-gate (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX); 23240Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, 23250Sstevel@tonic-gate conf_name_class_map); 23260Sstevel@tonic-gate } 23270Sstevel@tonic-gate 23280Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 23290Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 23300Sstevel@tonic-gate (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX); 23310Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, 23320Sstevel@tonic-gate conf_name_class_map); 23330Sstevel@tonic-gate } 23340Sstevel@tonic-gate 23350Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR, 23360Sstevel@tonic-gate DEVTREE_CONFFILE_NAME); 23370Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, conf_name_class_map); 23380Sstevel@tonic-gate } 23390Sstevel@tonic-gate 23400Sstevel@tonic-gate static asr_conf_entries_t *conf_name_asr_map = NULL; 23410Sstevel@tonic-gate 23420Sstevel@tonic-gate static void 23430Sstevel@tonic-gate free_asr_conf_entries(asr_conf_entries_t *list) { 23440Sstevel@tonic-gate asr_conf_entries_t *el; 23450Sstevel@tonic-gate asr_conf_entries_t *del; 23460Sstevel@tonic-gate 23470Sstevel@tonic-gate el = list; 23480Sstevel@tonic-gate while (el != NULL) { 23490Sstevel@tonic-gate del = el; 23500Sstevel@tonic-gate el = el->next; 23510Sstevel@tonic-gate if (del->name) 23520Sstevel@tonic-gate free(del->name); 23530Sstevel@tonic-gate if (del->address) 23540Sstevel@tonic-gate free(del->address); 23550Sstevel@tonic-gate if (del->status) 23560Sstevel@tonic-gate free(del->status); 23570Sstevel@tonic-gate if (del->piclclass) 23580Sstevel@tonic-gate free(del->piclclass); 23590Sstevel@tonic-gate if (del->props) 23600Sstevel@tonic-gate free(del->props); 23610Sstevel@tonic-gate free(del); 23620Sstevel@tonic-gate } 23630Sstevel@tonic-gate } 23640Sstevel@tonic-gate 23650Sstevel@tonic-gate /* 23660Sstevel@tonic-gate * Reading config order: platform, common 23670Sstevel@tonic-gate */ 23680Sstevel@tonic-gate static asr_conf_entries_t * 23690Sstevel@tonic-gate read_asr_conf_file(char *fname, asr_conf_entries_t *list) 23700Sstevel@tonic-gate { 23710Sstevel@tonic-gate FILE *fp; 23720Sstevel@tonic-gate char lbuf[CONFFILE_LINELEN_MAX]; 23730Sstevel@tonic-gate char *nametok; 23740Sstevel@tonic-gate char *classtok; 23750Sstevel@tonic-gate char *statustok; 23760Sstevel@tonic-gate char *addresstok; 23770Sstevel@tonic-gate char *propstok; 23780Sstevel@tonic-gate asr_conf_entries_t *el; 23790Sstevel@tonic-gate asr_conf_entries_t *ptr; 23800Sstevel@tonic-gate 23810Sstevel@tonic-gate if (fname == NULL) 23820Sstevel@tonic-gate return (list); 23830Sstevel@tonic-gate 23840Sstevel@tonic-gate fp = fopen(fname, "r"); 23850Sstevel@tonic-gate if (fp == NULL) 23860Sstevel@tonic-gate return (list); 23870Sstevel@tonic-gate 23880Sstevel@tonic-gate while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) { 23890Sstevel@tonic-gate if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n')) 23900Sstevel@tonic-gate continue; 23910Sstevel@tonic-gate 23920Sstevel@tonic-gate nametok = strtok(lbuf, " \t\n"); 23930Sstevel@tonic-gate if (nametok == NULL) 23940Sstevel@tonic-gate continue; 23950Sstevel@tonic-gate 23960Sstevel@tonic-gate classtok = strtok(NULL, " \t\n"); 23970Sstevel@tonic-gate if (classtok == NULL) 23980Sstevel@tonic-gate continue; 23990Sstevel@tonic-gate 24000Sstevel@tonic-gate statustok = strtok(NULL, " \t\n"); 24010Sstevel@tonic-gate if (statustok == NULL) 24020Sstevel@tonic-gate continue; 24030Sstevel@tonic-gate 24040Sstevel@tonic-gate addresstok = strtok(NULL, " \t\n"); 24050Sstevel@tonic-gate if (addresstok == NULL) 24060Sstevel@tonic-gate continue; 24070Sstevel@tonic-gate 24080Sstevel@tonic-gate /* 24090Sstevel@tonic-gate * props are optional 24100Sstevel@tonic-gate */ 24110Sstevel@tonic-gate propstok = strtok(NULL, " \t\n"); 24120Sstevel@tonic-gate 24130Sstevel@tonic-gate el = malloc(sizeof (asr_conf_entries_t)); 24140Sstevel@tonic-gate if (el == NULL) 24150Sstevel@tonic-gate break; 24160Sstevel@tonic-gate el->name = strdup(nametok); 24170Sstevel@tonic-gate el->piclclass = strdup(classtok); 24180Sstevel@tonic-gate el->status = strdup(statustok); 24190Sstevel@tonic-gate el->address = strdup(addresstok); 24200Sstevel@tonic-gate if (propstok != NULL) 24210Sstevel@tonic-gate el->props = strdup(propstok); 24220Sstevel@tonic-gate else 24230Sstevel@tonic-gate el->props = NULL; 24240Sstevel@tonic-gate if ((el->name == NULL) || (el->piclclass == NULL) || 24250Sstevel@tonic-gate (el->address == NULL) || (el->status == NULL)) { 24260Sstevel@tonic-gate if (el->name) 24270Sstevel@tonic-gate free(el->name); 24280Sstevel@tonic-gate if (el->address) 24290Sstevel@tonic-gate free(el->address); 24300Sstevel@tonic-gate if (el->status) 24310Sstevel@tonic-gate free(el->status); 24320Sstevel@tonic-gate if (el->piclclass) 24330Sstevel@tonic-gate free(el->piclclass); 24340Sstevel@tonic-gate if (el->props) 24350Sstevel@tonic-gate free(el->props); 24360Sstevel@tonic-gate free(el); 24370Sstevel@tonic-gate break; 24380Sstevel@tonic-gate } 24390Sstevel@tonic-gate el->next = NULL; 24400Sstevel@tonic-gate 24410Sstevel@tonic-gate /* 24420Sstevel@tonic-gate * Add it to the end of list 24430Sstevel@tonic-gate */ 24440Sstevel@tonic-gate if (list == NULL) 24450Sstevel@tonic-gate list = el; 24460Sstevel@tonic-gate else { 24470Sstevel@tonic-gate ptr = list; 24480Sstevel@tonic-gate while (ptr->next != NULL) 24490Sstevel@tonic-gate ptr = ptr->next; 24500Sstevel@tonic-gate ptr->next = el; 24510Sstevel@tonic-gate } 24520Sstevel@tonic-gate 24530Sstevel@tonic-gate } 24540Sstevel@tonic-gate (void) fclose(fp); 24550Sstevel@tonic-gate return (list); 24560Sstevel@tonic-gate } 24570Sstevel@tonic-gate 24580Sstevel@tonic-gate /* 24590Sstevel@tonic-gate * Process the asr conf file 24600Sstevel@tonic-gate */ 24610Sstevel@tonic-gate static void 24620Sstevel@tonic-gate process_asrtree_conf_file(void) 24630Sstevel@tonic-gate { 24640Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 24650Sstevel@tonic-gate char pname[PATH_MAX]; 24660Sstevel@tonic-gate 24670Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 24680Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 24690Sstevel@tonic-gate (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX); 24700Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, 24715028Sfw157321 conf_name_asr_map); 24720Sstevel@tonic-gate } 24730Sstevel@tonic-gate 24740Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 24750Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 24760Sstevel@tonic-gate (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX); 24770Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, 24785028Sfw157321 conf_name_asr_map); 24790Sstevel@tonic-gate } 24800Sstevel@tonic-gate 24810Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR, 24820Sstevel@tonic-gate ASRTREE_CONFFILE_NAME); 24830Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, conf_name_asr_map); 24840Sstevel@tonic-gate } 24850Sstevel@tonic-gate 24860Sstevel@tonic-gate /* 24870Sstevel@tonic-gate * This function reads the export file list from ASR 24880Sstevel@tonic-gate */ 24890Sstevel@tonic-gate static int 24900Sstevel@tonic-gate get_asr_export_list(char **exportlist, int *exportlistlen) 24910Sstevel@tonic-gate { 24920Sstevel@tonic-gate struct openpromio oppbuf; 24930Sstevel@tonic-gate struct openpromio *opp = &oppbuf; 24940Sstevel@tonic-gate int d; 24950Sstevel@tonic-gate int listsize; 24960Sstevel@tonic-gate 24970Sstevel@tonic-gate d = open("/dev/openprom", O_RDWR); 24980Sstevel@tonic-gate if (d < 0) 24990Sstevel@tonic-gate return (0); 25000Sstevel@tonic-gate 25010Sstevel@tonic-gate if (ioctl(d, OPROMEXPORTLEN, opp) == -1) { 25020Sstevel@tonic-gate (void) close(d); 25030Sstevel@tonic-gate return (0); 25040Sstevel@tonic-gate } 25050Sstevel@tonic-gate listsize = opp->oprom_size; 25060Sstevel@tonic-gate opp = (struct openpromio *)malloc(sizeof (struct openpromio) + 25070Sstevel@tonic-gate listsize); 25080Sstevel@tonic-gate if (opp == NULL) { 25090Sstevel@tonic-gate (void) close(d); 25100Sstevel@tonic-gate return (0); 25110Sstevel@tonic-gate } 25120Sstevel@tonic-gate (void) memset(opp, '\0', sizeof (struct openpromio) + listsize); 25130Sstevel@tonic-gate opp->oprom_size = listsize; 25140Sstevel@tonic-gate if (ioctl(d, OPROMEXPORT, opp) == -1) { 25150Sstevel@tonic-gate free(opp); 25160Sstevel@tonic-gate (void) close(d); 25170Sstevel@tonic-gate return (0); 25180Sstevel@tonic-gate } 25190Sstevel@tonic-gate *exportlist = malloc(listsize); 25200Sstevel@tonic-gate if (*exportlist == NULL) { 25210Sstevel@tonic-gate free(opp); 25220Sstevel@tonic-gate (void) close(d); 25230Sstevel@tonic-gate return (0); 25240Sstevel@tonic-gate } 25250Sstevel@tonic-gate (void) memcpy(*exportlist, opp->oprom_array, opp->oprom_size); 25260Sstevel@tonic-gate free(opp); 25270Sstevel@tonic-gate *exportlistlen = opp->oprom_size; 25280Sstevel@tonic-gate (void) close(d); 25290Sstevel@tonic-gate return (1); 25300Sstevel@tonic-gate } 25310Sstevel@tonic-gate 25320Sstevel@tonic-gate /* 25330Sstevel@tonic-gate * Parses properties string, fills in triplet structure with first 25340Sstevel@tonic-gate * type, name, val triplet and returns pointer to next property. 25350Sstevel@tonic-gate * Returns NULL if no valid triplet found 25360Sstevel@tonic-gate * CAUTION: drops \0 characters over separator characters: if you 25370Sstevel@tonic-gate * want to parse the string twice, you'll have to take a copy. 25380Sstevel@tonic-gate */ 25390Sstevel@tonic-gate static char * 25400Sstevel@tonic-gate parse_props_string(char *props, asr_prop_triplet_t *triplet) 25410Sstevel@tonic-gate { 25420Sstevel@tonic-gate char *prop_name; 25430Sstevel@tonic-gate char *prop_val; 25440Sstevel@tonic-gate char *prop_next; 25450Sstevel@tonic-gate 25460Sstevel@tonic-gate prop_name = strchr(props, '?'); 25470Sstevel@tonic-gate if (prop_name == NULL) 25480Sstevel@tonic-gate return (NULL); 25490Sstevel@tonic-gate *prop_name++ = '\0'; 25500Sstevel@tonic-gate prop_val = strchr(prop_name, '='); 25510Sstevel@tonic-gate if (prop_val == NULL) 25520Sstevel@tonic-gate return (NULL); 25530Sstevel@tonic-gate *prop_val++ = '\0'; 25540Sstevel@tonic-gate triplet->proptype = props; 25550Sstevel@tonic-gate triplet->propname = prop_name; 25560Sstevel@tonic-gate triplet->propval = prop_val; 25570Sstevel@tonic-gate prop_next = strchr(prop_val, ':'); 25580Sstevel@tonic-gate if (prop_next == NULL) 25590Sstevel@tonic-gate return (prop_val - 1); 25600Sstevel@tonic-gate *prop_next++ = '\0'; 25610Sstevel@tonic-gate return (prop_next); 25620Sstevel@tonic-gate } 25630Sstevel@tonic-gate 25640Sstevel@tonic-gate static int 25650Sstevel@tonic-gate add_status_prop(picl_nodehdl_t chdh, char *status) 25660Sstevel@tonic-gate { 25670Sstevel@tonic-gate ptree_propinfo_t propinfo; 25680Sstevel@tonic-gate picl_prophdl_t proph; 25690Sstevel@tonic-gate int err; 25700Sstevel@tonic-gate 25710Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 25720Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(status) + 1, 25730Sstevel@tonic-gate PICL_PROP_STATUS, NULL, NULL); 25740Sstevel@tonic-gate if (err != PICL_SUCCESS) 25750Sstevel@tonic-gate return (err); 25760Sstevel@tonic-gate err = ptree_create_and_add_prop(chdh, &propinfo, status, &proph); 25770Sstevel@tonic-gate return (err); 25780Sstevel@tonic-gate } 25790Sstevel@tonic-gate 25800Sstevel@tonic-gate static void 25810Sstevel@tonic-gate create_asr_node(char *parent, char *child, char *unitaddr, char *class, 25820Sstevel@tonic-gate char *status, char *props) 25830Sstevel@tonic-gate { 25840Sstevel@tonic-gate char ptreepath[PATH_MAX]; 25850Sstevel@tonic-gate char nodename[PICL_PROPNAMELEN_MAX]; 25860Sstevel@tonic-gate char ua[MAX_UNIT_ADDRESS_LEN]; 25870Sstevel@tonic-gate char *props_copy = NULL; 25880Sstevel@tonic-gate char *next; 25890Sstevel@tonic-gate char *prop_string; 25900Sstevel@tonic-gate boolean_t found = B_FALSE; 25910Sstevel@tonic-gate picl_nodehdl_t nodeh; 25920Sstevel@tonic-gate picl_nodehdl_t chdh; 25930Sstevel@tonic-gate asr_prop_triplet_t triple; 25940Sstevel@tonic-gate ptree_propinfo_t propinfo; 25950Sstevel@tonic-gate picl_prophdl_t proph; 25960Sstevel@tonic-gate int val; 25970Sstevel@tonic-gate int err; 25980Sstevel@tonic-gate 25990Sstevel@tonic-gate (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX); 26000Sstevel@tonic-gate (void) strlcat(ptreepath, parent, PATH_MAX); 26010Sstevel@tonic-gate 26020Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS) 26030Sstevel@tonic-gate return; 26040Sstevel@tonic-gate /* 26050Sstevel@tonic-gate * see if the required child node already exists 26060Sstevel@tonic-gate */ 26070Sstevel@tonic-gate for (err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 26080Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 26090Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 26105028Sfw157321 sizeof (picl_nodehdl_t))) { 26110Sstevel@tonic-gate if (err != PICL_SUCCESS) 26120Sstevel@tonic-gate break; 26130Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_NAME, 26140Sstevel@tonic-gate (void *)nodename, PICL_PROPNAMELEN_MAX); 26150Sstevel@tonic-gate if (err != PICL_SUCCESS) 26160Sstevel@tonic-gate break; 26170Sstevel@tonic-gate if (strcmp(nodename, child) != 0) 26180Sstevel@tonic-gate continue; 26190Sstevel@tonic-gate /* 26200Sstevel@tonic-gate * found a candidate child node 26210Sstevel@tonic-gate */ 26220Sstevel@tonic-gate if (unitaddr) { 26230Sstevel@tonic-gate /* 26240Sstevel@tonic-gate * does it match the required unit address? 26250Sstevel@tonic-gate */ 26260Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 26270Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, ua, sizeof (ua)); 26280Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 26290Sstevel@tonic-gate continue; 26300Sstevel@tonic-gate if (err != PICL_SUCCESS) 26310Sstevel@tonic-gate break; 26320Sstevel@tonic-gate if (strcmp(unitaddr, ua) != 0) 26330Sstevel@tonic-gate continue; 26340Sstevel@tonic-gate } 26350Sstevel@tonic-gate if (props == NULL) { 26360Sstevel@tonic-gate next = ""; 26370Sstevel@tonic-gate } else if (props_copy == NULL) { 26380Sstevel@tonic-gate props_copy = strdup(props); 26390Sstevel@tonic-gate if (props_copy == NULL) 26400Sstevel@tonic-gate return; 26410Sstevel@tonic-gate next = props_copy; 26420Sstevel@tonic-gate } 26430Sstevel@tonic-gate while ((next = parse_props_string(next, &triple)) != NULL) { 26440Sstevel@tonic-gate err = ptree_get_prop_by_name(chdh, triple.propname, 26450Sstevel@tonic-gate &proph); 26460Sstevel@tonic-gate if (err != PICL_SUCCESS) 26470Sstevel@tonic-gate break; 26480Sstevel@tonic-gate err = ptree_get_propinfo(proph, &propinfo); 26490Sstevel@tonic-gate if (err != PICL_SUCCESS) 26500Sstevel@tonic-gate break; 26510Sstevel@tonic-gate err = PICL_FAILURE; 26520Sstevel@tonic-gate switch (propinfo.piclinfo.type) { 26530Sstevel@tonic-gate case PICL_PTYPE_INT: 26540Sstevel@tonic-gate case PICL_PTYPE_UNSIGNED_INT: 26550Sstevel@tonic-gate if (strcmp(triple.proptype, "I") != 0) 26560Sstevel@tonic-gate break; 26570Sstevel@tonic-gate err = ptree_get_propval(proph, (void *)&val, 26580Sstevel@tonic-gate sizeof (val)); 26590Sstevel@tonic-gate if (err != PICL_SUCCESS) 26600Sstevel@tonic-gate break; 26610Sstevel@tonic-gate if (val != atoi(triple.propval)) 26620Sstevel@tonic-gate err = PICL_FAILURE; 26630Sstevel@tonic-gate break; 26640Sstevel@tonic-gate case PICL_PTYPE_CHARSTRING: 26650Sstevel@tonic-gate if (strcmp(triple.proptype, "S") != 0) 26660Sstevel@tonic-gate break; 26670Sstevel@tonic-gate prop_string = malloc(propinfo.piclinfo.size); 26680Sstevel@tonic-gate if (prop_string == NULL) 26690Sstevel@tonic-gate break; 26700Sstevel@tonic-gate err = ptree_get_propval(proph, 26710Sstevel@tonic-gate (void *)prop_string, 26720Sstevel@tonic-gate propinfo.piclinfo.size); 26730Sstevel@tonic-gate if (err != PICL_SUCCESS) { 26740Sstevel@tonic-gate free(prop_string); 26750Sstevel@tonic-gate break; 26760Sstevel@tonic-gate } 26770Sstevel@tonic-gate if (strcmp(prop_string, triple.propval) != 0) 26780Sstevel@tonic-gate err = PICL_FAILURE; 26790Sstevel@tonic-gate free(prop_string); 26800Sstevel@tonic-gate break; 26810Sstevel@tonic-gate default: 26820Sstevel@tonic-gate break; 26830Sstevel@tonic-gate } 26840Sstevel@tonic-gate if (err != PICL_SUCCESS) { 26850Sstevel@tonic-gate break; 26860Sstevel@tonic-gate } 26870Sstevel@tonic-gate } 26880Sstevel@tonic-gate if (next == NULL) { 26890Sstevel@tonic-gate found = B_TRUE; 26900Sstevel@tonic-gate break; 26910Sstevel@tonic-gate } 26920Sstevel@tonic-gate } 26930Sstevel@tonic-gate if (props_copy) 26940Sstevel@tonic-gate free(props_copy); 26950Sstevel@tonic-gate if (found) { 26960Sstevel@tonic-gate /* 26970Sstevel@tonic-gate * does the pre-existing node have a status property? 26980Sstevel@tonic-gate */ 26990Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_STATUS, 27000Sstevel@tonic-gate ua, sizeof (ua)); 27010Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 27020Sstevel@tonic-gate (void) add_status_prop(chdh, status); 27030Sstevel@tonic-gate if (err != PICL_SUCCESS) 27040Sstevel@tonic-gate return; 27050Sstevel@tonic-gate if ((strcmp(ua, ASR_DISABLED) == 0) || 27060Sstevel@tonic-gate (strcmp(ua, ASR_FAILED) == 0) || 27070Sstevel@tonic-gate ((strcmp(status, ASR_DISABLED) != 0) && 27080Sstevel@tonic-gate (strcmp(status, ASR_FAILED) != 0))) { 27090Sstevel@tonic-gate return; 27100Sstevel@tonic-gate } 27110Sstevel@tonic-gate /* 27120Sstevel@tonic-gate * more urgent status now, so replace existing value 27130Sstevel@tonic-gate */ 27140Sstevel@tonic-gate err = ptree_get_prop_by_name(chdh, PICL_PROP_STATUS, &proph); 27150Sstevel@tonic-gate if (err != PICL_SUCCESS) 27160Sstevel@tonic-gate return; 27170Sstevel@tonic-gate (void) ptree_delete_prop(proph); 27180Sstevel@tonic-gate (void) ptree_destroy_prop(proph); 27190Sstevel@tonic-gate err = add_status_prop(chdh, status); 27200Sstevel@tonic-gate if (err != PICL_SUCCESS) 27210Sstevel@tonic-gate return; 27220Sstevel@tonic-gate return; 27230Sstevel@tonic-gate } 27240Sstevel@tonic-gate 27250Sstevel@tonic-gate /* 27260Sstevel@tonic-gate * typical case, node needs adding together with a set of properties 27270Sstevel@tonic-gate */ 27280Sstevel@tonic-gate if (ptree_create_and_add_node(nodeh, child, class, &chdh) == 27290Sstevel@tonic-gate PICL_SUCCESS) { 27300Sstevel@tonic-gate (void) add_status_prop(chdh, status); 27310Sstevel@tonic-gate if (unitaddr) { 27320Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 27330Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, 27340Sstevel@tonic-gate PICL_READ, strlen(unitaddr) + 1, 27350Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL); 27360Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, &propinfo, 27370Sstevel@tonic-gate unitaddr, &proph); 27380Sstevel@tonic-gate (void) strlcpy(ptreepath, parent, PATH_MAX); 27390Sstevel@tonic-gate (void) strlcat(ptreepath, "/", PATH_MAX); 27400Sstevel@tonic-gate (void) strlcat(ptreepath, child, PATH_MAX); 27410Sstevel@tonic-gate (void) strlcat(ptreepath, "@", PATH_MAX); 27420Sstevel@tonic-gate (void) strlcat(ptreepath, unitaddr, PATH_MAX); 27430Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 27440Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, 27450Sstevel@tonic-gate PICL_READ, strlen(ptreepath) + 1, 27460Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, NULL, NULL); 27470Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, &propinfo, 27480Sstevel@tonic-gate ptreepath, &proph); 27490Sstevel@tonic-gate } 27500Sstevel@tonic-gate next = props; 27510Sstevel@tonic-gate while ((next = parse_props_string(next, &triple)) != NULL) { 27520Sstevel@tonic-gate /* 27530Sstevel@tonic-gate * only handle int and string properties for 27540Sstevel@tonic-gate * simplicity 27550Sstevel@tonic-gate */ 27560Sstevel@tonic-gate if (strcmp(triple.proptype, "I") == 0) { 27570Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 27580Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 27590Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, 27600Sstevel@tonic-gate sizeof (int), triple.propname, NULL, NULL); 27610Sstevel@tonic-gate val = atoi(triple.propval); 27620Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, 27630Sstevel@tonic-gate &propinfo, &val, &proph); 27640Sstevel@tonic-gate } else { 27650Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 27660Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 27670Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 27680Sstevel@tonic-gate strlen(triple.propval) + 1, 27695028Sfw157321 triple.propname, NULL, NULL); 27700Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, 27710Sstevel@tonic-gate &propinfo, triple.propval, &proph); 27720Sstevel@tonic-gate } 27730Sstevel@tonic-gate } 27740Sstevel@tonic-gate } 27750Sstevel@tonic-gate } 27760Sstevel@tonic-gate 27770Sstevel@tonic-gate static void 27780Sstevel@tonic-gate add_asr_nodes() 27790Sstevel@tonic-gate { 27800Sstevel@tonic-gate char *asrexport; 27810Sstevel@tonic-gate int asrexportlen; 27820Sstevel@tonic-gate asr_conf_entries_t *c = NULL; 27830Sstevel@tonic-gate int i; 27840Sstevel@tonic-gate char *key; 27850Sstevel@tonic-gate char *child; 27860Sstevel@tonic-gate char *unitaddr; 27870Sstevel@tonic-gate uint16_t count; 27880Sstevel@tonic-gate int disabled; 27890Sstevel@tonic-gate 27900Sstevel@tonic-gate if (get_asr_export_list(&asrexport, &asrexportlen) == 0) 27910Sstevel@tonic-gate return; 27920Sstevel@tonic-gate process_asrtree_conf_file(); 27930Sstevel@tonic-gate if (conf_name_asr_map == NULL) 27940Sstevel@tonic-gate return; 27950Sstevel@tonic-gate i = 0; 27960Sstevel@tonic-gate while (i < asrexportlen) { 27970Sstevel@tonic-gate key = &asrexport[i]; 27980Sstevel@tonic-gate i += strlen(key) + 1; 27990Sstevel@tonic-gate if (i >= asrexportlen) 28000Sstevel@tonic-gate break; 28010Sstevel@tonic-gate 28020Sstevel@tonic-gate /* 28030Sstevel@tonic-gate * next byte tells us whether failed by diags or manually 28040Sstevel@tonic-gate * disabled 28050Sstevel@tonic-gate */ 28060Sstevel@tonic-gate disabled = asrexport[i]; 28070Sstevel@tonic-gate i++; 28080Sstevel@tonic-gate if (i >= asrexportlen) 28090Sstevel@tonic-gate break; 28100Sstevel@tonic-gate 28110Sstevel@tonic-gate /* 28120Sstevel@tonic-gate * only type 1 supported 28130Sstevel@tonic-gate */ 28140Sstevel@tonic-gate if (asrexport[i] != 1) 28150Sstevel@tonic-gate break; 28160Sstevel@tonic-gate i++; 28170Sstevel@tonic-gate if (i >= asrexportlen) 28180Sstevel@tonic-gate break; 28190Sstevel@tonic-gate 28200Sstevel@tonic-gate /* 28210Sstevel@tonic-gate * next two bytes give size of reason string 28220Sstevel@tonic-gate */ 28230Sstevel@tonic-gate count = (asrexport[i] << 8) | asrexport[i + 1]; 28240Sstevel@tonic-gate i += count + 2; 28250Sstevel@tonic-gate if (i > asrexportlen) 28260Sstevel@tonic-gate break; 28270Sstevel@tonic-gate 28280Sstevel@tonic-gate /* 28290Sstevel@tonic-gate * now look for key in conf file info 28300Sstevel@tonic-gate */ 28310Sstevel@tonic-gate c = conf_name_asr_map; 28320Sstevel@tonic-gate while (c != NULL) { 28330Sstevel@tonic-gate if (strcmp(key, c->name) == 0) { 28340Sstevel@tonic-gate child = strrchr(c->address, '/'); 28350Sstevel@tonic-gate *child++ = '\0'; 28360Sstevel@tonic-gate unitaddr = strchr(child, '@'); 28370Sstevel@tonic-gate if (unitaddr) 28380Sstevel@tonic-gate *unitaddr++ = '\0'; 28390Sstevel@tonic-gate if (strcmp(c->status, ASR_DISABLED) == 0) { 28400Sstevel@tonic-gate create_asr_node(c->address, child, 28410Sstevel@tonic-gate unitaddr, c->piclclass, disabled ? 28420Sstevel@tonic-gate ASR_DISABLED : ASR_FAILED, 28430Sstevel@tonic-gate c->props); 28440Sstevel@tonic-gate } else { 28450Sstevel@tonic-gate create_asr_node(c->address, child, 28460Sstevel@tonic-gate unitaddr, c->piclclass, c->status, 28470Sstevel@tonic-gate c->props); 28480Sstevel@tonic-gate } 28490Sstevel@tonic-gate } 28500Sstevel@tonic-gate c = c->next; 28510Sstevel@tonic-gate } 28520Sstevel@tonic-gate } 28530Sstevel@tonic-gate 28540Sstevel@tonic-gate free_asr_conf_entries(conf_name_asr_map); 28550Sstevel@tonic-gate free(asrexport); 28560Sstevel@tonic-gate } 28570Sstevel@tonic-gate 28580Sstevel@tonic-gate /* 28590Sstevel@tonic-gate * This function adds information to the /platform node 28600Sstevel@tonic-gate */ 28610Sstevel@tonic-gate static int 28620Sstevel@tonic-gate add_platform_info(picl_nodehdl_t plafh) 28630Sstevel@tonic-gate { 28640Sstevel@tonic-gate struct utsname uts_info; 28650Sstevel@tonic-gate int err; 28660Sstevel@tonic-gate ptree_propinfo_t propinfo; 28670Sstevel@tonic-gate picl_prophdl_t proph; 28680Sstevel@tonic-gate 28690Sstevel@tonic-gate if (uname(&uts_info) < 0) 28700Sstevel@tonic-gate return (PICL_FAILURE); 28710Sstevel@tonic-gate 28720Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 28730Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.sysname) + 1, 28740Sstevel@tonic-gate PICL_PROP_SYSNAME, NULL, NULL); 28750Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.sysname, 28760Sstevel@tonic-gate &proph); 28770Sstevel@tonic-gate if (err != PICL_SUCCESS) 28780Sstevel@tonic-gate return (err); 28790Sstevel@tonic-gate 28800Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 28810Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.nodename) + 1, 28820Sstevel@tonic-gate PICL_PROP_NODENAME, NULL, NULL); 28830Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.nodename, 28840Sstevel@tonic-gate &proph); 28850Sstevel@tonic-gate if (err != PICL_SUCCESS) 28860Sstevel@tonic-gate return (err); 28870Sstevel@tonic-gate 28880Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 28890Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.release) + 1, 28900Sstevel@tonic-gate PICL_PROP_RELEASE, NULL, NULL); 28910Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.release, 28920Sstevel@tonic-gate &proph); 28930Sstevel@tonic-gate if (err != PICL_SUCCESS) 28940Sstevel@tonic-gate return (err); 28950Sstevel@tonic-gate 28960Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 28970Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.version) + 1, 28980Sstevel@tonic-gate PICL_PROP_VERSION, NULL, NULL); 28990Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.version, 29000Sstevel@tonic-gate &proph); 29010Sstevel@tonic-gate if (err != PICL_SUCCESS) 29020Sstevel@tonic-gate return (err); 29030Sstevel@tonic-gate 29040Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 29050Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.machine) + 1, 29060Sstevel@tonic-gate PICL_PROP_MACHINE, NULL, NULL); 29070Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.machine, 29080Sstevel@tonic-gate &proph); 29090Sstevel@tonic-gate return (err); 29100Sstevel@tonic-gate } 29110Sstevel@tonic-gate 29120Sstevel@tonic-gate /* 29130Sstevel@tonic-gate * Get first 32-bit value from the reg property 29140Sstevel@tonic-gate */ 29150Sstevel@tonic-gate static int 29160Sstevel@tonic-gate get_first_reg_word(picl_nodehdl_t nodeh, uint32_t *regval) 29170Sstevel@tonic-gate { 29180Sstevel@tonic-gate int err; 29190Sstevel@tonic-gate uint32_t *regbuf; 29200Sstevel@tonic-gate picl_prophdl_t regh; 29210Sstevel@tonic-gate ptree_propinfo_t pinfo; 29220Sstevel@tonic-gate 29230Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 29240Sstevel@tonic-gate if (err != PICL_SUCCESS) /* no reg property */ 29250Sstevel@tonic-gate return (err); 29260Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 29270Sstevel@tonic-gate if (err != PICL_SUCCESS) 29280Sstevel@tonic-gate return (err); 29290Sstevel@tonic-gate if (pinfo.piclinfo.size < sizeof (uint32_t)) /* too small */ 29300Sstevel@tonic-gate return (PICL_FAILURE); 29310Sstevel@tonic-gate regbuf = alloca(pinfo.piclinfo.size); 29320Sstevel@tonic-gate if (regbuf == NULL) 29330Sstevel@tonic-gate return (PICL_FAILURE); 29340Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, pinfo.piclinfo.size); 29350Sstevel@tonic-gate if (err != PICL_SUCCESS) 29360Sstevel@tonic-gate return (err); 29370Sstevel@tonic-gate *regval = *regbuf; /* get first 32-bit value */ 29380Sstevel@tonic-gate return (PICL_SUCCESS); 29390Sstevel@tonic-gate } 29400Sstevel@tonic-gate 29410Sstevel@tonic-gate /* 29420Sstevel@tonic-gate * Get device ID from the reg property 29430Sstevel@tonic-gate */ 29440Sstevel@tonic-gate static int 29450Sstevel@tonic-gate get_device_id(picl_nodehdl_t nodeh, uint32_t *dev_id) 29460Sstevel@tonic-gate { 29470Sstevel@tonic-gate int err; 29480Sstevel@tonic-gate uint32_t regval; 29490Sstevel@tonic-gate 29500Sstevel@tonic-gate err = get_first_reg_word(nodeh, ®val); 29510Sstevel@tonic-gate if (err != PICL_SUCCESS) 29520Sstevel@tonic-gate return (err); 29530Sstevel@tonic-gate 29540Sstevel@tonic-gate *dev_id = PCI_DEVICE_ID(regval); 29550Sstevel@tonic-gate return (PICL_SUCCESS); 29560Sstevel@tonic-gate } 29570Sstevel@tonic-gate 29580Sstevel@tonic-gate /* 29590Sstevel@tonic-gate * add Slot property for children of SBUS node 29600Sstevel@tonic-gate */ 29610Sstevel@tonic-gate /* ARGSUSED */ 29620Sstevel@tonic-gate static int 29630Sstevel@tonic-gate add_sbus_slots(picl_nodehdl_t pcih, void *args) 29640Sstevel@tonic-gate { 29650Sstevel@tonic-gate picl_nodehdl_t nodeh; 29660Sstevel@tonic-gate uint32_t slot; 29670Sstevel@tonic-gate int err; 29680Sstevel@tonic-gate ptree_propinfo_t pinfo; 29690Sstevel@tonic-gate 29700Sstevel@tonic-gate for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 29710Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 29725028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 29735028Sfw157321 sizeof (picl_nodehdl_t))) { 29740Sstevel@tonic-gate if (err != PICL_SUCCESS) 29750Sstevel@tonic-gate return (err); 29760Sstevel@tonic-gate 29770Sstevel@tonic-gate if (get_first_reg_word(nodeh, &slot) != 0) 29780Sstevel@tonic-gate continue; 29790Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 29800Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t), 29810Sstevel@tonic-gate PICL_PROP_SLOT, NULL, NULL); 29820Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, &slot, NULL); 29830Sstevel@tonic-gate } 29840Sstevel@tonic-gate 29850Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 29860Sstevel@tonic-gate } 29870Sstevel@tonic-gate 29880Sstevel@tonic-gate /* 29890Sstevel@tonic-gate * This function creates a Slot property for SBUS child nodes 29900Sstevel@tonic-gate * which can be correlated with the slot they are plugged into 29910Sstevel@tonic-gate * on the motherboard. 29920Sstevel@tonic-gate */ 29930Sstevel@tonic-gate static int 29940Sstevel@tonic-gate set_sbus_slot(picl_nodehdl_t plafh) 29950Sstevel@tonic-gate { 29960Sstevel@tonic-gate int err; 29970Sstevel@tonic-gate 29980Sstevel@tonic-gate err = ptree_walk_tree_by_class(plafh, PICL_CLASS_SBUS, NULL, 29990Sstevel@tonic-gate add_sbus_slots); 30000Sstevel@tonic-gate 30010Sstevel@tonic-gate return (err); 30020Sstevel@tonic-gate } 30030Sstevel@tonic-gate 30040Sstevel@tonic-gate /* 3005944Svenki * add DeviceID property for children of PCI/PCIEX node 30060Sstevel@tonic-gate */ 30070Sstevel@tonic-gate /* ARGSUSED */ 30080Sstevel@tonic-gate static int 30090Sstevel@tonic-gate add_pci_deviceids(picl_nodehdl_t pcih, void *args) 30100Sstevel@tonic-gate { 30110Sstevel@tonic-gate picl_nodehdl_t nodeh; 30120Sstevel@tonic-gate uint32_t dev_id; 30130Sstevel@tonic-gate int err; 30140Sstevel@tonic-gate ptree_propinfo_t pinfo; 30150Sstevel@tonic-gate 30160Sstevel@tonic-gate for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 30170Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 30185028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 30195028Sfw157321 sizeof (picl_nodehdl_t))) { 30200Sstevel@tonic-gate if (err != PICL_SUCCESS) 30210Sstevel@tonic-gate return (err); 30220Sstevel@tonic-gate 30230Sstevel@tonic-gate if (get_device_id(nodeh, &dev_id) != 0) 30240Sstevel@tonic-gate continue; 30250Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 30260Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t), 30270Sstevel@tonic-gate PICL_PROP_DEVICE_ID, NULL, NULL); 30280Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, &dev_id, NULL); 30290Sstevel@tonic-gate } 30300Sstevel@tonic-gate 30310Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 30320Sstevel@tonic-gate } 30330Sstevel@tonic-gate 30340Sstevel@tonic-gate /* 3035944Svenki * This function creates a DeviceID property for PCI/PCIEX child nodes 30360Sstevel@tonic-gate * which can be correlated with the slot they are plugged into 30370Sstevel@tonic-gate * on the motherboard. 30380Sstevel@tonic-gate */ 3039944Svenki static void 3040944Svenki set_pci_pciex_deviceid(picl_nodehdl_t plafh) 30410Sstevel@tonic-gate { 3042944Svenki (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCI, NULL, 30430Sstevel@tonic-gate add_pci_deviceids); 30440Sstevel@tonic-gate 3045944Svenki (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, NULL, 3046944Svenki add_pci_deviceids); 30470Sstevel@tonic-gate } 30480Sstevel@tonic-gate 30490Sstevel@tonic-gate /* 30500Sstevel@tonic-gate * Default UnitAddress encode function 30510Sstevel@tonic-gate */ 30520Sstevel@tonic-gate static int 30530Sstevel@tonic-gate encode_default_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 30540Sstevel@tonic-gate { 30550Sstevel@tonic-gate int i, len; 30560Sstevel@tonic-gate 30570Sstevel@tonic-gate /* 30580Sstevel@tonic-gate * Encode UnitAddress as %a,%b,%c,...,%n 30590Sstevel@tonic-gate */ 30600Sstevel@tonic-gate if (addrcells < 1) 30610Sstevel@tonic-gate return (-1); 30620Sstevel@tonic-gate 30630Sstevel@tonic-gate len = snprintf(buf, sz, "%x", *regprop); 30640Sstevel@tonic-gate for (i = 1; i < addrcells && len < sz; i++) 30650Sstevel@tonic-gate len += snprintf(&buf[len], sz-len, ",%x", regprop[i]); 30660Sstevel@tonic-gate 30670Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 30680Sstevel@tonic-gate } 30690Sstevel@tonic-gate 30700Sstevel@tonic-gate /* 30710Sstevel@tonic-gate * UnitAddress encode function where the last component is not printed 30720Sstevel@tonic-gate * unless non-zero. 30730Sstevel@tonic-gate */ 30740Sstevel@tonic-gate static int 30750Sstevel@tonic-gate encode_optional_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 30760Sstevel@tonic-gate { 30770Sstevel@tonic-gate int retval; 30780Sstevel@tonic-gate 30790Sstevel@tonic-gate /* 30800Sstevel@tonic-gate * Encode UnitAddress as %a,%b,%c,...,%n where the last component 30810Sstevel@tonic-gate * is printed only if non-zero. 30820Sstevel@tonic-gate */ 30830Sstevel@tonic-gate if (addrcells > 1 && regprop[addrcells-1] == 0) 30840Sstevel@tonic-gate retval = encode_default_unitaddr(buf, sz, regprop, addrcells-1); 30850Sstevel@tonic-gate else 30860Sstevel@tonic-gate retval = encode_default_unitaddr(buf, sz, regprop, addrcells); 30870Sstevel@tonic-gate 30880Sstevel@tonic-gate return (retval); 30890Sstevel@tonic-gate } 30900Sstevel@tonic-gate 30910Sstevel@tonic-gate 30920Sstevel@tonic-gate /* 30930Sstevel@tonic-gate * UnitAddress encode function for SCSI class of devices 30940Sstevel@tonic-gate */ 30950Sstevel@tonic-gate static int 30960Sstevel@tonic-gate encode_scsi_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 30970Sstevel@tonic-gate { 30980Sstevel@tonic-gate int len, retval; 30990Sstevel@tonic-gate 31000Sstevel@tonic-gate /* 31010Sstevel@tonic-gate * #address-cells Format 31020Sstevel@tonic-gate * 2 second component printed only if non-zero 31030Sstevel@tonic-gate * 31040Sstevel@tonic-gate * 4 regprop: phys_hi phys_lo lun_hi lun_lo 31050Sstevel@tonic-gate * UnitAddr: w<phys_hi><phys_lo>,<lun_lo> 31060Sstevel@tonic-gate */ 31070Sstevel@tonic-gate 31080Sstevel@tonic-gate if (addrcells == 2) { 31090Sstevel@tonic-gate retval = encode_optional_unitaddr(buf, sz, regprop, addrcells); 31100Sstevel@tonic-gate } else if (addrcells == 4) { 31110Sstevel@tonic-gate len = snprintf(buf, sz, "w%08x%08x,%x", regprop[0], regprop[1], 31120Sstevel@tonic-gate regprop[3]); 31130Sstevel@tonic-gate retval = (len >= sz) ? -1 : 0; 31140Sstevel@tonic-gate } else 31150Sstevel@tonic-gate retval = -1; 31160Sstevel@tonic-gate 31170Sstevel@tonic-gate return (retval); 31180Sstevel@tonic-gate } 31190Sstevel@tonic-gate 31200Sstevel@tonic-gate /* 31210Sstevel@tonic-gate * UnitAddress encode function for UPA devices 31220Sstevel@tonic-gate */ 31230Sstevel@tonic-gate static int 31240Sstevel@tonic-gate encode_upa_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 31250Sstevel@tonic-gate { 31260Sstevel@tonic-gate int len; 31270Sstevel@tonic-gate 31280Sstevel@tonic-gate if (addrcells != 2) 31290Sstevel@tonic-gate return (-1); 31300Sstevel@tonic-gate 31310Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", (regprop[0]/2)&0x1f, regprop[1]); 31320Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 31330Sstevel@tonic-gate } 31340Sstevel@tonic-gate 31350Sstevel@tonic-gate /* 31360Sstevel@tonic-gate * UnitAddress encode function for GPTWO, JBUS devices 31370Sstevel@tonic-gate */ 31380Sstevel@tonic-gate static int 31390Sstevel@tonic-gate encode_gptwo_jbus_unitaddr(char *buf, int sz, uint32_t *regprop, 31400Sstevel@tonic-gate uint_t addrcells) 31410Sstevel@tonic-gate { 31420Sstevel@tonic-gate uint32_t hi, lo; 31430Sstevel@tonic-gate int len, id, off; 31440Sstevel@tonic-gate 31450Sstevel@tonic-gate if (addrcells != 2) 31460Sstevel@tonic-gate return (-1); 31470Sstevel@tonic-gate 31480Sstevel@tonic-gate hi = regprop[0]; 31490Sstevel@tonic-gate lo = regprop[1]; 31500Sstevel@tonic-gate 31510Sstevel@tonic-gate if (hi & 0x400) { 31520Sstevel@tonic-gate id = ((hi & 0x1) << 9) | (lo >> 23); /* agent id */ 31530Sstevel@tonic-gate off = lo & 0x7fffff; /* config offset */ 31540Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", id, off); 31550Sstevel@tonic-gate } else { 31560Sstevel@tonic-gate len = snprintf(buf, sz, "m%x,%x", hi, lo); 31570Sstevel@tonic-gate } 31580Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 31590Sstevel@tonic-gate } 31600Sstevel@tonic-gate 31610Sstevel@tonic-gate /* 31620Sstevel@tonic-gate * UnitAddress encode function for PCI devices 31630Sstevel@tonic-gate */ 31640Sstevel@tonic-gate static int 31650Sstevel@tonic-gate encode_pci_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 31660Sstevel@tonic-gate { 31670Sstevel@tonic-gate typedef struct { 31680Sstevel@tonic-gate uint32_t n:1, /* relocatable */ 31690Sstevel@tonic-gate p:1, /* prefetchable */ 31700Sstevel@tonic-gate t:1, /* address region aliases */ 31710Sstevel@tonic-gate zero:3, /* must be zero */ 31720Sstevel@tonic-gate ss:2, /* address space type */ 31730Sstevel@tonic-gate bus:8, /* bus number */ 31740Sstevel@tonic-gate dev:5, /* device number */ 31750Sstevel@tonic-gate fn:3, /* function number */ 31760Sstevel@tonic-gate reg:8; /* register number */ 31770Sstevel@tonic-gate uint32_t phys_hi; /* high physical address */ 31780Sstevel@tonic-gate uint32_t phys_lo; /* low physical address */ 31790Sstevel@tonic-gate } pci_addrcell_t; 31800Sstevel@tonic-gate 31810Sstevel@tonic-gate pci_addrcell_t *p; 31820Sstevel@tonic-gate int len; 31830Sstevel@tonic-gate 31840Sstevel@tonic-gate if (addrcells != 3) 31850Sstevel@tonic-gate return (-1); 31860Sstevel@tonic-gate 31870Sstevel@tonic-gate p = (pci_addrcell_t *)regprop; 31880Sstevel@tonic-gate switch (p->ss) { 31890Sstevel@tonic-gate case 0: /* Config */ 31900Sstevel@tonic-gate if (p->fn) 31910Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", p->dev, p->fn); 31920Sstevel@tonic-gate else 31930Sstevel@tonic-gate len = snprintf(buf, sz, "%x", p->dev); 31940Sstevel@tonic-gate break; 31950Sstevel@tonic-gate case 1: /* IO */ 31960Sstevel@tonic-gate len = snprintf(buf, sz, "i%x,%x,%x,%x", p->dev, p->fn, p->reg, 31970Sstevel@tonic-gate p->phys_lo); 31980Sstevel@tonic-gate break; 31990Sstevel@tonic-gate case 2: /* Mem32 */ 32000Sstevel@tonic-gate len = snprintf(buf, sz, "m%x,%x,%x,%x", p->dev, p->fn, p->reg, 32010Sstevel@tonic-gate p->phys_lo); 32020Sstevel@tonic-gate break; 32030Sstevel@tonic-gate case 3: /* Mem64 */ 32040Sstevel@tonic-gate len = snprintf(buf, sz, "x%x,%x,%x,%x%08x", p->dev, p->fn, 32050Sstevel@tonic-gate p->reg, p->phys_hi, p->phys_lo); 32060Sstevel@tonic-gate break; 32070Sstevel@tonic-gate } 32080Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 32090Sstevel@tonic-gate } 32100Sstevel@tonic-gate 32110Sstevel@tonic-gate /* 32120Sstevel@tonic-gate * Get #address-cells property value 32130Sstevel@tonic-gate */ 32140Sstevel@tonic-gate static uint_t 32150Sstevel@tonic-gate get_addrcells_prop(picl_nodehdl_t nodeh) 32160Sstevel@tonic-gate { 32170Sstevel@tonic-gate int len, err; 32180Sstevel@tonic-gate uint32_t addrcells; 32190Sstevel@tonic-gate ptree_propinfo_t pinfo; 32200Sstevel@tonic-gate picl_prophdl_t proph; 32210Sstevel@tonic-gate 32220Sstevel@tonic-gate /* 32230Sstevel@tonic-gate * Get #address-cells property. If not present, use default value. 32240Sstevel@tonic-gate */ 32250Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_PROP_ADDRESS_CELLS, &proph); 32260Sstevel@tonic-gate if (err == PICL_SUCCESS) 32270Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 32280Sstevel@tonic-gate 32290Sstevel@tonic-gate len = pinfo.piclinfo.size; 32300Sstevel@tonic-gate if (err == PICL_SUCCESS && len >= sizeof (uint8_t) && 32310Sstevel@tonic-gate len <= sizeof (addrcells)) { 32320Sstevel@tonic-gate err = ptree_get_propval(proph, &addrcells, len); 32330Sstevel@tonic-gate if (err == PICL_SUCCESS) { 32340Sstevel@tonic-gate if (len == sizeof (uint8_t)) 32350Sstevel@tonic-gate addrcells = *(uint8_t *)&addrcells; 32360Sstevel@tonic-gate else if (len == sizeof (uint16_t)) 32370Sstevel@tonic-gate addrcells = *(uint16_t *)&addrcells; 32380Sstevel@tonic-gate } else 32390Sstevel@tonic-gate addrcells = DEFAULT_ADDRESS_CELLS; 32400Sstevel@tonic-gate } else 32410Sstevel@tonic-gate addrcells = DEFAULT_ADDRESS_CELLS; 32420Sstevel@tonic-gate 32430Sstevel@tonic-gate return (addrcells); 32440Sstevel@tonic-gate } 32450Sstevel@tonic-gate 32460Sstevel@tonic-gate /* 32470Sstevel@tonic-gate * Get UnitAddress mapping entry for a node 32480Sstevel@tonic-gate */ 32490Sstevel@tonic-gate static unitaddr_map_t * 32500Sstevel@tonic-gate get_unitaddr_mapping(picl_nodehdl_t nodeh) 32510Sstevel@tonic-gate { 32520Sstevel@tonic-gate int err; 32530Sstevel@tonic-gate unitaddr_map_t *uamap; 32540Sstevel@tonic-gate char clname[PICL_CLASSNAMELEN_MAX]; 32550Sstevel@tonic-gate 32560Sstevel@tonic-gate /* 32570Sstevel@tonic-gate * Get my classname and locate a function to translate "reg" prop 32580Sstevel@tonic-gate * into "UnitAddress" prop for my children. 32590Sstevel@tonic-gate */ 32600Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, clname, 32610Sstevel@tonic-gate sizeof (clname)); 32620Sstevel@tonic-gate if (err != PICL_SUCCESS) 32630Sstevel@tonic-gate (void) strcpy(clname, ""); /* NULL class name */ 32640Sstevel@tonic-gate 32650Sstevel@tonic-gate for (uamap = &unitaddr_map_table[0]; uamap->class != NULL; uamap++) 32660Sstevel@tonic-gate if (strcmp(clname, uamap->class) == 0) 32670Sstevel@tonic-gate break; 32680Sstevel@tonic-gate 32690Sstevel@tonic-gate return (uamap); 32700Sstevel@tonic-gate } 32710Sstevel@tonic-gate 32720Sstevel@tonic-gate /* 32730Sstevel@tonic-gate * Add UnitAddress property to the specified node 32740Sstevel@tonic-gate */ 32750Sstevel@tonic-gate static int 32760Sstevel@tonic-gate add_unitaddr_prop(picl_nodehdl_t nodeh, unitaddr_map_t *uamap, uint_t addrcells) 32770Sstevel@tonic-gate { 32780Sstevel@tonic-gate int regproplen, err; 32790Sstevel@tonic-gate uint32_t *regbuf; 32800Sstevel@tonic-gate picl_prophdl_t regh; 32810Sstevel@tonic-gate ptree_propinfo_t pinfo; 32820Sstevel@tonic-gate char unitaddr[MAX_UNIT_ADDRESS_LEN]; 32830Sstevel@tonic-gate 32840Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 32850Sstevel@tonic-gate if (err != PICL_SUCCESS) 32860Sstevel@tonic-gate return (err); 32870Sstevel@tonic-gate 32880Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 32890Sstevel@tonic-gate if (err != PICL_SUCCESS) 32900Sstevel@tonic-gate return (PICL_FAILURE); 32910Sstevel@tonic-gate 32920Sstevel@tonic-gate if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t))) 32930Sstevel@tonic-gate return (PICL_FAILURE); 32940Sstevel@tonic-gate 32950Sstevel@tonic-gate regproplen = pinfo.piclinfo.size; 32960Sstevel@tonic-gate regbuf = alloca(regproplen); 32970Sstevel@tonic-gate if (regbuf == NULL) 32980Sstevel@tonic-gate return (PICL_FAILURE); 32990Sstevel@tonic-gate 33000Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, regproplen); 33010Sstevel@tonic-gate if (err != PICL_SUCCESS || uamap->func == NULL || 33020Sstevel@tonic-gate (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) || 33030Sstevel@tonic-gate (uamap->func)(unitaddr, sizeof (unitaddr), regbuf, 33040Sstevel@tonic-gate addrcells) != 0) { 33050Sstevel@tonic-gate return (PICL_FAILURE); 33060Sstevel@tonic-gate } 33070Sstevel@tonic-gate 33080Sstevel@tonic-gate err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 33090Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(unitaddr)+1, 33100Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL); 33110Sstevel@tonic-gate if (err == PICL_SUCCESS) 33120Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &pinfo, unitaddr, NULL); 33130Sstevel@tonic-gate 33140Sstevel@tonic-gate return (err); 33150Sstevel@tonic-gate } 33160Sstevel@tonic-gate 33170Sstevel@tonic-gate /* 33180Sstevel@tonic-gate * work out UnitAddress property of the specified node 33190Sstevel@tonic-gate */ 33200Sstevel@tonic-gate static int 33210Sstevel@tonic-gate get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh, char *unitaddr, 33220Sstevel@tonic-gate size_t ualen) 33230Sstevel@tonic-gate { 33240Sstevel@tonic-gate int regproplen, err; 33250Sstevel@tonic-gate uint32_t *regbuf; 33260Sstevel@tonic-gate picl_prophdl_t regh; 33270Sstevel@tonic-gate ptree_propinfo_t pinfo; 33280Sstevel@tonic-gate unitaddr_map_t *uamap; 33290Sstevel@tonic-gate uint32_t addrcells; 33300Sstevel@tonic-gate 33310Sstevel@tonic-gate addrcells = get_addrcells_prop(parh); 33320Sstevel@tonic-gate uamap = get_unitaddr_mapping(parh); 33330Sstevel@tonic-gate 33340Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 33350Sstevel@tonic-gate if (err != PICL_SUCCESS) 33360Sstevel@tonic-gate return (err); 33370Sstevel@tonic-gate 33380Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 33390Sstevel@tonic-gate if (err != PICL_SUCCESS) 33400Sstevel@tonic-gate return (err); 33410Sstevel@tonic-gate 33420Sstevel@tonic-gate if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t))) 33430Sstevel@tonic-gate return (PICL_FAILURE); 33440Sstevel@tonic-gate 33450Sstevel@tonic-gate regproplen = pinfo.piclinfo.size; 33460Sstevel@tonic-gate regbuf = alloca(regproplen); 33470Sstevel@tonic-gate if (regbuf == NULL) 33480Sstevel@tonic-gate return (PICL_FAILURE); 33490Sstevel@tonic-gate 33500Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, regproplen); 33510Sstevel@tonic-gate if (err != PICL_SUCCESS || uamap->func == NULL || 33520Sstevel@tonic-gate (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) || 33530Sstevel@tonic-gate (uamap->func)(unitaddr, ualen, regbuf, addrcells) != 0) { 33540Sstevel@tonic-gate return (PICL_FAILURE); 33550Sstevel@tonic-gate } 33560Sstevel@tonic-gate return (PICL_SUCCESS); 33570Sstevel@tonic-gate } 33580Sstevel@tonic-gate 33590Sstevel@tonic-gate /* 33600Sstevel@tonic-gate * Add UnitAddress property to all children of the specified node 33610Sstevel@tonic-gate */ 33620Sstevel@tonic-gate static int 33630Sstevel@tonic-gate add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh) 33640Sstevel@tonic-gate { 33650Sstevel@tonic-gate int err; 33660Sstevel@tonic-gate picl_nodehdl_t chdh; 33670Sstevel@tonic-gate unitaddr_map_t *uamap; 33680Sstevel@tonic-gate uint32_t addrcells; 33690Sstevel@tonic-gate 33700Sstevel@tonic-gate /* 33710Sstevel@tonic-gate * Get #address-cells and unit address mapping entry for my 33720Sstevel@tonic-gate * node's class 33730Sstevel@tonic-gate */ 33740Sstevel@tonic-gate addrcells = get_addrcells_prop(nodeh); 33750Sstevel@tonic-gate uamap = get_unitaddr_mapping(nodeh); 33760Sstevel@tonic-gate 33770Sstevel@tonic-gate /* 33780Sstevel@tonic-gate * Add UnitAddress property to my children and their subtree 33790Sstevel@tonic-gate */ 33800Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 33810Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 33820Sstevel@tonic-gate 33830Sstevel@tonic-gate while (err == PICL_SUCCESS) { 33840Sstevel@tonic-gate (void) add_unitaddr_prop(chdh, uamap, addrcells); 33850Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(chdh); 33860Sstevel@tonic-gate 33870Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 33880Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 33890Sstevel@tonic-gate } 33900Sstevel@tonic-gate 33910Sstevel@tonic-gate return (PICL_SUCCESS); 33920Sstevel@tonic-gate } 33930Sstevel@tonic-gate 33940Sstevel@tonic-gate static int 33950Sstevel@tonic-gate update_memory_size_prop(picl_nodehdl_t plafh) 33960Sstevel@tonic-gate { 33970Sstevel@tonic-gate picl_nodehdl_t memh; 33980Sstevel@tonic-gate picl_prophdl_t proph; 33990Sstevel@tonic-gate ptree_propinfo_t pinfo; 34000Sstevel@tonic-gate int err, nspecs, snum, pval; 34010Sstevel@tonic-gate char *regbuf; 34020Sstevel@tonic-gate memspecs_t *mspecs; 34030Sstevel@tonic-gate uint64_t memsize; 34040Sstevel@tonic-gate 34050Sstevel@tonic-gate /* 34060Sstevel@tonic-gate * check if the #size-cells of the platform node is 2 34070Sstevel@tonic-gate */ 34080Sstevel@tonic-gate err = ptree_get_propval_by_name(plafh, OBP_PROP_SIZE_CELLS, &pval, 34095028Sfw157321 sizeof (pval)); 34100Sstevel@tonic-gate 34110Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 34120Sstevel@tonic-gate pval = SUPPORTED_NUM_CELL_SIZE; 34130Sstevel@tonic-gate else if (err != PICL_SUCCESS) 34140Sstevel@tonic-gate return (err); 34150Sstevel@tonic-gate 34160Sstevel@tonic-gate /* 34170Sstevel@tonic-gate * don't know how to handle other vals 34180Sstevel@tonic-gate */ 34190Sstevel@tonic-gate if (pval != SUPPORTED_NUM_CELL_SIZE) 34200Sstevel@tonic-gate return (PICL_FAILURE); 34210Sstevel@tonic-gate 34220Sstevel@tonic-gate err = ptree_get_node_by_path(MEMORY_PATH, &memh); 34230Sstevel@tonic-gate if (err != PICL_SUCCESS) 34240Sstevel@tonic-gate return (err); 34250Sstevel@tonic-gate 34260Sstevel@tonic-gate /* 34270Sstevel@tonic-gate * Get the REG property to calculate the size of memory 34280Sstevel@tonic-gate */ 34290Sstevel@tonic-gate err = ptree_get_prop_by_name(memh, OBP_REG, &proph); 34300Sstevel@tonic-gate if (err != PICL_SUCCESS) 34310Sstevel@tonic-gate return (err); 34320Sstevel@tonic-gate 34330Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 34340Sstevel@tonic-gate if (err != PICL_SUCCESS) 34350Sstevel@tonic-gate return (err); 34360Sstevel@tonic-gate 34370Sstevel@tonic-gate regbuf = alloca(pinfo.piclinfo.size); 34380Sstevel@tonic-gate if (regbuf == NULL) 34390Sstevel@tonic-gate return (PICL_FAILURE); 34400Sstevel@tonic-gate 34410Sstevel@tonic-gate err = ptree_get_propval(proph, regbuf, pinfo.piclinfo.size); 34420Sstevel@tonic-gate if (err != PICL_SUCCESS) 34430Sstevel@tonic-gate return (err); 34440Sstevel@tonic-gate 34450Sstevel@tonic-gate mspecs = (memspecs_t *)regbuf; 34460Sstevel@tonic-gate nspecs = pinfo.piclinfo.size / sizeof (memspecs_t); 34470Sstevel@tonic-gate 34480Sstevel@tonic-gate memsize = 0; 34490Sstevel@tonic-gate for (snum = 0; snum < nspecs; ++snum) 34500Sstevel@tonic-gate memsize += mspecs[snum].size; 34510Sstevel@tonic-gate 34520Sstevel@tonic-gate err = ptree_get_prop_by_name(memh, PICL_PROP_SIZE, &proph); 34530Sstevel@tonic-gate if (err == PICL_SUCCESS) { 34540Sstevel@tonic-gate err = ptree_update_propval(proph, &memsize, sizeof (memsize)); 34550Sstevel@tonic-gate return (err); 34560Sstevel@tonic-gate } 34570Sstevel@tonic-gate 34580Sstevel@tonic-gate /* 34590Sstevel@tonic-gate * Add the size property 34600Sstevel@tonic-gate */ 34610Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 34625028Sfw157321 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (memsize), 34635028Sfw157321 PICL_PROP_SIZE, NULL, NULL); 34640Sstevel@tonic-gate err = ptree_create_and_add_prop(memh, &pinfo, &memsize, NULL); 34650Sstevel@tonic-gate return (err); 34660Sstevel@tonic-gate } 34670Sstevel@tonic-gate 34680Sstevel@tonic-gate /* 34690Sstevel@tonic-gate * This function is executed as part of .init when the plugin is 34700Sstevel@tonic-gate * dlopen()ed 34710Sstevel@tonic-gate */ 34720Sstevel@tonic-gate static void 34730Sstevel@tonic-gate picldevtree_register(void) 34740Sstevel@tonic-gate { 34750Sstevel@tonic-gate if (getenv(SUNW_PICLDEVTREE_PLUGIN_DEBUG)) 34760Sstevel@tonic-gate picldevtree_debug = 1; 34770Sstevel@tonic-gate (void) picld_plugin_register(&my_reg_info); 34780Sstevel@tonic-gate } 34790Sstevel@tonic-gate 34800Sstevel@tonic-gate /* 34810Sstevel@tonic-gate * This function is the init entry point of the plugin. 34820Sstevel@tonic-gate * It initializes the /platform tree based on libdevinfo 34830Sstevel@tonic-gate */ 34840Sstevel@tonic-gate static void 34850Sstevel@tonic-gate picldevtree_init(void) 34860Sstevel@tonic-gate { 34870Sstevel@tonic-gate picl_nodehdl_t rhdl; 34880Sstevel@tonic-gate int err; 34890Sstevel@tonic-gate struct utsname utsname; 34900Sstevel@tonic-gate picl_nodehdl_t plafh; 34910Sstevel@tonic-gate 34920Sstevel@tonic-gate if (uname(&utsname) < 0) 34930Sstevel@tonic-gate return; 34940Sstevel@tonic-gate 34950Sstevel@tonic-gate (void) strcpy(mach_name, utsname.machine); 34960Sstevel@tonic-gate 34970Sstevel@tonic-gate if (strcmp(mach_name, "sun4u") == 0) { 34980Sstevel@tonic-gate builtin_map_ptr = sun4u_map; 34990Sstevel@tonic-gate builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t); 35003941Svenki } else if (strcmp(mach_name, "sun4v") == 0) { 35013941Svenki builtin_map_ptr = sun4u_map; 35023941Svenki builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t); 35030Sstevel@tonic-gate } else if (strcmp(mach_name, "i86pc") == 0) { 35040Sstevel@tonic-gate builtin_map_ptr = i86pc_map; 35050Sstevel@tonic-gate builtin_map_size = sizeof (i86pc_map) / sizeof (builtin_map_t); 35060Sstevel@tonic-gate } else { 35070Sstevel@tonic-gate builtin_map_ptr = NULL; 35080Sstevel@tonic-gate builtin_map_size = 0; 35090Sstevel@tonic-gate } 35100Sstevel@tonic-gate 35110Sstevel@tonic-gate err = ptree_get_root(&rhdl); 35120Sstevel@tonic-gate if (err != PICL_SUCCESS) { 35130Sstevel@tonic-gate syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED); 35140Sstevel@tonic-gate return; 35150Sstevel@tonic-gate } 35160Sstevel@tonic-gate 35170Sstevel@tonic-gate process_devtree_conf_file(); 35180Sstevel@tonic-gate 35190Sstevel@tonic-gate if (libdevinfo_init(rhdl) != PICL_SUCCESS) { 35200Sstevel@tonic-gate syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED); 35210Sstevel@tonic-gate return; 35220Sstevel@tonic-gate } 35230Sstevel@tonic-gate 35240Sstevel@tonic-gate err = ptree_get_node_by_path(PLATFORM_PATH, &plafh); 35250Sstevel@tonic-gate if (err != PICL_SUCCESS) 35260Sstevel@tonic-gate return; 35270Sstevel@tonic-gate 35280Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(plafh); 35290Sstevel@tonic-gate 35300Sstevel@tonic-gate add_asr_nodes(); 35310Sstevel@tonic-gate 35320Sstevel@tonic-gate (void) update_memory_size_prop(plafh); 35330Sstevel@tonic-gate 35340Sstevel@tonic-gate (void) setup_cpus(plafh); 35350Sstevel@tonic-gate 35360Sstevel@tonic-gate (void) add_ffb_config_info(plafh); 35370Sstevel@tonic-gate 35380Sstevel@tonic-gate (void) add_platform_info(plafh); 35390Sstevel@tonic-gate 3540944Svenki set_pci_pciex_deviceid(plafh); 35410Sstevel@tonic-gate 35420Sstevel@tonic-gate (void) set_sbus_slot(plafh); 35430Sstevel@tonic-gate 35440Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 35450Sstevel@tonic-gate picldevtree_evhandler, NULL); 35460Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 35470Sstevel@tonic-gate picldevtree_evhandler, NULL); 35485028Sfw157321 (void) ptree_register_handler(PICLEVENT_CPU_STATE_CHANGE, 35495028Sfw157321 picldevtree_evhandler, NULL); 35500Sstevel@tonic-gate } 35510Sstevel@tonic-gate 35520Sstevel@tonic-gate /* 35530Sstevel@tonic-gate * This function is the fini entry point of the plugin 35540Sstevel@tonic-gate */ 35550Sstevel@tonic-gate static void 35560Sstevel@tonic-gate picldevtree_fini(void) 35570Sstevel@tonic-gate { 35580Sstevel@tonic-gate /* First unregister the event handlers */ 35590Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 35600Sstevel@tonic-gate picldevtree_evhandler, NULL); 35610Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 35620Sstevel@tonic-gate picldevtree_evhandler, NULL); 35635028Sfw157321 (void) ptree_unregister_handler(PICLEVENT_CPU_STATE_CHANGE, 35645028Sfw157321 picldevtree_evhandler, NULL); 35650Sstevel@tonic-gate 35660Sstevel@tonic-gate conf_name_class_map = free_conf_entries(conf_name_class_map); 35670Sstevel@tonic-gate } 35680Sstevel@tonic-gate 35690Sstevel@tonic-gate /* 35700Sstevel@tonic-gate * This function is the event handler of this plug-in. 35710Sstevel@tonic-gate * 35720Sstevel@tonic-gate * It processes the following events: 35730Sstevel@tonic-gate * 35740Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_ADDED 35750Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_REMOVED 35765028Sfw157321 * PICLEVENT_CPU_STATE_CHANGE 35770Sstevel@tonic-gate */ 35780Sstevel@tonic-gate /* ARGSUSED */ 35790Sstevel@tonic-gate static void 35800Sstevel@tonic-gate picldevtree_evhandler(const char *ename, const void *earg, size_t size, 35810Sstevel@tonic-gate void *cookie) 35820Sstevel@tonic-gate { 35830Sstevel@tonic-gate char *devfs_path; 35840Sstevel@tonic-gate char ptreepath[PATH_MAX]; 35850Sstevel@tonic-gate char dipath[PATH_MAX]; 35860Sstevel@tonic-gate picl_nodehdl_t plafh; 35870Sstevel@tonic-gate picl_nodehdl_t nodeh; 35880Sstevel@tonic-gate nvlist_t *nvlp; 35890Sstevel@tonic-gate 35900Sstevel@tonic-gate if (earg == NULL) 35910Sstevel@tonic-gate return; 35920Sstevel@tonic-gate 35930Sstevel@tonic-gate nvlp = NULL; 35940Sstevel@tonic-gate if (ptree_get_node_by_path(PLATFORM_PATH, &plafh) != PICL_SUCCESS || 35950Sstevel@tonic-gate nvlist_unpack((char *)earg, size, &nvlp, NULL) || 35960Sstevel@tonic-gate nvlist_lookup_string(nvlp, PICLEVENTARG_DEVFS_PATH, &devfs_path) || 35970Sstevel@tonic-gate strlen(devfs_path) > (PATH_MAX - sizeof (PLATFORM_PATH))) { 35980Sstevel@tonic-gate syslog(LOG_INFO, PICL_EVENT_DROPPED, ename); 35990Sstevel@tonic-gate if (nvlp) 36000Sstevel@tonic-gate nvlist_free(nvlp); 36010Sstevel@tonic-gate return; 36020Sstevel@tonic-gate } 36030Sstevel@tonic-gate 36040Sstevel@tonic-gate (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX); 36050Sstevel@tonic-gate (void) strlcat(ptreepath, devfs_path, PATH_MAX); 36060Sstevel@tonic-gate (void) strlcpy(dipath, devfs_path, PATH_MAX); 36070Sstevel@tonic-gate nvlist_free(nvlp); 36080Sstevel@tonic-gate 36090Sstevel@tonic-gate if (picldevtree_debug) 36100Sstevel@tonic-gate syslog(LOG_INFO, "picldevtree: event handler invoked ename:%s " 36110Sstevel@tonic-gate "ptreepath:%s\n", ename, ptreepath); 36120Sstevel@tonic-gate 36135028Sfw157321 if (strcmp(ename, PICLEVENT_CPU_STATE_CHANGE) == 0) { 36145028Sfw157321 goto done; 36155028Sfw157321 } 36160Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) { 36170Sstevel@tonic-gate di_node_t devnode; 36180Sstevel@tonic-gate char *strp; 36190Sstevel@tonic-gate picl_nodehdl_t parh; 36200Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 36210Sstevel@tonic-gate char *nodename; 36220Sstevel@tonic-gate int err; 36230Sstevel@tonic-gate 36240Sstevel@tonic-gate /* If the node already exist, then nothing else to do here */ 36250Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) == PICL_SUCCESS) 36260Sstevel@tonic-gate return; 36270Sstevel@tonic-gate 36280Sstevel@tonic-gate /* Skip if unable to find parent PICL node handle */ 36290Sstevel@tonic-gate parh = plafh; 36300Sstevel@tonic-gate if (((strp = strrchr(ptreepath, '/')) != NULL) && 36310Sstevel@tonic-gate (strp != strchr(ptreepath, '/'))) { 36320Sstevel@tonic-gate *strp = '\0'; 36330Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &parh) != 36340Sstevel@tonic-gate PICL_SUCCESS) 36350Sstevel@tonic-gate return; 36360Sstevel@tonic-gate } 36370Sstevel@tonic-gate 36380Sstevel@tonic-gate /* 36390Sstevel@tonic-gate * If parent is the root node 36400Sstevel@tonic-gate */ 36410Sstevel@tonic-gate if (parh == plafh) { 36420Sstevel@tonic-gate ph = di_prom_init(); 36430Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 36440Sstevel@tonic-gate if (devnode == DI_NODE_NIL) { 36450Sstevel@tonic-gate if (ph != NULL) { 36460Sstevel@tonic-gate di_prom_fini(ph); 36470Sstevel@tonic-gate ph = NULL; 36480Sstevel@tonic-gate } 36490Sstevel@tonic-gate return; 36500Sstevel@tonic-gate } 36510Sstevel@tonic-gate nodename = di_node_name(devnode); 36520Sstevel@tonic-gate if (nodename == NULL) { 36530Sstevel@tonic-gate di_fini(devnode); 36540Sstevel@tonic-gate if (ph != NULL) { 36550Sstevel@tonic-gate di_prom_fini(ph); 36560Sstevel@tonic-gate ph = NULL; 36570Sstevel@tonic-gate } 36580Sstevel@tonic-gate return; 36590Sstevel@tonic-gate } 36600Sstevel@tonic-gate 36610Sstevel@tonic-gate err = get_node_class(nodeclass, devnode, nodename); 36620Sstevel@tonic-gate if (err < 0) { 36630Sstevel@tonic-gate di_fini(devnode); 36640Sstevel@tonic-gate if (ph != NULL) { 36650Sstevel@tonic-gate di_prom_fini(ph); 36660Sstevel@tonic-gate ph = NULL; 36670Sstevel@tonic-gate } 36680Sstevel@tonic-gate return; 36690Sstevel@tonic-gate } 36700Sstevel@tonic-gate err = construct_devtype_node(plafh, nodename, 36710Sstevel@tonic-gate nodeclass, devnode, &nodeh); 36720Sstevel@tonic-gate if (err != PICL_SUCCESS) { 36730Sstevel@tonic-gate di_fini(devnode); 36740Sstevel@tonic-gate if (ph != NULL) { 36750Sstevel@tonic-gate di_prom_fini(ph); 36760Sstevel@tonic-gate ph = NULL; 36770Sstevel@tonic-gate } 36780Sstevel@tonic-gate return; 36790Sstevel@tonic-gate } 36800Sstevel@tonic-gate (void) update_subtree(nodeh, devnode); 36810Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(nodeh); 36820Sstevel@tonic-gate if (ph != NULL) { 36830Sstevel@tonic-gate di_prom_fini(ph); 36840Sstevel@tonic-gate ph = NULL; 36850Sstevel@tonic-gate } 36860Sstevel@tonic-gate di_fini(devnode); 36870Sstevel@tonic-gate goto done; 36880Sstevel@tonic-gate } 36890Sstevel@tonic-gate 36900Sstevel@tonic-gate /* kludge ... try without bus-addr first */ 36910Sstevel@tonic-gate if ((strp = strrchr(dipath, '@')) != NULL) { 36920Sstevel@tonic-gate char *p; 36930Sstevel@tonic-gate 36940Sstevel@tonic-gate p = strrchr(dipath, '/'); 36950Sstevel@tonic-gate if (p != NULL && strp > p) { 36960Sstevel@tonic-gate *strp = '\0'; 36970Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 36980Sstevel@tonic-gate if (devnode != DI_NODE_NIL) 36990Sstevel@tonic-gate di_fini(devnode); 37000Sstevel@tonic-gate *strp = '@'; 37010Sstevel@tonic-gate } 37020Sstevel@tonic-gate } 37030Sstevel@tonic-gate /* Get parent devnode */ 37040Sstevel@tonic-gate if ((strp = strrchr(dipath, '/')) != NULL) 37050Sstevel@tonic-gate *++strp = '\0'; 37060Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 37070Sstevel@tonic-gate if (devnode == DI_NODE_NIL) 37080Sstevel@tonic-gate return; 37090Sstevel@tonic-gate ph = di_prom_init(); 37100Sstevel@tonic-gate (void) update_subtree(parh, devnode); 37110Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(parh); 37120Sstevel@tonic-gate if (ph) { 37130Sstevel@tonic-gate di_prom_fini(ph); 37140Sstevel@tonic-gate ph = NULL; 37150Sstevel@tonic-gate } 37160Sstevel@tonic-gate di_fini(devnode); 37170Sstevel@tonic-gate } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) { 37180Sstevel@tonic-gate char delclass[PICL_CLASSNAMELEN_MAX]; 37190Sstevel@tonic-gate char *strp; 37200Sstevel@tonic-gate 37210Sstevel@tonic-gate /* 37220Sstevel@tonic-gate * if final element of path doesn't have a unit address 37230Sstevel@tonic-gate * then it is not uniquely identifiable - cannot remove 37240Sstevel@tonic-gate */ 37250Sstevel@tonic-gate if (((strp = strrchr(ptreepath, '/')) != NULL) && 37260Sstevel@tonic-gate strchr(strp, '@') == NULL) 37270Sstevel@tonic-gate return; 37280Sstevel@tonic-gate 37290Sstevel@tonic-gate /* skip if can't find the node */ 37300Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS) 37310Sstevel@tonic-gate return; 37320Sstevel@tonic-gate 37330Sstevel@tonic-gate if (ptree_delete_node(nodeh) != PICL_SUCCESS) 37340Sstevel@tonic-gate return; 37350Sstevel@tonic-gate 37360Sstevel@tonic-gate if (picldevtree_debug) 37370Sstevel@tonic-gate syslog(LOG_INFO, 37380Sstevel@tonic-gate "picldevtree: deleted node nodeh:%llx\n", nodeh); 37390Sstevel@tonic-gate if ((ptree_get_propval_by_name(nodeh, 37400Sstevel@tonic-gate PICL_PROP_CLASSNAME, delclass, PICL_CLASSNAMELEN_MAX) == 37410Sstevel@tonic-gate PICL_SUCCESS) && IS_MC(delclass)) { 37420Sstevel@tonic-gate if (post_mc_event(PICLEVENT_MC_REMOVED, nodeh) != 37430Sstevel@tonic-gate PICL_SUCCESS) 37440Sstevel@tonic-gate syslog(LOG_WARNING, PICL_EVENT_DROPPED, 37450Sstevel@tonic-gate PICLEVENT_MC_REMOVED); 37460Sstevel@tonic-gate } else 37470Sstevel@tonic-gate (void) ptree_destroy_node(nodeh); 37480Sstevel@tonic-gate } 37490Sstevel@tonic-gate done: 37500Sstevel@tonic-gate (void) setup_cpus(plafh); 37510Sstevel@tonic-gate (void) add_ffb_config_info(plafh); 3752944Svenki set_pci_pciex_deviceid(plafh); 37530Sstevel@tonic-gate (void) set_sbus_slot(plafh); 37540Sstevel@tonic-gate if (picldevtree_debug > 1) 37550Sstevel@tonic-gate syslog(LOG_INFO, "picldevtree: event handler done\n"); 37560Sstevel@tonic-gate } 3757