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 /* 22*7442SMichael.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; 235*7442SMichael.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 10140Sstevel@tonic-gate /* 10150Sstevel@tonic-gate * Add properties provided by libdevinfo 10160Sstevel@tonic-gate */ 10170Sstevel@tonic-gate static void 10180Sstevel@tonic-gate add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node) 10190Sstevel@tonic-gate { 10200Sstevel@tonic-gate int instance; 10210Sstevel@tonic-gate char *di_val; 10220Sstevel@tonic-gate di_prop_t di_prop; 10230Sstevel@tonic-gate int di_ptype; 10240Sstevel@tonic-gate ptree_propinfo_t propinfo; 10253343Srd117015 char *sdata; 10263343Srd117015 unsigned char *bdata; 10273343Srd117015 int *idata; 10283343Srd117015 int len; 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate instance = di_instance(di_node); 10310Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10320Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE, 10330Sstevel@tonic-gate NULL, NULL); 10340Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL); 10350Sstevel@tonic-gate 10360Sstevel@tonic-gate di_val = di_bus_addr(di_node); 10370Sstevel@tonic-gate if (di_val) { 10380Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10390Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 10400Sstevel@tonic-gate PICL_PROP_BUS_ADDR, NULL, NULL); 10410Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 10420Sstevel@tonic-gate NULL); 10430Sstevel@tonic-gate } 10440Sstevel@tonic-gate 10450Sstevel@tonic-gate di_val = di_binding_name(di_node); 10460Sstevel@tonic-gate if (di_val) { 10470Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10480Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 10490Sstevel@tonic-gate PICL_PROP_BINDING_NAME, NULL, NULL); 10500Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 10510Sstevel@tonic-gate NULL); 10520Sstevel@tonic-gate } 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate di_val = di_driver_name(di_node); 10550Sstevel@tonic-gate if (di_val) { 10560Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10570Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 10580Sstevel@tonic-gate PICL_PROP_DRIVER_NAME, NULL, NULL); 10590Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 10600Sstevel@tonic-gate NULL); 10610Sstevel@tonic-gate } 10620Sstevel@tonic-gate 10630Sstevel@tonic-gate di_val = di_devfs_path(di_node); 10640Sstevel@tonic-gate if (di_val) { 10650Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10660Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 10670Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, NULL, NULL); 10680Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 10690Sstevel@tonic-gate NULL); 10700Sstevel@tonic-gate di_devfs_path_free(di_val); 10710Sstevel@tonic-gate } 10720Sstevel@tonic-gate 10730Sstevel@tonic-gate for (di_prop = di_prop_next(di_node, DI_PROP_NIL); 10740Sstevel@tonic-gate di_prop != DI_PROP_NIL; 10755028Sfw157321 di_prop = di_prop_next(di_node, di_prop)) { 10760Sstevel@tonic-gate 10770Sstevel@tonic-gate di_val = di_prop_name(di_prop); 10780Sstevel@tonic-gate di_ptype = di_prop_type(di_prop); 10793343Srd117015 10800Sstevel@tonic-gate switch (di_ptype) { 10810Sstevel@tonic-gate case DI_PROP_TYPE_BOOLEAN: 10823343Srd117015 add_boolean_prop(nodeh, propinfo, di_val); 10830Sstevel@tonic-gate break; 10843343Srd117015 case DI_PROP_TYPE_INT: 10850Sstevel@tonic-gate len = di_prop_ints(di_prop, &idata); 10860Sstevel@tonic-gate if (len < 0) 10873343Srd117015 /* Received error, so ignore prop */ 10880Sstevel@tonic-gate break; 10893343Srd117015 add_uints_prop(nodeh, propinfo, di_val, idata, len); 10903343Srd117015 break; 10913343Srd117015 case DI_PROP_TYPE_STRING: 10920Sstevel@tonic-gate len = di_prop_strings(di_prop, &sdata); 10930Sstevel@tonic-gate if (len < 0) 10940Sstevel@tonic-gate break; 10953343Srd117015 add_strings_prop(nodeh, propinfo, di_val, sdata, len); 10963343Srd117015 break; 10973343Srd117015 case DI_PROP_TYPE_BYTE: 10980Sstevel@tonic-gate len = di_prop_bytes(di_prop, &bdata); 10990Sstevel@tonic-gate if (len < 0) 11000Sstevel@tonic-gate break; 11013343Srd117015 add_bytes_prop(nodeh, propinfo, di_val, bdata, len); 11023343Srd117015 break; 11030Sstevel@tonic-gate case DI_PROP_TYPE_UNKNOWN: 11043343Srd117015 /* 11053343Srd117015 * Unknown type, we'll try and guess what it should be. 11063343Srd117015 */ 11073343Srd117015 len = di_prop_strings(di_prop, &sdata); 11083343Srd117015 if ((len > 0) && (sdata[0] != 0)) { 11093343Srd117015 add_strings_prop(nodeh, propinfo, di_val, sdata, 11103343Srd117015 len); 11113343Srd117015 break; 11123343Srd117015 } 11133343Srd117015 len = di_prop_ints(di_prop, &idata); 11143343Srd117015 if (len > 0) { 11153343Srd117015 add_uints_prop(nodeh, propinfo, di_val, 11163343Srd117015 idata, len); 11173343Srd117015 break; 11183343Srd117015 } 11193343Srd117015 len = di_prop_rawdata(di_prop, &bdata); 11203343Srd117015 if (len > 0) 11213343Srd117015 add_bytes_prop(nodeh, propinfo, 11223343Srd117015 di_val, bdata, len); 11233343Srd117015 else if (len == 0) 11243343Srd117015 add_boolean_prop(nodeh, propinfo, 11253343Srd117015 di_val); 11260Sstevel@tonic-gate break; 11270Sstevel@tonic-gate case DI_PROP_TYPE_UNDEF_IT: 11280Sstevel@tonic-gate break; 11290Sstevel@tonic-gate default: 11300Sstevel@tonic-gate break; 11310Sstevel@tonic-gate } 11320Sstevel@tonic-gate } 11330Sstevel@tonic-gate } 11340Sstevel@tonic-gate 11350Sstevel@tonic-gate /* 11360Sstevel@tonic-gate * This function creates the /obp node in the PICL tree for OBP nodes 11370Sstevel@tonic-gate * without a device type class. 11380Sstevel@tonic-gate */ 11390Sstevel@tonic-gate static int 11400Sstevel@tonic-gate construct_picl_openprom(picl_nodehdl_t rooth, picl_nodehdl_t *obph) 11410Sstevel@tonic-gate { 11420Sstevel@tonic-gate picl_nodehdl_t tmph; 11430Sstevel@tonic-gate int err; 11440Sstevel@tonic-gate 11450Sstevel@tonic-gate err = ptree_create_and_add_node(rooth, PICL_NODE_OBP, 11460Sstevel@tonic-gate PICL_CLASS_PICL, &tmph); 11470Sstevel@tonic-gate 11480Sstevel@tonic-gate if (err != PICL_SUCCESS) 11490Sstevel@tonic-gate return (err); 11500Sstevel@tonic-gate *obph = tmph; 11510Sstevel@tonic-gate return (PICL_SUCCESS); 11520Sstevel@tonic-gate } 11530Sstevel@tonic-gate 11540Sstevel@tonic-gate /* 11550Sstevel@tonic-gate * This function creates the /platform node in the PICL tree and 11560Sstevel@tonic-gate * its properties. It sets the "platform-name" property to the 11570Sstevel@tonic-gate * platform name 11580Sstevel@tonic-gate */ 11590Sstevel@tonic-gate static int 11600Sstevel@tonic-gate construct_picl_platform(picl_nodehdl_t rooth, di_node_t di_root, 11610Sstevel@tonic-gate picl_nodehdl_t *piclh) 11620Sstevel@tonic-gate { 11630Sstevel@tonic-gate int err; 11640Sstevel@tonic-gate picl_nodehdl_t plafh; 11650Sstevel@tonic-gate char *nodename; 11660Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 11670Sstevel@tonic-gate ptree_propinfo_t propinfo; 11680Sstevel@tonic-gate picl_prophdl_t proph; 11690Sstevel@tonic-gate 11700Sstevel@tonic-gate nodename = di_node_name(di_root); 11710Sstevel@tonic-gate if (nodename == NULL) 11720Sstevel@tonic-gate return (PICL_FAILURE); 11730Sstevel@tonic-gate 11740Sstevel@tonic-gate err = 0; 11750Sstevel@tonic-gate if (di_nodeid(di_root) == DI_PROM_NODEID || 11760Sstevel@tonic-gate di_nodeid(di_root) == DI_SID_NODEID) 11770Sstevel@tonic-gate err = get_device_type(nodeclass, di_root); 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate if (err < 0) 11800Sstevel@tonic-gate (void) strcpy(nodeclass, PICL_CLASS_UPA); /* default */ 11810Sstevel@tonic-gate 11820Sstevel@tonic-gate err = ptree_create_and_add_node(rooth, PICL_NODE_PLATFORM, 11830Sstevel@tonic-gate nodeclass, &plafh); 11840Sstevel@tonic-gate if (err != PICL_SUCCESS) 11850Sstevel@tonic-gate return (err); 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 11880Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(nodename) + 1, 11890Sstevel@tonic-gate PICL_PROP_PLATFORM_NAME, NULL, NULL); 11900Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, nodename, &proph); 11910Sstevel@tonic-gate if (err != PICL_SUCCESS) 11920Sstevel@tonic-gate return (err); 11930Sstevel@tonic-gate 11940Sstevel@tonic-gate (void) add_devinfo_props(plafh, di_root); 11950Sstevel@tonic-gate 11960Sstevel@tonic-gate (void) add_openprom_props(plafh, di_root); 11970Sstevel@tonic-gate 11980Sstevel@tonic-gate *piclh = plafh; 11990Sstevel@tonic-gate 12000Sstevel@tonic-gate return (PICL_SUCCESS); 12010Sstevel@tonic-gate } 12020Sstevel@tonic-gate 12030Sstevel@tonic-gate /* 12040Sstevel@tonic-gate * This function creates a node in /obp tree for the libdevinfo handle. 12050Sstevel@tonic-gate */ 12060Sstevel@tonic-gate static int 12070Sstevel@tonic-gate construct_obp_node(picl_nodehdl_t parh, di_node_t dn, picl_nodehdl_t *chdh) 12080Sstevel@tonic-gate { 12090Sstevel@tonic-gate int err; 12100Sstevel@tonic-gate char *nodename; 12110Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 12120Sstevel@tonic-gate picl_nodehdl_t anodeh; 12130Sstevel@tonic-gate 12140Sstevel@tonic-gate nodename = di_node_name(dn); /* PICL_PROP_NAME */ 12150Sstevel@tonic-gate if (nodename == NULL) 12160Sstevel@tonic-gate return (PICL_FAILURE); 12170Sstevel@tonic-gate 12180Sstevel@tonic-gate if (strcmp(nodename, "pseudo") == 0) 12190Sstevel@tonic-gate return (PICL_FAILURE); 12200Sstevel@tonic-gate 12210Sstevel@tonic-gate if ((di_nodeid(dn) == DI_PROM_NODEID) && 12220Sstevel@tonic-gate (get_device_type(nodeclass, dn) == 0)) 12230Sstevel@tonic-gate return (PICL_FAILURE); 12240Sstevel@tonic-gate 12250Sstevel@tonic-gate err = ptree_create_and_add_node(parh, nodename, nodename, &anodeh); 12260Sstevel@tonic-gate if (err != PICL_SUCCESS) 12270Sstevel@tonic-gate return (err); 12280Sstevel@tonic-gate 12290Sstevel@tonic-gate add_devinfo_props(anodeh, dn); 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate (void) add_openprom_props(anodeh, dn); 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate *chdh = anodeh; 12340Sstevel@tonic-gate 12350Sstevel@tonic-gate return (PICL_SUCCESS); 12360Sstevel@tonic-gate } 12370Sstevel@tonic-gate 12380Sstevel@tonic-gate /* 12390Sstevel@tonic-gate * This function creates a PICL node in /platform tree for a device 12400Sstevel@tonic-gate */ 12410Sstevel@tonic-gate static int 12420Sstevel@tonic-gate construct_devtype_node(picl_nodehdl_t parh, char *nodename, 12430Sstevel@tonic-gate char *nodeclass, di_node_t dn, picl_nodehdl_t *chdh) 12440Sstevel@tonic-gate { 12450Sstevel@tonic-gate int err; 12460Sstevel@tonic-gate picl_nodehdl_t anodeh; 12470Sstevel@tonic-gate 12480Sstevel@tonic-gate err = ptree_create_and_add_node(parh, nodename, nodeclass, &anodeh); 12490Sstevel@tonic-gate if (err != PICL_SUCCESS) 12500Sstevel@tonic-gate return (err); 12510Sstevel@tonic-gate 12520Sstevel@tonic-gate (void) add_devinfo_props(anodeh, dn); 12530Sstevel@tonic-gate (void) add_openprom_props(anodeh, dn); 12540Sstevel@tonic-gate 12550Sstevel@tonic-gate *chdh = anodeh; 12560Sstevel@tonic-gate return (err); 12570Sstevel@tonic-gate } 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate /* 12600Sstevel@tonic-gate * Create a subtree of "picl" class nodes in /obp for these nodes 12610Sstevel@tonic-gate */ 12620Sstevel@tonic-gate static int 12630Sstevel@tonic-gate construct_openprom_tree(picl_nodehdl_t nodeh, di_node_t dinode) 12640Sstevel@tonic-gate { 12650Sstevel@tonic-gate di_node_t cnode; 12660Sstevel@tonic-gate picl_nodehdl_t chdh; 12670Sstevel@tonic-gate int err; 12680Sstevel@tonic-gate 12690Sstevel@tonic-gate err = construct_obp_node(nodeh, dinode, &chdh); 12700Sstevel@tonic-gate if (err != PICL_SUCCESS) 12710Sstevel@tonic-gate return (err); 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 12740Sstevel@tonic-gate cnode = di_sibling_node(cnode)) 12750Sstevel@tonic-gate (void) construct_openprom_tree(chdh, cnode); 12760Sstevel@tonic-gate 12770Sstevel@tonic-gate return (PICL_SUCCESS); 12780Sstevel@tonic-gate 12790Sstevel@tonic-gate } 12800Sstevel@tonic-gate 12810Sstevel@tonic-gate /* 12820Sstevel@tonic-gate * Process the libdevinfo device tree and create nodes in /platform or /obp 12830Sstevel@tonic-gate * PICL tree. 12840Sstevel@tonic-gate * 12850Sstevel@tonic-gate * This routine traverses the immediate children of "dinode" device and 12860Sstevel@tonic-gate * determines the node class for that child. If it finds a valid class 12870Sstevel@tonic-gate * name, then it builds a PICL node under /platform subtree and calls itself 12880Sstevel@tonic-gate * recursively to construct the subtree for that child node. Otherwise, if 12890Sstevel@tonic-gate * the parent_class is NULL, then it constructs a node and subtree under /obp 12900Sstevel@tonic-gate * subtree. 12910Sstevel@tonic-gate * 12920Sstevel@tonic-gate * Note that we skip the children nodes that don't have a valid class name 12930Sstevel@tonic-gate * and the parent_class is non NULL to prevent creation of any placeholder 12940Sstevel@tonic-gate * nodes (such as sd,...). 12950Sstevel@tonic-gate */ 12960Sstevel@tonic-gate static int 12970Sstevel@tonic-gate construct_devinfo_tree(picl_nodehdl_t plafh, picl_nodehdl_t obph, 12980Sstevel@tonic-gate di_node_t dinode, char *parent_class) 12990Sstevel@tonic-gate { 13000Sstevel@tonic-gate di_node_t cnode; 13010Sstevel@tonic-gate picl_nodehdl_t chdh; 13020Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 13030Sstevel@tonic-gate char *nodename; 13040Sstevel@tonic-gate int err; 13050Sstevel@tonic-gate 13060Sstevel@tonic-gate err = PICL_SUCCESS; 13070Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 13080Sstevel@tonic-gate cnode = di_sibling_node(cnode)) { 13090Sstevel@tonic-gate nodename = di_node_name(cnode); /* PICL_PROP_NAME */ 13100Sstevel@tonic-gate if (nodename == NULL) 13110Sstevel@tonic-gate continue; 13120Sstevel@tonic-gate 13130Sstevel@tonic-gate err = get_node_class(nodeclass, cnode, nodename); 13140Sstevel@tonic-gate 13150Sstevel@tonic-gate if (err == 0) { 13160Sstevel@tonic-gate err = construct_devtype_node(plafh, nodename, 13170Sstevel@tonic-gate nodeclass, cnode, &chdh); 13180Sstevel@tonic-gate if (err != PICL_SUCCESS) 13190Sstevel@tonic-gate return (err); 13200Sstevel@tonic-gate err = construct_devinfo_tree(chdh, obph, cnode, 13210Sstevel@tonic-gate nodeclass); 13220Sstevel@tonic-gate } else if (parent_class == NULL) 13230Sstevel@tonic-gate err = construct_openprom_tree(obph, cnode); 13240Sstevel@tonic-gate else 13250Sstevel@tonic-gate continue; 13260Sstevel@tonic-gate /* 13270Sstevel@tonic-gate * if parent_class is non NULL, skip the children nodes 13280Sstevel@tonic-gate * that don't have a valid device class - eliminates 13290Sstevel@tonic-gate * placeholder nodes (sd,...) from being created. 13300Sstevel@tonic-gate */ 13310Sstevel@tonic-gate } 13320Sstevel@tonic-gate 13330Sstevel@tonic-gate return (err); 13340Sstevel@tonic-gate 13350Sstevel@tonic-gate } 13360Sstevel@tonic-gate 13370Sstevel@tonic-gate /* 13380Sstevel@tonic-gate * This function is called from the event handler called from the daemon 13390Sstevel@tonic-gate * on PICL events. 13400Sstevel@tonic-gate * 13410Sstevel@tonic-gate * This routine traverses the children of the "dinode" device and 13420Sstevel@tonic-gate * creates a PICL node for each child not found in the PICL tree and 13430Sstevel@tonic-gate * invokes itself recursively to create a subtree for the newly created 13440Sstevel@tonic-gate * child node. It also checks if the node being created is a meory 13450Sstevel@tonic-gate * controller. If so, it posts PICLEVENT_MC_ADDED PICL event to the PICL 13460Sstevel@tonic-gate * framework. 13470Sstevel@tonic-gate */ 13480Sstevel@tonic-gate static int 13490Sstevel@tonic-gate update_subtree(picl_nodehdl_t nodeh, di_node_t dinode) 13500Sstevel@tonic-gate { 13510Sstevel@tonic-gate di_node_t cnode; 13520Sstevel@tonic-gate picl_nodehdl_t chdh; 13530Sstevel@tonic-gate picl_nodehdl_t nh; 13540Sstevel@tonic-gate char *nodename; 13550Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 13560Sstevel@tonic-gate char *path_buf; 13570Sstevel@tonic-gate char buf[MAX_UNIT_ADDRESS_LEN]; 13580Sstevel@tonic-gate char unitaddr[MAX_UNIT_ADDRESS_LEN]; 13590Sstevel@tonic-gate char path_w_ua[MAXPATHLEN]; 13600Sstevel@tonic-gate char path_wo_ua[MAXPATHLEN]; 13610Sstevel@tonic-gate char *strp; 13620Sstevel@tonic-gate int gotit; 13630Sstevel@tonic-gate int err; 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 13660Sstevel@tonic-gate cnode = di_sibling_node(cnode)) { 13670Sstevel@tonic-gate path_buf = di_devfs_path(cnode); 13680Sstevel@tonic-gate if (path_buf == NULL) 13690Sstevel@tonic-gate continue; 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate nodename = di_node_name(cnode); 13720Sstevel@tonic-gate if (nodename == NULL) { 13730Sstevel@tonic-gate di_devfs_path_free(path_buf); 13740Sstevel@tonic-gate continue; 13750Sstevel@tonic-gate } 13760Sstevel@tonic-gate 13770Sstevel@tonic-gate err = get_node_class(nodeclass, cnode, nodename); 13780Sstevel@tonic-gate 13790Sstevel@tonic-gate if (err < 0) { 13800Sstevel@tonic-gate di_devfs_path_free(path_buf); 13810Sstevel@tonic-gate continue; 13820Sstevel@tonic-gate } 13830Sstevel@tonic-gate 13840Sstevel@tonic-gate /* 13850Sstevel@tonic-gate * this is quite complicated - both path_buf and any nodes 13860Sstevel@tonic-gate * already in the picl tree may, or may not, have the 13870Sstevel@tonic-gate * @<unit_addr> at the end of their names. So we must 13880Sstevel@tonic-gate * take path_buf and work out what the device path would 13890Sstevel@tonic-gate * be both with and without the unit_address, then search 13900Sstevel@tonic-gate * the picl tree for both forms. 13910Sstevel@tonic-gate */ 13920Sstevel@tonic-gate if (((strp = strrchr(path_buf, '/')) != NULL) && 13930Sstevel@tonic-gate strchr(strp, '@') == NULL) { 13940Sstevel@tonic-gate /* 13950Sstevel@tonic-gate * this is an unattached node - so the path is not 13960Sstevel@tonic-gate * unique. Need to find out which node it is. 13970Sstevel@tonic-gate * Find the unit_address from the obp properties. 13980Sstevel@tonic-gate */ 13990Sstevel@tonic-gate err = ptree_create_node(nodename, nodeclass, &chdh); 14000Sstevel@tonic-gate if (err != PICL_SUCCESS) 14010Sstevel@tonic-gate return (err); 14020Sstevel@tonic-gate (void) add_openprom_props(chdh, cnode); 14030Sstevel@tonic-gate err = get_unitaddr(nodeh, chdh, unitaddr, 14040Sstevel@tonic-gate sizeof (unitaddr)); 14050Sstevel@tonic-gate if (err != PICL_SUCCESS) 14060Sstevel@tonic-gate return (err); 14070Sstevel@tonic-gate (void) ptree_destroy_node(chdh); 14080Sstevel@tonic-gate (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s@%s", 14090Sstevel@tonic-gate path_buf, unitaddr); 14100Sstevel@tonic-gate (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s", 14110Sstevel@tonic-gate path_buf); 14120Sstevel@tonic-gate } else { 14130Sstevel@tonic-gate /* 14140Sstevel@tonic-gate * this is an attached node - so the path is unique 14150Sstevel@tonic-gate */ 14160Sstevel@tonic-gate (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s", 14170Sstevel@tonic-gate path_buf); 14180Sstevel@tonic-gate (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s", 14190Sstevel@tonic-gate path_buf); 14200Sstevel@tonic-gate strp = strrchr(path_wo_ua, '@'); 14210Sstevel@tonic-gate *strp++ = '\0'; 14220Sstevel@tonic-gate (void) snprintf(unitaddr, sizeof (unitaddr), "%s", 14230Sstevel@tonic-gate strp); 14240Sstevel@tonic-gate } 14250Sstevel@tonic-gate /* 14260Sstevel@tonic-gate * first look for node with unit address in devfs_path 14270Sstevel@tonic-gate */ 14280Sstevel@tonic-gate if (ptree_find_node(nodeh, PICL_PROP_DEVFS_PATH, 14290Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, path_w_ua, strlen(path_w_ua) + 1, 14300Sstevel@tonic-gate &nh) == PICL_SUCCESS) { 14310Sstevel@tonic-gate /* 14320Sstevel@tonic-gate * node already there - there's nothing we need to do 14330Sstevel@tonic-gate */ 14340Sstevel@tonic-gate if (picldevtree_debug > 1) 14350Sstevel@tonic-gate syslog(LOG_INFO, 14360Sstevel@tonic-gate "update_subtree: path:%s node exists\n", 14370Sstevel@tonic-gate path_buf); 14380Sstevel@tonic-gate di_devfs_path_free(path_buf); 14390Sstevel@tonic-gate continue; 14400Sstevel@tonic-gate } 14410Sstevel@tonic-gate /* 14420Sstevel@tonic-gate * now look for node without unit address in devfs_path. 14430Sstevel@tonic-gate * This might be just one out of several 14440Sstevel@tonic-gate * nodes - need to check all siblings 14450Sstevel@tonic-gate */ 14460Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, 14470Sstevel@tonic-gate &chdh, sizeof (chdh)); 14480Sstevel@tonic-gate if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND)) 14490Sstevel@tonic-gate return (err); 14500Sstevel@tonic-gate gotit = 0; 14510Sstevel@tonic-gate while (err == PICL_SUCCESS) { 14520Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 14530Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, buf, sizeof (buf)); 14540Sstevel@tonic-gate if (err != PICL_SUCCESS) 14550Sstevel@tonic-gate return (err); 14560Sstevel@tonic-gate if (strcmp(buf, path_wo_ua) == 0) { 14570Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 14580Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, buf, sizeof (buf)); 14590Sstevel@tonic-gate if (err != PICL_SUCCESS) 14600Sstevel@tonic-gate return (err); 14610Sstevel@tonic-gate if (strcmp(buf, unitaddr) == 0) { 14620Sstevel@tonic-gate gotit = 1; 14630Sstevel@tonic-gate break; 14640Sstevel@tonic-gate } 14650Sstevel@tonic-gate } 14660Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 14670Sstevel@tonic-gate PICL_PROP_PEER, &chdh, sizeof (chdh)); 14680Sstevel@tonic-gate if (err != PICL_SUCCESS) 14690Sstevel@tonic-gate break; 14700Sstevel@tonic-gate } 14710Sstevel@tonic-gate if (gotit) { 14720Sstevel@tonic-gate /* 14730Sstevel@tonic-gate * node already there - there's nothing we need to do 14740Sstevel@tonic-gate */ 14750Sstevel@tonic-gate if (picldevtree_debug > 1) 14760Sstevel@tonic-gate syslog(LOG_INFO, 14770Sstevel@tonic-gate "update_subtree: path:%s node exists\n", 14780Sstevel@tonic-gate path_buf); 14790Sstevel@tonic-gate di_devfs_path_free(path_buf); 14800Sstevel@tonic-gate continue; 14810Sstevel@tonic-gate } 14820Sstevel@tonic-gate 14830Sstevel@tonic-gate #define IS_MC(x) (strcmp(x, PICL_CLASS_MEMORY_CONTROLLER) == 0 ? 1 : 0) 14840Sstevel@tonic-gate 14850Sstevel@tonic-gate if (construct_devtype_node(nodeh, nodename, nodeclass, cnode, 14860Sstevel@tonic-gate &chdh) == PICL_SUCCESS) { 14870Sstevel@tonic-gate if (picldevtree_debug) 14880Sstevel@tonic-gate syslog(LOG_INFO, 14890Sstevel@tonic-gate "picldevtree: added node:%s path:%s\n", 14900Sstevel@tonic-gate nodename, path_buf); 14910Sstevel@tonic-gate if (IS_MC(nodeclass)) { 14920Sstevel@tonic-gate if (post_mc_event(PICLEVENT_MC_ADDED, chdh) != 14930Sstevel@tonic-gate PICL_SUCCESS) 14940Sstevel@tonic-gate syslog(LOG_WARNING, PICL_EVENT_DROPPED, 14950Sstevel@tonic-gate PICLEVENT_MC_ADDED); 14960Sstevel@tonic-gate } 14970Sstevel@tonic-gate 14980Sstevel@tonic-gate di_devfs_path_free(path_buf); 14990Sstevel@tonic-gate (void) update_subtree(chdh, cnode); 15000Sstevel@tonic-gate } 15010Sstevel@tonic-gate } 15020Sstevel@tonic-gate 15030Sstevel@tonic-gate return (PICL_SUCCESS); 15040Sstevel@tonic-gate 15050Sstevel@tonic-gate } 15060Sstevel@tonic-gate 15070Sstevel@tonic-gate /* 1508*7442SMichael.Bergknoff@Sun.COM * Check for a stale OBP node. EINVAL is returned from the openprom(7D) driver 1509*7442SMichael.Bergknoff@Sun.COM * if the nodeid stored in the snapshot is not valid. 1510*7442SMichael.Bergknoff@Sun.COM */ 1511*7442SMichael.Bergknoff@Sun.COM static int 1512*7442SMichael.Bergknoff@Sun.COM check_stale_node(di_node_t node, void *arg) 1513*7442SMichael.Bergknoff@Sun.COM { 1514*7442SMichael.Bergknoff@Sun.COM di_prom_prop_t promp; 1515*7442SMichael.Bergknoff@Sun.COM 1516*7442SMichael.Bergknoff@Sun.COM errno = 0; 1517*7442SMichael.Bergknoff@Sun.COM promp = di_prom_prop_next(ph, node, DI_PROM_PROP_NIL); 1518*7442SMichael.Bergknoff@Sun.COM if (promp == DI_PROM_PROP_NIL && errno == EINVAL) { 1519*7442SMichael.Bergknoff@Sun.COM snapshot_stale = 1; 1520*7442SMichael.Bergknoff@Sun.COM return (DI_WALK_TERMINATE); 1521*7442SMichael.Bergknoff@Sun.COM } 1522*7442SMichael.Bergknoff@Sun.COM return (DI_WALK_CONTINUE); 1523*7442SMichael.Bergknoff@Sun.COM } 1524*7442SMichael.Bergknoff@Sun.COM 1525*7442SMichael.Bergknoff@Sun.COM /* 1526*7442SMichael.Bergknoff@Sun.COM * Walk the snapshot and check the OBP properties of each node. 1527*7442SMichael.Bergknoff@Sun.COM */ 1528*7442SMichael.Bergknoff@Sun.COM static int 1529*7442SMichael.Bergknoff@Sun.COM is_snapshot_stale(di_node_t root) 1530*7442SMichael.Bergknoff@Sun.COM { 1531*7442SMichael.Bergknoff@Sun.COM snapshot_stale = 0; 1532*7442SMichael.Bergknoff@Sun.COM di_walk_node(root, DI_WALK_CLDFIRST, NULL, check_stale_node); 1533*7442SMichael.Bergknoff@Sun.COM return (snapshot_stale); 1534*7442SMichael.Bergknoff@Sun.COM } 1535*7442SMichael.Bergknoff@Sun.COM 1536*7442SMichael.Bergknoff@Sun.COM /* 15370Sstevel@tonic-gate * This function processes the data from libdevinfo and creates nodes 15380Sstevel@tonic-gate * in the PICL tree. 15390Sstevel@tonic-gate */ 15400Sstevel@tonic-gate static int 15410Sstevel@tonic-gate libdevinfo_init(picl_nodehdl_t rooth) 15420Sstevel@tonic-gate { 15430Sstevel@tonic-gate di_node_t di_root; 15440Sstevel@tonic-gate picl_nodehdl_t plafh; 15450Sstevel@tonic-gate picl_nodehdl_t obph; 15460Sstevel@tonic-gate int err; 15470Sstevel@tonic-gate 15485492Sarutz /* 15495492Sarutz * Use DINFOCACHE so that we obtain all attributes for all 15505492Sarutz * device instances (without necessarily doing a load/attach 15515492Sarutz * of all drivers). Once the (on-disk) cache file is built, it 15525492Sarutz * exists over a reboot and can be read into memory at a very 15535492Sarutz * low cost. 15545492Sarutz */ 15555492Sarutz if ((di_root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) 15560Sstevel@tonic-gate return (PICL_FAILURE); 15570Sstevel@tonic-gate 15580Sstevel@tonic-gate if ((ph = di_prom_init()) == NULL) 15590Sstevel@tonic-gate return (PICL_FAILURE); 1560*7442SMichael.Bergknoff@Sun.COM 1561*7442SMichael.Bergknoff@Sun.COM /* 1562*7442SMichael.Bergknoff@Sun.COM * Check if the snapshot cache contains stale OBP nodeid references. 1563*7442SMichael.Bergknoff@Sun.COM * If it does release the snapshot and obtain a live snapshot from the 1564*7442SMichael.Bergknoff@Sun.COM * kernel. 1565*7442SMichael.Bergknoff@Sun.COM */ 1566*7442SMichael.Bergknoff@Sun.COM if (is_snapshot_stale(di_root)) { 1567*7442SMichael.Bergknoff@Sun.COM syslog(LOG_INFO, "picld detected stale snapshot cache"); 1568*7442SMichael.Bergknoff@Sun.COM di_fini(di_root); 1569*7442SMichael.Bergknoff@Sun.COM if ((di_root = di_init("/", DINFOCPYALL | DINFOFORCE)) == 1570*7442SMichael.Bergknoff@Sun.COM DI_NODE_NIL) { 1571*7442SMichael.Bergknoff@Sun.COM return (PICL_FAILURE); 1572*7442SMichael.Bergknoff@Sun.COM } 1573*7442SMichael.Bergknoff@Sun.COM } 1574*7442SMichael.Bergknoff@Sun.COM 15750Sstevel@tonic-gate /* 15760Sstevel@tonic-gate * create platform PICL node using di_root node 15770Sstevel@tonic-gate */ 15780Sstevel@tonic-gate err = construct_picl_platform(rooth, di_root, &plafh); 15790Sstevel@tonic-gate if (err != PICL_SUCCESS) { 15800Sstevel@tonic-gate di_fini(di_root); 15810Sstevel@tonic-gate return (PICL_FAILURE); 15820Sstevel@tonic-gate } 15830Sstevel@tonic-gate 15840Sstevel@tonic-gate err = construct_picl_openprom(rooth, &obph); 15850Sstevel@tonic-gate if (err != PICL_SUCCESS) { 15860Sstevel@tonic-gate di_fini(di_root); 15870Sstevel@tonic-gate return (PICL_FAILURE); 15880Sstevel@tonic-gate } 15890Sstevel@tonic-gate 15900Sstevel@tonic-gate (void) construct_devinfo_tree(plafh, obph, di_root, NULL); 15910Sstevel@tonic-gate if (ph) { 15920Sstevel@tonic-gate di_prom_fini(ph); 15930Sstevel@tonic-gate ph = NULL; 15940Sstevel@tonic-gate } 15950Sstevel@tonic-gate di_fini(di_root); 15960Sstevel@tonic-gate return (err); 15970Sstevel@tonic-gate } 15980Sstevel@tonic-gate 15990Sstevel@tonic-gate /* 16000Sstevel@tonic-gate * This function returns the integer property value 16010Sstevel@tonic-gate */ 16020Sstevel@tonic-gate static int 16030Sstevel@tonic-gate get_int_propval_by_name(picl_nodehdl_t nodeh, char *pname, int *ival) 16040Sstevel@tonic-gate { 16050Sstevel@tonic-gate int err; 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, pname, ival, 16080Sstevel@tonic-gate sizeof (int)); 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate return (err); 16110Sstevel@tonic-gate } 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate /* 16140Sstevel@tonic-gate * This function returns the port ID (or CPU ID in the case of CMP cores) 16150Sstevel@tonic-gate * of the specific CPU node handle. If upa_portid exists, return its value. 16160Sstevel@tonic-gate * Otherwise, return portid/cpuid. 16170Sstevel@tonic-gate */ 16180Sstevel@tonic-gate static int 16190Sstevel@tonic-gate get_cpu_portid(picl_nodehdl_t modh, int *id) 16200Sstevel@tonic-gate { 16210Sstevel@tonic-gate int err; 16220Sstevel@tonic-gate 16235028Sfw157321 if (strcmp(mach_name, "sun4u") == 0 || 16245028Sfw157321 strcmp(mach_name, "sun4v") == 0) { 16250Sstevel@tonic-gate err = get_int_propval_by_name(modh, OBP_PROP_UPA_PORTID, id); 16260Sstevel@tonic-gate if (err == PICL_SUCCESS) 16270Sstevel@tonic-gate return (err); 16280Sstevel@tonic-gate err = get_int_propval_by_name(modh, OBP_PROP_PORTID, id); 16290Sstevel@tonic-gate if (err == PICL_SUCCESS) 16300Sstevel@tonic-gate return (err); 16310Sstevel@tonic-gate return (get_int_propval_by_name(modh, OBP_PROP_CPUID, id)); 16320Sstevel@tonic-gate } 16330Sstevel@tonic-gate if (strcmp(mach_name, "i86pc") == 0) 16340Sstevel@tonic-gate return (get_int_propval_by_name(modh, PICL_PROP_INSTANCE, id)); 16350Sstevel@tonic-gate 16360Sstevel@tonic-gate return (PICL_FAILURE); 16370Sstevel@tonic-gate } 16380Sstevel@tonic-gate 16390Sstevel@tonic-gate /* 16400Sstevel@tonic-gate * This function is the volatile read access function of CPU state 16410Sstevel@tonic-gate * property 16420Sstevel@tonic-gate */ 16430Sstevel@tonic-gate static int 16440Sstevel@tonic-gate get_pi_state(ptree_rarg_t *rarg, void *vbuf) 16450Sstevel@tonic-gate { 16460Sstevel@tonic-gate int id; 16470Sstevel@tonic-gate int err; 16480Sstevel@tonic-gate 16490Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 16500Sstevel@tonic-gate if (err != PICL_SUCCESS) 16510Sstevel@tonic-gate return (err); 16520Sstevel@tonic-gate 16530Sstevel@tonic-gate switch (p_online(id, P_STATUS)) { 16540Sstevel@tonic-gate case P_ONLINE: 16550Sstevel@tonic-gate (void) strlcpy(vbuf, PS_ONLINE, MAX_STATE_SIZE); 16560Sstevel@tonic-gate break; 16570Sstevel@tonic-gate case P_OFFLINE: 16580Sstevel@tonic-gate (void) strlcpy(vbuf, PS_OFFLINE, MAX_STATE_SIZE); 16590Sstevel@tonic-gate break; 16600Sstevel@tonic-gate case P_NOINTR: 16610Sstevel@tonic-gate (void) strlcpy(vbuf, PS_NOINTR, MAX_STATE_SIZE); 16620Sstevel@tonic-gate break; 16630Sstevel@tonic-gate case P_SPARE: 16640Sstevel@tonic-gate (void) strlcpy(vbuf, PS_SPARE, MAX_STATE_SIZE); 16650Sstevel@tonic-gate break; 16660Sstevel@tonic-gate case P_FAULTED: 16670Sstevel@tonic-gate (void) strlcpy(vbuf, PS_FAULTED, MAX_STATE_SIZE); 16680Sstevel@tonic-gate break; 16690Sstevel@tonic-gate case P_POWEROFF: 16700Sstevel@tonic-gate (void) strlcpy(vbuf, PS_POWEROFF, MAX_STATE_SIZE); 16710Sstevel@tonic-gate break; 16720Sstevel@tonic-gate default: 16730Sstevel@tonic-gate (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE); 16740Sstevel@tonic-gate break; 16750Sstevel@tonic-gate } 16760Sstevel@tonic-gate return (PICL_SUCCESS); 16770Sstevel@tonic-gate } 16780Sstevel@tonic-gate 16790Sstevel@tonic-gate /* 16800Sstevel@tonic-gate * This function is the volatile read access function of CPU processor_type 16810Sstevel@tonic-gate * property 16820Sstevel@tonic-gate */ 16830Sstevel@tonic-gate static int 16840Sstevel@tonic-gate get_processor_type(ptree_rarg_t *rarg, void *vbuf) 16850Sstevel@tonic-gate { 16860Sstevel@tonic-gate processor_info_t cpu_info; 16870Sstevel@tonic-gate int id; 16880Sstevel@tonic-gate int err; 16890Sstevel@tonic-gate 16900Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 16910Sstevel@tonic-gate if (err != PICL_SUCCESS) 16920Sstevel@tonic-gate return (err); 16930Sstevel@tonic-gate 16940Sstevel@tonic-gate if (processor_info(id, &cpu_info) >= 0) { 16950Sstevel@tonic-gate (void) strlcpy(vbuf, cpu_info.pi_processor_type, PI_TYPELEN); 16960Sstevel@tonic-gate } 16970Sstevel@tonic-gate return (PICL_SUCCESS); 16980Sstevel@tonic-gate } 16990Sstevel@tonic-gate 17000Sstevel@tonic-gate /* 17010Sstevel@tonic-gate * This function is the volatile read access function of CPU fputypes 17020Sstevel@tonic-gate * property 17030Sstevel@tonic-gate */ 17040Sstevel@tonic-gate static int 17050Sstevel@tonic-gate get_fputypes(ptree_rarg_t *rarg, void *vbuf) 17060Sstevel@tonic-gate { 17070Sstevel@tonic-gate processor_info_t cpu_info; 17080Sstevel@tonic-gate int id; 17090Sstevel@tonic-gate int err; 17100Sstevel@tonic-gate 17110Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 17120Sstevel@tonic-gate if (err != PICL_SUCCESS) 17130Sstevel@tonic-gate return (err); 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate if (processor_info(id, &cpu_info) >= 0) { 17160Sstevel@tonic-gate (void) strlcpy(vbuf, cpu_info.pi_fputypes, PI_FPUTYPE); 17170Sstevel@tonic-gate } 17180Sstevel@tonic-gate return (PICL_SUCCESS); 17190Sstevel@tonic-gate } 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate /* 17220Sstevel@tonic-gate * This function is the volatile read access function of CPU StateBegin 17230Sstevel@tonic-gate * property. To minimize overhead, use kstat_chain_update() to refresh 17240Sstevel@tonic-gate * the kstat header info as opposed to invoking kstat_open() every time. 17250Sstevel@tonic-gate */ 17260Sstevel@tonic-gate static int 17270Sstevel@tonic-gate get_pi_state_begin(ptree_rarg_t *rarg, void *vbuf) 17280Sstevel@tonic-gate { 17290Sstevel@tonic-gate int err; 17300Sstevel@tonic-gate int cpu_id; 17310Sstevel@tonic-gate static kstat_ctl_t *kc = NULL; 17320Sstevel@tonic-gate static pthread_mutex_t kc_mutex = PTHREAD_MUTEX_INITIALIZER; 17330Sstevel@tonic-gate kstat_t *kp; 17340Sstevel@tonic-gate kstat_named_t *kn; 17350Sstevel@tonic-gate 17360Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &cpu_id); 17370Sstevel@tonic-gate if (err != PICL_SUCCESS) 17380Sstevel@tonic-gate return (err); 17390Sstevel@tonic-gate 17400Sstevel@tonic-gate (void) pthread_mutex_lock(&kc_mutex); 17410Sstevel@tonic-gate if (kc == NULL) 17420Sstevel@tonic-gate kc = kstat_open(); 17430Sstevel@tonic-gate else if (kstat_chain_update(kc) == -1) { 17440Sstevel@tonic-gate (void) kstat_close(kc); 17450Sstevel@tonic-gate kc = kstat_open(); 17460Sstevel@tonic-gate } 17470Sstevel@tonic-gate 17480Sstevel@tonic-gate if (kc == NULL) { 17490Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 17500Sstevel@tonic-gate return (PICL_FAILURE); 17510Sstevel@tonic-gate } 17520Sstevel@tonic-gate 17530Sstevel@tonic-gate /* Get the state_begin from kstat */ 17540Sstevel@tonic-gate if ((kp = kstat_lookup(kc, KSTAT_CPU_INFO, cpu_id, NULL)) == NULL || 17550Sstevel@tonic-gate kp->ks_type != KSTAT_TYPE_NAMED || kstat_read(kc, kp, 0) < 0) { 17560Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 17570Sstevel@tonic-gate return (PICL_FAILURE); 17580Sstevel@tonic-gate } 17590Sstevel@tonic-gate 17600Sstevel@tonic-gate kn = kstat_data_lookup(kp, KSTAT_STATE_BEGIN); 17610Sstevel@tonic-gate if (kn) { 17620Sstevel@tonic-gate *(uint64_t *)vbuf = (uint64_t)kn->value.l; 17630Sstevel@tonic-gate err = PICL_SUCCESS; 17640Sstevel@tonic-gate } else 17650Sstevel@tonic-gate err = PICL_FAILURE; 17660Sstevel@tonic-gate 17670Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 17680Sstevel@tonic-gate return (err); 17690Sstevel@tonic-gate } 17700Sstevel@tonic-gate 17710Sstevel@tonic-gate /* 17720Sstevel@tonic-gate * This function adds CPU information to the CPU nodes 17730Sstevel@tonic-gate */ 17740Sstevel@tonic-gate /* ARGSUSED */ 17750Sstevel@tonic-gate static int 17760Sstevel@tonic-gate add_processor_info(picl_nodehdl_t cpuh, void *args) 17770Sstevel@tonic-gate { 17780Sstevel@tonic-gate int err; 17790Sstevel@tonic-gate int cpu_id; 17800Sstevel@tonic-gate ptree_propinfo_t propinfo; 17810Sstevel@tonic-gate ptree_propinfo_t pinfo; 17820Sstevel@tonic-gate 17830Sstevel@tonic-gate err = get_cpu_portid(cpuh, &cpu_id); 17840Sstevel@tonic-gate if (err != PICL_SUCCESS) 17850Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 17860Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 17870Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (int), PICL_PROP_ID, NULL, NULL); 17880Sstevel@tonic-gate err = ptree_create_and_add_prop(cpuh, &propinfo, &cpu_id, NULL); 17890Sstevel@tonic-gate if (err != PICL_SUCCESS) 17900Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 17910Sstevel@tonic-gate 17920Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 17930Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), MAX_STATE_SIZE, 17940Sstevel@tonic-gate PICL_PROP_STATE, get_pi_state, NULL); 17950Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 17960Sstevel@tonic-gate 17970Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 17980Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_TYPELEN, 17990Sstevel@tonic-gate PICL_PROP_PROCESSOR_TYPE, get_processor_type, NULL); 18000Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 18010Sstevel@tonic-gate 18020Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 18030Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_FPUTYPE, 18040Sstevel@tonic-gate PICL_PROP_FPUTYPE, get_fputypes, NULL); 18050Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 18060Sstevel@tonic-gate 18070Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 18080Sstevel@tonic-gate PICL_PTYPE_TIMESTAMP, PICL_READ|PICL_VOLATILE, sizeof (uint64_t), 18090Sstevel@tonic-gate PICL_PROP_STATE_BEGIN, get_pi_state_begin, NULL); 18100Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 18110Sstevel@tonic-gate 18120Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 18130Sstevel@tonic-gate } 18140Sstevel@tonic-gate 18150Sstevel@tonic-gate /* 18160Sstevel@tonic-gate * This function sets up the "ID" property in every CPU nodes 18170Sstevel@tonic-gate * and adds processor info 18180Sstevel@tonic-gate */ 18190Sstevel@tonic-gate static int 18200Sstevel@tonic-gate setup_cpus(picl_nodehdl_t plafh) 18210Sstevel@tonic-gate { 18220Sstevel@tonic-gate int err; 18230Sstevel@tonic-gate 18240Sstevel@tonic-gate err = ptree_walk_tree_by_class(plafh, PICL_CLASS_CPU, NULL, 18250Sstevel@tonic-gate add_processor_info); 18260Sstevel@tonic-gate 18270Sstevel@tonic-gate return (err); 18280Sstevel@tonic-gate } 18290Sstevel@tonic-gate 18300Sstevel@tonic-gate /* 18310Sstevel@tonic-gate * This function format's the manufacture's information for FFB display 18320Sstevel@tonic-gate * devices 18330Sstevel@tonic-gate */ 18340Sstevel@tonic-gate static void 18350Sstevel@tonic-gate fmt_manf_id(manuf_t manufid, int bufsz, char *outbuf) 18360Sstevel@tonic-gate { 18370Sstevel@tonic-gate /* 18380Sstevel@tonic-gate * Format the manufacturer's info. Note a small inconsistency we 18390Sstevel@tonic-gate * have to work around - Brooktree has it's part number in decimal, 18400Sstevel@tonic-gate * while Mitsubishi has it's part number in hex. 18410Sstevel@tonic-gate */ 18420Sstevel@tonic-gate switch (manufid.fld.manf) { 18430Sstevel@tonic-gate case MANF_BROOKTREE: 18440Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, "%s %d, version %d", 18450Sstevel@tonic-gate "Brooktree", manufid.fld.partno, manufid.fld.version); 18460Sstevel@tonic-gate break; 18470Sstevel@tonic-gate 18480Sstevel@tonic-gate case MANF_MITSUBISHI: 18490Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, "%s %x, version %d", 18500Sstevel@tonic-gate "Mitsubishi", manufid.fld.partno, manufid.fld.version); 18510Sstevel@tonic-gate break; 18520Sstevel@tonic-gate 18530Sstevel@tonic-gate default: 18540Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, 18550Sstevel@tonic-gate "JED code %d, Part num 0x%x, version %d", 18560Sstevel@tonic-gate manufid.fld.manf, manufid.fld.partno, manufid.fld.version); 18570Sstevel@tonic-gate } 18580Sstevel@tonic-gate } 18590Sstevel@tonic-gate 18600Sstevel@tonic-gate /* 18610Sstevel@tonic-gate * If it's an ffb device, open ffb devices and return PICL_SUCCESS 18620Sstevel@tonic-gate */ 18630Sstevel@tonic-gate static int 18640Sstevel@tonic-gate open_ffb_device(picl_nodehdl_t ffbh, int *fd) 18650Sstevel@tonic-gate { 18660Sstevel@tonic-gate DIR *dirp; 18670Sstevel@tonic-gate char devfs_path[PATH_MAX]; 18680Sstevel@tonic-gate char dev_path[PATH_MAX]; 18690Sstevel@tonic-gate char *devp; 18700Sstevel@tonic-gate struct dirent *direntp; 18710Sstevel@tonic-gate int err; 18720Sstevel@tonic-gate int tmpfd; 18730Sstevel@tonic-gate 18740Sstevel@tonic-gate /* Get the devfs_path of the ffb devices */ 18750Sstevel@tonic-gate err = ptree_get_propval_by_name(ffbh, PICL_PROP_DEVFS_PATH, devfs_path, 18760Sstevel@tonic-gate sizeof (devfs_path)); 18770Sstevel@tonic-gate if (err != PICL_SUCCESS) 18780Sstevel@tonic-gate return (err); 18790Sstevel@tonic-gate 18800Sstevel@tonic-gate /* Get the device node name */ 18810Sstevel@tonic-gate devp = strrchr(devfs_path, '/'); 18820Sstevel@tonic-gate if (devp == NULL) 18830Sstevel@tonic-gate return (PICL_FAILURE); 18840Sstevel@tonic-gate *devp = '\0'; 18850Sstevel@tonic-gate ++devp; 18860Sstevel@tonic-gate 18870Sstevel@tonic-gate /* 18880Sstevel@tonic-gate * Check if device node name has the ffb string 18890Sstevel@tonic-gate * If not, assume it's not a ffb device. 18900Sstevel@tonic-gate */ 18910Sstevel@tonic-gate if (strstr(devp, FFB_NAME) == NULL) 18920Sstevel@tonic-gate return (PICL_FAILURE); 18930Sstevel@tonic-gate 18940Sstevel@tonic-gate /* 18950Sstevel@tonic-gate * Get the parent path of the ffb device node. 18960Sstevel@tonic-gate */ 18970Sstevel@tonic-gate (void) snprintf(dev_path, sizeof (dev_path), "%s/%s", "/devices", 18980Sstevel@tonic-gate devfs_path); 18990Sstevel@tonic-gate 19000Sstevel@tonic-gate /* 19010Sstevel@tonic-gate * Since we don't know ffb's minor nodename, 19020Sstevel@tonic-gate * we need to search all the devices under its 19030Sstevel@tonic-gate * parent dir by comparing the node name 19040Sstevel@tonic-gate */ 19050Sstevel@tonic-gate if ((dirp = opendir(dev_path)) == NULL) 19060Sstevel@tonic-gate return (PICL_FAILURE); 19070Sstevel@tonic-gate 19080Sstevel@tonic-gate while ((direntp = readdir(dirp)) != NULL) { 19090Sstevel@tonic-gate if (strstr(direntp->d_name, devp) != NULL) { 19100Sstevel@tonic-gate (void) strcat(dev_path, "/"); 19110Sstevel@tonic-gate (void) strcat(dev_path, direntp->d_name); 19120Sstevel@tonic-gate tmpfd = open(dev_path, O_RDWR); 19130Sstevel@tonic-gate if (tmpfd < 0) 19140Sstevel@tonic-gate continue; 19150Sstevel@tonic-gate *fd = tmpfd; 19160Sstevel@tonic-gate (void) closedir(dirp); 19170Sstevel@tonic-gate return (PICL_SUCCESS); 19180Sstevel@tonic-gate } 19190Sstevel@tonic-gate } 19200Sstevel@tonic-gate 19210Sstevel@tonic-gate (void) closedir(dirp); 19220Sstevel@tonic-gate return (PICL_FAILURE); 19230Sstevel@tonic-gate } 19240Sstevel@tonic-gate 19250Sstevel@tonic-gate /* 19260Sstevel@tonic-gate * This function recursively searches the tree for ffb display devices 19270Sstevel@tonic-gate * and add ffb config information 19280Sstevel@tonic-gate */ 19290Sstevel@tonic-gate static int 19300Sstevel@tonic-gate add_ffb_config_info(picl_nodehdl_t rooth) 19310Sstevel@tonic-gate { 19320Sstevel@tonic-gate picl_nodehdl_t nodeh; 19330Sstevel@tonic-gate int err; 19340Sstevel@tonic-gate char piclclass[PICL_CLASSNAMELEN_MAX]; 19350Sstevel@tonic-gate char manfidbuf[FFB_MANUF_BUFSIZE]; 19360Sstevel@tonic-gate int fd; 19370Sstevel@tonic-gate int board_rev; 19380Sstevel@tonic-gate ffb_sys_info_t fsi; 19390Sstevel@tonic-gate ptree_propinfo_t pinfo; 19400Sstevel@tonic-gate 19410Sstevel@tonic-gate for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh, 19420Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 19435028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, 19445028Sfw157321 &nodeh, sizeof (picl_nodehdl_t))) { 19450Sstevel@tonic-gate 19460Sstevel@tonic-gate if (err != PICL_SUCCESS) 19470Sstevel@tonic-gate return (err); 19480Sstevel@tonic-gate 19490Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 19500Sstevel@tonic-gate piclclass, PICL_CLASSNAMELEN_MAX); 19510Sstevel@tonic-gate 19520Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 19530Sstevel@tonic-gate (strcmp(piclclass, PICL_CLASS_DISPLAY) == 0)) { 19540Sstevel@tonic-gate 19550Sstevel@tonic-gate err = open_ffb_device(nodeh, &fd); 19560Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 19570Sstevel@tonic-gate (ioctl(fd, FFB_SYS_INFO, &fsi) >= 0)) { 19580Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 19590Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 19600Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, 19610Sstevel@tonic-gate sizeof (int), PICL_PROP_FFB_BOARD_REV, 19620Sstevel@tonic-gate NULL, NULL); 19630Sstevel@tonic-gate board_rev = fsi.ffb_strap_bits.fld.board_rev; 19640Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 19650Sstevel@tonic-gate &board_rev, NULL); 19660Sstevel@tonic-gate 19670Sstevel@tonic-gate fmt_manf_id(fsi.dac_version, 19680Sstevel@tonic-gate sizeof (manfidbuf), manfidbuf); 19690Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 19700Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 19710Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 19720Sstevel@tonic-gate strlen(manfidbuf) + 1, 19730Sstevel@tonic-gate PICL_PROP_FFB_DAC_VER, NULL, NULL); 19740Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 19750Sstevel@tonic-gate manfidbuf, NULL); 19760Sstevel@tonic-gate 19770Sstevel@tonic-gate fmt_manf_id(fsi.fbram_version, 19780Sstevel@tonic-gate sizeof (manfidbuf), manfidbuf); 19790Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 19800Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 19810Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 19820Sstevel@tonic-gate strlen(manfidbuf) + 1, 19830Sstevel@tonic-gate PICL_PROP_FFB_FBRAM_VER, NULL, 19840Sstevel@tonic-gate NULL); 19850Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 19860Sstevel@tonic-gate manfidbuf, NULL); 19870Sstevel@tonic-gate (void) close(fd); 19880Sstevel@tonic-gate } 19890Sstevel@tonic-gate } else if (add_ffb_config_info(nodeh) != PICL_SUCCESS) 19900Sstevel@tonic-gate return (PICL_FAILURE); 19910Sstevel@tonic-gate } 19920Sstevel@tonic-gate return (PICL_SUCCESS); 19930Sstevel@tonic-gate } 19940Sstevel@tonic-gate 19950Sstevel@tonic-gate static conf_entries_t * 19960Sstevel@tonic-gate free_conf_entries(conf_entries_t *list) 19970Sstevel@tonic-gate { 19980Sstevel@tonic-gate conf_entries_t *el; 19990Sstevel@tonic-gate conf_entries_t *del; 20000Sstevel@tonic-gate 20010Sstevel@tonic-gate if (list == NULL) 20020Sstevel@tonic-gate return (NULL); 20030Sstevel@tonic-gate el = list; 20040Sstevel@tonic-gate while (el != NULL) { 20050Sstevel@tonic-gate del = el; 20060Sstevel@tonic-gate el = el->next; 20070Sstevel@tonic-gate free(del->name); 20080Sstevel@tonic-gate free(del->piclclass); 20090Sstevel@tonic-gate free(del); 20100Sstevel@tonic-gate } 20110Sstevel@tonic-gate return (el); 20120Sstevel@tonic-gate } 20130Sstevel@tonic-gate 20140Sstevel@tonic-gate /* 20150Sstevel@tonic-gate * Reading config order: platform, common 20160Sstevel@tonic-gate */ 20170Sstevel@tonic-gate static conf_entries_t * 20180Sstevel@tonic-gate read_conf_file(char *fname, conf_entries_t *list) 20190Sstevel@tonic-gate { 20200Sstevel@tonic-gate FILE *fp; 20210Sstevel@tonic-gate char lbuf[CONFFILE_LINELEN_MAX]; 20220Sstevel@tonic-gate char *nametok; 20230Sstevel@tonic-gate char *classtok; 20240Sstevel@tonic-gate conf_entries_t *el; 20250Sstevel@tonic-gate conf_entries_t *ptr; 20260Sstevel@tonic-gate 20270Sstevel@tonic-gate if (fname == NULL) 20280Sstevel@tonic-gate return (list); 20290Sstevel@tonic-gate 20300Sstevel@tonic-gate fp = fopen(fname, "r"); 20310Sstevel@tonic-gate 20320Sstevel@tonic-gate if (fp == NULL) 20330Sstevel@tonic-gate return (list); 20340Sstevel@tonic-gate 20350Sstevel@tonic-gate while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) { 20360Sstevel@tonic-gate if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n')) 20370Sstevel@tonic-gate continue; 20380Sstevel@tonic-gate 20390Sstevel@tonic-gate nametok = strtok(lbuf, " \t\n"); 20400Sstevel@tonic-gate if (nametok == NULL) 20410Sstevel@tonic-gate continue; 20420Sstevel@tonic-gate 20430Sstevel@tonic-gate classtok = strtok(NULL, " \t\n"); 20440Sstevel@tonic-gate if (classtok == NULL) 20450Sstevel@tonic-gate continue; 20460Sstevel@tonic-gate 20470Sstevel@tonic-gate el = malloc(sizeof (conf_entries_t)); 20480Sstevel@tonic-gate if (el == NULL) 20490Sstevel@tonic-gate break; 20500Sstevel@tonic-gate el->name = strdup(nametok); 20510Sstevel@tonic-gate el->piclclass = strdup(classtok); 20520Sstevel@tonic-gate if ((el->name == NULL) || (el->piclclass == NULL)) { 20530Sstevel@tonic-gate free(el); 20540Sstevel@tonic-gate return (list); 20550Sstevel@tonic-gate } 20560Sstevel@tonic-gate el->next = NULL; 20570Sstevel@tonic-gate 20580Sstevel@tonic-gate /* 20590Sstevel@tonic-gate * Add it to the end of list 20600Sstevel@tonic-gate */ 20610Sstevel@tonic-gate if (list == NULL) 20620Sstevel@tonic-gate list = el; 20630Sstevel@tonic-gate else { 20640Sstevel@tonic-gate ptr = list; 20650Sstevel@tonic-gate while (ptr->next != NULL) 20660Sstevel@tonic-gate ptr = ptr->next; 20670Sstevel@tonic-gate ptr->next = el; 20680Sstevel@tonic-gate } 20690Sstevel@tonic-gate 20700Sstevel@tonic-gate } 20710Sstevel@tonic-gate (void) fclose(fp); 20720Sstevel@tonic-gate return (list); 20730Sstevel@tonic-gate } 20740Sstevel@tonic-gate 20750Sstevel@tonic-gate /* 20760Sstevel@tonic-gate * Process the devtree conf file and set up the conf_name_class_map list 20770Sstevel@tonic-gate */ 20780Sstevel@tonic-gate static void 20790Sstevel@tonic-gate process_devtree_conf_file(void) 20800Sstevel@tonic-gate { 20810Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 20820Sstevel@tonic-gate char pname[PATH_MAX]; 20830Sstevel@tonic-gate 20840Sstevel@tonic-gate conf_name_class_map = NULL; 20850Sstevel@tonic-gate 20860Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 20870Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 20880Sstevel@tonic-gate (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX); 20890Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, 20900Sstevel@tonic-gate conf_name_class_map); 20910Sstevel@tonic-gate } 20920Sstevel@tonic-gate 20930Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 20940Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 20950Sstevel@tonic-gate (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX); 20960Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, 20970Sstevel@tonic-gate conf_name_class_map); 20980Sstevel@tonic-gate } 20990Sstevel@tonic-gate 21000Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR, 21010Sstevel@tonic-gate DEVTREE_CONFFILE_NAME); 21020Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, conf_name_class_map); 21030Sstevel@tonic-gate } 21040Sstevel@tonic-gate 21050Sstevel@tonic-gate static asr_conf_entries_t *conf_name_asr_map = NULL; 21060Sstevel@tonic-gate 21070Sstevel@tonic-gate static void 21080Sstevel@tonic-gate free_asr_conf_entries(asr_conf_entries_t *list) { 21090Sstevel@tonic-gate asr_conf_entries_t *el; 21100Sstevel@tonic-gate asr_conf_entries_t *del; 21110Sstevel@tonic-gate 21120Sstevel@tonic-gate el = list; 21130Sstevel@tonic-gate while (el != NULL) { 21140Sstevel@tonic-gate del = el; 21150Sstevel@tonic-gate el = el->next; 21160Sstevel@tonic-gate if (del->name) 21170Sstevel@tonic-gate free(del->name); 21180Sstevel@tonic-gate if (del->address) 21190Sstevel@tonic-gate free(del->address); 21200Sstevel@tonic-gate if (del->status) 21210Sstevel@tonic-gate free(del->status); 21220Sstevel@tonic-gate if (del->piclclass) 21230Sstevel@tonic-gate free(del->piclclass); 21240Sstevel@tonic-gate if (del->props) 21250Sstevel@tonic-gate free(del->props); 21260Sstevel@tonic-gate free(del); 21270Sstevel@tonic-gate } 21280Sstevel@tonic-gate } 21290Sstevel@tonic-gate 21300Sstevel@tonic-gate /* 21310Sstevel@tonic-gate * Reading config order: platform, common 21320Sstevel@tonic-gate */ 21330Sstevel@tonic-gate static asr_conf_entries_t * 21340Sstevel@tonic-gate read_asr_conf_file(char *fname, asr_conf_entries_t *list) 21350Sstevel@tonic-gate { 21360Sstevel@tonic-gate FILE *fp; 21370Sstevel@tonic-gate char lbuf[CONFFILE_LINELEN_MAX]; 21380Sstevel@tonic-gate char *nametok; 21390Sstevel@tonic-gate char *classtok; 21400Sstevel@tonic-gate char *statustok; 21410Sstevel@tonic-gate char *addresstok; 21420Sstevel@tonic-gate char *propstok; 21430Sstevel@tonic-gate asr_conf_entries_t *el; 21440Sstevel@tonic-gate asr_conf_entries_t *ptr; 21450Sstevel@tonic-gate 21460Sstevel@tonic-gate if (fname == NULL) 21470Sstevel@tonic-gate return (list); 21480Sstevel@tonic-gate 21490Sstevel@tonic-gate fp = fopen(fname, "r"); 21500Sstevel@tonic-gate if (fp == NULL) 21510Sstevel@tonic-gate return (list); 21520Sstevel@tonic-gate 21530Sstevel@tonic-gate while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) { 21540Sstevel@tonic-gate if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n')) 21550Sstevel@tonic-gate continue; 21560Sstevel@tonic-gate 21570Sstevel@tonic-gate nametok = strtok(lbuf, " \t\n"); 21580Sstevel@tonic-gate if (nametok == NULL) 21590Sstevel@tonic-gate continue; 21600Sstevel@tonic-gate 21610Sstevel@tonic-gate classtok = strtok(NULL, " \t\n"); 21620Sstevel@tonic-gate if (classtok == NULL) 21630Sstevel@tonic-gate continue; 21640Sstevel@tonic-gate 21650Sstevel@tonic-gate statustok = strtok(NULL, " \t\n"); 21660Sstevel@tonic-gate if (statustok == NULL) 21670Sstevel@tonic-gate continue; 21680Sstevel@tonic-gate 21690Sstevel@tonic-gate addresstok = strtok(NULL, " \t\n"); 21700Sstevel@tonic-gate if (addresstok == NULL) 21710Sstevel@tonic-gate continue; 21720Sstevel@tonic-gate 21730Sstevel@tonic-gate /* 21740Sstevel@tonic-gate * props are optional 21750Sstevel@tonic-gate */ 21760Sstevel@tonic-gate propstok = strtok(NULL, " \t\n"); 21770Sstevel@tonic-gate 21780Sstevel@tonic-gate el = malloc(sizeof (asr_conf_entries_t)); 21790Sstevel@tonic-gate if (el == NULL) 21800Sstevel@tonic-gate break; 21810Sstevel@tonic-gate el->name = strdup(nametok); 21820Sstevel@tonic-gate el->piclclass = strdup(classtok); 21830Sstevel@tonic-gate el->status = strdup(statustok); 21840Sstevel@tonic-gate el->address = strdup(addresstok); 21850Sstevel@tonic-gate if (propstok != NULL) 21860Sstevel@tonic-gate el->props = strdup(propstok); 21870Sstevel@tonic-gate else 21880Sstevel@tonic-gate el->props = NULL; 21890Sstevel@tonic-gate if ((el->name == NULL) || (el->piclclass == NULL) || 21900Sstevel@tonic-gate (el->address == NULL) || (el->status == NULL)) { 21910Sstevel@tonic-gate if (el->name) 21920Sstevel@tonic-gate free(el->name); 21930Sstevel@tonic-gate if (el->address) 21940Sstevel@tonic-gate free(el->address); 21950Sstevel@tonic-gate if (el->status) 21960Sstevel@tonic-gate free(el->status); 21970Sstevel@tonic-gate if (el->piclclass) 21980Sstevel@tonic-gate free(el->piclclass); 21990Sstevel@tonic-gate if (el->props) 22000Sstevel@tonic-gate free(el->props); 22010Sstevel@tonic-gate free(el); 22020Sstevel@tonic-gate break; 22030Sstevel@tonic-gate } 22040Sstevel@tonic-gate el->next = NULL; 22050Sstevel@tonic-gate 22060Sstevel@tonic-gate /* 22070Sstevel@tonic-gate * Add it to the end of list 22080Sstevel@tonic-gate */ 22090Sstevel@tonic-gate if (list == NULL) 22100Sstevel@tonic-gate list = el; 22110Sstevel@tonic-gate else { 22120Sstevel@tonic-gate ptr = list; 22130Sstevel@tonic-gate while (ptr->next != NULL) 22140Sstevel@tonic-gate ptr = ptr->next; 22150Sstevel@tonic-gate ptr->next = el; 22160Sstevel@tonic-gate } 22170Sstevel@tonic-gate 22180Sstevel@tonic-gate } 22190Sstevel@tonic-gate (void) fclose(fp); 22200Sstevel@tonic-gate return (list); 22210Sstevel@tonic-gate } 22220Sstevel@tonic-gate 22230Sstevel@tonic-gate /* 22240Sstevel@tonic-gate * Process the asr conf file 22250Sstevel@tonic-gate */ 22260Sstevel@tonic-gate static void 22270Sstevel@tonic-gate process_asrtree_conf_file(void) 22280Sstevel@tonic-gate { 22290Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 22300Sstevel@tonic-gate char pname[PATH_MAX]; 22310Sstevel@tonic-gate 22320Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 22330Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 22340Sstevel@tonic-gate (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX); 22350Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, 22365028Sfw157321 conf_name_asr_map); 22370Sstevel@tonic-gate } 22380Sstevel@tonic-gate 22390Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 22400Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 22410Sstevel@tonic-gate (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX); 22420Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, 22435028Sfw157321 conf_name_asr_map); 22440Sstevel@tonic-gate } 22450Sstevel@tonic-gate 22460Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR, 22470Sstevel@tonic-gate ASRTREE_CONFFILE_NAME); 22480Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, conf_name_asr_map); 22490Sstevel@tonic-gate } 22500Sstevel@tonic-gate 22510Sstevel@tonic-gate /* 22520Sstevel@tonic-gate * This function reads the export file list from ASR 22530Sstevel@tonic-gate */ 22540Sstevel@tonic-gate static int 22550Sstevel@tonic-gate get_asr_export_list(char **exportlist, int *exportlistlen) 22560Sstevel@tonic-gate { 22570Sstevel@tonic-gate struct openpromio oppbuf; 22580Sstevel@tonic-gate struct openpromio *opp = &oppbuf; 22590Sstevel@tonic-gate int d; 22600Sstevel@tonic-gate int listsize; 22610Sstevel@tonic-gate 22620Sstevel@tonic-gate d = open("/dev/openprom", O_RDWR); 22630Sstevel@tonic-gate if (d < 0) 22640Sstevel@tonic-gate return (0); 22650Sstevel@tonic-gate 22660Sstevel@tonic-gate if (ioctl(d, OPROMEXPORTLEN, opp) == -1) { 22670Sstevel@tonic-gate (void) close(d); 22680Sstevel@tonic-gate return (0); 22690Sstevel@tonic-gate } 22700Sstevel@tonic-gate listsize = opp->oprom_size; 22710Sstevel@tonic-gate opp = (struct openpromio *)malloc(sizeof (struct openpromio) + 22720Sstevel@tonic-gate listsize); 22730Sstevel@tonic-gate if (opp == NULL) { 22740Sstevel@tonic-gate (void) close(d); 22750Sstevel@tonic-gate return (0); 22760Sstevel@tonic-gate } 22770Sstevel@tonic-gate (void) memset(opp, '\0', sizeof (struct openpromio) + listsize); 22780Sstevel@tonic-gate opp->oprom_size = listsize; 22790Sstevel@tonic-gate if (ioctl(d, OPROMEXPORT, opp) == -1) { 22800Sstevel@tonic-gate free(opp); 22810Sstevel@tonic-gate (void) close(d); 22820Sstevel@tonic-gate return (0); 22830Sstevel@tonic-gate } 22840Sstevel@tonic-gate *exportlist = malloc(listsize); 22850Sstevel@tonic-gate if (*exportlist == NULL) { 22860Sstevel@tonic-gate free(opp); 22870Sstevel@tonic-gate (void) close(d); 22880Sstevel@tonic-gate return (0); 22890Sstevel@tonic-gate } 22900Sstevel@tonic-gate (void) memcpy(*exportlist, opp->oprom_array, opp->oprom_size); 22910Sstevel@tonic-gate free(opp); 22920Sstevel@tonic-gate *exportlistlen = opp->oprom_size; 22930Sstevel@tonic-gate (void) close(d); 22940Sstevel@tonic-gate return (1); 22950Sstevel@tonic-gate } 22960Sstevel@tonic-gate 22970Sstevel@tonic-gate /* 22980Sstevel@tonic-gate * Parses properties string, fills in triplet structure with first 22990Sstevel@tonic-gate * type, name, val triplet and returns pointer to next property. 23000Sstevel@tonic-gate * Returns NULL if no valid triplet found 23010Sstevel@tonic-gate * CAUTION: drops \0 characters over separator characters: if you 23020Sstevel@tonic-gate * want to parse the string twice, you'll have to take a copy. 23030Sstevel@tonic-gate */ 23040Sstevel@tonic-gate static char * 23050Sstevel@tonic-gate parse_props_string(char *props, asr_prop_triplet_t *triplet) 23060Sstevel@tonic-gate { 23070Sstevel@tonic-gate char *prop_name; 23080Sstevel@tonic-gate char *prop_val; 23090Sstevel@tonic-gate char *prop_next; 23100Sstevel@tonic-gate 23110Sstevel@tonic-gate prop_name = strchr(props, '?'); 23120Sstevel@tonic-gate if (prop_name == NULL) 23130Sstevel@tonic-gate return (NULL); 23140Sstevel@tonic-gate *prop_name++ = '\0'; 23150Sstevel@tonic-gate prop_val = strchr(prop_name, '='); 23160Sstevel@tonic-gate if (prop_val == NULL) 23170Sstevel@tonic-gate return (NULL); 23180Sstevel@tonic-gate *prop_val++ = '\0'; 23190Sstevel@tonic-gate triplet->proptype = props; 23200Sstevel@tonic-gate triplet->propname = prop_name; 23210Sstevel@tonic-gate triplet->propval = prop_val; 23220Sstevel@tonic-gate prop_next = strchr(prop_val, ':'); 23230Sstevel@tonic-gate if (prop_next == NULL) 23240Sstevel@tonic-gate return (prop_val - 1); 23250Sstevel@tonic-gate *prop_next++ = '\0'; 23260Sstevel@tonic-gate return (prop_next); 23270Sstevel@tonic-gate } 23280Sstevel@tonic-gate 23290Sstevel@tonic-gate static int 23300Sstevel@tonic-gate add_status_prop(picl_nodehdl_t chdh, char *status) 23310Sstevel@tonic-gate { 23320Sstevel@tonic-gate ptree_propinfo_t propinfo; 23330Sstevel@tonic-gate picl_prophdl_t proph; 23340Sstevel@tonic-gate int err; 23350Sstevel@tonic-gate 23360Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 23370Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(status) + 1, 23380Sstevel@tonic-gate PICL_PROP_STATUS, NULL, NULL); 23390Sstevel@tonic-gate if (err != PICL_SUCCESS) 23400Sstevel@tonic-gate return (err); 23410Sstevel@tonic-gate err = ptree_create_and_add_prop(chdh, &propinfo, status, &proph); 23420Sstevel@tonic-gate return (err); 23430Sstevel@tonic-gate } 23440Sstevel@tonic-gate 23450Sstevel@tonic-gate static void 23460Sstevel@tonic-gate create_asr_node(char *parent, char *child, char *unitaddr, char *class, 23470Sstevel@tonic-gate char *status, char *props) 23480Sstevel@tonic-gate { 23490Sstevel@tonic-gate char ptreepath[PATH_MAX]; 23500Sstevel@tonic-gate char nodename[PICL_PROPNAMELEN_MAX]; 23510Sstevel@tonic-gate char ua[MAX_UNIT_ADDRESS_LEN]; 23520Sstevel@tonic-gate char *props_copy = NULL; 23530Sstevel@tonic-gate char *next; 23540Sstevel@tonic-gate char *prop_string; 23550Sstevel@tonic-gate boolean_t found = B_FALSE; 23560Sstevel@tonic-gate picl_nodehdl_t nodeh; 23570Sstevel@tonic-gate picl_nodehdl_t chdh; 23580Sstevel@tonic-gate asr_prop_triplet_t triple; 23590Sstevel@tonic-gate ptree_propinfo_t propinfo; 23600Sstevel@tonic-gate picl_prophdl_t proph; 23610Sstevel@tonic-gate int val; 23620Sstevel@tonic-gate int err; 23630Sstevel@tonic-gate 23640Sstevel@tonic-gate (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX); 23650Sstevel@tonic-gate (void) strlcat(ptreepath, parent, PATH_MAX); 23660Sstevel@tonic-gate 23670Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS) 23680Sstevel@tonic-gate return; 23690Sstevel@tonic-gate /* 23700Sstevel@tonic-gate * see if the required child node already exists 23710Sstevel@tonic-gate */ 23720Sstevel@tonic-gate for (err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 23730Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 23740Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 23755028Sfw157321 sizeof (picl_nodehdl_t))) { 23760Sstevel@tonic-gate if (err != PICL_SUCCESS) 23770Sstevel@tonic-gate break; 23780Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_NAME, 23790Sstevel@tonic-gate (void *)nodename, PICL_PROPNAMELEN_MAX); 23800Sstevel@tonic-gate if (err != PICL_SUCCESS) 23810Sstevel@tonic-gate break; 23820Sstevel@tonic-gate if (strcmp(nodename, child) != 0) 23830Sstevel@tonic-gate continue; 23840Sstevel@tonic-gate /* 23850Sstevel@tonic-gate * found a candidate child node 23860Sstevel@tonic-gate */ 23870Sstevel@tonic-gate if (unitaddr) { 23880Sstevel@tonic-gate /* 23890Sstevel@tonic-gate * does it match the required unit address? 23900Sstevel@tonic-gate */ 23910Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 23920Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, ua, sizeof (ua)); 23930Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 23940Sstevel@tonic-gate continue; 23950Sstevel@tonic-gate if (err != PICL_SUCCESS) 23960Sstevel@tonic-gate break; 23970Sstevel@tonic-gate if (strcmp(unitaddr, ua) != 0) 23980Sstevel@tonic-gate continue; 23990Sstevel@tonic-gate } 24000Sstevel@tonic-gate if (props == NULL) { 24010Sstevel@tonic-gate next = ""; 24020Sstevel@tonic-gate } else if (props_copy == NULL) { 24030Sstevel@tonic-gate props_copy = strdup(props); 24040Sstevel@tonic-gate if (props_copy == NULL) 24050Sstevel@tonic-gate return; 24060Sstevel@tonic-gate next = props_copy; 24070Sstevel@tonic-gate } 24080Sstevel@tonic-gate while ((next = parse_props_string(next, &triple)) != NULL) { 24090Sstevel@tonic-gate err = ptree_get_prop_by_name(chdh, triple.propname, 24100Sstevel@tonic-gate &proph); 24110Sstevel@tonic-gate if (err != PICL_SUCCESS) 24120Sstevel@tonic-gate break; 24130Sstevel@tonic-gate err = ptree_get_propinfo(proph, &propinfo); 24140Sstevel@tonic-gate if (err != PICL_SUCCESS) 24150Sstevel@tonic-gate break; 24160Sstevel@tonic-gate err = PICL_FAILURE; 24170Sstevel@tonic-gate switch (propinfo.piclinfo.type) { 24180Sstevel@tonic-gate case PICL_PTYPE_INT: 24190Sstevel@tonic-gate case PICL_PTYPE_UNSIGNED_INT: 24200Sstevel@tonic-gate if (strcmp(triple.proptype, "I") != 0) 24210Sstevel@tonic-gate break; 24220Sstevel@tonic-gate err = ptree_get_propval(proph, (void *)&val, 24230Sstevel@tonic-gate sizeof (val)); 24240Sstevel@tonic-gate if (err != PICL_SUCCESS) 24250Sstevel@tonic-gate break; 24260Sstevel@tonic-gate if (val != atoi(triple.propval)) 24270Sstevel@tonic-gate err = PICL_FAILURE; 24280Sstevel@tonic-gate break; 24290Sstevel@tonic-gate case PICL_PTYPE_CHARSTRING: 24300Sstevel@tonic-gate if (strcmp(triple.proptype, "S") != 0) 24310Sstevel@tonic-gate break; 24320Sstevel@tonic-gate prop_string = malloc(propinfo.piclinfo.size); 24330Sstevel@tonic-gate if (prop_string == NULL) 24340Sstevel@tonic-gate break; 24350Sstevel@tonic-gate err = ptree_get_propval(proph, 24360Sstevel@tonic-gate (void *)prop_string, 24370Sstevel@tonic-gate propinfo.piclinfo.size); 24380Sstevel@tonic-gate if (err != PICL_SUCCESS) { 24390Sstevel@tonic-gate free(prop_string); 24400Sstevel@tonic-gate break; 24410Sstevel@tonic-gate } 24420Sstevel@tonic-gate if (strcmp(prop_string, triple.propval) != 0) 24430Sstevel@tonic-gate err = PICL_FAILURE; 24440Sstevel@tonic-gate free(prop_string); 24450Sstevel@tonic-gate break; 24460Sstevel@tonic-gate default: 24470Sstevel@tonic-gate break; 24480Sstevel@tonic-gate } 24490Sstevel@tonic-gate if (err != PICL_SUCCESS) { 24500Sstevel@tonic-gate break; 24510Sstevel@tonic-gate } 24520Sstevel@tonic-gate } 24530Sstevel@tonic-gate if (next == NULL) { 24540Sstevel@tonic-gate found = B_TRUE; 24550Sstevel@tonic-gate break; 24560Sstevel@tonic-gate } 24570Sstevel@tonic-gate } 24580Sstevel@tonic-gate if (props_copy) 24590Sstevel@tonic-gate free(props_copy); 24600Sstevel@tonic-gate if (found) { 24610Sstevel@tonic-gate /* 24620Sstevel@tonic-gate * does the pre-existing node have a status property? 24630Sstevel@tonic-gate */ 24640Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_STATUS, 24650Sstevel@tonic-gate ua, sizeof (ua)); 24660Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 24670Sstevel@tonic-gate (void) add_status_prop(chdh, status); 24680Sstevel@tonic-gate if (err != PICL_SUCCESS) 24690Sstevel@tonic-gate return; 24700Sstevel@tonic-gate if ((strcmp(ua, ASR_DISABLED) == 0) || 24710Sstevel@tonic-gate (strcmp(ua, ASR_FAILED) == 0) || 24720Sstevel@tonic-gate ((strcmp(status, ASR_DISABLED) != 0) && 24730Sstevel@tonic-gate (strcmp(status, ASR_FAILED) != 0))) { 24740Sstevel@tonic-gate return; 24750Sstevel@tonic-gate } 24760Sstevel@tonic-gate /* 24770Sstevel@tonic-gate * more urgent status now, so replace existing value 24780Sstevel@tonic-gate */ 24790Sstevel@tonic-gate err = ptree_get_prop_by_name(chdh, PICL_PROP_STATUS, &proph); 24800Sstevel@tonic-gate if (err != PICL_SUCCESS) 24810Sstevel@tonic-gate return; 24820Sstevel@tonic-gate (void) ptree_delete_prop(proph); 24830Sstevel@tonic-gate (void) ptree_destroy_prop(proph); 24840Sstevel@tonic-gate err = add_status_prop(chdh, status); 24850Sstevel@tonic-gate if (err != PICL_SUCCESS) 24860Sstevel@tonic-gate return; 24870Sstevel@tonic-gate return; 24880Sstevel@tonic-gate } 24890Sstevel@tonic-gate 24900Sstevel@tonic-gate /* 24910Sstevel@tonic-gate * typical case, node needs adding together with a set of properties 24920Sstevel@tonic-gate */ 24930Sstevel@tonic-gate if (ptree_create_and_add_node(nodeh, child, class, &chdh) == 24940Sstevel@tonic-gate PICL_SUCCESS) { 24950Sstevel@tonic-gate (void) add_status_prop(chdh, status); 24960Sstevel@tonic-gate if (unitaddr) { 24970Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 24980Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, 24990Sstevel@tonic-gate PICL_READ, strlen(unitaddr) + 1, 25000Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL); 25010Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, &propinfo, 25020Sstevel@tonic-gate unitaddr, &proph); 25030Sstevel@tonic-gate (void) strlcpy(ptreepath, parent, PATH_MAX); 25040Sstevel@tonic-gate (void) strlcat(ptreepath, "/", PATH_MAX); 25050Sstevel@tonic-gate (void) strlcat(ptreepath, child, PATH_MAX); 25060Sstevel@tonic-gate (void) strlcat(ptreepath, "@", PATH_MAX); 25070Sstevel@tonic-gate (void) strlcat(ptreepath, unitaddr, PATH_MAX); 25080Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 25090Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, 25100Sstevel@tonic-gate PICL_READ, strlen(ptreepath) + 1, 25110Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, NULL, NULL); 25120Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, &propinfo, 25130Sstevel@tonic-gate ptreepath, &proph); 25140Sstevel@tonic-gate } 25150Sstevel@tonic-gate next = props; 25160Sstevel@tonic-gate while ((next = parse_props_string(next, &triple)) != NULL) { 25170Sstevel@tonic-gate /* 25180Sstevel@tonic-gate * only handle int and string properties for 25190Sstevel@tonic-gate * simplicity 25200Sstevel@tonic-gate */ 25210Sstevel@tonic-gate if (strcmp(triple.proptype, "I") == 0) { 25220Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 25230Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 25240Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, 25250Sstevel@tonic-gate sizeof (int), triple.propname, NULL, NULL); 25260Sstevel@tonic-gate val = atoi(triple.propval); 25270Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, 25280Sstevel@tonic-gate &propinfo, &val, &proph); 25290Sstevel@tonic-gate } else { 25300Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 25310Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 25320Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 25330Sstevel@tonic-gate strlen(triple.propval) + 1, 25345028Sfw157321 triple.propname, NULL, NULL); 25350Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, 25360Sstevel@tonic-gate &propinfo, triple.propval, &proph); 25370Sstevel@tonic-gate } 25380Sstevel@tonic-gate } 25390Sstevel@tonic-gate } 25400Sstevel@tonic-gate } 25410Sstevel@tonic-gate 25420Sstevel@tonic-gate static void 25430Sstevel@tonic-gate add_asr_nodes() 25440Sstevel@tonic-gate { 25450Sstevel@tonic-gate char *asrexport; 25460Sstevel@tonic-gate int asrexportlen; 25470Sstevel@tonic-gate asr_conf_entries_t *c = NULL; 25480Sstevel@tonic-gate int i; 25490Sstevel@tonic-gate char *key; 25500Sstevel@tonic-gate char *child; 25510Sstevel@tonic-gate char *unitaddr; 25520Sstevel@tonic-gate uint16_t count; 25530Sstevel@tonic-gate int disabled; 25540Sstevel@tonic-gate 25550Sstevel@tonic-gate if (get_asr_export_list(&asrexport, &asrexportlen) == 0) 25560Sstevel@tonic-gate return; 25570Sstevel@tonic-gate process_asrtree_conf_file(); 25580Sstevel@tonic-gate if (conf_name_asr_map == NULL) 25590Sstevel@tonic-gate return; 25600Sstevel@tonic-gate i = 0; 25610Sstevel@tonic-gate while (i < asrexportlen) { 25620Sstevel@tonic-gate key = &asrexport[i]; 25630Sstevel@tonic-gate i += strlen(key) + 1; 25640Sstevel@tonic-gate if (i >= asrexportlen) 25650Sstevel@tonic-gate break; 25660Sstevel@tonic-gate 25670Sstevel@tonic-gate /* 25680Sstevel@tonic-gate * next byte tells us whether failed by diags or manually 25690Sstevel@tonic-gate * disabled 25700Sstevel@tonic-gate */ 25710Sstevel@tonic-gate disabled = asrexport[i]; 25720Sstevel@tonic-gate i++; 25730Sstevel@tonic-gate if (i >= asrexportlen) 25740Sstevel@tonic-gate break; 25750Sstevel@tonic-gate 25760Sstevel@tonic-gate /* 25770Sstevel@tonic-gate * only type 1 supported 25780Sstevel@tonic-gate */ 25790Sstevel@tonic-gate if (asrexport[i] != 1) 25800Sstevel@tonic-gate break; 25810Sstevel@tonic-gate i++; 25820Sstevel@tonic-gate if (i >= asrexportlen) 25830Sstevel@tonic-gate break; 25840Sstevel@tonic-gate 25850Sstevel@tonic-gate /* 25860Sstevel@tonic-gate * next two bytes give size of reason string 25870Sstevel@tonic-gate */ 25880Sstevel@tonic-gate count = (asrexport[i] << 8) | asrexport[i + 1]; 25890Sstevel@tonic-gate i += count + 2; 25900Sstevel@tonic-gate if (i > asrexportlen) 25910Sstevel@tonic-gate break; 25920Sstevel@tonic-gate 25930Sstevel@tonic-gate /* 25940Sstevel@tonic-gate * now look for key in conf file info 25950Sstevel@tonic-gate */ 25960Sstevel@tonic-gate c = conf_name_asr_map; 25970Sstevel@tonic-gate while (c != NULL) { 25980Sstevel@tonic-gate if (strcmp(key, c->name) == 0) { 25990Sstevel@tonic-gate child = strrchr(c->address, '/'); 26000Sstevel@tonic-gate *child++ = '\0'; 26010Sstevel@tonic-gate unitaddr = strchr(child, '@'); 26020Sstevel@tonic-gate if (unitaddr) 26030Sstevel@tonic-gate *unitaddr++ = '\0'; 26040Sstevel@tonic-gate if (strcmp(c->status, ASR_DISABLED) == 0) { 26050Sstevel@tonic-gate create_asr_node(c->address, child, 26060Sstevel@tonic-gate unitaddr, c->piclclass, disabled ? 26070Sstevel@tonic-gate ASR_DISABLED : ASR_FAILED, 26080Sstevel@tonic-gate c->props); 26090Sstevel@tonic-gate } else { 26100Sstevel@tonic-gate create_asr_node(c->address, child, 26110Sstevel@tonic-gate unitaddr, c->piclclass, c->status, 26120Sstevel@tonic-gate c->props); 26130Sstevel@tonic-gate } 26140Sstevel@tonic-gate } 26150Sstevel@tonic-gate c = c->next; 26160Sstevel@tonic-gate } 26170Sstevel@tonic-gate } 26180Sstevel@tonic-gate 26190Sstevel@tonic-gate free_asr_conf_entries(conf_name_asr_map); 26200Sstevel@tonic-gate free(asrexport); 26210Sstevel@tonic-gate } 26220Sstevel@tonic-gate 26230Sstevel@tonic-gate /* 26240Sstevel@tonic-gate * This function adds information to the /platform node 26250Sstevel@tonic-gate */ 26260Sstevel@tonic-gate static int 26270Sstevel@tonic-gate add_platform_info(picl_nodehdl_t plafh) 26280Sstevel@tonic-gate { 26290Sstevel@tonic-gate struct utsname uts_info; 26300Sstevel@tonic-gate int err; 26310Sstevel@tonic-gate ptree_propinfo_t propinfo; 26320Sstevel@tonic-gate picl_prophdl_t proph; 26330Sstevel@tonic-gate 26340Sstevel@tonic-gate if (uname(&uts_info) < 0) 26350Sstevel@tonic-gate return (PICL_FAILURE); 26360Sstevel@tonic-gate 26370Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 26380Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.sysname) + 1, 26390Sstevel@tonic-gate PICL_PROP_SYSNAME, NULL, NULL); 26400Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.sysname, 26410Sstevel@tonic-gate &proph); 26420Sstevel@tonic-gate if (err != PICL_SUCCESS) 26430Sstevel@tonic-gate return (err); 26440Sstevel@tonic-gate 26450Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 26460Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.nodename) + 1, 26470Sstevel@tonic-gate PICL_PROP_NODENAME, NULL, NULL); 26480Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.nodename, 26490Sstevel@tonic-gate &proph); 26500Sstevel@tonic-gate if (err != PICL_SUCCESS) 26510Sstevel@tonic-gate return (err); 26520Sstevel@tonic-gate 26530Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 26540Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.release) + 1, 26550Sstevel@tonic-gate PICL_PROP_RELEASE, NULL, NULL); 26560Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.release, 26570Sstevel@tonic-gate &proph); 26580Sstevel@tonic-gate if (err != PICL_SUCCESS) 26590Sstevel@tonic-gate return (err); 26600Sstevel@tonic-gate 26610Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 26620Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.version) + 1, 26630Sstevel@tonic-gate PICL_PROP_VERSION, NULL, NULL); 26640Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.version, 26650Sstevel@tonic-gate &proph); 26660Sstevel@tonic-gate if (err != PICL_SUCCESS) 26670Sstevel@tonic-gate return (err); 26680Sstevel@tonic-gate 26690Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 26700Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.machine) + 1, 26710Sstevel@tonic-gate PICL_PROP_MACHINE, NULL, NULL); 26720Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.machine, 26730Sstevel@tonic-gate &proph); 26740Sstevel@tonic-gate return (err); 26750Sstevel@tonic-gate } 26760Sstevel@tonic-gate 26770Sstevel@tonic-gate /* 26780Sstevel@tonic-gate * Get first 32-bit value from the reg property 26790Sstevel@tonic-gate */ 26800Sstevel@tonic-gate static int 26810Sstevel@tonic-gate get_first_reg_word(picl_nodehdl_t nodeh, uint32_t *regval) 26820Sstevel@tonic-gate { 26830Sstevel@tonic-gate int err; 26840Sstevel@tonic-gate uint32_t *regbuf; 26850Sstevel@tonic-gate picl_prophdl_t regh; 26860Sstevel@tonic-gate ptree_propinfo_t pinfo; 26870Sstevel@tonic-gate 26880Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 26890Sstevel@tonic-gate if (err != PICL_SUCCESS) /* no reg property */ 26900Sstevel@tonic-gate return (err); 26910Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 26920Sstevel@tonic-gate if (err != PICL_SUCCESS) 26930Sstevel@tonic-gate return (err); 26940Sstevel@tonic-gate if (pinfo.piclinfo.size < sizeof (uint32_t)) /* too small */ 26950Sstevel@tonic-gate return (PICL_FAILURE); 26960Sstevel@tonic-gate regbuf = alloca(pinfo.piclinfo.size); 26970Sstevel@tonic-gate if (regbuf == NULL) 26980Sstevel@tonic-gate return (PICL_FAILURE); 26990Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, pinfo.piclinfo.size); 27000Sstevel@tonic-gate if (err != PICL_SUCCESS) 27010Sstevel@tonic-gate return (err); 27020Sstevel@tonic-gate *regval = *regbuf; /* get first 32-bit value */ 27030Sstevel@tonic-gate return (PICL_SUCCESS); 27040Sstevel@tonic-gate } 27050Sstevel@tonic-gate 27060Sstevel@tonic-gate /* 27070Sstevel@tonic-gate * Get device ID from the reg property 27080Sstevel@tonic-gate */ 27090Sstevel@tonic-gate static int 27100Sstevel@tonic-gate get_device_id(picl_nodehdl_t nodeh, uint32_t *dev_id) 27110Sstevel@tonic-gate { 27120Sstevel@tonic-gate int err; 27130Sstevel@tonic-gate uint32_t regval; 27140Sstevel@tonic-gate 27150Sstevel@tonic-gate err = get_first_reg_word(nodeh, ®val); 27160Sstevel@tonic-gate if (err != PICL_SUCCESS) 27170Sstevel@tonic-gate return (err); 27180Sstevel@tonic-gate 27190Sstevel@tonic-gate *dev_id = PCI_DEVICE_ID(regval); 27200Sstevel@tonic-gate return (PICL_SUCCESS); 27210Sstevel@tonic-gate } 27220Sstevel@tonic-gate 27230Sstevel@tonic-gate /* 27240Sstevel@tonic-gate * add Slot property for children of SBUS node 27250Sstevel@tonic-gate */ 27260Sstevel@tonic-gate /* ARGSUSED */ 27270Sstevel@tonic-gate static int 27280Sstevel@tonic-gate add_sbus_slots(picl_nodehdl_t pcih, void *args) 27290Sstevel@tonic-gate { 27300Sstevel@tonic-gate picl_nodehdl_t nodeh; 27310Sstevel@tonic-gate uint32_t slot; 27320Sstevel@tonic-gate int err; 27330Sstevel@tonic-gate ptree_propinfo_t pinfo; 27340Sstevel@tonic-gate 27350Sstevel@tonic-gate for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 27360Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 27375028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 27385028Sfw157321 sizeof (picl_nodehdl_t))) { 27390Sstevel@tonic-gate if (err != PICL_SUCCESS) 27400Sstevel@tonic-gate return (err); 27410Sstevel@tonic-gate 27420Sstevel@tonic-gate if (get_first_reg_word(nodeh, &slot) != 0) 27430Sstevel@tonic-gate continue; 27440Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 27450Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t), 27460Sstevel@tonic-gate PICL_PROP_SLOT, NULL, NULL); 27470Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, &slot, NULL); 27480Sstevel@tonic-gate } 27490Sstevel@tonic-gate 27500Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 27510Sstevel@tonic-gate } 27520Sstevel@tonic-gate 27530Sstevel@tonic-gate /* 27540Sstevel@tonic-gate * This function creates a Slot property for SBUS child nodes 27550Sstevel@tonic-gate * which can be correlated with the slot they are plugged into 27560Sstevel@tonic-gate * on the motherboard. 27570Sstevel@tonic-gate */ 27580Sstevel@tonic-gate static int 27590Sstevel@tonic-gate set_sbus_slot(picl_nodehdl_t plafh) 27600Sstevel@tonic-gate { 27610Sstevel@tonic-gate int err; 27620Sstevel@tonic-gate 27630Sstevel@tonic-gate err = ptree_walk_tree_by_class(plafh, PICL_CLASS_SBUS, NULL, 27640Sstevel@tonic-gate add_sbus_slots); 27650Sstevel@tonic-gate 27660Sstevel@tonic-gate return (err); 27670Sstevel@tonic-gate } 27680Sstevel@tonic-gate 27690Sstevel@tonic-gate /* 2770944Svenki * add DeviceID property for children of PCI/PCIEX node 27710Sstevel@tonic-gate */ 27720Sstevel@tonic-gate /* ARGSUSED */ 27730Sstevel@tonic-gate static int 27740Sstevel@tonic-gate add_pci_deviceids(picl_nodehdl_t pcih, void *args) 27750Sstevel@tonic-gate { 27760Sstevel@tonic-gate picl_nodehdl_t nodeh; 27770Sstevel@tonic-gate uint32_t dev_id; 27780Sstevel@tonic-gate int err; 27790Sstevel@tonic-gate ptree_propinfo_t pinfo; 27800Sstevel@tonic-gate 27810Sstevel@tonic-gate for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 27820Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 27835028Sfw157321 err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 27845028Sfw157321 sizeof (picl_nodehdl_t))) { 27850Sstevel@tonic-gate if (err != PICL_SUCCESS) 27860Sstevel@tonic-gate return (err); 27870Sstevel@tonic-gate 27880Sstevel@tonic-gate if (get_device_id(nodeh, &dev_id) != 0) 27890Sstevel@tonic-gate continue; 27900Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 27910Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t), 27920Sstevel@tonic-gate PICL_PROP_DEVICE_ID, NULL, NULL); 27930Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, &dev_id, NULL); 27940Sstevel@tonic-gate } 27950Sstevel@tonic-gate 27960Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 27970Sstevel@tonic-gate } 27980Sstevel@tonic-gate 27990Sstevel@tonic-gate /* 2800944Svenki * This function creates a DeviceID property for PCI/PCIEX child nodes 28010Sstevel@tonic-gate * which can be correlated with the slot they are plugged into 28020Sstevel@tonic-gate * on the motherboard. 28030Sstevel@tonic-gate */ 2804944Svenki static void 2805944Svenki set_pci_pciex_deviceid(picl_nodehdl_t plafh) 28060Sstevel@tonic-gate { 2807944Svenki (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCI, NULL, 28080Sstevel@tonic-gate add_pci_deviceids); 28090Sstevel@tonic-gate 2810944Svenki (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, NULL, 2811944Svenki add_pci_deviceids); 28120Sstevel@tonic-gate } 28130Sstevel@tonic-gate 28140Sstevel@tonic-gate /* 28150Sstevel@tonic-gate * Default UnitAddress encode function 28160Sstevel@tonic-gate */ 28170Sstevel@tonic-gate static int 28180Sstevel@tonic-gate encode_default_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 28190Sstevel@tonic-gate { 28200Sstevel@tonic-gate int i, len; 28210Sstevel@tonic-gate 28220Sstevel@tonic-gate /* 28230Sstevel@tonic-gate * Encode UnitAddress as %a,%b,%c,...,%n 28240Sstevel@tonic-gate */ 28250Sstevel@tonic-gate if (addrcells < 1) 28260Sstevel@tonic-gate return (-1); 28270Sstevel@tonic-gate 28280Sstevel@tonic-gate len = snprintf(buf, sz, "%x", *regprop); 28290Sstevel@tonic-gate for (i = 1; i < addrcells && len < sz; i++) 28300Sstevel@tonic-gate len += snprintf(&buf[len], sz-len, ",%x", regprop[i]); 28310Sstevel@tonic-gate 28320Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 28330Sstevel@tonic-gate } 28340Sstevel@tonic-gate 28350Sstevel@tonic-gate /* 28360Sstevel@tonic-gate * UnitAddress encode function where the last component is not printed 28370Sstevel@tonic-gate * unless non-zero. 28380Sstevel@tonic-gate */ 28390Sstevel@tonic-gate static int 28400Sstevel@tonic-gate encode_optional_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 28410Sstevel@tonic-gate { 28420Sstevel@tonic-gate int retval; 28430Sstevel@tonic-gate 28440Sstevel@tonic-gate /* 28450Sstevel@tonic-gate * Encode UnitAddress as %a,%b,%c,...,%n where the last component 28460Sstevel@tonic-gate * is printed only if non-zero. 28470Sstevel@tonic-gate */ 28480Sstevel@tonic-gate if (addrcells > 1 && regprop[addrcells-1] == 0) 28490Sstevel@tonic-gate retval = encode_default_unitaddr(buf, sz, regprop, addrcells-1); 28500Sstevel@tonic-gate else 28510Sstevel@tonic-gate retval = encode_default_unitaddr(buf, sz, regprop, addrcells); 28520Sstevel@tonic-gate 28530Sstevel@tonic-gate return (retval); 28540Sstevel@tonic-gate } 28550Sstevel@tonic-gate 28560Sstevel@tonic-gate 28570Sstevel@tonic-gate /* 28580Sstevel@tonic-gate * UnitAddress encode function for SCSI class of devices 28590Sstevel@tonic-gate */ 28600Sstevel@tonic-gate static int 28610Sstevel@tonic-gate encode_scsi_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 28620Sstevel@tonic-gate { 28630Sstevel@tonic-gate int len, retval; 28640Sstevel@tonic-gate 28650Sstevel@tonic-gate /* 28660Sstevel@tonic-gate * #address-cells Format 28670Sstevel@tonic-gate * 2 second component printed only if non-zero 28680Sstevel@tonic-gate * 28690Sstevel@tonic-gate * 4 regprop: phys_hi phys_lo lun_hi lun_lo 28700Sstevel@tonic-gate * UnitAddr: w<phys_hi><phys_lo>,<lun_lo> 28710Sstevel@tonic-gate */ 28720Sstevel@tonic-gate 28730Sstevel@tonic-gate if (addrcells == 2) { 28740Sstevel@tonic-gate retval = encode_optional_unitaddr(buf, sz, regprop, addrcells); 28750Sstevel@tonic-gate } else if (addrcells == 4) { 28760Sstevel@tonic-gate len = snprintf(buf, sz, "w%08x%08x,%x", regprop[0], regprop[1], 28770Sstevel@tonic-gate regprop[3]); 28780Sstevel@tonic-gate retval = (len >= sz) ? -1 : 0; 28790Sstevel@tonic-gate } else 28800Sstevel@tonic-gate retval = -1; 28810Sstevel@tonic-gate 28820Sstevel@tonic-gate return (retval); 28830Sstevel@tonic-gate } 28840Sstevel@tonic-gate 28850Sstevel@tonic-gate /* 28860Sstevel@tonic-gate * UnitAddress encode function for UPA devices 28870Sstevel@tonic-gate */ 28880Sstevel@tonic-gate static int 28890Sstevel@tonic-gate encode_upa_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 28900Sstevel@tonic-gate { 28910Sstevel@tonic-gate int len; 28920Sstevel@tonic-gate 28930Sstevel@tonic-gate if (addrcells != 2) 28940Sstevel@tonic-gate return (-1); 28950Sstevel@tonic-gate 28960Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", (regprop[0]/2)&0x1f, regprop[1]); 28970Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 28980Sstevel@tonic-gate } 28990Sstevel@tonic-gate 29000Sstevel@tonic-gate /* 29010Sstevel@tonic-gate * UnitAddress encode function for GPTWO, JBUS devices 29020Sstevel@tonic-gate */ 29030Sstevel@tonic-gate static int 29040Sstevel@tonic-gate encode_gptwo_jbus_unitaddr(char *buf, int sz, uint32_t *regprop, 29050Sstevel@tonic-gate uint_t addrcells) 29060Sstevel@tonic-gate { 29070Sstevel@tonic-gate uint32_t hi, lo; 29080Sstevel@tonic-gate int len, id, off; 29090Sstevel@tonic-gate 29100Sstevel@tonic-gate if (addrcells != 2) 29110Sstevel@tonic-gate return (-1); 29120Sstevel@tonic-gate 29130Sstevel@tonic-gate hi = regprop[0]; 29140Sstevel@tonic-gate lo = regprop[1]; 29150Sstevel@tonic-gate 29160Sstevel@tonic-gate if (hi & 0x400) { 29170Sstevel@tonic-gate id = ((hi & 0x1) << 9) | (lo >> 23); /* agent id */ 29180Sstevel@tonic-gate off = lo & 0x7fffff; /* config offset */ 29190Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", id, off); 29200Sstevel@tonic-gate } else { 29210Sstevel@tonic-gate len = snprintf(buf, sz, "m%x,%x", hi, lo); 29220Sstevel@tonic-gate } 29230Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 29240Sstevel@tonic-gate } 29250Sstevel@tonic-gate 29260Sstevel@tonic-gate /* 29270Sstevel@tonic-gate * UnitAddress encode function for PCI devices 29280Sstevel@tonic-gate */ 29290Sstevel@tonic-gate static int 29300Sstevel@tonic-gate encode_pci_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 29310Sstevel@tonic-gate { 29320Sstevel@tonic-gate typedef struct { 29330Sstevel@tonic-gate uint32_t n:1, /* relocatable */ 29340Sstevel@tonic-gate p:1, /* prefetchable */ 29350Sstevel@tonic-gate t:1, /* address region aliases */ 29360Sstevel@tonic-gate zero:3, /* must be zero */ 29370Sstevel@tonic-gate ss:2, /* address space type */ 29380Sstevel@tonic-gate bus:8, /* bus number */ 29390Sstevel@tonic-gate dev:5, /* device number */ 29400Sstevel@tonic-gate fn:3, /* function number */ 29410Sstevel@tonic-gate reg:8; /* register number */ 29420Sstevel@tonic-gate uint32_t phys_hi; /* high physical address */ 29430Sstevel@tonic-gate uint32_t phys_lo; /* low physical address */ 29440Sstevel@tonic-gate } pci_addrcell_t; 29450Sstevel@tonic-gate 29460Sstevel@tonic-gate pci_addrcell_t *p; 29470Sstevel@tonic-gate int len; 29480Sstevel@tonic-gate 29490Sstevel@tonic-gate if (addrcells != 3) 29500Sstevel@tonic-gate return (-1); 29510Sstevel@tonic-gate 29520Sstevel@tonic-gate p = (pci_addrcell_t *)regprop; 29530Sstevel@tonic-gate switch (p->ss) { 29540Sstevel@tonic-gate case 0: /* Config */ 29550Sstevel@tonic-gate if (p->fn) 29560Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", p->dev, p->fn); 29570Sstevel@tonic-gate else 29580Sstevel@tonic-gate len = snprintf(buf, sz, "%x", p->dev); 29590Sstevel@tonic-gate break; 29600Sstevel@tonic-gate case 1: /* IO */ 29610Sstevel@tonic-gate len = snprintf(buf, sz, "i%x,%x,%x,%x", p->dev, p->fn, p->reg, 29620Sstevel@tonic-gate p->phys_lo); 29630Sstevel@tonic-gate break; 29640Sstevel@tonic-gate case 2: /* Mem32 */ 29650Sstevel@tonic-gate len = snprintf(buf, sz, "m%x,%x,%x,%x", p->dev, p->fn, p->reg, 29660Sstevel@tonic-gate p->phys_lo); 29670Sstevel@tonic-gate break; 29680Sstevel@tonic-gate case 3: /* Mem64 */ 29690Sstevel@tonic-gate len = snprintf(buf, sz, "x%x,%x,%x,%x%08x", p->dev, p->fn, 29700Sstevel@tonic-gate p->reg, p->phys_hi, p->phys_lo); 29710Sstevel@tonic-gate break; 29720Sstevel@tonic-gate } 29730Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 29740Sstevel@tonic-gate } 29750Sstevel@tonic-gate 29760Sstevel@tonic-gate /* 29770Sstevel@tonic-gate * Get #address-cells property value 29780Sstevel@tonic-gate */ 29790Sstevel@tonic-gate static uint_t 29800Sstevel@tonic-gate get_addrcells_prop(picl_nodehdl_t nodeh) 29810Sstevel@tonic-gate { 29820Sstevel@tonic-gate int len, err; 29830Sstevel@tonic-gate uint32_t addrcells; 29840Sstevel@tonic-gate ptree_propinfo_t pinfo; 29850Sstevel@tonic-gate picl_prophdl_t proph; 29860Sstevel@tonic-gate 29870Sstevel@tonic-gate /* 29880Sstevel@tonic-gate * Get #address-cells property. If not present, use default value. 29890Sstevel@tonic-gate */ 29900Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_PROP_ADDRESS_CELLS, &proph); 29910Sstevel@tonic-gate if (err == PICL_SUCCESS) 29920Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 29930Sstevel@tonic-gate 29940Sstevel@tonic-gate len = pinfo.piclinfo.size; 29950Sstevel@tonic-gate if (err == PICL_SUCCESS && len >= sizeof (uint8_t) && 29960Sstevel@tonic-gate len <= sizeof (addrcells)) { 29970Sstevel@tonic-gate err = ptree_get_propval(proph, &addrcells, len); 29980Sstevel@tonic-gate if (err == PICL_SUCCESS) { 29990Sstevel@tonic-gate if (len == sizeof (uint8_t)) 30000Sstevel@tonic-gate addrcells = *(uint8_t *)&addrcells; 30010Sstevel@tonic-gate else if (len == sizeof (uint16_t)) 30020Sstevel@tonic-gate addrcells = *(uint16_t *)&addrcells; 30030Sstevel@tonic-gate } else 30040Sstevel@tonic-gate addrcells = DEFAULT_ADDRESS_CELLS; 30050Sstevel@tonic-gate } else 30060Sstevel@tonic-gate addrcells = DEFAULT_ADDRESS_CELLS; 30070Sstevel@tonic-gate 30080Sstevel@tonic-gate return (addrcells); 30090Sstevel@tonic-gate } 30100Sstevel@tonic-gate 30110Sstevel@tonic-gate /* 30120Sstevel@tonic-gate * Get UnitAddress mapping entry for a node 30130Sstevel@tonic-gate */ 30140Sstevel@tonic-gate static unitaddr_map_t * 30150Sstevel@tonic-gate get_unitaddr_mapping(picl_nodehdl_t nodeh) 30160Sstevel@tonic-gate { 30170Sstevel@tonic-gate int err; 30180Sstevel@tonic-gate unitaddr_map_t *uamap; 30190Sstevel@tonic-gate char clname[PICL_CLASSNAMELEN_MAX]; 30200Sstevel@tonic-gate 30210Sstevel@tonic-gate /* 30220Sstevel@tonic-gate * Get my classname and locate a function to translate "reg" prop 30230Sstevel@tonic-gate * into "UnitAddress" prop for my children. 30240Sstevel@tonic-gate */ 30250Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, clname, 30260Sstevel@tonic-gate sizeof (clname)); 30270Sstevel@tonic-gate if (err != PICL_SUCCESS) 30280Sstevel@tonic-gate (void) strcpy(clname, ""); /* NULL class name */ 30290Sstevel@tonic-gate 30300Sstevel@tonic-gate for (uamap = &unitaddr_map_table[0]; uamap->class != NULL; uamap++) 30310Sstevel@tonic-gate if (strcmp(clname, uamap->class) == 0) 30320Sstevel@tonic-gate break; 30330Sstevel@tonic-gate 30340Sstevel@tonic-gate return (uamap); 30350Sstevel@tonic-gate } 30360Sstevel@tonic-gate 30370Sstevel@tonic-gate /* 30380Sstevel@tonic-gate * Add UnitAddress property to the specified node 30390Sstevel@tonic-gate */ 30400Sstevel@tonic-gate static int 30410Sstevel@tonic-gate add_unitaddr_prop(picl_nodehdl_t nodeh, unitaddr_map_t *uamap, uint_t addrcells) 30420Sstevel@tonic-gate { 30430Sstevel@tonic-gate int regproplen, err; 30440Sstevel@tonic-gate uint32_t *regbuf; 30450Sstevel@tonic-gate picl_prophdl_t regh; 30460Sstevel@tonic-gate ptree_propinfo_t pinfo; 30470Sstevel@tonic-gate char unitaddr[MAX_UNIT_ADDRESS_LEN]; 30480Sstevel@tonic-gate 30490Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 30500Sstevel@tonic-gate if (err != PICL_SUCCESS) 30510Sstevel@tonic-gate return (err); 30520Sstevel@tonic-gate 30530Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 30540Sstevel@tonic-gate if (err != PICL_SUCCESS) 30550Sstevel@tonic-gate return (PICL_FAILURE); 30560Sstevel@tonic-gate 30570Sstevel@tonic-gate if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t))) 30580Sstevel@tonic-gate return (PICL_FAILURE); 30590Sstevel@tonic-gate 30600Sstevel@tonic-gate regproplen = pinfo.piclinfo.size; 30610Sstevel@tonic-gate regbuf = alloca(regproplen); 30620Sstevel@tonic-gate if (regbuf == NULL) 30630Sstevel@tonic-gate return (PICL_FAILURE); 30640Sstevel@tonic-gate 30650Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, regproplen); 30660Sstevel@tonic-gate if (err != PICL_SUCCESS || uamap->func == NULL || 30670Sstevel@tonic-gate (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) || 30680Sstevel@tonic-gate (uamap->func)(unitaddr, sizeof (unitaddr), regbuf, 30690Sstevel@tonic-gate addrcells) != 0) { 30700Sstevel@tonic-gate return (PICL_FAILURE); 30710Sstevel@tonic-gate } 30720Sstevel@tonic-gate 30730Sstevel@tonic-gate err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 30740Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(unitaddr)+1, 30750Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL); 30760Sstevel@tonic-gate if (err == PICL_SUCCESS) 30770Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &pinfo, unitaddr, NULL); 30780Sstevel@tonic-gate 30790Sstevel@tonic-gate return (err); 30800Sstevel@tonic-gate } 30810Sstevel@tonic-gate 30820Sstevel@tonic-gate /* 30830Sstevel@tonic-gate * work out UnitAddress property of the specified node 30840Sstevel@tonic-gate */ 30850Sstevel@tonic-gate static int 30860Sstevel@tonic-gate get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh, char *unitaddr, 30870Sstevel@tonic-gate size_t ualen) 30880Sstevel@tonic-gate { 30890Sstevel@tonic-gate int regproplen, err; 30900Sstevel@tonic-gate uint32_t *regbuf; 30910Sstevel@tonic-gate picl_prophdl_t regh; 30920Sstevel@tonic-gate ptree_propinfo_t pinfo; 30930Sstevel@tonic-gate unitaddr_map_t *uamap; 30940Sstevel@tonic-gate uint32_t addrcells; 30950Sstevel@tonic-gate 30960Sstevel@tonic-gate addrcells = get_addrcells_prop(parh); 30970Sstevel@tonic-gate uamap = get_unitaddr_mapping(parh); 30980Sstevel@tonic-gate 30990Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 31000Sstevel@tonic-gate if (err != PICL_SUCCESS) 31010Sstevel@tonic-gate return (err); 31020Sstevel@tonic-gate 31030Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 31040Sstevel@tonic-gate if (err != PICL_SUCCESS) 31050Sstevel@tonic-gate return (err); 31060Sstevel@tonic-gate 31070Sstevel@tonic-gate if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t))) 31080Sstevel@tonic-gate return (PICL_FAILURE); 31090Sstevel@tonic-gate 31100Sstevel@tonic-gate regproplen = pinfo.piclinfo.size; 31110Sstevel@tonic-gate regbuf = alloca(regproplen); 31120Sstevel@tonic-gate if (regbuf == NULL) 31130Sstevel@tonic-gate return (PICL_FAILURE); 31140Sstevel@tonic-gate 31150Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, regproplen); 31160Sstevel@tonic-gate if (err != PICL_SUCCESS || uamap->func == NULL || 31170Sstevel@tonic-gate (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) || 31180Sstevel@tonic-gate (uamap->func)(unitaddr, ualen, regbuf, addrcells) != 0) { 31190Sstevel@tonic-gate return (PICL_FAILURE); 31200Sstevel@tonic-gate } 31210Sstevel@tonic-gate return (PICL_SUCCESS); 31220Sstevel@tonic-gate } 31230Sstevel@tonic-gate 31240Sstevel@tonic-gate /* 31250Sstevel@tonic-gate * Add UnitAddress property to all children of the specified node 31260Sstevel@tonic-gate */ 31270Sstevel@tonic-gate static int 31280Sstevel@tonic-gate add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh) 31290Sstevel@tonic-gate { 31300Sstevel@tonic-gate int err; 31310Sstevel@tonic-gate picl_nodehdl_t chdh; 31320Sstevel@tonic-gate unitaddr_map_t *uamap; 31330Sstevel@tonic-gate uint32_t addrcells; 31340Sstevel@tonic-gate 31350Sstevel@tonic-gate /* 31360Sstevel@tonic-gate * Get #address-cells and unit address mapping entry for my 31370Sstevel@tonic-gate * node's class 31380Sstevel@tonic-gate */ 31390Sstevel@tonic-gate addrcells = get_addrcells_prop(nodeh); 31400Sstevel@tonic-gate uamap = get_unitaddr_mapping(nodeh); 31410Sstevel@tonic-gate 31420Sstevel@tonic-gate /* 31430Sstevel@tonic-gate * Add UnitAddress property to my children and their subtree 31440Sstevel@tonic-gate */ 31450Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 31460Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 31470Sstevel@tonic-gate 31480Sstevel@tonic-gate while (err == PICL_SUCCESS) { 31490Sstevel@tonic-gate (void) add_unitaddr_prop(chdh, uamap, addrcells); 31500Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(chdh); 31510Sstevel@tonic-gate 31520Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 31530Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 31540Sstevel@tonic-gate } 31550Sstevel@tonic-gate 31560Sstevel@tonic-gate return (PICL_SUCCESS); 31570Sstevel@tonic-gate } 31580Sstevel@tonic-gate 31590Sstevel@tonic-gate static int 31600Sstevel@tonic-gate update_memory_size_prop(picl_nodehdl_t plafh) 31610Sstevel@tonic-gate { 31620Sstevel@tonic-gate picl_nodehdl_t memh; 31630Sstevel@tonic-gate picl_prophdl_t proph; 31640Sstevel@tonic-gate ptree_propinfo_t pinfo; 31650Sstevel@tonic-gate int err, nspecs, snum, pval; 31660Sstevel@tonic-gate char *regbuf; 31670Sstevel@tonic-gate memspecs_t *mspecs; 31680Sstevel@tonic-gate uint64_t memsize; 31690Sstevel@tonic-gate 31700Sstevel@tonic-gate /* 31710Sstevel@tonic-gate * check if the #size-cells of the platform node is 2 31720Sstevel@tonic-gate */ 31730Sstevel@tonic-gate err = ptree_get_propval_by_name(plafh, OBP_PROP_SIZE_CELLS, &pval, 31745028Sfw157321 sizeof (pval)); 31750Sstevel@tonic-gate 31760Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 31770Sstevel@tonic-gate pval = SUPPORTED_NUM_CELL_SIZE; 31780Sstevel@tonic-gate else if (err != PICL_SUCCESS) 31790Sstevel@tonic-gate return (err); 31800Sstevel@tonic-gate 31810Sstevel@tonic-gate /* 31820Sstevel@tonic-gate * don't know how to handle other vals 31830Sstevel@tonic-gate */ 31840Sstevel@tonic-gate if (pval != SUPPORTED_NUM_CELL_SIZE) 31850Sstevel@tonic-gate return (PICL_FAILURE); 31860Sstevel@tonic-gate 31870Sstevel@tonic-gate err = ptree_get_node_by_path(MEMORY_PATH, &memh); 31880Sstevel@tonic-gate if (err != PICL_SUCCESS) 31890Sstevel@tonic-gate return (err); 31900Sstevel@tonic-gate 31910Sstevel@tonic-gate /* 31920Sstevel@tonic-gate * Get the REG property to calculate the size of memory 31930Sstevel@tonic-gate */ 31940Sstevel@tonic-gate err = ptree_get_prop_by_name(memh, OBP_REG, &proph); 31950Sstevel@tonic-gate if (err != PICL_SUCCESS) 31960Sstevel@tonic-gate return (err); 31970Sstevel@tonic-gate 31980Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 31990Sstevel@tonic-gate if (err != PICL_SUCCESS) 32000Sstevel@tonic-gate return (err); 32010Sstevel@tonic-gate 32020Sstevel@tonic-gate regbuf = alloca(pinfo.piclinfo.size); 32030Sstevel@tonic-gate if (regbuf == NULL) 32040Sstevel@tonic-gate return (PICL_FAILURE); 32050Sstevel@tonic-gate 32060Sstevel@tonic-gate err = ptree_get_propval(proph, regbuf, pinfo.piclinfo.size); 32070Sstevel@tonic-gate if (err != PICL_SUCCESS) 32080Sstevel@tonic-gate return (err); 32090Sstevel@tonic-gate 32100Sstevel@tonic-gate mspecs = (memspecs_t *)regbuf; 32110Sstevel@tonic-gate nspecs = pinfo.piclinfo.size / sizeof (memspecs_t); 32120Sstevel@tonic-gate 32130Sstevel@tonic-gate memsize = 0; 32140Sstevel@tonic-gate for (snum = 0; snum < nspecs; ++snum) 32150Sstevel@tonic-gate memsize += mspecs[snum].size; 32160Sstevel@tonic-gate 32170Sstevel@tonic-gate err = ptree_get_prop_by_name(memh, PICL_PROP_SIZE, &proph); 32180Sstevel@tonic-gate if (err == PICL_SUCCESS) { 32190Sstevel@tonic-gate err = ptree_update_propval(proph, &memsize, sizeof (memsize)); 32200Sstevel@tonic-gate return (err); 32210Sstevel@tonic-gate } 32220Sstevel@tonic-gate 32230Sstevel@tonic-gate /* 32240Sstevel@tonic-gate * Add the size property 32250Sstevel@tonic-gate */ 32260Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 32275028Sfw157321 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (memsize), 32285028Sfw157321 PICL_PROP_SIZE, NULL, NULL); 32290Sstevel@tonic-gate err = ptree_create_and_add_prop(memh, &pinfo, &memsize, NULL); 32300Sstevel@tonic-gate return (err); 32310Sstevel@tonic-gate } 32320Sstevel@tonic-gate 32330Sstevel@tonic-gate /* 32340Sstevel@tonic-gate * This function is executed as part of .init when the plugin is 32350Sstevel@tonic-gate * dlopen()ed 32360Sstevel@tonic-gate */ 32370Sstevel@tonic-gate static void 32380Sstevel@tonic-gate picldevtree_register(void) 32390Sstevel@tonic-gate { 32400Sstevel@tonic-gate if (getenv(SUNW_PICLDEVTREE_PLUGIN_DEBUG)) 32410Sstevel@tonic-gate picldevtree_debug = 1; 32420Sstevel@tonic-gate (void) picld_plugin_register(&my_reg_info); 32430Sstevel@tonic-gate } 32440Sstevel@tonic-gate 32450Sstevel@tonic-gate /* 32460Sstevel@tonic-gate * This function is the init entry point of the plugin. 32470Sstevel@tonic-gate * It initializes the /platform tree based on libdevinfo 32480Sstevel@tonic-gate */ 32490Sstevel@tonic-gate static void 32500Sstevel@tonic-gate picldevtree_init(void) 32510Sstevel@tonic-gate { 32520Sstevel@tonic-gate picl_nodehdl_t rhdl; 32530Sstevel@tonic-gate int err; 32540Sstevel@tonic-gate struct utsname utsname; 32550Sstevel@tonic-gate picl_nodehdl_t plafh; 32560Sstevel@tonic-gate 32570Sstevel@tonic-gate if (uname(&utsname) < 0) 32580Sstevel@tonic-gate return; 32590Sstevel@tonic-gate 32600Sstevel@tonic-gate (void) strcpy(mach_name, utsname.machine); 32610Sstevel@tonic-gate 32620Sstevel@tonic-gate if (strcmp(mach_name, "sun4u") == 0) { 32630Sstevel@tonic-gate builtin_map_ptr = sun4u_map; 32640Sstevel@tonic-gate builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t); 32653941Svenki } else if (strcmp(mach_name, "sun4v") == 0) { 32663941Svenki builtin_map_ptr = sun4u_map; 32673941Svenki builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t); 32680Sstevel@tonic-gate } else if (strcmp(mach_name, "i86pc") == 0) { 32690Sstevel@tonic-gate builtin_map_ptr = i86pc_map; 32700Sstevel@tonic-gate builtin_map_size = sizeof (i86pc_map) / sizeof (builtin_map_t); 32710Sstevel@tonic-gate } else { 32720Sstevel@tonic-gate builtin_map_ptr = NULL; 32730Sstevel@tonic-gate builtin_map_size = 0; 32740Sstevel@tonic-gate } 32750Sstevel@tonic-gate 32760Sstevel@tonic-gate err = ptree_get_root(&rhdl); 32770Sstevel@tonic-gate if (err != PICL_SUCCESS) { 32780Sstevel@tonic-gate syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED); 32790Sstevel@tonic-gate return; 32800Sstevel@tonic-gate } 32810Sstevel@tonic-gate 32820Sstevel@tonic-gate process_devtree_conf_file(); 32830Sstevel@tonic-gate 32840Sstevel@tonic-gate if (libdevinfo_init(rhdl) != PICL_SUCCESS) { 32850Sstevel@tonic-gate syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED); 32860Sstevel@tonic-gate return; 32870Sstevel@tonic-gate } 32880Sstevel@tonic-gate 32890Sstevel@tonic-gate err = ptree_get_node_by_path(PLATFORM_PATH, &plafh); 32900Sstevel@tonic-gate if (err != PICL_SUCCESS) 32910Sstevel@tonic-gate return; 32920Sstevel@tonic-gate 32930Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(plafh); 32940Sstevel@tonic-gate 32950Sstevel@tonic-gate add_asr_nodes(); 32960Sstevel@tonic-gate 32970Sstevel@tonic-gate (void) update_memory_size_prop(plafh); 32980Sstevel@tonic-gate 32990Sstevel@tonic-gate (void) setup_cpus(plafh); 33000Sstevel@tonic-gate 33010Sstevel@tonic-gate (void) add_ffb_config_info(plafh); 33020Sstevel@tonic-gate 33030Sstevel@tonic-gate (void) add_platform_info(plafh); 33040Sstevel@tonic-gate 3305944Svenki set_pci_pciex_deviceid(plafh); 33060Sstevel@tonic-gate 33070Sstevel@tonic-gate (void) set_sbus_slot(plafh); 33080Sstevel@tonic-gate 33090Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 33100Sstevel@tonic-gate picldevtree_evhandler, NULL); 33110Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 33120Sstevel@tonic-gate picldevtree_evhandler, NULL); 33135028Sfw157321 (void) ptree_register_handler(PICLEVENT_CPU_STATE_CHANGE, 33145028Sfw157321 picldevtree_evhandler, NULL); 33150Sstevel@tonic-gate } 33160Sstevel@tonic-gate 33170Sstevel@tonic-gate /* 33180Sstevel@tonic-gate * This function is the fini entry point of the plugin 33190Sstevel@tonic-gate */ 33200Sstevel@tonic-gate static void 33210Sstevel@tonic-gate picldevtree_fini(void) 33220Sstevel@tonic-gate { 33230Sstevel@tonic-gate /* First unregister the event handlers */ 33240Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 33250Sstevel@tonic-gate picldevtree_evhandler, NULL); 33260Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 33270Sstevel@tonic-gate picldevtree_evhandler, NULL); 33285028Sfw157321 (void) ptree_unregister_handler(PICLEVENT_CPU_STATE_CHANGE, 33295028Sfw157321 picldevtree_evhandler, NULL); 33300Sstevel@tonic-gate 33310Sstevel@tonic-gate conf_name_class_map = free_conf_entries(conf_name_class_map); 33320Sstevel@tonic-gate } 33330Sstevel@tonic-gate 33340Sstevel@tonic-gate /* 33350Sstevel@tonic-gate * This function is the event handler of this plug-in. 33360Sstevel@tonic-gate * 33370Sstevel@tonic-gate * It processes the following events: 33380Sstevel@tonic-gate * 33390Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_ADDED 33400Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_REMOVED 33415028Sfw157321 * PICLEVENT_CPU_STATE_CHANGE 33420Sstevel@tonic-gate */ 33430Sstevel@tonic-gate /* ARGSUSED */ 33440Sstevel@tonic-gate static void 33450Sstevel@tonic-gate picldevtree_evhandler(const char *ename, const void *earg, size_t size, 33460Sstevel@tonic-gate void *cookie) 33470Sstevel@tonic-gate { 33480Sstevel@tonic-gate char *devfs_path; 33490Sstevel@tonic-gate char ptreepath[PATH_MAX]; 33500Sstevel@tonic-gate char dipath[PATH_MAX]; 33510Sstevel@tonic-gate picl_nodehdl_t plafh; 33520Sstevel@tonic-gate picl_nodehdl_t nodeh; 33530Sstevel@tonic-gate nvlist_t *nvlp; 33540Sstevel@tonic-gate 33550Sstevel@tonic-gate if (earg == NULL) 33560Sstevel@tonic-gate return; 33570Sstevel@tonic-gate 33580Sstevel@tonic-gate nvlp = NULL; 33590Sstevel@tonic-gate if (ptree_get_node_by_path(PLATFORM_PATH, &plafh) != PICL_SUCCESS || 33600Sstevel@tonic-gate nvlist_unpack((char *)earg, size, &nvlp, NULL) || 33610Sstevel@tonic-gate nvlist_lookup_string(nvlp, PICLEVENTARG_DEVFS_PATH, &devfs_path) || 33620Sstevel@tonic-gate strlen(devfs_path) > (PATH_MAX - sizeof (PLATFORM_PATH))) { 33630Sstevel@tonic-gate syslog(LOG_INFO, PICL_EVENT_DROPPED, ename); 33640Sstevel@tonic-gate if (nvlp) 33650Sstevel@tonic-gate nvlist_free(nvlp); 33660Sstevel@tonic-gate return; 33670Sstevel@tonic-gate } 33680Sstevel@tonic-gate 33690Sstevel@tonic-gate (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX); 33700Sstevel@tonic-gate (void) strlcat(ptreepath, devfs_path, PATH_MAX); 33710Sstevel@tonic-gate (void) strlcpy(dipath, devfs_path, PATH_MAX); 33720Sstevel@tonic-gate nvlist_free(nvlp); 33730Sstevel@tonic-gate 33740Sstevel@tonic-gate if (picldevtree_debug) 33750Sstevel@tonic-gate syslog(LOG_INFO, "picldevtree: event handler invoked ename:%s " 33760Sstevel@tonic-gate "ptreepath:%s\n", ename, ptreepath); 33770Sstevel@tonic-gate 33785028Sfw157321 if (strcmp(ename, PICLEVENT_CPU_STATE_CHANGE) == 0) { 33795028Sfw157321 goto done; 33805028Sfw157321 } 33810Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) { 33820Sstevel@tonic-gate di_node_t devnode; 33830Sstevel@tonic-gate char *strp; 33840Sstevel@tonic-gate picl_nodehdl_t parh; 33850Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 33860Sstevel@tonic-gate char *nodename; 33870Sstevel@tonic-gate int err; 33880Sstevel@tonic-gate 33890Sstevel@tonic-gate /* If the node already exist, then nothing else to do here */ 33900Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) == PICL_SUCCESS) 33910Sstevel@tonic-gate return; 33920Sstevel@tonic-gate 33930Sstevel@tonic-gate /* Skip if unable to find parent PICL node handle */ 33940Sstevel@tonic-gate parh = plafh; 33950Sstevel@tonic-gate if (((strp = strrchr(ptreepath, '/')) != NULL) && 33960Sstevel@tonic-gate (strp != strchr(ptreepath, '/'))) { 33970Sstevel@tonic-gate *strp = '\0'; 33980Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &parh) != 33990Sstevel@tonic-gate PICL_SUCCESS) 34000Sstevel@tonic-gate return; 34010Sstevel@tonic-gate } 34020Sstevel@tonic-gate 34030Sstevel@tonic-gate /* 34040Sstevel@tonic-gate * If parent is the root node 34050Sstevel@tonic-gate */ 34060Sstevel@tonic-gate if (parh == plafh) { 34070Sstevel@tonic-gate ph = di_prom_init(); 34080Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 34090Sstevel@tonic-gate if (devnode == DI_NODE_NIL) { 34100Sstevel@tonic-gate if (ph != NULL) { 34110Sstevel@tonic-gate di_prom_fini(ph); 34120Sstevel@tonic-gate ph = NULL; 34130Sstevel@tonic-gate } 34140Sstevel@tonic-gate return; 34150Sstevel@tonic-gate } 34160Sstevel@tonic-gate nodename = di_node_name(devnode); 34170Sstevel@tonic-gate if (nodename == NULL) { 34180Sstevel@tonic-gate di_fini(devnode); 34190Sstevel@tonic-gate if (ph != NULL) { 34200Sstevel@tonic-gate di_prom_fini(ph); 34210Sstevel@tonic-gate ph = NULL; 34220Sstevel@tonic-gate } 34230Sstevel@tonic-gate return; 34240Sstevel@tonic-gate } 34250Sstevel@tonic-gate 34260Sstevel@tonic-gate err = get_node_class(nodeclass, devnode, nodename); 34270Sstevel@tonic-gate if (err < 0) { 34280Sstevel@tonic-gate di_fini(devnode); 34290Sstevel@tonic-gate if (ph != NULL) { 34300Sstevel@tonic-gate di_prom_fini(ph); 34310Sstevel@tonic-gate ph = NULL; 34320Sstevel@tonic-gate } 34330Sstevel@tonic-gate return; 34340Sstevel@tonic-gate } 34350Sstevel@tonic-gate err = construct_devtype_node(plafh, nodename, 34360Sstevel@tonic-gate nodeclass, devnode, &nodeh); 34370Sstevel@tonic-gate if (err != PICL_SUCCESS) { 34380Sstevel@tonic-gate di_fini(devnode); 34390Sstevel@tonic-gate if (ph != NULL) { 34400Sstevel@tonic-gate di_prom_fini(ph); 34410Sstevel@tonic-gate ph = NULL; 34420Sstevel@tonic-gate } 34430Sstevel@tonic-gate return; 34440Sstevel@tonic-gate } 34450Sstevel@tonic-gate (void) update_subtree(nodeh, devnode); 34460Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(nodeh); 34470Sstevel@tonic-gate if (ph != NULL) { 34480Sstevel@tonic-gate di_prom_fini(ph); 34490Sstevel@tonic-gate ph = NULL; 34500Sstevel@tonic-gate } 34510Sstevel@tonic-gate di_fini(devnode); 34520Sstevel@tonic-gate goto done; 34530Sstevel@tonic-gate } 34540Sstevel@tonic-gate 34550Sstevel@tonic-gate /* kludge ... try without bus-addr first */ 34560Sstevel@tonic-gate if ((strp = strrchr(dipath, '@')) != NULL) { 34570Sstevel@tonic-gate char *p; 34580Sstevel@tonic-gate 34590Sstevel@tonic-gate p = strrchr(dipath, '/'); 34600Sstevel@tonic-gate if (p != NULL && strp > p) { 34610Sstevel@tonic-gate *strp = '\0'; 34620Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 34630Sstevel@tonic-gate if (devnode != DI_NODE_NIL) 34640Sstevel@tonic-gate di_fini(devnode); 34650Sstevel@tonic-gate *strp = '@'; 34660Sstevel@tonic-gate } 34670Sstevel@tonic-gate } 34680Sstevel@tonic-gate /* Get parent devnode */ 34690Sstevel@tonic-gate if ((strp = strrchr(dipath, '/')) != NULL) 34700Sstevel@tonic-gate *++strp = '\0'; 34710Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 34720Sstevel@tonic-gate if (devnode == DI_NODE_NIL) 34730Sstevel@tonic-gate return; 34740Sstevel@tonic-gate ph = di_prom_init(); 34750Sstevel@tonic-gate (void) update_subtree(parh, devnode); 34760Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(parh); 34770Sstevel@tonic-gate if (ph) { 34780Sstevel@tonic-gate di_prom_fini(ph); 34790Sstevel@tonic-gate ph = NULL; 34800Sstevel@tonic-gate } 34810Sstevel@tonic-gate di_fini(devnode); 34820Sstevel@tonic-gate } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) { 34830Sstevel@tonic-gate char delclass[PICL_CLASSNAMELEN_MAX]; 34840Sstevel@tonic-gate char *strp; 34850Sstevel@tonic-gate 34860Sstevel@tonic-gate /* 34870Sstevel@tonic-gate * if final element of path doesn't have a unit address 34880Sstevel@tonic-gate * then it is not uniquely identifiable - cannot remove 34890Sstevel@tonic-gate */ 34900Sstevel@tonic-gate if (((strp = strrchr(ptreepath, '/')) != NULL) && 34910Sstevel@tonic-gate strchr(strp, '@') == NULL) 34920Sstevel@tonic-gate return; 34930Sstevel@tonic-gate 34940Sstevel@tonic-gate /* skip if can't find the node */ 34950Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS) 34960Sstevel@tonic-gate return; 34970Sstevel@tonic-gate 34980Sstevel@tonic-gate if (ptree_delete_node(nodeh) != PICL_SUCCESS) 34990Sstevel@tonic-gate return; 35000Sstevel@tonic-gate 35010Sstevel@tonic-gate if (picldevtree_debug) 35020Sstevel@tonic-gate syslog(LOG_INFO, 35030Sstevel@tonic-gate "picldevtree: deleted node nodeh:%llx\n", nodeh); 35040Sstevel@tonic-gate if ((ptree_get_propval_by_name(nodeh, 35050Sstevel@tonic-gate PICL_PROP_CLASSNAME, delclass, PICL_CLASSNAMELEN_MAX) == 35060Sstevel@tonic-gate PICL_SUCCESS) && IS_MC(delclass)) { 35070Sstevel@tonic-gate if (post_mc_event(PICLEVENT_MC_REMOVED, nodeh) != 35080Sstevel@tonic-gate PICL_SUCCESS) 35090Sstevel@tonic-gate syslog(LOG_WARNING, PICL_EVENT_DROPPED, 35100Sstevel@tonic-gate PICLEVENT_MC_REMOVED); 35110Sstevel@tonic-gate } else 35120Sstevel@tonic-gate (void) ptree_destroy_node(nodeh); 35130Sstevel@tonic-gate } 35140Sstevel@tonic-gate done: 35150Sstevel@tonic-gate (void) setup_cpus(plafh); 35160Sstevel@tonic-gate (void) add_ffb_config_info(plafh); 3517944Svenki set_pci_pciex_deviceid(plafh); 35180Sstevel@tonic-gate (void) set_sbus_slot(plafh); 35190Sstevel@tonic-gate if (picldevtree_debug > 1) 35200Sstevel@tonic-gate syslog(LOG_INFO, "picldevtree: event handler done\n"); 35210Sstevel@tonic-gate } 3522