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
51103Sjbeloro * Common Development and Distribution License (the "License").
61103Sjbeloro * 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 */
211103Sjbeloro
220Sstevel@tonic-gate /*
23*12601SJustin.Frank@Sun.COM * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <stddef.h>
280Sstevel@tonic-gate #include <syslog.h>
290Sstevel@tonic-gate #include <strings.h>
300Sstevel@tonic-gate #include <unistd.h>
310Sstevel@tonic-gate #include <libintl.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include <ctype.h>
340Sstevel@tonic-gate #include <picl.h>
350Sstevel@tonic-gate #include <picltree.h>
360Sstevel@tonic-gate #include <picld_pluginutil.h>
370Sstevel@tonic-gate #include <sys/types.h>
380Sstevel@tonic-gate #include <sys/stat.h>
390Sstevel@tonic-gate #include <fcntl.h>
400Sstevel@tonic-gate #include <dirent.h>
410Sstevel@tonic-gate #include <sys/sysevent/dr.h>
420Sstevel@tonic-gate #include <pthread.h>
430Sstevel@tonic-gate #include <libdevinfo.h>
440Sstevel@tonic-gate #include <limits.h>
450Sstevel@tonic-gate #include <sys/systeminfo.h>
460Sstevel@tonic-gate #include <sys/envmon.h>
470Sstevel@tonic-gate #include <i2c_gpio.h>
480Sstevel@tonic-gate #include "libdevice.h"
490Sstevel@tonic-gate #include "picldefs.h"
500Sstevel@tonic-gate #include <sys/raidioctl.h>
510Sstevel@tonic-gate #include <sys/param.h>
521103Sjbeloro #include <sys/epic.h>
530Sstevel@tonic-gate
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate * Plugin registration entry points
560Sstevel@tonic-gate */
570Sstevel@tonic-gate static void piclfrudr_register(void);
580Sstevel@tonic-gate static void piclfrudr_init(void);
590Sstevel@tonic-gate static void piclfrudr_fini(void);
601103Sjbeloro static void rmc_state_event(void);
611103Sjbeloro static void seattle_setleds(void);
621103Sjbeloro static void boston_set_frontleds(const char *, int);
631103Sjbeloro static void boston_set_rearleds(const char *, int);
641103Sjbeloro
650Sstevel@tonic-gate #pragma init(piclfrudr_register)
660Sstevel@tonic-gate
670Sstevel@tonic-gate static picld_plugin_reg_t my_reg_info = {
680Sstevel@tonic-gate PICLD_PLUGIN_VERSION_1,
690Sstevel@tonic-gate PICLD_PLUGIN_CRITICAL,
700Sstevel@tonic-gate "SUNW_MPXU_frudr",
710Sstevel@tonic-gate piclfrudr_init,
720Sstevel@tonic-gate piclfrudr_fini,
730Sstevel@tonic-gate };
740Sstevel@tonic-gate
750Sstevel@tonic-gate /*
760Sstevel@tonic-gate * Log message texts
770Sstevel@tonic-gate */
780Sstevel@tonic-gate #define EM_THREAD_CREATE_FAILED gettext("piclfrudr: pthread_create failed: %s")
790Sstevel@tonic-gate #define DELETE_PROP_FAIL gettext("ptree_delete_prop failed: %d")
800Sstevel@tonic-gate #define EM_DI_INIT_FAIL gettext("piclfrudr: di_init failed: %s")
810Sstevel@tonic-gate #define PROPINFO_FAIL gettext("ptree_init_propinfo %s failed: %d")
820Sstevel@tonic-gate #define ADD_NODE_FAIL gettext("ptree_create_and_add_node %s failed: %d")
830Sstevel@tonic-gate #define ADD_TBL_ENTRY_FAIL gettext("piclfrudr: cannot add entry to table")
840Sstevel@tonic-gate #define EM_POLL_FAIL gettext("piclfrudr: poll() failed: %s")
850Sstevel@tonic-gate #define ADD_PROP_FAIL gettext("ptree_create_and_add_prop %s failed: %d")
860Sstevel@tonic-gate #define EM_MUTEX_FAIL gettext("piclfrudr: pthread_mutex_lock returned: %s")
870Sstevel@tonic-gate #define EM_UNK_FRU gettext("piclfrudr: Fru removed event for unknown node")
880Sstevel@tonic-gate #define PARSE_CONF_FAIL gettext("parse config file %s failed")
890Sstevel@tonic-gate #define EM_NO_SC_DEV gettext("piclfrudr: failed to locate SC device node")
900Sstevel@tonic-gate #define EM_NO_SYSINFO gettext("piclfrudr: failed to get SC sysinfo: %s")
910Sstevel@tonic-gate
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate * PICL property values
940Sstevel@tonic-gate */
950Sstevel@tonic-gate #define PICL_PROPVAL_ON "ON"
960Sstevel@tonic-gate #define PICL_PROPVAL_OFF "OFF"
970Sstevel@tonic-gate
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate * Local defines
1000Sstevel@tonic-gate */
1010Sstevel@tonic-gate #define SEEPROM_DRIVER_NAME "seeprom"
1020Sstevel@tonic-gate #define FRUTREE_PATH "/frutree"
1030Sstevel@tonic-gate #define CHASSIS_LOC_PATH "/frutree/chassis/%s"
1040Sstevel@tonic-gate #define SYS_BOARD_PATH "/frutree/chassis/MB/system-board/%s"
1051103Sjbeloro #define SEATTLE1U_HDDBP_PATH \
1061103Sjbeloro "/frutree/chassis/MB/system-board/HDDBP/disk-backplane-1/%s"
1071103Sjbeloro #define SEATTLE2U_HDDBP_PATH \
1081103Sjbeloro "/frutree/chassis/MB/system-board/HDDBP/disk-backplane-3/%s"
1091103Sjbeloro #define BOSTON_HDDBP_PATH \
1101103Sjbeloro "/frutree/chassis/MB/system-board/HDDCNTRL/disk-controller/HDDBP" \
1111103Sjbeloro "/disk-backplane-8/%s"
1121103Sjbeloro
1130Sstevel@tonic-gate #define CONFFILE_PREFIX "fru_"
1140Sstevel@tonic-gate #define CONFFILE_SUFFIX ".conf"
1150Sstevel@tonic-gate #define CONFFILE_FRUTREE "piclfrutree.conf"
1160Sstevel@tonic-gate #define PS_NAME "PS"
1170Sstevel@tonic-gate #define PS_NAME_LEN 2
1180Sstevel@tonic-gate #define PS_FRU_NAME "power-supply"
1190Sstevel@tonic-gate #define PS_PLATFORM_NAME "power-supply-fru-prom"
1200Sstevel@tonic-gate #define DISK_NAME "HDD"
1210Sstevel@tonic-gate #define DISK_NAME_LEN 3
1220Sstevel@tonic-gate #define DISK_FRU_NAME "disk"
1230Sstevel@tonic-gate #define SCC_NAME "SCC"
1240Sstevel@tonic-gate #define SCC_NAME_LEN 3
1250Sstevel@tonic-gate #define SCC_FRU_NAME "scc"
1260Sstevel@tonic-gate #define RMC_NAME "SC"
1270Sstevel@tonic-gate #define RMC_NAME_LEN 2
1280Sstevel@tonic-gate #define RMC_FRU_NAME "sc"
1292606Svenki #define FT_NAME "FT"
1302606Svenki #define FT_NAME_LEN 2
131*12601SJustin.Frank@Sun.COM #define F0_NAME "F0"
132*12601SJustin.Frank@Sun.COM #define F0_NAME_LEN 2
133*12601SJustin.Frank@Sun.COM #define F1_NAME "F1"
134*12601SJustin.Frank@Sun.COM #define F1_NAME_LEN 2
1352606Svenki #define FT_FRU_NAME "fan-tray"
136*12601SJustin.Frank@Sun.COM #define FT_FRU_NAME_LEN 8
1372606Svenki #define FT_ID_BUFSZ (FT_NAME_LEN + 2)
1380Sstevel@tonic-gate #define DEV_PREFIX "/devices"
1390Sstevel@tonic-gate #define ENXS_FRONT_SRVC_LED 0x20
1400Sstevel@tonic-gate #define ENXS_FRONT_ACT_LED 0x10
1410Sstevel@tonic-gate #define ENXS_REAR_SRVC_LED 0x20
1420Sstevel@tonic-gate #define ENXS_REAR_ACT_LED 0x10
1430Sstevel@tonic-gate #define ENTS_SRVC_LED 0x20
1440Sstevel@tonic-gate #define ENTS_ACT_LED 0x10
1450Sstevel@tonic-gate #define V440_SRVC_LED 0x2
1460Sstevel@tonic-gate #define V440_ACT_LED 0x1
1471103Sjbeloro #define BOSTON_FRONT_SRVC_LED 0x2
1481103Sjbeloro #define BOSTON_FRONT_ACT_LED 0x4
1491103Sjbeloro #define BOSTON_FRONT_CLEAR_DIR 0x0
1501103Sjbeloro #define BOSTON_FRONT_CLEAR_POL 0x0
1511103Sjbeloro #define BOSTON_FRONT_LED_MASK 0xffffffff
1521467Sfw157321 #define BOSTON_REAR_SRVC_LED 0x8000
1531467Sfw157321 #define BOSTON_REAR_ACT_LED 0x2000
1541103Sjbeloro #define BOSTON_REAR_CLEAR_POL 0x0000
1551103Sjbeloro #define BOSTON_REAR_LED_MASK 0xe000
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate /*
1580Sstevel@tonic-gate * PSU defines
1590Sstevel@tonic-gate */
1600Sstevel@tonic-gate #define PSU_I2C_BUS_DEV "/devices/pci@1e,600000/isa@7/i2c@0,320:devctl"
1610Sstevel@tonic-gate #define PSU_DEV \
1620Sstevel@tonic-gate "/devices/pci@1e,600000/isa@7/i2c@0,320/power-supply-fru-prom@0,%x"
1630Sstevel@tonic-gate #define PSU_PLATFORM "/platform/pci@1e,600000/isa@7/i2c@0,320"
1640Sstevel@tonic-gate #define PS0_ADDR ((sys_platform == PLAT_CHALUPA19) ? 0xc0 : 0xb0)
1650Sstevel@tonic-gate #define PS1_ADDR ((sys_platform == PLAT_CHALUPA19) ? 0xc2 : 0xa4)
1660Sstevel@tonic-gate #define PS2_ADDR 0x70
1670Sstevel@tonic-gate #define PS3_ADDR 0x72
1680Sstevel@tonic-gate #define PS0_UNITADDR ((sys_platform == PLAT_CHALUPA19) ? "0,c0" : "0,b0")
1690Sstevel@tonic-gate #define PS1_UNITADDR ((sys_platform == PLAT_CHALUPA19) ? "0,c2" : "0,a4")
1700Sstevel@tonic-gate #define PS2_UNITADDR "0,70"
1710Sstevel@tonic-gate #define PS3_UNITADDR "0,72"
1720Sstevel@tonic-gate #define PS0_NAME "PS0"
1730Sstevel@tonic-gate #define PS1_NAME "PS1"
1740Sstevel@tonic-gate #define PS2_NAME "PS2"
1750Sstevel@tonic-gate #define PS3_NAME "PS3"
1760Sstevel@tonic-gate #define PSU0_NAME "PSU0"
1770Sstevel@tonic-gate #define PSU1_NAME "PSU1"
1780Sstevel@tonic-gate #define PSU2_NAME "PSU2"
1790Sstevel@tonic-gate #define PSU3_NAME "PSU3"
1800Sstevel@tonic-gate #define PS_DEVICE_NAME "power-supply-fru-prom"
1812392Svenki #define PSU_COMPATIBLE "i2c-at24c64"
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate /*
1841103Sjbeloro * Seattle/Boston PSU defines
1851103Sjbeloro */
1861103Sjbeloro #define SEATTLE_PSU_I2C_BUS_DEV "/devices/i2c@1f,530000:devctl"
1871103Sjbeloro #define SEATTLE_PSU_DEV \
1881103Sjbeloro "/devices/i2c@1f,530000/power-supply-fru-prom@0,%x"
1891103Sjbeloro #define SEATTLE_PSU_PLATFORM "/platform/i2c@1f,530000"
1901103Sjbeloro #define SEATTLE_PS0_ADDR 0x6c
1911103Sjbeloro #define SEATTLE_PS1_ADDR 0x6e
1921103Sjbeloro #define SEATTLE_PS0_UNITADDR "0,6c"
1931103Sjbeloro #define SEATTLE_PS1_UNITADDR "0,6e"
1942392Svenki #define SEATTLE_PSU_COMPATIBLE "i2c-at34c02"
1951103Sjbeloro #define BOSTON_PSU_I2C_BUS_DEV "/devices/i2c@1f,520000:devctl"
1961103Sjbeloro #define BOSTON_PSU_DEV \
1971103Sjbeloro "/devices/i2c@1f,520000/power-supply-fru-prom@0,%x"
1981103Sjbeloro #define BOSTON_PSU_PLATFORM "/platform/i2c@1f,520000"
1991103Sjbeloro #define BOSTON_PS0_ADDR 0x24
2001103Sjbeloro #define BOSTON_PS1_ADDR 0x32
2011103Sjbeloro #define BOSTON_PS2_ADDR 0x52
2021103Sjbeloro #define BOSTON_PS3_ADDR 0x72
2031103Sjbeloro #define BOSTON_PS0_UNITADDR "0,24"
2041103Sjbeloro #define BOSTON_PS1_UNITADDR "0,32"
2051103Sjbeloro #define BOSTON_PS2_UNITADDR "0,52"
2061103Sjbeloro #define BOSTON_PS3_UNITADDR "0,72"
2072392Svenki #define BOSTON_PSU_COMPATIBLE "i2c-at34c02"
2081103Sjbeloro
2091103Sjbeloro /*
2102606Svenki * Seattle fan-tray paths
2112606Svenki */
2122606Svenki #define SEATTLE_FCB0_1U \
2132606Svenki "/frutree/chassis/MB/system-board/FIOB/front-io-board-1" \
2142606Svenki "/FCB0/fan-connector-board/%s"
2152606Svenki #define SEATTLE_FCB1_1U \
2162606Svenki "/frutree/chassis/MB/system-board/FIOB/front-io-board-1" \
2172606Svenki "/FCB1/fan-connector-board/%s"
2182606Svenki #define SEATTLE_PDB_1U \
2192606Svenki "/frutree/chassis/PDB/power-distribution-board/%s"
2202606Svenki #define SEATTLE_FCB0_2U \
2212606Svenki "/frutree/chassis/MB/system-board/FIOB/front-io-board-2" \
2222606Svenki "/FCB0/fan-connector-board/%s"
2232606Svenki #define SEATTLE_FCB1_2U \
2242606Svenki "/frutree/chassis/MB/system-board/FIOB/front-io-board-2" \
2252606Svenki "/FCB1/fan-connector-board/%s"
2262606Svenki #define SEATTLE_PDB_2U \
2272606Svenki "/frutree/chassis/PDB/power-distribution-board" \
2282606Svenki "/HDDFB/fan-connector-board/%s"
2292606Svenki
2302606Svenki /*
2310Sstevel@tonic-gate * disk defines
2320Sstevel@tonic-gate */
2330Sstevel@tonic-gate #define REMOK_LED "OK2RM"
2340Sstevel@tonic-gate #define FAULT_LED "SERVICE"
2350Sstevel@tonic-gate #define PLATFORMLEN 9
2360Sstevel@tonic-gate #define N_DISKS 8
2370Sstevel@tonic-gate #define N_CHALUPA_DISKS 4
2380Sstevel@tonic-gate #define N_ENTS_DISKS 8
2390Sstevel@tonic-gate #define N_MPXU_DISKS 4
2400Sstevel@tonic-gate #define N_EN19_DISKS 2
2410Sstevel@tonic-gate #define DISK_POLL_TIME 5000
2420Sstevel@tonic-gate /* For V440 RAID policy */
2430Sstevel@tonic-gate #define V440_DISK_DEVCTL "/devices/pci@1f,700000/scsi@2:devctl"
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate /*
2461103Sjbeloro * Seattle/Boston disk defines
2471103Sjbeloro */
2481103Sjbeloro #define N_SEATTLE1U_DISKS 2
2491103Sjbeloro #define N_SEATTLE2U_DISKS 4
2501103Sjbeloro #define N_BOSTON_DISKS 8
2511103Sjbeloro #define SEATTLE_DISK_DEVCTL \
2521103Sjbeloro "/devices/pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1:devctl"
2531296Sfw157321 #define BOSTON_DISK_DEVCTL_1068X \
2541103Sjbeloro "/devices/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1:devctl"
2551296Sfw157321 #define BOSTON_DISK_DEVCTL_1068E \
2561296Sfw157321 "/devices/pci@1e,600000/pci@0/pci@2/scsi@0:devctl"
2571103Sjbeloro
2581103Sjbeloro /*
2590Sstevel@tonic-gate * led defines
2600Sstevel@tonic-gate */
2610Sstevel@tonic-gate #define ENXS_LED_DIR "/devices/pci@1e,600000/isa@7/i2c@0,320/"
2620Sstevel@tonic-gate #define ENXS_FRONT_LEDS "gpio@0,70:"
2630Sstevel@tonic-gate #define ENXS_REAR_LEDS ENXS_LED_DIR "gpio@0,44:port_1"
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate #define ENTS_LED_DIR "/devices/pci@1e,600000/isa@7/i2c@0,320/"
2660Sstevel@tonic-gate #define ENTS_LEDS "gpio@0,70:"
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate #define V440_LED_DIR "/devices/pci@1e,600000/isa@7/i2c@0,320/"
2690Sstevel@tonic-gate #define V440_LED_PATH V440_LED_DIR "gpio@0,48:port_0"
2700Sstevel@tonic-gate
2711103Sjbeloro /*
2721103Sjbeloro * Seattle/Boston led defines
2731103Sjbeloro */
2741103Sjbeloro #define SEATTLE_LED_DEV "/devices/ebus@1f,464000/env-monitor@3,0:env-monitor0"
2751103Sjbeloro #define BOSTON_LED_DIR "/devices/i2c@1f,520000/"
2761103Sjbeloro #define BOSTON_FRONT_LED_PATH BOSTON_LED_DIR "gpio@0,3a:port_0"
2771103Sjbeloro #define BOSTON_REAR_LED_PATH BOSTON_LED_DIR "hardware-monitor@0,5c:adm1026"
2781103Sjbeloro
2791103Sjbeloro /*
2801103Sjbeloro * Seattle/Boston USB defines
2811103Sjbeloro */
2821103Sjbeloro #define MAX_USB_PORTS 4
2831103Sjbeloro #define USB_CONF_FILE_NAME "usb-a-"
2841103Sjbeloro
2850Sstevel@tonic-gate typedef struct id_props {
2860Sstevel@tonic-gate envmon_handle_t envhandle;
2870Sstevel@tonic-gate picl_prophdl_t volprop;
2880Sstevel@tonic-gate } id_props_t;
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate typedef struct idp_lkup {
2910Sstevel@tonic-gate int maxnum; /* entries in array */
2920Sstevel@tonic-gate int num; /* entries in use */
2930Sstevel@tonic-gate id_props_t idp[1];
2940Sstevel@tonic-gate } idp_lkup_t;
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate /*
2970Sstevel@tonic-gate * table for mapping RMC handles to volatile property handles
2980Sstevel@tonic-gate */
2990Sstevel@tonic-gate static idp_lkup_t *idprop = NULL;
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate /*
3020Sstevel@tonic-gate * path names to system-controller device and fault led gpio
3030Sstevel@tonic-gate */
3040Sstevel@tonic-gate static char *sc_device_name = NULL;
3050Sstevel@tonic-gate static char *bezel_leds = NULL;
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate /*
3080Sstevel@tonic-gate * disk data
3090Sstevel@tonic-gate */
3100Sstevel@tonic-gate static int disk_ready[N_DISKS];
3110Sstevel@tonic-gate static char *disk_name[N_DISKS] = { "HDD0", "HDD1", "HDD2", "HDD3",
3120Sstevel@tonic-gate "HDD4", "HDD5", "HDD6", "HDD7" };
3130Sstevel@tonic-gate static volatile boolean_t disk_leds_thread_ack = B_FALSE;
3140Sstevel@tonic-gate static volatile boolean_t disk_leds_thread_running = B_FALSE;
3150Sstevel@tonic-gate static pthread_t ledsthr_tid;
3160Sstevel@tonic-gate static pthread_attr_t ledsthr_attr;
3170Sstevel@tonic-gate static boolean_t ledsthr_created = B_FALSE;
3180Sstevel@tonic-gate static boolean_t g_mutex_init = B_FALSE;
3190Sstevel@tonic-gate static pthread_cond_t g_cv;
3200Sstevel@tonic-gate static pthread_cond_t g_cv_ack;
3210Sstevel@tonic-gate static pthread_mutex_t g_mutex;
3220Sstevel@tonic-gate static volatile boolean_t g_finish_now = B_FALSE;
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate /*
3251296Sfw157321 * Boston platform-specific flag which tells us if we are using
3261296Sfw157321 * a LSI 1068X disk controller (0) or a LSI 1068E (1).
3271296Sfw157321 */
3281296Sfw157321 static int boston_1068e_flag = 0;
3291296Sfw157321
3301296Sfw157321 /*
3310Sstevel@tonic-gate * static strings
3320Sstevel@tonic-gate */
3330Sstevel@tonic-gate static const char str_devfs_path[] = "devfs-path";
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate /*
3360Sstevel@tonic-gate * OperationalStatus property values
3370Sstevel@tonic-gate */
3380Sstevel@tonic-gate static const char str_opst_present[] = "present";
3390Sstevel@tonic-gate static const char str_opst_ok[] = "okay";
3400Sstevel@tonic-gate static const char str_opst_faulty[] = "faulty";
3410Sstevel@tonic-gate static const char str_opst_download[] = "download";
3420Sstevel@tonic-gate static const char str_opst_unknown[] = "unknown";
3430Sstevel@tonic-gate static size_t max_opst_len = sizeof (str_opst_download);
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate /*
3460Sstevel@tonic-gate * forward reference
3470Sstevel@tonic-gate */
3480Sstevel@tonic-gate static void opst_init(void);
3490Sstevel@tonic-gate static void add_op_status_by_name(const char *name, const char *child_name,
3500Sstevel@tonic-gate picl_prophdl_t *prophdl_p);
3510Sstevel@tonic-gate static void add_op_status_to_node(picl_nodehdl_t nodeh,
3520Sstevel@tonic-gate picl_prophdl_t *prophdl_p);
3530Sstevel@tonic-gate static int read_vol_data(ptree_rarg_t *r_arg, void *buf);
3540Sstevel@tonic-gate static int find_picl_handle(picl_prophdl_t proph);
3550Sstevel@tonic-gate static void disk_leds_init(void);
3560Sstevel@tonic-gate static void disk_leds_fini(void);
3570Sstevel@tonic-gate static void *disk_leds_thread(void *args);
3580Sstevel@tonic-gate static picl_nodehdl_t find_child_by_name(picl_nodehdl_t parh, char *name);
3590Sstevel@tonic-gate static void post_frudr_event(char *ename, picl_nodehdl_t parenth,
3600Sstevel@tonic-gate picl_nodehdl_t fruh);
3610Sstevel@tonic-gate static int add_prop_ref(picl_nodehdl_t nodeh, picl_nodehdl_t value, char *name);
3620Sstevel@tonic-gate static void remove_fru_parents(picl_nodehdl_t fruh);
3630Sstevel@tonic-gate static int get_node_by_class(picl_nodehdl_t nodeh, const char *classname,
3640Sstevel@tonic-gate picl_nodehdl_t *foundnodeh);
3650Sstevel@tonic-gate static int get_sys_controller_node(picl_nodehdl_t *nodeh);
3660Sstevel@tonic-gate static char *create_sys_controller_pathname(picl_nodehdl_t sysconh);
3670Sstevel@tonic-gate static char *create_bezel_leds_pathname(const char *dirpath,
3680Sstevel@tonic-gate const char *devname);
3690Sstevel@tonic-gate static void frudr_evhandler(const char *ename, const void *earg,
3700Sstevel@tonic-gate size_t size, void *cookie);
3710Sstevel@tonic-gate static void fru_add_handler(const char *ename, const void *earg,
3720Sstevel@tonic-gate size_t size, void *cookie);
3730Sstevel@tonic-gate static void frutree_evhandler(const char *ename, const void *earg,
3740Sstevel@tonic-gate size_t size, void *cookie);
3750Sstevel@tonic-gate static int create_table(picl_nodehdl_t fruhdl, picl_prophdl_t *tblhdlp,
3760Sstevel@tonic-gate char *tbl_name);
3770Sstevel@tonic-gate static int create_table_entry(picl_prophdl_t tblhdl,
3780Sstevel@tonic-gate picl_nodehdl_t refhdl, char *class);
3790Sstevel@tonic-gate static int create_i2c_node(char *ap_id);
3800Sstevel@tonic-gate static void delete_i2c_node(char *ap_id);
3810Sstevel@tonic-gate static int set_led(char *name, char *ptr, char *value);
3820Sstevel@tonic-gate static int ps_name_to_addr(char *name);
3830Sstevel@tonic-gate static char *ps_name_to_unitaddr(char *name);
3840Sstevel@tonic-gate static char *ps_apid_to_nodename(char *apid);
3850Sstevel@tonic-gate static void add_op_status(envmon_hpu_t *hpu, int *index);
3862606Svenki static void get_fantray_path(char *ap_id, char *path, int bufsz);
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate #define sprintf_buf2(buf, a1, a2) (void) snprintf(buf, sizeof (buf), a1, a2)
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate * Because this plugin is shared across different platforms, we need to
3920Sstevel@tonic-gate * distinguish for certain functionality
3930Sstevel@tonic-gate */
3940Sstevel@tonic-gate #define PLAT_UNKNOWN (-1)
3950Sstevel@tonic-gate #define PLAT_ENXS 0
3960Sstevel@tonic-gate #define PLAT_ENTS 1
3970Sstevel@tonic-gate #define PLAT_CHALUPA 2
3980Sstevel@tonic-gate #define PLAT_EN19 3
3990Sstevel@tonic-gate #define PLAT_CHALUPA19 4
4000Sstevel@tonic-gate #define PLAT_SALSA19 5
4011103Sjbeloro #define PLAT_SEATTLE1U 6
4021103Sjbeloro #define PLAT_SEATTLE2U 7
4031103Sjbeloro #define PLAT_BOSTON 8
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate static int sys_platform;
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate static void
get_platform()4080Sstevel@tonic-gate get_platform()
4090Sstevel@tonic-gate {
4100Sstevel@tonic-gate char platform[64];
4110Sstevel@tonic-gate (void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
4120Sstevel@tonic-gate if (strcmp(platform, "SUNW,Sun-Fire-V250") == 0)
4130Sstevel@tonic-gate sys_platform = PLAT_ENTS;
4140Sstevel@tonic-gate else if (strcmp(platform, "SUNW,Sun-Fire-V440") == 0)
4150Sstevel@tonic-gate sys_platform = PLAT_CHALUPA;
4160Sstevel@tonic-gate else if (strcmp(platform, "SUNW,Sun-Fire-V210") == 0)
4170Sstevel@tonic-gate sys_platform = PLAT_ENXS;
4180Sstevel@tonic-gate else if (strcmp(platform, "SUNW,Sun-Fire-V240") == 0)
4190Sstevel@tonic-gate sys_platform = PLAT_ENXS;
4200Sstevel@tonic-gate else if (strcmp(platform, "SUNW,Netra-240") == 0)
4210Sstevel@tonic-gate sys_platform = PLAT_EN19;
4220Sstevel@tonic-gate else if (strcmp(platform, "SUNW,Netra-210") == 0)
4230Sstevel@tonic-gate sys_platform = PLAT_SALSA19;
4240Sstevel@tonic-gate else if (strcmp(platform, "SUNW,Netra-440") == 0)
4250Sstevel@tonic-gate sys_platform = PLAT_CHALUPA19;
4261103Sjbeloro else if (strcmp(platform, "SUNW,Sun-Fire-V215") == 0)
4271103Sjbeloro sys_platform = PLAT_SEATTLE1U;
4281103Sjbeloro else if (strcmp(platform, "SUNW,Sun-Fire-V245") == 0)
4291103Sjbeloro sys_platform = PLAT_SEATTLE2U;
4301103Sjbeloro else if (strcmp(platform, "SUNW,Sun-Fire-V445") == 0)
4311103Sjbeloro sys_platform = PLAT_BOSTON;
4320Sstevel@tonic-gate else
4330Sstevel@tonic-gate sys_platform = PLAT_UNKNOWN;
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate /*
4370Sstevel@tonic-gate * This function is executed as part of .init when the plugin is
4380Sstevel@tonic-gate * dlopen()ed
4390Sstevel@tonic-gate */
4400Sstevel@tonic-gate static void
piclfrudr_register(void)4410Sstevel@tonic-gate piclfrudr_register(void)
4420Sstevel@tonic-gate {
4430Sstevel@tonic-gate (void) picld_plugin_register(&my_reg_info);
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /*
4470Sstevel@tonic-gate * This function is the init entry point of the plugin.
4480Sstevel@tonic-gate * It initializes the /frutree tree
4490Sstevel@tonic-gate */
4500Sstevel@tonic-gate static void
piclfrudr_init(void)4510Sstevel@tonic-gate piclfrudr_init(void)
4520Sstevel@tonic-gate {
4530Sstevel@tonic-gate picl_nodehdl_t sc_nodeh;
4540Sstevel@tonic-gate picl_nodehdl_t locationh;
4550Sstevel@tonic-gate picl_nodehdl_t childh;
4560Sstevel@tonic-gate char namebuf[PATH_MAX];
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate get_platform();
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate if (sc_device_name != NULL) {
4610Sstevel@tonic-gate free(sc_device_name); /* must have reen restarted */
4620Sstevel@tonic-gate sc_device_name = NULL;
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate if ((get_sys_controller_node(&sc_nodeh) != PICL_SUCCESS) ||
4660Sstevel@tonic-gate ((sc_device_name = create_sys_controller_pathname(sc_nodeh)) ==
4670Sstevel@tonic-gate NULL))
4680Sstevel@tonic-gate syslog(LOG_ERR, EM_NO_SC_DEV);
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate opst_init();
4710Sstevel@tonic-gate disk_leds_init();
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_DR_AP_STATE_CHANGE,
4740Sstevel@tonic-gate frudr_evhandler, NULL);
4750Sstevel@tonic-gate (void) ptree_register_handler(PICL_FRU_ADDED, fru_add_handler, NULL);
4760Sstevel@tonic-gate (void) ptree_register_handler(PICLEVENT_SYSEVENT_DEVICE_ADDED,
4770Sstevel@tonic-gate frutree_evhandler, NULL);
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate /*
4800Sstevel@tonic-gate * There is a window of opportunity for the RMC to deliver an event
4810Sstevel@tonic-gate * indicating a newly operable state just before we are listening for
4820Sstevel@tonic-gate * it. In this case, envmon will have missed setting up /platform
4830Sstevel@tonic-gate * and won't get a signal from frudr. So send it a PICL_FRU_ADDED just
4840Sstevel@tonic-gate * in case.
4850Sstevel@tonic-gate */
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate if ((sys_platform == PLAT_CHALUPA) ||
488*12601SJustin.Frank@Sun.COM (sys_platform == PLAT_CHALUPA19)) {
4890Sstevel@tonic-gate sprintf_buf2(namebuf, CHASSIS_LOC_PATH, RMC_NAME);
4900Sstevel@tonic-gate } else {
4910Sstevel@tonic-gate sprintf_buf2(namebuf, SYS_BOARD_PATH, RMC_NAME);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate if (ptree_get_node_by_path(namebuf, &locationh) != PICL_SUCCESS)
4950Sstevel@tonic-gate return;
4960Sstevel@tonic-gate if (ptree_get_propval_by_name(locationh, PICL_PROP_CHILD,
4970Sstevel@tonic-gate &childh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS)
4980Sstevel@tonic-gate return;
4990Sstevel@tonic-gate post_frudr_event(PICL_FRU_ADDED, locationh, childh);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate static void
add_op_status_by_name(const char * name,const char * child_name,picl_prophdl_t * prophdl_p)5030Sstevel@tonic-gate add_op_status_by_name(const char *name, const char *child_name,
5040Sstevel@tonic-gate picl_prophdl_t *prophdl_p)
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate picl_nodehdl_t nodeh;
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate if (ptree_get_node_by_path(name, &nodeh) != PICL_SUCCESS) {
5090Sstevel@tonic-gate return;
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate if (ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD,
5130Sstevel@tonic-gate &nodeh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS) {
5140Sstevel@tonic-gate
5150Sstevel@tonic-gate if (child_name == NULL)
5160Sstevel@tonic-gate return;
5170Sstevel@tonic-gate /*
5180Sstevel@tonic-gate * create fru node of supplied name
5190Sstevel@tonic-gate */
5200Sstevel@tonic-gate if (ptree_create_and_add_node(nodeh, child_name,
5210Sstevel@tonic-gate PICL_CLASS_FRU, &nodeh) != PICL_SUCCESS)
5220Sstevel@tonic-gate return;
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate add_op_status_to_node(nodeh, prophdl_p);
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate /*
5290Sstevel@tonic-gate * function to add a volatile property to a specified node
5300Sstevel@tonic-gate */
5310Sstevel@tonic-gate static void
add_op_status_to_node(picl_nodehdl_t nodeh,picl_prophdl_t * prophdl_p)5320Sstevel@tonic-gate add_op_status_to_node(picl_nodehdl_t nodeh, picl_prophdl_t *prophdl_p)
5330Sstevel@tonic-gate {
5340Sstevel@tonic-gate int err;
5350Sstevel@tonic-gate ptree_propinfo_t info;
5360Sstevel@tonic-gate picl_prophdl_t proph;
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate err = ptree_init_propinfo(&info, PTREE_PROPINFO_VERSION,
5390Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_VOLATILE | PICL_READ, max_opst_len,
5400Sstevel@tonic-gate PICL_PROP_OPERATIONAL_STATUS, read_vol_data, NULL);
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate if (err == PICL_SUCCESS) {
5430Sstevel@tonic-gate if (ptree_get_prop_by_name(nodeh, PICL_PROP_OPERATIONAL_STATUS,
5440Sstevel@tonic-gate &proph) == PICL_SUCCESS) {
5450Sstevel@tonic-gate if (ptree_delete_prop(proph) == PICL_SUCCESS)
5460Sstevel@tonic-gate err = ptree_destroy_prop(proph);
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate if ((err != PICL_SUCCESS) || ((err = ptree_create_and_add_prop(nodeh,
5510Sstevel@tonic-gate &info, NULL, prophdl_p)) != PICL_SUCCESS)) {
5520Sstevel@tonic-gate syslog(LOG_ERR, ADD_PROP_FAIL, PICL_PROP_OPERATIONAL_STATUS,
5530Sstevel@tonic-gate err);
5540Sstevel@tonic-gate return;
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate /*
5590Sstevel@tonic-gate * Deliver volatile property value.
5600Sstevel@tonic-gate * prtpicl gets very upset if we fail this command, so if the property
5610Sstevel@tonic-gate * cannot be retrieved, return a status of unknown.
5620Sstevel@tonic-gate */
5630Sstevel@tonic-gate static int
read_vol_data(ptree_rarg_t * r_arg,void * buf)5640Sstevel@tonic-gate read_vol_data(ptree_rarg_t *r_arg, void *buf)
5650Sstevel@tonic-gate {
5660Sstevel@tonic-gate picl_prophdl_t proph;
5670Sstevel@tonic-gate int index;
5680Sstevel@tonic-gate int envmon_fd;
5690Sstevel@tonic-gate int err;
5700Sstevel@tonic-gate envmon_hpu_t data;
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate proph = r_arg->proph;
5730Sstevel@tonic-gate index = find_picl_handle(proph);
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate if (index < 0) {
5760Sstevel@tonic-gate /*
5770Sstevel@tonic-gate * We drop memory of PSU op status handles in opst_init()
5780Sstevel@tonic-gate * when we get an RMC faulty event. We cannot access the
5790Sstevel@tonic-gate * status info in this circumstance, so returning "unknown"
5800Sstevel@tonic-gate * is appropriate.
5810Sstevel@tonic-gate */
5820Sstevel@tonic-gate (void) strlcpy(buf, str_opst_unknown, max_opst_len);
5830Sstevel@tonic-gate return (PICL_SUCCESS);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate envmon_fd = open(sc_device_name, O_RDONLY);
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate if (envmon_fd < 0) {
5890Sstevel@tonic-gate /*
5900Sstevel@tonic-gate * To get this far we must have succeeded with an earlier
5910Sstevel@tonic-gate * open, so this is an unlikely failure. It would be more
5920Sstevel@tonic-gate * helpful to indicate the nature of the failure, but we
5930Sstevel@tonic-gate * don't have the space to say much. Just return "unknown".
5940Sstevel@tonic-gate */
5950Sstevel@tonic-gate (void) strlcpy(buf, str_opst_unknown, max_opst_len);
5960Sstevel@tonic-gate return (PICL_SUCCESS);
5970Sstevel@tonic-gate }
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate data.id = idprop->idp[index].envhandle;
6000Sstevel@tonic-gate err = ioctl(envmon_fd, ENVMONIOCHPU, &data);
6010Sstevel@tonic-gate
6020Sstevel@tonic-gate if (err < 0) {
6030Sstevel@tonic-gate /*
6040Sstevel@tonic-gate * If we can't read the stats, "unknown" is a reasonable
6050Sstevel@tonic-gate * status to return. This one really shouldn't happen.
6060Sstevel@tonic-gate */
6070Sstevel@tonic-gate (void) strlcpy(buf, str_opst_unknown, max_opst_len);
6080Sstevel@tonic-gate (void) close(envmon_fd);
6090Sstevel@tonic-gate return (PICL_SUCCESS);
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate
6120Sstevel@tonic-gate (void) close(envmon_fd);
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate if (strncmp(data.id.name, DISK_NAME, DISK_NAME_LEN) == 0 &&
6150Sstevel@tonic-gate data.fru_status == ENVMON_FRU_PRESENT) {
6160Sstevel@tonic-gate (void) strlcpy(buf, str_opst_present, max_opst_len);
6170Sstevel@tonic-gate return (PICL_SUCCESS);
6180Sstevel@tonic-gate }
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate if (data.sensor_status != ENVMON_SENSOR_OK) {
6210Sstevel@tonic-gate (void) strlcpy(buf, str_opst_unknown, max_opst_len);
6220Sstevel@tonic-gate return (PICL_SUCCESS);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate (void) strlcpy(buf,
6260Sstevel@tonic-gate data.fru_status == ENVMON_FRU_PRESENT ? str_opst_ok :
6270Sstevel@tonic-gate data.fru_status == ENVMON_FRU_DOWNLOAD ? str_opst_download :
6280Sstevel@tonic-gate data.fru_status == ENVMON_FRU_FAULT ? str_opst_faulty :
6290Sstevel@tonic-gate str_opst_unknown, max_opst_len);
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate return (PICL_SUCCESS);
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate /*
6350Sstevel@tonic-gate * Function for explicitly turning on system leds
6360Sstevel@tonic-gate * for a failed/degraded RMC (SC).
6370Sstevel@tonic-gate */
6380Sstevel@tonic-gate static void
solaris_setleds(const char * led_path,int leds)6390Sstevel@tonic-gate solaris_setleds(const char *led_path, int leds)
6400Sstevel@tonic-gate {
6410Sstevel@tonic-gate i2c_gpio_t gpio;
6420Sstevel@tonic-gate int fd = open(led_path, O_RDWR);
6430Sstevel@tonic-gate
6440Sstevel@tonic-gate if (fd < 0)
6450Sstevel@tonic-gate return;
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate gpio.reg_val = (leds ^ 0xff);
6480Sstevel@tonic-gate gpio.reg_mask = 0xffffffff;
6490Sstevel@tonic-gate if (ioctl(fd, GPIO_SET_CONFIG, &gpio) == 0) {
6500Sstevel@tonic-gate gpio.reg_val = (leds ^ 0xff);
6510Sstevel@tonic-gate gpio.reg_mask = 0xffffffff;
6520Sstevel@tonic-gate (void) ioctl(fd, GPIO_SET_OUTPUT, &gpio);
6530Sstevel@tonic-gate }
6540Sstevel@tonic-gate (void) close(fd);
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate
6571103Sjbeloro /*
6581103Sjbeloro * Function for explicitly turning on system leds
6591103Sjbeloro * for a failed/degraded RMC (SC) on Seattle
6601103Sjbeloro */
6611103Sjbeloro static void
seattle_setleds(void)6621103Sjbeloro seattle_setleds(void)
6631103Sjbeloro {
6641103Sjbeloro int fd;
6651103Sjbeloro
6661103Sjbeloro fd = open(SEATTLE_LED_DEV, O_RDWR);
6671103Sjbeloro
6681103Sjbeloro if (fd < 0)
6691103Sjbeloro return;
6701103Sjbeloro
6711103Sjbeloro ioctl(fd, EPIC_SET_POWER_LED, (char *)0);
6721103Sjbeloro ioctl(fd, EPIC_SET_ALERT_LED, (char *)0);
6731103Sjbeloro (void) close(fd);
6741103Sjbeloro }
6751103Sjbeloro
6761103Sjbeloro /*
6771103Sjbeloro * Function for explicitly turning on the front system leds
6781103Sjbeloro * for a failed/degraded RMC (SC) on Boston
6791103Sjbeloro */
6801103Sjbeloro static void
boston_set_frontleds(const char * led_path,int leds)6811103Sjbeloro boston_set_frontleds(const char *led_path, int leds)
6821103Sjbeloro {
6831103Sjbeloro i2c_gpio_t gpio;
6841103Sjbeloro int fd = open(led_path, O_RDWR);
6851103Sjbeloro
6861103Sjbeloro if (fd < 0) {
6871103Sjbeloro return;
6881103Sjbeloro }
6891103Sjbeloro
6901103Sjbeloro /* first clear the polarity */
6911103Sjbeloro gpio.reg_val = BOSTON_FRONT_CLEAR_POL;
6921103Sjbeloro gpio.reg_mask = BOSTON_FRONT_LED_MASK;
6931103Sjbeloro if (ioctl(fd, GPIO_SET_POLARITY, &gpio) < 0) {
6941103Sjbeloro (void) close(fd);
6951103Sjbeloro return;
6961103Sjbeloro }
6971103Sjbeloro
6981103Sjbeloro /* now clear the direction */
6991103Sjbeloro gpio.reg_val = BOSTON_FRONT_CLEAR_DIR;
7001103Sjbeloro gpio.reg_mask = BOSTON_FRONT_LED_MASK;
7011103Sjbeloro if (ioctl(fd, GPIO_SET_CONFIG, &gpio) < 0) {
7021103Sjbeloro (void) close(fd);
7031103Sjbeloro return;
7041103Sjbeloro }
7051103Sjbeloro
7061103Sjbeloro /* and light the leds */
7071103Sjbeloro gpio.reg_val = leds;
7081103Sjbeloro gpio.reg_mask = BOSTON_FRONT_LED_MASK;
7091103Sjbeloro ioctl(fd, GPIO_SET_OUTPUT, &gpio);
7101103Sjbeloro (void) close(fd);
7111103Sjbeloro }
7121103Sjbeloro
7131103Sjbeloro /*
7141103Sjbeloro * Function for explicitly turning on the rear system leds
7151103Sjbeloro * for a failed/degraded RMC (SC) on Boston
7161103Sjbeloro */
7171103Sjbeloro static void
boston_set_rearleds(const char * led_path,int leds)7181103Sjbeloro boston_set_rearleds(const char *led_path, int leds)
7191103Sjbeloro {
7201103Sjbeloro i2c_gpio_t gpio;
7211103Sjbeloro int fd = open(led_path, O_RDWR);
7221103Sjbeloro
7231103Sjbeloro if (fd < 0) {
7241103Sjbeloro return;
7251103Sjbeloro }
7261103Sjbeloro
7271103Sjbeloro /* first clear the polarity */
7281103Sjbeloro gpio.reg_val = BOSTON_REAR_CLEAR_POL;
7291103Sjbeloro gpio.reg_mask = BOSTON_REAR_LED_MASK;
7301103Sjbeloro if (ioctl(fd, GPIO_SET_POLARITY, &gpio) < 0) {
7311103Sjbeloro (void) close(fd);
7321103Sjbeloro return;
7331103Sjbeloro }
7341103Sjbeloro
7351103Sjbeloro /* now set the direction */
7361103Sjbeloro gpio.reg_val = BOSTON_REAR_LED_MASK;
7371103Sjbeloro gpio.reg_mask = BOSTON_REAR_LED_MASK;
7381103Sjbeloro if (ioctl(fd, GPIO_SET_CONFIG, &gpio) < 0) {
7391103Sjbeloro (void) close(fd);
7401103Sjbeloro return;
7411103Sjbeloro }
7421103Sjbeloro
7431103Sjbeloro /* and light the leds */
7441103Sjbeloro gpio.reg_val = leds;
7451103Sjbeloro gpio.reg_mask = BOSTON_REAR_LED_MASK;
7461103Sjbeloro ioctl(fd, GPIO_SET_OUTPUT, &gpio);
7471103Sjbeloro (void) close(fd);
7481103Sjbeloro }
7491103Sjbeloro
7500Sstevel@tonic-gate static void
rmc_state_event(void)7510Sstevel@tonic-gate rmc_state_event(void)
7520Sstevel@tonic-gate {
7530Sstevel@tonic-gate envmon_hpu_t hpu;
7540Sstevel@tonic-gate int res;
7550Sstevel@tonic-gate int fd = open(sc_device_name, O_RDONLY);
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate if (fd < 0)
7580Sstevel@tonic-gate return;
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate (void) strlcpy(hpu.id.name, RMC_NAME, sizeof (hpu.id.name));
7610Sstevel@tonic-gate res = ioctl(fd, ENVMONIOCHPU, &hpu);
7620Sstevel@tonic-gate (void) close(fd);
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate if ((res == 0) && (hpu.sensor_status == ENVMON_SENSOR_OK) &&
7650Sstevel@tonic-gate ((hpu.fru_status & ENVMON_FRU_FAULT) != 0)) {
7660Sstevel@tonic-gate /*
7670Sstevel@tonic-gate * SC failed event - light the service led
7680Sstevel@tonic-gate * note that as Solaris is still running,
7690Sstevel@tonic-gate * the Solaris active led should be lit too.
7700Sstevel@tonic-gate */
7710Sstevel@tonic-gate switch (sys_platform) {
7720Sstevel@tonic-gate case PLAT_ENXS:
7730Sstevel@tonic-gate case PLAT_SALSA19:
7740Sstevel@tonic-gate case PLAT_EN19:
7750Sstevel@tonic-gate solaris_setleds(ENXS_REAR_LEDS,
7760Sstevel@tonic-gate ENXS_REAR_SRVC_LED | ENXS_REAR_ACT_LED);
7770Sstevel@tonic-gate /*
7780Sstevel@tonic-gate * the device name for the bezel leds GPIO device
7790Sstevel@tonic-gate * tends to vary from Unix to Unix. Search for it.
7800Sstevel@tonic-gate */
7810Sstevel@tonic-gate if (bezel_leds == NULL) {
7820Sstevel@tonic-gate bezel_leds =
7830Sstevel@tonic-gate create_bezel_leds_pathname(ENXS_LED_DIR,
7840Sstevel@tonic-gate ENXS_FRONT_LEDS);
7850Sstevel@tonic-gate }
7860Sstevel@tonic-gate if (bezel_leds == NULL)
7870Sstevel@tonic-gate return;
7880Sstevel@tonic-gate solaris_setleds(bezel_leds,
7890Sstevel@tonic-gate ENXS_FRONT_SRVC_LED | ENXS_FRONT_ACT_LED);
7900Sstevel@tonic-gate break;
7910Sstevel@tonic-gate case PLAT_ENTS:
7920Sstevel@tonic-gate /*
7930Sstevel@tonic-gate * the device name for the system leds gpio can vary
7940Sstevel@tonic-gate * as there are several similar gpio devices. Search
7950Sstevel@tonic-gate * for one with the desired address.
7960Sstevel@tonic-gate */
7970Sstevel@tonic-gate if (bezel_leds == NULL) {
7980Sstevel@tonic-gate bezel_leds =
7990Sstevel@tonic-gate create_bezel_leds_pathname(ENTS_LED_DIR,
8000Sstevel@tonic-gate ENTS_LEDS);
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate if (bezel_leds == NULL)
8030Sstevel@tonic-gate return;
8040Sstevel@tonic-gate solaris_setleds(bezel_leds,
8050Sstevel@tonic-gate ENTS_SRVC_LED | ENTS_ACT_LED);
8060Sstevel@tonic-gate break;
8070Sstevel@tonic-gate case PLAT_CHALUPA:
8080Sstevel@tonic-gate case PLAT_CHALUPA19:
8090Sstevel@tonic-gate solaris_setleds(V440_LED_PATH,
8100Sstevel@tonic-gate V440_SRVC_LED | V440_ACT_LED);
8110Sstevel@tonic-gate break;
8121103Sjbeloro case PLAT_BOSTON:
8131103Sjbeloro /* set front leds */
8141103Sjbeloro boston_set_frontleds(BOSTON_FRONT_LED_PATH,
8151103Sjbeloro BOSTON_FRONT_SRVC_LED | BOSTON_FRONT_ACT_LED);
8161103Sjbeloro /* and then the rear leds */
8171103Sjbeloro boston_set_rearleds(BOSTON_REAR_LED_PATH,
8181103Sjbeloro BOSTON_REAR_SRVC_LED | BOSTON_REAR_ACT_LED);
8191103Sjbeloro break;
8201103Sjbeloro case PLAT_SEATTLE1U:
8211103Sjbeloro case PLAT_SEATTLE2U:
8221103Sjbeloro seattle_setleds();
8231103Sjbeloro break;
8240Sstevel@tonic-gate default:
8250Sstevel@tonic-gate break;
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate static int
find_picl_handle(picl_prophdl_t proph)8310Sstevel@tonic-gate find_picl_handle(picl_prophdl_t proph)
8320Sstevel@tonic-gate {
8330Sstevel@tonic-gate int index;
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate if (idprop == NULL)
8360Sstevel@tonic-gate return (-1);
8370Sstevel@tonic-gate
8380Sstevel@tonic-gate for (index = 0; index < idprop->num; index++) {
8390Sstevel@tonic-gate if (idprop->idp[index].volprop == proph)
8400Sstevel@tonic-gate return (index);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate return (-1);
8440Sstevel@tonic-gate }
8450Sstevel@tonic-gate
8460Sstevel@tonic-gate static int
find_vol_prop_by_name(const char * name)8470Sstevel@tonic-gate find_vol_prop_by_name(const char *name)
8480Sstevel@tonic-gate {
8490Sstevel@tonic-gate int index;
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate if (idprop == NULL)
8520Sstevel@tonic-gate return (-1);
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate for (index = 0; index < idprop->num; index++) {
8550Sstevel@tonic-gate if (strcmp(idprop->idp[index].envhandle.name, name) == 0)
8560Sstevel@tonic-gate return (index);
8570Sstevel@tonic-gate }
8580Sstevel@tonic-gate
8590Sstevel@tonic-gate return (-1);
8600Sstevel@tonic-gate }
8610Sstevel@tonic-gate
8620Sstevel@tonic-gate /*
8630Sstevel@tonic-gate * This function is the fini entry point of the plugin.
8640Sstevel@tonic-gate */
8650Sstevel@tonic-gate static void
piclfrudr_fini(void)8660Sstevel@tonic-gate piclfrudr_fini(void)
8670Sstevel@tonic-gate {
8680Sstevel@tonic-gate (void) ptree_unregister_handler(PICLEVENT_DR_AP_STATE_CHANGE,
8690Sstevel@tonic-gate frudr_evhandler, NULL);
8700Sstevel@tonic-gate (void) ptree_unregister_handler(PICL_FRU_ADDED, fru_add_handler,
8710Sstevel@tonic-gate NULL);
8720Sstevel@tonic-gate disk_leds_fini();
8730Sstevel@tonic-gate if (idprop != NULL) {
8740Sstevel@tonic-gate free(idprop);
8750Sstevel@tonic-gate idprop = NULL;
8760Sstevel@tonic-gate }
8770Sstevel@tonic-gate if (sc_device_name != NULL) {
8780Sstevel@tonic-gate free(sc_device_name);
8790Sstevel@tonic-gate sc_device_name = NULL;
8800Sstevel@tonic-gate }
8810Sstevel@tonic-gate }
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate /*
8840Sstevel@tonic-gate * subroutine for various functions. Finds immediate child of parh with
8850Sstevel@tonic-gate * requested name if present. Otherwise returns NULL.
8860Sstevel@tonic-gate */
8870Sstevel@tonic-gate static picl_nodehdl_t
find_child_by_name(picl_nodehdl_t parh,char * name)8880Sstevel@tonic-gate find_child_by_name(picl_nodehdl_t parh, char *name)
8890Sstevel@tonic-gate {
8900Sstevel@tonic-gate picl_nodehdl_t nodeh;
8910Sstevel@tonic-gate int err;
8920Sstevel@tonic-gate char nodename[PICL_PROPNAMELEN_MAX];
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate err = ptree_get_propval_by_name(parh, PICL_PROP_CHILD,
8950Sstevel@tonic-gate &nodeh, sizeof (picl_nodehdl_t));
8960Sstevel@tonic-gate if (err != PICL_SUCCESS)
8970Sstevel@tonic-gate return (NULL);
8980Sstevel@tonic-gate for (;;) {
8990Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_NAME, nodename,
9000Sstevel@tonic-gate sizeof (nodename));
9010Sstevel@tonic-gate if (err != PICL_SUCCESS)
9020Sstevel@tonic-gate return (NULL);
9030Sstevel@tonic-gate if (strcmp(name, nodename) == 0) {
9040Sstevel@tonic-gate return (nodeh);
9050Sstevel@tonic-gate }
9060Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_PEER,
9070Sstevel@tonic-gate &nodeh, sizeof (picl_nodehdl_t));
9080Sstevel@tonic-gate if (err != PICL_SUCCESS)
9090Sstevel@tonic-gate return (NULL);
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate /* Creates a reference property for a given PICL node */
9140Sstevel@tonic-gate static int
add_prop_ref(picl_nodehdl_t nodeh,picl_nodehdl_t value,char * name)9150Sstevel@tonic-gate add_prop_ref(picl_nodehdl_t nodeh, picl_nodehdl_t value, char *name)
9160Sstevel@tonic-gate {
9170Sstevel@tonic-gate picl_prophdl_t proph;
9180Sstevel@tonic-gate ptree_propinfo_t propinfo;
9190Sstevel@tonic-gate int err;
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
9220Sstevel@tonic-gate PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t), name,
9230Sstevel@tonic-gate NULL, NULL);
9240Sstevel@tonic-gate if (err != PICL_SUCCESS) {
9250Sstevel@tonic-gate syslog(LOG_ERR, PROPINFO_FAIL, name, err);
9260Sstevel@tonic-gate return (err);
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate err = ptree_create_and_add_prop(nodeh, &propinfo, &value, &proph);
9290Sstevel@tonic-gate if (err != PICL_SUCCESS) {
9300Sstevel@tonic-gate syslog(LOG_ERR, ADD_PROP_FAIL, name, err);
9310Sstevel@tonic-gate return (err);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate return (PICL_SUCCESS);
9340Sstevel@tonic-gate }
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate /* create an entry in the specified table */
9370Sstevel@tonic-gate static int
create_table_entry(picl_prophdl_t tblhdl,picl_nodehdl_t refhdl,char * class)9380Sstevel@tonic-gate create_table_entry(picl_prophdl_t tblhdl, picl_nodehdl_t refhdl, char *class)
9390Sstevel@tonic-gate {
9400Sstevel@tonic-gate int err;
9410Sstevel@tonic-gate ptree_propinfo_t prop;
9420Sstevel@tonic-gate picl_prophdl_t prophdl[2];
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate /* first column is class */
9450Sstevel@tonic-gate prop.version = PTREE_PROPINFO_VERSION;
9460Sstevel@tonic-gate prop.piclinfo.type = PICL_PTYPE_CHARSTRING;
9470Sstevel@tonic-gate prop.piclinfo.accessmode = PICL_READ;
9480Sstevel@tonic-gate prop.piclinfo.size = PICL_CLASSNAMELEN_MAX;
9490Sstevel@tonic-gate prop.read = NULL;
9500Sstevel@tonic-gate prop.write = NULL;
9510Sstevel@tonic-gate (void) strlcpy(prop.piclinfo.name, PICL_PROP_CLASS,
9520Sstevel@tonic-gate sizeof (prop.piclinfo.name));
9530Sstevel@tonic-gate err = ptree_create_prop(&prop, class, &prophdl[0]);
9540Sstevel@tonic-gate if (err != PICL_SUCCESS) {
9550Sstevel@tonic-gate syslog(LOG_ERR, ADD_TBL_ENTRY_FAIL, err);
9560Sstevel@tonic-gate return (err);
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate /* second column is reference property */
9600Sstevel@tonic-gate prop.version = PTREE_PROPINFO_VERSION;
9610Sstevel@tonic-gate prop.piclinfo.type = PICL_PTYPE_REFERENCE;
9620Sstevel@tonic-gate prop.piclinfo.accessmode = PICL_READ;
9630Sstevel@tonic-gate prop.piclinfo.size = sizeof (picl_nodehdl_t);
9640Sstevel@tonic-gate prop.read = NULL;
9650Sstevel@tonic-gate prop.write = NULL;
9660Sstevel@tonic-gate sprintf_buf2(prop.piclinfo.name, "_%s_", class);
9670Sstevel@tonic-gate err = ptree_create_prop(&prop, &refhdl, &prophdl[1]);
9680Sstevel@tonic-gate if (err != PICL_SUCCESS) {
9690Sstevel@tonic-gate syslog(LOG_ERR, ADD_TBL_ENTRY_FAIL, err);
9700Sstevel@tonic-gate return (err);
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate
9730Sstevel@tonic-gate /* add row to table */
9740Sstevel@tonic-gate err = ptree_add_row_to_table(tblhdl, 2, prophdl);
9750Sstevel@tonic-gate if (err != PICL_SUCCESS)
9760Sstevel@tonic-gate syslog(LOG_ERR, ADD_TBL_ENTRY_FAIL, err);
9770Sstevel@tonic-gate return (err);
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate /* create an empty table property */
9810Sstevel@tonic-gate static int
create_table(picl_nodehdl_t fruhdl,picl_prophdl_t * tblhdlp,char * tbl_name)9820Sstevel@tonic-gate create_table(picl_nodehdl_t fruhdl, picl_prophdl_t *tblhdlp, char *tbl_name)
9830Sstevel@tonic-gate {
9840Sstevel@tonic-gate int err;
9850Sstevel@tonic-gate ptree_propinfo_t prop;
9860Sstevel@tonic-gate picl_prophdl_t tblprophdl;
9870Sstevel@tonic-gate
9880Sstevel@tonic-gate err = ptree_create_table(tblhdlp);
9890Sstevel@tonic-gate if (err != PICL_SUCCESS) {
9900Sstevel@tonic-gate syslog(LOG_ERR, ADD_PROP_FAIL, tbl_name, err);
9910Sstevel@tonic-gate return (err);
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate prop.version = PTREE_PROPINFO_VERSION;
9940Sstevel@tonic-gate prop.piclinfo.type = PICL_PTYPE_TABLE;
9950Sstevel@tonic-gate prop.piclinfo.accessmode = PICL_READ;
9960Sstevel@tonic-gate prop.piclinfo.size = sizeof (picl_prophdl_t);
9970Sstevel@tonic-gate prop.read = NULL;
9980Sstevel@tonic-gate prop.write = NULL;
9990Sstevel@tonic-gate (void) strlcpy(prop.piclinfo.name, tbl_name,
10000Sstevel@tonic-gate sizeof (prop.piclinfo.name));
10010Sstevel@tonic-gate err = ptree_create_and_add_prop(fruhdl, &prop, tblhdlp, &tblprophdl);
10020Sstevel@tonic-gate if (err != PICL_SUCCESS)
10030Sstevel@tonic-gate syslog(LOG_ERR, ADD_PROP_FAIL, tbl_name, err);
10040Sstevel@tonic-gate return (err);
10050Sstevel@tonic-gate }
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate /*
10080Sstevel@tonic-gate * The size of outfilename must be PATH_MAX
10090Sstevel@tonic-gate */
10100Sstevel@tonic-gate static int
get_config_file(char * outfilename,char * fru)10110Sstevel@tonic-gate get_config_file(char *outfilename, char *fru)
10120Sstevel@tonic-gate {
10130Sstevel@tonic-gate char nmbuf[SYS_NMLN];
10140Sstevel@tonic-gate char pname[PATH_MAX];
10150Sstevel@tonic-gate int dir;
10160Sstevel@tonic-gate
10170Sstevel@tonic-gate for (dir = 0; dir < 2; dir++) {
10180Sstevel@tonic-gate if (sysinfo(dir == 0 ? SI_PLATFORM : SI_MACHINE,
10190Sstevel@tonic-gate nmbuf, sizeof (nmbuf)) == -1) {
10200Sstevel@tonic-gate continue;
10210Sstevel@tonic-gate }
10220Sstevel@tonic-gate
10230Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, nmbuf);
10240Sstevel@tonic-gate (void) strlcat(pname, CONFFILE_PREFIX, PATH_MAX);
10250Sstevel@tonic-gate (void) strlcat(pname, fru, PATH_MAX);
10260Sstevel@tonic-gate (void) strlcat(pname, CONFFILE_SUFFIX, PATH_MAX);
10270Sstevel@tonic-gate
10280Sstevel@tonic-gate if (access(pname, R_OK) == 0) {
10290Sstevel@tonic-gate (void) strlcpy(outfilename, pname, PATH_MAX);
10300Sstevel@tonic-gate return (0);
10310Sstevel@tonic-gate }
10320Sstevel@tonic-gate }
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate (void) snprintf(pname, PATH_MAX, "%s/%s%s%s",
10350Sstevel@tonic-gate PICLD_COMMON_PLUGIN_DIR, CONFFILE_PREFIX, fru,
10360Sstevel@tonic-gate CONFFILE_SUFFIX);
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate if (access(pname, R_OK) == 0) {
10390Sstevel@tonic-gate (void) strlcpy(outfilename, pname, PATH_MAX);
10400Sstevel@tonic-gate return (0);
10410Sstevel@tonic-gate }
10420Sstevel@tonic-gate
10430Sstevel@tonic-gate return (-1);
10440Sstevel@tonic-gate }
10450Sstevel@tonic-gate
1046*12601SJustin.Frank@Sun.COM /*
1047*12601SJustin.Frank@Sun.COM * This helper function for Netra-440 fan tray removal removes
1048*12601SJustin.Frank@Sun.COM * the rmclomv-rooted nodes and their properties.
1049*12601SJustin.Frank@Sun.COM */
1050*12601SJustin.Frank@Sun.COM static void
delete_node_and_props(picl_nodehdl_t hdl)1051*12601SJustin.Frank@Sun.COM delete_node_and_props(picl_nodehdl_t hdl)
1052*12601SJustin.Frank@Sun.COM {
1053*12601SJustin.Frank@Sun.COM picl_prophdl_t prop;
1054*12601SJustin.Frank@Sun.COM int err;
1055*12601SJustin.Frank@Sun.COM
1056*12601SJustin.Frank@Sun.COM do {
1057*12601SJustin.Frank@Sun.COM err = ptree_get_first_prop(hdl, &prop);
1058*12601SJustin.Frank@Sun.COM if (err == PICL_SUCCESS) {
1059*12601SJustin.Frank@Sun.COM if (ptree_delete_prop(prop) == PICL_SUCCESS)
1060*12601SJustin.Frank@Sun.COM (void) ptree_destroy_prop(prop);
1061*12601SJustin.Frank@Sun.COM }
1062*12601SJustin.Frank@Sun.COM } while (err == PICL_SUCCESS);
1063*12601SJustin.Frank@Sun.COM if (ptree_delete_node(hdl) == PICL_SUCCESS)
1064*12601SJustin.Frank@Sun.COM (void) ptree_destroy_node(hdl);
1065*12601SJustin.Frank@Sun.COM }
1066*12601SJustin.Frank@Sun.COM
10670Sstevel@tonic-gate static void
remove_fru_parents(picl_nodehdl_t fruh)10680Sstevel@tonic-gate remove_fru_parents(picl_nodehdl_t fruh)
10690Sstevel@tonic-gate {
10700Sstevel@tonic-gate char name[MAXPATHLEN];
10710Sstevel@tonic-gate int retval;
10720Sstevel@tonic-gate picl_nodehdl_t nodeh;
10730Sstevel@tonic-gate picl_prophdl_t tableh;
10740Sstevel@tonic-gate picl_prophdl_t tblh;
10750Sstevel@tonic-gate picl_prophdl_t fruph;
10762606Svenki picl_nodehdl_t childh;
1077*12601SJustin.Frank@Sun.COM int fanfru = 0;
10780Sstevel@tonic-gate
10790Sstevel@tonic-gate retval = ptree_get_propval_by_name(fruh, PICL_PROP_NAME, name,
10800Sstevel@tonic-gate sizeof (name));
10810Sstevel@tonic-gate if (retval != PICL_SUCCESS) {
10820Sstevel@tonic-gate syslog(LOG_ERR, EM_UNK_FRU);
10830Sstevel@tonic-gate return;
10840Sstevel@tonic-gate }
10852606Svenki
10862606Svenki retval = ptree_get_prop_by_name(fruh, PICL_PROP_DEVICES, &tableh);
10872606Svenki if (retval != PICL_SUCCESS) {
10882606Svenki /*
1089*12601SJustin.Frank@Sun.COM * No Devices table. However on Seattle, Boston and
1090*12601SJustin.Frank@Sun.COM * Netra-440 (Chalupa19) (which support fan fru hotplug),
1091*12601SJustin.Frank@Sun.COM * the Devices table will be found under the child node (Fn)
1092*12601SJustin.Frank@Sun.COM * of the fru (fan-tray).
10932606Svenki * Therefore, check the first child of the fru for the
10942606Svenki * Devices table on these platforms before returning.
10952606Svenki */
10962606Svenki switch (sys_platform) {
10972606Svenki case PLAT_SEATTLE1U:
10982606Svenki case PLAT_SEATTLE2U:
10992606Svenki case PLAT_BOSTON:
11002606Svenki if (strcmp(name, FT_FRU_NAME) != 0)
11012606Svenki return;
1102*12601SJustin.Frank@Sun.COM fanfru = 1;
1103*12601SJustin.Frank@Sun.COM break;
1104*12601SJustin.Frank@Sun.COM case PLAT_CHALUPA19:
1105*12601SJustin.Frank@Sun.COM if (strncmp(name, F0_NAME, F0_NAME_LEN) &&
1106*12601SJustin.Frank@Sun.COM strncmp(name, F1_NAME, F1_NAME_LEN))
11072606Svenki return;
1108*12601SJustin.Frank@Sun.COM fanfru = 1;
11092606Svenki break;
11102606Svenki default:
11112606Svenki /* nothing to do */
11122606Svenki return;
11132606Svenki }
1114*12601SJustin.Frank@Sun.COM retval = ptree_get_propval_by_name(fruh,
1115*12601SJustin.Frank@Sun.COM PICL_PROP_CHILD, &childh, sizeof (picl_nodehdl_t));
1116*12601SJustin.Frank@Sun.COM if (retval != PICL_SUCCESS)
1117*12601SJustin.Frank@Sun.COM return;
1118*12601SJustin.Frank@Sun.COM retval = ptree_get_prop_by_name(childh,
1119*12601SJustin.Frank@Sun.COM PICL_PROP_DEVICES, &tableh);
1120*12601SJustin.Frank@Sun.COM if (retval != PICL_SUCCESS)
1121*12601SJustin.Frank@Sun.COM return;
11220Sstevel@tonic-gate }
11230Sstevel@tonic-gate
11240Sstevel@tonic-gate /*
11250Sstevel@tonic-gate * follow all reference properties in the second
11260Sstevel@tonic-gate * column of the table and delete any _fru_parent node
11270Sstevel@tonic-gate * at the referenced node.
11280Sstevel@tonic-gate */
11290Sstevel@tonic-gate retval = ptree_get_propval(tableh, &tblh, sizeof (tblh));
11300Sstevel@tonic-gate if (retval != PICL_SUCCESS) {
11310Sstevel@tonic-gate /* can't get value of table property */
1132*12601SJustin.Frank@Sun.COM goto afterloop;
11330Sstevel@tonic-gate }
11342606Svenki
11350Sstevel@tonic-gate /* get first col, first row */
11360Sstevel@tonic-gate retval = ptree_get_next_by_col(tblh, &tblh);
11370Sstevel@tonic-gate if (retval != PICL_SUCCESS) {
11380Sstevel@tonic-gate /* no rows? */
1139*12601SJustin.Frank@Sun.COM goto afterloop;
11400Sstevel@tonic-gate }
11412606Svenki
11420Sstevel@tonic-gate /*
11430Sstevel@tonic-gate * starting at next col, get every entry in the column
11440Sstevel@tonic-gate */
11450Sstevel@tonic-gate for (retval = ptree_get_next_by_row(tblh, &tblh);
11460Sstevel@tonic-gate retval == PICL_SUCCESS;
11470Sstevel@tonic-gate retval = ptree_get_next_by_col(tblh, &tblh)) {
11480Sstevel@tonic-gate /*
11490Sstevel@tonic-gate * should be a ref prop in our hands,
11500Sstevel@tonic-gate * get the target node handle
11510Sstevel@tonic-gate */
11520Sstevel@tonic-gate retval = ptree_get_propval(tblh, &nodeh,
11530Sstevel@tonic-gate sizeof (nodeh));
11540Sstevel@tonic-gate if (retval != PICL_SUCCESS) {
11550Sstevel@tonic-gate continue;
11560Sstevel@tonic-gate }
11570Sstevel@tonic-gate /*
11580Sstevel@tonic-gate * got the referenced node, has it got a
11590Sstevel@tonic-gate * _fru_parent property?
11600Sstevel@tonic-gate */
11610Sstevel@tonic-gate retval = ptree_get_prop_by_name(nodeh,
11620Sstevel@tonic-gate PICL_REFPROP_FRU_PARENT, &fruph);
11630Sstevel@tonic-gate if (retval != PICL_SUCCESS) {
11642606Svenki /*
1165*12601SJustin.Frank@Sun.COM * on Boston, Seattle and Netra-440 we should
1166*12601SJustin.Frank@Sun.COM * actually be looking for the _location_parent
1167*12601SJustin.Frank@Sun.COM * property for fan frus
11682606Svenki */
1169*12601SJustin.Frank@Sun.COM if (fanfru) {
1170*12601SJustin.Frank@Sun.COM retval = ptree_get_prop_by_name(nodeh,
1171*12601SJustin.Frank@Sun.COM PICL_REFPROP_LOC_PARENT, &fruph);
11722606Svenki }
11732606Svenki if (retval != PICL_SUCCESS)
11742606Svenki continue;
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate /*
11770Sstevel@tonic-gate * got a _fru_parent node reference delete it
11780Sstevel@tonic-gate */
1179*12601SJustin.Frank@Sun.COM if (ptree_delete_prop(fruph) == PICL_SUCCESS)
1180*12601SJustin.Frank@Sun.COM (void) ptree_destroy_prop(fruph);
1181*12601SJustin.Frank@Sun.COM
1182*12601SJustin.Frank@Sun.COM /* On Netra-440, extra clean-up is required for fan trays */
1183*12601SJustin.Frank@Sun.COM if ((sys_platform == PLAT_CHALUPA19) && (fanfru)) {
1184*12601SJustin.Frank@Sun.COM /* remove the rmclomv node and its properties */
1185*12601SJustin.Frank@Sun.COM delete_node_and_props(nodeh);
11860Sstevel@tonic-gate }
1187*12601SJustin.Frank@Sun.COM }
1188*12601SJustin.Frank@Sun.COM afterloop:
1189*12601SJustin.Frank@Sun.COM /* More Netra-440 fan tray clean-up */
1190*12601SJustin.Frank@Sun.COM if ((sys_platform == PLAT_CHALUPA19) && (fanfru)) {
1191*12601SJustin.Frank@Sun.COM /* remove the fru's child's table */
1192*12601SJustin.Frank@Sun.COM if (ptree_delete_prop(tableh) == PICL_SUCCESS)
1193*12601SJustin.Frank@Sun.COM (void) ptree_destroy_prop(tableh);
1194*12601SJustin.Frank@Sun.COM /* remove the child */
1195*12601SJustin.Frank@Sun.COM if (ptree_delete_node(childh) == PICL_SUCCESS)
1196*12601SJustin.Frank@Sun.COM (void) ptree_destroy_node(childh);
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate
12000Sstevel@tonic-gate static void
remove_tables(picl_nodehdl_t rootnd)12010Sstevel@tonic-gate remove_tables(picl_nodehdl_t rootnd)
12020Sstevel@tonic-gate {
12030Sstevel@tonic-gate picl_nodehdl_t tableh;
12040Sstevel@tonic-gate int retval;
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate retval = ptree_get_prop_by_name(rootnd, PICL_PROP_DEVICES, &tableh);
12070Sstevel@tonic-gate
12080Sstevel@tonic-gate if (retval == PICL_SUCCESS) {
12090Sstevel@tonic-gate /*
12100Sstevel@tonic-gate * found a Devices property, delete it
12110Sstevel@tonic-gate */
12120Sstevel@tonic-gate if ((retval = ptree_delete_prop(tableh)) == PICL_SUCCESS) {
12130Sstevel@tonic-gate (void) ptree_destroy_prop(tableh);
12140Sstevel@tonic-gate }
12150Sstevel@tonic-gate }
12160Sstevel@tonic-gate
12170Sstevel@tonic-gate /*
12180Sstevel@tonic-gate * is there a child node?
12190Sstevel@tonic-gate */
12200Sstevel@tonic-gate retval = ptree_get_propval_by_name(rootnd, PICL_PROP_CHILD, &rootnd,
12210Sstevel@tonic-gate sizeof (rootnd));
12220Sstevel@tonic-gate
12230Sstevel@tonic-gate while (retval == PICL_SUCCESS) {
12240Sstevel@tonic-gate
12250Sstevel@tonic-gate remove_tables(rootnd);
12260Sstevel@tonic-gate
12270Sstevel@tonic-gate /*
12280Sstevel@tonic-gate * any siblings?
12290Sstevel@tonic-gate */
12300Sstevel@tonic-gate retval = ptree_get_propval_by_name(rootnd, PICL_PROP_PEER,
12310Sstevel@tonic-gate &rootnd, sizeof (rootnd));
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate }
12340Sstevel@tonic-gate
12352606Svenki /*
12362606Svenki * Event completion handler for PICL_FRU_ADDED/PICL_FRU_REMOVED events
12372606Svenki */
1238*12601SJustin.Frank@Sun.COM /* ARGSUSED */
12390Sstevel@tonic-gate static void
frudr_completion_handler(char * ename,void * earg,size_t size)12400Sstevel@tonic-gate frudr_completion_handler(char *ename, void *earg, size_t size)
12410Sstevel@tonic-gate {
12420Sstevel@tonic-gate picl_nodehdl_t fruh;
12432606Svenki picl_nodehdl_t parh;
1244*12601SJustin.Frank@Sun.COM picl_nodehdl_t peerh = NULL;
1245*12601SJustin.Frank@Sun.COM char nodename[PICL_PROPNAMELEN_MAX] = { '\0' };
12460Sstevel@tonic-gate int err;
12470Sstevel@tonic-gate
12480Sstevel@tonic-gate if (strcmp(ename, PICL_FRU_REMOVED) == 0) {
12490Sstevel@tonic-gate /*
12500Sstevel@tonic-gate * now frudata has been notified that the node is to be
12510Sstevel@tonic-gate * removed, we can actually remove it
12520Sstevel@tonic-gate */
12530Sstevel@tonic-gate fruh = NULL;
12540Sstevel@tonic-gate (void) nvlist_lookup_uint64(earg,
12550Sstevel@tonic-gate PICLEVENTARG_FRUHANDLE, &fruh);
12560Sstevel@tonic-gate if (fruh != NULL) {
1257*12601SJustin.Frank@Sun.COM (void) ptree_get_propval_by_name(fruh, PICL_PROP_PEER,
1258*12601SJustin.Frank@Sun.COM &peerh, sizeof (peerh));
1259*12601SJustin.Frank@Sun.COM
12600Sstevel@tonic-gate /*
12610Sstevel@tonic-gate * first find name of the fru
12620Sstevel@tonic-gate */
12630Sstevel@tonic-gate err = ptree_get_propval_by_name(fruh, PICL_PROP_PARENT,
12642606Svenki &parh, sizeof (parh));
12650Sstevel@tonic-gate if (err == PICL_SUCCESS) {
12662606Svenki err = ptree_get_propval_by_name(parh,
12670Sstevel@tonic-gate PICL_PROP_NAME, nodename,
12680Sstevel@tonic-gate sizeof (nodename));
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate if (err == PICL_SUCCESS) {
12710Sstevel@tonic-gate /*
12720Sstevel@tonic-gate * if it was a power supply, delete i2c node
12730Sstevel@tonic-gate */
12740Sstevel@tonic-gate if (strncmp(nodename, PS_NAME,
12750Sstevel@tonic-gate PS_NAME_LEN) == 0) {
12760Sstevel@tonic-gate (void) delete_i2c_node(nodename);
12770Sstevel@tonic-gate }
12780Sstevel@tonic-gate
12790Sstevel@tonic-gate /*
12800Sstevel@tonic-gate * is disk node, make thread re-evaluate led
12810Sstevel@tonic-gate * state
12820Sstevel@tonic-gate */
12830Sstevel@tonic-gate if (strncmp(nodename, DISK_NAME,
12840Sstevel@tonic-gate DISK_NAME_LEN) == 0) {
12850Sstevel@tonic-gate disk_ready[nodename[DISK_NAME_LEN] -
12860Sstevel@tonic-gate '0'] = -1;
12870Sstevel@tonic-gate }
12880Sstevel@tonic-gate }
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate remove_fru_parents(fruh);
12910Sstevel@tonic-gate
12920Sstevel@tonic-gate /*
12930Sstevel@tonic-gate * now we can delete the node
12940Sstevel@tonic-gate */
12950Sstevel@tonic-gate err = ptree_delete_node(fruh);
12960Sstevel@tonic-gate if (err == PICL_SUCCESS) {
12970Sstevel@tonic-gate (void) ptree_destroy_node(fruh);
12980Sstevel@tonic-gate } else {
12990Sstevel@tonic-gate syslog(LOG_ERR, DELETE_PROP_FAIL, err);
13000Sstevel@tonic-gate }
1301*12601SJustin.Frank@Sun.COM
1302*12601SJustin.Frank@Sun.COM if ((sys_platform == PLAT_CHALUPA19) &&
1303*12601SJustin.Frank@Sun.COM (strncmp(nodename, FT_NAME, FT_NAME_LEN) == 0) &&
1304*12601SJustin.Frank@Sun.COM (peerh != NULL)) {
1305*12601SJustin.Frank@Sun.COM /*
1306*12601SJustin.Frank@Sun.COM * On Netra-440 platforms, a fan tray
1307*12601SJustin.Frank@Sun.COM * may contain 2 fans (F0 and F1) but
1308*12601SJustin.Frank@Sun.COM * we only receive a single notification
1309*12601SJustin.Frank@Sun.COM * for removal of F0. If F1 is present,
1310*12601SJustin.Frank@Sun.COM * peerh will be valid and we need to
1311*12601SJustin.Frank@Sun.COM * process it as well.
1312*12601SJustin.Frank@Sun.COM */
1313*12601SJustin.Frank@Sun.COM remove_fru_parents(peerh);
1314*12601SJustin.Frank@Sun.COM err = ptree_delete_node(peerh);
1315*12601SJustin.Frank@Sun.COM if (err == PICL_SUCCESS) {
1316*12601SJustin.Frank@Sun.COM (void) ptree_destroy_node(peerh);
1317*12601SJustin.Frank@Sun.COM } else {
1318*12601SJustin.Frank@Sun.COM syslog(LOG_ERR, DELETE_PROP_FAIL, err);
1319*12601SJustin.Frank@Sun.COM }
1320*12601SJustin.Frank@Sun.COM }
13210Sstevel@tonic-gate }
13220Sstevel@tonic-gate }
13232606Svenki
13242606Svenki free(ename);
13250Sstevel@tonic-gate nvlist_free(earg);
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate
13280Sstevel@tonic-gate /*
13290Sstevel@tonic-gate * Post the PICL_FRU_ADDED/PICL_FRU_REMOVED event
13300Sstevel@tonic-gate */
13310Sstevel@tonic-gate static void
post_frudr_event(char * ename,picl_nodehdl_t parenth,picl_nodehdl_t fruh)13320Sstevel@tonic-gate post_frudr_event(char *ename, picl_nodehdl_t parenth, picl_nodehdl_t fruh)
13330Sstevel@tonic-gate {
13340Sstevel@tonic-gate nvlist_t *nvl;
13350Sstevel@tonic-gate char *ev_name;
13360Sstevel@tonic-gate
13370Sstevel@tonic-gate ev_name = strdup(ename);
13380Sstevel@tonic-gate if (ev_name == NULL)
13390Sstevel@tonic-gate return;
13400Sstevel@tonic-gate if (nvlist_alloc(&nvl, NV_UNIQUE_NAME_TYPE, NULL)) {
13410Sstevel@tonic-gate free(ev_name);
13420Sstevel@tonic-gate return;
13430Sstevel@tonic-gate }
13440Sstevel@tonic-gate if (parenth != 0L &&
13450Sstevel@tonic-gate nvlist_add_uint64(nvl, PICLEVENTARG_PARENTHANDLE, parenth)) {
13460Sstevel@tonic-gate free(ev_name);
13470Sstevel@tonic-gate nvlist_free(nvl);
13480Sstevel@tonic-gate return;
13490Sstevel@tonic-gate }
13500Sstevel@tonic-gate if (fruh != 0L &&
13510Sstevel@tonic-gate nvlist_add_uint64(nvl, PICLEVENTARG_FRUHANDLE, fruh)) {
13520Sstevel@tonic-gate free(ev_name);
13530Sstevel@tonic-gate nvlist_free(nvl);
13540Sstevel@tonic-gate return;
13550Sstevel@tonic-gate }
13560Sstevel@tonic-gate if (ptree_post_event(ev_name, nvl, sizeof (nvl),
13570Sstevel@tonic-gate frudr_completion_handler) != 0) {
13580Sstevel@tonic-gate free(ev_name);
13590Sstevel@tonic-gate nvlist_free(nvl);
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate }
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate static void
add_ps_to_platform(char * unit)13640Sstevel@tonic-gate add_ps_to_platform(char *unit)
13650Sstevel@tonic-gate {
13660Sstevel@tonic-gate picl_nodehdl_t parent_hdl;
13670Sstevel@tonic-gate picl_nodehdl_t child_hdl;
13680Sstevel@tonic-gate ptree_propinfo_t info;
13690Sstevel@tonic-gate int unit_size = 1 + strlen(unit);
13700Sstevel@tonic-gate int res;
13710Sstevel@tonic-gate char unit_addr[PICL_UNITADDR_LEN_MAX];
13720Sstevel@tonic-gate
13731103Sjbeloro switch (sys_platform) {
13741103Sjbeloro case PLAT_SEATTLE1U:
13751103Sjbeloro case PLAT_SEATTLE2U:
13761103Sjbeloro res = ptree_get_node_by_path(SEATTLE_PSU_PLATFORM, &parent_hdl);
13771103Sjbeloro break;
13781103Sjbeloro case PLAT_BOSTON:
13791103Sjbeloro res = ptree_get_node_by_path(BOSTON_PSU_PLATFORM, &parent_hdl);
13801103Sjbeloro break;
13811103Sjbeloro default:
13821103Sjbeloro res = ptree_get_node_by_path(PSU_PLATFORM, &parent_hdl);
13831103Sjbeloro break;
13841103Sjbeloro }
13851103Sjbeloro
13861103Sjbeloro if (res != PICL_SUCCESS)
13870Sstevel@tonic-gate return;
13880Sstevel@tonic-gate /*
13890Sstevel@tonic-gate * seeprom nodes sit below this node,
13900Sstevel@tonic-gate * is there one with the supplied unit address?
13910Sstevel@tonic-gate */
13920Sstevel@tonic-gate res = ptree_get_propval_by_name(parent_hdl, PICL_PROP_CHILD,
13930Sstevel@tonic-gate &child_hdl, sizeof (picl_nodehdl_t));
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate while (res == PICL_SUCCESS) {
13960Sstevel@tonic-gate res = ptree_get_propval_by_name(child_hdl, PICL_PROP_PEER,
13970Sstevel@tonic-gate &child_hdl, sizeof (picl_nodehdl_t));
13980Sstevel@tonic-gate if ((res == PICL_SUCCESS) &&
1399*12601SJustin.Frank@Sun.COM ptree_get_propval_by_name(child_hdl,
1400*12601SJustin.Frank@Sun.COM PICL_PROP_UNIT_ADDRESS, unit_addr,
1401*12601SJustin.Frank@Sun.COM sizeof (unit_addr)) == PICL_SUCCESS) {
14020Sstevel@tonic-gate unit_addr[sizeof (unit_addr) - 1] = '\0';
14030Sstevel@tonic-gate if (strcmp(unit_addr, unit) == 0)
14040Sstevel@tonic-gate return; /* unit address exists already */
14050Sstevel@tonic-gate }
14060Sstevel@tonic-gate }
14070Sstevel@tonic-gate
14080Sstevel@tonic-gate /*
14090Sstevel@tonic-gate * found platform location for PS seeprom node, create it
14100Sstevel@tonic-gate */
14110Sstevel@tonic-gate if (ptree_create_and_add_node(parent_hdl, PS_PLATFORM_NAME,
14120Sstevel@tonic-gate PICL_CLASS_SEEPROM, &child_hdl) != PICL_SUCCESS)
14130Sstevel@tonic-gate return;
14140Sstevel@tonic-gate if (ptree_init_propinfo(&info, PTREE_PROPINFO_VERSION,
14150Sstevel@tonic-gate PICL_PTYPE_CHARSTRING, PICL_READ, unit_size,
14160Sstevel@tonic-gate PICL_PROP_UNIT_ADDRESS, NULL, NULL) != PICL_SUCCESS)
14170Sstevel@tonic-gate return;
14180Sstevel@tonic-gate (void) ptree_create_and_add_prop(child_hdl, &info, unit, NULL);
14190Sstevel@tonic-gate }
14200Sstevel@tonic-gate
14212606Svenki static void
get_fantray_path(char * ap_id,char * path,int bufsz)14222606Svenki get_fantray_path(char *ap_id, char *path, int bufsz)
14232606Svenki {
14242606Svenki char ft_id[FT_ID_BUFSZ];
14252606Svenki
14262606Svenki (void) strlcpy(ft_id, ap_id, FT_ID_BUFSZ);
14272606Svenki
14282606Svenki switch (sys_platform) {
14292606Svenki case PLAT_SEATTLE1U:
14302606Svenki if ((strncmp(ap_id, "FT0", 3) == 0) ||
14312606Svenki (strncmp(ap_id, "FT1", 3) == 0) ||
14322606Svenki (strncmp(ap_id, "FT2", 3) == 0)) {
14332606Svenki (void) snprintf(path, bufsz, SEATTLE_FCB0_1U, ft_id);
14342606Svenki } else if ((strncmp(ap_id, "FT3", 3) == 0) ||
14352606Svenki (strncmp(ap_id, "FT4", 3) == 0) ||
14362606Svenki (strncmp(ap_id, "FT5", 3) == 0)) {
14372606Svenki (void) snprintf(path, bufsz, SEATTLE_FCB1_1U, ft_id);
14382606Svenki } else {
14392606Svenki (void) snprintf(path, bufsz, SEATTLE_PDB_1U, ft_id);
14402606Svenki }
14412606Svenki break;
14422606Svenki
14432606Svenki case PLAT_SEATTLE2U:
14442606Svenki if ((strncmp(ap_id, "FT0", 3) == 0) ||
14452606Svenki (strncmp(ap_id, "FT1", 3) == 0) ||
14462606Svenki (strncmp(ap_id, "FT2", 3) == 0)) {
14472606Svenki (void) snprintf(path, bufsz, SEATTLE_FCB0_2U, ft_id);
14482606Svenki } else if ((strncmp(ap_id, "FT3", 3) == 0) ||
14492606Svenki (strncmp(ap_id, "FT4", 3) == 0) ||
14502606Svenki (strncmp(ap_id, "FT5", 3) == 0)) {
14512606Svenki (void) snprintf(path, bufsz, SEATTLE_FCB1_2U, ft_id);
14522606Svenki } else {
14532606Svenki (void) snprintf(path, bufsz, SEATTLE_PDB_2U, ft_id);
14542606Svenki }
14552606Svenki break;
14562606Svenki
14572606Svenki case PLAT_BOSTON:
14582606Svenki (void) snprintf(path, bufsz, SYS_BOARD_PATH, ft_id);
14592606Svenki break;
14602606Svenki
14612606Svenki default:
14622606Svenki (void) snprintf(path, bufsz, CHASSIS_LOC_PATH, ft_id);
14632606Svenki break;
14642606Svenki }
14652606Svenki }
14662606Svenki
14670Sstevel@tonic-gate /*
14680Sstevel@tonic-gate * handle EC_DR picl events
14690Sstevel@tonic-gate */
14700Sstevel@tonic-gate /*ARGSUSED*/
14710Sstevel@tonic-gate static void
frudr_evhandler(const char * ename,const void * earg,size_t size,void * cookie)14720Sstevel@tonic-gate frudr_evhandler(const char *ename, const void *earg, size_t size, void *cookie)
14730Sstevel@tonic-gate {
14740Sstevel@tonic-gate nvlist_t *nvlp;
14750Sstevel@tonic-gate char *dtype;
14760Sstevel@tonic-gate char *ap_id;
14770Sstevel@tonic-gate char *hint;
14780Sstevel@tonic-gate char path[MAXPATHLEN];
14790Sstevel@tonic-gate picl_nodehdl_t fruh;
14800Sstevel@tonic-gate picl_nodehdl_t locnodeh;
14810Sstevel@tonic-gate int err;
14820Sstevel@tonic-gate int index;
14830Sstevel@tonic-gate picl_nodehdl_t childh;
14840Sstevel@tonic-gate char *fru_name;
14850Sstevel@tonic-gate boolean_t rmc_flag = B_FALSE;
14860Sstevel@tonic-gate
14870Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_DR_AP_STATE_CHANGE) != 0) {
14880Sstevel@tonic-gate return;
14890Sstevel@tonic-gate }
14900Sstevel@tonic-gate
14910Sstevel@tonic-gate if (nvlist_unpack((char *)earg, size, &nvlp, NULL)) {
14920Sstevel@tonic-gate return;
14930Sstevel@tonic-gate }
14940Sstevel@tonic-gate
14950Sstevel@tonic-gate if (nvlist_lookup_string(nvlp, PICLEVENTARG_DATA_TYPE, &dtype)) {
14960Sstevel@tonic-gate nvlist_free(nvlp);
14970Sstevel@tonic-gate return;
14980Sstevel@tonic-gate }
14990Sstevel@tonic-gate
15000Sstevel@tonic-gate if (strcmp(dtype, PICLEVENTARG_PICLEVENT_DATA) != 0) {
15010Sstevel@tonic-gate nvlist_free(nvlp);
15020Sstevel@tonic-gate return;
15030Sstevel@tonic-gate }
15040Sstevel@tonic-gate
15050Sstevel@tonic-gate if (nvlist_lookup_string(nvlp, PICLEVENTARG_AP_ID, &ap_id)) {
15060Sstevel@tonic-gate nvlist_free(nvlp);
15070Sstevel@tonic-gate return;
15080Sstevel@tonic-gate }
15090Sstevel@tonic-gate
15100Sstevel@tonic-gate /*
15110Sstevel@tonic-gate * check ap_id really is a hot-plug device
15120Sstevel@tonic-gate */
15130Sstevel@tonic-gate if (strncmp(ap_id, PS_NAME, PS_NAME_LEN) == 0) {
15140Sstevel@tonic-gate fru_name = PS_FRU_NAME;
15150Sstevel@tonic-gate } else if (strncmp(ap_id, DISK_NAME, DISK_NAME_LEN) == 0) {
15160Sstevel@tonic-gate fru_name = DISK_FRU_NAME;
15170Sstevel@tonic-gate } else if (strncmp(ap_id, SCC_NAME, SCC_NAME_LEN) == 0) {
15180Sstevel@tonic-gate fru_name = SCC_FRU_NAME;
15190Sstevel@tonic-gate } else if (strncmp(ap_id, RMC_NAME, RMC_NAME_LEN) == 0) {
15200Sstevel@tonic-gate fru_name = RMC_FRU_NAME;
15210Sstevel@tonic-gate rmc_flag = B_TRUE;
15222606Svenki } else if (strncmp(ap_id, FT_NAME, FT_NAME_LEN) == 0) {
15232606Svenki fru_name = FT_FRU_NAME;
15240Sstevel@tonic-gate } else {
15250Sstevel@tonic-gate nvlist_free(nvlp);
15260Sstevel@tonic-gate return;
15270Sstevel@tonic-gate }
15280Sstevel@tonic-gate
15290Sstevel@tonic-gate if (nvlist_lookup_string(nvlp, PICLEVENTARG_HINT, &hint)) {
15300Sstevel@tonic-gate nvlist_free(nvlp);
15310Sstevel@tonic-gate return;
15320Sstevel@tonic-gate }
15330Sstevel@tonic-gate
15340Sstevel@tonic-gate /*
15350Sstevel@tonic-gate * OK - so this is an EC_DR event - let's handle it.
15360Sstevel@tonic-gate */
15370Sstevel@tonic-gate if (rmc_flag && (sys_platform != PLAT_CHALUPA) &&
1538*12601SJustin.Frank@Sun.COM (sys_platform != PLAT_CHALUPA19))
15390Sstevel@tonic-gate sprintf_buf2(path, SYS_BOARD_PATH, ap_id);
15400Sstevel@tonic-gate else {
15410Sstevel@tonic-gate if ((sys_platform == PLAT_CHALUPA19) &&
1542*12601SJustin.Frank@Sun.COM (strncmp(ap_id, PS_NAME, PS_NAME_LEN) == 0)) {
15430Sstevel@tonic-gate sprintf_buf2(path, CHASSIS_LOC_PATH,
1544*12601SJustin.Frank@Sun.COM ps_apid_to_nodename(ap_id));
15451103Sjbeloro } else if (strncmp(ap_id, DISK_NAME, DISK_NAME_LEN) == 0) {
15461103Sjbeloro switch (sys_platform) {
15471103Sjbeloro case PLAT_SEATTLE1U:
15481103Sjbeloro sprintf_buf2(path, SEATTLE1U_HDDBP_PATH, ap_id);
15491103Sjbeloro break;
15501103Sjbeloro case PLAT_SEATTLE2U:
15511103Sjbeloro sprintf_buf2(path, SEATTLE2U_HDDBP_PATH, ap_id);
15521103Sjbeloro break;
15531103Sjbeloro case PLAT_BOSTON:
15541103Sjbeloro sprintf_buf2(path, BOSTON_HDDBP_PATH, ap_id);
15551103Sjbeloro break;
15561103Sjbeloro default:
15571103Sjbeloro sprintf_buf2(path, CHASSIS_LOC_PATH, ap_id);
15581103Sjbeloro break;
15591103Sjbeloro }
15602606Svenki } else if (strncmp(ap_id, FT_NAME, FT_NAME_LEN) == 0) {
15612606Svenki get_fantray_path(ap_id, path, MAXPATHLEN);
15621103Sjbeloro } else {
15631103Sjbeloro sprintf_buf2(path, CHASSIS_LOC_PATH, ap_id);
15640Sstevel@tonic-gate }
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate if (ptree_get_node_by_path(path, &locnodeh) != PICL_SUCCESS) {
15680Sstevel@tonic-gate nvlist_free(nvlp);
15690Sstevel@tonic-gate return;
15700Sstevel@tonic-gate }
15710Sstevel@tonic-gate
15720Sstevel@tonic-gate /*
15730Sstevel@tonic-gate * now either add or delete the fru node as appropriate. If no
15740Sstevel@tonic-gate * hint, treat as insert and update the tree if necessary.
15750Sstevel@tonic-gate */
15760Sstevel@tonic-gate if (strcmp(hint, DR_HINT_REMOVE) == 0) {
15770Sstevel@tonic-gate if (ptree_get_propval_by_name(locnodeh, PICL_PROP_CHILD,
15780Sstevel@tonic-gate &fruh, sizeof (picl_nodehdl_t)) == PICL_SUCCESS) {
15790Sstevel@tonic-gate /*
15800Sstevel@tonic-gate * fru was there - but has gone away
15810Sstevel@tonic-gate */
15820Sstevel@tonic-gate post_frudr_event(PICL_FRU_REMOVED, NULL, fruh);
15830Sstevel@tonic-gate }
15840Sstevel@tonic-gate } else if (rmc_flag) {
15850Sstevel@tonic-gate /*
15860Sstevel@tonic-gate * An event on the RMC location, just pass it on
15870Sstevel@tonic-gate * it's not really a PICL_FRU_ADDED event, so offer
15880Sstevel@tonic-gate * the child handle as well (if it exists).
15890Sstevel@tonic-gate */
15900Sstevel@tonic-gate if (ptree_get_propval_by_name(locnodeh, PICL_PROP_CHILD,
15910Sstevel@tonic-gate &fruh, sizeof (picl_nodehdl_t)) != PICL_SUCCESS) {
15920Sstevel@tonic-gate fruh = NULL;
15930Sstevel@tonic-gate }
15940Sstevel@tonic-gate post_frudr_event(PICL_FRU_ADDED, locnodeh, fruh);
15950Sstevel@tonic-gate } else {
15960Sstevel@tonic-gate /*
15970Sstevel@tonic-gate * fru has been inserted (or may need to update)
15980Sstevel@tonic-gate * if node already there, then just return
15990Sstevel@tonic-gate */
16000Sstevel@tonic-gate childh = find_child_by_name(locnodeh, fru_name);
16010Sstevel@tonic-gate if (childh != NULL) {
16020Sstevel@tonic-gate nvlist_free(nvlp);
16030Sstevel@tonic-gate return;
16040Sstevel@tonic-gate }
16050Sstevel@tonic-gate
16060Sstevel@tonic-gate /*
1607*12601SJustin.Frank@Sun.COM * On Netra-440, the fan-tray location nodes are
1608*12601SJustin.Frank@Sun.COM * not deleted when fan-trays are physically
1609*12601SJustin.Frank@Sun.COM * removed, so we do not need to create another
1610*12601SJustin.Frank@Sun.COM * fru node.
16110Sstevel@tonic-gate */
1612*12601SJustin.Frank@Sun.COM if ((sys_platform != PLAT_CHALUPA19) ||
1613*12601SJustin.Frank@Sun.COM (strncmp(fru_name, FT_FRU_NAME, FT_FRU_NAME_LEN) != 0)) {
1614*12601SJustin.Frank@Sun.COM /*
1615*12601SJustin.Frank@Sun.COM * create requested fru node
1616*12601SJustin.Frank@Sun.COM */
1617*12601SJustin.Frank@Sun.COM err = ptree_create_and_add_node(locnodeh, fru_name,
1618*12601SJustin.Frank@Sun.COM PICL_CLASS_FRU, &childh);
1619*12601SJustin.Frank@Sun.COM if (err != PICL_SUCCESS) {
1620*12601SJustin.Frank@Sun.COM syslog(LOG_ERR, ADD_NODE_FAIL, ap_id, err);
1621*12601SJustin.Frank@Sun.COM nvlist_free(nvlp);
1622*12601SJustin.Frank@Sun.COM return;
1623*12601SJustin.Frank@Sun.COM }
16240Sstevel@tonic-gate }
16250Sstevel@tonic-gate
16260Sstevel@tonic-gate /*
16270Sstevel@tonic-gate * power supplies have operational status and fruid -
16280Sstevel@tonic-gate * add OperationalStatus property and create i2c device node
16290Sstevel@tonic-gate * before posting fru_added event
16300Sstevel@tonic-gate */
16310Sstevel@tonic-gate if (strncmp(ap_id, PS_NAME, PS_NAME_LEN) == 0) {
16320Sstevel@tonic-gate index = find_vol_prop_by_name(
1633*12601SJustin.Frank@Sun.COM ps_apid_to_nodename(ap_id));
16340Sstevel@tonic-gate if (index >= 0)
16350Sstevel@tonic-gate add_op_status_to_node(childh,
16360Sstevel@tonic-gate &idprop->idp[index].volprop);
16370Sstevel@tonic-gate (void) create_i2c_node(ap_id);
16380Sstevel@tonic-gate add_ps_to_platform(ps_name_to_unitaddr(ap_id));
16390Sstevel@tonic-gate }
16400Sstevel@tonic-gate
16410Sstevel@tonic-gate /*
16420Sstevel@tonic-gate * now post event
16430Sstevel@tonic-gate */
16440Sstevel@tonic-gate post_frudr_event(PICL_FRU_ADDED, locnodeh, NULL);
16450Sstevel@tonic-gate }
16460Sstevel@tonic-gate nvlist_free(nvlp);
16470Sstevel@tonic-gate }
16480Sstevel@tonic-gate
16490Sstevel@tonic-gate /*
16500Sstevel@tonic-gate * Handle PICL_FRU_ADDED events.
16510Sstevel@tonic-gate * These events are posted by the frudr_evhandler of this plugin in response to
16520Sstevel@tonic-gate * PICLEVENT_DR_AP_STATE_CHANGE events. The sequence is as follows:
16530Sstevel@tonic-gate * 1) frudr_evhandler catches PICLEVENT_DR_AP_STATE_CHANGE and creates a
16540Sstevel@tonic-gate * child node below the relevant location.
16550Sstevel@tonic-gate * 2) frudr_evhandler posts a PICL_FRU_ADDED event.
16560Sstevel@tonic-gate * 3) envmon catches PICL_FRU_ADDED event, gropes the RMC configuration
16570Sstevel@tonic-gate * and creates platform tree nodes (primarily for PSUs). (If the event
16580Sstevel@tonic-gate * is for the RMC itself, envmon deletes existing platform nodes and
16590Sstevel@tonic-gate * rebuilds from scratch.)
16600Sstevel@tonic-gate * 4) this plugin catches PICL_FRU_ADDED event, looks for a related
16610Sstevel@tonic-gate * configuration file and parses it. This adds Fru data properties (etc.).
16620Sstevel@tonic-gate * 5) frudata catches the event and updates its FRUID data cache.
16630Sstevel@tonic-gate */
16640Sstevel@tonic-gate /*ARGSUSED*/
16650Sstevel@tonic-gate static void
fru_add_handler(const char * ename,const void * earg,size_t size,void * cookie)16660Sstevel@tonic-gate fru_add_handler(const char *ename, const void *earg, size_t size, void *cookie)
16670Sstevel@tonic-gate {
16680Sstevel@tonic-gate int retval;
16690Sstevel@tonic-gate picl_nodehdl_t locnodeh;
16700Sstevel@tonic-gate picl_nodehdl_t rooth;
16710Sstevel@tonic-gate char path[MAXPATHLEN];
16720Sstevel@tonic-gate char *fru_name;
16730Sstevel@tonic-gate
16740Sstevel@tonic-gate if (strcmp(ename, PICL_FRU_ADDED) != 0)
16750Sstevel@tonic-gate return;
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate retval = nvlist_lookup_uint64((nvlist_t *)earg,
16780Sstevel@tonic-gate PICLEVENTARG_PARENTHANDLE, &locnodeh);
16790Sstevel@tonic-gate if (retval != PICL_SUCCESS)
16800Sstevel@tonic-gate return;
16810Sstevel@tonic-gate
16820Sstevel@tonic-gate retval = ptree_get_propval_by_name(locnodeh, PICL_PROP_NAME,
16830Sstevel@tonic-gate path, sizeof (path));
16840Sstevel@tonic-gate if (retval != PICL_SUCCESS)
16850Sstevel@tonic-gate return;
16860Sstevel@tonic-gate
16870Sstevel@tonic-gate fru_name = strdup(path);
16880Sstevel@tonic-gate if (fru_name == NULL)
16890Sstevel@tonic-gate return;
16900Sstevel@tonic-gate
16910Sstevel@tonic-gate /*
16920Sstevel@tonic-gate * We're about to parse a fru-specific .conf file to populate
16930Sstevel@tonic-gate * picl nodes relating to the dynamically added component. In the
16940Sstevel@tonic-gate * case of the RMC, there is a problem: all of its /platform tree
16950Sstevel@tonic-gate * nodes have just been replaced by envmon. It is now necessary to
16960Sstevel@tonic-gate * repopulate Devices tables in /frutree.
16970Sstevel@tonic-gate * picld_pluginutil_parse_config_file doesn't handle repopulating
16980Sstevel@tonic-gate * existing tables, so as a work round, delete all tables found
16990Sstevel@tonic-gate * under /frutree. This works on Enchilada Server as the tables
17000Sstevel@tonic-gate * are all created from parsing a .conf file, and we're about to
17010Sstevel@tonic-gate * redo that action.
17020Sstevel@tonic-gate */
17030Sstevel@tonic-gate if (strcmp(fru_name, RMC_NAME) == 0) {
17040Sstevel@tonic-gate rmc_state_event();
17050Sstevel@tonic-gate retval = ptree_get_node_by_path(FRUTREE_PATH, &rooth);
17060Sstevel@tonic-gate if (retval == PICL_SUCCESS) {
17070Sstevel@tonic-gate remove_tables(rooth);
17080Sstevel@tonic-gate }
17090Sstevel@tonic-gate }
17100Sstevel@tonic-gate
17110Sstevel@tonic-gate /*
17120Sstevel@tonic-gate * Re-establish the HPU(FRU) volatile properties.
17130Sstevel@tonic-gate * This needs to be done before the .conf file is parsed because
17140Sstevel@tonic-gate * it has a side effect of re-creating any missing power-supply
17150Sstevel@tonic-gate * fru node. The .conf file can then hang properties beneath.
17160Sstevel@tonic-gate */
17170Sstevel@tonic-gate opst_init();
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate /*
17200Sstevel@tonic-gate * see if there's a .conf file for this fru
17210Sstevel@tonic-gate */
17220Sstevel@tonic-gate if (get_config_file(path, fru_name) == 0) {
17230Sstevel@tonic-gate if ((ptree_get_root(&rooth) != PICL_SUCCESS) ||
17240Sstevel@tonic-gate (picld_pluginutil_parse_config_file(rooth, path) !=
17250Sstevel@tonic-gate PICL_SUCCESS)) {
17260Sstevel@tonic-gate syslog(LOG_ERR, PARSE_CONF_FAIL, path);
17270Sstevel@tonic-gate }
17280Sstevel@tonic-gate }
17290Sstevel@tonic-gate
17300Sstevel@tonic-gate free(fru_name);
17310Sstevel@tonic-gate }
17320Sstevel@tonic-gate
17330Sstevel@tonic-gate /*
17340Sstevel@tonic-gate * Handle PICLEVENT_SYSEVENT_DEVICE_ADDED events.
17350Sstevel@tonic-gate */
17360Sstevel@tonic-gate /*ARGSUSED*/
17370Sstevel@tonic-gate static void
frutree_evhandler(const char * ename,const void * earg,size_t size,void * cookie)17380Sstevel@tonic-gate frutree_evhandler(const char *ename, const void *earg, size_t size,
17390Sstevel@tonic-gate void *cookie)
17400Sstevel@tonic-gate {
17410Sstevel@tonic-gate nvlist_t *nvlp;
17420Sstevel@tonic-gate picl_nodehdl_t rooth;
17430Sstevel@tonic-gate char path[MAXPATHLEN];
17440Sstevel@tonic-gate char *fru_name;
17450Sstevel@tonic-gate char *dtype;
17460Sstevel@tonic-gate char *dpath;
17470Sstevel@tonic-gate char *ptr;
17480Sstevel@tonic-gate char *ptr2;
17490Sstevel@tonic-gate int done = B_FALSE;
17501103Sjbeloro int i;
17510Sstevel@tonic-gate
17520Sstevel@tonic-gate if (strcmp(ename, PICLEVENT_SYSEVENT_DEVICE_ADDED) != 0)
17530Sstevel@tonic-gate return;
17540Sstevel@tonic-gate
17550Sstevel@tonic-gate if (nvlist_unpack((char *)earg, size, &nvlp, NULL))
17560Sstevel@tonic-gate return;
17570Sstevel@tonic-gate
17580Sstevel@tonic-gate if (nvlist_lookup_string(nvlp, PICLEVENTARG_DATA_TYPE, &dtype)) {
17590Sstevel@tonic-gate nvlist_free(nvlp);
17600Sstevel@tonic-gate return;
17610Sstevel@tonic-gate }
17620Sstevel@tonic-gate
17630Sstevel@tonic-gate if (strcmp(dtype, PICLEVENTARG_PICLEVENT_DATA) != 0) {
17640Sstevel@tonic-gate nvlist_free(nvlp);
17650Sstevel@tonic-gate return;
17660Sstevel@tonic-gate }
17670Sstevel@tonic-gate
17680Sstevel@tonic-gate if (nvlist_lookup_string(nvlp, PICLEVENTARG_DEVFS_PATH, &dpath)) {
17690Sstevel@tonic-gate nvlist_free(nvlp);
17700Sstevel@tonic-gate return;
17710Sstevel@tonic-gate }
17720Sstevel@tonic-gate
17730Sstevel@tonic-gate fru_name = strdup(dpath);
17740Sstevel@tonic-gate if (fru_name == NULL) {
17750Sstevel@tonic-gate nvlist_free(nvlp);
17760Sstevel@tonic-gate return;
17770Sstevel@tonic-gate }
17780Sstevel@tonic-gate
17790Sstevel@tonic-gate nvlist_free(nvlp);
17800Sstevel@tonic-gate
17810Sstevel@tonic-gate /*
17820Sstevel@tonic-gate * fru_name is of the form
17830Sstevel@tonic-gate * "/pci@1e,600000/usb@a/mouse@2"
17840Sstevel@tonic-gate * or
17850Sstevel@tonic-gate * "/pci@1e,600000/usb@a/device@2/mouse@0"
17860Sstevel@tonic-gate * reduce it to "usb-a-2"
17870Sstevel@tonic-gate */
17881103Sjbeloro if ((sys_platform == PLAT_SEATTLE1U) ||
17891103Sjbeloro (sys_platform == PLAT_SEATTLE2U) ||
17901103Sjbeloro (sys_platform == PLAT_BOSTON)) {
17911103Sjbeloro for (i = 0; i < MAX_USB_PORTS; i++) {
17921103Sjbeloro sprintf(fru_name, "%s%d", USB_CONF_FILE_NAME, i+1);
17931103Sjbeloro if (get_config_file(path, fru_name) == 0) {
17941103Sjbeloro if ((ptree_get_root(&rooth) != PICL_SUCCESS) ||
17951103Sjbeloro (picld_pluginutil_parse_config_file(rooth,
17961103Sjbeloro path) != PICL_SUCCESS)) {
17971103Sjbeloro syslog(LOG_ERR, PARSE_CONF_FAIL, path);
17981103Sjbeloro }
17991103Sjbeloro }
18001103Sjbeloro }
18011103Sjbeloro } else {
18021103Sjbeloro ptr = fru_name;
18031103Sjbeloro if (*ptr == '/') {
18040Sstevel@tonic-gate ptr++;
18051103Sjbeloro ptr = strchr(ptr, '/');
18060Sstevel@tonic-gate if (ptr != NULL) {
18070Sstevel@tonic-gate ptr++;
18081103Sjbeloro (void) memmove(fru_name, ptr, strlen(ptr) + 1);
18091103Sjbeloro ptr = strchr(fru_name, '@');
18100Sstevel@tonic-gate if (ptr != NULL) {
18110Sstevel@tonic-gate *ptr = '-';
18120Sstevel@tonic-gate ptr++;
18131103Sjbeloro ptr = strchr(ptr, '/');
18140Sstevel@tonic-gate if (ptr != NULL) {
18151103Sjbeloro *ptr = '-';
18160Sstevel@tonic-gate ptr++;
18171103Sjbeloro ptr2 = ptr;
18181103Sjbeloro ptr = strchr(ptr, '@');
18191103Sjbeloro if (ptr != NULL) {
18201103Sjbeloro ptr++;
18211103Sjbeloro (void) memmove(ptr2,
18221103Sjbeloro ptr, strlen(ptr)+1);
18231103Sjbeloro ptr2 = strchr(ptr2,
18241103Sjbeloro '/');
18251103Sjbeloro if (ptr2 != NULL) {
18261103Sjbeloro *ptr2 = '\0';
18271103Sjbeloro }
18281103Sjbeloro done = B_TRUE;
18290Sstevel@tonic-gate }
18300Sstevel@tonic-gate }
18310Sstevel@tonic-gate }
18320Sstevel@tonic-gate }
18330Sstevel@tonic-gate }
18341103Sjbeloro if (done == B_FALSE) {
18351103Sjbeloro free(fru_name);
18361103Sjbeloro return;
18371103Sjbeloro }
18380Sstevel@tonic-gate
18391103Sjbeloro /*
18401103Sjbeloro * see if there's a .conf file for this fru
18411103Sjbeloro */
18421103Sjbeloro
18431103Sjbeloro if (get_config_file(path, fru_name) == 0) {
18441103Sjbeloro if ((ptree_get_root(&rooth) != PICL_SUCCESS) ||
18451103Sjbeloro (picld_pluginutil_parse_config_file(rooth, path) !=
18461103Sjbeloro PICL_SUCCESS)) {
18471103Sjbeloro syslog(LOG_ERR, PARSE_CONF_FAIL, path);
18481103Sjbeloro }
18490Sstevel@tonic-gate }
18500Sstevel@tonic-gate }
18510Sstevel@tonic-gate
18520Sstevel@tonic-gate free(fru_name);
18530Sstevel@tonic-gate }
18540Sstevel@tonic-gate
18550Sstevel@tonic-gate static int
set_led(char * name,char * ptr,char * value)18560Sstevel@tonic-gate set_led(char *name, char *ptr, char *value)
18570Sstevel@tonic-gate {
18580Sstevel@tonic-gate char path[MAXPATHLEN];
18590Sstevel@tonic-gate picl_prophdl_t proph;
18600Sstevel@tonic-gate ptree_propinfo_t propinfo;
18610Sstevel@tonic-gate picl_prophdl_t tableh;
18620Sstevel@tonic-gate picl_nodehdl_t locnodeh;
18630Sstevel@tonic-gate picl_nodehdl_t nodeh;
18640Sstevel@tonic-gate picl_prophdl_t tblh;
18650Sstevel@tonic-gate int retval;
18660Sstevel@tonic-gate char *value_ptr;
18670Sstevel@tonic-gate char label[PICL_PROPNAMELEN_MAX];
18680Sstevel@tonic-gate char class[PICL_PROPNAMELEN_MAX];
18690Sstevel@tonic-gate
18700Sstevel@tonic-gate /* find the location node */
18711103Sjbeloro switch (sys_platform) {
18721103Sjbeloro case PLAT_CHALUPA:
18731103Sjbeloro case PLAT_CHALUPA19:
18741103Sjbeloro sprintf_buf2(path, CHASSIS_LOC_PATH, name);
18751103Sjbeloro break;
18761103Sjbeloro case PLAT_SEATTLE1U:
18771103Sjbeloro sprintf_buf2(path, SEATTLE1U_HDDBP_PATH, name);
18781103Sjbeloro break;
18791103Sjbeloro case PLAT_SEATTLE2U:
18801103Sjbeloro sprintf_buf2(path, SEATTLE2U_HDDBP_PATH, name);
18811103Sjbeloro break;
18821103Sjbeloro case PLAT_BOSTON:
18831103Sjbeloro sprintf_buf2(path, BOSTON_HDDBP_PATH, name);
18841103Sjbeloro break;
18851103Sjbeloro default:
18861103Sjbeloro sprintf_buf2(path, CHASSIS_LOC_PATH, name);
18871103Sjbeloro break;
18881103Sjbeloro }
18891103Sjbeloro
18901103Sjbeloro if (ptree_get_node_by_path(path, &locnodeh) != PICL_SUCCESS) {
18910Sstevel@tonic-gate return (PICL_FAILURE);
18921103Sjbeloro }
18930Sstevel@tonic-gate
18940Sstevel@tonic-gate /*
18950Sstevel@tonic-gate * if no fru node, then turn led off
18960Sstevel@tonic-gate */
18970Sstevel@tonic-gate if (find_child_by_name(locnodeh, DISK_FRU_NAME) != NULL)
18980Sstevel@tonic-gate value_ptr = value;
18990Sstevel@tonic-gate else
19000Sstevel@tonic-gate value_ptr = PICL_PROPVAL_OFF;
19010Sstevel@tonic-gate
19020Sstevel@tonic-gate /* get its Devices table */
19030Sstevel@tonic-gate if (ptree_get_prop_by_name(locnodeh, PICL_PROP_DEVICES, &tableh) !=
19040Sstevel@tonic-gate PICL_SUCCESS)
19050Sstevel@tonic-gate return (PICL_FAILURE);
19060Sstevel@tonic-gate if (ptree_get_propval(tableh, &tblh, sizeof (tblh)) != PICL_SUCCESS)
19070Sstevel@tonic-gate return (PICL_FAILURE);
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate /* get first col, first row */
19100Sstevel@tonic-gate if (ptree_get_next_by_col(tblh, &tblh) != PICL_SUCCESS)
19110Sstevel@tonic-gate return (PICL_FAILURE);
19120Sstevel@tonic-gate
19130Sstevel@tonic-gate /*
19140Sstevel@tonic-gate * starting at next col, get every entry in the column
19150Sstevel@tonic-gate */
19160Sstevel@tonic-gate for (retval = ptree_get_next_by_row(tblh, &tblh);
19170Sstevel@tonic-gate retval == PICL_SUCCESS;
19180Sstevel@tonic-gate retval = ptree_get_next_by_col(tblh, &tblh)) {
19190Sstevel@tonic-gate /*
19200Sstevel@tonic-gate * get the target node handle
19210Sstevel@tonic-gate */
19220Sstevel@tonic-gate if (ptree_get_propval(tblh, &nodeh, sizeof (nodeh))
19230Sstevel@tonic-gate != PICL_SUCCESS)
19240Sstevel@tonic-gate continue;
19250Sstevel@tonic-gate
19260Sstevel@tonic-gate /*
19270Sstevel@tonic-gate * check it's a led
19280Sstevel@tonic-gate */
19290Sstevel@tonic-gate if (ptree_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME,
19300Sstevel@tonic-gate class, sizeof (class)) != PICL_SUCCESS)
19310Sstevel@tonic-gate continue;
19320Sstevel@tonic-gate if (strcmp(class, "led") != 0)
19330Sstevel@tonic-gate continue;
19340Sstevel@tonic-gate
19350Sstevel@tonic-gate /*
19360Sstevel@tonic-gate * check its the right led
19370Sstevel@tonic-gate */
19380Sstevel@tonic-gate if (ptree_get_propval_by_name(nodeh, PICL_PROP_LABEL,
19390Sstevel@tonic-gate label, sizeof (label)) != PICL_SUCCESS)
19400Sstevel@tonic-gate continue;
19410Sstevel@tonic-gate if (strcmp(label, ptr) == 0) {
19420Sstevel@tonic-gate /*
19430Sstevel@tonic-gate * set it
19440Sstevel@tonic-gate */
19450Sstevel@tonic-gate if (ptree_get_prop_by_name(nodeh, PICL_PROP_STATE,
19460Sstevel@tonic-gate &proph) != PICL_SUCCESS)
19470Sstevel@tonic-gate continue;
19480Sstevel@tonic-gate if (ptree_get_propinfo(proph, &propinfo) !=
19490Sstevel@tonic-gate PICL_SUCCESS)
19500Sstevel@tonic-gate continue;
19510Sstevel@tonic-gate retval = ptree_update_propval_by_name(nodeh,
19520Sstevel@tonic-gate PICL_PROP_STATE, value_ptr, propinfo.piclinfo.size);
19530Sstevel@tonic-gate return (retval);
19540Sstevel@tonic-gate }
19550Sstevel@tonic-gate }
19560Sstevel@tonic-gate return (PICL_FAILURE);
19570Sstevel@tonic-gate }
19580Sstevel@tonic-gate
19590Sstevel@tonic-gate /*
19600Sstevel@tonic-gate * function to find first node of specified class beneath supplied node
19610Sstevel@tonic-gate */
19620Sstevel@tonic-gate static int
get_node_by_class(picl_nodehdl_t nodeh,const char * classname,picl_nodehdl_t * foundnodeh)19630Sstevel@tonic-gate get_node_by_class(picl_nodehdl_t nodeh, const char *classname,
19640Sstevel@tonic-gate picl_nodehdl_t *foundnodeh)
19650Sstevel@tonic-gate {
19660Sstevel@tonic-gate int err;
19670Sstevel@tonic-gate char clname[PICL_CLASSNAMELEN_MAX+1];
19680Sstevel@tonic-gate picl_nodehdl_t childh;
19690Sstevel@tonic-gate
19700Sstevel@tonic-gate /*
19710Sstevel@tonic-gate * go through the children
19720Sstevel@tonic-gate */
19730Sstevel@tonic-gate err = ptree_get_propval_by_name(nodeh, PICL_PROP_CHILD, &childh,
19740Sstevel@tonic-gate sizeof (picl_nodehdl_t));
19750Sstevel@tonic-gate
19760Sstevel@tonic-gate while (err == PICL_SUCCESS) {
19770Sstevel@tonic-gate err = ptree_get_propval_by_name(childh, PICL_PROP_CLASSNAME,
19780Sstevel@tonic-gate clname, sizeof (clname));
19790Sstevel@tonic-gate
19800Sstevel@tonic-gate if ((err == PICL_SUCCESS) && (strcmp(clname, classname) == 0)) {
19810Sstevel@tonic-gate *foundnodeh = childh;
19820Sstevel@tonic-gate return (PICL_SUCCESS);
19830Sstevel@tonic-gate }
19840Sstevel@tonic-gate
19850Sstevel@tonic-gate err = get_node_by_class(childh, classname, foundnodeh);
19860Sstevel@tonic-gate if (err == PICL_SUCCESS)
19870Sstevel@tonic-gate return (PICL_SUCCESS);
19880Sstevel@tonic-gate
19890Sstevel@tonic-gate err = ptree_get_propval_by_name(childh, PICL_PROP_PEER,
19900Sstevel@tonic-gate &childh, sizeof (picl_nodehdl_t));
19910Sstevel@tonic-gate }
19920Sstevel@tonic-gate
19930Sstevel@tonic-gate return (PICL_NODENOTFOUND);
19940Sstevel@tonic-gate }
19950Sstevel@tonic-gate
19960Sstevel@tonic-gate /*
19970Sstevel@tonic-gate * get system-controller node
19980Sstevel@tonic-gate */
19990Sstevel@tonic-gate static int
get_sys_controller_node(picl_nodehdl_t * nodeh)20000Sstevel@tonic-gate get_sys_controller_node(picl_nodehdl_t *nodeh)
20010Sstevel@tonic-gate {
20020Sstevel@tonic-gate int err;
20030Sstevel@tonic-gate
20040Sstevel@tonic-gate /* get platform node */
20050Sstevel@tonic-gate err = ptree_get_node_by_path(PICL_NODE_ROOT PICL_NODE_PLATFORM, nodeh);
20060Sstevel@tonic-gate if (err != PICL_SUCCESS)
20070Sstevel@tonic-gate return (err);
20080Sstevel@tonic-gate err = get_node_by_class(*nodeh, PICL_CLASS_SERVICE_PROCESSOR, nodeh);
20090Sstevel@tonic-gate return (err);
20100Sstevel@tonic-gate }
20110Sstevel@tonic-gate
20120Sstevel@tonic-gate /*
20130Sstevel@tonic-gate * create pathname string for system-controller device
20140Sstevel@tonic-gate */
20150Sstevel@tonic-gate static char *
create_sys_controller_pathname(picl_nodehdl_t sysconh)20160Sstevel@tonic-gate create_sys_controller_pathname(picl_nodehdl_t sysconh)
20170Sstevel@tonic-gate {
20180Sstevel@tonic-gate char *ptr;
20190Sstevel@tonic-gate char namebuf[PATH_MAX];
20200Sstevel@tonic-gate size_t len;
20210Sstevel@tonic-gate DIR *dirp;
20220Sstevel@tonic-gate struct dirent *dp;
20230Sstevel@tonic-gate struct stat statbuf;
20240Sstevel@tonic-gate
20250Sstevel@tonic-gate /*
20260Sstevel@tonic-gate * prefix devfs-path name with /devices
20270Sstevel@tonic-gate */
20280Sstevel@tonic-gate (void) strlcpy(namebuf, DEV_PREFIX, PATH_MAX);
20290Sstevel@tonic-gate
20300Sstevel@tonic-gate /*
20310Sstevel@tonic-gate * append devfs-path property
20320Sstevel@tonic-gate */
20330Sstevel@tonic-gate len = strlen(namebuf);
20340Sstevel@tonic-gate if (ptree_get_propval_by_name(sysconh, str_devfs_path, namebuf + len,
20350Sstevel@tonic-gate sizeof (namebuf) - len) != PICL_SUCCESS) {
20360Sstevel@tonic-gate return (NULL);
20370Sstevel@tonic-gate }
20380Sstevel@tonic-gate
20390Sstevel@tonic-gate /*
20400Sstevel@tonic-gate * locate final component of name
20410Sstevel@tonic-gate */
20420Sstevel@tonic-gate ptr = strrchr(namebuf, '/');
20430Sstevel@tonic-gate if (ptr == NULL)
20440Sstevel@tonic-gate return (NULL);
20450Sstevel@tonic-gate *ptr = '\0'; /* terminate at end of directory path */
20460Sstevel@tonic-gate len = strlen(ptr + 1); /* length of terminal name */
20470Sstevel@tonic-gate dirp = opendir(namebuf);
20480Sstevel@tonic-gate if (dirp == NULL) {
20490Sstevel@tonic-gate return (NULL);
20500Sstevel@tonic-gate }
20510Sstevel@tonic-gate *ptr++ = '/'; /* restore '/' and advance to final name */
20520Sstevel@tonic-gate
20530Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) {
20540Sstevel@tonic-gate /*
20550Sstevel@tonic-gate * look for a name which starts with the string at *ptr
20560Sstevel@tonic-gate */
20570Sstevel@tonic-gate if (strlen(dp->d_name) < len)
20580Sstevel@tonic-gate continue; /* skip short names */
20590Sstevel@tonic-gate if (strncmp(dp->d_name, ptr, len) == 0) {
20600Sstevel@tonic-gate /*
20610Sstevel@tonic-gate * Got a match, restore full pathname and stat the
20620Sstevel@tonic-gate * entry. Reject if not a char device
20630Sstevel@tonic-gate */
20640Sstevel@tonic-gate (void) strlcpy(ptr, dp->d_name,
20650Sstevel@tonic-gate sizeof (namebuf) - (ptr - namebuf));
20660Sstevel@tonic-gate if (stat(namebuf, &statbuf) < 0)
20670Sstevel@tonic-gate continue; /* reject if can't stat it */
20680Sstevel@tonic-gate if (!S_ISCHR(statbuf.st_mode))
20690Sstevel@tonic-gate continue; /* not a character device */
20700Sstevel@tonic-gate /*
20710Sstevel@tonic-gate * go with this entry
20720Sstevel@tonic-gate */
20730Sstevel@tonic-gate (void) closedir(dirp);
20740Sstevel@tonic-gate return (strdup(namebuf));
20750Sstevel@tonic-gate }
20760Sstevel@tonic-gate }
20770Sstevel@tonic-gate (void) closedir(dirp);
20780Sstevel@tonic-gate return (NULL);
20790Sstevel@tonic-gate }
20800Sstevel@tonic-gate
20810Sstevel@tonic-gate /*
20820Sstevel@tonic-gate * create pathname string for bezel leds device
20830Sstevel@tonic-gate */
20840Sstevel@tonic-gate static char *
create_bezel_leds_pathname(const char * dirpath,const char * devname)20850Sstevel@tonic-gate create_bezel_leds_pathname(const char *dirpath, const char *devname)
20860Sstevel@tonic-gate {
20870Sstevel@tonic-gate char namebuf[PATH_MAX];
20880Sstevel@tonic-gate size_t lendirpath;
20890Sstevel@tonic-gate size_t len;
20900Sstevel@tonic-gate DIR *dirp;
20910Sstevel@tonic-gate struct dirent *dp;
20920Sstevel@tonic-gate struct stat statbuf;
20930Sstevel@tonic-gate
20940Sstevel@tonic-gate /*
20950Sstevel@tonic-gate * start with directory name
20960Sstevel@tonic-gate */
20970Sstevel@tonic-gate (void) strlcpy(namebuf, dirpath, PATH_MAX);
20980Sstevel@tonic-gate
20990Sstevel@tonic-gate /*
21000Sstevel@tonic-gate * append devfs-path property
21010Sstevel@tonic-gate */
21020Sstevel@tonic-gate lendirpath = strlen(namebuf);
21030Sstevel@tonic-gate dirp = opendir(namebuf);
21040Sstevel@tonic-gate if (dirp == NULL) {
21050Sstevel@tonic-gate return (NULL);
21060Sstevel@tonic-gate }
21070Sstevel@tonic-gate
21080Sstevel@tonic-gate len = strlen(devname);
21090Sstevel@tonic-gate
21100Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) {
21110Sstevel@tonic-gate /*
21120Sstevel@tonic-gate * look for a name which starts with the gpio string
21130Sstevel@tonic-gate */
21140Sstevel@tonic-gate if (strlen(dp->d_name) < len)
21150Sstevel@tonic-gate continue; /* skip short names */
21160Sstevel@tonic-gate if (strncmp(dp->d_name, devname, len) == 0) {
21170Sstevel@tonic-gate /*
21180Sstevel@tonic-gate * Got a match, restore full pathname and stat the
21190Sstevel@tonic-gate * entry. Reject if not a char device
21200Sstevel@tonic-gate */
21210Sstevel@tonic-gate (void) strlcpy(namebuf + lendirpath, dp->d_name,
21220Sstevel@tonic-gate sizeof (namebuf) - lendirpath);
21230Sstevel@tonic-gate if (stat(namebuf, &statbuf) < 0)
21240Sstevel@tonic-gate continue; /* reject if can't stat it */
21250Sstevel@tonic-gate if (!S_ISCHR(statbuf.st_mode))
21260Sstevel@tonic-gate continue; /* not a character device */
21270Sstevel@tonic-gate /*
21280Sstevel@tonic-gate * go with this entry
21290Sstevel@tonic-gate */
21300Sstevel@tonic-gate (void) closedir(dirp);
21310Sstevel@tonic-gate return (strdup(namebuf));
21320Sstevel@tonic-gate }
21330Sstevel@tonic-gate }
21340Sstevel@tonic-gate (void) closedir(dirp);
21350Sstevel@tonic-gate return (NULL);
21360Sstevel@tonic-gate }
21370Sstevel@tonic-gate
21380Sstevel@tonic-gate /*
21390Sstevel@tonic-gate * initialise structure associated with nodes requiring OperationalStatus
21400Sstevel@tonic-gate */
21410Sstevel@tonic-gate static void
opst_init(void)21420Sstevel@tonic-gate opst_init(void)
21430Sstevel@tonic-gate {
21440Sstevel@tonic-gate int res;
21450Sstevel@tonic-gate int index = 0;
21460Sstevel@tonic-gate int fd;
21470Sstevel@tonic-gate int entries = 0;
21480Sstevel@tonic-gate int err = 0;
21490Sstevel@tonic-gate boolean_t rmc_flag;
21500Sstevel@tonic-gate boolean_t ps_flag;
21510Sstevel@tonic-gate boolean_t disk_flag;
21520Sstevel@tonic-gate size_t len;
21530Sstevel@tonic-gate envmon_sysinfo_t sysinfo;
21540Sstevel@tonic-gate envmon_hpu_t hpu;
21550Sstevel@tonic-gate
21560Sstevel@tonic-gate if (idprop != NULL) {
21570Sstevel@tonic-gate /*
21580Sstevel@tonic-gate * This must be a restart, clean up earlier allocation
21590Sstevel@tonic-gate */
21600Sstevel@tonic-gate free(idprop);
21610Sstevel@tonic-gate idprop = NULL;
21620Sstevel@tonic-gate }
21630Sstevel@tonic-gate
21640Sstevel@tonic-gate if (sc_device_name == NULL)
21650Sstevel@tonic-gate err = 1;
21660Sstevel@tonic-gate else {
21670Sstevel@tonic-gate fd = open(sc_device_name, O_RDONLY);
21680Sstevel@tonic-gate
21690Sstevel@tonic-gate if (fd < 0) {
21700Sstevel@tonic-gate syslog(LOG_ERR, EM_NO_SC_DEV);
21710Sstevel@tonic-gate err = 1;
21720Sstevel@tonic-gate }
21730Sstevel@tonic-gate }
21740Sstevel@tonic-gate
21750Sstevel@tonic-gate if (err == 0) {
21760Sstevel@tonic-gate res = ioctl(fd, ENVMONIOCSYSINFO, &sysinfo);
21770Sstevel@tonic-gate
21780Sstevel@tonic-gate if (res < 0) {
21790Sstevel@tonic-gate syslog(LOG_ERR, EM_NO_SYSINFO, strerror(errno));
21800Sstevel@tonic-gate (void) close(fd);
21810Sstevel@tonic-gate err = 1;
21820Sstevel@tonic-gate }
21830Sstevel@tonic-gate }
21840Sstevel@tonic-gate
21850Sstevel@tonic-gate if (err == 0) {
21860Sstevel@tonic-gate entries = sysinfo.maxHPU;
21870Sstevel@tonic-gate len = offsetof(idp_lkup_t, idp) + entries * sizeof (id_props_t);
21880Sstevel@tonic-gate idprop = calloc(len, 1);
21890Sstevel@tonic-gate if (idprop == NULL) {
21900Sstevel@tonic-gate (void) close(fd);
21910Sstevel@tonic-gate err = 1;
21920Sstevel@tonic-gate }
21930Sstevel@tonic-gate }
21940Sstevel@tonic-gate
21950Sstevel@tonic-gate if (err == 0) {
21960Sstevel@tonic-gate idprop->maxnum = entries;
21970Sstevel@tonic-gate hpu.id.name[0] = '\0'; /* request for first name */
21980Sstevel@tonic-gate res = ioctl(fd, ENVMONIOCHPU, &hpu);
21990Sstevel@tonic-gate
22000Sstevel@tonic-gate /*
22010Sstevel@tonic-gate * The HPU node for the RMC is a special case. Its handle is
22020Sstevel@tonic-gate * generated by the rmclomv driver. Rather than building
22030Sstevel@tonic-gate * knowledge of its frutree hierarchic name into the driver, we
22040Sstevel@tonic-gate * put that knowledge here.
22050Sstevel@tonic-gate */
22060Sstevel@tonic-gate while ((res == 0) && (index < entries) &&
22070Sstevel@tonic-gate (hpu.next_id.name[0] != '\0')) {
22080Sstevel@tonic-gate hpu.id = hpu.next_id;
22090Sstevel@tonic-gate res = ioctl(fd, ENVMONIOCHPU, &hpu);
22100Sstevel@tonic-gate if ((res == 0) &&
22110Sstevel@tonic-gate ((hpu.sensor_status & ENVMON_NOT_PRESENT) == 0)) {
22120Sstevel@tonic-gate add_op_status(&hpu, &index);
22130Sstevel@tonic-gate }
22140Sstevel@tonic-gate }
22150Sstevel@tonic-gate
22160Sstevel@tonic-gate idprop->num = index;
22170Sstevel@tonic-gate (void) close(fd);
22180Sstevel@tonic-gate }
22190Sstevel@tonic-gate }
22200Sstevel@tonic-gate
22210Sstevel@tonic-gate static void
disk_leds_init(void)22220Sstevel@tonic-gate disk_leds_init(void)
22230Sstevel@tonic-gate {
22240Sstevel@tonic-gate int err = 0, i;
22250Sstevel@tonic-gate
22260Sstevel@tonic-gate if (!g_mutex_init) {
22270Sstevel@tonic-gate if ((pthread_cond_init(&g_cv, NULL) == 0) &&
22280Sstevel@tonic-gate (pthread_cond_init(&g_cv_ack, NULL) == 0) &&
22290Sstevel@tonic-gate (pthread_mutex_init(&g_mutex, NULL) == 0)) {
22300Sstevel@tonic-gate g_mutex_init = B_TRUE;
22310Sstevel@tonic-gate } else {
22320Sstevel@tonic-gate return;
22330Sstevel@tonic-gate }
22340Sstevel@tonic-gate }
22350Sstevel@tonic-gate
22360Sstevel@tonic-gate /*
22370Sstevel@tonic-gate * Initialise to -1 so the led thread will set correctly.
22380Sstevel@tonic-gate * Do this before creating the disk_leds thread,
22390Sstevel@tonic-gate * so there's no race.
22400Sstevel@tonic-gate */
22410Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++)
22420Sstevel@tonic-gate disk_ready[i] = -1;
22430Sstevel@tonic-gate
22440Sstevel@tonic-gate if (ledsthr_created) {
22450Sstevel@tonic-gate /*
22460Sstevel@tonic-gate * this is a restart, wake up sleeping threads
22470Sstevel@tonic-gate */
22480Sstevel@tonic-gate err = pthread_mutex_lock(&g_mutex);
22490Sstevel@tonic-gate if (err != 0) {
22500Sstevel@tonic-gate syslog(LOG_ERR, EM_MUTEX_FAIL, strerror(errno));
22510Sstevel@tonic-gate return;
22520Sstevel@tonic-gate }
22530Sstevel@tonic-gate g_finish_now = B_FALSE;
22540Sstevel@tonic-gate (void) pthread_cond_broadcast(&g_cv);
22550Sstevel@tonic-gate (void) pthread_mutex_unlock(&g_mutex);
22560Sstevel@tonic-gate } else {
22570Sstevel@tonic-gate if ((pthread_attr_init(&ledsthr_attr) != 0) ||
22580Sstevel@tonic-gate (pthread_attr_setscope(&ledsthr_attr,
22590Sstevel@tonic-gate PTHREAD_SCOPE_SYSTEM) != 0))
22600Sstevel@tonic-gate return;
22610Sstevel@tonic-gate if ((err = pthread_create(&ledsthr_tid, &ledsthr_attr,
22620Sstevel@tonic-gate disk_leds_thread, NULL)) != 0) {
22630Sstevel@tonic-gate syslog(LOG_ERR, EM_THREAD_CREATE_FAILED,
22640Sstevel@tonic-gate strerror(errno));
22650Sstevel@tonic-gate return;
22660Sstevel@tonic-gate }
22670Sstevel@tonic-gate ledsthr_created = B_TRUE;
22680Sstevel@tonic-gate }
22690Sstevel@tonic-gate }
22700Sstevel@tonic-gate
22710Sstevel@tonic-gate static void
disk_leds_fini(void)22720Sstevel@tonic-gate disk_leds_fini(void)
22730Sstevel@tonic-gate {
22740Sstevel@tonic-gate int err, i;
22750Sstevel@tonic-gate
22760Sstevel@tonic-gate /*
22770Sstevel@tonic-gate * turn the leds off as we'll no longer be monitoring them
22780Sstevel@tonic-gate */
22790Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++)
22800Sstevel@tonic-gate (void) set_led(disk_name[i], REMOK_LED, PICL_PROPVAL_OFF);
22810Sstevel@tonic-gate
22820Sstevel@tonic-gate /*
22830Sstevel@tonic-gate * disk_leds_thread() never started or an error occured so
22840Sstevel@tonic-gate * that it's not running
22850Sstevel@tonic-gate */
22860Sstevel@tonic-gate if (!disk_leds_thread_running)
22870Sstevel@tonic-gate return;
22880Sstevel@tonic-gate
22890Sstevel@tonic-gate /*
22900Sstevel@tonic-gate * tell led thread to pause
22910Sstevel@tonic-gate */
22920Sstevel@tonic-gate if (!ledsthr_created)
22930Sstevel@tonic-gate return;
22940Sstevel@tonic-gate err = pthread_mutex_lock(&g_mutex);
22950Sstevel@tonic-gate if (err != 0) {
22960Sstevel@tonic-gate syslog(LOG_ERR, EM_MUTEX_FAIL, strerror(errno));
22970Sstevel@tonic-gate return;
22980Sstevel@tonic-gate }
22990Sstevel@tonic-gate g_finish_now = B_TRUE;
23000Sstevel@tonic-gate disk_leds_thread_ack = B_FALSE;
23010Sstevel@tonic-gate (void) pthread_cond_broadcast(&g_cv);
23020Sstevel@tonic-gate
23030Sstevel@tonic-gate /*
23040Sstevel@tonic-gate * and wait for them to acknowledge
23050Sstevel@tonic-gate */
23060Sstevel@tonic-gate while (!disk_leds_thread_ack) {
23070Sstevel@tonic-gate (void) pthread_cond_wait(&g_cv_ack, &g_mutex);
23080Sstevel@tonic-gate }
23090Sstevel@tonic-gate (void) pthread_mutex_unlock(&g_mutex);
23100Sstevel@tonic-gate }
23110Sstevel@tonic-gate
23120Sstevel@tonic-gate static void
update_disk_node(char * fruname,char * devpath)23130Sstevel@tonic-gate update_disk_node(char *fruname, char *devpath)
23140Sstevel@tonic-gate {
23150Sstevel@tonic-gate picl_nodehdl_t slotndh;
23160Sstevel@tonic-gate picl_nodehdl_t diskndh;
23170Sstevel@tonic-gate picl_nodehdl_t devhdl;
23180Sstevel@tonic-gate picl_prophdl_t tblhdl;
23190Sstevel@tonic-gate picl_prophdl_t tblhdl2;
23200Sstevel@tonic-gate picl_prophdl_t tblproph;
23210Sstevel@tonic-gate int err;
23220Sstevel@tonic-gate char path[MAXPATHLEN];
23230Sstevel@tonic-gate
23241103Sjbeloro switch (sys_platform) {
23251103Sjbeloro case PLAT_CHALUPA:
23261103Sjbeloro case PLAT_CHALUPA19:
23271103Sjbeloro sprintf_buf2(path, CHASSIS_LOC_PATH, fruname);
23281103Sjbeloro break;
23291103Sjbeloro case PLAT_SEATTLE1U:
23301103Sjbeloro sprintf_buf2(path, SEATTLE1U_HDDBP_PATH, fruname);
23311103Sjbeloro break;
23321103Sjbeloro case PLAT_SEATTLE2U:
23331103Sjbeloro sprintf_buf2(path, SEATTLE2U_HDDBP_PATH, fruname);
23341103Sjbeloro break;
23351103Sjbeloro case PLAT_BOSTON:
23361103Sjbeloro sprintf_buf2(path, BOSTON_HDDBP_PATH, fruname);
23371103Sjbeloro break;
23381103Sjbeloro default:
23391103Sjbeloro sprintf_buf2(path, CHASSIS_LOC_PATH, fruname);
23401103Sjbeloro break;
23411103Sjbeloro }
23421103Sjbeloro
23430Sstevel@tonic-gate if (ptree_get_node_by_path(path, &slotndh) != PICL_SUCCESS) {
23440Sstevel@tonic-gate return;
23450Sstevel@tonic-gate }
23460Sstevel@tonic-gate diskndh = find_child_by_name(slotndh, DISK_FRU_NAME);
23470Sstevel@tonic-gate if (diskndh == NULL) {
23480Sstevel@tonic-gate return;
23490Sstevel@tonic-gate }
23500Sstevel@tonic-gate err = ptree_get_node_by_path(devpath, &devhdl);
23510Sstevel@tonic-gate if (err == PICL_SUCCESS) {
23520Sstevel@tonic-gate err = ptree_get_propval_by_name(diskndh,
23530Sstevel@tonic-gate PICL_PROP_DEVICES, &tblhdl, sizeof (tblhdl));
23540Sstevel@tonic-gate if (err != PICL_SUCCESS)
23550Sstevel@tonic-gate return;
23560Sstevel@tonic-gate err = ptree_get_next_by_col(tblhdl, &tblhdl2);
23570Sstevel@tonic-gate if (err != PICL_SUCCESS) {
23580Sstevel@tonic-gate err = create_table_entry(tblhdl, devhdl,
23590Sstevel@tonic-gate PICL_CLASS_BLOCK);
23600Sstevel@tonic-gate if (err != PICL_SUCCESS)
23610Sstevel@tonic-gate return;
23620Sstevel@tonic-gate err = add_prop_ref(devhdl, diskndh,
23630Sstevel@tonic-gate PICL_REFPROP_FRU_PARENT);
23640Sstevel@tonic-gate if (err != PICL_SUCCESS)
23650Sstevel@tonic-gate return;
23660Sstevel@tonic-gate }
23670Sstevel@tonic-gate } else {
23680Sstevel@tonic-gate /*
23690Sstevel@tonic-gate * no mechanism for deleting row - so delete
23700Sstevel@tonic-gate * whole table and start again
23710Sstevel@tonic-gate */
23720Sstevel@tonic-gate err = ptree_get_prop_by_name(diskndh, PICL_PROP_DEVICES,
23730Sstevel@tonic-gate &tblproph);
23740Sstevel@tonic-gate if (err != PICL_SUCCESS)
23750Sstevel@tonic-gate return;
23760Sstevel@tonic-gate err = ptree_delete_prop(tblproph);
23770Sstevel@tonic-gate if (err != PICL_SUCCESS)
23780Sstevel@tonic-gate return;
23790Sstevel@tonic-gate (void) ptree_destroy_prop(tblproph);
23800Sstevel@tonic-gate err = create_table(diskndh, &tblhdl, PICL_PROP_DEVICES);
23810Sstevel@tonic-gate if (err != PICL_SUCCESS)
23820Sstevel@tonic-gate return;
23830Sstevel@tonic-gate }
23840Sstevel@tonic-gate }
23850Sstevel@tonic-gate
23861103Sjbeloro /*
23871103Sjbeloro * We will light the OK2REMOVE LED for disks configured
23881103Sjbeloro * into a raid if (and only if) the driver reports
23891103Sjbeloro * that the disk has failed.
23901103Sjbeloro */
23910Sstevel@tonic-gate static int
raid_ok2rem_policy(raid_config_t config,int target)23921103Sjbeloro raid_ok2rem_policy(raid_config_t config, int target)
23930Sstevel@tonic-gate {
23941103Sjbeloro int i;
23951103Sjbeloro
23961103Sjbeloro for (i = 0; i < config.ndisks; i++) {
23971103Sjbeloro int d = config.disk[i];
23981103Sjbeloro int dstatus = config.diskstatus[i];
23991103Sjbeloro
24001103Sjbeloro if (d == target) {
24011103Sjbeloro switch (dstatus) {
24021103Sjbeloro case RAID_DISKSTATUS_MISSING:
24031103Sjbeloro /* If LED is on, turn it off */
24041103Sjbeloro if (disk_ready[d] == B_FALSE) {
24051103Sjbeloro if (set_led(disk_name[d], REMOK_LED,
24061103Sjbeloro PICL_PROPVAL_OFF) == PICL_SUCCESS) {
24071103Sjbeloro disk_ready[d] = B_TRUE;
24081103Sjbeloro }
24091103Sjbeloro }
24101103Sjbeloro break;
24111103Sjbeloro case RAID_DISKSTATUS_GOOD:
24121103Sjbeloro if (disk_ready[d] != B_TRUE) {
24131103Sjbeloro if (set_led(disk_name[d], REMOK_LED,
24141103Sjbeloro PICL_PROPVAL_OFF) == PICL_SUCCESS) {
24151103Sjbeloro disk_ready[d] = B_TRUE;
24161103Sjbeloro }
24171103Sjbeloro }
24181103Sjbeloro break;
24191103Sjbeloro case RAID_DISKSTATUS_FAILED:
24201103Sjbeloro if (disk_ready[d] != B_FALSE) {
24211103Sjbeloro if (set_led(disk_name[d], REMOK_LED,
2422*12601SJustin.Frank@Sun.COM PICL_PROPVAL_ON) == PICL_SUCCESS) {
24231103Sjbeloro disk_ready[d] = B_FALSE;
24241103Sjbeloro }
24251103Sjbeloro }
24261103Sjbeloro break;
24271103Sjbeloro default:
24281103Sjbeloro break;
24291103Sjbeloro }
24301103Sjbeloro return (1);
24311103Sjbeloro }
24321103Sjbeloro }
24331103Sjbeloro return (0);
24341103Sjbeloro }
24351103Sjbeloro
24361103Sjbeloro static int
check_raid(int target)24371103Sjbeloro check_raid(int target)
24381103Sjbeloro {
24391103Sjbeloro raid_config_t config;
24400Sstevel@tonic-gate int fd;
24411103Sjbeloro int numvols;
24421103Sjbeloro int i, j;
24430Sstevel@tonic-gate
24440Sstevel@tonic-gate switch (sys_platform) {
24450Sstevel@tonic-gate case PLAT_CHALUPA:
24460Sstevel@tonic-gate case PLAT_CHALUPA19:
24470Sstevel@tonic-gate fd = open(V440_DISK_DEVCTL, O_RDONLY);
24480Sstevel@tonic-gate break;
24491103Sjbeloro case PLAT_SEATTLE1U:
24501103Sjbeloro case PLAT_SEATTLE2U:
24511103Sjbeloro fd = open(SEATTLE_DISK_DEVCTL, O_RDONLY);
24521103Sjbeloro break;
24531103Sjbeloro case PLAT_BOSTON:
24541296Sfw157321 if (boston_1068e_flag) {
2455*12601SJustin.Frank@Sun.COM fd = open(BOSTON_DISK_DEVCTL_1068E, O_RDONLY);
24561296Sfw157321 } else {
2457*12601SJustin.Frank@Sun.COM fd = open(BOSTON_DISK_DEVCTL_1068X, O_RDONLY);
24581296Sfw157321 }
24591103Sjbeloro break;
24600Sstevel@tonic-gate default:
24610Sstevel@tonic-gate fd = -1;
24620Sstevel@tonic-gate break;
24630Sstevel@tonic-gate }
24640Sstevel@tonic-gate
24650Sstevel@tonic-gate if (fd == -1) {
24661103Sjbeloro return (0);
24671103Sjbeloro }
24681103Sjbeloro
24691103Sjbeloro if (ioctl(fd, RAID_NUMVOLUMES, &numvols)) {
24701103Sjbeloro (void) close(fd);
24711103Sjbeloro return (0);
24720Sstevel@tonic-gate }
24730Sstevel@tonic-gate
24741103Sjbeloro for (i = 0; i < numvols; i++) {
24751103Sjbeloro config.unitid = i;
24761103Sjbeloro if (ioctl(fd, RAID_GETCONFIG, &config)) {
24771103Sjbeloro (void) close(fd);
24781103Sjbeloro return (0);
24791103Sjbeloro }
24801103Sjbeloro if (raid_ok2rem_policy(config, target)) {
24811103Sjbeloro (void) close(fd);
24821103Sjbeloro return (1);
24831103Sjbeloro }
24840Sstevel@tonic-gate }
24850Sstevel@tonic-gate
24860Sstevel@tonic-gate (void) close(fd);
24870Sstevel@tonic-gate return (0);
24880Sstevel@tonic-gate }
24890Sstevel@tonic-gate
24900Sstevel@tonic-gate /*ARGSUSED*/
24910Sstevel@tonic-gate static void *
disk_leds_thread(void * args)24920Sstevel@tonic-gate disk_leds_thread(void *args)
24930Sstevel@tonic-gate {
24940Sstevel@tonic-gate int c;
24950Sstevel@tonic-gate int i;
24960Sstevel@tonic-gate char **disk_dev;
24971296Sfw157321 int fd;
24980Sstevel@tonic-gate
24990Sstevel@tonic-gate devctl_hdl_t dhdl;
25000Sstevel@tonic-gate
25010Sstevel@tonic-gate int n_disks = 0,
2502*12601SJustin.Frank@Sun.COM do_raid = 0,
2503*12601SJustin.Frank@Sun.COM err = 0;
25040Sstevel@tonic-gate uint_t statep = 0;
25050Sstevel@tonic-gate
25060Sstevel@tonic-gate static char *mpxu_devs[] = {
25070Sstevel@tonic-gate "/pci@1c,600000/scsi@2/sd@0,0",
25080Sstevel@tonic-gate "/pci@1c,600000/scsi@2/sd@1,0",
25090Sstevel@tonic-gate "/pci@1c,600000/scsi@2/sd@2,0",
25100Sstevel@tonic-gate "/pci@1c,600000/scsi@2/sd@3,0"
25110Sstevel@tonic-gate };
25120Sstevel@tonic-gate
25130Sstevel@tonic-gate static char *ents_devs[] = {
25140Sstevel@tonic-gate "/pci@1d,700000/scsi@4/sd@0,0",
25150Sstevel@tonic-gate "/pci@1d,700000/scsi@4/sd@1,0",
25160Sstevel@tonic-gate "/pci@1d,700000/scsi@4/sd@2,0",
25170Sstevel@tonic-gate "/pci@1d,700000/scsi@4/sd@3,0",
25180Sstevel@tonic-gate "/pci@1d,700000/scsi@4/sd@8,0",
25190Sstevel@tonic-gate "/pci@1d,700000/scsi@4/sd@9,0",
25200Sstevel@tonic-gate "/pci@1d,700000/scsi@4/sd@a,0",
25210Sstevel@tonic-gate "/pci@1d,700000/scsi@4/sd@b,0"
25220Sstevel@tonic-gate };
25230Sstevel@tonic-gate
25240Sstevel@tonic-gate static char *v440_devs[] = {
25250Sstevel@tonic-gate "/pci@1f,700000/scsi@2/sd@0,0",
25260Sstevel@tonic-gate "/pci@1f,700000/scsi@2/sd@1,0",
25270Sstevel@tonic-gate "/pci@1f,700000/scsi@2/sd@2,0",
25280Sstevel@tonic-gate "/pci@1f,700000/scsi@2/sd@3,0"
25290Sstevel@tonic-gate };
25300Sstevel@tonic-gate
25310Sstevel@tonic-gate static char *n210_devs[] = {
25320Sstevel@tonic-gate "/pci@1c,600000/LSILogic,sas@1/sd@0,0",
25330Sstevel@tonic-gate "/pci@1c,600000/LSILogic,sas@1/sd@1,0"
25340Sstevel@tonic-gate };
25350Sstevel@tonic-gate
25361103Sjbeloro static char *seattle_devs[] = {
25371103Sjbeloro "/pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1/sd@0,0",
25381103Sjbeloro "/pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1/sd@1,0",
25391103Sjbeloro "/pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1/sd@2,0",
25401103Sjbeloro "/pci@1e,600000/pci@0/pci@a/pci@0/pci@8/scsi@1/sd@3,0"
25411103Sjbeloro };
25421103Sjbeloro
25431296Sfw157321 static char *boston_devs_1068e[] = {
25441296Sfw157321 "/pci@1e,600000/pci@0/pci@2/scsi@0/sd@0,0",
25451296Sfw157321 "/pci@1e,600000/pci@0/pci@2/scsi@0/sd@1,0",
25461296Sfw157321 "/pci@1e,600000/pci@0/pci@2/scsi@0/sd@2,0",
25471296Sfw157321 "/pci@1e,600000/pci@0/pci@2/scsi@0/sd@3,0",
25481296Sfw157321 "/pci@1e,600000/pci@0/pci@2/scsi@0/sd@4,0",
25491296Sfw157321 "/pci@1e,600000/pci@0/pci@2/scsi@0/sd@5,0",
25501296Sfw157321 "/pci@1e,600000/pci@0/pci@2/scsi@0/sd@6,0",
25511296Sfw157321 "/pci@1e,600000/pci@0/pci@2/scsi@0/sd@7,0"
25521296Sfw157321 };
25531296Sfw157321 static char *boston_devs_1068x[] = {
25541103Sjbeloro "/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1/sd@0,0",
25551103Sjbeloro "/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1/sd@1,0",
25561103Sjbeloro "/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1/sd@2,0",
25571103Sjbeloro "/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1/sd@3,0",
25581103Sjbeloro "/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1/sd@4,0",
25591103Sjbeloro "/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1/sd@5,0",
25601103Sjbeloro "/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1/sd@6,0",
25611103Sjbeloro "/pci@1f,700000/pci@0/pci@2/pci@0/pci@8/LSILogic,sas@1/sd@7,0"
25621103Sjbeloro };
25631103Sjbeloro
25640Sstevel@tonic-gate char *ddev[N_DISKS]; /* "/devices" */
25650Sstevel@tonic-gate char *pdev[N_DISKS]; /* "/platform" */
25660Sstevel@tonic-gate
25670Sstevel@tonic-gate switch (sys_platform) {
25680Sstevel@tonic-gate
25690Sstevel@tonic-gate case PLAT_ENTS:
25700Sstevel@tonic-gate disk_dev = ents_devs;
25710Sstevel@tonic-gate n_disks = N_ENTS_DISKS;
25720Sstevel@tonic-gate break;
25730Sstevel@tonic-gate
25740Sstevel@tonic-gate case PLAT_CHALUPA:
25750Sstevel@tonic-gate case PLAT_CHALUPA19:
25760Sstevel@tonic-gate do_raid = 1;
25770Sstevel@tonic-gate disk_dev = v440_devs;
25780Sstevel@tonic-gate n_disks = N_CHALUPA_DISKS;
25790Sstevel@tonic-gate break;
25800Sstevel@tonic-gate
25810Sstevel@tonic-gate case PLAT_SALSA19:
25820Sstevel@tonic-gate disk_dev = n210_devs;
25830Sstevel@tonic-gate n_disks = N_EN19_DISKS;
25840Sstevel@tonic-gate break;
25850Sstevel@tonic-gate
25861103Sjbeloro case PLAT_SEATTLE1U:
25871103Sjbeloro case PLAT_SEATTLE2U:
25881103Sjbeloro do_raid = 1;
25891103Sjbeloro disk_dev = seattle_devs;
25901103Sjbeloro n_disks = (sys_platform == PLAT_SEATTLE1U) ?
2591*12601SJustin.Frank@Sun.COM N_SEATTLE1U_DISKS : N_SEATTLE2U_DISKS;
25921103Sjbeloro break;
25931103Sjbeloro
25941103Sjbeloro case PLAT_BOSTON:
25951296Sfw157321 /*
25961296Sfw157321 * If we can open the devctl path for the built-in 1068E
25971296Sfw157321 * controller then assume we're a 1068E-equipped Boston
25981296Sfw157321 * and make all the paths appropriate for that hardware.
25991296Sfw157321 * Otherwise assume we are a 1068X-equipped Boston and
26001296Sfw157321 * make all of the paths appropriate for a 1068X PCI-X
26011296Sfw157321 * controller in PCI slot 4.
26021296Sfw157321 *
26031296Sfw157321 * The flag is also used in the check_raid() function.
26041296Sfw157321 */
26051296Sfw157321 if ((fd = open(BOSTON_DISK_DEVCTL_1068E, O_RDONLY)) != -1) {
26061296Sfw157321 boston_1068e_flag = 1;
26071296Sfw157321 disk_dev = boston_devs_1068e;
26081296Sfw157321 } else {
26091296Sfw157321 boston_1068e_flag = 0;
26101296Sfw157321 disk_dev = boston_devs_1068x;
26111296Sfw157321 }
26121296Sfw157321 (void) close(fd);
26131103Sjbeloro do_raid = 1;
26141103Sjbeloro n_disks = N_BOSTON_DISKS;
26151103Sjbeloro break;
26161103Sjbeloro
26170Sstevel@tonic-gate default: /* PLAT_ENXS/PLAT_EN19 */
26180Sstevel@tonic-gate disk_dev = mpxu_devs;
26190Sstevel@tonic-gate n_disks = (sys_platform == PLAT_EN19) ?
2620*12601SJustin.Frank@Sun.COM N_EN19_DISKS : N_MPXU_DISKS;
26210Sstevel@tonic-gate }
26220Sstevel@tonic-gate
26230Sstevel@tonic-gate /*
26240Sstevel@tonic-gate * make up disk names
26250Sstevel@tonic-gate */
26260Sstevel@tonic-gate
26270Sstevel@tonic-gate for (i = 0; i < n_disks; i++) {
26280Sstevel@tonic-gate char buffer[MAXPATHLEN];
26290Sstevel@tonic-gate sprintf(buffer, "/devices%s", disk_dev[i]);
26300Sstevel@tonic-gate ddev[i] = strdup(buffer);
26310Sstevel@tonic-gate sprintf(buffer, "/platform%s", disk_dev[i]);
26320Sstevel@tonic-gate pdev[i] = strdup(buffer);
26330Sstevel@tonic-gate }
26340Sstevel@tonic-gate
26350Sstevel@tonic-gate disk_leds_thread_running = B_TRUE;
26360Sstevel@tonic-gate
26370Sstevel@tonic-gate for (;;) {
26380Sstevel@tonic-gate for (i = 0; i < n_disks; i++) {
26390Sstevel@tonic-gate /*
26401103Sjbeloro * If it's one of the RAID disks, we have already
26410Sstevel@tonic-gate * applied the ok2remove policy.
26420Sstevel@tonic-gate */
26431103Sjbeloro if (do_raid && check_raid(i)) {
26440Sstevel@tonic-gate continue;
26451103Sjbeloro }
26460Sstevel@tonic-gate
26470Sstevel@tonic-gate dhdl = devctl_device_acquire(ddev[i], 0);
26480Sstevel@tonic-gate devctl_device_getstate(dhdl, &statep);
26490Sstevel@tonic-gate devctl_release(dhdl);
26500Sstevel@tonic-gate
26510Sstevel@tonic-gate if (statep & DEVICE_OFFLINE) {
26520Sstevel@tonic-gate if (disk_ready[i] != B_FALSE) {
26530Sstevel@tonic-gate update_disk_node(disk_name[i], pdev[i]);
26540Sstevel@tonic-gate if (set_led(disk_name[i], REMOK_LED,
26550Sstevel@tonic-gate PICL_PROPVAL_ON) == PICL_SUCCESS)
26560Sstevel@tonic-gate disk_ready[i] = B_FALSE;
26570Sstevel@tonic-gate }
26580Sstevel@tonic-gate } else if (statep & DEVICE_ONLINE) {
26590Sstevel@tonic-gate if (disk_ready[i] != B_TRUE) {
26600Sstevel@tonic-gate update_disk_node(disk_name[i], pdev[i]);
26610Sstevel@tonic-gate if (set_led(disk_name[i], REMOK_LED,
26620Sstevel@tonic-gate PICL_PROPVAL_OFF) == PICL_SUCCESS)
26630Sstevel@tonic-gate disk_ready[i] = B_TRUE;
26640Sstevel@tonic-gate }
26650Sstevel@tonic-gate }
26660Sstevel@tonic-gate }
26670Sstevel@tonic-gate
26680Sstevel@tonic-gate /*
26690Sstevel@tonic-gate * wait a bit until we check again
26700Sstevel@tonic-gate */
26710Sstevel@tonic-gate
26720Sstevel@tonic-gate (void) poll(NULL, 0, DISK_POLL_TIME);
26730Sstevel@tonic-gate
26740Sstevel@tonic-gate /*
26750Sstevel@tonic-gate * are we to stop?
26760Sstevel@tonic-gate */
26770Sstevel@tonic-gate
26780Sstevel@tonic-gate (void) pthread_mutex_lock(&g_mutex);
26790Sstevel@tonic-gate
26800Sstevel@tonic-gate while (g_finish_now) {
26810Sstevel@tonic-gate /*
26820Sstevel@tonic-gate * notify _fini routine that we've paused
26830Sstevel@tonic-gate */
26840Sstevel@tonic-gate disk_leds_thread_ack = B_TRUE;
26850Sstevel@tonic-gate (void) pthread_cond_signal(&g_cv_ack);
26860Sstevel@tonic-gate
26870Sstevel@tonic-gate /*
26880Sstevel@tonic-gate * and go to sleep in case we get restarted
26890Sstevel@tonic-gate */
26900Sstevel@tonic-gate (void) pthread_cond_wait(&g_cv, &g_mutex);
26910Sstevel@tonic-gate }
26920Sstevel@tonic-gate (void) pthread_mutex_unlock(&g_mutex);
26930Sstevel@tonic-gate }
26940Sstevel@tonic-gate
26950Sstevel@tonic-gate return ((void *)err);
26960Sstevel@tonic-gate }
26970Sstevel@tonic-gate
26980Sstevel@tonic-gate /*
26990Sstevel@tonic-gate * Given the powersupply name, convert to addr
27000Sstevel@tonic-gate */
27010Sstevel@tonic-gate static int
ps_name_to_addr(char * name)27020Sstevel@tonic-gate ps_name_to_addr(char *name)
27030Sstevel@tonic-gate {
27040Sstevel@tonic-gate int ps_addr = 0;
27050Sstevel@tonic-gate if ((strcmp(name, PS0_NAME) == 0) ||
2706*12601SJustin.Frank@Sun.COM (strcmp(name, PSU0_NAME) == 0)) {
27071103Sjbeloro switch (sys_platform) {
27081103Sjbeloro case PLAT_SEATTLE1U:
27091103Sjbeloro case PLAT_SEATTLE2U:
27101103Sjbeloro ps_addr = SEATTLE_PS0_ADDR;
27111103Sjbeloro break;
27121103Sjbeloro case PLAT_BOSTON:
27131103Sjbeloro ps_addr = BOSTON_PS0_ADDR;
27141103Sjbeloro break;
27151103Sjbeloro default:
27161103Sjbeloro ps_addr = PS0_ADDR;
27171103Sjbeloro break;
27181103Sjbeloro }
27191103Sjbeloro } else if ((strcmp(name, PS1_NAME) == 0) ||
2720*12601SJustin.Frank@Sun.COM (strcmp(name, PSU1_NAME) == 0)) {
27211103Sjbeloro switch (sys_platform) {
27221103Sjbeloro case PLAT_SEATTLE1U:
27231103Sjbeloro case PLAT_SEATTLE2U:
27241103Sjbeloro ps_addr = SEATTLE_PS1_ADDR;
27251103Sjbeloro break;
27261103Sjbeloro case PLAT_BOSTON:
27271103Sjbeloro ps_addr = BOSTON_PS1_ADDR;
27281103Sjbeloro break;
27291103Sjbeloro default:
27301103Sjbeloro ps_addr = PS1_ADDR;
27311103Sjbeloro break;
27321103Sjbeloro }
27331103Sjbeloro } else if ((strcmp(name, PS2_NAME) == 0) ||
2734*12601SJustin.Frank@Sun.COM (strcmp(name, PSU2_NAME) == 0)) {
27351103Sjbeloro switch (sys_platform) {
27361103Sjbeloro case PLAT_BOSTON:
27371103Sjbeloro ps_addr = BOSTON_PS2_ADDR;
27381103Sjbeloro break;
27391103Sjbeloro default:
27401103Sjbeloro ps_addr = PS2_ADDR;
27411103Sjbeloro break;
27421103Sjbeloro }
27431103Sjbeloro } else if ((strcmp(name, PS3_NAME) == 0) ||
2744*12601SJustin.Frank@Sun.COM (strcmp(name, PSU3_NAME) == 0)) {
27451103Sjbeloro switch (sys_platform) {
27461103Sjbeloro case PLAT_BOSTON:
27471103Sjbeloro ps_addr = BOSTON_PS3_ADDR;
27481103Sjbeloro break;
27491103Sjbeloro default:
27501103Sjbeloro ps_addr = PS3_ADDR;
27511103Sjbeloro break;
27521103Sjbeloro }
27531103Sjbeloro }
27540Sstevel@tonic-gate
27550Sstevel@tonic-gate return (ps_addr);
27560Sstevel@tonic-gate }
27570Sstevel@tonic-gate
27580Sstevel@tonic-gate /*
27590Sstevel@tonic-gate * Given powersupply name, convert to unit addr
27600Sstevel@tonic-gate */
27610Sstevel@tonic-gate static char *
ps_name_to_unitaddr(char * name)27620Sstevel@tonic-gate ps_name_to_unitaddr(char *name)
27630Sstevel@tonic-gate {
27640Sstevel@tonic-gate char *unitaddr;
27650Sstevel@tonic-gate
27661103Sjbeloro if (strcmp(name, PS0_NAME) == 0) {
27671103Sjbeloro switch (sys_platform) {
27681103Sjbeloro case PLAT_SEATTLE1U:
27691103Sjbeloro case PLAT_SEATTLE2U:
27701103Sjbeloro unitaddr = SEATTLE_PS0_UNITADDR;
27711103Sjbeloro break;
27721103Sjbeloro case PLAT_BOSTON:
27731103Sjbeloro unitaddr = BOSTON_PS0_UNITADDR;
27741103Sjbeloro break;
27751103Sjbeloro default:
27761103Sjbeloro unitaddr = PS0_UNITADDR;
27771103Sjbeloro break;
27781103Sjbeloro }
27791103Sjbeloro } else if (strcmp(name, PS1_NAME) == 0) {
27801103Sjbeloro switch (sys_platform) {
27811103Sjbeloro case PLAT_SEATTLE1U:
27821103Sjbeloro case PLAT_SEATTLE2U:
27831103Sjbeloro unitaddr = SEATTLE_PS1_UNITADDR;
27841103Sjbeloro break;
27851103Sjbeloro case PLAT_BOSTON:
27861103Sjbeloro unitaddr = BOSTON_PS1_UNITADDR;
27871103Sjbeloro break;
27881103Sjbeloro default:
27891103Sjbeloro unitaddr = PS1_UNITADDR;
27901103Sjbeloro break;
27911103Sjbeloro }
27921103Sjbeloro } else if (strcmp(name, PS2_NAME) == 0) {
27931103Sjbeloro switch (sys_platform) {
27941103Sjbeloro case PLAT_BOSTON:
27951103Sjbeloro unitaddr = BOSTON_PS2_UNITADDR;
27961103Sjbeloro break;
27971103Sjbeloro default:
27981103Sjbeloro unitaddr = PS2_UNITADDR;
27991103Sjbeloro break;
28001103Sjbeloro }
28011103Sjbeloro } else if (strcmp(name, PS3_NAME) == 0) {
28021103Sjbeloro switch (sys_platform) {
28031103Sjbeloro case PLAT_BOSTON:
28041103Sjbeloro unitaddr = BOSTON_PS3_UNITADDR;
28051103Sjbeloro break;
28061103Sjbeloro default:
28071103Sjbeloro unitaddr = PS3_UNITADDR;
28081103Sjbeloro break;
28091103Sjbeloro }
28101103Sjbeloro }
28110Sstevel@tonic-gate else
28120Sstevel@tonic-gate unitaddr = NULL;
28130Sstevel@tonic-gate
28140Sstevel@tonic-gate return (unitaddr);
28150Sstevel@tonic-gate }
28160Sstevel@tonic-gate
28170Sstevel@tonic-gate /*
28180Sstevel@tonic-gate * converts apid to real FRU name in PICL tree. The
28190Sstevel@tonic-gate * name of powersupply devices on chalupa19 are
28200Sstevel@tonic-gate * PSU instead of PS
28210Sstevel@tonic-gate */
28220Sstevel@tonic-gate static char *
ps_apid_to_nodename(char * apid)28230Sstevel@tonic-gate ps_apid_to_nodename(char *apid)
28240Sstevel@tonic-gate {
28250Sstevel@tonic-gate char *nodename;
28260Sstevel@tonic-gate
28270Sstevel@tonic-gate if (sys_platform != PLAT_CHALUPA19)
28280Sstevel@tonic-gate return (apid);
28290Sstevel@tonic-gate
28300Sstevel@tonic-gate if (strcmp(apid, PS0_NAME) == 0)
28310Sstevel@tonic-gate nodename = PSU0_NAME;
28320Sstevel@tonic-gate else if (strcmp(apid, PS1_NAME) == 0)
28330Sstevel@tonic-gate nodename = PSU1_NAME;
28340Sstevel@tonic-gate else if (strcmp(apid, PS2_NAME) == 0)
28350Sstevel@tonic-gate nodename = PSU2_NAME;
28360Sstevel@tonic-gate else if (strcmp(apid, PS3_NAME) == 0)
28370Sstevel@tonic-gate nodename = PSU3_NAME;
28380Sstevel@tonic-gate else
28390Sstevel@tonic-gate nodename = apid;
28400Sstevel@tonic-gate
28410Sstevel@tonic-gate return (nodename);
28420Sstevel@tonic-gate }
28430Sstevel@tonic-gate
28440Sstevel@tonic-gate /*
28450Sstevel@tonic-gate * Create SEEPROM node at insertion time.
28460Sstevel@tonic-gate */
28470Sstevel@tonic-gate static int
create_i2c_node(char * ap_id)28480Sstevel@tonic-gate create_i2c_node(char *ap_id)
28490Sstevel@tonic-gate {
28500Sstevel@tonic-gate int nd_reg[2];
28510Sstevel@tonic-gate devctl_ddef_t ddef_hdl;
28520Sstevel@tonic-gate devctl_hdl_t bus_hdl;
28530Sstevel@tonic-gate devctl_hdl_t dev_hdl;
28540Sstevel@tonic-gate char dev_path[MAXPATHLEN];
28552392Svenki char *compatible;
28560Sstevel@tonic-gate
28570Sstevel@tonic-gate /* create seeprom node */
28580Sstevel@tonic-gate nd_reg[0] = 0;
28590Sstevel@tonic-gate nd_reg[1] = ps_name_to_addr(ap_id);
28600Sstevel@tonic-gate
28611103Sjbeloro switch (sys_platform) {
28621103Sjbeloro case PLAT_SEATTLE1U:
28631103Sjbeloro case PLAT_SEATTLE2U:
28641103Sjbeloro bus_hdl = devctl_bus_acquire(SEATTLE_PSU_I2C_BUS_DEV, 0);
28652392Svenki compatible = SEATTLE_PSU_COMPATIBLE;
28661103Sjbeloro break;
28671103Sjbeloro case PLAT_BOSTON:
28681103Sjbeloro bus_hdl = devctl_bus_acquire(BOSTON_PSU_I2C_BUS_DEV, 0);
28692392Svenki compatible = BOSTON_PSU_COMPATIBLE;
28701103Sjbeloro break;
28711103Sjbeloro default:
28721103Sjbeloro bus_hdl = devctl_bus_acquire(PSU_I2C_BUS_DEV, 0);
28732392Svenki compatible = PSU_COMPATIBLE;
28741103Sjbeloro break;
28751103Sjbeloro }
28761103Sjbeloro
28770Sstevel@tonic-gate if (bus_hdl == NULL)
28780Sstevel@tonic-gate return (DDI_FAILURE);
28790Sstevel@tonic-gate
28800Sstevel@tonic-gate /* device definition properties */
28810Sstevel@tonic-gate ddef_hdl = devctl_ddef_alloc(PS_DEVICE_NAME, 0);
28822392Svenki (void) devctl_ddef_string(ddef_hdl, "compatible", compatible);
28830Sstevel@tonic-gate (void) devctl_ddef_string(ddef_hdl, "device_type", "seeprom");
28840Sstevel@tonic-gate (void) devctl_ddef_int_array(ddef_hdl, "reg", 2, nd_reg);
28850Sstevel@tonic-gate
28860Sstevel@tonic-gate /* create the device node */
28870Sstevel@tonic-gate if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl))
28880Sstevel@tonic-gate return (DDI_FAILURE);
28890Sstevel@tonic-gate
28900Sstevel@tonic-gate if (devctl_get_pathname(dev_hdl, dev_path, MAXPATHLEN) == NULL)
28910Sstevel@tonic-gate return (DDI_FAILURE);
28920Sstevel@tonic-gate
28930Sstevel@tonic-gate devctl_release(dev_hdl);
28940Sstevel@tonic-gate devctl_ddef_free(ddef_hdl);
28950Sstevel@tonic-gate devctl_release(bus_hdl);
28960Sstevel@tonic-gate return (DDI_SUCCESS);
28970Sstevel@tonic-gate }
28980Sstevel@tonic-gate
28990Sstevel@tonic-gate /*
29000Sstevel@tonic-gate * Delete SEEPROM node at insertion time.
29010Sstevel@tonic-gate */
29020Sstevel@tonic-gate static void
delete_i2c_node(char * ap_id)29030Sstevel@tonic-gate delete_i2c_node(char *ap_id)
29040Sstevel@tonic-gate {
29050Sstevel@tonic-gate devctl_hdl_t dev_hdl;
29060Sstevel@tonic-gate char buf[MAXPATHLEN];
29070Sstevel@tonic-gate
29081103Sjbeloro switch (sys_platform) {
29091103Sjbeloro case PLAT_SEATTLE1U:
29101103Sjbeloro case PLAT_SEATTLE2U:
29111103Sjbeloro sprintf_buf2(buf, SEATTLE_PSU_DEV, ps_name_to_addr(ap_id));
29121103Sjbeloro break;
29131103Sjbeloro case PLAT_BOSTON:
29141103Sjbeloro sprintf_buf2(buf, BOSTON_PSU_DEV, ps_name_to_addr(ap_id));
29151103Sjbeloro break;
29161103Sjbeloro default:
29171103Sjbeloro sprintf_buf2(buf, PSU_DEV, ps_name_to_addr(ap_id));
29181103Sjbeloro break;
29191103Sjbeloro }
29201103Sjbeloro
29210Sstevel@tonic-gate dev_hdl = devctl_device_acquire(buf, 0);
29220Sstevel@tonic-gate if (dev_hdl == NULL) {
29230Sstevel@tonic-gate return;
29240Sstevel@tonic-gate }
29250Sstevel@tonic-gate
29260Sstevel@tonic-gate /*
29270Sstevel@tonic-gate * If the seeprom driver is not loaded, calls to
29280Sstevel@tonic-gate * devctl_device_remove fails for seeprom devices
29290Sstevel@tonic-gate */
29300Sstevel@tonic-gate if (devctl_device_remove(dev_hdl)) {
29310Sstevel@tonic-gate di_init_driver(SEEPROM_DRIVER_NAME, 0);
29320Sstevel@tonic-gate devctl_device_remove(dev_hdl);
29330Sstevel@tonic-gate }
29340Sstevel@tonic-gate devctl_release(dev_hdl);
29350Sstevel@tonic-gate }
29360Sstevel@tonic-gate
29370Sstevel@tonic-gate static void
add_op_status(envmon_hpu_t * hpu,int * index)29380Sstevel@tonic-gate add_op_status(envmon_hpu_t *hpu, int *index)
29390Sstevel@tonic-gate {
29400Sstevel@tonic-gate boolean_t rmc_flag;
29410Sstevel@tonic-gate boolean_t ps_flag;
29420Sstevel@tonic-gate boolean_t disk_flag;
29430Sstevel@tonic-gate char node_name[MAXPATHLEN];
29440Sstevel@tonic-gate boolean_t flag;
29450Sstevel@tonic-gate
29460Sstevel@tonic-gate rmc_flag = (strcmp(hpu->id.name, RMC_NAME) == 0);
29470Sstevel@tonic-gate ps_flag = (strncmp(hpu->id.name, PS_NAME,
2948*12601SJustin.Frank@Sun.COM PS_NAME_LEN) == 0);
29490Sstevel@tonic-gate disk_flag = (strncmp(hpu->id.name, DISK_NAME,
2950*12601SJustin.Frank@Sun.COM DISK_NAME_LEN) == 0);
29511103Sjbeloro if (rmc_flag || ps_flag) {
29520Sstevel@tonic-gate idprop->idp[*index].envhandle = hpu->id;
29530Sstevel@tonic-gate flag = rmc_flag && ((sys_platform != PLAT_CHALUPA) &&
2954*12601SJustin.Frank@Sun.COM (sys_platform != PLAT_CHALUPA19));
29550Sstevel@tonic-gate sprintf_buf2(node_name,
2956*12601SJustin.Frank@Sun.COM flag ? SYS_BOARD_PATH : CHASSIS_LOC_PATH, ps_flag ?
2957*12601SJustin.Frank@Sun.COM ps_apid_to_nodename(hpu->id.name) : hpu->id.name);
29580Sstevel@tonic-gate
29591103Sjbeloro add_op_status_by_name(node_name, ps_flag ? PS_FRU_NAME : NULL,
2960*12601SJustin.Frank@Sun.COM &idprop->idp[(*index)++].volprop);
29611103Sjbeloro } else if (disk_flag) {
29621103Sjbeloro idprop->idp[*index].envhandle = hpu->id;
29631103Sjbeloro switch (sys_platform) {
29641103Sjbeloro case PLAT_CHALUPA:
29651103Sjbeloro case PLAT_CHALUPA19:
29661103Sjbeloro sprintf_buf2(node_name, CHASSIS_LOC_PATH, hpu->id.name);
29671103Sjbeloro break;
29681103Sjbeloro case PLAT_SEATTLE1U:
29691103Sjbeloro sprintf_buf2(node_name, SEATTLE1U_HDDBP_PATH, \
2970*12601SJustin.Frank@Sun.COM hpu->id.name);
29711103Sjbeloro break;
29721103Sjbeloro case PLAT_SEATTLE2U:
29731103Sjbeloro sprintf_buf2(node_name, SEATTLE2U_HDDBP_PATH, \
2974*12601SJustin.Frank@Sun.COM hpu->id.name);
29751103Sjbeloro break;
29761103Sjbeloro case PLAT_BOSTON:
29771103Sjbeloro sprintf_buf2(node_name, BOSTON_HDDBP_PATH, \
2978*12601SJustin.Frank@Sun.COM hpu->id.name);
29791103Sjbeloro break;
29801103Sjbeloro default:
29811103Sjbeloro sprintf_buf2(node_name, SYS_BOARD_PATH, hpu->id.name);
29821103Sjbeloro break;
29831103Sjbeloro }
29841103Sjbeloro add_op_status_by_name(node_name, DISK_FRU_NAME,
2985*12601SJustin.Frank@Sun.COM &idprop->idp[(*index)++].volprop);
29860Sstevel@tonic-gate }
29870Sstevel@tonic-gate }
2988