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*3941Svenki * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * PICL plug-in that creates device tree nodes for all platforms 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <stdio.h> 330Sstevel@tonic-gate #include <string.h> 340Sstevel@tonic-gate #include <ctype.h> 350Sstevel@tonic-gate #include <limits.h> 360Sstevel@tonic-gate #include <stdlib.h> 370Sstevel@tonic-gate #include <assert.h> 380Sstevel@tonic-gate #include <alloca.h> 390Sstevel@tonic-gate #include <unistd.h> 400Sstevel@tonic-gate #include <stropts.h> 410Sstevel@tonic-gate #include <syslog.h> 420Sstevel@tonic-gate #include <libdevinfo.h> 430Sstevel@tonic-gate #include <sys/dkio.h> 440Sstevel@tonic-gate #include <sys/vtoc.h> 450Sstevel@tonic-gate #include <sys/time.h> 460Sstevel@tonic-gate #include <fcntl.h> 470Sstevel@tonic-gate #include <picl.h> 480Sstevel@tonic-gate #include <picltree.h> 490Sstevel@tonic-gate #include <sys/types.h> 500Sstevel@tonic-gate #include <sys/processor.h> 510Sstevel@tonic-gate #include <kstat.h> 520Sstevel@tonic-gate #include <sys/sysinfo.h> 530Sstevel@tonic-gate #include <dirent.h> 540Sstevel@tonic-gate #include <libintl.h> 550Sstevel@tonic-gate #include <pthread.h> 560Sstevel@tonic-gate #include <libnvpair.h> 570Sstevel@tonic-gate #include <sys/utsname.h> 580Sstevel@tonic-gate #include <sys/systeminfo.h> 590Sstevel@tonic-gate #include <sys/obpdefs.h> 600Sstevel@tonic-gate #include <sys/openpromio.h> 610Sstevel@tonic-gate #include "picldevtree.h" 620Sstevel@tonic-gate 630Sstevel@tonic-gate /* 640Sstevel@tonic-gate * Plugin registration entry points 650Sstevel@tonic-gate */ 660Sstevel@tonic-gate static void picldevtree_register(void); 670Sstevel@tonic-gate static void picldevtree_init(void); 680Sstevel@tonic-gate static void picldevtree_fini(void); 690Sstevel@tonic-gate 700Sstevel@tonic-gate static void picldevtree_evhandler(const char *ename, const void *earg, 710Sstevel@tonic-gate size_t size, void *cookie); 720Sstevel@tonic-gate 730Sstevel@tonic-gate #pragma init(picldevtree_register) 740Sstevel@tonic-gate 750Sstevel@tonic-gate /* 760Sstevel@tonic-gate * Log message texts 770Sstevel@tonic-gate */ 780Sstevel@tonic-gate #define DEVINFO_PLUGIN_INIT_FAILED gettext("SUNW_picldevtree failed!\n") 790Sstevel@tonic-gate #define PICL_EVENT_DROPPED \ 800Sstevel@tonic-gate gettext("SUNW_picldevtree '%s' event dropped.\n") 810Sstevel@tonic-gate 820Sstevel@tonic-gate /* 830Sstevel@tonic-gate * Macro to get PCI device id (from IEEE 1275 spec) 840Sstevel@tonic-gate */ 850Sstevel@tonic-gate #define PCI_DEVICE_ID(x) (((x) >> 11) & 0x1f) 860Sstevel@tonic-gate /* 870Sstevel@tonic-gate * Local variables 880Sstevel@tonic-gate */ 890Sstevel@tonic-gate static picld_plugin_reg_t my_reg_info = { 900Sstevel@tonic-gate PICLD_PLUGIN_VERSION_1, 910Sstevel@tonic-gate PICLD_PLUGIN_CRITICAL, 920Sstevel@tonic-gate "SUNW_picldevtree", 930Sstevel@tonic-gate picldevtree_init, 940Sstevel@tonic-gate picldevtree_fini 950Sstevel@tonic-gate }; 960Sstevel@tonic-gate 970Sstevel@tonic-gate /* 980Sstevel@tonic-gate * Debug enabling environment variable 990Sstevel@tonic-gate */ 1000Sstevel@tonic-gate #define SUNW_PICLDEVTREE_PLUGIN_DEBUG "SUNW_PICLDEVTREE_PLUGIN_DEBUG" 1010Sstevel@tonic-gate static int picldevtree_debug = 0; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate static conf_entries_t *conf_name_class_map = NULL; 1040Sstevel@tonic-gate static builtin_map_t sun4u_map[] = { 1050Sstevel@tonic-gate /* MAX_NAMEVAL_SIZE */ 1060Sstevel@tonic-gate { "SUNW,bpp", PICL_CLASS_PARALLEL}, 1070Sstevel@tonic-gate { "parallel", PICL_CLASS_PARALLEL}, 1080Sstevel@tonic-gate { "floppy", PICL_CLASS_FLOPPY}, 1090Sstevel@tonic-gate { "memory", PICL_CLASS_MEMORY}, 1100Sstevel@tonic-gate { "ebus", PICL_CLASS_EBUS}, 1110Sstevel@tonic-gate { "i2c", PICL_CLASS_I2C}, 1120Sstevel@tonic-gate { "usb", PICL_CLASS_USB}, 1130Sstevel@tonic-gate { "isa", PICL_CLASS_ISA}, 1140Sstevel@tonic-gate { "dma", PICL_CLASS_DMA}, 1150Sstevel@tonic-gate { "keyboard", PICL_CLASS_KEYBOARD}, 1160Sstevel@tonic-gate { "mouse", PICL_CLASS_MOUSE}, 1170Sstevel@tonic-gate { "fan-control", PICL_CLASS_FAN_CONTROL}, 1180Sstevel@tonic-gate { "sc", PICL_CLASS_SYSTEM_CONTROLLER}, 1190Sstevel@tonic-gate { "dimm", PICL_CLASS_SEEPROM}, 1200Sstevel@tonic-gate { "dimm-fru", PICL_CLASS_SEEPROM}, 1210Sstevel@tonic-gate { "cpu", PICL_CLASS_SEEPROM}, 1220Sstevel@tonic-gate { "cpu-fru", PICL_CLASS_SEEPROM}, 1230Sstevel@tonic-gate { "flashprom", PICL_CLASS_FLASHPROM}, 1240Sstevel@tonic-gate { "temperature", PICL_CLASS_TEMPERATURE_DEVICE}, 1250Sstevel@tonic-gate { "motherboard", PICL_CLASS_SEEPROM}, 1260Sstevel@tonic-gate { "motherboard-fru", PICL_CLASS_SEEPROM}, 1270Sstevel@tonic-gate { "motherboard-fru-prom", PICL_CLASS_SEEPROM}, 1280Sstevel@tonic-gate { "pmu", PICL_CLASS_PMU}, 1290Sstevel@tonic-gate { "sound", PICL_CLASS_SOUND}, 1300Sstevel@tonic-gate { "firewire", PICL_CLASS_FIREWIRE}, 1310Sstevel@tonic-gate { "i2c-at34c02", PICL_CLASS_SEEPROM}, 1320Sstevel@tonic-gate { "hardware-monitor", PICL_CLASS_HARDWARE_MONITOR}, 1330Sstevel@tonic-gate { "", ""} 1340Sstevel@tonic-gate }; 1350Sstevel@tonic-gate static builtin_map_t i86pc_map[] = { 1360Sstevel@tonic-gate /* MAX_NAMEVAL_SIZE */ 1370Sstevel@tonic-gate { "cpus", PICL_CLASS_I86CPUS}, 1380Sstevel@tonic-gate { "cpu", PICL_CLASS_CPU}, 1390Sstevel@tonic-gate { "memory", PICL_CLASS_MEMORY}, 1400Sstevel@tonic-gate { "asy", PICL_CLASS_SERIAL}, 1410Sstevel@tonic-gate { "", ""} 1420Sstevel@tonic-gate }; 1430Sstevel@tonic-gate static pname_type_map_t pname_type_map[] = { 1440Sstevel@tonic-gate { "reg", PICL_PTYPE_BYTEARRAY}, 1450Sstevel@tonic-gate { "device_type", PICL_PTYPE_CHARSTRING}, 1460Sstevel@tonic-gate { "ranges", PICL_PTYPE_BYTEARRAY}, 1470Sstevel@tonic-gate { "status", PICL_PTYPE_CHARSTRING}, 1480Sstevel@tonic-gate { "compatible", PICL_PTYPE_CHARSTRING}, 1490Sstevel@tonic-gate { "interrupts", PICL_PTYPE_BYTEARRAY}, 1500Sstevel@tonic-gate { "model", PICL_PTYPE_CHARSTRING}, 1510Sstevel@tonic-gate { "address", PICL_PTYPE_BYTEARRAY}, 1520Sstevel@tonic-gate { "vendor-id", PICL_PTYPE_UNSIGNED_INT}, 1530Sstevel@tonic-gate { "device-id", PICL_PTYPE_UNSIGNED_INT}, 1540Sstevel@tonic-gate { "revision-id", PICL_PTYPE_UNSIGNED_INT}, 1550Sstevel@tonic-gate { "class-code", PICL_PTYPE_UNSIGNED_INT}, 1560Sstevel@tonic-gate { "min-grant", PICL_PTYPE_UNSIGNED_INT}, 1570Sstevel@tonic-gate { "max-latency", PICL_PTYPE_UNSIGNED_INT}, 1580Sstevel@tonic-gate { "devsel-speed", PICL_PTYPE_UNSIGNED_INT}, 1590Sstevel@tonic-gate { "subsystem-id", PICL_PTYPE_UNSIGNED_INT}, 1600Sstevel@tonic-gate { "subsystem-vendor-id", PICL_PTYPE_UNSIGNED_INT}, 1610Sstevel@tonic-gate { "assigned-addresses", PICL_PTYPE_BYTEARRAY}, 1620Sstevel@tonic-gate { "configuration#", PICL_PTYPE_UNSIGNED_INT}, 1630Sstevel@tonic-gate { "assigned-address", PICL_PTYPE_UNSIGNED_INT}, 1640Sstevel@tonic-gate { "#address-cells", PICL_PTYPE_UNSIGNED_INT}, 1650Sstevel@tonic-gate { "#size-cells", PICL_PTYPE_UNSIGNED_INT}, 1660Sstevel@tonic-gate { "clock-frequency", PICL_PTYPE_UNSIGNED_INT}, 1670Sstevel@tonic-gate { "scsi-initiator-id", PICL_PTYPE_UNSIGNED_INT}, 1680Sstevel@tonic-gate { "differential", PICL_PTYPE_UNSIGNED_INT}, 1690Sstevel@tonic-gate { "idprom", PICL_PTYPE_BYTEARRAY}, 1700Sstevel@tonic-gate { "bus-range", PICL_PTYPE_BYTEARRAY}, 1710Sstevel@tonic-gate { "alternate-reg", PICL_PTYPE_BYTEARRAY}, 1720Sstevel@tonic-gate { "power-consumption", PICL_PTYPE_BYTEARRAY}, 1730Sstevel@tonic-gate { "slot-names", PICL_PTYPE_BYTEARRAY}, 1740Sstevel@tonic-gate { "burst-sizes", PICL_PTYPE_UNSIGNED_INT}, 1750Sstevel@tonic-gate { "up-burst-sizes", PICL_PTYPE_UNSIGNED_INT}, 1760Sstevel@tonic-gate { "slot-address-bits", PICL_PTYPE_UNSIGNED_INT}, 1770Sstevel@tonic-gate { "eisa-slots", PICL_PTYPE_BYTEARRAY}, 1780Sstevel@tonic-gate { "dma", PICL_PTYPE_BYTEARRAY}, 1790Sstevel@tonic-gate { "slot-names-index", PICL_PTYPE_UNSIGNED_INT}, 1800Sstevel@tonic-gate { "pnp-csn", PICL_PTYPE_UNSIGNED_INT}, 1810Sstevel@tonic-gate { "pnp-data", PICL_PTYPE_BYTEARRAY}, 1820Sstevel@tonic-gate { "description", PICL_PTYPE_CHARSTRING}, 1830Sstevel@tonic-gate { "pnp-id", PICL_PTYPE_CHARSTRING}, 1840Sstevel@tonic-gate { "max-frame-size", PICL_PTYPE_UNSIGNED_INT}, 1850Sstevel@tonic-gate { "address-bits", PICL_PTYPE_UNSIGNED_INT}, 1860Sstevel@tonic-gate { "local-mac-address", PICL_PTYPE_BYTEARRAY}, 1870Sstevel@tonic-gate { "mac-address", PICL_PTYPE_BYTEARRAY}, 1880Sstevel@tonic-gate { "character-set", PICL_PTYPE_CHARSTRING}, 1890Sstevel@tonic-gate { "available", PICL_PTYPE_BYTEARRAY}, 1900Sstevel@tonic-gate { "port-wwn", PICL_PTYPE_BYTEARRAY}, 1910Sstevel@tonic-gate { "node-wwn", PICL_PTYPE_BYTEARRAY}, 1920Sstevel@tonic-gate { "width", PICL_PTYPE_UNSIGNED_INT}, 1930Sstevel@tonic-gate { "linebytes", PICL_PTYPE_UNSIGNED_INT}, 1940Sstevel@tonic-gate { "height", PICL_PTYPE_UNSIGNED_INT}, 1950Sstevel@tonic-gate { "banner-name", PICL_PTYPE_CHARSTRING}, 1960Sstevel@tonic-gate { "reset-reason", PICL_PTYPE_CHARSTRING}, 1970Sstevel@tonic-gate { "implementation#", PICL_PTYPE_UNSIGNED_INT}, 1980Sstevel@tonic-gate { "version#", PICL_PTYPE_UNSIGNED_INT}, 1990Sstevel@tonic-gate { "icache-size", PICL_PTYPE_UNSIGNED_INT}, 2000Sstevel@tonic-gate { "icache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2010Sstevel@tonic-gate { "icache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2020Sstevel@tonic-gate { "l1-icache-size", PICL_PTYPE_UNSIGNED_INT}, 2030Sstevel@tonic-gate { "l1-icache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2040Sstevel@tonic-gate { "l1-icache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2050Sstevel@tonic-gate { "#itlb-entries", PICL_PTYPE_UNSIGNED_INT}, 2060Sstevel@tonic-gate { "dcache-size", PICL_PTYPE_UNSIGNED_INT}, 2070Sstevel@tonic-gate { "dcache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2080Sstevel@tonic-gate { "dcache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2090Sstevel@tonic-gate { "l1-dcache-size", PICL_PTYPE_UNSIGNED_INT}, 2100Sstevel@tonic-gate { "l1-dcache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2110Sstevel@tonic-gate { "l1-dcache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2120Sstevel@tonic-gate { "#dtlb-entries", PICL_PTYPE_UNSIGNED_INT}, 2130Sstevel@tonic-gate { "ecache-size", PICL_PTYPE_UNSIGNED_INT}, 2140Sstevel@tonic-gate { "ecache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2150Sstevel@tonic-gate { "ecache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2160Sstevel@tonic-gate { "l2-cache-size", PICL_PTYPE_UNSIGNED_INT}, 2170Sstevel@tonic-gate { "l2-cache-line-size", PICL_PTYPE_UNSIGNED_INT}, 2180Sstevel@tonic-gate { "l2-cache-associativity", PICL_PTYPE_UNSIGNED_INT}, 2190Sstevel@tonic-gate { "l2-cache-sharing", PICL_PTYPE_BYTEARRAY}, 2200Sstevel@tonic-gate { "mask#", PICL_PTYPE_UNSIGNED_INT}, 2210Sstevel@tonic-gate { "manufacturer#", PICL_PTYPE_UNSIGNED_INT}, 2220Sstevel@tonic-gate { "sparc-version", PICL_PTYPE_UNSIGNED_INT}, 2230Sstevel@tonic-gate { "version", PICL_PTYPE_CHARSTRING}, 2240Sstevel@tonic-gate { "cpu-model", PICL_PTYPE_UNSIGNED_INT}, 2250Sstevel@tonic-gate { "memory-layout", PICL_PTYPE_BYTEARRAY}, 2260Sstevel@tonic-gate { "#interrupt-cells", PICL_PTYPE_UNSIGNED_INT}, 2270Sstevel@tonic-gate { "interrupt-map", PICL_PTYPE_BYTEARRAY}, 2280Sstevel@tonic-gate { "interrupt-map-mask", PICL_PTYPE_BYTEARRAY} 2290Sstevel@tonic-gate }; 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate #define PNAME_MAP_SIZE sizeof (pname_type_map) / sizeof (pname_type_map_t) 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate static builtin_map_t *builtin_map_ptr = NULL; 2340Sstevel@tonic-gate static int builtin_map_size = 0; 2350Sstevel@tonic-gate static char mach_name[SYS_NMLN]; 2360Sstevel@tonic-gate static di_prom_handle_t ph = DI_PROM_HANDLE_NIL; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate /* 2390Sstevel@tonic-gate * UnitAddress mapping table 2400Sstevel@tonic-gate */ 2410Sstevel@tonic-gate static unitaddr_func_t encode_default_unitaddr; 2420Sstevel@tonic-gate static unitaddr_func_t encode_optional_unitaddr; 2430Sstevel@tonic-gate static unitaddr_func_t encode_scsi_unitaddr; 2440Sstevel@tonic-gate static unitaddr_func_t encode_upa_unitaddr; 2450Sstevel@tonic-gate static unitaddr_func_t encode_gptwo_jbus_unitaddr; 2460Sstevel@tonic-gate static unitaddr_func_t encode_pci_unitaddr; 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate static unitaddr_map_t unitaddr_map_table[] = { 2490Sstevel@tonic-gate {PICL_CLASS_JBUS, encode_gptwo_jbus_unitaddr, 0}, 2500Sstevel@tonic-gate {PICL_CLASS_GPTWO, encode_gptwo_jbus_unitaddr, 0}, 2510Sstevel@tonic-gate {PICL_CLASS_PCI, encode_pci_unitaddr, 0}, 252944Svenki {PICL_CLASS_PCIEX, encode_pci_unitaddr, 0}, 2530Sstevel@tonic-gate {PICL_CLASS_UPA, encode_upa_unitaddr, 0}, 2540Sstevel@tonic-gate {PICL_CLASS_SCSI, encode_scsi_unitaddr, 0}, 2550Sstevel@tonic-gate {PICL_CLASS_SCSI2, encode_scsi_unitaddr, 0}, 2560Sstevel@tonic-gate {PICL_CLASS_EBUS, encode_default_unitaddr, 2}, 2570Sstevel@tonic-gate {PICL_CLASS_SBUS, encode_default_unitaddr, 2}, 2580Sstevel@tonic-gate {PICL_CLASS_I2C, encode_default_unitaddr, 2}, 2590Sstevel@tonic-gate {PICL_CLASS_USB, encode_default_unitaddr, 1}, 2600Sstevel@tonic-gate {PICL_CLASS_PMU, encode_optional_unitaddr, 2}, 2610Sstevel@tonic-gate {NULL, encode_default_unitaddr, 0} 2620Sstevel@tonic-gate }; 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate static int add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh); 2650Sstevel@tonic-gate static int get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh, 2660Sstevel@tonic-gate char *unitaddr, size_t ualen); 267944Svenki static void set_pci_pciex_deviceid(picl_nodehdl_t plafh); 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate /* 2700Sstevel@tonic-gate * The mc event completion handler. 2710Sstevel@tonic-gate * The arguments are event name buffer and a packed nvlist buffer 2720Sstevel@tonic-gate * with the size specifying the size of unpacked nvlist. These 2730Sstevel@tonic-gate * buffers are deallcoated here. 2740Sstevel@tonic-gate * 2750Sstevel@tonic-gate * Also, if a memory controller node is being removed then destroy the 2760Sstevel@tonic-gate * PICL subtree associated with that memory controller. 2770Sstevel@tonic-gate */ 2780Sstevel@tonic-gate static void 2790Sstevel@tonic-gate mc_completion_handler(char *ename, void *earg, size_t size) 2800Sstevel@tonic-gate { 2810Sstevel@tonic-gate picl_nodehdl_t mch; 2820Sstevel@tonic-gate nvlist_t *unpack_nvl; 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_MC_REMOVED) == 0 && 2850Sstevel@tonic-gate nvlist_unpack(earg, size, &unpack_nvl, NULL) == 0) { 2860Sstevel@tonic-gate mch = NULL; 2870Sstevel@tonic-gate (void) nvlist_lookup_uint64(unpack_nvl, 2880Sstevel@tonic-gate PICLEVENTARG_NODEHANDLE, &mch); 2890Sstevel@tonic-gate if (mch != NULL) { 2900Sstevel@tonic-gate if (picldevtree_debug) 2910Sstevel@tonic-gate syslog(LOG_INFO, 2920Sstevel@tonic-gate "picldevtree: destroying_node:%llx\n", 2930Sstevel@tonic-gate mch); 2940Sstevel@tonic-gate (void) ptree_destroy_node(mch); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate nvlist_free(unpack_nvl); 2970Sstevel@tonic-gate } 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate free(ename); 3000Sstevel@tonic-gate free(earg); 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate /* 3040Sstevel@tonic-gate * Functions to post memory controller change event 3050Sstevel@tonic-gate */ 3060Sstevel@tonic-gate static int 3070Sstevel@tonic-gate post_mc_event(char *ename, picl_nodehdl_t mch) 3080Sstevel@tonic-gate { 3090Sstevel@tonic-gate nvlist_t *nvl; 3100Sstevel@tonic-gate size_t nvl_size; 3110Sstevel@tonic-gate char *pack_buf; 3120Sstevel@tonic-gate char *ev_name; 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate ev_name = strdup(ename); 3150Sstevel@tonic-gate if (ev_name == NULL) 3160Sstevel@tonic-gate return (-1); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) { 3190Sstevel@tonic-gate free(ev_name); 3200Sstevel@tonic-gate return (-1); 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate pack_buf = NULL; 3240Sstevel@tonic-gate if (nvlist_add_uint64(nvl, PICLEVENTARG_NODEHANDLE, mch) || 3250Sstevel@tonic-gate nvlist_pack(nvl, &pack_buf, &nvl_size, NV_ENCODE_NATIVE, NULL)) { 3260Sstevel@tonic-gate free(ev_name); 3270Sstevel@tonic-gate nvlist_free(nvl); 3280Sstevel@tonic-gate return (-1); 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate if (picldevtree_debug) 3320Sstevel@tonic-gate syslog(LOG_INFO, 3330Sstevel@tonic-gate "picldevtree: posting MC event ename:%s nodeh:%llx\n", 3340Sstevel@tonic-gate ev_name, mch); 3350Sstevel@tonic-gate if (ptree_post_event(ev_name, pack_buf, nvl_size, 3360Sstevel@tonic-gate mc_completion_handler) != PICL_SUCCESS) { 3370Sstevel@tonic-gate free(ev_name); 3380Sstevel@tonic-gate nvlist_free(nvl); 3390Sstevel@tonic-gate return (-1); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate nvlist_free(nvl); 3420Sstevel@tonic-gate return (0); 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * Lookup a name in the name to class map tables 3470Sstevel@tonic-gate */ 3480Sstevel@tonic-gate static int 3490Sstevel@tonic-gate lookup_name_class_map(char *classbuf, const char *nm) 3500Sstevel@tonic-gate { 3510Sstevel@tonic-gate conf_entries_t *ptr; 3520Sstevel@tonic-gate int i; 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate /* 3550Sstevel@tonic-gate * check name to class mapping in conf file 3560Sstevel@tonic-gate */ 3570Sstevel@tonic-gate ptr = conf_name_class_map; 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate while (ptr != NULL) { 3600Sstevel@tonic-gate if (strcmp(ptr->name, nm) == 0) { 3610Sstevel@tonic-gate (void) strlcpy(classbuf, ptr->piclclass, 3620Sstevel@tonic-gate PICL_CLASSNAMELEN_MAX); 3630Sstevel@tonic-gate return (0); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate ptr = ptr->next; 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate /* 3690Sstevel@tonic-gate * check name to class mapping in builtin table 3700Sstevel@tonic-gate */ 3710Sstevel@tonic-gate if (builtin_map_ptr == NULL) 3720Sstevel@tonic-gate return (-1); 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate for (i = 0; i < builtin_map_size; ++i) 3750Sstevel@tonic-gate if (strcmp(builtin_map_ptr[i].name, nm) == 0) { 3760Sstevel@tonic-gate (void) strlcpy(classbuf, builtin_map_ptr[i].piclclass, 3770Sstevel@tonic-gate PICL_CLASSNAMELEN_MAX); 3780Sstevel@tonic-gate return (0); 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate return (-1); 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* 3840Sstevel@tonic-gate * Lookup a prop name in the pname to class map table 3850Sstevel@tonic-gate */ 3860Sstevel@tonic-gate static int 3870Sstevel@tonic-gate lookup_pname_type_map(const char *pname, picl_prop_type_t *type) 3880Sstevel@tonic-gate { 3890Sstevel@tonic-gate int i; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate for (i = 0; i < PNAME_MAP_SIZE; ++i) 3920Sstevel@tonic-gate if (strcmp(pname_type_map[i].pname, pname) == 0) { 3930Sstevel@tonic-gate *type = pname_type_map[i].type; 3940Sstevel@tonic-gate return (0); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate return (-1); 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* 4010Sstevel@tonic-gate * Return the number of strings in the buffer 4020Sstevel@tonic-gate */ 4030Sstevel@tonic-gate static int 4040Sstevel@tonic-gate get_string_count(char *strdat, int length) 4050Sstevel@tonic-gate { 4060Sstevel@tonic-gate int count; 4070Sstevel@tonic-gate char *lastnull; 4080Sstevel@tonic-gate char *nullptr; 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate count = 1; 4110Sstevel@tonic-gate for (lastnull = &strdat[length - 1], nullptr = strchr(strdat, '\0'); 4120Sstevel@tonic-gate nullptr != lastnull; nullptr = strchr(nullptr+1, '\0')) 4130Sstevel@tonic-gate count++; 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate return (count); 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate /* 4190Sstevel@tonic-gate * Return 1 if the node has a "reg" property 4200Sstevel@tonic-gate */ 4210Sstevel@tonic-gate static int 4220Sstevel@tonic-gate has_reg_prop(di_node_t dn) 4230Sstevel@tonic-gate { 4240Sstevel@tonic-gate int *pdata; 4250Sstevel@tonic-gate int dret; 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate dret = di_prop_lookup_ints(DDI_DEV_T_ANY, dn, OBP_REG, &pdata); 4280Sstevel@tonic-gate if (dret > 0) 4290Sstevel@tonic-gate return (1); 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate if (!ph) 4320Sstevel@tonic-gate return (0); 4330Sstevel@tonic-gate dret = di_prom_prop_lookup_ints(ph, dn, OBP_REG, &pdata); 4340Sstevel@tonic-gate return (dret < 0 ? 0 : 1); 4350Sstevel@tonic-gate } 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * This function copies a PROM node's device_type property value into the 4390Sstevel@tonic-gate * buffer given by outbuf. The buffer size is PICL_CLASSNAMELEN_MAX. 4400Sstevel@tonic-gate * 4410Sstevel@tonic-gate * We reclassify device_type 'fru-prom' to PICL class 'seeprom' 4420Sstevel@tonic-gate * for FRUID support. 4430Sstevel@tonic-gate */ 4440Sstevel@tonic-gate static int 4450Sstevel@tonic-gate get_device_type(char *outbuf, di_node_t dn) 4460Sstevel@tonic-gate { 4470Sstevel@tonic-gate char *pdata; 4480Sstevel@tonic-gate char *pdatap; 4490Sstevel@tonic-gate int dret; 4500Sstevel@tonic-gate int i; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate dret = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, OBP_DEVICETYPE, 4530Sstevel@tonic-gate &pdata); 4540Sstevel@tonic-gate if (dret <= 0) { 4550Sstevel@tonic-gate if (!ph) 4560Sstevel@tonic-gate return (-1); 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate dret = di_prom_prop_lookup_strings(ph, dn, OBP_DEVICETYPE, 4590Sstevel@tonic-gate &pdata); 4600Sstevel@tonic-gate if (dret <= 0) { 4610Sstevel@tonic-gate return (-1); 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate if (dret != 1) { 4660Sstevel@tonic-gate /* 4670Sstevel@tonic-gate * multiple strings 4680Sstevel@tonic-gate */ 4690Sstevel@tonic-gate pdatap = pdata; 4700Sstevel@tonic-gate for (i = 0; i < (dret - 1); ++i) { 4710Sstevel@tonic-gate pdatap += strlen(pdatap); 4720Sstevel@tonic-gate *pdatap = '-'; /* replace '\0' with '-' */ 4730Sstevel@tonic-gate pdatap++; 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate if (strcasecmp(pdata, "fru-prom") == 0) { 4770Sstevel@tonic-gate /* 4780Sstevel@tonic-gate * Use PICL 'seeprom' class for fru-prom device types 4790Sstevel@tonic-gate */ 4800Sstevel@tonic-gate (void) strlcpy(outbuf, PICL_CLASS_SEEPROM, 4810Sstevel@tonic-gate PICL_CLASSNAMELEN_MAX); 4820Sstevel@tonic-gate } else { 4830Sstevel@tonic-gate (void) strlcpy(outbuf, pdata, PICL_CLASSNAMELEN_MAX); 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate return (0); 4860Sstevel@tonic-gate } 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate /* 4890Sstevel@tonic-gate * Get the minor node name in the class buffer passed 4900Sstevel@tonic-gate */ 4910Sstevel@tonic-gate static int 4920Sstevel@tonic-gate get_minor_class(char *classbuf, di_node_t dn) 4930Sstevel@tonic-gate { 4940Sstevel@tonic-gate di_minor_t mi_node; 4950Sstevel@tonic-gate char *mi_nodetype; 4960Sstevel@tonic-gate char *mi_name; 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate /* get minor node type */ 4990Sstevel@tonic-gate mi_node = di_minor_next(dn, DI_MINOR_NIL); 5000Sstevel@tonic-gate if (mi_node == DI_MINOR_NIL) 5010Sstevel@tonic-gate return (-1); 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate mi_nodetype = di_minor_nodetype(mi_node); 5040Sstevel@tonic-gate if (mi_nodetype == NULL) { /* no type info, return name */ 5050Sstevel@tonic-gate mi_name = di_minor_name(mi_node); 5060Sstevel@tonic-gate if (mi_name == NULL) 5070Sstevel@tonic-gate return (-1); 5080Sstevel@tonic-gate (void) strlcpy(classbuf, mi_name, PICL_CLASSNAMELEN_MAX); 5090Sstevel@tonic-gate return (0); 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate #define DDI_NODETYPE(x, y) (strncmp(x, y, (sizeof (y) - 1)) == 0) 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate /* 5150Sstevel@tonic-gate * convert the string to the picl class for non-peudo nodes 5160Sstevel@tonic-gate */ 5170Sstevel@tonic-gate if (DDI_NODETYPE(mi_nodetype, DDI_PSEUDO)) 5180Sstevel@tonic-gate return (-1); 5190Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_WWN)) 5200Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_BLOCK); 5210Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_CHAN)) 5220Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_BLOCK); 5230Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_CD)) 5240Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_CDROM); 5250Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_CD_CHAN)) 5260Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_CDROM); 5270Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_FD)) 5280Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_FLOPPY); 5290Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK_FABRIC)) 5300Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_FABRIC); 5310Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_BLOCK)) 5320Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_BLOCK); 5330Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_MOUSE)) 5340Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_MOUSE); 5350Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_KEYBOARD)) 5360Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_KEYBOARD); 5370Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_ATTACHMENT_POINT)) 5380Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_ATTACHMENT_POINT); 5390Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_TAPE)) 5400Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_TAPE); 5410Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_SCSI_ENCLOSURE)) 5420Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_SCSI); 5430Sstevel@tonic-gate else if (DDI_NODETYPE(mi_nodetype, DDI_NT_ENCLOSURE)) { 5440Sstevel@tonic-gate char *colon; 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate if ((colon = strchr(mi_nodetype, ':')) == NULL) 5470Sstevel@tonic-gate return (-1); 5480Sstevel@tonic-gate ++colon; 5490Sstevel@tonic-gate (void) strcpy(classbuf, colon); 5500Sstevel@tonic-gate } else { /* unrecognized type, return name */ 5510Sstevel@tonic-gate mi_name = di_minor_name(mi_node); 5520Sstevel@tonic-gate if (mi_name == NULL) 5530Sstevel@tonic-gate return (-1); 5540Sstevel@tonic-gate (void) strlcpy(classbuf, mi_name, PICL_CLASSNAMELEN_MAX); 5550Sstevel@tonic-gate } 5560Sstevel@tonic-gate return (0); 5570Sstevel@tonic-gate } 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate /* 5600Sstevel@tonic-gate * Derive PICL class using the compatible property of the node 5610Sstevel@tonic-gate * We use the map table to map compatible property value to 5620Sstevel@tonic-gate * class. 5630Sstevel@tonic-gate */ 5640Sstevel@tonic-gate static int 5650Sstevel@tonic-gate get_compatible_class(char *outbuf, di_node_t dn) 5660Sstevel@tonic-gate { 5670Sstevel@tonic-gate char *pdata; 5680Sstevel@tonic-gate char *pdatap; 5690Sstevel@tonic-gate int dret; 5700Sstevel@tonic-gate int i; 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate dret = di_prop_lookup_strings(DDI_DEV_T_ANY, dn, OBP_COMPATIBLE, 5730Sstevel@tonic-gate &pdata); 5740Sstevel@tonic-gate if (dret <= 0) { 5750Sstevel@tonic-gate if (!ph) 5760Sstevel@tonic-gate return (-1); 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate dret = di_prom_prop_lookup_strings(ph, dn, OBP_COMPATIBLE, 5790Sstevel@tonic-gate &pdata); 5800Sstevel@tonic-gate if (dret <= 0) { 5810Sstevel@tonic-gate return (-1); 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate pdatap = pdata; 5860Sstevel@tonic-gate for (i = 0; i < dret; ++i) { 5870Sstevel@tonic-gate if (lookup_name_class_map(outbuf, pdatap) == 0) 5880Sstevel@tonic-gate return (0); 5890Sstevel@tonic-gate pdatap += strlen(pdatap); 5900Sstevel@tonic-gate pdatap++; 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate return (-1); 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate /* 5960Sstevel@tonic-gate * For a given device node find the PICL class to use. Returns NULL 5970Sstevel@tonic-gate * for non device node 5980Sstevel@tonic-gate */ 5990Sstevel@tonic-gate static int 6000Sstevel@tonic-gate get_node_class(char *classbuf, di_node_t dn, const char *nodename) 6010Sstevel@tonic-gate { 6020Sstevel@tonic-gate if (get_device_type(classbuf, dn) == 0) { 6030Sstevel@tonic-gate if (di_nodeid(dn) == DI_PROM_NODEID) { 6040Sstevel@tonic-gate /* 6050Sstevel@tonic-gate * discard place holder nodes 6060Sstevel@tonic-gate */ 6070Sstevel@tonic-gate if ((strcmp(classbuf, DEVICE_TYPE_BLOCK) == 0) || 6080Sstevel@tonic-gate (strcmp(classbuf, DEVICE_TYPE_BYTE) == 0) || 6090Sstevel@tonic-gate (strcmp(classbuf, DEVICE_TYPE_SES) == 0) || 6100Sstevel@tonic-gate (strcmp(classbuf, DEVICE_TYPE_FP) == 0) || 6110Sstevel@tonic-gate (strcmp(classbuf, DEVICE_TYPE_DISK) == 0)) 6120Sstevel@tonic-gate return (-1); 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate return (0); 6150Sstevel@tonic-gate } 6160Sstevel@tonic-gate return (0); /* return device_type value */ 6170Sstevel@tonic-gate } 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate if (get_compatible_class(classbuf, dn) == 0) { 6200Sstevel@tonic-gate return (0); /* derive class using compatible prop */ 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate if (lookup_name_class_map(classbuf, nodename) == 0) 6240Sstevel@tonic-gate return (0); /* derive class using name prop */ 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate if (has_reg_prop(dn)) { /* use default obp-device */ 6270Sstevel@tonic-gate (void) strcpy(classbuf, PICL_CLASS_OBP_DEVICE); 6280Sstevel@tonic-gate return (0); 6290Sstevel@tonic-gate } 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate return (get_minor_class(classbuf, dn)); 6320Sstevel@tonic-gate } 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate /* 6350Sstevel@tonic-gate * Add a table property containing nrows with one column 6360Sstevel@tonic-gate */ 6370Sstevel@tonic-gate static int 6380Sstevel@tonic-gate add_string_list_prop(picl_nodehdl_t nodeh, char *name, char *strlist, 6390Sstevel@tonic-gate unsigned int nrows) 6400Sstevel@tonic-gate { 6410Sstevel@tonic-gate ptree_propinfo_t propinfo; 6420Sstevel@tonic-gate picl_prophdl_t proph; 6430Sstevel@tonic-gate picl_prophdl_t tblh; 6440Sstevel@tonic-gate int err; 6450Sstevel@tonic-gate unsigned int i; 6460Sstevel@tonic-gate unsigned int j; 6470Sstevel@tonic-gate picl_prophdl_t *proprow; 6480Sstevel@tonic-gate int len; 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate #define NCOLS_IN_STRING_TABLE 1 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 6530Sstevel@tonic-gate PICL_PTYPE_TABLE, PICL_READ, sizeof (picl_prophdl_t), name, 6540Sstevel@tonic-gate NULL, NULL); 6550Sstevel@tonic-gate if (err != PICL_SUCCESS) 6560Sstevel@tonic-gate return (err); 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate err = ptree_create_table(&tblh); 6590Sstevel@tonic-gate if (err != PICL_SUCCESS) 6600Sstevel@tonic-gate return (err); 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &propinfo, &tblh, &proph); 6630Sstevel@tonic-gate if (err != PICL_SUCCESS) 6640Sstevel@tonic-gate return (err); 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate proprow = alloca(sizeof (picl_prophdl_t) * nrows); 6670Sstevel@tonic-gate if (proprow == NULL) { 6680Sstevel@tonic-gate (void) ptree_destroy_prop(proph); 6690Sstevel@tonic-gate return (PICL_FAILURE); 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate for (j = 0; j < nrows; ++j) { 6730Sstevel@tonic-gate len = strlen(strlist) + 1; 6740Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 6750Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, len, name, 6760Sstevel@tonic-gate NULL, NULL); 6770Sstevel@tonic-gate if (err != PICL_SUCCESS) 6780Sstevel@tonic-gate break; 6790Sstevel@tonic-gate err = ptree_create_prop(&propinfo, strlist, &proprow[j]); 6800Sstevel@tonic-gate if (err != PICL_SUCCESS) 6810Sstevel@tonic-gate break; 6820Sstevel@tonic-gate strlist += len; 6830Sstevel@tonic-gate err = ptree_add_row_to_table(tblh, NCOLS_IN_STRING_TABLE, 6840Sstevel@tonic-gate &proprow[j]); 6850Sstevel@tonic-gate if (err != PICL_SUCCESS) 6860Sstevel@tonic-gate break; 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate if (err != PICL_SUCCESS) { 6900Sstevel@tonic-gate for (i = 0; i < j; ++i) 6910Sstevel@tonic-gate (void) ptree_destroy_prop(proprow[i]); 6920Sstevel@tonic-gate (void) ptree_delete_prop(proph); 6930Sstevel@tonic-gate (void) ptree_destroy_prop(proph); 6940Sstevel@tonic-gate return (err); 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate return (PICL_SUCCESS); 6980Sstevel@tonic-gate } 6990Sstevel@tonic-gate 7000Sstevel@tonic-gate /* 7010Sstevel@tonic-gate * return 1 if this node has this property with the given value 7020Sstevel@tonic-gate */ 7030Sstevel@tonic-gate static int 7040Sstevel@tonic-gate compare_string_propval(picl_nodehdl_t nodeh, const char *pname, 7050Sstevel@tonic-gate const char *pval) 7060Sstevel@tonic-gate { 7070Sstevel@tonic-gate char *pvalbuf; 7080Sstevel@tonic-gate int err; 7090Sstevel@tonic-gate int len; 7100Sstevel@tonic-gate ptree_propinfo_t pinfo; 7110Sstevel@tonic-gate picl_prophdl_t proph; 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, pname, &proph); 7140Sstevel@tonic-gate if (err != PICL_SUCCESS) /* prop doesn't exist */ 7150Sstevel@tonic-gate return (0); 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 7180Sstevel@tonic-gate if (pinfo.piclinfo.type != PICL_PTYPE_CHARSTRING) 7190Sstevel@tonic-gate return (0); /* not string prop */ 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate len = strlen(pval) + 1; 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate pvalbuf = alloca(len); 7240Sstevel@tonic-gate if (pvalbuf == NULL) 7250Sstevel@tonic-gate return (0); 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate err = ptree_get_propval(proph, pvalbuf, len); 7280Sstevel@tonic-gate if ((err == PICL_SUCCESS) && (strcmp(pvalbuf, pval) == 0)) 7290Sstevel@tonic-gate return (1); /* prop match */ 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate return (0); 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate /* 7350Sstevel@tonic-gate * This function recursively searches the tree for a node that has 7360Sstevel@tonic-gate * the specified string property name and value 7370Sstevel@tonic-gate */ 7380Sstevel@tonic-gate static int 7390Sstevel@tonic-gate find_node_by_string_prop(picl_nodehdl_t rooth, const char *pname, 7400Sstevel@tonic-gate const char *pval, picl_nodehdl_t *nodeh) 7410Sstevel@tonic-gate { 7420Sstevel@tonic-gate picl_nodehdl_t childh; 7430Sstevel@tonic-gate int err; 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &childh, 7460Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 7470Sstevel@tonic-gate err = ptree_get_propval_by_name(childh, PICL_PROP_PEER, &childh, 7480Sstevel@tonic-gate sizeof (picl_nodehdl_t))) { 7490Sstevel@tonic-gate if (err != PICL_SUCCESS) 7500Sstevel@tonic-gate return (err); 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate if (compare_string_propval(childh, pname, pval)) { 7530Sstevel@tonic-gate *nodeh = childh; 7540Sstevel@tonic-gate return (PICL_SUCCESS); 7550Sstevel@tonic-gate } 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate if (find_node_by_string_prop(childh, pname, pval, nodeh) == 7580Sstevel@tonic-gate PICL_SUCCESS) 7590Sstevel@tonic-gate return (PICL_SUCCESS); 7600Sstevel@tonic-gate } 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate return (PICL_FAILURE); 7630Sstevel@tonic-gate } 7640Sstevel@tonic-gate 7650Sstevel@tonic-gate /* 7660Sstevel@tonic-gate * check if this is a string prop 7670Sstevel@tonic-gate * If the length is less than or equal to 4, assume it's not a string list. 7680Sstevel@tonic-gate * If there is any non-ascii or non-print char, it's not a string prop 7690Sstevel@tonic-gate * If \0 is in the first char or any two consecutive \0's exist, 7700Sstevel@tonic-gate * it's a bytearray prop. 7710Sstevel@tonic-gate * Return value: 0 means it's not a string prop, 1 means it's a string prop 7720Sstevel@tonic-gate */ 7730Sstevel@tonic-gate static int 7740Sstevel@tonic-gate is_string_propval(unsigned char *pdata, int len) 7750Sstevel@tonic-gate { 7760Sstevel@tonic-gate int i; 7770Sstevel@tonic-gate int lastindex; 7780Sstevel@tonic-gate int prevnull = -1; 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate switch (len) { 7810Sstevel@tonic-gate case 1: 7820Sstevel@tonic-gate if (!isascii(pdata[0]) || !isprint(pdata[0])) 7830Sstevel@tonic-gate return (0); 7840Sstevel@tonic-gate return (1); 7850Sstevel@tonic-gate case 2: 7860Sstevel@tonic-gate case 3: 7870Sstevel@tonic-gate case 4: 7880Sstevel@tonic-gate lastindex = len; 7890Sstevel@tonic-gate if (pdata[len-1] == '\0') 7900Sstevel@tonic-gate lastindex = len - 1; 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate for (i = 0; i < lastindex; i++) 7930Sstevel@tonic-gate if (!isascii(pdata[i]) || !isprint(pdata[i])) 7940Sstevel@tonic-gate return (0); 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate return (1); 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate default: 7990Sstevel@tonic-gate if (len <= 0) 8000Sstevel@tonic-gate return (0); 8010Sstevel@tonic-gate for (i = 0; i < len; i++) { 8020Sstevel@tonic-gate if (!isascii(pdata[i]) || !isprint(pdata[i])) { 8030Sstevel@tonic-gate if (pdata[i] != '\0') 8040Sstevel@tonic-gate return (0); 8050Sstevel@tonic-gate /* 8060Sstevel@tonic-gate * if the null char is in the first char 8070Sstevel@tonic-gate * or two consecutive nulls' exist, 8080Sstevel@tonic-gate * it's a bytearray prop 8090Sstevel@tonic-gate */ 8100Sstevel@tonic-gate if ((i == 0) || ((i - prevnull) == 1)) 8110Sstevel@tonic-gate return (0); 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate prevnull = i; 8140Sstevel@tonic-gate } 8150Sstevel@tonic-gate } 8160Sstevel@tonic-gate break; 8170Sstevel@tonic-gate } 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate return (1); 8200Sstevel@tonic-gate } 8210Sstevel@tonic-gate 8220Sstevel@tonic-gate /* 8230Sstevel@tonic-gate * This function counts the number of strings in the value buffer pdata 8240Sstevel@tonic-gate * and creates a property. 8250Sstevel@tonic-gate * If there is only one string in the buffer, pdata, a charstring property 8260Sstevel@tonic-gate * type is created and added. 8270Sstevel@tonic-gate * If there are more than one string in the buffer, pdata, then a table 8280Sstevel@tonic-gate * of charstrings is added. 8290Sstevel@tonic-gate */ 8300Sstevel@tonic-gate static int 8310Sstevel@tonic-gate process_charstring_data(picl_nodehdl_t nodeh, char *pname, unsigned char *pdata, 8320Sstevel@tonic-gate int retval) 8330Sstevel@tonic-gate { 8340Sstevel@tonic-gate int err; 8350Sstevel@tonic-gate int strcount; 8360Sstevel@tonic-gate char *strdat; 8370Sstevel@tonic-gate ptree_propinfo_t propinfo; 8380Sstevel@tonic-gate 8390Sstevel@tonic-gate /* 8400Sstevel@tonic-gate * append the null char at the end of string when there is 8410Sstevel@tonic-gate * no null terminator 8420Sstevel@tonic-gate */ 8430Sstevel@tonic-gate if (pdata[retval - 1] != '\0') { 8440Sstevel@tonic-gate strdat = alloca(retval + 1); 8450Sstevel@tonic-gate (void) memcpy(strdat, pdata, retval); 8460Sstevel@tonic-gate strdat[retval] = '\0'; 8470Sstevel@tonic-gate retval++; 8480Sstevel@tonic-gate } else { 8490Sstevel@tonic-gate strdat = alloca(retval); 8500Sstevel@tonic-gate (void) memcpy(strdat, pdata, retval); 8510Sstevel@tonic-gate } 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate /* 8540Sstevel@tonic-gate * If it's a string list, create a table prop 8550Sstevel@tonic-gate */ 8560Sstevel@tonic-gate strcount = get_string_count(strdat, retval); 8570Sstevel@tonic-gate if (strcount > 1) { 8580Sstevel@tonic-gate err = add_string_list_prop(nodeh, pname, 8590Sstevel@tonic-gate strdat, strcount); 8600Sstevel@tonic-gate if (err != PICL_SUCCESS) 8610Sstevel@tonic-gate return (err); 8620Sstevel@tonic-gate } else { 8630Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 8640Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 8650Sstevel@tonic-gate strlen(strdat) + 1, pname, NULL, 8660Sstevel@tonic-gate NULL); 8670Sstevel@tonic-gate if (err != PICL_SUCCESS) 8680Sstevel@tonic-gate return (err); 8690Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, 8700Sstevel@tonic-gate strdat, NULL); 8710Sstevel@tonic-gate } 8720Sstevel@tonic-gate return (PICL_SUCCESS); 8730Sstevel@tonic-gate } 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate /* 8760Sstevel@tonic-gate * Add the OBP properties as properties of the PICL node 8770Sstevel@tonic-gate */ 8780Sstevel@tonic-gate static int 8790Sstevel@tonic-gate add_openprom_props(picl_nodehdl_t nodeh, di_node_t di_node) 8800Sstevel@tonic-gate { 8810Sstevel@tonic-gate di_prom_prop_t promp; 8820Sstevel@tonic-gate char *pname; 8830Sstevel@tonic-gate unsigned char *pdata; 8840Sstevel@tonic-gate int retval; 8850Sstevel@tonic-gate ptree_propinfo_t propinfo; 8860Sstevel@tonic-gate int err; 8870Sstevel@tonic-gate picl_prop_type_t type; 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate if (!ph) 8900Sstevel@tonic-gate return (PICL_FAILURE); 8910Sstevel@tonic-gate 8920Sstevel@tonic-gate for (promp = di_prom_prop_next(ph, di_node, DI_PROM_PROP_NIL); 8930Sstevel@tonic-gate promp != DI_PROM_PROP_NIL; 8940Sstevel@tonic-gate promp = di_prom_prop_next(ph, di_node, promp)) { 8950Sstevel@tonic-gate 8960Sstevel@tonic-gate pname = di_prom_prop_name(promp); 8970Sstevel@tonic-gate 8980Sstevel@tonic-gate retval = di_prom_prop_data(promp, &pdata); 8990Sstevel@tonic-gate if (retval < 0) { 9000Sstevel@tonic-gate return (PICL_SUCCESS); 9010Sstevel@tonic-gate } 9020Sstevel@tonic-gate if (retval == 0) { 9030Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, 9040Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID, 9050Sstevel@tonic-gate PICL_READ, (size_t)0, pname, NULL, NULL); 9060Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9070Sstevel@tonic-gate return (err); 9080Sstevel@tonic-gate } 9090Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, 9100Sstevel@tonic-gate NULL); 9110Sstevel@tonic-gate continue; 9120Sstevel@tonic-gate } 9130Sstevel@tonic-gate 9140Sstevel@tonic-gate /* 9150Sstevel@tonic-gate * Get the prop type from pname map table 9160Sstevel@tonic-gate */ 9170Sstevel@tonic-gate if (lookup_pname_type_map(pname, &type) == 0) { 9180Sstevel@tonic-gate if (type == PICL_PTYPE_CHARSTRING) { 9190Sstevel@tonic-gate err = process_charstring_data(nodeh, pname, 9200Sstevel@tonic-gate pdata, retval); 9210Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9220Sstevel@tonic-gate return (err); 9230Sstevel@tonic-gate } 9240Sstevel@tonic-gate continue; 9250Sstevel@tonic-gate } 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, 9280Sstevel@tonic-gate PTREE_PROPINFO_VERSION, type, PICL_READ, 9290Sstevel@tonic-gate retval, pname, NULL, NULL); 9300Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9310Sstevel@tonic-gate return (err); 9320Sstevel@tonic-gate } 9330Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, 9340Sstevel@tonic-gate pdata, NULL); 9350Sstevel@tonic-gate } else if (!is_string_propval(pdata, retval)) { 9360Sstevel@tonic-gate switch (retval) { 9370Sstevel@tonic-gate case sizeof (uint8_t): 9380Sstevel@tonic-gate /*FALLTHROUGH*/ 9390Sstevel@tonic-gate case sizeof (uint16_t): 9400Sstevel@tonic-gate /*FALLTHROUGH*/ 9410Sstevel@tonic-gate case sizeof (uint32_t): 9420Sstevel@tonic-gate type = PICL_PTYPE_UNSIGNED_INT; 9430Sstevel@tonic-gate break; 9440Sstevel@tonic-gate default: 9450Sstevel@tonic-gate type = PICL_PTYPE_BYTEARRAY; 9460Sstevel@tonic-gate break; 9470Sstevel@tonic-gate } 9480Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, 9490Sstevel@tonic-gate PTREE_PROPINFO_VERSION, type, PICL_READ, 9500Sstevel@tonic-gate retval, pname, NULL, NULL); 9510Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9520Sstevel@tonic-gate return (err); 9530Sstevel@tonic-gate } 9540Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, 9550Sstevel@tonic-gate pdata, NULL); 9560Sstevel@tonic-gate } else { 9570Sstevel@tonic-gate err = process_charstring_data(nodeh, pname, pdata, 9580Sstevel@tonic-gate retval); 9590Sstevel@tonic-gate if (err != PICL_SUCCESS) { 9600Sstevel@tonic-gate return (err); 9610Sstevel@tonic-gate } 9620Sstevel@tonic-gate } 9630Sstevel@tonic-gate } 9640Sstevel@tonic-gate 9650Sstevel@tonic-gate return (PICL_SUCCESS); 9660Sstevel@tonic-gate } 9670Sstevel@tonic-gate 9683343Srd117015 static void 9693343Srd117015 add_boolean_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val) 9703343Srd117015 { 9713343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 9723343Srd117015 PICL_PTYPE_VOID, PICL_READ, (size_t)0, di_val, NULL, NULL); 9733343Srd117015 (void) ptree_create_and_add_prop(nodeh, &propinfo, NULL, NULL); 9743343Srd117015 } 9753343Srd117015 9763343Srd117015 static void 9773343Srd117015 add_uints_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val, 9783343Srd117015 int *idata, int len) 9793343Srd117015 { 9803343Srd117015 if (len == 1) 9813343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 9823343Srd117015 PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (int), di_val, 9833343Srd117015 NULL, NULL); 9843343Srd117015 else 9853343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 9863343Srd117015 PICL_PTYPE_BYTEARRAY, PICL_READ, len * sizeof (int), di_val, 9873343Srd117015 NULL, NULL); 9883343Srd117015 9893343Srd117015 (void) ptree_create_and_add_prop(nodeh, &propinfo, idata, NULL); 9903343Srd117015 } 9913343Srd117015 9923343Srd117015 static void 9933343Srd117015 add_strings_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val, 9943343Srd117015 char *sdata, int len) 9953343Srd117015 { 9963343Srd117015 if (len == 1) { 9973343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 9983343Srd117015 PICL_PTYPE_CHARSTRING, PICL_READ, strlen(sdata) + 1, di_val, 9993343Srd117015 NULL, NULL); 10003343Srd117015 (void) ptree_create_and_add_prop(nodeh, &propinfo, sdata, NULL); 10013343Srd117015 } else { 10023343Srd117015 (void) add_string_list_prop(nodeh, di_val, sdata, len); 10033343Srd117015 } 10043343Srd117015 } 10053343Srd117015 10063343Srd117015 static void 10073343Srd117015 add_bytes_prop(picl_nodehdl_t nodeh, ptree_propinfo_t propinfo, char *di_val, 10083343Srd117015 unsigned char *bdata, int len) 10093343Srd117015 { 10103343Srd117015 (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10113343Srd117015 PICL_PTYPE_BYTEARRAY, PICL_READ, len, di_val, NULL, NULL); 10123343Srd117015 (void) ptree_create_and_add_prop(nodeh, &propinfo, bdata, NULL); 10133343Srd117015 } 10143343Srd117015 10150Sstevel@tonic-gate /* 10160Sstevel@tonic-gate * Add properties provided by libdevinfo 10170Sstevel@tonic-gate */ 10180Sstevel@tonic-gate static void 10190Sstevel@tonic-gate add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node) 10200Sstevel@tonic-gate { 10210Sstevel@tonic-gate int instance; 10220Sstevel@tonic-gate char *di_val; 10230Sstevel@tonic-gate di_prop_t di_prop; 10240Sstevel@tonic-gate int di_ptype; 10250Sstevel@tonic-gate ptree_propinfo_t propinfo; 10263343Srd117015 char *sdata; 10273343Srd117015 unsigned char *bdata; 10283343Srd117015 int *idata; 10293343Srd117015 int len; 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate instance = di_instance(di_node); 10320Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10330Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE, 10340Sstevel@tonic-gate NULL, NULL); 10350Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL); 10360Sstevel@tonic-gate 10370Sstevel@tonic-gate di_val = di_bus_addr(di_node); 10380Sstevel@tonic-gate if (di_val) { 10390Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10400Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 10410Sstevel@tonic-gate PICL_PROP_BUS_ADDR, NULL, NULL); 10420Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 10430Sstevel@tonic-gate NULL); 10440Sstevel@tonic-gate } 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate di_val = di_binding_name(di_node); 10470Sstevel@tonic-gate if (di_val) { 10480Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10490Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 10500Sstevel@tonic-gate PICL_PROP_BINDING_NAME, NULL, NULL); 10510Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 10520Sstevel@tonic-gate NULL); 10530Sstevel@tonic-gate } 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate di_val = di_driver_name(di_node); 10560Sstevel@tonic-gate if (di_val) { 10570Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10580Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 10590Sstevel@tonic-gate PICL_PROP_DRIVER_NAME, NULL, NULL); 10600Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 10610Sstevel@tonic-gate NULL); 10620Sstevel@tonic-gate } 10630Sstevel@tonic-gate 10640Sstevel@tonic-gate di_val = di_devfs_path(di_node); 10650Sstevel@tonic-gate if (di_val) { 10660Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 10670Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1, 10680Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, NULL, NULL); 10690Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &propinfo, di_val, 10700Sstevel@tonic-gate NULL); 10710Sstevel@tonic-gate di_devfs_path_free(di_val); 10720Sstevel@tonic-gate } 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate for (di_prop = di_prop_next(di_node, DI_PROP_NIL); 10750Sstevel@tonic-gate di_prop != DI_PROP_NIL; 10760Sstevel@tonic-gate di_prop = di_prop_next(di_node, di_prop)) { 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate di_val = di_prop_name(di_prop); 10790Sstevel@tonic-gate di_ptype = di_prop_type(di_prop); 10803343Srd117015 10810Sstevel@tonic-gate switch (di_ptype) { 10820Sstevel@tonic-gate case DI_PROP_TYPE_BOOLEAN: 10833343Srd117015 add_boolean_prop(nodeh, propinfo, di_val); 10840Sstevel@tonic-gate break; 10853343Srd117015 case DI_PROP_TYPE_INT: 10860Sstevel@tonic-gate len = di_prop_ints(di_prop, &idata); 10870Sstevel@tonic-gate if (len < 0) 10883343Srd117015 /* Received error, so ignore prop */ 10890Sstevel@tonic-gate break; 10903343Srd117015 add_uints_prop(nodeh, propinfo, di_val, idata, len); 10913343Srd117015 break; 10923343Srd117015 case DI_PROP_TYPE_STRING: 10930Sstevel@tonic-gate len = di_prop_strings(di_prop, &sdata); 10940Sstevel@tonic-gate if (len < 0) 10950Sstevel@tonic-gate break; 10963343Srd117015 add_strings_prop(nodeh, propinfo, di_val, sdata, len); 10973343Srd117015 break; 10983343Srd117015 case DI_PROP_TYPE_BYTE: 10990Sstevel@tonic-gate len = di_prop_bytes(di_prop, &bdata); 11000Sstevel@tonic-gate if (len < 0) 11010Sstevel@tonic-gate break; 11023343Srd117015 add_bytes_prop(nodeh, propinfo, di_val, bdata, len); 11033343Srd117015 break; 11040Sstevel@tonic-gate case DI_PROP_TYPE_UNKNOWN: 11053343Srd117015 /* 11063343Srd117015 * Unknown type, we'll try and guess what it should be. 11073343Srd117015 */ 11083343Srd117015 len = di_prop_strings(di_prop, &sdata); 11093343Srd117015 if ((len > 0) && (sdata[0] != 0)) { 11103343Srd117015 add_strings_prop(nodeh, propinfo, di_val, sdata, 11113343Srd117015 len); 11123343Srd117015 break; 11133343Srd117015 } 11143343Srd117015 len = di_prop_ints(di_prop, &idata); 11153343Srd117015 if (len > 0) { 11163343Srd117015 add_uints_prop(nodeh, propinfo, di_val, 11173343Srd117015 idata, len); 11183343Srd117015 break; 11193343Srd117015 } 11203343Srd117015 len = di_prop_rawdata(di_prop, &bdata); 11213343Srd117015 if (len > 0) 11223343Srd117015 add_bytes_prop(nodeh, propinfo, 11233343Srd117015 di_val, bdata, len); 11243343Srd117015 else if (len == 0) 11253343Srd117015 add_boolean_prop(nodeh, propinfo, 11263343Srd117015 di_val); 11270Sstevel@tonic-gate break; 11280Sstevel@tonic-gate case DI_PROP_TYPE_UNDEF_IT: 11290Sstevel@tonic-gate break; 11300Sstevel@tonic-gate default: 11310Sstevel@tonic-gate break; 11320Sstevel@tonic-gate } 11330Sstevel@tonic-gate } 11340Sstevel@tonic-gate } 11350Sstevel@tonic-gate 11360Sstevel@tonic-gate /* 11370Sstevel@tonic-gate * This function creates the /obp node in the PICL tree for OBP nodes 11380Sstevel@tonic-gate * without a device type class. 11390Sstevel@tonic-gate */ 11400Sstevel@tonic-gate static int 11410Sstevel@tonic-gate construct_picl_openprom(picl_nodehdl_t rooth, picl_nodehdl_t *obph) 11420Sstevel@tonic-gate { 11430Sstevel@tonic-gate picl_nodehdl_t tmph; 11440Sstevel@tonic-gate int err; 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate err = ptree_create_and_add_node(rooth, PICL_NODE_OBP, 11470Sstevel@tonic-gate PICL_CLASS_PICL, &tmph); 11480Sstevel@tonic-gate 11490Sstevel@tonic-gate if (err != PICL_SUCCESS) 11500Sstevel@tonic-gate return (err); 11510Sstevel@tonic-gate *obph = tmph; 11520Sstevel@tonic-gate return (PICL_SUCCESS); 11530Sstevel@tonic-gate } 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate /* 11560Sstevel@tonic-gate * This function creates the /platform node in the PICL tree and 11570Sstevel@tonic-gate * its properties. It sets the "platform-name" property to the 11580Sstevel@tonic-gate * platform name 11590Sstevel@tonic-gate */ 11600Sstevel@tonic-gate static int 11610Sstevel@tonic-gate construct_picl_platform(picl_nodehdl_t rooth, di_node_t di_root, 11620Sstevel@tonic-gate picl_nodehdl_t *piclh) 11630Sstevel@tonic-gate { 11640Sstevel@tonic-gate int err; 11650Sstevel@tonic-gate picl_nodehdl_t plafh; 11660Sstevel@tonic-gate char *nodename; 11670Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 11680Sstevel@tonic-gate ptree_propinfo_t propinfo; 11690Sstevel@tonic-gate picl_prophdl_t proph; 11700Sstevel@tonic-gate 11710Sstevel@tonic-gate nodename = di_node_name(di_root); 11720Sstevel@tonic-gate if (nodename == NULL) 11730Sstevel@tonic-gate return (PICL_FAILURE); 11740Sstevel@tonic-gate 11750Sstevel@tonic-gate err = 0; 11760Sstevel@tonic-gate if (di_nodeid(di_root) == DI_PROM_NODEID || 11770Sstevel@tonic-gate di_nodeid(di_root) == DI_SID_NODEID) 11780Sstevel@tonic-gate err = get_device_type(nodeclass, di_root); 11790Sstevel@tonic-gate 11800Sstevel@tonic-gate if (err < 0) 11810Sstevel@tonic-gate (void) strcpy(nodeclass, PICL_CLASS_UPA); /* default */ 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate err = ptree_create_and_add_node(rooth, PICL_NODE_PLATFORM, 11840Sstevel@tonic-gate nodeclass, &plafh); 11850Sstevel@tonic-gate if (err != PICL_SUCCESS) 11860Sstevel@tonic-gate return (err); 11870Sstevel@tonic-gate 11880Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 11890Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(nodename) + 1, 11900Sstevel@tonic-gate PICL_PROP_PLATFORM_NAME, NULL, NULL); 11910Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, nodename, &proph); 11920Sstevel@tonic-gate if (err != PICL_SUCCESS) 11930Sstevel@tonic-gate return (err); 11940Sstevel@tonic-gate 11950Sstevel@tonic-gate (void) add_devinfo_props(plafh, di_root); 11960Sstevel@tonic-gate 11970Sstevel@tonic-gate (void) add_openprom_props(plafh, di_root); 11980Sstevel@tonic-gate 11990Sstevel@tonic-gate *piclh = plafh; 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate return (PICL_SUCCESS); 12020Sstevel@tonic-gate } 12030Sstevel@tonic-gate 12040Sstevel@tonic-gate /* 12050Sstevel@tonic-gate * This function creates a node in /obp tree for the libdevinfo handle. 12060Sstevel@tonic-gate */ 12070Sstevel@tonic-gate static int 12080Sstevel@tonic-gate construct_obp_node(picl_nodehdl_t parh, di_node_t dn, picl_nodehdl_t *chdh) 12090Sstevel@tonic-gate { 12100Sstevel@tonic-gate int err; 12110Sstevel@tonic-gate char *nodename; 12120Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 12130Sstevel@tonic-gate picl_nodehdl_t anodeh; 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate nodename = di_node_name(dn); /* PICL_PROP_NAME */ 12160Sstevel@tonic-gate if (nodename == NULL) 12170Sstevel@tonic-gate return (PICL_FAILURE); 12180Sstevel@tonic-gate 12190Sstevel@tonic-gate if (strcmp(nodename, "pseudo") == 0) 12200Sstevel@tonic-gate return (PICL_FAILURE); 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate if ((di_nodeid(dn) == DI_PROM_NODEID) && 12230Sstevel@tonic-gate (get_device_type(nodeclass, dn) == 0)) 12240Sstevel@tonic-gate return (PICL_FAILURE); 12250Sstevel@tonic-gate 12260Sstevel@tonic-gate err = ptree_create_and_add_node(parh, nodename, nodename, &anodeh); 12270Sstevel@tonic-gate if (err != PICL_SUCCESS) 12280Sstevel@tonic-gate return (err); 12290Sstevel@tonic-gate 12300Sstevel@tonic-gate add_devinfo_props(anodeh, dn); 12310Sstevel@tonic-gate 12320Sstevel@tonic-gate (void) add_openprom_props(anodeh, dn); 12330Sstevel@tonic-gate 12340Sstevel@tonic-gate *chdh = anodeh; 12350Sstevel@tonic-gate 12360Sstevel@tonic-gate return (PICL_SUCCESS); 12370Sstevel@tonic-gate } 12380Sstevel@tonic-gate 12390Sstevel@tonic-gate /* 12400Sstevel@tonic-gate * This function creates a PICL node in /platform tree for a device 12410Sstevel@tonic-gate */ 12420Sstevel@tonic-gate static int 12430Sstevel@tonic-gate construct_devtype_node(picl_nodehdl_t parh, char *nodename, 12440Sstevel@tonic-gate char *nodeclass, di_node_t dn, picl_nodehdl_t *chdh) 12450Sstevel@tonic-gate { 12460Sstevel@tonic-gate int err; 12470Sstevel@tonic-gate picl_nodehdl_t anodeh; 12480Sstevel@tonic-gate 12490Sstevel@tonic-gate err = ptree_create_and_add_node(parh, nodename, nodeclass, &anodeh); 12500Sstevel@tonic-gate if (err != PICL_SUCCESS) 12510Sstevel@tonic-gate return (err); 12520Sstevel@tonic-gate 12530Sstevel@tonic-gate (void) add_devinfo_props(anodeh, dn); 12540Sstevel@tonic-gate (void) add_openprom_props(anodeh, dn); 12550Sstevel@tonic-gate 12560Sstevel@tonic-gate *chdh = anodeh; 12570Sstevel@tonic-gate return (err); 12580Sstevel@tonic-gate } 12590Sstevel@tonic-gate 12600Sstevel@tonic-gate /* 12610Sstevel@tonic-gate * Create a subtree of "picl" class nodes in /obp for these nodes 12620Sstevel@tonic-gate */ 12630Sstevel@tonic-gate static int 12640Sstevel@tonic-gate construct_openprom_tree(picl_nodehdl_t nodeh, di_node_t dinode) 12650Sstevel@tonic-gate { 12660Sstevel@tonic-gate di_node_t cnode; 12670Sstevel@tonic-gate picl_nodehdl_t chdh; 12680Sstevel@tonic-gate int err; 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate err = construct_obp_node(nodeh, dinode, &chdh); 12710Sstevel@tonic-gate if (err != PICL_SUCCESS) 12720Sstevel@tonic-gate return (err); 12730Sstevel@tonic-gate 12740Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 12750Sstevel@tonic-gate cnode = di_sibling_node(cnode)) 12760Sstevel@tonic-gate (void) construct_openprom_tree(chdh, cnode); 12770Sstevel@tonic-gate 12780Sstevel@tonic-gate return (PICL_SUCCESS); 12790Sstevel@tonic-gate 12800Sstevel@tonic-gate } 12810Sstevel@tonic-gate 12820Sstevel@tonic-gate /* 12830Sstevel@tonic-gate * Process the libdevinfo device tree and create nodes in /platform or /obp 12840Sstevel@tonic-gate * PICL tree. 12850Sstevel@tonic-gate * 12860Sstevel@tonic-gate * This routine traverses the immediate children of "dinode" device and 12870Sstevel@tonic-gate * determines the node class for that child. If it finds a valid class 12880Sstevel@tonic-gate * name, then it builds a PICL node under /platform subtree and calls itself 12890Sstevel@tonic-gate * recursively to construct the subtree for that child node. Otherwise, if 12900Sstevel@tonic-gate * the parent_class is NULL, then it constructs a node and subtree under /obp 12910Sstevel@tonic-gate * subtree. 12920Sstevel@tonic-gate * 12930Sstevel@tonic-gate * Note that we skip the children nodes that don't have a valid class name 12940Sstevel@tonic-gate * and the parent_class is non NULL to prevent creation of any placeholder 12950Sstevel@tonic-gate * nodes (such as sd,...). 12960Sstevel@tonic-gate */ 12970Sstevel@tonic-gate static int 12980Sstevel@tonic-gate construct_devinfo_tree(picl_nodehdl_t plafh, picl_nodehdl_t obph, 12990Sstevel@tonic-gate di_node_t dinode, char *parent_class) 13000Sstevel@tonic-gate { 13010Sstevel@tonic-gate di_node_t cnode; 13020Sstevel@tonic-gate picl_nodehdl_t chdh; 13030Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 13040Sstevel@tonic-gate char *nodename; 13050Sstevel@tonic-gate int err; 13060Sstevel@tonic-gate 13070Sstevel@tonic-gate err = PICL_SUCCESS; 13080Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 13090Sstevel@tonic-gate cnode = di_sibling_node(cnode)) { 13100Sstevel@tonic-gate nodename = di_node_name(cnode); /* PICL_PROP_NAME */ 13110Sstevel@tonic-gate if (nodename == NULL) 13120Sstevel@tonic-gate continue; 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate err = get_node_class(nodeclass, cnode, nodename); 13150Sstevel@tonic-gate 13160Sstevel@tonic-gate if (err == 0) { 13170Sstevel@tonic-gate err = construct_devtype_node(plafh, nodename, 13180Sstevel@tonic-gate nodeclass, cnode, &chdh); 13190Sstevel@tonic-gate if (err != PICL_SUCCESS) 13200Sstevel@tonic-gate return (err); 13210Sstevel@tonic-gate err = construct_devinfo_tree(chdh, obph, cnode, 13220Sstevel@tonic-gate nodeclass); 13230Sstevel@tonic-gate } else if (parent_class == NULL) 13240Sstevel@tonic-gate err = construct_openprom_tree(obph, cnode); 13250Sstevel@tonic-gate else 13260Sstevel@tonic-gate continue; 13270Sstevel@tonic-gate /* 13280Sstevel@tonic-gate * if parent_class is non NULL, skip the children nodes 13290Sstevel@tonic-gate * that don't have a valid device class - eliminates 13300Sstevel@tonic-gate * placeholder nodes (sd,...) from being created. 13310Sstevel@tonic-gate */ 13320Sstevel@tonic-gate } 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate return (err); 13350Sstevel@tonic-gate 13360Sstevel@tonic-gate } 13370Sstevel@tonic-gate 13380Sstevel@tonic-gate /* 13390Sstevel@tonic-gate * This function is called from the event handler called from the daemon 13400Sstevel@tonic-gate * on PICL events. 13410Sstevel@tonic-gate * 13420Sstevel@tonic-gate * This routine traverses the children of the "dinode" device and 13430Sstevel@tonic-gate * creates a PICL node for each child not found in the PICL tree and 13440Sstevel@tonic-gate * invokes itself recursively to create a subtree for the newly created 13450Sstevel@tonic-gate * child node. It also checks if the node being created is a meory 13460Sstevel@tonic-gate * controller. If so, it posts PICLEVENT_MC_ADDED PICL event to the PICL 13470Sstevel@tonic-gate * framework. 13480Sstevel@tonic-gate */ 13490Sstevel@tonic-gate static int 13500Sstevel@tonic-gate update_subtree(picl_nodehdl_t nodeh, di_node_t dinode) 13510Sstevel@tonic-gate { 13520Sstevel@tonic-gate di_node_t cnode; 13530Sstevel@tonic-gate picl_nodehdl_t chdh; 13540Sstevel@tonic-gate picl_nodehdl_t nh; 13550Sstevel@tonic-gate char *nodename; 13560Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 13570Sstevel@tonic-gate char *path_buf; 13580Sstevel@tonic-gate char buf[MAX_UNIT_ADDRESS_LEN]; 13590Sstevel@tonic-gate char unitaddr[MAX_UNIT_ADDRESS_LEN]; 13600Sstevel@tonic-gate char path_w_ua[MAXPATHLEN]; 13610Sstevel@tonic-gate char path_wo_ua[MAXPATHLEN]; 13620Sstevel@tonic-gate char *strp; 13630Sstevel@tonic-gate int gotit; 13640Sstevel@tonic-gate int err; 13650Sstevel@tonic-gate 13660Sstevel@tonic-gate for (cnode = di_child_node(dinode); cnode != DI_NODE_NIL; 13670Sstevel@tonic-gate cnode = di_sibling_node(cnode)) { 13680Sstevel@tonic-gate path_buf = di_devfs_path(cnode); 13690Sstevel@tonic-gate if (path_buf == NULL) 13700Sstevel@tonic-gate continue; 13710Sstevel@tonic-gate 13720Sstevel@tonic-gate nodename = di_node_name(cnode); 13730Sstevel@tonic-gate if (nodename == NULL) { 13740Sstevel@tonic-gate di_devfs_path_free(path_buf); 13750Sstevel@tonic-gate continue; 13760Sstevel@tonic-gate } 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate err = get_node_class(nodeclass, cnode, nodename); 13790Sstevel@tonic-gate 13800Sstevel@tonic-gate if (err < 0) { 13810Sstevel@tonic-gate di_devfs_path_free(path_buf); 13820Sstevel@tonic-gate continue; 13830Sstevel@tonic-gate } 13840Sstevel@tonic-gate 13850Sstevel@tonic-gate /* 13860Sstevel@tonic-gate * this is quite complicated - both path_buf and any nodes 13870Sstevel@tonic-gate * already in the picl tree may, or may not, have the 13880Sstevel@tonic-gate * @<unit_addr> at the end of their names. So we must 13890Sstevel@tonic-gate * take path_buf and work out what the device path would 13900Sstevel@tonic-gate * be both with and without the unit_address, then search 13910Sstevel@tonic-gate * the picl tree for both forms. 13920Sstevel@tonic-gate */ 13930Sstevel@tonic-gate if (((strp = strrchr(path_buf, '/')) != NULL) && 13940Sstevel@tonic-gate strchr(strp, '@') == NULL) { 13950Sstevel@tonic-gate /* 13960Sstevel@tonic-gate * this is an unattached node - so the path is not 13970Sstevel@tonic-gate * unique. Need to find out which node it is. 13980Sstevel@tonic-gate * Find the unit_address from the obp properties. 13990Sstevel@tonic-gate */ 14000Sstevel@tonic-gate err = ptree_create_node(nodename, nodeclass, &chdh); 14010Sstevel@tonic-gate if (err != PICL_SUCCESS) 14020Sstevel@tonic-gate return (err); 14030Sstevel@tonic-gate (void) add_openprom_props(chdh, cnode); 14040Sstevel@tonic-gate err = get_unitaddr(nodeh, chdh, unitaddr, 14050Sstevel@tonic-gate sizeof (unitaddr)); 14060Sstevel@tonic-gate if (err != PICL_SUCCESS) 14070Sstevel@tonic-gate return (err); 14080Sstevel@tonic-gate (void) ptree_destroy_node(chdh); 14090Sstevel@tonic-gate (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s@%s", 14100Sstevel@tonic-gate path_buf, unitaddr); 14110Sstevel@tonic-gate (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s", 14120Sstevel@tonic-gate path_buf); 14130Sstevel@tonic-gate } else { 14140Sstevel@tonic-gate /* 14150Sstevel@tonic-gate * this is an attached node - so the path is unique 14160Sstevel@tonic-gate */ 14170Sstevel@tonic-gate (void) snprintf(path_w_ua, sizeof (path_w_ua), "%s", 14180Sstevel@tonic-gate path_buf); 14190Sstevel@tonic-gate (void) snprintf(path_wo_ua, sizeof (path_wo_ua), "%s", 14200Sstevel@tonic-gate path_buf); 14210Sstevel@tonic-gate strp = strrchr(path_wo_ua, '@'); 14220Sstevel@tonic-gate *strp++ = '\0'; 14230Sstevel@tonic-gate (void) snprintf(unitaddr, sizeof (unitaddr), "%s", 14240Sstevel@tonic-gate strp); 14250Sstevel@tonic-gate } 14260Sstevel@tonic-gate /* 14270Sstevel@tonic-gate * first look for node with unit address in devfs_path 14280Sstevel@tonic-gate */ 14290Sstevel@tonic-gate if (ptree_find_node(nodeh, PICL_PROP_DEVFS_PATH, 14300Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, path_w_ua, strlen(path_w_ua) + 1, 14310Sstevel@tonic-gate &nh) == PICL_SUCCESS) { 14320Sstevel@tonic-gate /* 14330Sstevel@tonic-gate * node already there - there's nothing we need to do 14340Sstevel@tonic-gate */ 14350Sstevel@tonic-gate if (picldevtree_debug > 1) 14360Sstevel@tonic-gate syslog(LOG_INFO, 14370Sstevel@tonic-gate "update_subtree: path:%s node exists\n", 14380Sstevel@tonic-gate path_buf); 14390Sstevel@tonic-gate di_devfs_path_free(path_buf); 14400Sstevel@tonic-gate continue; 14410Sstevel@tonic-gate } 14420Sstevel@tonic-gate /* 14430Sstevel@tonic-gate * now look for node without unit address in devfs_path. 14440Sstevel@tonic-gate * This might be just one out of several 14450Sstevel@tonic-gate * nodes - need to check all siblings 14460Sstevel@tonic-gate */ 14470Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, 14480Sstevel@tonic-gate &chdh, sizeof (chdh)); 14490Sstevel@tonic-gate if ((err != PICL_SUCCESS) && (err != PICL_PROPNOTFOUND)) 14500Sstevel@tonic-gate return (err); 14510Sstevel@tonic-gate gotit = 0; 14520Sstevel@tonic-gate while (err == PICL_SUCCESS) { 14530Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 14540Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, buf, sizeof (buf)); 14550Sstevel@tonic-gate if (err != PICL_SUCCESS) 14560Sstevel@tonic-gate return (err); 14570Sstevel@tonic-gate if (strcmp(buf, path_wo_ua) == 0) { 14580Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 14590Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, buf, sizeof (buf)); 14600Sstevel@tonic-gate if (err != PICL_SUCCESS) 14610Sstevel@tonic-gate return (err); 14620Sstevel@tonic-gate if (strcmp(buf, unitaddr) == 0) { 14630Sstevel@tonic-gate gotit = 1; 14640Sstevel@tonic-gate break; 14650Sstevel@tonic-gate } 14660Sstevel@tonic-gate } 14670Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 14680Sstevel@tonic-gate PICL_PROP_PEER, &chdh, sizeof (chdh)); 14690Sstevel@tonic-gate if (err != PICL_SUCCESS) 14700Sstevel@tonic-gate break; 14710Sstevel@tonic-gate } 14720Sstevel@tonic-gate if (gotit) { 14730Sstevel@tonic-gate /* 14740Sstevel@tonic-gate * node already there - there's nothing we need to do 14750Sstevel@tonic-gate */ 14760Sstevel@tonic-gate if (picldevtree_debug > 1) 14770Sstevel@tonic-gate syslog(LOG_INFO, 14780Sstevel@tonic-gate "update_subtree: path:%s node exists\n", 14790Sstevel@tonic-gate path_buf); 14800Sstevel@tonic-gate di_devfs_path_free(path_buf); 14810Sstevel@tonic-gate continue; 14820Sstevel@tonic-gate } 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate #define IS_MC(x) (strcmp(x, PICL_CLASS_MEMORY_CONTROLLER) == 0 ? 1 : 0) 14850Sstevel@tonic-gate 14860Sstevel@tonic-gate if (construct_devtype_node(nodeh, nodename, nodeclass, cnode, 14870Sstevel@tonic-gate &chdh) == PICL_SUCCESS) { 14880Sstevel@tonic-gate if (picldevtree_debug) 14890Sstevel@tonic-gate syslog(LOG_INFO, 14900Sstevel@tonic-gate "picldevtree: added node:%s path:%s\n", 14910Sstevel@tonic-gate nodename, path_buf); 14920Sstevel@tonic-gate if (IS_MC(nodeclass)) { 14930Sstevel@tonic-gate if (post_mc_event(PICLEVENT_MC_ADDED, chdh) != 14940Sstevel@tonic-gate PICL_SUCCESS) 14950Sstevel@tonic-gate syslog(LOG_WARNING, PICL_EVENT_DROPPED, 14960Sstevel@tonic-gate PICLEVENT_MC_ADDED); 14970Sstevel@tonic-gate } 14980Sstevel@tonic-gate 14990Sstevel@tonic-gate di_devfs_path_free(path_buf); 15000Sstevel@tonic-gate (void) update_subtree(chdh, cnode); 15010Sstevel@tonic-gate } 15020Sstevel@tonic-gate } 15030Sstevel@tonic-gate 15040Sstevel@tonic-gate return (PICL_SUCCESS); 15050Sstevel@tonic-gate 15060Sstevel@tonic-gate } 15070Sstevel@tonic-gate 15080Sstevel@tonic-gate /* 15090Sstevel@tonic-gate * This function processes the data from libdevinfo and creates nodes 15100Sstevel@tonic-gate * in the PICL tree. 15110Sstevel@tonic-gate */ 15120Sstevel@tonic-gate static int 15130Sstevel@tonic-gate libdevinfo_init(picl_nodehdl_t rooth) 15140Sstevel@tonic-gate { 15150Sstevel@tonic-gate di_node_t di_root; 15160Sstevel@tonic-gate picl_nodehdl_t plafh; 15170Sstevel@tonic-gate picl_nodehdl_t obph; 15180Sstevel@tonic-gate int err; 15190Sstevel@tonic-gate 15200Sstevel@tonic-gate 15210Sstevel@tonic-gate if ((di_root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) 15220Sstevel@tonic-gate return (PICL_FAILURE); 15230Sstevel@tonic-gate 15240Sstevel@tonic-gate if ((ph = di_prom_init()) == NULL) 15250Sstevel@tonic-gate return (PICL_FAILURE); 15260Sstevel@tonic-gate /* 15270Sstevel@tonic-gate * create platform PICL node using di_root node 15280Sstevel@tonic-gate */ 15290Sstevel@tonic-gate err = construct_picl_platform(rooth, di_root, &plafh); 15300Sstevel@tonic-gate if (err != PICL_SUCCESS) { 15310Sstevel@tonic-gate di_fini(di_root); 15320Sstevel@tonic-gate return (PICL_FAILURE); 15330Sstevel@tonic-gate } 15340Sstevel@tonic-gate 15350Sstevel@tonic-gate err = construct_picl_openprom(rooth, &obph); 15360Sstevel@tonic-gate if (err != PICL_SUCCESS) { 15370Sstevel@tonic-gate di_fini(di_root); 15380Sstevel@tonic-gate return (PICL_FAILURE); 15390Sstevel@tonic-gate } 15400Sstevel@tonic-gate 15410Sstevel@tonic-gate (void) construct_devinfo_tree(plafh, obph, di_root, NULL); 15420Sstevel@tonic-gate if (ph) { 15430Sstevel@tonic-gate di_prom_fini(ph); 15440Sstevel@tonic-gate ph = NULL; 15450Sstevel@tonic-gate } 15460Sstevel@tonic-gate di_fini(di_root); 15470Sstevel@tonic-gate return (err); 15480Sstevel@tonic-gate } 15490Sstevel@tonic-gate 15500Sstevel@tonic-gate /* 15510Sstevel@tonic-gate * This function returns the integer property value 15520Sstevel@tonic-gate */ 15530Sstevel@tonic-gate static int 15540Sstevel@tonic-gate get_int_propval_by_name(picl_nodehdl_t nodeh, char *pname, int *ival) 15550Sstevel@tonic-gate { 15560Sstevel@tonic-gate int err; 15570Sstevel@tonic-gate 15580Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, pname, ival, 15590Sstevel@tonic-gate sizeof (int)); 15600Sstevel@tonic-gate 15610Sstevel@tonic-gate return (err); 15620Sstevel@tonic-gate } 15630Sstevel@tonic-gate 15640Sstevel@tonic-gate /* 15650Sstevel@tonic-gate * This function returns the port ID (or CPU ID in the case of CMP cores) 15660Sstevel@tonic-gate * of the specific CPU node handle. If upa_portid exists, return its value. 15670Sstevel@tonic-gate * Otherwise, return portid/cpuid. 15680Sstevel@tonic-gate */ 15690Sstevel@tonic-gate static int 15700Sstevel@tonic-gate get_cpu_portid(picl_nodehdl_t modh, int *id) 15710Sstevel@tonic-gate { 15720Sstevel@tonic-gate int err; 15730Sstevel@tonic-gate 15740Sstevel@tonic-gate if (strcmp(mach_name, "sun4u") == 0) { 15750Sstevel@tonic-gate err = get_int_propval_by_name(modh, OBP_PROP_UPA_PORTID, id); 15760Sstevel@tonic-gate if (err == PICL_SUCCESS) 15770Sstevel@tonic-gate return (err); 15780Sstevel@tonic-gate err = get_int_propval_by_name(modh, OBP_PROP_PORTID, id); 15790Sstevel@tonic-gate if (err == PICL_SUCCESS) 15800Sstevel@tonic-gate return (err); 15810Sstevel@tonic-gate return (get_int_propval_by_name(modh, OBP_PROP_CPUID, id)); 15820Sstevel@tonic-gate } 15830Sstevel@tonic-gate if (strcmp(mach_name, "i86pc") == 0) 15840Sstevel@tonic-gate return (get_int_propval_by_name(modh, PICL_PROP_INSTANCE, id)); 15850Sstevel@tonic-gate 15860Sstevel@tonic-gate return (PICL_FAILURE); 15870Sstevel@tonic-gate } 15880Sstevel@tonic-gate 15890Sstevel@tonic-gate /* 15900Sstevel@tonic-gate * This function is the volatile read access function of CPU state 15910Sstevel@tonic-gate * property 15920Sstevel@tonic-gate */ 15930Sstevel@tonic-gate static int 15940Sstevel@tonic-gate get_pi_state(ptree_rarg_t *rarg, void *vbuf) 15950Sstevel@tonic-gate { 15960Sstevel@tonic-gate int id; 15970Sstevel@tonic-gate int err; 15980Sstevel@tonic-gate 15990Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 16000Sstevel@tonic-gate if (err != PICL_SUCCESS) 16010Sstevel@tonic-gate return (err); 16020Sstevel@tonic-gate 16030Sstevel@tonic-gate switch (p_online(id, P_STATUS)) { 16040Sstevel@tonic-gate case P_ONLINE: 16050Sstevel@tonic-gate (void) strlcpy(vbuf, PS_ONLINE, MAX_STATE_SIZE); 16060Sstevel@tonic-gate break; 16070Sstevel@tonic-gate case P_OFFLINE: 16080Sstevel@tonic-gate (void) strlcpy(vbuf, PS_OFFLINE, MAX_STATE_SIZE); 16090Sstevel@tonic-gate break; 16100Sstevel@tonic-gate case P_NOINTR: 16110Sstevel@tonic-gate (void) strlcpy(vbuf, PS_NOINTR, MAX_STATE_SIZE); 16120Sstevel@tonic-gate break; 16130Sstevel@tonic-gate case P_SPARE: 16140Sstevel@tonic-gate (void) strlcpy(vbuf, PS_SPARE, MAX_STATE_SIZE); 16150Sstevel@tonic-gate break; 16160Sstevel@tonic-gate case P_FAULTED: 16170Sstevel@tonic-gate (void) strlcpy(vbuf, PS_FAULTED, MAX_STATE_SIZE); 16180Sstevel@tonic-gate break; 16190Sstevel@tonic-gate case P_POWEROFF: 16200Sstevel@tonic-gate (void) strlcpy(vbuf, PS_POWEROFF, MAX_STATE_SIZE); 16210Sstevel@tonic-gate break; 16220Sstevel@tonic-gate default: 16230Sstevel@tonic-gate (void) strlcpy(vbuf, "unknown", MAX_STATE_SIZE); 16240Sstevel@tonic-gate break; 16250Sstevel@tonic-gate } 16260Sstevel@tonic-gate return (PICL_SUCCESS); 16270Sstevel@tonic-gate } 16280Sstevel@tonic-gate 16290Sstevel@tonic-gate /* 16300Sstevel@tonic-gate * This function is the volatile read access function of CPU processor_type 16310Sstevel@tonic-gate * property 16320Sstevel@tonic-gate */ 16330Sstevel@tonic-gate static int 16340Sstevel@tonic-gate get_processor_type(ptree_rarg_t *rarg, void *vbuf) 16350Sstevel@tonic-gate { 16360Sstevel@tonic-gate processor_info_t cpu_info; 16370Sstevel@tonic-gate int id; 16380Sstevel@tonic-gate int err; 16390Sstevel@tonic-gate 16400Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 16410Sstevel@tonic-gate if (err != PICL_SUCCESS) 16420Sstevel@tonic-gate return (err); 16430Sstevel@tonic-gate 16440Sstevel@tonic-gate if (processor_info(id, &cpu_info) >= 0) { 16450Sstevel@tonic-gate (void) strlcpy(vbuf, cpu_info.pi_processor_type, PI_TYPELEN); 16460Sstevel@tonic-gate } 16470Sstevel@tonic-gate return (PICL_SUCCESS); 16480Sstevel@tonic-gate } 16490Sstevel@tonic-gate 16500Sstevel@tonic-gate /* 16510Sstevel@tonic-gate * This function is the volatile read access function of CPU fputypes 16520Sstevel@tonic-gate * property 16530Sstevel@tonic-gate */ 16540Sstevel@tonic-gate static int 16550Sstevel@tonic-gate get_fputypes(ptree_rarg_t *rarg, void *vbuf) 16560Sstevel@tonic-gate { 16570Sstevel@tonic-gate processor_info_t cpu_info; 16580Sstevel@tonic-gate int id; 16590Sstevel@tonic-gate int err; 16600Sstevel@tonic-gate 16610Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &id); 16620Sstevel@tonic-gate if (err != PICL_SUCCESS) 16630Sstevel@tonic-gate return (err); 16640Sstevel@tonic-gate 16650Sstevel@tonic-gate if (processor_info(id, &cpu_info) >= 0) { 16660Sstevel@tonic-gate (void) strlcpy(vbuf, cpu_info.pi_fputypes, PI_FPUTYPE); 16670Sstevel@tonic-gate } 16680Sstevel@tonic-gate return (PICL_SUCCESS); 16690Sstevel@tonic-gate } 16700Sstevel@tonic-gate 16710Sstevel@tonic-gate /* 16720Sstevel@tonic-gate * This function is the volatile read access function of CPU StateBegin 16730Sstevel@tonic-gate * property. To minimize overhead, use kstat_chain_update() to refresh 16740Sstevel@tonic-gate * the kstat header info as opposed to invoking kstat_open() every time. 16750Sstevel@tonic-gate */ 16760Sstevel@tonic-gate static int 16770Sstevel@tonic-gate get_pi_state_begin(ptree_rarg_t *rarg, void *vbuf) 16780Sstevel@tonic-gate { 16790Sstevel@tonic-gate int err; 16800Sstevel@tonic-gate int cpu_id; 16810Sstevel@tonic-gate static kstat_ctl_t *kc = NULL; 16820Sstevel@tonic-gate static pthread_mutex_t kc_mutex = PTHREAD_MUTEX_INITIALIZER; 16830Sstevel@tonic-gate kstat_t *kp; 16840Sstevel@tonic-gate kstat_named_t *kn; 16850Sstevel@tonic-gate 16860Sstevel@tonic-gate err = get_int_propval_by_name(rarg->nodeh, PICL_PROP_ID, &cpu_id); 16870Sstevel@tonic-gate if (err != PICL_SUCCESS) 16880Sstevel@tonic-gate return (err); 16890Sstevel@tonic-gate 16900Sstevel@tonic-gate (void) pthread_mutex_lock(&kc_mutex); 16910Sstevel@tonic-gate if (kc == NULL) 16920Sstevel@tonic-gate kc = kstat_open(); 16930Sstevel@tonic-gate else if (kstat_chain_update(kc) == -1) { 16940Sstevel@tonic-gate (void) kstat_close(kc); 16950Sstevel@tonic-gate kc = kstat_open(); 16960Sstevel@tonic-gate } 16970Sstevel@tonic-gate 16980Sstevel@tonic-gate if (kc == NULL) { 16990Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 17000Sstevel@tonic-gate return (PICL_FAILURE); 17010Sstevel@tonic-gate } 17020Sstevel@tonic-gate 17030Sstevel@tonic-gate /* Get the state_begin from kstat */ 17040Sstevel@tonic-gate if ((kp = kstat_lookup(kc, KSTAT_CPU_INFO, cpu_id, NULL)) == NULL || 17050Sstevel@tonic-gate kp->ks_type != KSTAT_TYPE_NAMED || kstat_read(kc, kp, 0) < 0) { 17060Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 17070Sstevel@tonic-gate return (PICL_FAILURE); 17080Sstevel@tonic-gate } 17090Sstevel@tonic-gate 17100Sstevel@tonic-gate kn = kstat_data_lookup(kp, KSTAT_STATE_BEGIN); 17110Sstevel@tonic-gate if (kn) { 17120Sstevel@tonic-gate *(uint64_t *)vbuf = (uint64_t)kn->value.l; 17130Sstevel@tonic-gate err = PICL_SUCCESS; 17140Sstevel@tonic-gate } else 17150Sstevel@tonic-gate err = PICL_FAILURE; 17160Sstevel@tonic-gate 17170Sstevel@tonic-gate (void) pthread_mutex_unlock(&kc_mutex); 17180Sstevel@tonic-gate return (err); 17190Sstevel@tonic-gate } 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate /* 17220Sstevel@tonic-gate * This function adds CPU information to the CPU nodes 17230Sstevel@tonic-gate */ 17240Sstevel@tonic-gate /* ARGSUSED */ 17250Sstevel@tonic-gate static int 17260Sstevel@tonic-gate add_processor_info(picl_nodehdl_t cpuh, void *args) 17270Sstevel@tonic-gate { 17280Sstevel@tonic-gate int err; 17290Sstevel@tonic-gate int cpu_id; 17300Sstevel@tonic-gate ptree_propinfo_t propinfo; 17310Sstevel@tonic-gate ptree_propinfo_t pinfo; 17320Sstevel@tonic-gate 17330Sstevel@tonic-gate err = get_cpu_portid(cpuh, &cpu_id); 17340Sstevel@tonic-gate if (err != PICL_SUCCESS) 17350Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 17360Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 17370Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, sizeof (int), PICL_PROP_ID, NULL, NULL); 17380Sstevel@tonic-gate err = ptree_create_and_add_prop(cpuh, &propinfo, &cpu_id, NULL); 17390Sstevel@tonic-gate if (err != PICL_SUCCESS) 17400Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 17410Sstevel@tonic-gate 17420Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 17430Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), MAX_STATE_SIZE, 17440Sstevel@tonic-gate PICL_PROP_STATE, get_pi_state, NULL); 17450Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 17460Sstevel@tonic-gate 17470Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 17480Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_TYPELEN, 17490Sstevel@tonic-gate PICL_PROP_PROCESSOR_TYPE, get_processor_type, NULL); 17500Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 17510Sstevel@tonic-gate 17520Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 17530Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, (PICL_READ|PICL_VOLATILE), PI_FPUTYPE, 17540Sstevel@tonic-gate PICL_PROP_FPUTYPE, get_fputypes, NULL); 17550Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 17560Sstevel@tonic-gate 17570Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 17580Sstevel@tonic-gate PICL_PTYPE_TIMESTAMP, PICL_READ|PICL_VOLATILE, sizeof (uint64_t), 17590Sstevel@tonic-gate PICL_PROP_STATE_BEGIN, get_pi_state_begin, NULL); 17600Sstevel@tonic-gate (void) ptree_create_and_add_prop(cpuh, &pinfo, NULL, NULL); 17610Sstevel@tonic-gate 17620Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 17630Sstevel@tonic-gate } 17640Sstevel@tonic-gate 17650Sstevel@tonic-gate /* 17660Sstevel@tonic-gate * This function sets up the "ID" property in every CPU nodes 17670Sstevel@tonic-gate * and adds processor info 17680Sstevel@tonic-gate */ 17690Sstevel@tonic-gate static int 17700Sstevel@tonic-gate setup_cpus(picl_nodehdl_t plafh) 17710Sstevel@tonic-gate { 17720Sstevel@tonic-gate int err; 17730Sstevel@tonic-gate 17740Sstevel@tonic-gate err = ptree_walk_tree_by_class(plafh, PICL_CLASS_CPU, NULL, 17750Sstevel@tonic-gate add_processor_info); 17760Sstevel@tonic-gate 17770Sstevel@tonic-gate return (err); 17780Sstevel@tonic-gate } 17790Sstevel@tonic-gate 17800Sstevel@tonic-gate /* 17810Sstevel@tonic-gate * This function format's the manufacture's information for FFB display 17820Sstevel@tonic-gate * devices 17830Sstevel@tonic-gate */ 17840Sstevel@tonic-gate static void 17850Sstevel@tonic-gate fmt_manf_id(manuf_t manufid, int bufsz, char *outbuf) 17860Sstevel@tonic-gate { 17870Sstevel@tonic-gate /* 17880Sstevel@tonic-gate * Format the manufacturer's info. Note a small inconsistency we 17890Sstevel@tonic-gate * have to work around - Brooktree has it's part number in decimal, 17900Sstevel@tonic-gate * while Mitsubishi has it's part number in hex. 17910Sstevel@tonic-gate */ 17920Sstevel@tonic-gate switch (manufid.fld.manf) { 17930Sstevel@tonic-gate case MANF_BROOKTREE: 17940Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, "%s %d, version %d", 17950Sstevel@tonic-gate "Brooktree", manufid.fld.partno, manufid.fld.version); 17960Sstevel@tonic-gate break; 17970Sstevel@tonic-gate 17980Sstevel@tonic-gate case MANF_MITSUBISHI: 17990Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, "%s %x, version %d", 18000Sstevel@tonic-gate "Mitsubishi", manufid.fld.partno, manufid.fld.version); 18010Sstevel@tonic-gate break; 18020Sstevel@tonic-gate 18030Sstevel@tonic-gate default: 18040Sstevel@tonic-gate (void) snprintf(outbuf, bufsz, 18050Sstevel@tonic-gate "JED code %d, Part num 0x%x, version %d", 18060Sstevel@tonic-gate manufid.fld.manf, manufid.fld.partno, manufid.fld.version); 18070Sstevel@tonic-gate } 18080Sstevel@tonic-gate } 18090Sstevel@tonic-gate 18100Sstevel@tonic-gate /* 18110Sstevel@tonic-gate * If it's an ffb device, open ffb devices and return PICL_SUCCESS 18120Sstevel@tonic-gate */ 18130Sstevel@tonic-gate static int 18140Sstevel@tonic-gate open_ffb_device(picl_nodehdl_t ffbh, int *fd) 18150Sstevel@tonic-gate { 18160Sstevel@tonic-gate DIR *dirp; 18170Sstevel@tonic-gate char devfs_path[PATH_MAX]; 18180Sstevel@tonic-gate char dev_path[PATH_MAX]; 18190Sstevel@tonic-gate char *devp; 18200Sstevel@tonic-gate struct dirent *direntp; 18210Sstevel@tonic-gate int err; 18220Sstevel@tonic-gate int tmpfd; 18230Sstevel@tonic-gate 18240Sstevel@tonic-gate /* Get the devfs_path of the ffb devices */ 18250Sstevel@tonic-gate err = ptree_get_propval_by_name(ffbh, PICL_PROP_DEVFS_PATH, devfs_path, 18260Sstevel@tonic-gate sizeof (devfs_path)); 18270Sstevel@tonic-gate if (err != PICL_SUCCESS) 18280Sstevel@tonic-gate return (err); 18290Sstevel@tonic-gate 18300Sstevel@tonic-gate /* Get the device node name */ 18310Sstevel@tonic-gate devp = strrchr(devfs_path, '/'); 18320Sstevel@tonic-gate if (devp == NULL) 18330Sstevel@tonic-gate return (PICL_FAILURE); 18340Sstevel@tonic-gate *devp = '\0'; 18350Sstevel@tonic-gate ++devp; 18360Sstevel@tonic-gate 18370Sstevel@tonic-gate /* 18380Sstevel@tonic-gate * Check if device node name has the ffb string 18390Sstevel@tonic-gate * If not, assume it's not a ffb device. 18400Sstevel@tonic-gate */ 18410Sstevel@tonic-gate if (strstr(devp, FFB_NAME) == NULL) 18420Sstevel@tonic-gate return (PICL_FAILURE); 18430Sstevel@tonic-gate 18440Sstevel@tonic-gate /* 18450Sstevel@tonic-gate * Get the parent path of the ffb device node. 18460Sstevel@tonic-gate */ 18470Sstevel@tonic-gate (void) snprintf(dev_path, sizeof (dev_path), "%s/%s", "/devices", 18480Sstevel@tonic-gate devfs_path); 18490Sstevel@tonic-gate 18500Sstevel@tonic-gate /* 18510Sstevel@tonic-gate * Since we don't know ffb's minor nodename, 18520Sstevel@tonic-gate * we need to search all the devices under its 18530Sstevel@tonic-gate * parent dir by comparing the node name 18540Sstevel@tonic-gate */ 18550Sstevel@tonic-gate if ((dirp = opendir(dev_path)) == NULL) 18560Sstevel@tonic-gate return (PICL_FAILURE); 18570Sstevel@tonic-gate 18580Sstevel@tonic-gate while ((direntp = readdir(dirp)) != NULL) { 18590Sstevel@tonic-gate if (strstr(direntp->d_name, devp) != NULL) { 18600Sstevel@tonic-gate (void) strcat(dev_path, "/"); 18610Sstevel@tonic-gate (void) strcat(dev_path, direntp->d_name); 18620Sstevel@tonic-gate tmpfd = open(dev_path, O_RDWR); 18630Sstevel@tonic-gate if (tmpfd < 0) 18640Sstevel@tonic-gate continue; 18650Sstevel@tonic-gate *fd = tmpfd; 18660Sstevel@tonic-gate (void) closedir(dirp); 18670Sstevel@tonic-gate return (PICL_SUCCESS); 18680Sstevel@tonic-gate } 18690Sstevel@tonic-gate } 18700Sstevel@tonic-gate 18710Sstevel@tonic-gate (void) closedir(dirp); 18720Sstevel@tonic-gate return (PICL_FAILURE); 18730Sstevel@tonic-gate } 18740Sstevel@tonic-gate 18750Sstevel@tonic-gate /* 18760Sstevel@tonic-gate * This function recursively searches the tree for ffb display devices 18770Sstevel@tonic-gate * and add ffb config information 18780Sstevel@tonic-gate */ 18790Sstevel@tonic-gate static int 18800Sstevel@tonic-gate add_ffb_config_info(picl_nodehdl_t rooth) 18810Sstevel@tonic-gate { 18820Sstevel@tonic-gate picl_nodehdl_t nodeh; 18830Sstevel@tonic-gate int err; 18840Sstevel@tonic-gate char piclclass[PICL_CLASSNAMELEN_MAX]; 18850Sstevel@tonic-gate char manfidbuf[FFB_MANUF_BUFSIZE]; 18860Sstevel@tonic-gate int fd; 18870Sstevel@tonic-gate int board_rev; 18880Sstevel@tonic-gate ffb_sys_info_t fsi; 18890Sstevel@tonic-gate ptree_propinfo_t pinfo; 18900Sstevel@tonic-gate 18910Sstevel@tonic-gate for (err = ptree_get_propval_by_name(rooth, PICL_PROP_CHILD, &nodeh, 18920Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 18930Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, 18940Sstevel@tonic-gate &nodeh, sizeof (picl_nodehdl_t))) { 18950Sstevel@tonic-gate 18960Sstevel@tonic-gate if (err != PICL_SUCCESS) 18970Sstevel@tonic-gate return (err); 18980Sstevel@tonic-gate 18990Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, 19000Sstevel@tonic-gate piclclass, PICL_CLASSNAMELEN_MAX); 19010Sstevel@tonic-gate 19020Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 19030Sstevel@tonic-gate (strcmp(piclclass, PICL_CLASS_DISPLAY) == 0)) { 19040Sstevel@tonic-gate 19050Sstevel@tonic-gate err = open_ffb_device(nodeh, &fd); 19060Sstevel@tonic-gate if ((err == PICL_SUCCESS) && 19070Sstevel@tonic-gate (ioctl(fd, FFB_SYS_INFO, &fsi) >= 0)) { 19080Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 19090Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 19100Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, 19110Sstevel@tonic-gate sizeof (int), PICL_PROP_FFB_BOARD_REV, 19120Sstevel@tonic-gate NULL, NULL); 19130Sstevel@tonic-gate board_rev = fsi.ffb_strap_bits.fld.board_rev; 19140Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 19150Sstevel@tonic-gate &board_rev, NULL); 19160Sstevel@tonic-gate 19170Sstevel@tonic-gate fmt_manf_id(fsi.dac_version, 19180Sstevel@tonic-gate sizeof (manfidbuf), manfidbuf); 19190Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 19200Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 19210Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 19220Sstevel@tonic-gate strlen(manfidbuf) + 1, 19230Sstevel@tonic-gate PICL_PROP_FFB_DAC_VER, NULL, NULL); 19240Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 19250Sstevel@tonic-gate manfidbuf, NULL); 19260Sstevel@tonic-gate 19270Sstevel@tonic-gate fmt_manf_id(fsi.fbram_version, 19280Sstevel@tonic-gate sizeof (manfidbuf), manfidbuf); 19290Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, 19300Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 19310Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 19320Sstevel@tonic-gate strlen(manfidbuf) + 1, 19330Sstevel@tonic-gate PICL_PROP_FFB_FBRAM_VER, NULL, 19340Sstevel@tonic-gate NULL); 19350Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, 19360Sstevel@tonic-gate manfidbuf, NULL); 19370Sstevel@tonic-gate (void) close(fd); 19380Sstevel@tonic-gate } 19390Sstevel@tonic-gate } else if (add_ffb_config_info(nodeh) != PICL_SUCCESS) 19400Sstevel@tonic-gate return (PICL_FAILURE); 19410Sstevel@tonic-gate } 19420Sstevel@tonic-gate return (PICL_SUCCESS); 19430Sstevel@tonic-gate } 19440Sstevel@tonic-gate 19450Sstevel@tonic-gate static conf_entries_t * 19460Sstevel@tonic-gate free_conf_entries(conf_entries_t *list) 19470Sstevel@tonic-gate { 19480Sstevel@tonic-gate conf_entries_t *el; 19490Sstevel@tonic-gate conf_entries_t *del; 19500Sstevel@tonic-gate 19510Sstevel@tonic-gate if (list == NULL) 19520Sstevel@tonic-gate return (NULL); 19530Sstevel@tonic-gate el = list; 19540Sstevel@tonic-gate while (el != NULL) { 19550Sstevel@tonic-gate del = el; 19560Sstevel@tonic-gate el = el->next; 19570Sstevel@tonic-gate free(del->name); 19580Sstevel@tonic-gate free(del->piclclass); 19590Sstevel@tonic-gate free(del); 19600Sstevel@tonic-gate } 19610Sstevel@tonic-gate return (el); 19620Sstevel@tonic-gate } 19630Sstevel@tonic-gate 19640Sstevel@tonic-gate /* 19650Sstevel@tonic-gate * Reading config order: platform, common 19660Sstevel@tonic-gate */ 19670Sstevel@tonic-gate static conf_entries_t * 19680Sstevel@tonic-gate read_conf_file(char *fname, conf_entries_t *list) 19690Sstevel@tonic-gate { 19700Sstevel@tonic-gate FILE *fp; 19710Sstevel@tonic-gate char lbuf[CONFFILE_LINELEN_MAX]; 19720Sstevel@tonic-gate char *nametok; 19730Sstevel@tonic-gate char *classtok; 19740Sstevel@tonic-gate conf_entries_t *el; 19750Sstevel@tonic-gate conf_entries_t *ptr; 19760Sstevel@tonic-gate 19770Sstevel@tonic-gate if (fname == NULL) 19780Sstevel@tonic-gate return (list); 19790Sstevel@tonic-gate 19800Sstevel@tonic-gate fp = fopen(fname, "r"); 19810Sstevel@tonic-gate 19820Sstevel@tonic-gate if (fp == NULL) 19830Sstevel@tonic-gate return (list); 19840Sstevel@tonic-gate 19850Sstevel@tonic-gate while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) { 19860Sstevel@tonic-gate if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n')) 19870Sstevel@tonic-gate continue; 19880Sstevel@tonic-gate 19890Sstevel@tonic-gate nametok = strtok(lbuf, " \t\n"); 19900Sstevel@tonic-gate if (nametok == NULL) 19910Sstevel@tonic-gate continue; 19920Sstevel@tonic-gate 19930Sstevel@tonic-gate classtok = strtok(NULL, " \t\n"); 19940Sstevel@tonic-gate if (classtok == NULL) 19950Sstevel@tonic-gate continue; 19960Sstevel@tonic-gate 19970Sstevel@tonic-gate el = malloc(sizeof (conf_entries_t)); 19980Sstevel@tonic-gate if (el == NULL) 19990Sstevel@tonic-gate break; 20000Sstevel@tonic-gate el->name = strdup(nametok); 20010Sstevel@tonic-gate el->piclclass = strdup(classtok); 20020Sstevel@tonic-gate if ((el->name == NULL) || (el->piclclass == NULL)) { 20030Sstevel@tonic-gate free(el); 20040Sstevel@tonic-gate return (list); 20050Sstevel@tonic-gate } 20060Sstevel@tonic-gate el->next = NULL; 20070Sstevel@tonic-gate 20080Sstevel@tonic-gate /* 20090Sstevel@tonic-gate * Add it to the end of list 20100Sstevel@tonic-gate */ 20110Sstevel@tonic-gate if (list == NULL) 20120Sstevel@tonic-gate list = el; 20130Sstevel@tonic-gate else { 20140Sstevel@tonic-gate ptr = list; 20150Sstevel@tonic-gate while (ptr->next != NULL) 20160Sstevel@tonic-gate ptr = ptr->next; 20170Sstevel@tonic-gate ptr->next = el; 20180Sstevel@tonic-gate } 20190Sstevel@tonic-gate 20200Sstevel@tonic-gate } 20210Sstevel@tonic-gate (void) fclose(fp); 20220Sstevel@tonic-gate return (list); 20230Sstevel@tonic-gate } 20240Sstevel@tonic-gate 20250Sstevel@tonic-gate /* 20260Sstevel@tonic-gate * Process the devtree conf file and set up the conf_name_class_map list 20270Sstevel@tonic-gate */ 20280Sstevel@tonic-gate static void 20290Sstevel@tonic-gate process_devtree_conf_file(void) 20300Sstevel@tonic-gate { 20310Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 20320Sstevel@tonic-gate char pname[PATH_MAX]; 20330Sstevel@tonic-gate 20340Sstevel@tonic-gate conf_name_class_map = NULL; 20350Sstevel@tonic-gate 20360Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 20370Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 20380Sstevel@tonic-gate (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX); 20390Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, 20400Sstevel@tonic-gate conf_name_class_map); 20410Sstevel@tonic-gate } 20420Sstevel@tonic-gate 20430Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 20440Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 20450Sstevel@tonic-gate (void) strlcat(pname, DEVTREE_CONFFILE_NAME, PATH_MAX); 20460Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, 20470Sstevel@tonic-gate conf_name_class_map); 20480Sstevel@tonic-gate } 20490Sstevel@tonic-gate 20500Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR, 20510Sstevel@tonic-gate DEVTREE_CONFFILE_NAME); 20520Sstevel@tonic-gate conf_name_class_map = read_conf_file(pname, conf_name_class_map); 20530Sstevel@tonic-gate } 20540Sstevel@tonic-gate 20550Sstevel@tonic-gate static asr_conf_entries_t *conf_name_asr_map = NULL; 20560Sstevel@tonic-gate 20570Sstevel@tonic-gate static void 20580Sstevel@tonic-gate free_asr_conf_entries(asr_conf_entries_t *list) { 20590Sstevel@tonic-gate asr_conf_entries_t *el; 20600Sstevel@tonic-gate asr_conf_entries_t *del; 20610Sstevel@tonic-gate 20620Sstevel@tonic-gate el = list; 20630Sstevel@tonic-gate while (el != NULL) { 20640Sstevel@tonic-gate del = el; 20650Sstevel@tonic-gate el = el->next; 20660Sstevel@tonic-gate if (del->name) 20670Sstevel@tonic-gate free(del->name); 20680Sstevel@tonic-gate if (del->address) 20690Sstevel@tonic-gate free(del->address); 20700Sstevel@tonic-gate if (del->status) 20710Sstevel@tonic-gate free(del->status); 20720Sstevel@tonic-gate if (del->piclclass) 20730Sstevel@tonic-gate free(del->piclclass); 20740Sstevel@tonic-gate if (del->props) 20750Sstevel@tonic-gate free(del->props); 20760Sstevel@tonic-gate free(del); 20770Sstevel@tonic-gate } 20780Sstevel@tonic-gate } 20790Sstevel@tonic-gate 20800Sstevel@tonic-gate /* 20810Sstevel@tonic-gate * Reading config order: platform, common 20820Sstevel@tonic-gate */ 20830Sstevel@tonic-gate static asr_conf_entries_t * 20840Sstevel@tonic-gate read_asr_conf_file(char *fname, asr_conf_entries_t *list) 20850Sstevel@tonic-gate { 20860Sstevel@tonic-gate FILE *fp; 20870Sstevel@tonic-gate char lbuf[CONFFILE_LINELEN_MAX]; 20880Sstevel@tonic-gate char *nametok; 20890Sstevel@tonic-gate char *classtok; 20900Sstevel@tonic-gate char *statustok; 20910Sstevel@tonic-gate char *addresstok; 20920Sstevel@tonic-gate char *propstok; 20930Sstevel@tonic-gate asr_conf_entries_t *el; 20940Sstevel@tonic-gate asr_conf_entries_t *ptr; 20950Sstevel@tonic-gate 20960Sstevel@tonic-gate if (fname == NULL) 20970Sstevel@tonic-gate return (list); 20980Sstevel@tonic-gate 20990Sstevel@tonic-gate fp = fopen(fname, "r"); 21000Sstevel@tonic-gate if (fp == NULL) 21010Sstevel@tonic-gate return (list); 21020Sstevel@tonic-gate 21030Sstevel@tonic-gate while (fgets(lbuf, CONFFILE_LINELEN_MAX, fp) != NULL) { 21040Sstevel@tonic-gate if ((lbuf[0] == CONFFILE_COMMENT_CHAR) || (lbuf[0] == '\n')) 21050Sstevel@tonic-gate continue; 21060Sstevel@tonic-gate 21070Sstevel@tonic-gate nametok = strtok(lbuf, " \t\n"); 21080Sstevel@tonic-gate if (nametok == NULL) 21090Sstevel@tonic-gate continue; 21100Sstevel@tonic-gate 21110Sstevel@tonic-gate classtok = strtok(NULL, " \t\n"); 21120Sstevel@tonic-gate if (classtok == NULL) 21130Sstevel@tonic-gate continue; 21140Sstevel@tonic-gate 21150Sstevel@tonic-gate statustok = strtok(NULL, " \t\n"); 21160Sstevel@tonic-gate if (statustok == NULL) 21170Sstevel@tonic-gate continue; 21180Sstevel@tonic-gate 21190Sstevel@tonic-gate addresstok = strtok(NULL, " \t\n"); 21200Sstevel@tonic-gate if (addresstok == NULL) 21210Sstevel@tonic-gate continue; 21220Sstevel@tonic-gate 21230Sstevel@tonic-gate /* 21240Sstevel@tonic-gate * props are optional 21250Sstevel@tonic-gate */ 21260Sstevel@tonic-gate propstok = strtok(NULL, " \t\n"); 21270Sstevel@tonic-gate 21280Sstevel@tonic-gate el = malloc(sizeof (asr_conf_entries_t)); 21290Sstevel@tonic-gate if (el == NULL) 21300Sstevel@tonic-gate break; 21310Sstevel@tonic-gate el->name = strdup(nametok); 21320Sstevel@tonic-gate el->piclclass = strdup(classtok); 21330Sstevel@tonic-gate el->status = strdup(statustok); 21340Sstevel@tonic-gate el->address = strdup(addresstok); 21350Sstevel@tonic-gate if (propstok != NULL) 21360Sstevel@tonic-gate el->props = strdup(propstok); 21370Sstevel@tonic-gate else 21380Sstevel@tonic-gate el->props = NULL; 21390Sstevel@tonic-gate if ((el->name == NULL) || (el->piclclass == NULL) || 21400Sstevel@tonic-gate (el->address == NULL) || (el->status == NULL)) { 21410Sstevel@tonic-gate if (el->name) 21420Sstevel@tonic-gate free(el->name); 21430Sstevel@tonic-gate if (el->address) 21440Sstevel@tonic-gate free(el->address); 21450Sstevel@tonic-gate if (el->status) 21460Sstevel@tonic-gate free(el->status); 21470Sstevel@tonic-gate if (el->piclclass) 21480Sstevel@tonic-gate free(el->piclclass); 21490Sstevel@tonic-gate if (el->props) 21500Sstevel@tonic-gate free(el->props); 21510Sstevel@tonic-gate free(el); 21520Sstevel@tonic-gate break; 21530Sstevel@tonic-gate } 21540Sstevel@tonic-gate el->next = NULL; 21550Sstevel@tonic-gate 21560Sstevel@tonic-gate /* 21570Sstevel@tonic-gate * Add it to the end of list 21580Sstevel@tonic-gate */ 21590Sstevel@tonic-gate if (list == NULL) 21600Sstevel@tonic-gate list = el; 21610Sstevel@tonic-gate else { 21620Sstevel@tonic-gate ptr = list; 21630Sstevel@tonic-gate while (ptr->next != NULL) 21640Sstevel@tonic-gate ptr = ptr->next; 21650Sstevel@tonic-gate ptr->next = el; 21660Sstevel@tonic-gate } 21670Sstevel@tonic-gate 21680Sstevel@tonic-gate } 21690Sstevel@tonic-gate (void) fclose(fp); 21700Sstevel@tonic-gate return (list); 21710Sstevel@tonic-gate } 21720Sstevel@tonic-gate 21730Sstevel@tonic-gate /* 21740Sstevel@tonic-gate * Process the asr conf file 21750Sstevel@tonic-gate */ 21760Sstevel@tonic-gate static void 21770Sstevel@tonic-gate process_asrtree_conf_file(void) 21780Sstevel@tonic-gate { 21790Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 21800Sstevel@tonic-gate char pname[PATH_MAX]; 21810Sstevel@tonic-gate 21820Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 21830Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 21840Sstevel@tonic-gate (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX); 21850Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, 21860Sstevel@tonic-gate conf_name_asr_map); 21870Sstevel@tonic-gate } 21880Sstevel@tonic-gate 21890Sstevel@tonic-gate if (sysinfo(SI_MACHINE, nmbuf, sizeof (nmbuf)) != -1) { 21900Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf); 21910Sstevel@tonic-gate (void) strlcat(pname, ASRTREE_CONFFILE_NAME, PATH_MAX); 21920Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, 21930Sstevel@tonic-gate conf_name_asr_map); 21940Sstevel@tonic-gate } 21950Sstevel@tonic-gate 21960Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s", PICLD_COMMON_PLUGIN_DIR, 21970Sstevel@tonic-gate ASRTREE_CONFFILE_NAME); 21980Sstevel@tonic-gate conf_name_asr_map = read_asr_conf_file(pname, conf_name_asr_map); 21990Sstevel@tonic-gate } 22000Sstevel@tonic-gate 22010Sstevel@tonic-gate /* 22020Sstevel@tonic-gate * This function reads the export file list from ASR 22030Sstevel@tonic-gate */ 22040Sstevel@tonic-gate static int 22050Sstevel@tonic-gate get_asr_export_list(char **exportlist, int *exportlistlen) 22060Sstevel@tonic-gate { 22070Sstevel@tonic-gate struct openpromio oppbuf; 22080Sstevel@tonic-gate struct openpromio *opp = &oppbuf; 22090Sstevel@tonic-gate int d; 22100Sstevel@tonic-gate int listsize; 22110Sstevel@tonic-gate 22120Sstevel@tonic-gate d = open("/dev/openprom", O_RDWR); 22130Sstevel@tonic-gate if (d < 0) 22140Sstevel@tonic-gate return (0); 22150Sstevel@tonic-gate 22160Sstevel@tonic-gate if (ioctl(d, OPROMEXPORTLEN, opp) == -1) { 22170Sstevel@tonic-gate (void) close(d); 22180Sstevel@tonic-gate return (0); 22190Sstevel@tonic-gate } 22200Sstevel@tonic-gate listsize = opp->oprom_size; 22210Sstevel@tonic-gate opp = (struct openpromio *)malloc(sizeof (struct openpromio) + 22220Sstevel@tonic-gate listsize); 22230Sstevel@tonic-gate if (opp == NULL) { 22240Sstevel@tonic-gate (void) close(d); 22250Sstevel@tonic-gate return (0); 22260Sstevel@tonic-gate } 22270Sstevel@tonic-gate (void) memset(opp, '\0', sizeof (struct openpromio) + listsize); 22280Sstevel@tonic-gate opp->oprom_size = listsize; 22290Sstevel@tonic-gate if (ioctl(d, OPROMEXPORT, opp) == -1) { 22300Sstevel@tonic-gate free(opp); 22310Sstevel@tonic-gate (void) close(d); 22320Sstevel@tonic-gate return (0); 22330Sstevel@tonic-gate } 22340Sstevel@tonic-gate *exportlist = malloc(listsize); 22350Sstevel@tonic-gate if (*exportlist == NULL) { 22360Sstevel@tonic-gate free(opp); 22370Sstevel@tonic-gate (void) close(d); 22380Sstevel@tonic-gate return (0); 22390Sstevel@tonic-gate } 22400Sstevel@tonic-gate (void) memcpy(*exportlist, opp->oprom_array, opp->oprom_size); 22410Sstevel@tonic-gate free(opp); 22420Sstevel@tonic-gate *exportlistlen = opp->oprom_size; 22430Sstevel@tonic-gate (void) close(d); 22440Sstevel@tonic-gate return (1); 22450Sstevel@tonic-gate } 22460Sstevel@tonic-gate 22470Sstevel@tonic-gate /* 22480Sstevel@tonic-gate * Parses properties string, fills in triplet structure with first 22490Sstevel@tonic-gate * type, name, val triplet and returns pointer to next property. 22500Sstevel@tonic-gate * Returns NULL if no valid triplet found 22510Sstevel@tonic-gate * CAUTION: drops \0 characters over separator characters: if you 22520Sstevel@tonic-gate * want to parse the string twice, you'll have to take a copy. 22530Sstevel@tonic-gate */ 22540Sstevel@tonic-gate static char * 22550Sstevel@tonic-gate parse_props_string(char *props, asr_prop_triplet_t *triplet) 22560Sstevel@tonic-gate { 22570Sstevel@tonic-gate char *prop_name; 22580Sstevel@tonic-gate char *prop_val; 22590Sstevel@tonic-gate char *prop_next; 22600Sstevel@tonic-gate 22610Sstevel@tonic-gate prop_name = strchr(props, '?'); 22620Sstevel@tonic-gate if (prop_name == NULL) 22630Sstevel@tonic-gate return (NULL); 22640Sstevel@tonic-gate *prop_name++ = '\0'; 22650Sstevel@tonic-gate prop_val = strchr(prop_name, '='); 22660Sstevel@tonic-gate if (prop_val == NULL) 22670Sstevel@tonic-gate return (NULL); 22680Sstevel@tonic-gate *prop_val++ = '\0'; 22690Sstevel@tonic-gate triplet->proptype = props; 22700Sstevel@tonic-gate triplet->propname = prop_name; 22710Sstevel@tonic-gate triplet->propval = prop_val; 22720Sstevel@tonic-gate prop_next = strchr(prop_val, ':'); 22730Sstevel@tonic-gate if (prop_next == NULL) 22740Sstevel@tonic-gate return (prop_val - 1); 22750Sstevel@tonic-gate *prop_next++ = '\0'; 22760Sstevel@tonic-gate return (prop_next); 22770Sstevel@tonic-gate } 22780Sstevel@tonic-gate 22790Sstevel@tonic-gate static int 22800Sstevel@tonic-gate add_status_prop(picl_nodehdl_t chdh, char *status) 22810Sstevel@tonic-gate { 22820Sstevel@tonic-gate ptree_propinfo_t propinfo; 22830Sstevel@tonic-gate picl_prophdl_t proph; 22840Sstevel@tonic-gate int err; 22850Sstevel@tonic-gate 22860Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 22870Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(status) + 1, 22880Sstevel@tonic-gate PICL_PROP_STATUS, NULL, NULL); 22890Sstevel@tonic-gate if (err != PICL_SUCCESS) 22900Sstevel@tonic-gate return (err); 22910Sstevel@tonic-gate err = ptree_create_and_add_prop(chdh, &propinfo, status, &proph); 22920Sstevel@tonic-gate return (err); 22930Sstevel@tonic-gate } 22940Sstevel@tonic-gate 22950Sstevel@tonic-gate static void 22960Sstevel@tonic-gate create_asr_node(char *parent, char *child, char *unitaddr, char *class, 22970Sstevel@tonic-gate char *status, char *props) 22980Sstevel@tonic-gate { 22990Sstevel@tonic-gate char ptreepath[PATH_MAX]; 23000Sstevel@tonic-gate char nodename[PICL_PROPNAMELEN_MAX]; 23010Sstevel@tonic-gate char ua[MAX_UNIT_ADDRESS_LEN]; 23020Sstevel@tonic-gate char *props_copy = NULL; 23030Sstevel@tonic-gate char *next; 23040Sstevel@tonic-gate char *prop_string; 23050Sstevel@tonic-gate boolean_t found = B_FALSE; 23060Sstevel@tonic-gate picl_nodehdl_t nodeh; 23070Sstevel@tonic-gate picl_nodehdl_t chdh; 23080Sstevel@tonic-gate asr_prop_triplet_t triple; 23090Sstevel@tonic-gate ptree_propinfo_t propinfo; 23100Sstevel@tonic-gate picl_prophdl_t proph; 23110Sstevel@tonic-gate int val; 23120Sstevel@tonic-gate int err; 23130Sstevel@tonic-gate 23140Sstevel@tonic-gate (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX); 23150Sstevel@tonic-gate (void) strlcat(ptreepath, parent, PATH_MAX); 23160Sstevel@tonic-gate 23170Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS) 23180Sstevel@tonic-gate return; 23190Sstevel@tonic-gate /* 23200Sstevel@tonic-gate * see if the required child node already exists 23210Sstevel@tonic-gate */ 23220Sstevel@tonic-gate for (err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 23230Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 23240Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 23250Sstevel@tonic-gate sizeof (picl_nodehdl_t))) { 23260Sstevel@tonic-gate if (err != PICL_SUCCESS) 23270Sstevel@tonic-gate break; 23280Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_NAME, 23290Sstevel@tonic-gate (void *)nodename, PICL_PROPNAMELEN_MAX); 23300Sstevel@tonic-gate if (err != PICL_SUCCESS) 23310Sstevel@tonic-gate break; 23320Sstevel@tonic-gate if (strcmp(nodename, child) != 0) 23330Sstevel@tonic-gate continue; 23340Sstevel@tonic-gate /* 23350Sstevel@tonic-gate * found a candidate child node 23360Sstevel@tonic-gate */ 23370Sstevel@tonic-gate if (unitaddr) { 23380Sstevel@tonic-gate /* 23390Sstevel@tonic-gate * does it match the required unit address? 23400Sstevel@tonic-gate */ 23410Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, 23420Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, ua, sizeof (ua)); 23430Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 23440Sstevel@tonic-gate continue; 23450Sstevel@tonic-gate if (err != PICL_SUCCESS) 23460Sstevel@tonic-gate break; 23470Sstevel@tonic-gate if (strcmp(unitaddr, ua) != 0) 23480Sstevel@tonic-gate continue; 23490Sstevel@tonic-gate } 23500Sstevel@tonic-gate if (props == NULL) { 23510Sstevel@tonic-gate next = ""; 23520Sstevel@tonic-gate } else if (props_copy == NULL) { 23530Sstevel@tonic-gate props_copy = strdup(props); 23540Sstevel@tonic-gate if (props_copy == NULL) 23550Sstevel@tonic-gate return; 23560Sstevel@tonic-gate next = props_copy; 23570Sstevel@tonic-gate } 23580Sstevel@tonic-gate while ((next = parse_props_string(next, &triple)) != NULL) { 23590Sstevel@tonic-gate err = ptree_get_prop_by_name(chdh, triple.propname, 23600Sstevel@tonic-gate &proph); 23610Sstevel@tonic-gate if (err != PICL_SUCCESS) 23620Sstevel@tonic-gate break; 23630Sstevel@tonic-gate err = ptree_get_propinfo(proph, &propinfo); 23640Sstevel@tonic-gate if (err != PICL_SUCCESS) 23650Sstevel@tonic-gate break; 23660Sstevel@tonic-gate err = PICL_FAILURE; 23670Sstevel@tonic-gate switch (propinfo.piclinfo.type) { 23680Sstevel@tonic-gate case PICL_PTYPE_INT: 23690Sstevel@tonic-gate case PICL_PTYPE_UNSIGNED_INT: 23700Sstevel@tonic-gate if (strcmp(triple.proptype, "I") != 0) 23710Sstevel@tonic-gate break; 23720Sstevel@tonic-gate err = ptree_get_propval(proph, (void *)&val, 23730Sstevel@tonic-gate sizeof (val)); 23740Sstevel@tonic-gate if (err != PICL_SUCCESS) 23750Sstevel@tonic-gate break; 23760Sstevel@tonic-gate if (val != atoi(triple.propval)) 23770Sstevel@tonic-gate err = PICL_FAILURE; 23780Sstevel@tonic-gate break; 23790Sstevel@tonic-gate case PICL_PTYPE_CHARSTRING: 23800Sstevel@tonic-gate if (strcmp(triple.proptype, "S") != 0) 23810Sstevel@tonic-gate break; 23820Sstevel@tonic-gate prop_string = malloc(propinfo.piclinfo.size); 23830Sstevel@tonic-gate if (prop_string == NULL) 23840Sstevel@tonic-gate break; 23850Sstevel@tonic-gate err = ptree_get_propval(proph, 23860Sstevel@tonic-gate (void *)prop_string, 23870Sstevel@tonic-gate propinfo.piclinfo.size); 23880Sstevel@tonic-gate if (err != PICL_SUCCESS) { 23890Sstevel@tonic-gate free(prop_string); 23900Sstevel@tonic-gate break; 23910Sstevel@tonic-gate } 23920Sstevel@tonic-gate if (strcmp(prop_string, triple.propval) != 0) 23930Sstevel@tonic-gate err = PICL_FAILURE; 23940Sstevel@tonic-gate free(prop_string); 23950Sstevel@tonic-gate break; 23960Sstevel@tonic-gate default: 23970Sstevel@tonic-gate break; 23980Sstevel@tonic-gate } 23990Sstevel@tonic-gate if (err != PICL_SUCCESS) { 24000Sstevel@tonic-gate break; 24010Sstevel@tonic-gate } 24020Sstevel@tonic-gate } 24030Sstevel@tonic-gate if (next == NULL) { 24040Sstevel@tonic-gate found = B_TRUE; 24050Sstevel@tonic-gate break; 24060Sstevel@tonic-gate } 24070Sstevel@tonic-gate } 24080Sstevel@tonic-gate if (props_copy) 24090Sstevel@tonic-gate free(props_copy); 24100Sstevel@tonic-gate if (found) { 24110Sstevel@tonic-gate /* 24120Sstevel@tonic-gate * does the pre-existing node have a status property? 24130Sstevel@tonic-gate */ 24140Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_STATUS, 24150Sstevel@tonic-gate ua, sizeof (ua)); 24160Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 24170Sstevel@tonic-gate (void) add_status_prop(chdh, status); 24180Sstevel@tonic-gate if (err != PICL_SUCCESS) 24190Sstevel@tonic-gate return; 24200Sstevel@tonic-gate if ((strcmp(ua, ASR_DISABLED) == 0) || 24210Sstevel@tonic-gate (strcmp(ua, ASR_FAILED) == 0) || 24220Sstevel@tonic-gate ((strcmp(status, ASR_DISABLED) != 0) && 24230Sstevel@tonic-gate (strcmp(status, ASR_FAILED) != 0))) { 24240Sstevel@tonic-gate return; 24250Sstevel@tonic-gate } 24260Sstevel@tonic-gate /* 24270Sstevel@tonic-gate * more urgent status now, so replace existing value 24280Sstevel@tonic-gate */ 24290Sstevel@tonic-gate err = ptree_get_prop_by_name(chdh, PICL_PROP_STATUS, &proph); 24300Sstevel@tonic-gate if (err != PICL_SUCCESS) 24310Sstevel@tonic-gate return; 24320Sstevel@tonic-gate (void) ptree_delete_prop(proph); 24330Sstevel@tonic-gate (void) ptree_destroy_prop(proph); 24340Sstevel@tonic-gate err = add_status_prop(chdh, status); 24350Sstevel@tonic-gate if (err != PICL_SUCCESS) 24360Sstevel@tonic-gate return; 24370Sstevel@tonic-gate return; 24380Sstevel@tonic-gate } 24390Sstevel@tonic-gate 24400Sstevel@tonic-gate /* 24410Sstevel@tonic-gate * typical case, node needs adding together with a set of properties 24420Sstevel@tonic-gate */ 24430Sstevel@tonic-gate if (ptree_create_and_add_node(nodeh, child, class, &chdh) == 24440Sstevel@tonic-gate PICL_SUCCESS) { 24450Sstevel@tonic-gate (void) add_status_prop(chdh, status); 24460Sstevel@tonic-gate if (unitaddr) { 24470Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 24480Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, 24490Sstevel@tonic-gate PICL_READ, strlen(unitaddr) + 1, 24500Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL); 24510Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, &propinfo, 24520Sstevel@tonic-gate unitaddr, &proph); 24530Sstevel@tonic-gate (void) strlcpy(ptreepath, parent, PATH_MAX); 24540Sstevel@tonic-gate (void) strlcat(ptreepath, "/", PATH_MAX); 24550Sstevel@tonic-gate (void) strlcat(ptreepath, child, PATH_MAX); 24560Sstevel@tonic-gate (void) strlcat(ptreepath, "@", PATH_MAX); 24570Sstevel@tonic-gate (void) strlcat(ptreepath, unitaddr, PATH_MAX); 24580Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 24590Sstevel@tonic-gate PTREE_PROPINFO_VERSION, PICL_PTYPE_CHARSTRING, 24600Sstevel@tonic-gate PICL_READ, strlen(ptreepath) + 1, 24610Sstevel@tonic-gate PICL_PROP_DEVFS_PATH, NULL, NULL); 24620Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, &propinfo, 24630Sstevel@tonic-gate ptreepath, &proph); 24640Sstevel@tonic-gate } 24650Sstevel@tonic-gate next = props; 24660Sstevel@tonic-gate while ((next = parse_props_string(next, &triple)) != NULL) { 24670Sstevel@tonic-gate /* 24680Sstevel@tonic-gate * only handle int and string properties for 24690Sstevel@tonic-gate * simplicity 24700Sstevel@tonic-gate */ 24710Sstevel@tonic-gate if (strcmp(triple.proptype, "I") == 0) { 24720Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 24730Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 24740Sstevel@tonic-gate PICL_PTYPE_INT, PICL_READ, 24750Sstevel@tonic-gate sizeof (int), triple.propname, NULL, NULL); 24760Sstevel@tonic-gate val = atoi(triple.propval); 24770Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, 24780Sstevel@tonic-gate &propinfo, &val, &proph); 24790Sstevel@tonic-gate } else { 24800Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, 24810Sstevel@tonic-gate PTREE_PROPINFO_VERSION, 24820Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, 24830Sstevel@tonic-gate strlen(triple.propval) + 1, 24840Sstevel@tonic-gate triple.propname, NULL, NULL); 24850Sstevel@tonic-gate (void) ptree_create_and_add_prop(chdh, 24860Sstevel@tonic-gate &propinfo, triple.propval, &proph); 24870Sstevel@tonic-gate } 24880Sstevel@tonic-gate } 24890Sstevel@tonic-gate } 24900Sstevel@tonic-gate } 24910Sstevel@tonic-gate 24920Sstevel@tonic-gate static void 24930Sstevel@tonic-gate add_asr_nodes() 24940Sstevel@tonic-gate { 24950Sstevel@tonic-gate char *asrexport; 24960Sstevel@tonic-gate int asrexportlen; 24970Sstevel@tonic-gate asr_conf_entries_t *c = NULL; 24980Sstevel@tonic-gate int i; 24990Sstevel@tonic-gate char *key; 25000Sstevel@tonic-gate char *child; 25010Sstevel@tonic-gate char *unitaddr; 25020Sstevel@tonic-gate uint16_t count; 25030Sstevel@tonic-gate int disabled; 25040Sstevel@tonic-gate 25050Sstevel@tonic-gate if (get_asr_export_list(&asrexport, &asrexportlen) == 0) 25060Sstevel@tonic-gate return; 25070Sstevel@tonic-gate process_asrtree_conf_file(); 25080Sstevel@tonic-gate if (conf_name_asr_map == NULL) 25090Sstevel@tonic-gate return; 25100Sstevel@tonic-gate i = 0; 25110Sstevel@tonic-gate while (i < asrexportlen) { 25120Sstevel@tonic-gate key = &asrexport[i]; 25130Sstevel@tonic-gate i += strlen(key) + 1; 25140Sstevel@tonic-gate if (i >= asrexportlen) 25150Sstevel@tonic-gate break; 25160Sstevel@tonic-gate 25170Sstevel@tonic-gate /* 25180Sstevel@tonic-gate * next byte tells us whether failed by diags or manually 25190Sstevel@tonic-gate * disabled 25200Sstevel@tonic-gate */ 25210Sstevel@tonic-gate disabled = asrexport[i]; 25220Sstevel@tonic-gate i++; 25230Sstevel@tonic-gate if (i >= asrexportlen) 25240Sstevel@tonic-gate break; 25250Sstevel@tonic-gate 25260Sstevel@tonic-gate /* 25270Sstevel@tonic-gate * only type 1 supported 25280Sstevel@tonic-gate */ 25290Sstevel@tonic-gate if (asrexport[i] != 1) 25300Sstevel@tonic-gate break; 25310Sstevel@tonic-gate i++; 25320Sstevel@tonic-gate if (i >= asrexportlen) 25330Sstevel@tonic-gate break; 25340Sstevel@tonic-gate 25350Sstevel@tonic-gate /* 25360Sstevel@tonic-gate * next two bytes give size of reason string 25370Sstevel@tonic-gate */ 25380Sstevel@tonic-gate count = (asrexport[i] << 8) | asrexport[i + 1]; 25390Sstevel@tonic-gate i += count + 2; 25400Sstevel@tonic-gate if (i > asrexportlen) 25410Sstevel@tonic-gate break; 25420Sstevel@tonic-gate 25430Sstevel@tonic-gate /* 25440Sstevel@tonic-gate * now look for key in conf file info 25450Sstevel@tonic-gate */ 25460Sstevel@tonic-gate c = conf_name_asr_map; 25470Sstevel@tonic-gate while (c != NULL) { 25480Sstevel@tonic-gate if (strcmp(key, c->name) == 0) { 25490Sstevel@tonic-gate child = strrchr(c->address, '/'); 25500Sstevel@tonic-gate *child++ = '\0'; 25510Sstevel@tonic-gate unitaddr = strchr(child, '@'); 25520Sstevel@tonic-gate if (unitaddr) 25530Sstevel@tonic-gate *unitaddr++ = '\0'; 25540Sstevel@tonic-gate if (strcmp(c->status, ASR_DISABLED) == 0) { 25550Sstevel@tonic-gate create_asr_node(c->address, child, 25560Sstevel@tonic-gate unitaddr, c->piclclass, disabled ? 25570Sstevel@tonic-gate ASR_DISABLED : ASR_FAILED, 25580Sstevel@tonic-gate c->props); 25590Sstevel@tonic-gate } else { 25600Sstevel@tonic-gate create_asr_node(c->address, child, 25610Sstevel@tonic-gate unitaddr, c->piclclass, c->status, 25620Sstevel@tonic-gate c->props); 25630Sstevel@tonic-gate } 25640Sstevel@tonic-gate } 25650Sstevel@tonic-gate c = c->next; 25660Sstevel@tonic-gate } 25670Sstevel@tonic-gate } 25680Sstevel@tonic-gate 25690Sstevel@tonic-gate free_asr_conf_entries(conf_name_asr_map); 25700Sstevel@tonic-gate free(asrexport); 25710Sstevel@tonic-gate } 25720Sstevel@tonic-gate 25730Sstevel@tonic-gate /* 25740Sstevel@tonic-gate * This function adds information to the /platform node 25750Sstevel@tonic-gate */ 25760Sstevel@tonic-gate static int 25770Sstevel@tonic-gate add_platform_info(picl_nodehdl_t plafh) 25780Sstevel@tonic-gate { 25790Sstevel@tonic-gate struct utsname uts_info; 25800Sstevel@tonic-gate int err; 25810Sstevel@tonic-gate ptree_propinfo_t propinfo; 25820Sstevel@tonic-gate picl_prophdl_t proph; 25830Sstevel@tonic-gate 25840Sstevel@tonic-gate if (uname(&uts_info) < 0) 25850Sstevel@tonic-gate return (PICL_FAILURE); 25860Sstevel@tonic-gate 25870Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 25880Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.sysname) + 1, 25890Sstevel@tonic-gate PICL_PROP_SYSNAME, NULL, NULL); 25900Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.sysname, 25910Sstevel@tonic-gate &proph); 25920Sstevel@tonic-gate if (err != PICL_SUCCESS) 25930Sstevel@tonic-gate return (err); 25940Sstevel@tonic-gate 25950Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 25960Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.nodename) + 1, 25970Sstevel@tonic-gate PICL_PROP_NODENAME, NULL, NULL); 25980Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.nodename, 25990Sstevel@tonic-gate &proph); 26000Sstevel@tonic-gate if (err != PICL_SUCCESS) 26010Sstevel@tonic-gate return (err); 26020Sstevel@tonic-gate 26030Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 26040Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.release) + 1, 26050Sstevel@tonic-gate PICL_PROP_RELEASE, NULL, NULL); 26060Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.release, 26070Sstevel@tonic-gate &proph); 26080Sstevel@tonic-gate if (err != PICL_SUCCESS) 26090Sstevel@tonic-gate return (err); 26100Sstevel@tonic-gate 26110Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 26120Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.version) + 1, 26130Sstevel@tonic-gate PICL_PROP_VERSION, NULL, NULL); 26140Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.version, 26150Sstevel@tonic-gate &proph); 26160Sstevel@tonic-gate if (err != PICL_SUCCESS) 26170Sstevel@tonic-gate return (err); 26180Sstevel@tonic-gate 26190Sstevel@tonic-gate (void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION, 26200Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(uts_info.machine) + 1, 26210Sstevel@tonic-gate PICL_PROP_MACHINE, NULL, NULL); 26220Sstevel@tonic-gate err = ptree_create_and_add_prop(plafh, &propinfo, uts_info.machine, 26230Sstevel@tonic-gate &proph); 26240Sstevel@tonic-gate return (err); 26250Sstevel@tonic-gate } 26260Sstevel@tonic-gate 26270Sstevel@tonic-gate /* 26280Sstevel@tonic-gate * Get first 32-bit value from the reg property 26290Sstevel@tonic-gate */ 26300Sstevel@tonic-gate static int 26310Sstevel@tonic-gate get_first_reg_word(picl_nodehdl_t nodeh, uint32_t *regval) 26320Sstevel@tonic-gate { 26330Sstevel@tonic-gate int err; 26340Sstevel@tonic-gate uint32_t *regbuf; 26350Sstevel@tonic-gate picl_prophdl_t regh; 26360Sstevel@tonic-gate ptree_propinfo_t pinfo; 26370Sstevel@tonic-gate 26380Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 26390Sstevel@tonic-gate if (err != PICL_SUCCESS) /* no reg property */ 26400Sstevel@tonic-gate return (err); 26410Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 26420Sstevel@tonic-gate if (err != PICL_SUCCESS) 26430Sstevel@tonic-gate return (err); 26440Sstevel@tonic-gate if (pinfo.piclinfo.size < sizeof (uint32_t)) /* too small */ 26450Sstevel@tonic-gate return (PICL_FAILURE); 26460Sstevel@tonic-gate regbuf = alloca(pinfo.piclinfo.size); 26470Sstevel@tonic-gate if (regbuf == NULL) 26480Sstevel@tonic-gate return (PICL_FAILURE); 26490Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, pinfo.piclinfo.size); 26500Sstevel@tonic-gate if (err != PICL_SUCCESS) 26510Sstevel@tonic-gate return (err); 26520Sstevel@tonic-gate *regval = *regbuf; /* get first 32-bit value */ 26530Sstevel@tonic-gate return (PICL_SUCCESS); 26540Sstevel@tonic-gate } 26550Sstevel@tonic-gate 26560Sstevel@tonic-gate /* 26570Sstevel@tonic-gate * Get device ID from the reg property 26580Sstevel@tonic-gate */ 26590Sstevel@tonic-gate static int 26600Sstevel@tonic-gate get_device_id(picl_nodehdl_t nodeh, uint32_t *dev_id) 26610Sstevel@tonic-gate { 26620Sstevel@tonic-gate int err; 26630Sstevel@tonic-gate uint32_t regval; 26640Sstevel@tonic-gate 26650Sstevel@tonic-gate err = get_first_reg_word(nodeh, ®val); 26660Sstevel@tonic-gate if (err != PICL_SUCCESS) 26670Sstevel@tonic-gate return (err); 26680Sstevel@tonic-gate 26690Sstevel@tonic-gate *dev_id = PCI_DEVICE_ID(regval); 26700Sstevel@tonic-gate return (PICL_SUCCESS); 26710Sstevel@tonic-gate } 26720Sstevel@tonic-gate 26730Sstevel@tonic-gate /* 26740Sstevel@tonic-gate * add Slot property for children of SBUS node 26750Sstevel@tonic-gate */ 26760Sstevel@tonic-gate /* ARGSUSED */ 26770Sstevel@tonic-gate static int 26780Sstevel@tonic-gate add_sbus_slots(picl_nodehdl_t pcih, void *args) 26790Sstevel@tonic-gate { 26800Sstevel@tonic-gate picl_nodehdl_t nodeh; 26810Sstevel@tonic-gate uint32_t slot; 26820Sstevel@tonic-gate int err; 26830Sstevel@tonic-gate ptree_propinfo_t pinfo; 26840Sstevel@tonic-gate 26850Sstevel@tonic-gate for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 26860Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 26870Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 26880Sstevel@tonic-gate sizeof (picl_nodehdl_t))) { 26890Sstevel@tonic-gate if (err != PICL_SUCCESS) 26900Sstevel@tonic-gate return (err); 26910Sstevel@tonic-gate 26920Sstevel@tonic-gate if (get_first_reg_word(nodeh, &slot) != 0) 26930Sstevel@tonic-gate continue; 26940Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 26950Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t), 26960Sstevel@tonic-gate PICL_PROP_SLOT, NULL, NULL); 26970Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, &slot, NULL); 26980Sstevel@tonic-gate } 26990Sstevel@tonic-gate 27000Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 27010Sstevel@tonic-gate } 27020Sstevel@tonic-gate 27030Sstevel@tonic-gate /* 27040Sstevel@tonic-gate * This function creates a Slot property for SBUS child nodes 27050Sstevel@tonic-gate * which can be correlated with the slot they are plugged into 27060Sstevel@tonic-gate * on the motherboard. 27070Sstevel@tonic-gate */ 27080Sstevel@tonic-gate static int 27090Sstevel@tonic-gate set_sbus_slot(picl_nodehdl_t plafh) 27100Sstevel@tonic-gate { 27110Sstevel@tonic-gate int err; 27120Sstevel@tonic-gate 27130Sstevel@tonic-gate err = ptree_walk_tree_by_class(plafh, PICL_CLASS_SBUS, NULL, 27140Sstevel@tonic-gate add_sbus_slots); 27150Sstevel@tonic-gate 27160Sstevel@tonic-gate return (err); 27170Sstevel@tonic-gate } 27180Sstevel@tonic-gate 27190Sstevel@tonic-gate /* 2720944Svenki * add DeviceID property for children of PCI/PCIEX node 27210Sstevel@tonic-gate */ 27220Sstevel@tonic-gate /* ARGSUSED */ 27230Sstevel@tonic-gate static int 27240Sstevel@tonic-gate add_pci_deviceids(picl_nodehdl_t pcih, void *args) 27250Sstevel@tonic-gate { 27260Sstevel@tonic-gate picl_nodehdl_t nodeh; 27270Sstevel@tonic-gate uint32_t dev_id; 27280Sstevel@tonic-gate int err; 27290Sstevel@tonic-gate ptree_propinfo_t pinfo; 27300Sstevel@tonic-gate 27310Sstevel@tonic-gate for (err = ptree_get_propval_by_name(pcih, PICL_PROP_CHILD, &nodeh, 27320Sstevel@tonic-gate sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND; 27330Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER, &nodeh, 27340Sstevel@tonic-gate sizeof (picl_nodehdl_t))) { 27350Sstevel@tonic-gate if (err != PICL_SUCCESS) 27360Sstevel@tonic-gate return (err); 27370Sstevel@tonic-gate 27380Sstevel@tonic-gate if (get_device_id(nodeh, &dev_id) != 0) 27390Sstevel@tonic-gate continue; 27400Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 27410Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (uint32_t), 27420Sstevel@tonic-gate PICL_PROP_DEVICE_ID, NULL, NULL); 27430Sstevel@tonic-gate (void) ptree_create_and_add_prop(nodeh, &pinfo, &dev_id, NULL); 27440Sstevel@tonic-gate } 27450Sstevel@tonic-gate 27460Sstevel@tonic-gate return (PICL_WALK_CONTINUE); 27470Sstevel@tonic-gate } 27480Sstevel@tonic-gate 27490Sstevel@tonic-gate /* 2750944Svenki * This function creates a DeviceID property for PCI/PCIEX child nodes 27510Sstevel@tonic-gate * which can be correlated with the slot they are plugged into 27520Sstevel@tonic-gate * on the motherboard. 27530Sstevel@tonic-gate */ 2754944Svenki static void 2755944Svenki set_pci_pciex_deviceid(picl_nodehdl_t plafh) 27560Sstevel@tonic-gate { 2757944Svenki (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCI, NULL, 27580Sstevel@tonic-gate add_pci_deviceids); 27590Sstevel@tonic-gate 2760944Svenki (void) ptree_walk_tree_by_class(plafh, PICL_CLASS_PCIEX, NULL, 2761944Svenki add_pci_deviceids); 27620Sstevel@tonic-gate } 27630Sstevel@tonic-gate 27640Sstevel@tonic-gate /* 27650Sstevel@tonic-gate * Default UnitAddress encode function 27660Sstevel@tonic-gate */ 27670Sstevel@tonic-gate static int 27680Sstevel@tonic-gate encode_default_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 27690Sstevel@tonic-gate { 27700Sstevel@tonic-gate int i, len; 27710Sstevel@tonic-gate 27720Sstevel@tonic-gate /* 27730Sstevel@tonic-gate * Encode UnitAddress as %a,%b,%c,...,%n 27740Sstevel@tonic-gate */ 27750Sstevel@tonic-gate if (addrcells < 1) 27760Sstevel@tonic-gate return (-1); 27770Sstevel@tonic-gate 27780Sstevel@tonic-gate len = snprintf(buf, sz, "%x", *regprop); 27790Sstevel@tonic-gate for (i = 1; i < addrcells && len < sz; i++) 27800Sstevel@tonic-gate len += snprintf(&buf[len], sz-len, ",%x", regprop[i]); 27810Sstevel@tonic-gate 27820Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 27830Sstevel@tonic-gate } 27840Sstevel@tonic-gate 27850Sstevel@tonic-gate /* 27860Sstevel@tonic-gate * UnitAddress encode function where the last component is not printed 27870Sstevel@tonic-gate * unless non-zero. 27880Sstevel@tonic-gate */ 27890Sstevel@tonic-gate static int 27900Sstevel@tonic-gate encode_optional_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 27910Sstevel@tonic-gate { 27920Sstevel@tonic-gate int retval; 27930Sstevel@tonic-gate 27940Sstevel@tonic-gate /* 27950Sstevel@tonic-gate * Encode UnitAddress as %a,%b,%c,...,%n where the last component 27960Sstevel@tonic-gate * is printed only if non-zero. 27970Sstevel@tonic-gate */ 27980Sstevel@tonic-gate if (addrcells > 1 && regprop[addrcells-1] == 0) 27990Sstevel@tonic-gate retval = encode_default_unitaddr(buf, sz, regprop, addrcells-1); 28000Sstevel@tonic-gate else 28010Sstevel@tonic-gate retval = encode_default_unitaddr(buf, sz, regprop, addrcells); 28020Sstevel@tonic-gate 28030Sstevel@tonic-gate return (retval); 28040Sstevel@tonic-gate } 28050Sstevel@tonic-gate 28060Sstevel@tonic-gate 28070Sstevel@tonic-gate /* 28080Sstevel@tonic-gate * UnitAddress encode function for SCSI class of devices 28090Sstevel@tonic-gate */ 28100Sstevel@tonic-gate static int 28110Sstevel@tonic-gate encode_scsi_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 28120Sstevel@tonic-gate { 28130Sstevel@tonic-gate int len, retval; 28140Sstevel@tonic-gate 28150Sstevel@tonic-gate /* 28160Sstevel@tonic-gate * #address-cells Format 28170Sstevel@tonic-gate * 2 second component printed only if non-zero 28180Sstevel@tonic-gate * 28190Sstevel@tonic-gate * 4 regprop: phys_hi phys_lo lun_hi lun_lo 28200Sstevel@tonic-gate * UnitAddr: w<phys_hi><phys_lo>,<lun_lo> 28210Sstevel@tonic-gate */ 28220Sstevel@tonic-gate 28230Sstevel@tonic-gate if (addrcells == 2) { 28240Sstevel@tonic-gate retval = encode_optional_unitaddr(buf, sz, regprop, addrcells); 28250Sstevel@tonic-gate } else if (addrcells == 4) { 28260Sstevel@tonic-gate len = snprintf(buf, sz, "w%08x%08x,%x", regprop[0], regprop[1], 28270Sstevel@tonic-gate regprop[3]); 28280Sstevel@tonic-gate retval = (len >= sz) ? -1 : 0; 28290Sstevel@tonic-gate } else 28300Sstevel@tonic-gate retval = -1; 28310Sstevel@tonic-gate 28320Sstevel@tonic-gate return (retval); 28330Sstevel@tonic-gate } 28340Sstevel@tonic-gate 28350Sstevel@tonic-gate /* 28360Sstevel@tonic-gate * UnitAddress encode function for UPA devices 28370Sstevel@tonic-gate */ 28380Sstevel@tonic-gate static int 28390Sstevel@tonic-gate encode_upa_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 28400Sstevel@tonic-gate { 28410Sstevel@tonic-gate int len; 28420Sstevel@tonic-gate 28430Sstevel@tonic-gate if (addrcells != 2) 28440Sstevel@tonic-gate return (-1); 28450Sstevel@tonic-gate 28460Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", (regprop[0]/2)&0x1f, regprop[1]); 28470Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 28480Sstevel@tonic-gate } 28490Sstevel@tonic-gate 28500Sstevel@tonic-gate /* 28510Sstevel@tonic-gate * UnitAddress encode function for GPTWO, JBUS devices 28520Sstevel@tonic-gate */ 28530Sstevel@tonic-gate static int 28540Sstevel@tonic-gate encode_gptwo_jbus_unitaddr(char *buf, int sz, uint32_t *regprop, 28550Sstevel@tonic-gate uint_t addrcells) 28560Sstevel@tonic-gate { 28570Sstevel@tonic-gate uint32_t hi, lo; 28580Sstevel@tonic-gate int len, id, off; 28590Sstevel@tonic-gate 28600Sstevel@tonic-gate if (addrcells != 2) 28610Sstevel@tonic-gate return (-1); 28620Sstevel@tonic-gate 28630Sstevel@tonic-gate hi = regprop[0]; 28640Sstevel@tonic-gate lo = regprop[1]; 28650Sstevel@tonic-gate 28660Sstevel@tonic-gate if (hi & 0x400) { 28670Sstevel@tonic-gate id = ((hi & 0x1) << 9) | (lo >> 23); /* agent id */ 28680Sstevel@tonic-gate off = lo & 0x7fffff; /* config offset */ 28690Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", id, off); 28700Sstevel@tonic-gate } else { 28710Sstevel@tonic-gate len = snprintf(buf, sz, "m%x,%x", hi, lo); 28720Sstevel@tonic-gate } 28730Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 28740Sstevel@tonic-gate } 28750Sstevel@tonic-gate 28760Sstevel@tonic-gate /* 28770Sstevel@tonic-gate * UnitAddress encode function for PCI devices 28780Sstevel@tonic-gate */ 28790Sstevel@tonic-gate static int 28800Sstevel@tonic-gate encode_pci_unitaddr(char *buf, int sz, uint32_t *regprop, uint_t addrcells) 28810Sstevel@tonic-gate { 28820Sstevel@tonic-gate typedef struct { 28830Sstevel@tonic-gate uint32_t n:1, /* relocatable */ 28840Sstevel@tonic-gate p:1, /* prefetchable */ 28850Sstevel@tonic-gate t:1, /* address region aliases */ 28860Sstevel@tonic-gate zero:3, /* must be zero */ 28870Sstevel@tonic-gate ss:2, /* address space type */ 28880Sstevel@tonic-gate bus:8, /* bus number */ 28890Sstevel@tonic-gate dev:5, /* device number */ 28900Sstevel@tonic-gate fn:3, /* function number */ 28910Sstevel@tonic-gate reg:8; /* register number */ 28920Sstevel@tonic-gate uint32_t phys_hi; /* high physical address */ 28930Sstevel@tonic-gate uint32_t phys_lo; /* low physical address */ 28940Sstevel@tonic-gate } pci_addrcell_t; 28950Sstevel@tonic-gate 28960Sstevel@tonic-gate pci_addrcell_t *p; 28970Sstevel@tonic-gate int len; 28980Sstevel@tonic-gate 28990Sstevel@tonic-gate if (addrcells != 3) 29000Sstevel@tonic-gate return (-1); 29010Sstevel@tonic-gate 29020Sstevel@tonic-gate p = (pci_addrcell_t *)regprop; 29030Sstevel@tonic-gate switch (p->ss) { 29040Sstevel@tonic-gate case 0: /* Config */ 29050Sstevel@tonic-gate if (p->fn) 29060Sstevel@tonic-gate len = snprintf(buf, sz, "%x,%x", p->dev, p->fn); 29070Sstevel@tonic-gate else 29080Sstevel@tonic-gate len = snprintf(buf, sz, "%x", p->dev); 29090Sstevel@tonic-gate break; 29100Sstevel@tonic-gate case 1: /* IO */ 29110Sstevel@tonic-gate len = snprintf(buf, sz, "i%x,%x,%x,%x", p->dev, p->fn, p->reg, 29120Sstevel@tonic-gate p->phys_lo); 29130Sstevel@tonic-gate break; 29140Sstevel@tonic-gate case 2: /* Mem32 */ 29150Sstevel@tonic-gate len = snprintf(buf, sz, "m%x,%x,%x,%x", p->dev, p->fn, p->reg, 29160Sstevel@tonic-gate p->phys_lo); 29170Sstevel@tonic-gate break; 29180Sstevel@tonic-gate case 3: /* Mem64 */ 29190Sstevel@tonic-gate len = snprintf(buf, sz, "x%x,%x,%x,%x%08x", p->dev, p->fn, 29200Sstevel@tonic-gate p->reg, p->phys_hi, p->phys_lo); 29210Sstevel@tonic-gate break; 29220Sstevel@tonic-gate } 29230Sstevel@tonic-gate return ((len >= sz) ? -1 : 0); 29240Sstevel@tonic-gate } 29250Sstevel@tonic-gate 29260Sstevel@tonic-gate /* 29270Sstevel@tonic-gate * Get #address-cells property value 29280Sstevel@tonic-gate */ 29290Sstevel@tonic-gate static uint_t 29300Sstevel@tonic-gate get_addrcells_prop(picl_nodehdl_t nodeh) 29310Sstevel@tonic-gate { 29320Sstevel@tonic-gate int len, err; 29330Sstevel@tonic-gate uint32_t addrcells; 29340Sstevel@tonic-gate ptree_propinfo_t pinfo; 29350Sstevel@tonic-gate picl_prophdl_t proph; 29360Sstevel@tonic-gate 29370Sstevel@tonic-gate /* 29380Sstevel@tonic-gate * Get #address-cells property. If not present, use default value. 29390Sstevel@tonic-gate */ 29400Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_PROP_ADDRESS_CELLS, &proph); 29410Sstevel@tonic-gate if (err == PICL_SUCCESS) 29420Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 29430Sstevel@tonic-gate 29440Sstevel@tonic-gate len = pinfo.piclinfo.size; 29450Sstevel@tonic-gate if (err == PICL_SUCCESS && len >= sizeof (uint8_t) && 29460Sstevel@tonic-gate len <= sizeof (addrcells)) { 29470Sstevel@tonic-gate err = ptree_get_propval(proph, &addrcells, len); 29480Sstevel@tonic-gate if (err == PICL_SUCCESS) { 29490Sstevel@tonic-gate if (len == sizeof (uint8_t)) 29500Sstevel@tonic-gate addrcells = *(uint8_t *)&addrcells; 29510Sstevel@tonic-gate else if (len == sizeof (uint16_t)) 29520Sstevel@tonic-gate addrcells = *(uint16_t *)&addrcells; 29530Sstevel@tonic-gate } else 29540Sstevel@tonic-gate addrcells = DEFAULT_ADDRESS_CELLS; 29550Sstevel@tonic-gate } else 29560Sstevel@tonic-gate addrcells = DEFAULT_ADDRESS_CELLS; 29570Sstevel@tonic-gate 29580Sstevel@tonic-gate return (addrcells); 29590Sstevel@tonic-gate } 29600Sstevel@tonic-gate 29610Sstevel@tonic-gate /* 29620Sstevel@tonic-gate * Get UnitAddress mapping entry for a node 29630Sstevel@tonic-gate */ 29640Sstevel@tonic-gate static unitaddr_map_t * 29650Sstevel@tonic-gate get_unitaddr_mapping(picl_nodehdl_t nodeh) 29660Sstevel@tonic-gate { 29670Sstevel@tonic-gate int err; 29680Sstevel@tonic-gate unitaddr_map_t *uamap; 29690Sstevel@tonic-gate char clname[PICL_CLASSNAMELEN_MAX]; 29700Sstevel@tonic-gate 29710Sstevel@tonic-gate /* 29720Sstevel@tonic-gate * Get my classname and locate a function to translate "reg" prop 29730Sstevel@tonic-gate * into "UnitAddress" prop for my children. 29740Sstevel@tonic-gate */ 29750Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, clname, 29760Sstevel@tonic-gate sizeof (clname)); 29770Sstevel@tonic-gate if (err != PICL_SUCCESS) 29780Sstevel@tonic-gate (void) strcpy(clname, ""); /* NULL class name */ 29790Sstevel@tonic-gate 29800Sstevel@tonic-gate for (uamap = &unitaddr_map_table[0]; uamap->class != NULL; uamap++) 29810Sstevel@tonic-gate if (strcmp(clname, uamap->class) == 0) 29820Sstevel@tonic-gate break; 29830Sstevel@tonic-gate 29840Sstevel@tonic-gate return (uamap); 29850Sstevel@tonic-gate } 29860Sstevel@tonic-gate 29870Sstevel@tonic-gate /* 29880Sstevel@tonic-gate * Add UnitAddress property to the specified node 29890Sstevel@tonic-gate */ 29900Sstevel@tonic-gate static int 29910Sstevel@tonic-gate add_unitaddr_prop(picl_nodehdl_t nodeh, unitaddr_map_t *uamap, uint_t addrcells) 29920Sstevel@tonic-gate { 29930Sstevel@tonic-gate int regproplen, err; 29940Sstevel@tonic-gate uint32_t *regbuf; 29950Sstevel@tonic-gate picl_prophdl_t regh; 29960Sstevel@tonic-gate ptree_propinfo_t pinfo; 29970Sstevel@tonic-gate char unitaddr[MAX_UNIT_ADDRESS_LEN]; 29980Sstevel@tonic-gate 29990Sstevel@tonic-gate err = ptree_get_prop_by_name(nodeh, OBP_REG, ®h); 30000Sstevel@tonic-gate if (err != PICL_SUCCESS) 30010Sstevel@tonic-gate return (err); 30020Sstevel@tonic-gate 30030Sstevel@tonic-gate err = ptree_get_propinfo(regh, &pinfo); 30040Sstevel@tonic-gate if (err != PICL_SUCCESS) 30050Sstevel@tonic-gate return (PICL_FAILURE); 30060Sstevel@tonic-gate 30070Sstevel@tonic-gate if (pinfo.piclinfo.size < (addrcells * sizeof (uint32_t))) 30080Sstevel@tonic-gate return (PICL_FAILURE); 30090Sstevel@tonic-gate 30100Sstevel@tonic-gate regproplen = pinfo.piclinfo.size; 30110Sstevel@tonic-gate regbuf = alloca(regproplen); 30120Sstevel@tonic-gate if (regbuf == NULL) 30130Sstevel@tonic-gate return (PICL_FAILURE); 30140Sstevel@tonic-gate 30150Sstevel@tonic-gate err = ptree_get_propval(regh, regbuf, regproplen); 30160Sstevel@tonic-gate if (err != PICL_SUCCESS || uamap->func == NULL || 30170Sstevel@tonic-gate (uamap->addrcellcnt && uamap->addrcellcnt != addrcells) || 30180Sstevel@tonic-gate (uamap->func)(unitaddr, sizeof (unitaddr), regbuf, 30190Sstevel@tonic-gate addrcells) != 0) { 30200Sstevel@tonic-gate return (PICL_FAILURE); 30210Sstevel@tonic-gate } 30220Sstevel@tonic-gate 30230Sstevel@tonic-gate err = ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 30240Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, strlen(unitaddr)+1, 30250Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL); 30260Sstevel@tonic-gate if (err == PICL_SUCCESS) 30270Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &pinfo, unitaddr, NULL); 30280Sstevel@tonic-gate 30290Sstevel@tonic-gate return (err); 30300Sstevel@tonic-gate } 30310Sstevel@tonic-gate 30320Sstevel@tonic-gate /* 30330Sstevel@tonic-gate * work out UnitAddress property of the specified node 30340Sstevel@tonic-gate */ 30350Sstevel@tonic-gate static int 30360Sstevel@tonic-gate get_unitaddr(picl_nodehdl_t parh, picl_nodehdl_t nodeh, char *unitaddr, 30370Sstevel@tonic-gate size_t ualen) 30380Sstevel@tonic-gate { 30390Sstevel@tonic-gate int regproplen, err; 30400Sstevel@tonic-gate uint32_t *regbuf; 30410Sstevel@tonic-gate picl_prophdl_t regh; 30420Sstevel@tonic-gate ptree_propinfo_t pinfo; 30430Sstevel@tonic-gate unitaddr_map_t *uamap; 30440Sstevel@tonic-gate uint32_t addrcells; 30450Sstevel@tonic-gate 30460Sstevel@tonic-gate addrcells = get_addrcells_prop(parh); 30470Sstevel@tonic-gate uamap = get_unitaddr_mapping(parh); 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 (err); 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, ualen, regbuf, addrcells) != 0) { 30690Sstevel@tonic-gate return (PICL_FAILURE); 30700Sstevel@tonic-gate } 30710Sstevel@tonic-gate return (PICL_SUCCESS); 30720Sstevel@tonic-gate } 30730Sstevel@tonic-gate 30740Sstevel@tonic-gate /* 30750Sstevel@tonic-gate * Add UnitAddress property to all children of the specified node 30760Sstevel@tonic-gate */ 30770Sstevel@tonic-gate static int 30780Sstevel@tonic-gate add_unitaddr_prop_to_subtree(picl_nodehdl_t nodeh) 30790Sstevel@tonic-gate { 30800Sstevel@tonic-gate int err; 30810Sstevel@tonic-gate picl_nodehdl_t chdh; 30820Sstevel@tonic-gate unitaddr_map_t *uamap; 30830Sstevel@tonic-gate uint32_t addrcells; 30840Sstevel@tonic-gate 30850Sstevel@tonic-gate /* 30860Sstevel@tonic-gate * Get #address-cells and unit address mapping entry for my 30870Sstevel@tonic-gate * node's class 30880Sstevel@tonic-gate */ 30890Sstevel@tonic-gate addrcells = get_addrcells_prop(nodeh); 30900Sstevel@tonic-gate uamap = get_unitaddr_mapping(nodeh); 30910Sstevel@tonic-gate 30920Sstevel@tonic-gate /* 30930Sstevel@tonic-gate * Add UnitAddress property to my children and their subtree 30940Sstevel@tonic-gate */ 30950Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh, 30960Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 30970Sstevel@tonic-gate 30980Sstevel@tonic-gate while (err == PICL_SUCCESS) { 30990Sstevel@tonic-gate (void) add_unitaddr_prop(chdh, uamap, addrcells); 31000Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(chdh); 31010Sstevel@tonic-gate 31020Sstevel@tonic-gate err = ptree_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh, 31030Sstevel@tonic-gate sizeof (picl_nodehdl_t)); 31040Sstevel@tonic-gate } 31050Sstevel@tonic-gate 31060Sstevel@tonic-gate return (PICL_SUCCESS); 31070Sstevel@tonic-gate } 31080Sstevel@tonic-gate 31090Sstevel@tonic-gate static int 31100Sstevel@tonic-gate update_memory_size_prop(picl_nodehdl_t plafh) 31110Sstevel@tonic-gate { 31120Sstevel@tonic-gate picl_nodehdl_t memh; 31130Sstevel@tonic-gate picl_prophdl_t proph; 31140Sstevel@tonic-gate ptree_propinfo_t pinfo; 31150Sstevel@tonic-gate int err, nspecs, snum, pval; 31160Sstevel@tonic-gate char *regbuf; 31170Sstevel@tonic-gate memspecs_t *mspecs; 31180Sstevel@tonic-gate uint64_t memsize; 31190Sstevel@tonic-gate 31200Sstevel@tonic-gate /* 31210Sstevel@tonic-gate * check if the #size-cells of the platform node is 2 31220Sstevel@tonic-gate */ 31230Sstevel@tonic-gate err = ptree_get_propval_by_name(plafh, OBP_PROP_SIZE_CELLS, &pval, 31240Sstevel@tonic-gate sizeof (pval)); 31250Sstevel@tonic-gate 31260Sstevel@tonic-gate if (err == PICL_PROPNOTFOUND) 31270Sstevel@tonic-gate pval = SUPPORTED_NUM_CELL_SIZE; 31280Sstevel@tonic-gate else if (err != PICL_SUCCESS) 31290Sstevel@tonic-gate return (err); 31300Sstevel@tonic-gate 31310Sstevel@tonic-gate /* 31320Sstevel@tonic-gate * don't know how to handle other vals 31330Sstevel@tonic-gate */ 31340Sstevel@tonic-gate if (pval != SUPPORTED_NUM_CELL_SIZE) 31350Sstevel@tonic-gate return (PICL_FAILURE); 31360Sstevel@tonic-gate 31370Sstevel@tonic-gate err = ptree_get_node_by_path(MEMORY_PATH, &memh); 31380Sstevel@tonic-gate if (err != PICL_SUCCESS) 31390Sstevel@tonic-gate return (err); 31400Sstevel@tonic-gate 31410Sstevel@tonic-gate /* 31420Sstevel@tonic-gate * Get the REG property to calculate the size of memory 31430Sstevel@tonic-gate */ 31440Sstevel@tonic-gate err = ptree_get_prop_by_name(memh, OBP_REG, &proph); 31450Sstevel@tonic-gate if (err != PICL_SUCCESS) 31460Sstevel@tonic-gate return (err); 31470Sstevel@tonic-gate 31480Sstevel@tonic-gate err = ptree_get_propinfo(proph, &pinfo); 31490Sstevel@tonic-gate if (err != PICL_SUCCESS) 31500Sstevel@tonic-gate return (err); 31510Sstevel@tonic-gate 31520Sstevel@tonic-gate regbuf = alloca(pinfo.piclinfo.size); 31530Sstevel@tonic-gate if (regbuf == NULL) 31540Sstevel@tonic-gate return (PICL_FAILURE); 31550Sstevel@tonic-gate 31560Sstevel@tonic-gate err = ptree_get_propval(proph, regbuf, pinfo.piclinfo.size); 31570Sstevel@tonic-gate if (err != PICL_SUCCESS) 31580Sstevel@tonic-gate return (err); 31590Sstevel@tonic-gate 31600Sstevel@tonic-gate mspecs = (memspecs_t *)regbuf; 31610Sstevel@tonic-gate nspecs = pinfo.piclinfo.size / sizeof (memspecs_t); 31620Sstevel@tonic-gate 31630Sstevel@tonic-gate memsize = 0; 31640Sstevel@tonic-gate for (snum = 0; snum < nspecs; ++snum) 31650Sstevel@tonic-gate memsize += mspecs[snum].size; 31660Sstevel@tonic-gate 31670Sstevel@tonic-gate err = ptree_get_prop_by_name(memh, PICL_PROP_SIZE, &proph); 31680Sstevel@tonic-gate if (err == PICL_SUCCESS) { 31690Sstevel@tonic-gate err = ptree_update_propval(proph, &memsize, sizeof (memsize)); 31700Sstevel@tonic-gate return (err); 31710Sstevel@tonic-gate } 31720Sstevel@tonic-gate 31730Sstevel@tonic-gate /* 31740Sstevel@tonic-gate * Add the size property 31750Sstevel@tonic-gate */ 31760Sstevel@tonic-gate (void) ptree_init_propinfo(&pinfo, PTREE_PROPINFO_VERSION, 31770Sstevel@tonic-gate PICL_PTYPE_UNSIGNED_INT, PICL_READ, sizeof (memsize), 31780Sstevel@tonic-gate PICL_PROP_SIZE, NULL, NULL); 31790Sstevel@tonic-gate err = ptree_create_and_add_prop(memh, &pinfo, &memsize, NULL); 31800Sstevel@tonic-gate return (err); 31810Sstevel@tonic-gate } 31820Sstevel@tonic-gate 31830Sstevel@tonic-gate /* 31840Sstevel@tonic-gate * This function is executed as part of .init when the plugin is 31850Sstevel@tonic-gate * dlopen()ed 31860Sstevel@tonic-gate */ 31870Sstevel@tonic-gate static void 31880Sstevel@tonic-gate picldevtree_register(void) 31890Sstevel@tonic-gate { 31900Sstevel@tonic-gate if (getenv(SUNW_PICLDEVTREE_PLUGIN_DEBUG)) 31910Sstevel@tonic-gate picldevtree_debug = 1; 31920Sstevel@tonic-gate (void) picld_plugin_register(&my_reg_info); 31930Sstevel@tonic-gate } 31940Sstevel@tonic-gate 31950Sstevel@tonic-gate /* 31960Sstevel@tonic-gate * This function is the init entry point of the plugin. 31970Sstevel@tonic-gate * It initializes the /platform tree based on libdevinfo 31980Sstevel@tonic-gate */ 31990Sstevel@tonic-gate static void 32000Sstevel@tonic-gate picldevtree_init(void) 32010Sstevel@tonic-gate { 32020Sstevel@tonic-gate picl_nodehdl_t rhdl; 32030Sstevel@tonic-gate int err; 32040Sstevel@tonic-gate struct utsname utsname; 32050Sstevel@tonic-gate picl_nodehdl_t plafh; 32060Sstevel@tonic-gate 32070Sstevel@tonic-gate if (uname(&utsname) < 0) 32080Sstevel@tonic-gate return; 32090Sstevel@tonic-gate 32100Sstevel@tonic-gate (void) strcpy(mach_name, utsname.machine); 32110Sstevel@tonic-gate 32120Sstevel@tonic-gate if (strcmp(mach_name, "sun4u") == 0) { 32130Sstevel@tonic-gate builtin_map_ptr = sun4u_map; 32140Sstevel@tonic-gate builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t); 3215*3941Svenki } else if (strcmp(mach_name, "sun4v") == 0) { 3216*3941Svenki builtin_map_ptr = sun4u_map; 3217*3941Svenki builtin_map_size = sizeof (sun4u_map) / sizeof (builtin_map_t); 32180Sstevel@tonic-gate } else if (strcmp(mach_name, "i86pc") == 0) { 32190Sstevel@tonic-gate builtin_map_ptr = i86pc_map; 32200Sstevel@tonic-gate builtin_map_size = sizeof (i86pc_map) / sizeof (builtin_map_t); 32210Sstevel@tonic-gate } else { 32220Sstevel@tonic-gate builtin_map_ptr = NULL; 32230Sstevel@tonic-gate builtin_map_size = 0; 32240Sstevel@tonic-gate } 32250Sstevel@tonic-gate 32260Sstevel@tonic-gate err = ptree_get_root(&rhdl); 32270Sstevel@tonic-gate if (err != PICL_SUCCESS) { 32280Sstevel@tonic-gate syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED); 32290Sstevel@tonic-gate return; 32300Sstevel@tonic-gate } 32310Sstevel@tonic-gate 32320Sstevel@tonic-gate process_devtree_conf_file(); 32330Sstevel@tonic-gate 32340Sstevel@tonic-gate if (libdevinfo_init(rhdl) != PICL_SUCCESS) { 32350Sstevel@tonic-gate syslog(LOG_ERR, DEVINFO_PLUGIN_INIT_FAILED); 32360Sstevel@tonic-gate return; 32370Sstevel@tonic-gate } 32380Sstevel@tonic-gate 32390Sstevel@tonic-gate err = ptree_get_node_by_path(PLATFORM_PATH, &plafh); 32400Sstevel@tonic-gate if (err != PICL_SUCCESS) 32410Sstevel@tonic-gate return; 32420Sstevel@tonic-gate 32430Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(plafh); 32440Sstevel@tonic-gate 32450Sstevel@tonic-gate add_asr_nodes(); 32460Sstevel@tonic-gate 32470Sstevel@tonic-gate (void) update_memory_size_prop(plafh); 32480Sstevel@tonic-gate 32490Sstevel@tonic-gate (void) setup_cpus(plafh); 32500Sstevel@tonic-gate 32510Sstevel@tonic-gate (void) add_ffb_config_info(plafh); 32520Sstevel@tonic-gate 32530Sstevel@tonic-gate (void) add_platform_info(plafh); 32540Sstevel@tonic-gate 3255944Svenki set_pci_pciex_deviceid(plafh); 32560Sstevel@tonic-gate 32570Sstevel@tonic-gate (void) set_sbus_slot(plafh); 32580Sstevel@tonic-gate 32590Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 32600Sstevel@tonic-gate picldevtree_evhandler, NULL); 32610Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 32620Sstevel@tonic-gate picldevtree_evhandler, NULL); 32630Sstevel@tonic-gate } 32640Sstevel@tonic-gate 32650Sstevel@tonic-gate /* 32660Sstevel@tonic-gate * This function is the fini entry point of the plugin 32670Sstevel@tonic-gate */ 32680Sstevel@tonic-gate static void 32690Sstevel@tonic-gate picldevtree_fini(void) 32700Sstevel@tonic-gate { 32710Sstevel@tonic-gate /* First unregister the event handlers */ 32720Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED, 32730Sstevel@tonic-gate picldevtree_evhandler, NULL); 32740Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_SYSEVENT_DEVICE_REMOVED, 32750Sstevel@tonic-gate picldevtree_evhandler, NULL); 32760Sstevel@tonic-gate 32770Sstevel@tonic-gate conf_name_class_map = free_conf_entries(conf_name_class_map); 32780Sstevel@tonic-gate } 32790Sstevel@tonic-gate 32800Sstevel@tonic-gate /* 32810Sstevel@tonic-gate * This function is the event handler of this plug-in. 32820Sstevel@tonic-gate * 32830Sstevel@tonic-gate * It processes the following events: 32840Sstevel@tonic-gate * 32850Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_ADDED 32860Sstevel@tonic-gate * PICLEVENT_SYSEVENT_DEVICE_REMOVED 32870Sstevel@tonic-gate */ 32880Sstevel@tonic-gate /* ARGSUSED */ 32890Sstevel@tonic-gate static void 32900Sstevel@tonic-gate picldevtree_evhandler(const char *ename, const void *earg, size_t size, 32910Sstevel@tonic-gate void *cookie) 32920Sstevel@tonic-gate { 32930Sstevel@tonic-gate char *devfs_path; 32940Sstevel@tonic-gate char ptreepath[PATH_MAX]; 32950Sstevel@tonic-gate char dipath[PATH_MAX]; 32960Sstevel@tonic-gate picl_nodehdl_t plafh; 32970Sstevel@tonic-gate picl_nodehdl_t nodeh; 32980Sstevel@tonic-gate nvlist_t *nvlp; 32990Sstevel@tonic-gate 33000Sstevel@tonic-gate if (earg == NULL) 33010Sstevel@tonic-gate return; 33020Sstevel@tonic-gate 33030Sstevel@tonic-gate nvlp = NULL; 33040Sstevel@tonic-gate if (ptree_get_node_by_path(PLATFORM_PATH, &plafh) != PICL_SUCCESS || 33050Sstevel@tonic-gate nvlist_unpack((char *)earg, size, &nvlp, NULL) || 33060Sstevel@tonic-gate nvlist_lookup_string(nvlp, PICLEVENTARG_DEVFS_PATH, &devfs_path) || 33070Sstevel@tonic-gate strlen(devfs_path) > (PATH_MAX - sizeof (PLATFORM_PATH))) { 33080Sstevel@tonic-gate syslog(LOG_INFO, PICL_EVENT_DROPPED, ename); 33090Sstevel@tonic-gate if (nvlp) 33100Sstevel@tonic-gate nvlist_free(nvlp); 33110Sstevel@tonic-gate return; 33120Sstevel@tonic-gate } 33130Sstevel@tonic-gate 33140Sstevel@tonic-gate (void) strlcpy(ptreepath, PLATFORM_PATH, PATH_MAX); 33150Sstevel@tonic-gate (void) strlcat(ptreepath, devfs_path, PATH_MAX); 33160Sstevel@tonic-gate (void) strlcpy(dipath, devfs_path, PATH_MAX); 33170Sstevel@tonic-gate nvlist_free(nvlp); 33180Sstevel@tonic-gate 33190Sstevel@tonic-gate if (picldevtree_debug) 33200Sstevel@tonic-gate syslog(LOG_INFO, "picldevtree: event handler invoked ename:%s " 33210Sstevel@tonic-gate "ptreepath:%s\n", ename, ptreepath); 33220Sstevel@tonic-gate 33230Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) == 0) { 33240Sstevel@tonic-gate di_node_t devnode; 33250Sstevel@tonic-gate char *strp; 33260Sstevel@tonic-gate picl_nodehdl_t parh; 33270Sstevel@tonic-gate char nodeclass[PICL_CLASSNAMELEN_MAX]; 33280Sstevel@tonic-gate char *nodename; 33290Sstevel@tonic-gate int err; 33300Sstevel@tonic-gate 33310Sstevel@tonic-gate /* If the node already exist, then nothing else to do here */ 33320Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) == PICL_SUCCESS) 33330Sstevel@tonic-gate return; 33340Sstevel@tonic-gate 33350Sstevel@tonic-gate /* Skip if unable to find parent PICL node handle */ 33360Sstevel@tonic-gate parh = plafh; 33370Sstevel@tonic-gate if (((strp = strrchr(ptreepath, '/')) != NULL) && 33380Sstevel@tonic-gate (strp != strchr(ptreepath, '/'))) { 33390Sstevel@tonic-gate *strp = '\0'; 33400Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &parh) != 33410Sstevel@tonic-gate PICL_SUCCESS) 33420Sstevel@tonic-gate return; 33430Sstevel@tonic-gate } 33440Sstevel@tonic-gate 33450Sstevel@tonic-gate /* 33460Sstevel@tonic-gate * If parent is the root node 33470Sstevel@tonic-gate */ 33480Sstevel@tonic-gate if (parh == plafh) { 33490Sstevel@tonic-gate ph = di_prom_init(); 33500Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 33510Sstevel@tonic-gate if (devnode == DI_NODE_NIL) { 33520Sstevel@tonic-gate if (ph != NULL) { 33530Sstevel@tonic-gate di_prom_fini(ph); 33540Sstevel@tonic-gate ph = NULL; 33550Sstevel@tonic-gate } 33560Sstevel@tonic-gate return; 33570Sstevel@tonic-gate } 33580Sstevel@tonic-gate nodename = di_node_name(devnode); 33590Sstevel@tonic-gate if (nodename == NULL) { 33600Sstevel@tonic-gate di_fini(devnode); 33610Sstevel@tonic-gate if (ph != NULL) { 33620Sstevel@tonic-gate di_prom_fini(ph); 33630Sstevel@tonic-gate ph = NULL; 33640Sstevel@tonic-gate } 33650Sstevel@tonic-gate return; 33660Sstevel@tonic-gate } 33670Sstevel@tonic-gate 33680Sstevel@tonic-gate err = get_node_class(nodeclass, devnode, nodename); 33690Sstevel@tonic-gate if (err < 0) { 33700Sstevel@tonic-gate di_fini(devnode); 33710Sstevel@tonic-gate if (ph != NULL) { 33720Sstevel@tonic-gate di_prom_fini(ph); 33730Sstevel@tonic-gate ph = NULL; 33740Sstevel@tonic-gate } 33750Sstevel@tonic-gate return; 33760Sstevel@tonic-gate } 33770Sstevel@tonic-gate err = construct_devtype_node(plafh, nodename, 33780Sstevel@tonic-gate nodeclass, devnode, &nodeh); 33790Sstevel@tonic-gate if (err != PICL_SUCCESS) { 33800Sstevel@tonic-gate di_fini(devnode); 33810Sstevel@tonic-gate if (ph != NULL) { 33820Sstevel@tonic-gate di_prom_fini(ph); 33830Sstevel@tonic-gate ph = NULL; 33840Sstevel@tonic-gate } 33850Sstevel@tonic-gate return; 33860Sstevel@tonic-gate } 33870Sstevel@tonic-gate (void) update_subtree(nodeh, devnode); 33880Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(nodeh); 33890Sstevel@tonic-gate if (ph != NULL) { 33900Sstevel@tonic-gate di_prom_fini(ph); 33910Sstevel@tonic-gate ph = NULL; 33920Sstevel@tonic-gate } 33930Sstevel@tonic-gate di_fini(devnode); 33940Sstevel@tonic-gate goto done; 33950Sstevel@tonic-gate } 33960Sstevel@tonic-gate 33970Sstevel@tonic-gate /* kludge ... try without bus-addr first */ 33980Sstevel@tonic-gate if ((strp = strrchr(dipath, '@')) != NULL) { 33990Sstevel@tonic-gate char *p; 34000Sstevel@tonic-gate 34010Sstevel@tonic-gate p = strrchr(dipath, '/'); 34020Sstevel@tonic-gate if (p != NULL && strp > p) { 34030Sstevel@tonic-gate *strp = '\0'; 34040Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 34050Sstevel@tonic-gate if (devnode != DI_NODE_NIL) 34060Sstevel@tonic-gate di_fini(devnode); 34070Sstevel@tonic-gate *strp = '@'; 34080Sstevel@tonic-gate } 34090Sstevel@tonic-gate } 34100Sstevel@tonic-gate /* Get parent devnode */ 34110Sstevel@tonic-gate if ((strp = strrchr(dipath, '/')) != NULL) 34120Sstevel@tonic-gate *++strp = '\0'; 34130Sstevel@tonic-gate devnode = di_init(dipath, DINFOCPYALL); 34140Sstevel@tonic-gate if (devnode == DI_NODE_NIL) 34150Sstevel@tonic-gate return; 34160Sstevel@tonic-gate ph = di_prom_init(); 34170Sstevel@tonic-gate (void) update_subtree(parh, devnode); 34180Sstevel@tonic-gate (void) add_unitaddr_prop_to_subtree(parh); 34190Sstevel@tonic-gate if (ph) { 34200Sstevel@tonic-gate di_prom_fini(ph); 34210Sstevel@tonic-gate ph = NULL; 34220Sstevel@tonic-gate } 34230Sstevel@tonic-gate di_fini(devnode); 34240Sstevel@tonic-gate } else if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_REMOVED) == 0) { 34250Sstevel@tonic-gate char delclass[PICL_CLASSNAMELEN_MAX]; 34260Sstevel@tonic-gate char *strp; 34270Sstevel@tonic-gate 34280Sstevel@tonic-gate /* 34290Sstevel@tonic-gate * if final element of path doesn't have a unit address 34300Sstevel@tonic-gate * then it is not uniquely identifiable - cannot remove 34310Sstevel@tonic-gate */ 34320Sstevel@tonic-gate if (((strp = strrchr(ptreepath, '/')) != NULL) && 34330Sstevel@tonic-gate strchr(strp, '@') == NULL) 34340Sstevel@tonic-gate return; 34350Sstevel@tonic-gate 34360Sstevel@tonic-gate /* skip if can't find the node */ 34370Sstevel@tonic-gate if (ptree_get_node_by_path(ptreepath, &nodeh) != PICL_SUCCESS) 34380Sstevel@tonic-gate return; 34390Sstevel@tonic-gate 34400Sstevel@tonic-gate if (ptree_delete_node(nodeh) != PICL_SUCCESS) 34410Sstevel@tonic-gate return; 34420Sstevel@tonic-gate 34430Sstevel@tonic-gate if (picldevtree_debug) 34440Sstevel@tonic-gate syslog(LOG_INFO, 34450Sstevel@tonic-gate "picldevtree: deleted node nodeh:%llx\n", nodeh); 34460Sstevel@tonic-gate if ((ptree_get_propval_by_name(nodeh, 34470Sstevel@tonic-gate PICL_PROP_CLASSNAME, delclass, PICL_CLASSNAMELEN_MAX) == 34480Sstevel@tonic-gate PICL_SUCCESS) && IS_MC(delclass)) { 34490Sstevel@tonic-gate if (post_mc_event(PICLEVENT_MC_REMOVED, nodeh) != 34500Sstevel@tonic-gate PICL_SUCCESS) 34510Sstevel@tonic-gate syslog(LOG_WARNING, PICL_EVENT_DROPPED, 34520Sstevel@tonic-gate PICLEVENT_MC_REMOVED); 34530Sstevel@tonic-gate } else 34540Sstevel@tonic-gate (void) ptree_destroy_node(nodeh); 34550Sstevel@tonic-gate } 34560Sstevel@tonic-gate done: 34570Sstevel@tonic-gate (void) setup_cpus(plafh); 34580Sstevel@tonic-gate (void) add_ffb_config_info(plafh); 3459944Svenki set_pci_pciex_deviceid(plafh); 34600Sstevel@tonic-gate (void) set_sbus_slot(plafh); 34610Sstevel@tonic-gate if (picldevtree_debug > 1) 34620Sstevel@tonic-gate syslog(LOG_INFO, "picldevtree: event handler done\n"); 34630Sstevel@tonic-gate } 3464