1*3db86aabSstevel /* 2*3db86aabSstevel * CDDL HEADER START 3*3db86aabSstevel * 4*3db86aabSstevel * The contents of this file are subject to the terms of the 5*3db86aabSstevel * Common Development and Distribution License (the "License"). 6*3db86aabSstevel * You may not use this file except in compliance with the License. 7*3db86aabSstevel * 8*3db86aabSstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3db86aabSstevel * or http://www.opensolaris.org/os/licensing. 10*3db86aabSstevel * See the License for the specific language governing permissions 11*3db86aabSstevel * and limitations under the License. 12*3db86aabSstevel * 13*3db86aabSstevel * When distributing Covered Code, include this CDDL HEADER in each 14*3db86aabSstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3db86aabSstevel * If applicable, add the following below this CDDL HEADER, with the 16*3db86aabSstevel * fields enclosed by brackets "[]" replaced with your own identifying 17*3db86aabSstevel * information: Portions Copyright [yyyy] [name of copyright owner] 18*3db86aabSstevel * 19*3db86aabSstevel * CDDL HEADER END 20*3db86aabSstevel */ 21*3db86aabSstevel 22*3db86aabSstevel /* 23*3db86aabSstevel * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*3db86aabSstevel * Use is subject to license terms. 25*3db86aabSstevel */ 26*3db86aabSstevel 27*3db86aabSstevel #pragma ident "%Z%%M% %I% %E% SMI" 28*3db86aabSstevel 29*3db86aabSstevel #include <sys/types.h> 30*3db86aabSstevel #include <sys/stat.h> 31*3db86aabSstevel #include <sys/conf.h> 32*3db86aabSstevel #include <sys/modctl.h> 33*3db86aabSstevel #include <sys/callb.h> 34*3db86aabSstevel #include <sys/strlog.h> 35*3db86aabSstevel #include <sys/cyclic.h> 36*3db86aabSstevel #include <sys/rmc_comm_dp.h> 37*3db86aabSstevel #include <sys/rmc_comm_dp_boot.h> 38*3db86aabSstevel #include <sys/rmc_comm_drvintf.h> 39*3db86aabSstevel #include <sys/rmc_comm.h> 40*3db86aabSstevel #include <sys/machsystm.h> 41*3db86aabSstevel #include <sys/sysevent.h> 42*3db86aabSstevel #include <sys/sysevent/dr.h> 43*3db86aabSstevel #include <sys/sysevent/env.h> 44*3db86aabSstevel #include <sys/sysevent/eventdefs.h> 45*3db86aabSstevel #include <sys/file.h> 46*3db86aabSstevel #include <sys/disp.h> 47*3db86aabSstevel #include <sys/reboot.h> 48*3db86aabSstevel #include <sys/envmon.h> 49*3db86aabSstevel #include <sys/rmclomv_impl.h> 50*3db86aabSstevel #include <sys/cpu_sgnblk_defs.h> 51*3db86aabSstevel #include <sys/utsname.h> 52*3db86aabSstevel #include <sys/systeminfo.h> 53*3db86aabSstevel #include <sys/ddi.h> 54*3db86aabSstevel #include <sys/time.h> 55*3db86aabSstevel #include <sys/promif.h> 56*3db86aabSstevel 57*3db86aabSstevel #define offsetof(s, m) (size_t)(&(((s *)0)->m)) 58*3db86aabSstevel #define RMCRESBUFLEN 1024 59*3db86aabSstevel #define DATE_TIME_MSG_SIZE 78 60*3db86aabSstevel #define RMCLOMV_WATCHDOG_MODE "rmclomv-watchdog-mode" 61*3db86aabSstevel 62*3db86aabSstevel extern void pmugpio_watchdog_pat(); 63*3db86aabSstevel static clock_t timesync_interval; 64*3db86aabSstevel 65*3db86aabSstevel extern int watchdog_activated; 66*3db86aabSstevel static int last_watchdog_msg = 1; 67*3db86aabSstevel extern int watchdog_enable; 68*3db86aabSstevel extern int boothowto; 69*3db86aabSstevel 70*3db86aabSstevel int rmclomv_watchdog_mode; 71*3db86aabSstevel 72*3db86aabSstevel /* 73*3db86aabSstevel * functions local to this driver. 74*3db86aabSstevel */ 75*3db86aabSstevel static int rmclomv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, 76*3db86aabSstevel void **resultp); 77*3db86aabSstevel static int rmclomv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 78*3db86aabSstevel static int rmclomv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 79*3db86aabSstevel static uint_t rmclomv_break_intr(caddr_t arg); 80*3db86aabSstevel static int rmclomv_add_intr_handlers(void); 81*3db86aabSstevel static int rmclomv_remove_intr_handlers(void); 82*3db86aabSstevel static uint_t rmclomv_event_data_handler(char *); 83*3db86aabSstevel static void rmclomv_dr_data_handler(const char *, int); 84*3db86aabSstevel static int rmclomv_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p); 85*3db86aabSstevel static int rmclomv_close(dev_t dev, int flag, int otyp, cred_t *cred_p); 86*3db86aabSstevel static int rmclomv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 87*3db86aabSstevel cred_t *cred_p, int *rval_p); 88*3db86aabSstevel static void rmclomv_checkrmc_start(void); 89*3db86aabSstevel static void rmclomv_checkrmc_destroy(void); 90*3db86aabSstevel static void rmclomv_checkrmc_wakeup(void *); 91*3db86aabSstevel static void rmclomv_refresh_start(void); 92*3db86aabSstevel static void rmclomv_refresh_destroy(void); 93*3db86aabSstevel static void rmclomv_refresh_wakeup(void); 94*3db86aabSstevel static void rmclomv_reset_cache(rmclomv_cache_section_t *new_chain, 95*3db86aabSstevel rmclomv_cache_section_t *new_subchain, dp_get_sysinfo_r_t *sysinfo); 96*3db86aabSstevel static rmclomv_cache_section_t *rmclomv_find_section( 97*3db86aabSstevel rmclomv_cache_section_t *start, uint16_t sensor); 98*3db86aabSstevel static rmclomv_cache_section_t *create_cache_section(int sensor_type, int num); 99*3db86aabSstevel static int get_sensor_by_name(const rmclomv_cache_section_t *section, 100*3db86aabSstevel const char *name, int *index); 101*3db86aabSstevel static int validate_section_entry(rmclomv_cache_section_t *section, 102*3db86aabSstevel int index); 103*3db86aabSstevel static int add_names_to_section(rmclomv_cache_section_t *section); 104*3db86aabSstevel static void free_section(rmclomv_cache_section_t *section); 105*3db86aabSstevel static void add_section(rmclomv_cache_section_t **head, 106*3db86aabSstevel rmclomv_cache_section_t *section); 107*3db86aabSstevel static int rmclomv_do_cmd(int req_cmd, int resp_cmd, int resp_len, 108*3db86aabSstevel intptr_t arg_req, intptr_t arg_res); 109*3db86aabSstevel static void refresh_name_cache(int force_fail); 110*3db86aabSstevel static void set_val_unav(envmon_sensor_t *sensor); 111*3db86aabSstevel static void set_fan_unav(envmon_fan_t *fan); 112*3db86aabSstevel static int do_psu_cmd(intptr_t arg, int mode, envmon_indicator_t *env_ind, 113*3db86aabSstevel dp_get_psu_status_t *rmc_psu, dp_get_psu_status_r_t *rmc_psu_r, 114*3db86aabSstevel int detector_type); 115*3db86aabSstevel static uint_t rmc_set_watchdog_timer(uint_t timeoutval); 116*3db86aabSstevel static uint_t rmc_clear_watchdog_timer(void); 117*3db86aabSstevel static void send_watchdog_msg(int msg); 118*3db86aabSstevel static void plat_timesync(void *arg); 119*3db86aabSstevel 120*3db86aabSstevel /* 121*3db86aabSstevel * Driver entry points 122*3db86aabSstevel */ 123*3db86aabSstevel static struct cb_ops rmclomv_cb_ops = { 124*3db86aabSstevel rmclomv_open, /* open */ 125*3db86aabSstevel rmclomv_close, /* close */ 126*3db86aabSstevel nodev, /* strategy() */ 127*3db86aabSstevel nodev, /* print() */ 128*3db86aabSstevel nodev, /* dump() */ 129*3db86aabSstevel nodev, /* read() */ 130*3db86aabSstevel nodev, /* write() */ 131*3db86aabSstevel rmclomv_ioctl, /* ioctl() */ 132*3db86aabSstevel nodev, /* devmap() */ 133*3db86aabSstevel nodev, /* mmap() */ 134*3db86aabSstevel ddi_segmap, /* segmap() */ 135*3db86aabSstevel nochpoll, /* poll() */ 136*3db86aabSstevel ddi_prop_op, /* prop_op() */ 137*3db86aabSstevel NULL, /* cb_str */ 138*3db86aabSstevel D_NEW | D_MP /* cb_flag */ 139*3db86aabSstevel }; 140*3db86aabSstevel 141*3db86aabSstevel 142*3db86aabSstevel static struct dev_ops rmclomv_ops = { 143*3db86aabSstevel DEVO_REV, 144*3db86aabSstevel 0, /* ref count */ 145*3db86aabSstevel rmclomv_getinfo, /* getinfo() */ 146*3db86aabSstevel nulldev, /* identify() */ 147*3db86aabSstevel nulldev, /* probe() */ 148*3db86aabSstevel rmclomv_attach, /* attach() */ 149*3db86aabSstevel rmclomv_detach, /* detach */ 150*3db86aabSstevel nodev, /* reset */ 151*3db86aabSstevel &rmclomv_cb_ops, /* pointer to cb_ops structure */ 152*3db86aabSstevel (struct bus_ops *)NULL, 153*3db86aabSstevel nulldev /* power() */ 154*3db86aabSstevel }; 155*3db86aabSstevel 156*3db86aabSstevel /* 157*3db86aabSstevel * Loadable module support. 158*3db86aabSstevel */ 159*3db86aabSstevel extern struct mod_ops mod_driverops; 160*3db86aabSstevel 161*3db86aabSstevel static struct modldrv modldrv = { 162*3db86aabSstevel &mod_driverops, /* Type of module. This is a driver */ 163*3db86aabSstevel "rmclomv control driver v%I%", /* Name of the module */ 164*3db86aabSstevel &rmclomv_ops /* pointer to the dev_ops structure */ 165*3db86aabSstevel }; 166*3db86aabSstevel 167*3db86aabSstevel static struct modlinkage modlinkage = { 168*3db86aabSstevel MODREV_1, 169*3db86aabSstevel &modldrv, 170*3db86aabSstevel NULL 171*3db86aabSstevel }; 172*3db86aabSstevel 173*3db86aabSstevel /* 174*3db86aabSstevel * Device info 175*3db86aabSstevel */ 176*3db86aabSstevel static dev_info_t *rmclomv_dip = NULL; 177*3db86aabSstevel static int rmclomv_break_requested = B_FALSE; 178*3db86aabSstevel static ddi_softintr_t rmclomv_softintr_id; 179*3db86aabSstevel static ddi_iblock_cookie_t rmclomv_soft_iblock_cookie; 180*3db86aabSstevel 181*3db86aabSstevel extern void (*abort_seq_handler)(); 182*3db86aabSstevel /* key_position is effective key-position. Set to locked if unknown */ 183*3db86aabSstevel static rsci8 key_position = RMC_KEYSWITCH_POS_LOCKED; 184*3db86aabSstevel /* real_key_position starts off as unknown and records value actually seen */ 185*3db86aabSstevel static rsci8 real_key_position = RMC_KEYSWITCH_POS_UNKNOWN; 186*3db86aabSstevel static void rmclomv_abort_seq_handler(char *msg); 187*3db86aabSstevel 188*3db86aabSstevel /* 189*3db86aabSstevel * mutexes which protect the interrupt handlers. 190*3db86aabSstevel */ 191*3db86aabSstevel static kmutex_t rmclomv_event_hdlr_lock; 192*3db86aabSstevel static kmutex_t rmclomv_refresh_lock; 193*3db86aabSstevel static kcondvar_t rmclomv_refresh_sig_cv; 194*3db86aabSstevel static kmutex_t rmclomv_checkrmc_lock; 195*3db86aabSstevel static kcondvar_t rmclomv_checkrmc_sig_cv; 196*3db86aabSstevel 197*3db86aabSstevel /* 198*3db86aabSstevel * mutex to protect the handle_name cache 199*3db86aabSstevel */ 200*3db86aabSstevel static kmutex_t rmclomv_cache_lock; 201*3db86aabSstevel 202*3db86aabSstevel /* 203*3db86aabSstevel * mutex to protect the RMC state 204*3db86aabSstevel */ 205*3db86aabSstevel static kmutex_t rmclomv_state_lock; 206*3db86aabSstevel 207*3db86aabSstevel /* 208*3db86aabSstevel * Payloads of the event handlers. 209*3db86aabSstevel */ 210*3db86aabSstevel static dp_event_notification_t rmclomv_event_payload; 211*3db86aabSstevel static rmc_comm_msg_t rmclomv_event_payload_msg; 212*3db86aabSstevel 213*3db86aabSstevel /* 214*3db86aabSstevel * Checkrmc commands.. 215*3db86aabSstevel */ 216*3db86aabSstevel #define RMCLOMV_CHECKRMC_EXITNOW (-1) 217*3db86aabSstevel #define RMCLOMV_CHECKRMC_WAIT 0 218*3db86aabSstevel #define RMCLOMV_CHECKRMC_PROCESSNOW 1 219*3db86aabSstevel 220*3db86aabSstevel /* 221*3db86aabSstevel * Checkrmc thread state 222*3db86aabSstevel */ 223*3db86aabSstevel static int rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_WAIT; 224*3db86aabSstevel static kt_did_t rmclomv_checkrmc_tid = 0; 225*3db86aabSstevel 226*3db86aabSstevel /* 227*3db86aabSstevel * RMC state data 228*3db86aabSstevel */ 229*3db86aabSstevel #define RMCLOMV_RMCSTATE_UNKNOWN 0 230*3db86aabSstevel #define RMCLOMV_RMCSTATE_OK 1 231*3db86aabSstevel #define RMCLOMV_RMCSTATE_FAILED 2 232*3db86aabSstevel #define RMCLOMV_RMCSTATE_DOWNLOAD 3 233*3db86aabSstevel 234*3db86aabSstevel /* 235*3db86aabSstevel * RMC error indicator values (status from last RMC command) 236*3db86aabSstevel */ 237*3db86aabSstevel #define RMCLOMV_RMCERROR_NONE 0 238*3db86aabSstevel 239*3db86aabSstevel /* fail RMC after 5 minutes without a good response */ 240*3db86aabSstevel #define RMCLOMV_RMCFAILTHRESHOLD 5 241*3db86aabSstevel 242*3db86aabSstevel /* 243*3db86aabSstevel * rmclomv_rmc_state is the state reported in OperationalStatus. 244*3db86aabSstevel * rmclomv_rmc_error reflects the result of the last RMC interaction. 245*3db86aabSstevel * rmclomv_rmcfailcount is used by the rmclomv_checkrmc thread to count 246*3db86aabSstevel * failures in its regular status polls. Once RMCLOMV_RMCFAILTHRESHOLD 247*3db86aabSstevel * is reached, rmclomv_rmc_state is marked as RMCLOMV_RMCSTATE_FAILED. 248*3db86aabSstevel */ 249*3db86aabSstevel static int rmclomv_rmc_state = RMCLOMV_RMCSTATE_UNKNOWN; 250*3db86aabSstevel static int rmclomv_rmc_error = RMCLOMV_RMCERROR_NONE; 251*3db86aabSstevel static int rmclomv_rmcfailcount; 252*3db86aabSstevel 253*3db86aabSstevel /* 254*3db86aabSstevel * Refresh commands.. 255*3db86aabSstevel */ 256*3db86aabSstevel #define RMCLOMV_REFRESH_EXITNOW (-1) 257*3db86aabSstevel #define RMCLOMV_REFRESH_WAIT 0 258*3db86aabSstevel #define RMCLOMV_REFRESH_PROCESSNOW 1 259*3db86aabSstevel 260*3db86aabSstevel /* 261*3db86aabSstevel * Refresh thread state 262*3db86aabSstevel */ 263*3db86aabSstevel static int rmclomv_refresh_sig = RMCLOMV_REFRESH_WAIT; 264*3db86aabSstevel static kt_did_t rmclomv_refresh_tid = 0; 265*3db86aabSstevel 266*3db86aabSstevel /* 267*3db86aabSstevel * timeout id 268*3db86aabSstevel */ 269*3db86aabSstevel static timeout_id_t timer_id; 270*3db86aabSstevel 271*3db86aabSstevel /* 272*3db86aabSstevel * Handle-name cache 273*3db86aabSstevel */ 274*3db86aabSstevel #define LOCK_CACHE mutex_enter(&rmclomv_cache_lock); 275*3db86aabSstevel #define RELEASE_CACHE mutex_exit(&rmclomv_cache_lock); 276*3db86aabSstevel static rmclomv_cache_section_t *rmclomv_cache; /* main handle-names */ 277*3db86aabSstevel static rmclomv_cache_section_t *rmclomv_subcache; /* derived names */ 278*3db86aabSstevel static dp_get_sysinfo_r_t rmclomv_sysinfo_data; 279*3db86aabSstevel static boolean_t rmclomv_sysinfo_valid; 280*3db86aabSstevel static int rmclomv_cache_valid; 281*3db86aabSstevel 282*3db86aabSstevel extern pri_t maxclsyspri; 283*3db86aabSstevel 284*3db86aabSstevel /* 285*3db86aabSstevel * static strings 286*3db86aabSstevel */ 287*3db86aabSstevel static const char str_percent[] = "%"; 288*3db86aabSstevel static const char str_rpm[] = " rpm"; 289*3db86aabSstevel static const char str_ip_volts_ind[] = "P_PWR"; 290*3db86aabSstevel static const char str_ip2_volts_ind[] = "P_PWR2"; 291*3db86aabSstevel static const char str_ff_pok_ind[] = "FF_POK"; 292*3db86aabSstevel static const char str_vlo_volts_ind[] = "FF_UV"; 293*3db86aabSstevel static const char str_vhi_volts_ind[] = "FF_OV"; 294*3db86aabSstevel static const char str_chi_amps_ind[] = "FF_OC"; 295*3db86aabSstevel static const char str_chi_nr_ind[] = "FF_NR"; 296*3db86aabSstevel static const char str_ot_tmpr_ind[] = "FF_OT"; 297*3db86aabSstevel static const char str_fan_ind[] = "FF_FAN"; 298*3db86aabSstevel static const char str_pdct_fan_ind[] = "FF_PDCT_FAN"; 299*3db86aabSstevel static const char str_sc[] = "SC"; 300*3db86aabSstevel 301*3db86aabSstevel int 302*3db86aabSstevel _init(void) 303*3db86aabSstevel { 304*3db86aabSstevel int error = 0; 305*3db86aabSstevel 306*3db86aabSstevel mutex_init(&rmclomv_event_hdlr_lock, NULL, MUTEX_DEFAULT, NULL); 307*3db86aabSstevel mutex_init(&rmclomv_checkrmc_lock, NULL, MUTEX_DRIVER, NULL); 308*3db86aabSstevel mutex_init(&rmclomv_refresh_lock, NULL, MUTEX_DRIVER, NULL); 309*3db86aabSstevel mutex_init(&rmclomv_cache_lock, NULL, MUTEX_DRIVER, NULL); 310*3db86aabSstevel mutex_init(&rmclomv_state_lock, NULL, MUTEX_DRIVER, NULL); 311*3db86aabSstevel cv_init(&rmclomv_checkrmc_sig_cv, NULL, CV_DRIVER, NULL); 312*3db86aabSstevel cv_init(&rmclomv_refresh_sig_cv, NULL, CV_DRIVER, NULL); 313*3db86aabSstevel 314*3db86aabSstevel error = mod_install(&modlinkage); 315*3db86aabSstevel if (error) { 316*3db86aabSstevel cv_destroy(&rmclomv_refresh_sig_cv); 317*3db86aabSstevel cv_destroy(&rmclomv_checkrmc_sig_cv); 318*3db86aabSstevel mutex_destroy(&rmclomv_state_lock); 319*3db86aabSstevel mutex_destroy(&rmclomv_cache_lock); 320*3db86aabSstevel mutex_destroy(&rmclomv_refresh_lock); 321*3db86aabSstevel mutex_destroy(&rmclomv_checkrmc_lock); 322*3db86aabSstevel mutex_destroy(&rmclomv_event_hdlr_lock); 323*3db86aabSstevel } 324*3db86aabSstevel return (error); 325*3db86aabSstevel } 326*3db86aabSstevel 327*3db86aabSstevel 328*3db86aabSstevel int 329*3db86aabSstevel _info(struct modinfo *modinfop) 330*3db86aabSstevel { 331*3db86aabSstevel return (mod_info(&modlinkage, modinfop)); 332*3db86aabSstevel } 333*3db86aabSstevel 334*3db86aabSstevel 335*3db86aabSstevel int 336*3db86aabSstevel _fini(void) 337*3db86aabSstevel { 338*3db86aabSstevel int error = 0; 339*3db86aabSstevel 340*3db86aabSstevel error = mod_remove(&modlinkage); 341*3db86aabSstevel if (error) 342*3db86aabSstevel return (error); 343*3db86aabSstevel cv_destroy(&rmclomv_refresh_sig_cv); 344*3db86aabSstevel cv_destroy(&rmclomv_checkrmc_sig_cv); 345*3db86aabSstevel mutex_destroy(&rmclomv_state_lock); 346*3db86aabSstevel mutex_destroy(&rmclomv_cache_lock); 347*3db86aabSstevel mutex_destroy(&rmclomv_refresh_lock); 348*3db86aabSstevel mutex_destroy(&rmclomv_checkrmc_lock); 349*3db86aabSstevel mutex_destroy(&rmclomv_event_hdlr_lock); 350*3db86aabSstevel return (error); 351*3db86aabSstevel } 352*3db86aabSstevel 353*3db86aabSstevel 354*3db86aabSstevel /* ARGSUSED */ 355*3db86aabSstevel static int 356*3db86aabSstevel rmclomv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) 357*3db86aabSstevel { 358*3db86aabSstevel minor_t m = getminor((dev_t)arg); 359*3db86aabSstevel 360*3db86aabSstevel switch (cmd) { 361*3db86aabSstevel case DDI_INFO_DEVT2DEVINFO: 362*3db86aabSstevel if ((m != 0) || (rmclomv_dip == NULL)) { 363*3db86aabSstevel *resultp = NULL; 364*3db86aabSstevel return (DDI_FAILURE); 365*3db86aabSstevel } 366*3db86aabSstevel *resultp = rmclomv_dip; 367*3db86aabSstevel return (DDI_SUCCESS); 368*3db86aabSstevel case DDI_INFO_DEVT2INSTANCE: 369*3db86aabSstevel *resultp = (void *)(uintptr_t)m; 370*3db86aabSstevel return (DDI_SUCCESS); 371*3db86aabSstevel default: 372*3db86aabSstevel return (DDI_FAILURE); 373*3db86aabSstevel } 374*3db86aabSstevel } 375*3db86aabSstevel 376*3db86aabSstevel 377*3db86aabSstevel static int 378*3db86aabSstevel rmclomv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 379*3db86aabSstevel { 380*3db86aabSstevel int instance; 381*3db86aabSstevel int err; 382*3db86aabSstevel char *wdog_state; 383*3db86aabSstevel int attaching = 1; 384*3db86aabSstevel 385*3db86aabSstevel switch (cmd) { 386*3db86aabSstevel case DDI_ATTACH: 387*3db86aabSstevel /* 388*3db86aabSstevel * only allow one instance 389*3db86aabSstevel */ 390*3db86aabSstevel instance = ddi_get_instance(dip); 391*3db86aabSstevel if (instance != 0) 392*3db86aabSstevel return (DDI_FAILURE); 393*3db86aabSstevel 394*3db86aabSstevel err = ddi_create_minor_node(dip, "rmclomv", S_IFCHR, 395*3db86aabSstevel instance, DDI_PSEUDO, NULL); 396*3db86aabSstevel if (err != DDI_SUCCESS) 397*3db86aabSstevel return (DDI_FAILURE); 398*3db86aabSstevel 399*3db86aabSstevel /* 400*3db86aabSstevel * Register with rmc_comm to prevent it being detached 401*3db86aabSstevel * (in the unlikely event that its attach succeeded on a 402*3db86aabSstevel * platform whose platmod doesn't lock it down). 403*3db86aabSstevel */ 404*3db86aabSstevel err = rmc_comm_register(); 405*3db86aabSstevel if (err != DDI_SUCCESS) { 406*3db86aabSstevel ddi_remove_minor_node(dip, NULL); 407*3db86aabSstevel return (DDI_FAILURE); 408*3db86aabSstevel } 409*3db86aabSstevel 410*3db86aabSstevel /* Remember the dev info */ 411*3db86aabSstevel rmclomv_dip = dip; 412*3db86aabSstevel 413*3db86aabSstevel /* 414*3db86aabSstevel * Add the handlers which watch for unsolicited messages 415*3db86aabSstevel * and post event to Sysevent Framework. 416*3db86aabSstevel */ 417*3db86aabSstevel err = rmclomv_add_intr_handlers(); 418*3db86aabSstevel if (err != DDI_SUCCESS) { 419*3db86aabSstevel rmc_comm_unregister(); 420*3db86aabSstevel ddi_remove_minor_node(dip, NULL); 421*3db86aabSstevel rmclomv_dip = NULL; 422*3db86aabSstevel return (DDI_FAILURE); 423*3db86aabSstevel } 424*3db86aabSstevel 425*3db86aabSstevel rmclomv_checkrmc_start(); 426*3db86aabSstevel rmclomv_refresh_start(); 427*3db86aabSstevel 428*3db86aabSstevel abort_seq_handler = rmclomv_abort_seq_handler; 429*3db86aabSstevel ddi_report_dev(dip); 430*3db86aabSstevel 431*3db86aabSstevel /* 432*3db86aabSstevel * Check whether we have an application watchdog 433*3db86aabSstevel */ 434*3db86aabSstevel if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 435*3db86aabSstevel DDI_PROP_DONTPASS, RMCLOMV_WATCHDOG_MODE, 436*3db86aabSstevel &wdog_state) == DDI_PROP_SUCCESS) { 437*3db86aabSstevel if (strcmp(wdog_state, "app") == 0) { 438*3db86aabSstevel rmclomv_watchdog_mode = 1; 439*3db86aabSstevel watchdog_enable = 0; 440*3db86aabSstevel } 441*3db86aabSstevel else 442*3db86aabSstevel rmclomv_watchdog_mode = 0; 443*3db86aabSstevel ddi_prop_free(wdog_state); 444*3db86aabSstevel } 445*3db86aabSstevel 446*3db86aabSstevel tod_ops.tod_set_watchdog_timer = rmc_set_watchdog_timer; 447*3db86aabSstevel tod_ops.tod_clear_watchdog_timer = rmc_clear_watchdog_timer; 448*3db86aabSstevel 449*3db86aabSstevel /* 450*3db86aabSstevel * Now is a good time to activate hardware watchdog 451*3db86aabSstevel * (if one exists). 452*3db86aabSstevel */ 453*3db86aabSstevel mutex_enter(&tod_lock); 454*3db86aabSstevel if (watchdog_enable && tod_ops.tod_set_watchdog_timer != NULL) 455*3db86aabSstevel err = tod_ops.tod_set_watchdog_timer(0); 456*3db86aabSstevel mutex_exit(&tod_lock); 457*3db86aabSstevel if (err != 0) 458*3db86aabSstevel printf("Hardware watchdog enabled\n"); 459*3db86aabSstevel 460*3db86aabSstevel /* 461*3db86aabSstevel * Set time interval and start timesync routine. 462*3db86aabSstevel * Also just this once set the Solaris clock 463*3db86aabSstevel * to the RMC clock. 464*3db86aabSstevel */ 465*3db86aabSstevel timesync_interval = drv_usectohz(5*60 * MICROSEC); 466*3db86aabSstevel plat_timesync((void *) &attaching); 467*3db86aabSstevel 468*3db86aabSstevel return (DDI_SUCCESS); 469*3db86aabSstevel case DDI_RESUME: 470*3db86aabSstevel return (DDI_SUCCESS); 471*3db86aabSstevel default: 472*3db86aabSstevel return (DDI_FAILURE); 473*3db86aabSstevel } 474*3db86aabSstevel } 475*3db86aabSstevel 476*3db86aabSstevel 477*3db86aabSstevel static int 478*3db86aabSstevel rmclomv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 479*3db86aabSstevel { 480*3db86aabSstevel int instance; 481*3db86aabSstevel int err; 482*3db86aabSstevel 483*3db86aabSstevel switch (cmd) { 484*3db86aabSstevel case DDI_DETACH: 485*3db86aabSstevel instance = ddi_get_instance(dip); 486*3db86aabSstevel if (instance != 0) 487*3db86aabSstevel return (DDI_FAILURE); 488*3db86aabSstevel 489*3db86aabSstevel /* 490*3db86aabSstevel * Remove the handlers which watch for unsolicited messages 491*3db86aabSstevel * and post event to Sysevent Framework. 492*3db86aabSstevel */ 493*3db86aabSstevel err = rmclomv_remove_intr_handlers(); 494*3db86aabSstevel if (err != DDI_SUCCESS) { 495*3db86aabSstevel cmn_err(CE_WARN, "Failed to remove event handlers"); 496*3db86aabSstevel return (DDI_FAILURE); 497*3db86aabSstevel } 498*3db86aabSstevel rmclomv_checkrmc_destroy(); 499*3db86aabSstevel rmclomv_refresh_destroy(); 500*3db86aabSstevel rmclomv_reset_cache(NULL, NULL, NULL); 501*3db86aabSstevel ddi_remove_minor_node(dip, NULL); 502*3db86aabSstevel 503*3db86aabSstevel /* Forget the dev info */ 504*3db86aabSstevel rmclomv_dip = NULL; 505*3db86aabSstevel rmc_comm_unregister(); 506*3db86aabSstevel return (DDI_SUCCESS); 507*3db86aabSstevel case DDI_SUSPEND: 508*3db86aabSstevel return (DDI_SUCCESS); 509*3db86aabSstevel default: 510*3db86aabSstevel return (DDI_FAILURE); 511*3db86aabSstevel } 512*3db86aabSstevel } 513*3db86aabSstevel 514*3db86aabSstevel static int 515*3db86aabSstevel rmclomv_add_intr_handlers() 516*3db86aabSstevel { 517*3db86aabSstevel int err; 518*3db86aabSstevel 519*3db86aabSstevel if (ddi_get_soft_iblock_cookie(rmclomv_dip, DDI_SOFTINT_HIGH, 520*3db86aabSstevel &rmclomv_soft_iblock_cookie) != DDI_SUCCESS) { 521*3db86aabSstevel return (DDI_FAILURE); 522*3db86aabSstevel } 523*3db86aabSstevel err = ddi_add_softintr(rmclomv_dip, DDI_SOFTINT_HIGH, 524*3db86aabSstevel &rmclomv_softintr_id, &rmclomv_soft_iblock_cookie, NULL, 525*3db86aabSstevel rmclomv_break_intr, NULL); 526*3db86aabSstevel if (err != DDI_SUCCESS) 527*3db86aabSstevel return (DDI_FAILURE); 528*3db86aabSstevel rmclomv_event_payload_msg.msg_buf = (caddr_t)&rmclomv_event_payload; 529*3db86aabSstevel rmclomv_event_payload_msg.msg_len = sizeof (rmclomv_event_payload); 530*3db86aabSstevel err = rmc_comm_reg_intr(DP_RMC_EVENTS, rmclomv_event_data_handler, 531*3db86aabSstevel &rmclomv_event_payload_msg, NULL, &rmclomv_event_hdlr_lock); 532*3db86aabSstevel if (err != 0) { 533*3db86aabSstevel ddi_remove_softintr(rmclomv_softintr_id); 534*3db86aabSstevel return (DDI_FAILURE); 535*3db86aabSstevel } 536*3db86aabSstevel return (DDI_SUCCESS); 537*3db86aabSstevel } 538*3db86aabSstevel 539*3db86aabSstevel static int 540*3db86aabSstevel rmclomv_remove_intr_handlers(void) 541*3db86aabSstevel { 542*3db86aabSstevel int err = rmc_comm_unreg_intr(DP_RMC_EVENTS, 543*3db86aabSstevel rmclomv_event_data_handler); 544*3db86aabSstevel if (err != 0) { 545*3db86aabSstevel cmn_err(CE_WARN, "Failed to unregister DP_RMC_EVENTS " 546*3db86aabSstevel "handler. Err=%d", err); 547*3db86aabSstevel return (DDI_FAILURE); 548*3db86aabSstevel } 549*3db86aabSstevel ddi_remove_softintr(rmclomv_softintr_id); 550*3db86aabSstevel return (DDI_SUCCESS); 551*3db86aabSstevel } 552*3db86aabSstevel 553*3db86aabSstevel static void 554*3db86aabSstevel rmclomv_abort_seq_handler(char *msg) 555*3db86aabSstevel { 556*3db86aabSstevel if (key_position == RMC_KEYSWITCH_POS_LOCKED) 557*3db86aabSstevel cmn_err(CE_CONT, "KEY in LOCKED position, " 558*3db86aabSstevel "ignoring debug enter sequence"); 559*3db86aabSstevel else { 560*3db86aabSstevel rmclomv_break_requested = B_TRUE; 561*3db86aabSstevel if (msg != NULL) 562*3db86aabSstevel prom_printf("%s\n", msg); 563*3db86aabSstevel 564*3db86aabSstevel ddi_trigger_softintr(rmclomv_softintr_id); 565*3db86aabSstevel } 566*3db86aabSstevel } 567*3db86aabSstevel 568*3db86aabSstevel /* ARGSUSED */ 569*3db86aabSstevel static uint_t 570*3db86aabSstevel rmclomv_break_intr(caddr_t arg) 571*3db86aabSstevel { 572*3db86aabSstevel if (rmclomv_break_requested) { 573*3db86aabSstevel rmclomv_break_requested = B_FALSE; 574*3db86aabSstevel debug_enter(NULL); 575*3db86aabSstevel return (DDI_INTR_CLAIMED); 576*3db86aabSstevel } 577*3db86aabSstevel 578*3db86aabSstevel return (DDI_INTR_UNCLAIMED); 579*3db86aabSstevel } 580*3db86aabSstevel 581*3db86aabSstevel /* 582*3db86aabSstevel * Create a cache section structure 583*3db86aabSstevel */ 584*3db86aabSstevel static rmclomv_cache_section_t * 585*3db86aabSstevel create_cache_section(int sensor_type, int num) 586*3db86aabSstevel { 587*3db86aabSstevel size_t len = offsetof(rmclomv_cache_section_t, entry[0]) + 588*3db86aabSstevel num * sizeof (rmclomv_cache_entry_t); 589*3db86aabSstevel rmclomv_cache_section_t *ptr = kmem_zalloc(len, KM_SLEEP); 590*3db86aabSstevel ptr->next_section = NULL; 591*3db86aabSstevel ptr->sensor_type = sensor_type; 592*3db86aabSstevel ptr->num_entries = num; 593*3db86aabSstevel ptr->section_len = len; 594*3db86aabSstevel return (ptr); 595*3db86aabSstevel } 596*3db86aabSstevel 597*3db86aabSstevel /* 598*3db86aabSstevel * Free a cache_section. 599*3db86aabSstevel */ 600*3db86aabSstevel static void 601*3db86aabSstevel free_section(rmclomv_cache_section_t *section) 602*3db86aabSstevel { 603*3db86aabSstevel size_t len = section->section_len; 604*3db86aabSstevel kmem_free(section, len); 605*3db86aabSstevel } 606*3db86aabSstevel 607*3db86aabSstevel /* 608*3db86aabSstevel * adds supplied section to end of cache chain 609*3db86aabSstevel * must be called with cache locked 610*3db86aabSstevel */ 611*3db86aabSstevel static void 612*3db86aabSstevel add_section(rmclomv_cache_section_t **head, rmclomv_cache_section_t *section) 613*3db86aabSstevel { 614*3db86aabSstevel section->next_section = *head; 615*3db86aabSstevel *head = section; 616*3db86aabSstevel } 617*3db86aabSstevel 618*3db86aabSstevel /* 619*3db86aabSstevel * This function releases all cache sections and exchanges the two 620*3db86aabSstevel * chain heads for new values. 621*3db86aabSstevel */ 622*3db86aabSstevel static void 623*3db86aabSstevel rmclomv_reset_cache(rmclomv_cache_section_t *new_chain, 624*3db86aabSstevel rmclomv_cache_section_t *new_subchain, dp_get_sysinfo_r_t *sysinfo) 625*3db86aabSstevel { 626*3db86aabSstevel rmclomv_cache_section_t *first; 627*3db86aabSstevel rmclomv_cache_section_t *sub_first; 628*3db86aabSstevel rmclomv_cache_section_t *next; 629*3db86aabSstevel 630*3db86aabSstevel LOCK_CACHE 631*3db86aabSstevel 632*3db86aabSstevel rmclomv_cache_valid = (new_chain != NULL); 633*3db86aabSstevel first = rmclomv_cache; 634*3db86aabSstevel rmclomv_cache = new_chain; 635*3db86aabSstevel sub_first = rmclomv_subcache; 636*3db86aabSstevel rmclomv_subcache = new_subchain; 637*3db86aabSstevel 638*3db86aabSstevel if (sysinfo == NULL) 639*3db86aabSstevel bzero(&rmclomv_sysinfo_data, sizeof (rmclomv_sysinfo_data)); 640*3db86aabSstevel else 641*3db86aabSstevel bcopy(sysinfo, &rmclomv_sysinfo_data, 642*3db86aabSstevel sizeof (rmclomv_sysinfo_data)); 643*3db86aabSstevel 644*3db86aabSstevel rmclomv_sysinfo_valid = (sysinfo != NULL); 645*3db86aabSstevel 646*3db86aabSstevel RELEASE_CACHE 647*3db86aabSstevel 648*3db86aabSstevel while (first != NULL) { 649*3db86aabSstevel next = first->next_section; 650*3db86aabSstevel free_section(first); 651*3db86aabSstevel first = next; 652*3db86aabSstevel } 653*3db86aabSstevel 654*3db86aabSstevel while (sub_first != NULL) { 655*3db86aabSstevel next = sub_first->next_section; 656*3db86aabSstevel free_section(sub_first); 657*3db86aabSstevel sub_first = next; 658*3db86aabSstevel } 659*3db86aabSstevel } 660*3db86aabSstevel 661*3db86aabSstevel /* 662*3db86aabSstevel * cache must be locked before calling rmclomv_find_section 663*3db86aabSstevel */ 664*3db86aabSstevel static rmclomv_cache_section_t * 665*3db86aabSstevel rmclomv_find_section(rmclomv_cache_section_t *start, uint16_t sensor) 666*3db86aabSstevel { 667*3db86aabSstevel rmclomv_cache_section_t *next = start; 668*3db86aabSstevel 669*3db86aabSstevel while ((next != NULL) && (next->sensor_type != sensor)) 670*3db86aabSstevel next = next->next_section; 671*3db86aabSstevel 672*3db86aabSstevel return (next); 673*3db86aabSstevel } 674*3db86aabSstevel 675*3db86aabSstevel /* 676*3db86aabSstevel * Return a string presenting the keyswitch position 677*3db86aabSstevel * For unknown values returns "Unknown" 678*3db86aabSstevel */ 679*3db86aabSstevel static char * 680*3db86aabSstevel rmclomv_key_position(enum rmc_keyswitch_pos pos) 681*3db86aabSstevel { 682*3db86aabSstevel switch (pos) { 683*3db86aabSstevel 684*3db86aabSstevel case RMC_KEYSWITCH_POS_NORMAL: 685*3db86aabSstevel return ("NORMAL"); 686*3db86aabSstevel case RMC_KEYSWITCH_POS_DIAG: 687*3db86aabSstevel return ("DIAG"); 688*3db86aabSstevel case RMC_KEYSWITCH_POS_LOCKED: 689*3db86aabSstevel return ("LOCKED"); 690*3db86aabSstevel case RMC_KEYSWITCH_POS_OFF: 691*3db86aabSstevel return ("STBY"); 692*3db86aabSstevel default: 693*3db86aabSstevel return ("UNKNOWN"); 694*3db86aabSstevel } 695*3db86aabSstevel } 696*3db86aabSstevel 697*3db86aabSstevel /* 698*3db86aabSstevel * The sensor id name is sought in the supplied section and if found 699*3db86aabSstevel * its index within the section is written to *index. 700*3db86aabSstevel * Return value is zero for success, otherwise -1. 701*3db86aabSstevel * The cache must be locked before calling get_sensor_by_name 702*3db86aabSstevel */ 703*3db86aabSstevel static int 704*3db86aabSstevel get_sensor_by_name(const rmclomv_cache_section_t *section, 705*3db86aabSstevel const char *name, int *index) 706*3db86aabSstevel { 707*3db86aabSstevel int i; 708*3db86aabSstevel 709*3db86aabSstevel for (i = 0; i < section->num_entries; i++) { 710*3db86aabSstevel if (strcmp(name, section->entry[i].handle_name.name) == 0) { 711*3db86aabSstevel *index = i; 712*3db86aabSstevel return (0); 713*3db86aabSstevel } 714*3db86aabSstevel } 715*3db86aabSstevel 716*3db86aabSstevel *index = 0; 717*3db86aabSstevel return (-1); 718*3db86aabSstevel } 719*3db86aabSstevel 720*3db86aabSstevel /* 721*3db86aabSstevel * fills in the envmon_handle name 722*3db86aabSstevel * if it is unknown (not cached), the dp_handle_t is returned as a hex-digit 723*3db86aabSstevel * string 724*3db86aabSstevel */ 725*3db86aabSstevel static void 726*3db86aabSstevel rmclomv_hdl_to_envhdl(dp_handle_t hdl, envmon_handle_t *envhdl) 727*3db86aabSstevel { 728*3db86aabSstevel rmclomv_cache_section_t *next; 729*3db86aabSstevel int i; 730*3db86aabSstevel 731*3db86aabSstevel LOCK_CACHE 732*3db86aabSstevel 733*3db86aabSstevel for (next = rmclomv_cache; next != NULL; next = next->next_section) { 734*3db86aabSstevel for (i = 0; i < next->num_entries; i++) { 735*3db86aabSstevel if (next->entry[i].handle == hdl) { 736*3db86aabSstevel *envhdl = next->entry[i].handle_name; 737*3db86aabSstevel RELEASE_CACHE 738*3db86aabSstevel return; 739*3db86aabSstevel } 740*3db86aabSstevel } 741*3db86aabSstevel } 742*3db86aabSstevel 743*3db86aabSstevel /* 744*3db86aabSstevel * Sought handle not currently cached. 745*3db86aabSstevel */ 746*3db86aabSstevel RELEASE_CACHE 747*3db86aabSstevel 748*3db86aabSstevel (void) snprintf(envhdl->name, sizeof (envhdl->name), 749*3db86aabSstevel "Unknown SC node 0x%x", hdl); 750*3db86aabSstevel } 751*3db86aabSstevel 752*3db86aabSstevel static void 753*3db86aabSstevel rmclomv_dr_data_handler(const char *fru_name, int hint) 754*3db86aabSstevel { 755*3db86aabSstevel int err = 0; 756*3db86aabSstevel nvlist_t *attr_list; 757*3db86aabSstevel char attach_pnt[MAXPATHLEN]; 758*3db86aabSstevel 759*3db86aabSstevel (void) snprintf(attach_pnt, sizeof (attach_pnt), "%s", fru_name); 760*3db86aabSstevel 761*3db86aabSstevel err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP); 762*3db86aabSstevel if (err != 0) { 763*3db86aabSstevel cmn_err(CE_WARN, 764*3db86aabSstevel "Failed to allocate name-value list for %s event", EC_DR); 765*3db86aabSstevel return; 766*3db86aabSstevel } 767*3db86aabSstevel 768*3db86aabSstevel err = nvlist_add_string(attr_list, DR_AP_ID, attach_pnt); 769*3db86aabSstevel if (err != 0) { 770*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s event", 771*3db86aabSstevel DR_AP_ID, EC_DR); 772*3db86aabSstevel nvlist_free(attr_list); 773*3db86aabSstevel return; 774*3db86aabSstevel } 775*3db86aabSstevel 776*3db86aabSstevel /* 777*3db86aabSstevel * Add the hint 778*3db86aabSstevel */ 779*3db86aabSstevel err = nvlist_add_string(attr_list, DR_HINT, SE_HINT2STR(hint)); 780*3db86aabSstevel if (err != 0) { 781*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s event", 782*3db86aabSstevel DR_HINT, EC_DR); 783*3db86aabSstevel nvlist_free(attr_list); 784*3db86aabSstevel return; 785*3db86aabSstevel } 786*3db86aabSstevel 787*3db86aabSstevel err = ddi_log_sysevent(rmclomv_dip, DDI_VENDOR_SUNW, EC_DR, 788*3db86aabSstevel ESC_DR_AP_STATE_CHANGE, attr_list, NULL, DDI_NOSLEEP); 789*3db86aabSstevel if (err != 0) { 790*3db86aabSstevel cmn_err(CE_WARN, "Failed to log %s/%s event", 791*3db86aabSstevel DR_AP_ID, EC_DR); 792*3db86aabSstevel } 793*3db86aabSstevel 794*3db86aabSstevel nvlist_free(attr_list); 795*3db86aabSstevel } 796*3db86aabSstevel 797*3db86aabSstevel static void 798*3db86aabSstevel fan_sysevent(char *fru_name, char *sensor_name, int sub_event) 799*3db86aabSstevel { 800*3db86aabSstevel nvlist_t *attr_list; 801*3db86aabSstevel char fan_str[MAXNAMELEN]; 802*3db86aabSstevel int err; 803*3db86aabSstevel 804*3db86aabSstevel err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP); 805*3db86aabSstevel if (err != 0) { 806*3db86aabSstevel cmn_err(CE_WARN, 807*3db86aabSstevel "Failed to allocate name-value list for %s/%s event", 808*3db86aabSstevel EC_ENV, ESC_ENV_FAN); 809*3db86aabSstevel return; 810*3db86aabSstevel } 811*3db86aabSstevel 812*3db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_ID, fru_name); 813*3db86aabSstevel if (err != 0) { 814*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 815*3db86aabSstevel ENV_FRU_ID, EC_ENV, ESC_ENV_FAN); 816*3db86aabSstevel nvlist_free(attr_list); 817*3db86aabSstevel return; 818*3db86aabSstevel } 819*3db86aabSstevel 820*3db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_RESOURCE_ID, sensor_name); 821*3db86aabSstevel if (err != 0) { 822*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 823*3db86aabSstevel ENV_FRU_RESOURCE_ID, EC_ENV, ESC_ENV_FAN); 824*3db86aabSstevel nvlist_free(attr_list); 825*3db86aabSstevel return; 826*3db86aabSstevel } 827*3db86aabSstevel 828*3db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_DEVICE, ENV_RESERVED_ATTR); 829*3db86aabSstevel if (err != 0) { 830*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 831*3db86aabSstevel ENV_FRU_DEVICE, EC_ENV, ESC_ENV_FAN); 832*3db86aabSstevel nvlist_free(attr_list); 833*3db86aabSstevel return; 834*3db86aabSstevel } 835*3db86aabSstevel 836*3db86aabSstevel err = nvlist_add_int32(attr_list, ENV_FRU_STATE, 837*3db86aabSstevel (sub_event == RMC_ENV_FAULT_EVENT) ? ENV_FAILED : ENV_OK); 838*3db86aabSstevel if (err != 0) { 839*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 840*3db86aabSstevel ENV_FRU_STATE, EC_ENV, ESC_ENV_FAN); 841*3db86aabSstevel nvlist_free(attr_list); 842*3db86aabSstevel return; 843*3db86aabSstevel } 844*3db86aabSstevel 845*3db86aabSstevel if (sub_event == RMC_ENV_FAULT_EVENT) { 846*3db86aabSstevel (void) snprintf(fan_str, sizeof (fan_str), 847*3db86aabSstevel "fan %s/%s is now failed", fru_name, sensor_name); 848*3db86aabSstevel } else { 849*3db86aabSstevel (void) snprintf(fan_str, sizeof (fan_str), 850*3db86aabSstevel "fan %s/%s is now ok", fru_name, sensor_name); 851*3db86aabSstevel } 852*3db86aabSstevel err = nvlist_add_string(attr_list, ENV_MSG, fan_str); 853*3db86aabSstevel if (err != 0) { 854*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 855*3db86aabSstevel ENV_MSG, EC_ENV, ESC_ENV_FAN); 856*3db86aabSstevel nvlist_free(attr_list); 857*3db86aabSstevel return; 858*3db86aabSstevel } 859*3db86aabSstevel 860*3db86aabSstevel err = ddi_log_sysevent(rmclomv_dip, DDI_VENDOR_SUNW, EC_ENV, 861*3db86aabSstevel ESC_ENV_FAN, attr_list, NULL, DDI_NOSLEEP); 862*3db86aabSstevel if (err != 0) { 863*3db86aabSstevel cmn_err(CE_WARN, "Failed to log %s/%s event", 864*3db86aabSstevel EC_ENV, ESC_ENV_FAN); 865*3db86aabSstevel } 866*3db86aabSstevel 867*3db86aabSstevel cmn_err(CE_NOTE, "%s", fan_str); 868*3db86aabSstevel nvlist_free(attr_list); 869*3db86aabSstevel } 870*3db86aabSstevel 871*3db86aabSstevel static void 872*3db86aabSstevel threshold_sysevent(char *fru_name, char *sensor_name, int sub_event, 873*3db86aabSstevel char event_type) 874*3db86aabSstevel { 875*3db86aabSstevel nvlist_t *attr_list; 876*3db86aabSstevel int err; 877*3db86aabSstevel char *subclass; 878*3db86aabSstevel char sensor_str[MAXNAMELEN]; 879*3db86aabSstevel 880*3db86aabSstevel subclass = (event_type == 'T') ? ESC_ENV_TEMP : ESC_ENV_POWER; 881*3db86aabSstevel 882*3db86aabSstevel err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP); 883*3db86aabSstevel if (err != 0) { 884*3db86aabSstevel cmn_err(CE_WARN, 885*3db86aabSstevel "Failed to allocate name-value list for %s/%s event", 886*3db86aabSstevel EC_ENV, subclass); 887*3db86aabSstevel return; 888*3db86aabSstevel } 889*3db86aabSstevel 890*3db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_ID, fru_name); 891*3db86aabSstevel if (err != 0) { 892*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 893*3db86aabSstevel ENV_FRU_ID, EC_ENV, subclass); 894*3db86aabSstevel nvlist_free(attr_list); 895*3db86aabSstevel return; 896*3db86aabSstevel } 897*3db86aabSstevel 898*3db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_RESOURCE_ID, sensor_name); 899*3db86aabSstevel if (err != 0) { 900*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 901*3db86aabSstevel ENV_FRU_RESOURCE_ID, EC_ENV, subclass); 902*3db86aabSstevel nvlist_free(attr_list); 903*3db86aabSstevel return; 904*3db86aabSstevel } 905*3db86aabSstevel 906*3db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_DEVICE, ENV_RESERVED_ATTR); 907*3db86aabSstevel if (err != 0) { 908*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 909*3db86aabSstevel ENV_FRU_DEVICE, EC_ENV, subclass); 910*3db86aabSstevel nvlist_free(attr_list); 911*3db86aabSstevel return; 912*3db86aabSstevel } 913*3db86aabSstevel 914*3db86aabSstevel switch (sub_event) { 915*3db86aabSstevel case RMC_ENV_OK_EVENT: 916*3db86aabSstevel err = nvlist_add_int32(attr_list, ENV_FRU_STATE, ENV_OK); 917*3db86aabSstevel break; 918*3db86aabSstevel case RMC_ENV_WARNING_THRESHOLD_EVENT: 919*3db86aabSstevel err = nvlist_add_int32(attr_list, ENV_FRU_STATE, ENV_WARNING); 920*3db86aabSstevel break; 921*3db86aabSstevel case RMC_ENV_SHUTDOWN_THRESHOLD_EVENT: 922*3db86aabSstevel err = nvlist_add_int32(attr_list, ENV_FRU_STATE, ENV_FAILED); 923*3db86aabSstevel break; 924*3db86aabSstevel } 925*3db86aabSstevel if (err != 0) { 926*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 927*3db86aabSstevel ENV_FRU_STATE, EC_ENV, subclass); 928*3db86aabSstevel nvlist_free(attr_list); 929*3db86aabSstevel return; 930*3db86aabSstevel } 931*3db86aabSstevel 932*3db86aabSstevel switch (sub_event) { 933*3db86aabSstevel case RMC_ENV_OK_EVENT: 934*3db86aabSstevel (void) snprintf(sensor_str, sizeof (sensor_str), 935*3db86aabSstevel "sensor %s/%s is now ok", fru_name, 936*3db86aabSstevel sensor_name); 937*3db86aabSstevel break; 938*3db86aabSstevel case RMC_ENV_WARNING_THRESHOLD_EVENT: 939*3db86aabSstevel (void) snprintf(sensor_str, sizeof (sensor_str), 940*3db86aabSstevel "sensor %s/%s is now outside warning thresholds", fru_name, 941*3db86aabSstevel sensor_name); 942*3db86aabSstevel break; 943*3db86aabSstevel case RMC_ENV_SHUTDOWN_THRESHOLD_EVENT: 944*3db86aabSstevel (void) snprintf(sensor_str, sizeof (sensor_str), 945*3db86aabSstevel "sensor %s/%s is now outside shutdown thresholds", fru_name, 946*3db86aabSstevel sensor_name); 947*3db86aabSstevel break; 948*3db86aabSstevel } 949*3db86aabSstevel err = nvlist_add_string(attr_list, ENV_MSG, sensor_str); 950*3db86aabSstevel if (err != 0) { 951*3db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event", 952*3db86aabSstevel ENV_MSG, EC_ENV, subclass); 953*3db86aabSstevel nvlist_free(attr_list); 954*3db86aabSstevel return; 955*3db86aabSstevel } 956*3db86aabSstevel 957*3db86aabSstevel err = ddi_log_sysevent(rmclomv_dip, DDI_VENDOR_SUNW, EC_ENV, 958*3db86aabSstevel subclass, attr_list, NULL, DDI_NOSLEEP); 959*3db86aabSstevel if (err != 0) { 960*3db86aabSstevel cmn_err(CE_WARN, "Failed to log %s/%s event", 961*3db86aabSstevel EC_ENV, subclass); 962*3db86aabSstevel } 963*3db86aabSstevel 964*3db86aabSstevel cmn_err(CE_NOTE, "%s", sensor_str); 965*3db86aabSstevel nvlist_free(attr_list); 966*3db86aabSstevel } 967*3db86aabSstevel 968*3db86aabSstevel static uint_t 969*3db86aabSstevel rmclomv_event_data_handler(char *arg) 970*3db86aabSstevel { 971*3db86aabSstevel dp_event_notification_t *payload; 972*3db86aabSstevel rmc_comm_msg_t *msg; 973*3db86aabSstevel envmon_handle_t envhdl; 974*3db86aabSstevel int hint; 975*3db86aabSstevel char *ptr, *save_ptr; 976*3db86aabSstevel 977*3db86aabSstevel if (arg == NULL) { 978*3db86aabSstevel return (DDI_INTR_CLAIMED); 979*3db86aabSstevel } 980*3db86aabSstevel 981*3db86aabSstevel msg = (rmc_comm_msg_t *)arg; 982*3db86aabSstevel if (msg->msg_buf == NULL) { 983*3db86aabSstevel return (DDI_INTR_CLAIMED); 984*3db86aabSstevel } 985*3db86aabSstevel 986*3db86aabSstevel payload = (dp_event_notification_t *)msg->msg_buf; 987*3db86aabSstevel switch (payload->event) { 988*3db86aabSstevel 989*3db86aabSstevel case RMC_KEYSWITCH_EVENT: 990*3db86aabSstevel real_key_position = payload->event_info.ev_keysw.key_position; 991*3db86aabSstevel cmn_err(CE_NOTE, "keyswitch change event - state = %s", 992*3db86aabSstevel rmclomv_key_position(real_key_position)); 993*3db86aabSstevel if ((real_key_position != RMC_KEYSWITCH_POS_UNKNOWN) && 994*3db86aabSstevel (real_key_position <= RMC_KEYSWITCH_POS_OFF)) { 995*3db86aabSstevel key_position = real_key_position; 996*3db86aabSstevel } else { 997*3db86aabSstevel /* treat unknown key position as locked */ 998*3db86aabSstevel key_position = RMC_KEYSWITCH_POS_LOCKED; 999*3db86aabSstevel } 1000*3db86aabSstevel break; 1001*3db86aabSstevel 1002*3db86aabSstevel case RMC_HPU_EVENT: 1003*3db86aabSstevel /* 1004*3db86aabSstevel * send appropriate sysevent 1005*3db86aabSstevel */ 1006*3db86aabSstevel switch (payload->event_info.ev_hpunot.sub_event) { 1007*3db86aabSstevel case RMC_HPU_REMOVE_EVENT: 1008*3db86aabSstevel hint = SE_HINT_REMOVE; 1009*3db86aabSstevel break; 1010*3db86aabSstevel case RMC_HPU_INSERT_EVENT: 1011*3db86aabSstevel hint = SE_HINT_INSERT; 1012*3db86aabSstevel break; 1013*3db86aabSstevel default: 1014*3db86aabSstevel hint = SE_NO_HINT; 1015*3db86aabSstevel break; 1016*3db86aabSstevel } 1017*3db86aabSstevel rmclomv_hdl_to_envhdl(payload->event_info.ev_hpunot.hpu_hdl, 1018*3db86aabSstevel &envhdl); 1019*3db86aabSstevel rmclomv_dr_data_handler(envhdl.name, hint); 1020*3db86aabSstevel break; 1021*3db86aabSstevel 1022*3db86aabSstevel case RMC_INIT_EVENT: 1023*3db86aabSstevel /* 1024*3db86aabSstevel * Wake up the refresh thread. 1025*3db86aabSstevel */ 1026*3db86aabSstevel rmclomv_refresh_wakeup(); 1027*3db86aabSstevel 1028*3db86aabSstevel /* 1029*3db86aabSstevel * Wake up the checkrmc thread for an early indication to PICL 1030*3db86aabSstevel */ 1031*3db86aabSstevel rmclomv_checkrmc_wakeup(NULL); 1032*3db86aabSstevel break; 1033*3db86aabSstevel 1034*3db86aabSstevel case RMC_ENV_EVENT: 1035*3db86aabSstevel rmclomv_hdl_to_envhdl(payload->event_info.ev_envnot.env_hdl, 1036*3db86aabSstevel &envhdl); 1037*3db86aabSstevel 1038*3db86aabSstevel /* split name into fru name and sensor name */ 1039*3db86aabSstevel ptr = strchr(envhdl.name, '.'); 1040*3db86aabSstevel 1041*3db86aabSstevel /* must have at least one '.' */ 1042*3db86aabSstevel if (ptr == NULL) 1043*3db86aabSstevel break; 1044*3db86aabSstevel 1045*3db86aabSstevel /* find last '.' - convert the others to '/' */ 1046*3db86aabSstevel for (;;) { 1047*3db86aabSstevel save_ptr = ptr; 1048*3db86aabSstevel ptr = strchr(ptr, '.'); 1049*3db86aabSstevel if (ptr == NULL) { 1050*3db86aabSstevel ptr = save_ptr; 1051*3db86aabSstevel break; 1052*3db86aabSstevel } 1053*3db86aabSstevel *save_ptr = '/'; 1054*3db86aabSstevel } 1055*3db86aabSstevel *ptr = '\0'; 1056*3db86aabSstevel ptr++; 1057*3db86aabSstevel /* is it a voltage or temperature sensor? */ 1058*3db86aabSstevel if ((*ptr == 'V' || *ptr == 'T') && *(ptr + 1) == '_') { 1059*3db86aabSstevel switch (payload->event_info.ev_envnot.sub_event) { 1060*3db86aabSstevel case RMC_ENV_WARNING_THRESHOLD_EVENT: 1061*3db86aabSstevel case RMC_ENV_SHUTDOWN_THRESHOLD_EVENT: 1062*3db86aabSstevel case RMC_ENV_OK_EVENT: 1063*3db86aabSstevel threshold_sysevent(envhdl.name, ptr, 1064*3db86aabSstevel payload->event_info.ev_envnot.sub_event, 1065*3db86aabSstevel *ptr); 1066*3db86aabSstevel break; 1067*3db86aabSstevel default: 1068*3db86aabSstevel break; 1069*3db86aabSstevel } 1070*3db86aabSstevel } 1071*3db86aabSstevel 1072*3db86aabSstevel /* 1073*3db86aabSstevel * is it a fan sensor? 1074*3db86aabSstevel * Fan sensor names end either in RS, F0 or F1 1075*3db86aabSstevel */ 1076*3db86aabSstevel if ((*ptr == 'R' && *(ptr + 1) == 'S' && *(ptr + 2) == '\0') || 1077*3db86aabSstevel (*ptr == 'F' && *(ptr + 1) == '0' && *(ptr + 2) == '\0') || 1078*3db86aabSstevel (*ptr == 'F' && *(ptr + 1) == '1' && *(ptr + 2) == '\0')) { 1079*3db86aabSstevel switch (payload->event_info.ev_envnot.sub_event) { 1080*3db86aabSstevel case RMC_ENV_FAULT_EVENT: 1081*3db86aabSstevel case RMC_ENV_OK_EVENT: 1082*3db86aabSstevel fan_sysevent(envhdl.name, ptr, 1083*3db86aabSstevel payload->event_info.ev_envnot.sub_event); 1084*3db86aabSstevel break; 1085*3db86aabSstevel default: 1086*3db86aabSstevel break; 1087*3db86aabSstevel } 1088*3db86aabSstevel } 1089*3db86aabSstevel break; 1090*3db86aabSstevel 1091*3db86aabSstevel case RMC_LOG_EVENT: 1092*3db86aabSstevel { 1093*3db86aabSstevel int level = 10; 1094*3db86aabSstevel int flags = SL_NOTE | SL_CONSOLE; 1095*3db86aabSstevel char *message = 1096*3db86aabSstevel (char *)payload->event_info.ev_rmclog.log_record; 1097*3db86aabSstevel 1098*3db86aabSstevel message[ payload->event_info.ev_rmclog.log_record_size] = '\0'; 1099*3db86aabSstevel 1100*3db86aabSstevel /* 1101*3db86aabSstevel * Logs have a 10 character prefix - specifying the severity of 1102*3db86aabSstevel * the event being logged. Thus all the magic number 10s down 1103*3db86aabSstevel * here 1104*3db86aabSstevel */ 1105*3db86aabSstevel if (0 == strncmp("CRITICAL: ", message, 10)) { 1106*3db86aabSstevel message += 10; 1107*3db86aabSstevel level = 0; 1108*3db86aabSstevel flags = SL_FATAL | SL_ERROR | SL_CONSOLE; 1109*3db86aabSstevel } else if (0 == strncmp("MAJOR: ", message, 10)) { 1110*3db86aabSstevel message += 10; 1111*3db86aabSstevel level = 5; 1112*3db86aabSstevel flags = SL_WARN | SL_ERROR | SL_CONSOLE; 1113*3db86aabSstevel } else if (0 == strncmp("MINOR: ", message, 10)) { 1114*3db86aabSstevel message += 10; 1115*3db86aabSstevel level = 10; 1116*3db86aabSstevel flags = SL_NOTE | SL_CONSOLE; 1117*3db86aabSstevel } 1118*3db86aabSstevel 1119*3db86aabSstevel (void) strlog(0, 0, level, flags, message); 1120*3db86aabSstevel break; 1121*3db86aabSstevel } 1122*3db86aabSstevel 1123*3db86aabSstevel default: 1124*3db86aabSstevel return (DDI_INTR_CLAIMED); 1125*3db86aabSstevel } 1126*3db86aabSstevel 1127*3db86aabSstevel return (DDI_INTR_CLAIMED); 1128*3db86aabSstevel } 1129*3db86aabSstevel 1130*3db86aabSstevel /*ARGSUSED*/ 1131*3db86aabSstevel static int 1132*3db86aabSstevel rmclomv_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p) 1133*3db86aabSstevel { 1134*3db86aabSstevel int error = 0; 1135*3db86aabSstevel int instance = getminor(*dev_p); 1136*3db86aabSstevel 1137*3db86aabSstevel if (instance != 0) 1138*3db86aabSstevel return (ENXIO); 1139*3db86aabSstevel 1140*3db86aabSstevel if ((flag & FWRITE) != 0 && (error = drv_priv(cred_p)) != 0) 1141*3db86aabSstevel return (error); 1142*3db86aabSstevel 1143*3db86aabSstevel return (0); 1144*3db86aabSstevel } 1145*3db86aabSstevel 1146*3db86aabSstevel /*ARGSUSED*/ 1147*3db86aabSstevel static int 1148*3db86aabSstevel rmclomv_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 1149*3db86aabSstevel { 1150*3db86aabSstevel return (DDI_SUCCESS); 1151*3db86aabSstevel } 1152*3db86aabSstevel 1153*3db86aabSstevel static int 1154*3db86aabSstevel rmclomv_do_cmd(int req_cmd, int resp_cmd, int resp_len, intptr_t arg_req, 1155*3db86aabSstevel intptr_t arg_res) 1156*3db86aabSstevel { 1157*3db86aabSstevel rmc_comm_msg_t request, *reqp = &request; 1158*3db86aabSstevel rmc_comm_msg_t response, *resp = &response; 1159*3db86aabSstevel int rv = 0; 1160*3db86aabSstevel 1161*3db86aabSstevel bzero((caddr_t)&request, sizeof (request)); 1162*3db86aabSstevel reqp->msg_type = req_cmd; 1163*3db86aabSstevel reqp->msg_buf = (caddr_t)arg_req; 1164*3db86aabSstevel bzero((caddr_t)&response, sizeof (response)); 1165*3db86aabSstevel resp->msg_type = resp_cmd; 1166*3db86aabSstevel resp->msg_buf = (caddr_t)arg_res; 1167*3db86aabSstevel resp->msg_len = resp_len; 1168*3db86aabSstevel 1169*3db86aabSstevel switch (req_cmd) { 1170*3db86aabSstevel case DP_GET_SYSINFO: 1171*3db86aabSstevel resp->msg_len = sizeof (dp_get_sysinfo_r_t); 1172*3db86aabSstevel break; 1173*3db86aabSstevel case DP_GET_EVENT_LOG: 1174*3db86aabSstevel resp->msg_len = sizeof (dp_get_event_log_r_t); 1175*3db86aabSstevel break; 1176*3db86aabSstevel case DP_GET_VOLTS: 1177*3db86aabSstevel reqp->msg_len = sizeof (dp_get_volts_t); 1178*3db86aabSstevel break; 1179*3db86aabSstevel case DP_GET_TEMPERATURES: 1180*3db86aabSstevel reqp->msg_len = sizeof (dp_get_temperatures_t); 1181*3db86aabSstevel break; 1182*3db86aabSstevel case DP_GET_CIRCUIT_BRKS: 1183*3db86aabSstevel reqp->msg_len = sizeof (dp_get_circuit_brks_t); 1184*3db86aabSstevel break; 1185*3db86aabSstevel case DP_GET_FAN_STATUS: 1186*3db86aabSstevel reqp->msg_len = sizeof (dp_get_fan_status_t); 1187*3db86aabSstevel break; 1188*3db86aabSstevel case DP_GET_PSU_STATUS: 1189*3db86aabSstevel reqp->msg_len = sizeof (dp_get_psu_status_t); 1190*3db86aabSstevel break; 1191*3db86aabSstevel case DP_GET_LED_STATE: 1192*3db86aabSstevel reqp->msg_len = sizeof (dp_get_led_state_t); 1193*3db86aabSstevel break; 1194*3db86aabSstevel case DP_SET_LED_STATE: 1195*3db86aabSstevel reqp->msg_len = sizeof (dp_set_led_state_t); 1196*3db86aabSstevel break; 1197*3db86aabSstevel case DP_GET_FRU_STATUS: 1198*3db86aabSstevel reqp->msg_len = sizeof (dp_get_fru_status_t); 1199*3db86aabSstevel break; 1200*3db86aabSstevel case DP_GET_HANDLE_NAME: 1201*3db86aabSstevel reqp->msg_len = sizeof (dp_get_handle_name_t); 1202*3db86aabSstevel break; 1203*3db86aabSstevel case DP_GET_ALARM_STATE: 1204*3db86aabSstevel reqp->msg_len = sizeof (dp_get_alarm_state_t); 1205*3db86aabSstevel break; 1206*3db86aabSstevel case DP_SET_ALARM_STATE: 1207*3db86aabSstevel reqp->msg_len = sizeof (dp_set_alarm_state_t); 1208*3db86aabSstevel break; 1209*3db86aabSstevel case DP_GET_SDP_VERSION: 1210*3db86aabSstevel resp->msg_len = sizeof (dp_get_sdp_version_r_t); 1211*3db86aabSstevel break; 1212*3db86aabSstevel case DP_GET_CHASSIS_SERIALNUM: 1213*3db86aabSstevel reqp->msg_len = 0; 1214*3db86aabSstevel break; 1215*3db86aabSstevel case DP_GET_DATE_TIME: 1216*3db86aabSstevel reqp->msg_len = 0; 1217*3db86aabSstevel break; 1218*3db86aabSstevel default: 1219*3db86aabSstevel return (EINVAL); 1220*3db86aabSstevel } 1221*3db86aabSstevel 1222*3db86aabSstevel rv = rmc_comm_request_response(reqp, resp, 1223*3db86aabSstevel RMCLOMV_DEFAULT_MAX_MBOX_WAIT_TIME); 1224*3db86aabSstevel 1225*3db86aabSstevel if (rv != RCNOERR) { 1226*3db86aabSstevel /* 1227*3db86aabSstevel * RMC returned an error or failed to respond. 1228*3db86aabSstevel * Where the RMC itself is implicated, rmclomv_rmc_error 1229*3db86aabSstevel * is set non-zero. It is cleared after an error free exchange. 1230*3db86aabSstevel * Two failure cases are distinguished: 1231*3db86aabSstevel * RMCLOMV_RMCSTATE_FAILED and RMCLOMV_RMCSTATE_DOWNLOAD. 1232*3db86aabSstevel */ 1233*3db86aabSstevel switch (rv) { 1234*3db86aabSstevel case RCENOSOFTSTATE: 1235*3db86aabSstevel /* invalid/NULL soft state structure */ 1236*3db86aabSstevel return (EIO); 1237*3db86aabSstevel case RCENODATALINK: 1238*3db86aabSstevel /* 1239*3db86aabSstevel * firmware download in progress, 1240*3db86aabSstevel * can you come back later? 1241*3db86aabSstevel */ 1242*3db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_DOWNLOAD; 1243*3db86aabSstevel rmclomv_rmc_state = RMCLOMV_RMCSTATE_DOWNLOAD; 1244*3db86aabSstevel return (EAGAIN); 1245*3db86aabSstevel case RCENOMEM: 1246*3db86aabSstevel /* memory problems */ 1247*3db86aabSstevel return (ENOMEM); 1248*3db86aabSstevel case RCECANTRESEND: 1249*3db86aabSstevel /* resend failed */ 1250*3db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED; 1251*3db86aabSstevel return (EIO); 1252*3db86aabSstevel case RCEMAXRETRIES: 1253*3db86aabSstevel /* reply not received - retries exceeded */ 1254*3db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED; 1255*3db86aabSstevel return (EINTR); 1256*3db86aabSstevel case RCETIMEOUT: 1257*3db86aabSstevel /* reply not received - command has timed out */ 1258*3db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED; 1259*3db86aabSstevel return (EINTR); 1260*3db86aabSstevel case RCEINVCMD: 1261*3db86aabSstevel /* data protocol cmd not supported */ 1262*3db86aabSstevel return (ENOTSUP); 1263*3db86aabSstevel case RCEINVARG: 1264*3db86aabSstevel /* invalid argument(s) */ 1265*3db86aabSstevel return (ENOTSUP); 1266*3db86aabSstevel case RCEGENERIC: 1267*3db86aabSstevel /* generic error */ 1268*3db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED; 1269*3db86aabSstevel return (EIO); 1270*3db86aabSstevel default: 1271*3db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED; 1272*3db86aabSstevel return (EIO); 1273*3db86aabSstevel } 1274*3db86aabSstevel } 1275*3db86aabSstevel 1276*3db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCERROR_NONE; 1277*3db86aabSstevel return (0); 1278*3db86aabSstevel } 1279*3db86aabSstevel 1280*3db86aabSstevel /* 1281*3db86aabSstevel * validate_section_entry checks that the entry at the specified index 1282*3db86aabSstevel * is valid and not duplicated by an entry above. If these tests fail 1283*3db86aabSstevel * the entry is removed and B_FALSE returned. Otherwise returns B_TRUE. 1284*3db86aabSstevel */ 1285*3db86aabSstevel static int 1286*3db86aabSstevel validate_section_entry(rmclomv_cache_section_t *section, int index) 1287*3db86aabSstevel { 1288*3db86aabSstevel int i; 1289*3db86aabSstevel rmclomv_cache_entry_t *entry; 1290*3db86aabSstevel 1291*3db86aabSstevel for (i = index; i < section->num_entries; i++) { 1292*3db86aabSstevel entry = §ion->entry[i]; 1293*3db86aabSstevel if (entry->handle_name.name[0] == '\0') { 1294*3db86aabSstevel cmn_err(CE_WARN, 1295*3db86aabSstevel "rmclomv: empty handle_name, handle 0x%x type %x", 1296*3db86aabSstevel entry->handle, section->sensor_type); 1297*3db86aabSstevel } else if (entry->ind_mask != 0) { 1298*3db86aabSstevel continue; /* skip special entries */ 1299*3db86aabSstevel } else if (entry->handle == DP_NULL_HANDLE) { 1300*3db86aabSstevel cmn_err(CE_WARN, 1301*3db86aabSstevel "rmclomv: null handle id for \"%s\" type %x", 1302*3db86aabSstevel entry->handle_name.name, section->sensor_type); 1303*3db86aabSstevel } else if (i == index) { 1304*3db86aabSstevel continue; 1305*3db86aabSstevel } else if (section->entry[index].handle == entry->handle) { 1306*3db86aabSstevel cmn_err(CE_WARN, 1307*3db86aabSstevel "rmclomv: duplicate handle 0x%x type %x", 1308*3db86aabSstevel entry->handle, section->sensor_type); 1309*3db86aabSstevel } else if (strcmp(entry->handle_name.name, 1310*3db86aabSstevel section->entry[index].handle_name.name) == 0) { 1311*3db86aabSstevel cmn_err(CE_WARN, 1312*3db86aabSstevel "rmclomv: duplicate handle_name \"%s\", " 1313*3db86aabSstevel "handle 0x%x type %x", entry->handle_name.name, 1314*3db86aabSstevel entry->handle, section->sensor_type); 1315*3db86aabSstevel } else 1316*3db86aabSstevel continue; 1317*3db86aabSstevel 1318*3db86aabSstevel /* 1319*3db86aabSstevel * need to remove the entry at index 1320*3db86aabSstevel */ 1321*3db86aabSstevel section->num_entries--; 1322*3db86aabSstevel 1323*3db86aabSstevel for (i = index; i < section->num_entries; i++) { 1324*3db86aabSstevel section->entry[i] = section->entry[i + 1]; 1325*3db86aabSstevel } 1326*3db86aabSstevel 1327*3db86aabSstevel return (B_FALSE); 1328*3db86aabSstevel } 1329*3db86aabSstevel 1330*3db86aabSstevel return (B_TRUE); 1331*3db86aabSstevel } 1332*3db86aabSstevel 1333*3db86aabSstevel /* 1334*3db86aabSstevel * Populate a section containing handles with corresponding names 1335*3db86aabSstevel * The supplied section structure must not be publically visible and the 1336*3db86aabSstevel * name cache must not be locked either (because RMC i/o is required). 1337*3db86aabSstevel * 1338*3db86aabSstevel * This is the place where a sanity check is applied. Entries containing 1339*3db86aabSstevel * duplicate handles, duplicate names or empty names are removed and the 1340*3db86aabSstevel * structure is compacted. As a result num_entries may be reduced. 1341*3db86aabSstevel */ 1342*3db86aabSstevel static int 1343*3db86aabSstevel add_names_to_section(rmclomv_cache_section_t *section) 1344*3db86aabSstevel { 1345*3db86aabSstevel int retval = 0; 1346*3db86aabSstevel int ditched = B_FALSE; 1347*3db86aabSstevel int index; 1348*3db86aabSstevel dp_get_handle_name_r_t handle_name_r; 1349*3db86aabSstevel rmclomv_cache_entry_t *entry; 1350*3db86aabSstevel 1351*3db86aabSstevel for (index = 0; index < section->num_entries; index++) { 1352*3db86aabSstevel entry = §ion->entry[index]; 1353*3db86aabSstevel if (entry->ind_mask != 0) 1354*3db86aabSstevel continue; /* skip special entries */ 1355*3db86aabSstevel handle_name_r.handle = entry->handle; 1356*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_HANDLE_NAME, 1357*3db86aabSstevel DP_GET_HANDLE_NAME_R, sizeof (handle_name_r), 1358*3db86aabSstevel (intptr_t)&handle_name_r, (intptr_t)&handle_name_r); 1359*3db86aabSstevel if (retval == 0) 1360*3db86aabSstevel bcopy(handle_name_r.name, 1361*3db86aabSstevel entry->handle_name.name, DP_MAX_HANDLE_NAME); 1362*3db86aabSstevel } 1363*3db86aabSstevel 1364*3db86aabSstevel /* 1365*3db86aabSstevel * now ditch invalid and duplicate entries 1366*3db86aabSstevel */ 1367*3db86aabSstevel for (index = 0; index < section->num_entries; index++) { 1368*3db86aabSstevel while (validate_section_entry(section, index) == B_FALSE) 1369*3db86aabSstevel ditched = B_TRUE; 1370*3db86aabSstevel } 1371*3db86aabSstevel 1372*3db86aabSstevel if (ditched) 1373*3db86aabSstevel cmn_err(CE_WARN, "Retaining %d nodes of type %d", 1374*3db86aabSstevel section->num_entries, section->sensor_type); 1375*3db86aabSstevel 1376*3db86aabSstevel return (retval); 1377*3db86aabSstevel } 1378*3db86aabSstevel 1379*3db86aabSstevel /* 1380*3db86aabSstevel * The supplied (PSU) cache section is traversed and entries are created 1381*3db86aabSstevel * for the individual indicators belonging to a PSU. These entries are 1382*3db86aabSstevel * placed in a private chain. The caller, subsequently acquires the 1383*3db86aabSstevel * cache lock and copies the chain head to make it public. 1384*3db86aabSstevel * The handle-names for PSU indicators are derived from the parent PSU 1385*3db86aabSstevel * handle-name. 1386*3db86aabSstevel * NOTE: add_names_to_section() may have reduced psu_section->num_entries 1387*3db86aabSstevel * so DON'T USE psu_resp->num_psus 1388*3db86aabSstevel */ 1389*3db86aabSstevel static void 1390*3db86aabSstevel make_psu_subsections(rmclomv_cache_section_t *psu_section, 1391*3db86aabSstevel rmclomv_cache_section_t **chain_head, dp_get_psu_status_r_t *psu_resp) 1392*3db86aabSstevel { 1393*3db86aabSstevel int index; 1394*3db86aabSstevel int subindex = 0; 1395*3db86aabSstevel rmclomv_cache_section_t *subsection; 1396*3db86aabSstevel rmclomv_cache_entry_t *src_entry; 1397*3db86aabSstevel rmclomv_cache_entry_t *dst_entry; 1398*3db86aabSstevel 1399*3db86aabSstevel subsection = create_cache_section(RMCLOMV_VOLT_IND, 1400*3db86aabSstevel RMCLOMV_MAX_VI_PER_PSU * psu_section->num_entries); 1401*3db86aabSstevel for (index = 0; index < psu_section->num_entries; index++) { 1402*3db86aabSstevel src_entry = &psu_section->entry[index]; 1403*3db86aabSstevel if ((psu_resp->psu_status[index].mask & 1404*3db86aabSstevel DP_PSU_INPUT_STATUS) != 0) { 1405*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1406*3db86aabSstevel dst_entry->handle = src_entry->handle; 1407*3db86aabSstevel dst_entry->ind_mask = DP_PSU_INPUT_STATUS; 1408*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1409*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1410*3db86aabSstevel src_entry->handle_name.name, 1411*3db86aabSstevel str_ip_volts_ind); 1412*3db86aabSstevel } 1413*3db86aabSstevel 1414*3db86aabSstevel if ((psu_resp->psu_status[index].mask & 1415*3db86aabSstevel DP_PSU_SEC_INPUT_STATUS) != 0) { 1416*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1417*3db86aabSstevel dst_entry->handle = src_entry->handle; 1418*3db86aabSstevel dst_entry->ind_mask = DP_PSU_SEC_INPUT_STATUS; 1419*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1420*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1421*3db86aabSstevel src_entry->handle_name.name, 1422*3db86aabSstevel str_ip2_volts_ind); 1423*3db86aabSstevel } 1424*3db86aabSstevel 1425*3db86aabSstevel if ((psu_resp->psu_status[index].mask & 1426*3db86aabSstevel DP_PSU_OUTPUT_STATUS) != 0) { 1427*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1428*3db86aabSstevel dst_entry->handle = src_entry->handle; 1429*3db86aabSstevel dst_entry->ind_mask = DP_PSU_OUTPUT_STATUS; 1430*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1431*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1432*3db86aabSstevel src_entry->handle_name.name, 1433*3db86aabSstevel str_ff_pok_ind); 1434*3db86aabSstevel } 1435*3db86aabSstevel 1436*3db86aabSstevel if ((psu_resp->psu_status[index].mask & 1437*3db86aabSstevel DP_PSU_OUTPUT_VLO_STATUS) != 0) { 1438*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1439*3db86aabSstevel dst_entry->handle = src_entry->handle; 1440*3db86aabSstevel dst_entry->ind_mask = DP_PSU_OUTPUT_VLO_STATUS; 1441*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1442*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1443*3db86aabSstevel src_entry->handle_name.name, 1444*3db86aabSstevel str_vlo_volts_ind); 1445*3db86aabSstevel } 1446*3db86aabSstevel 1447*3db86aabSstevel if ((psu_resp->psu_status[index].mask & 1448*3db86aabSstevel DP_PSU_OUTPUT_VHI_STATUS) != 0) { 1449*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1450*3db86aabSstevel dst_entry->handle = src_entry->handle; 1451*3db86aabSstevel dst_entry->ind_mask = DP_PSU_OUTPUT_VHI_STATUS; 1452*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1453*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1454*3db86aabSstevel src_entry->handle_name.name, 1455*3db86aabSstevel str_vhi_volts_ind); 1456*3db86aabSstevel } 1457*3db86aabSstevel } 1458*3db86aabSstevel /* 1459*3db86aabSstevel * Adjust number of entries value in cache section 1460*3db86aabSstevel * to match the facts. 1461*3db86aabSstevel */ 1462*3db86aabSstevel subsection->num_entries = subindex; 1463*3db86aabSstevel add_section(chain_head, subsection); 1464*3db86aabSstevel 1465*3db86aabSstevel subsection = create_cache_section(RMCLOMV_AMP_IND, 1466*3db86aabSstevel RMCLOMV_MAX_CI_PER_PSU * psu_section->num_entries); 1467*3db86aabSstevel subindex = 0; 1468*3db86aabSstevel for (index = 0; index < psu_section->num_entries; index++) { 1469*3db86aabSstevel int mask = psu_resp->psu_status[index].mask; 1470*3db86aabSstevel src_entry = &psu_section->entry[index]; 1471*3db86aabSstevel if ((mask & DP_PSU_OUTPUT_AHI_STATUS) != 0) { 1472*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1473*3db86aabSstevel dst_entry->handle = src_entry->handle; 1474*3db86aabSstevel dst_entry->ind_mask = DP_PSU_OUTPUT_AHI_STATUS; 1475*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1476*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1477*3db86aabSstevel src_entry->handle_name.name, 1478*3db86aabSstevel str_chi_amps_ind); 1479*3db86aabSstevel } 1480*3db86aabSstevel if ((mask & DP_PSU_NR_WARNING) != 0) { 1481*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1482*3db86aabSstevel dst_entry->handle = src_entry->handle; 1483*3db86aabSstevel dst_entry->ind_mask = DP_PSU_NR_WARNING; 1484*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1485*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1486*3db86aabSstevel src_entry->handle_name.name, 1487*3db86aabSstevel str_chi_nr_ind); 1488*3db86aabSstevel } 1489*3db86aabSstevel } 1490*3db86aabSstevel subsection->num_entries = subindex; 1491*3db86aabSstevel add_section(chain_head, subsection); 1492*3db86aabSstevel 1493*3db86aabSstevel subsection = create_cache_section(RMCLOMV_TEMP_IND, 1494*3db86aabSstevel psu_section->num_entries); 1495*3db86aabSstevel subindex = 0; 1496*3db86aabSstevel for (index = 0; index < psu_section->num_entries; index++) { 1497*3db86aabSstevel if ((psu_resp->psu_status[index].mask & 1498*3db86aabSstevel DP_PSU_OVERTEMP_FAULT) != 0) { 1499*3db86aabSstevel src_entry = &psu_section->entry[index]; 1500*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1501*3db86aabSstevel dst_entry->handle = src_entry->handle; 1502*3db86aabSstevel dst_entry->ind_mask = DP_PSU_OVERTEMP_FAULT; 1503*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1504*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1505*3db86aabSstevel src_entry->handle_name.name, 1506*3db86aabSstevel str_ot_tmpr_ind); 1507*3db86aabSstevel } 1508*3db86aabSstevel } 1509*3db86aabSstevel subsection->num_entries = subindex; 1510*3db86aabSstevel add_section(chain_head, subsection); 1511*3db86aabSstevel 1512*3db86aabSstevel subsection = create_cache_section(RMCLOMV_FAN_IND, 1513*3db86aabSstevel RMCLOMV_MAX_FI_PER_PSU * psu_section->num_entries); 1514*3db86aabSstevel subindex = 0; 1515*3db86aabSstevel for (index = 0; index < psu_section->num_entries; index++) { 1516*3db86aabSstevel int mask = psu_resp->psu_status[index].mask; 1517*3db86aabSstevel src_entry = &psu_section->entry[index]; 1518*3db86aabSstevel if ((mask & DP_PSU_FAN_FAULT) != 0) { 1519*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1520*3db86aabSstevel dst_entry->handle = src_entry->handle; 1521*3db86aabSstevel dst_entry->ind_mask = DP_PSU_FAN_FAULT; 1522*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1523*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1524*3db86aabSstevel src_entry->handle_name.name, str_fan_ind); 1525*3db86aabSstevel } 1526*3db86aabSstevel if ((mask & DP_PSU_PDCT_FAN) != 0) { 1527*3db86aabSstevel dst_entry = &subsection->entry[subindex++]; 1528*3db86aabSstevel dst_entry->handle = src_entry->handle; 1529*3db86aabSstevel dst_entry->ind_mask = DP_PSU_PDCT_FAN; 1530*3db86aabSstevel (void) snprintf(dst_entry->handle_name.name, 1531*3db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s", 1532*3db86aabSstevel src_entry->handle_name.name, str_pdct_fan_ind); 1533*3db86aabSstevel } 1534*3db86aabSstevel } 1535*3db86aabSstevel subsection->num_entries = subindex; 1536*3db86aabSstevel add_section(chain_head, subsection); 1537*3db86aabSstevel } 1538*3db86aabSstevel 1539*3db86aabSstevel static void 1540*3db86aabSstevel refresh_name_cache(int force_fail) 1541*3db86aabSstevel { 1542*3db86aabSstevel union { 1543*3db86aabSstevel dp_get_volts_t u_volts_cmd; 1544*3db86aabSstevel dp_get_temperatures_t u_temp_cmd; 1545*3db86aabSstevel dp_get_circuit_brks_t u_ampi_cmd; 1546*3db86aabSstevel dp_get_fan_status_t u_fan_cmd; 1547*3db86aabSstevel dp_get_psu_status_t u_psu_cmd; 1548*3db86aabSstevel dp_get_fru_status_t u_fru_cmd; 1549*3db86aabSstevel dp_get_led_state_t u_led_cmd; 1550*3db86aabSstevel dp_set_led_state_t u_setled_cmd; 1551*3db86aabSstevel dp_get_alarm_state_t u_alarm_cmd; 1552*3db86aabSstevel dp_set_alarm_state_t u_setalarm_cmd; 1553*3db86aabSstevel } rmc_cmdbuf; 1554*3db86aabSstevel 1555*3db86aabSstevel /* defines for accessing union fields */ 1556*3db86aabSstevel #define volts_cmd rmc_cmdbuf.u_volts_cmd 1557*3db86aabSstevel #define temp_cmd rmc_cmdbuf.u_temp_cmd 1558*3db86aabSstevel #define ampi_cmd rmc_cmdbuf.u_ampi_cmd 1559*3db86aabSstevel #define fan_cmd rmc_cmdbuf.u_fan_cmd 1560*3db86aabSstevel #define psu_cmd rmc_cmdbuf.u_psu_cmd 1561*3db86aabSstevel #define fru_cmd rmc_cmdbuf.u_fru_cmd 1562*3db86aabSstevel #define led_cmd rmc_cmdbuf.u_led_cmd 1563*3db86aabSstevel #define setled_cmd rmc_cmdbuf.u_setled_cmd 1564*3db86aabSstevel #define alarm_cmd rmc_cmdbuf.u_alarm_cmd 1565*3db86aabSstevel #define setalarm_cmd rmc_cmdbuf.u_setalarm_cmd 1566*3db86aabSstevel 1567*3db86aabSstevel /* 1568*3db86aabSstevel * Data area to read sensor data into 1569*3db86aabSstevel */ 1570*3db86aabSstevel static union { 1571*3db86aabSstevel char reservation[RMCRESBUFLEN]; 1572*3db86aabSstevel dp_get_volts_r_t u_volts_r; 1573*3db86aabSstevel dp_get_temperatures_r_t u_temp_r; 1574*3db86aabSstevel dp_get_circuit_brks_r_t u_ampi_r; 1575*3db86aabSstevel dp_get_fan_status_r_t u_fan_r; 1576*3db86aabSstevel dp_get_psu_status_r_t u_psu_r; 1577*3db86aabSstevel dp_get_fru_status_r_t u_fru_r; 1578*3db86aabSstevel dp_get_led_state_r_t u_led_r; 1579*3db86aabSstevel dp_set_led_state_r_t u_setled_r; 1580*3db86aabSstevel dp_get_alarm_state_r_t u_alarm_r; 1581*3db86aabSstevel dp_set_alarm_state_r_t u_setalarm_r; 1582*3db86aabSstevel } rmc_sensbuf; 1583*3db86aabSstevel 1584*3db86aabSstevel /* defines for accessing union fields */ 1585*3db86aabSstevel #define volts_r rmc_sensbuf.u_volts_r 1586*3db86aabSstevel #define temp_r rmc_sensbuf.u_temp_r 1587*3db86aabSstevel #define ampi_r rmc_sensbuf.u_ampi_r 1588*3db86aabSstevel #define fan_r rmc_sensbuf.u_fan_r 1589*3db86aabSstevel #define psu_r rmc_sensbuf.u_psu_r 1590*3db86aabSstevel #define fru_r rmc_sensbuf.u_fru_r 1591*3db86aabSstevel #define led_r rmc_sensbuf.u_led_r 1592*3db86aabSstevel #define setled_r rmc_sensbuf.u_setled_r 1593*3db86aabSstevel #define alarm_r rmc_sensbuf.u_alarm_r 1594*3db86aabSstevel #define setalarm_r rmc_sensbuf.u_setalarm_r 1595*3db86aabSstevel 1596*3db86aabSstevel int retval = force_fail; 1597*3db86aabSstevel int retval1 = retval; 1598*3db86aabSstevel int index; 1599*3db86aabSstevel rmclomv_cache_section_t *my_chain = NULL; 1600*3db86aabSstevel rmclomv_cache_section_t *derived_chain = NULL; 1601*3db86aabSstevel rmclomv_cache_section_t *section; 1602*3db86aabSstevel rmclomv_cache_section_t *psu_section; 1603*3db86aabSstevel rmclomv_cache_section_t *fru_section; 1604*3db86aabSstevel dp_get_sysinfo_r_t sysinfo; 1605*3db86aabSstevel rmclomv_cache_entry_t *entry; 1606*3db86aabSstevel 1607*3db86aabSstevel if (retval == 0) { 1608*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_SYSINFO, DP_GET_SYSINFO_R, 1609*3db86aabSstevel sizeof (sysinfo), NULL, (intptr_t)&sysinfo); 1610*3db86aabSstevel } 1611*3db86aabSstevel if (retval == 0) { 1612*3db86aabSstevel fru_cmd.handle = DP_NULL_HANDLE; 1613*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_FRU_STATUS, DP_GET_FRU_STATUS_R, 1614*3db86aabSstevel RMCRESBUFLEN, (intptr_t)&fru_cmd, (intptr_t)&fru_r); 1615*3db86aabSstevel } 1616*3db86aabSstevel if (retval != 0) 1617*3db86aabSstevel fru_r.num_frus = 0; 1618*3db86aabSstevel 1619*3db86aabSstevel /* 1620*3db86aabSstevel * Reserve space for special additional entries in the FRU section 1621*3db86aabSstevel */ 1622*3db86aabSstevel fru_section = create_cache_section(RMCLOMV_HPU_IND, 1623*3db86aabSstevel RMCLOMV_NUM_SPECIAL_FRUS + fru_r.num_frus); 1624*3db86aabSstevel 1625*3db86aabSstevel /* 1626*3db86aabSstevel * add special entry for RMC itself 1627*3db86aabSstevel */ 1628*3db86aabSstevel entry = &fru_section->entry[0]; 1629*3db86aabSstevel (void) snprintf(entry->handle_name.name, sizeof (envmon_handle_t), 1630*3db86aabSstevel "SC"); 1631*3db86aabSstevel entry->handle = 0; 1632*3db86aabSstevel entry->ind_mask = 1; /* flag as a special entry */ 1633*3db86aabSstevel 1634*3db86aabSstevel /* 1635*3db86aabSstevel * populate any other FRU entries 1636*3db86aabSstevel */ 1637*3db86aabSstevel for (index = 0; index < fru_r.num_frus; index++) { 1638*3db86aabSstevel fru_section->entry[RMCLOMV_NUM_SPECIAL_FRUS + index].handle = 1639*3db86aabSstevel fru_r.fru_status[index].handle; 1640*3db86aabSstevel fru_section->entry[RMCLOMV_NUM_SPECIAL_FRUS + index].ind_mask = 1641*3db86aabSstevel 0; 1642*3db86aabSstevel } 1643*3db86aabSstevel 1644*3db86aabSstevel my_chain = fru_section; 1645*3db86aabSstevel 1646*3db86aabSstevel if (retval == 0) { 1647*3db86aabSstevel volts_cmd.handle = DP_NULL_HANDLE; 1648*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_VOLTS, DP_GET_VOLTS_R, 1649*3db86aabSstevel RMCRESBUFLEN, (intptr_t)&volts_cmd, (intptr_t)&volts_r); 1650*3db86aabSstevel } 1651*3db86aabSstevel if (retval == 0) { 1652*3db86aabSstevel section = create_cache_section(RMCLOMV_VOLT_SENS, 1653*3db86aabSstevel volts_r.num_volts); 1654*3db86aabSstevel for (index = 0; index < volts_r.num_volts; index++) { 1655*3db86aabSstevel section->entry[index].handle = 1656*3db86aabSstevel volts_r.volt_status[index].handle; 1657*3db86aabSstevel } 1658*3db86aabSstevel add_section(&my_chain, section); 1659*3db86aabSstevel } 1660*3db86aabSstevel if (retval == 0) { 1661*3db86aabSstevel temp_cmd.handle = DP_NULL_HANDLE; 1662*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_TEMPERATURES, 1663*3db86aabSstevel DP_GET_TEMPERATURES_R, RMCRESBUFLEN, 1664*3db86aabSstevel (intptr_t)&temp_cmd, (intptr_t)&temp_r); 1665*3db86aabSstevel } 1666*3db86aabSstevel if (retval == 0) { 1667*3db86aabSstevel section = create_cache_section(RMCLOMV_TEMP_SENS, 1668*3db86aabSstevel temp_r.num_temps); 1669*3db86aabSstevel for (index = 0; index < temp_r.num_temps; index++) { 1670*3db86aabSstevel section->entry[index].handle = 1671*3db86aabSstevel temp_r.temp_status[index].handle; 1672*3db86aabSstevel } 1673*3db86aabSstevel add_section(&my_chain, section); 1674*3db86aabSstevel } 1675*3db86aabSstevel if (retval == 0) { 1676*3db86aabSstevel fan_cmd.handle = DP_NULL_HANDLE; 1677*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_FAN_STATUS, DP_GET_FAN_STATUS_R, 1678*3db86aabSstevel RMCRESBUFLEN, (intptr_t)&fan_cmd, (intptr_t)&fan_r); 1679*3db86aabSstevel } 1680*3db86aabSstevel if (retval == 0) { 1681*3db86aabSstevel section = create_cache_section(RMCLOMV_FAN_SENS, 1682*3db86aabSstevel fan_r.num_fans); 1683*3db86aabSstevel for (index = 0; index < fan_r.num_fans; index++) { 1684*3db86aabSstevel section->entry[index].handle = 1685*3db86aabSstevel fan_r.fan_status[index].handle; 1686*3db86aabSstevel } 1687*3db86aabSstevel add_section(&my_chain, section); 1688*3db86aabSstevel } 1689*3db86aabSstevel if (retval == 0) { 1690*3db86aabSstevel ampi_cmd.handle = DP_NULL_HANDLE; 1691*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_CIRCUIT_BRKS, 1692*3db86aabSstevel DP_GET_CIRCUIT_BRKS_R, RMCRESBUFLEN, 1693*3db86aabSstevel (intptr_t)&i_cmd, (intptr_t)&i_r); 1694*3db86aabSstevel } 1695*3db86aabSstevel if (retval == 0) { 1696*3db86aabSstevel section = create_cache_section(RMCLOMV_AMP_IND, 1697*3db86aabSstevel ampi_r.num_circuit_brks); 1698*3db86aabSstevel for (index = 0; index < ampi_r.num_circuit_brks; index++) { 1699*3db86aabSstevel section->entry[index].handle = 1700*3db86aabSstevel ampi_r.circuit_brk_status[index].handle; 1701*3db86aabSstevel } 1702*3db86aabSstevel add_section(&my_chain, section); 1703*3db86aabSstevel } 1704*3db86aabSstevel if (retval == 0) { 1705*3db86aabSstevel led_cmd.handle = DP_NULL_HANDLE; 1706*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_LED_STATE, DP_GET_LED_STATE_R, 1707*3db86aabSstevel RMCRESBUFLEN, (intptr_t)&led_cmd, (intptr_t)&led_r); 1708*3db86aabSstevel } 1709*3db86aabSstevel if (retval == 0) { 1710*3db86aabSstevel section = create_cache_section(RMCLOMV_LED_IND, 1711*3db86aabSstevel led_r.num_leds); 1712*3db86aabSstevel for (index = 0; index < led_r.num_leds; index++) { 1713*3db86aabSstevel section->entry[index].handle = 1714*3db86aabSstevel led_r.led_state[index].handle; 1715*3db86aabSstevel } 1716*3db86aabSstevel add_section(&my_chain, section); 1717*3db86aabSstevel } 1718*3db86aabSstevel /* 1719*3db86aabSstevel * The command DP_GET_ALARM_STATE may not be valid on 1720*3db86aabSstevel * some RMC versions, so we ignore the return value 1721*3db86aabSstevel * and proceed 1722*3db86aabSstevel */ 1723*3db86aabSstevel if (retval == 0) { 1724*3db86aabSstevel alarm_cmd.handle = DP_NULL_HANDLE; 1725*3db86aabSstevel retval1 = rmclomv_do_cmd(DP_GET_ALARM_STATE, 1726*3db86aabSstevel DP_GET_ALARM_STATE_R, RMCRESBUFLEN, 1727*3db86aabSstevel (intptr_t)&alarm_cmd, (intptr_t)&alarm_r); 1728*3db86aabSstevel if ((retval1 == 0) && alarm_r.num_alarms) { 1729*3db86aabSstevel section = create_cache_section(RMCLOMV_ALARM_IND, 1730*3db86aabSstevel alarm_r.num_alarms); 1731*3db86aabSstevel for (index = 0; index < alarm_r.num_alarms; index++) { 1732*3db86aabSstevel section->entry[index].handle = 1733*3db86aabSstevel alarm_r.alarm_state[index].handle; 1734*3db86aabSstevel } 1735*3db86aabSstevel add_section(&my_chain, section); 1736*3db86aabSstevel } 1737*3db86aabSstevel } 1738*3db86aabSstevel if (retval == 0) { 1739*3db86aabSstevel psu_cmd.handle = DP_NULL_HANDLE; 1740*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_PSU_STATUS, DP_GET_PSU_STATUS_R, 1741*3db86aabSstevel RMCRESBUFLEN, (intptr_t)&psu_cmd, (intptr_t)&psu_r); 1742*3db86aabSstevel } 1743*3db86aabSstevel if (retval == 0) { 1744*3db86aabSstevel /* 1745*3db86aabSstevel * WARNING: 1746*3db86aabSstevel * ======= 1747*3db86aabSstevel * The PSUs must be probed last so that the response data 1748*3db86aabSstevel * (psu_r) is available for make_psu_subsections() below. 1749*3db86aabSstevel * Note that all the responses share the same data area 1750*3db86aabSstevel * which is declared as a union. 1751*3db86aabSstevel */ 1752*3db86aabSstevel psu_section = create_cache_section(RMCLOMV_PSU_IND, 1753*3db86aabSstevel psu_r.num_psus); 1754*3db86aabSstevel for (index = 0; index < psu_r.num_psus; index++) { 1755*3db86aabSstevel psu_section->entry[index].handle = 1756*3db86aabSstevel psu_r.psu_status[index].handle; 1757*3db86aabSstevel } 1758*3db86aabSstevel add_section(&my_chain, psu_section); 1759*3db86aabSstevel } 1760*3db86aabSstevel if (retval == 0) { 1761*3db86aabSstevel for (section = my_chain; 1762*3db86aabSstevel section != NULL; 1763*3db86aabSstevel section = section->next_section) { 1764*3db86aabSstevel retval = add_names_to_section(section); 1765*3db86aabSstevel if (retval != 0) { 1766*3db86aabSstevel break; 1767*3db86aabSstevel } 1768*3db86aabSstevel } 1769*3db86aabSstevel } 1770*3db86aabSstevel 1771*3db86aabSstevel /* 1772*3db86aabSstevel * now add nodes derived from PSUs 1773*3db86aabSstevel */ 1774*3db86aabSstevel if (retval == 0) { 1775*3db86aabSstevel make_psu_subsections(psu_section, &derived_chain, &psu_r); 1776*3db86aabSstevel /* 1777*3db86aabSstevel * name cache sections all set, exchange new for old 1778*3db86aabSstevel */ 1779*3db86aabSstevel rmclomv_reset_cache(my_chain, derived_chain, &sysinfo); 1780*3db86aabSstevel } else { 1781*3db86aabSstevel /* 1782*3db86aabSstevel * RMC is not responding, ditch any existing cache 1783*3db86aabSstevel * and just leave the special SC FRU node 1784*3db86aabSstevel */ 1785*3db86aabSstevel rmclomv_reset_cache(my_chain, NULL, NULL); 1786*3db86aabSstevel } 1787*3db86aabSstevel } 1788*3db86aabSstevel 1789*3db86aabSstevel static void 1790*3db86aabSstevel set_val_unav(envmon_sensor_t *sensor) 1791*3db86aabSstevel { 1792*3db86aabSstevel sensor->value = ENVMON_VAL_UNAVAILABLE; 1793*3db86aabSstevel sensor->lowthresholds.warning = ENVMON_VAL_UNAVAILABLE; 1794*3db86aabSstevel sensor->lowthresholds.shutdown = ENVMON_VAL_UNAVAILABLE; 1795*3db86aabSstevel sensor->lowthresholds.poweroff = ENVMON_VAL_UNAVAILABLE; 1796*3db86aabSstevel sensor->highthresholds.warning = ENVMON_VAL_UNAVAILABLE; 1797*3db86aabSstevel sensor->highthresholds.shutdown = ENVMON_VAL_UNAVAILABLE; 1798*3db86aabSstevel sensor->highthresholds.poweroff = ENVMON_VAL_UNAVAILABLE; 1799*3db86aabSstevel } 1800*3db86aabSstevel 1801*3db86aabSstevel static void 1802*3db86aabSstevel set_fan_unav(envmon_fan_t *fan) 1803*3db86aabSstevel { 1804*3db86aabSstevel fan->speed = ENVMON_VAL_UNAVAILABLE; 1805*3db86aabSstevel fan->units[0] = '\0'; 1806*3db86aabSstevel fan->lowthresholds.warning = ENVMON_VAL_UNAVAILABLE; 1807*3db86aabSstevel fan->lowthresholds.shutdown = ENVMON_VAL_UNAVAILABLE; 1808*3db86aabSstevel fan->lowthresholds.poweroff = ENVMON_VAL_UNAVAILABLE; 1809*3db86aabSstevel } 1810*3db86aabSstevel 1811*3db86aabSstevel static int 1812*3db86aabSstevel do_psu_cmd(intptr_t arg, int mode, envmon_indicator_t *env_ind, 1813*3db86aabSstevel dp_get_psu_status_t *rmc_psu, dp_get_psu_status_r_t *rmc_psu_r, 1814*3db86aabSstevel int detector_type) 1815*3db86aabSstevel { 1816*3db86aabSstevel int index; 1817*3db86aabSstevel uint16_t sensor_status; 1818*3db86aabSstevel rmclomv_cache_section_t *section; 1819*3db86aabSstevel uint16_t indicator_mask; 1820*3db86aabSstevel 1821*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)env_ind, 1822*3db86aabSstevel sizeof (envmon_indicator_t), mode) != 0) 1823*3db86aabSstevel return (EFAULT); 1824*3db86aabSstevel 1825*3db86aabSstevel /* ensure we've got PSU handles cached */ 1826*3db86aabSstevel LOCK_CACHE 1827*3db86aabSstevel 1828*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 1829*3db86aabSstevel section = rmclomv_find_section(rmclomv_subcache, detector_type); 1830*3db86aabSstevel if (env_ind->id.name[0] == '\0') { 1831*3db86aabSstevel /* request for first handle */ 1832*3db86aabSstevel if ((section == NULL) || (section->num_entries == 0)) 1833*3db86aabSstevel env_ind->next_id.name[0] = '\0'; 1834*3db86aabSstevel else 1835*3db86aabSstevel env_ind->next_id = section->entry[0].handle_name; 1836*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 1837*3db86aabSstevel } else { 1838*3db86aabSstevel /* ensure name is properly terminated */ 1839*3db86aabSstevel env_ind->id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 1840*3db86aabSstevel if ((section == NULL) || (get_sensor_by_name(section, 1841*3db86aabSstevel env_ind->id.name, &index)) != 0) { 1842*3db86aabSstevel env_ind->next_id.name[0] = '\0'; 1843*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 1844*3db86aabSstevel } else if (index + 1 < section->num_entries) 1845*3db86aabSstevel env_ind->next_id = 1846*3db86aabSstevel section->entry[index + 1].handle_name; 1847*3db86aabSstevel else 1848*3db86aabSstevel env_ind->next_id.name[0] = '\0'; 1849*3db86aabSstevel } 1850*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 1851*3db86aabSstevel /* 1852*3db86aabSstevel * user correctly identified a sensor, note its 1853*3db86aabSstevel * handle value and request the indicator status 1854*3db86aabSstevel */ 1855*3db86aabSstevel rmc_psu->handle = section->entry[index].handle; 1856*3db86aabSstevel indicator_mask = section->entry[index].ind_mask; 1857*3db86aabSstevel } 1858*3db86aabSstevel 1859*3db86aabSstevel RELEASE_CACHE 1860*3db86aabSstevel 1861*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error || 1862*3db86aabSstevel rmclomv_do_cmd(DP_GET_PSU_STATUS, DP_GET_PSU_STATUS_R, 1863*3db86aabSstevel sizeof (dp_get_psu_status_r_t), (intptr_t)rmc_psu, 1864*3db86aabSstevel (intptr_t)rmc_psu_r) != 0)) { 1865*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 1866*3db86aabSstevel } 1867*3db86aabSstevel if ((env_ind->sensor_status = sensor_status) == ENVMON_SENSOR_OK) { 1868*3db86aabSstevel /* 1869*3db86aabSstevel * copy results into buffer for user 1870*3db86aabSstevel */ 1871*3db86aabSstevel if ((rmc_psu_r->psu_status[0].flag & DP_PSU_PRESENCE) == 0) 1872*3db86aabSstevel env_ind->sensor_status |= ENVMON_NOT_PRESENT; 1873*3db86aabSstevel if (rmc_psu_r->psu_status[0].sensor_status != 1874*3db86aabSstevel DP_SENSOR_DATA_AVAILABLE) 1875*3db86aabSstevel env_ind->sensor_status |= ENVMON_INACCESSIBLE; 1876*3db86aabSstevel env_ind->condition = 1877*3db86aabSstevel (rmc_psu_r->psu_status[0].flag & indicator_mask) == 0 ? 1878*3db86aabSstevel 0 : 1; 1879*3db86aabSstevel } 1880*3db86aabSstevel 1881*3db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) 1882*3db86aabSstevel env_ind->sensor_status = ENVMON_INACCESSIBLE; 1883*3db86aabSstevel 1884*3db86aabSstevel if (ddi_copyout((caddr_t)env_ind, (caddr_t)arg, 1885*3db86aabSstevel sizeof (envmon_indicator_t), mode) != 0) 1886*3db86aabSstevel return (EFAULT); 1887*3db86aabSstevel 1888*3db86aabSstevel return (0); 1889*3db86aabSstevel } 1890*3db86aabSstevel 1891*3db86aabSstevel /*ARGSUSED*/ 1892*3db86aabSstevel static int 1893*3db86aabSstevel rmclomv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p, 1894*3db86aabSstevel int *rval_p) 1895*3db86aabSstevel { 1896*3db86aabSstevel int instance = getminor(dev); 1897*3db86aabSstevel envmon_sysinfo_t lomv_sysinfo; 1898*3db86aabSstevel union { 1899*3db86aabSstevel envmon_sensor_t u_env_sensor; 1900*3db86aabSstevel envmon_indicator_t u_env_ind; 1901*3db86aabSstevel envmon_fan_t u_env_fan; 1902*3db86aabSstevel envmon_led_info_t u_env_ledinfo; 1903*3db86aabSstevel envmon_led_ctl_t u_env_ledctl; 1904*3db86aabSstevel envmon_hpu_t u_env_hpu; 1905*3db86aabSstevel envmon_alarm_info_t u_env_alarminfo; 1906*3db86aabSstevel envmon_alarm_ctl_t u_env_alarmctl; 1907*3db86aabSstevel } env_buf; 1908*3db86aabSstevel #define env_sensor env_buf.u_env_sensor 1909*3db86aabSstevel #define env_ind env_buf.u_env_ind 1910*3db86aabSstevel #define env_fan env_buf.u_env_fan 1911*3db86aabSstevel #define env_ledinfo env_buf.u_env_ledinfo 1912*3db86aabSstevel #define env_ledctl env_buf.u_env_ledctl 1913*3db86aabSstevel #define env_hpu env_buf.u_env_hpu 1914*3db86aabSstevel #define env_alarminfo env_buf.u_env_alarminfo 1915*3db86aabSstevel #define env_alarmctl env_buf.u_env_alarmctl 1916*3db86aabSstevel 1917*3db86aabSstevel union { 1918*3db86aabSstevel dp_get_volts_t u_rmc_volts; 1919*3db86aabSstevel dp_get_temperatures_t u_rmc_temp; 1920*3db86aabSstevel dp_get_circuit_brks_t u_rmc_ampi; 1921*3db86aabSstevel dp_get_fan_status_t u_rmc_fan; 1922*3db86aabSstevel dp_get_psu_status_t u_rmc_psu; 1923*3db86aabSstevel dp_get_fru_status_t u_rmc_fru; 1924*3db86aabSstevel dp_get_led_state_t u_rmc_led; 1925*3db86aabSstevel dp_set_led_state_t u_rmc_setled; 1926*3db86aabSstevel dp_get_alarm_state_t u_rmc_alarm; 1927*3db86aabSstevel dp_set_alarm_state_t u_rmc_setalarm; 1928*3db86aabSstevel } rmc_reqbuf; 1929*3db86aabSstevel #define rmc_volts rmc_reqbuf.u_rmc_volts 1930*3db86aabSstevel #define rmc_temp rmc_reqbuf.u_rmc_temp 1931*3db86aabSstevel #define rmc_ampi rmc_reqbuf.u_rmc_ampi 1932*3db86aabSstevel #define rmc_fan rmc_reqbuf.u_rmc_fan 1933*3db86aabSstevel #define rmc_psu rmc_reqbuf.u_rmc_psu 1934*3db86aabSstevel #define rmc_fru rmc_reqbuf.u_rmc_fru 1935*3db86aabSstevel #define rmc_led rmc_reqbuf.u_rmc_led 1936*3db86aabSstevel #define rmc_setled rmc_reqbuf.u_rmc_setled 1937*3db86aabSstevel #define rmc_alarm rmc_reqbuf.u_rmc_alarm 1938*3db86aabSstevel #define rmc_setalarm rmc_reqbuf.u_rmc_setalarm 1939*3db86aabSstevel 1940*3db86aabSstevel union { 1941*3db86aabSstevel dp_get_volts_r_t u_rmc_volts_r; 1942*3db86aabSstevel dp_get_temperatures_r_t u_rmc_temp_r; 1943*3db86aabSstevel dp_get_circuit_brks_r_t u_rmc_ampi_r; 1944*3db86aabSstevel dp_get_fan_status_r_t u_rmc_fan_r; 1945*3db86aabSstevel dp_get_psu_status_r_t u_rmc_psu_r; 1946*3db86aabSstevel dp_get_fru_status_r_t u_rmc_fru_r; 1947*3db86aabSstevel dp_get_led_state_r_t u_rmc_led_r; 1948*3db86aabSstevel dp_set_led_state_r_t u_rmc_setled_r; 1949*3db86aabSstevel dp_get_alarm_state_r_t u_rmc_alarm_r; 1950*3db86aabSstevel dp_set_alarm_state_r_t u_rmc_setalarm_r; 1951*3db86aabSstevel dp_get_sdp_version_r_t u_rmc_sdpversion_r; 1952*3db86aabSstevel dp_get_serialnum_r_t u_rmc_serialnum_r; 1953*3db86aabSstevel } rmc_resbuf; 1954*3db86aabSstevel #define rmc_volts_r rmc_resbuf.u_rmc_volts_r 1955*3db86aabSstevel #define rmc_temp_r rmc_resbuf.u_rmc_temp_r 1956*3db86aabSstevel #define rmc_ampi_r rmc_resbuf.u_rmc_ampi_r 1957*3db86aabSstevel #define rmc_fan_r rmc_resbuf.u_rmc_fan_r 1958*3db86aabSstevel #define rmc_psu_r rmc_resbuf.u_rmc_psu_r 1959*3db86aabSstevel #define rmc_fru_r rmc_resbuf.u_rmc_fru_r 1960*3db86aabSstevel #define rmc_led_r rmc_resbuf.u_rmc_led_r 1961*3db86aabSstevel #define rmc_setled_r rmc_resbuf.u_rmc_setled_r 1962*3db86aabSstevel #define rmc_alarm_r rmc_resbuf.u_rmc_alarm_r 1963*3db86aabSstevel #define rmc_setalarm_r rmc_resbuf.u_rmc_setalarm_r 1964*3db86aabSstevel #define rmc_sdpver_r rmc_resbuf.u_rmc_sdpversion_r 1965*3db86aabSstevel #define rmc_serialnum_r rmc_resbuf.u_rmc_serialnum_r 1966*3db86aabSstevel 1967*3db86aabSstevel int retval = 0; 1968*3db86aabSstevel int special = 0; 1969*3db86aabSstevel int index; 1970*3db86aabSstevel uint16_t sensor_status; 1971*3db86aabSstevel rmclomv_cache_section_t *section; 1972*3db86aabSstevel envmon_chassis_t chassis; 1973*3db86aabSstevel 1974*3db86aabSstevel if (instance != 0) 1975*3db86aabSstevel return (ENXIO); 1976*3db86aabSstevel 1977*3db86aabSstevel switch (cmd) { 1978*3db86aabSstevel case ENVMONIOCSYSINFO: 1979*3db86aabSstevel 1980*3db86aabSstevel LOCK_CACHE 1981*3db86aabSstevel 1982*3db86aabSstevel /* 1983*3db86aabSstevel * A number of OK/not_OK indicators are supported by PSUs 1984*3db86aabSstevel * (voltage, current, fan, temperature). So the maximum 1985*3db86aabSstevel * number of such indicators relates to the maximum number 1986*3db86aabSstevel * of power-supplies. 1987*3db86aabSstevel */ 1988*3db86aabSstevel if (rmclomv_sysinfo_valid) { 1989*3db86aabSstevel lomv_sysinfo.maxVoltSens = rmclomv_sysinfo_data.maxVolt; 1990*3db86aabSstevel lomv_sysinfo.maxVoltInd = 1991*3db86aabSstevel RMCLOMV_MAX_VI_PER_PSU * 1992*3db86aabSstevel rmclomv_sysinfo_data.maxPSU; 1993*3db86aabSstevel /* 1994*3db86aabSstevel * the ALOM-Solaris interface does not include 1995*3db86aabSstevel * amp sensors, so we can hard code this value 1996*3db86aabSstevel */ 1997*3db86aabSstevel lomv_sysinfo.maxAmpSens = 0; 1998*3db86aabSstevel lomv_sysinfo.maxAmpInd = 1999*3db86aabSstevel rmclomv_sysinfo_data.maxCircuitBrks + 2000*3db86aabSstevel (RMCLOMV_MAX_CI_PER_PSU * 2001*3db86aabSstevel rmclomv_sysinfo_data.maxPSU); 2002*3db86aabSstevel lomv_sysinfo.maxTempSens = rmclomv_sysinfo_data.maxTemp; 2003*3db86aabSstevel lomv_sysinfo.maxTempInd = 2004*3db86aabSstevel (RMCLOMV_MAX_TI_PER_PSU * 2005*3db86aabSstevel rmclomv_sysinfo_data.maxPSU); 2006*3db86aabSstevel lomv_sysinfo.maxFanSens = rmclomv_sysinfo_data.maxFan; 2007*3db86aabSstevel lomv_sysinfo.maxFanInd = 2008*3db86aabSstevel RMCLOMV_MAX_FI_PER_PSU * 2009*3db86aabSstevel rmclomv_sysinfo_data.maxPSU; 2010*3db86aabSstevel lomv_sysinfo.maxLED = rmclomv_sysinfo_data.maxLED; 2011*3db86aabSstevel lomv_sysinfo.maxHPU = RMCLOMV_NUM_SPECIAL_FRUS + 2012*3db86aabSstevel rmclomv_sysinfo_data.maxFRU; 2013*3db86aabSstevel } else { 2014*3db86aabSstevel bzero(&lomv_sysinfo, sizeof (lomv_sysinfo)); 2015*3db86aabSstevel lomv_sysinfo.maxHPU = 1; /* just the SC node */ 2016*3db86aabSstevel } 2017*3db86aabSstevel 2018*3db86aabSstevel RELEASE_CACHE 2019*3db86aabSstevel 2020*3db86aabSstevel if (ddi_copyout((caddr_t)&lomv_sysinfo, (caddr_t)arg, 2021*3db86aabSstevel sizeof (lomv_sysinfo), mode) != 0) 2022*3db86aabSstevel return (EFAULT); 2023*3db86aabSstevel break; 2024*3db86aabSstevel 2025*3db86aabSstevel case ENVMONIOCVOLTSENSOR: 2026*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_sensor, 2027*3db86aabSstevel sizeof (envmon_sensor_t), mode) != 0) 2028*3db86aabSstevel return (EFAULT); 2029*3db86aabSstevel 2030*3db86aabSstevel /* see if we've got volts handles cached */ 2031*3db86aabSstevel LOCK_CACHE 2032*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 2033*3db86aabSstevel 2034*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2035*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2036*3db86aabSstevel RMCLOMV_VOLT_SENS)) == NULL)) { 2037*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2038*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2039*3db86aabSstevel } else if (env_sensor.id.name[0] == '\0') { 2040*3db86aabSstevel /* request for first handle */ 2041*3db86aabSstevel if (section->num_entries == 0) 2042*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2043*3db86aabSstevel else 2044*3db86aabSstevel env_sensor.next_id = 2045*3db86aabSstevel section->entry[0].handle_name; 2046*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2047*3db86aabSstevel } else { 2048*3db86aabSstevel /* ensure name is properly terminated */ 2049*3db86aabSstevel env_sensor.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2050*3db86aabSstevel if (get_sensor_by_name(section, env_sensor.id.name, 2051*3db86aabSstevel &index) != 0) { 2052*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2053*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2054*3db86aabSstevel } else if (index + 1 < section->num_entries) 2055*3db86aabSstevel env_sensor.next_id = 2056*3db86aabSstevel section->entry[index + 1].handle_name; 2057*3db86aabSstevel else 2058*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2059*3db86aabSstevel } 2060*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 2061*3db86aabSstevel /* 2062*3db86aabSstevel * user correctly identified a sensor, note its 2063*3db86aabSstevel * handle value and request the sensor value 2064*3db86aabSstevel */ 2065*3db86aabSstevel rmc_volts.handle = section->entry[index].handle; 2066*3db86aabSstevel } 2067*3db86aabSstevel RELEASE_CACHE 2068*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error || 2069*3db86aabSstevel rmclomv_do_cmd(DP_GET_VOLTS, DP_GET_VOLTS_R, 2070*3db86aabSstevel sizeof (rmc_volts_r), (intptr_t)&rmc_volts, 2071*3db86aabSstevel (intptr_t)&rmc_volts_r) != 0)) { 2072*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 2073*3db86aabSstevel } 2074*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && 2075*3db86aabSstevel (rmc_volts_r.volt_status[0].sensor_status == 2076*3db86aabSstevel DP_SENSOR_NOT_PRESENT)) { 2077*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2078*3db86aabSstevel } 2079*3db86aabSstevel if ((env_sensor.sensor_status = sensor_status) == 2080*3db86aabSstevel ENVMON_SENSOR_OK) { 2081*3db86aabSstevel /* 2082*3db86aabSstevel * copy results into buffer for user 2083*3db86aabSstevel */ 2084*3db86aabSstevel if (rmc_volts_r.volt_status[0].sensor_status != 2085*3db86aabSstevel DP_SENSOR_DATA_AVAILABLE) 2086*3db86aabSstevel env_sensor.sensor_status = ENVMON_INACCESSIBLE; 2087*3db86aabSstevel env_sensor.value = 2088*3db86aabSstevel rmc_volts_r.volt_status[0].reading; 2089*3db86aabSstevel env_sensor.lowthresholds.warning = 2090*3db86aabSstevel rmc_volts_r.volt_status[0].low_warning; 2091*3db86aabSstevel env_sensor.lowthresholds.shutdown = 2092*3db86aabSstevel rmc_volts_r.volt_status[0].low_soft_shutdown; 2093*3db86aabSstevel env_sensor.lowthresholds.poweroff = 2094*3db86aabSstevel rmc_volts_r.volt_status[0].low_hard_shutdown; 2095*3db86aabSstevel env_sensor.highthresholds.warning = 2096*3db86aabSstevel rmc_volts_r.volt_status[0].high_warning; 2097*3db86aabSstevel env_sensor.highthresholds.shutdown = 2098*3db86aabSstevel rmc_volts_r.volt_status[0].high_soft_shutdown; 2099*3db86aabSstevel env_sensor.highthresholds.poweroff = 2100*3db86aabSstevel rmc_volts_r.volt_status[0].high_hard_shutdown; 2101*3db86aabSstevel } 2102*3db86aabSstevel if (env_sensor.sensor_status != ENVMON_SENSOR_OK || 2103*3db86aabSstevel rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) 2104*3db86aabSstevel set_val_unav(&env_sensor); 2105*3db86aabSstevel 2106*3db86aabSstevel if (ddi_copyout((caddr_t)&env_sensor, (caddr_t)arg, 2107*3db86aabSstevel sizeof (envmon_sensor_t), mode) != 0) 2108*3db86aabSstevel return (EFAULT); 2109*3db86aabSstevel break; 2110*3db86aabSstevel 2111*3db86aabSstevel case ENVMONIOCVOLTIND: 2112*3db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, &rmc_psu, &rmc_psu_r, 2113*3db86aabSstevel RMCLOMV_VOLT_IND)); 2114*3db86aabSstevel 2115*3db86aabSstevel case ENVMONIOCTEMPIND: 2116*3db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, &rmc_psu, &rmc_psu_r, 2117*3db86aabSstevel RMCLOMV_TEMP_IND)); 2118*3db86aabSstevel 2119*3db86aabSstevel case ENVMONIOCFANIND: 2120*3db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, &rmc_psu, &rmc_psu_r, 2121*3db86aabSstevel RMCLOMV_FAN_IND)); 2122*3db86aabSstevel 2123*3db86aabSstevel case ENVMONIOCAMPSENSOR: 2124*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_sensor, 2125*3db86aabSstevel sizeof (envmon_sensor_t), mode) != 0) 2126*3db86aabSstevel return (EFAULT); 2127*3db86aabSstevel 2128*3db86aabSstevel env_sensor.sensor_status = ENVMON_NOT_PRESENT; 2129*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2130*3db86aabSstevel 2131*3db86aabSstevel if (ddi_copyout((caddr_t)&env_sensor, (caddr_t)arg, 2132*3db86aabSstevel sizeof (envmon_sensor_t), mode) != 0) 2133*3db86aabSstevel return (EFAULT); 2134*3db86aabSstevel break; 2135*3db86aabSstevel 2136*3db86aabSstevel case ENVMONIOCTEMPSENSOR: 2137*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_sensor, 2138*3db86aabSstevel sizeof (envmon_sensor_t), mode) != 0) 2139*3db86aabSstevel return (EFAULT); 2140*3db86aabSstevel 2141*3db86aabSstevel /* see if we've got temperature handles cached */ 2142*3db86aabSstevel LOCK_CACHE 2143*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 2144*3db86aabSstevel 2145*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2146*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2147*3db86aabSstevel RMCLOMV_TEMP_SENS)) == NULL)) { 2148*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2149*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2150*3db86aabSstevel } else if (env_sensor.id.name[0] == '\0') { 2151*3db86aabSstevel /* request for first handle */ 2152*3db86aabSstevel if (section->num_entries == 0) 2153*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2154*3db86aabSstevel else 2155*3db86aabSstevel env_sensor.next_id = 2156*3db86aabSstevel section->entry[0].handle_name; 2157*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2158*3db86aabSstevel } else { 2159*3db86aabSstevel /* ensure name is properly terminated */ 2160*3db86aabSstevel env_sensor.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2161*3db86aabSstevel if (get_sensor_by_name(section, env_sensor.id.name, 2162*3db86aabSstevel &index) != 0) { 2163*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2164*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2165*3db86aabSstevel } else if (index + 1 < section->num_entries) 2166*3db86aabSstevel env_sensor.next_id = 2167*3db86aabSstevel section->entry[index + 1].handle_name; 2168*3db86aabSstevel else 2169*3db86aabSstevel env_sensor.next_id.name[0] = '\0'; 2170*3db86aabSstevel } 2171*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 2172*3db86aabSstevel /* 2173*3db86aabSstevel * user correctly identified a sensor, note its 2174*3db86aabSstevel * handle value and request the sensor value 2175*3db86aabSstevel */ 2176*3db86aabSstevel rmc_temp.handle = section->entry[index].handle; 2177*3db86aabSstevel } 2178*3db86aabSstevel RELEASE_CACHE 2179*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error || 2180*3db86aabSstevel rmclomv_do_cmd(DP_GET_TEMPERATURES, DP_GET_TEMPERATURES_R, 2181*3db86aabSstevel sizeof (rmc_temp_r), (intptr_t)&rmc_temp, 2182*3db86aabSstevel (intptr_t)&rmc_temp_r) != 0)) { 2183*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 2184*3db86aabSstevel } 2185*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && 2186*3db86aabSstevel (rmc_temp_r.temp_status[0].sensor_status == 2187*3db86aabSstevel DP_SENSOR_NOT_PRESENT)) { 2188*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2189*3db86aabSstevel } 2190*3db86aabSstevel if ((env_sensor.sensor_status = sensor_status) == 2191*3db86aabSstevel ENVMON_SENSOR_OK) { 2192*3db86aabSstevel /* 2193*3db86aabSstevel * copy results into buffer for user 2194*3db86aabSstevel */ 2195*3db86aabSstevel if (rmc_temp_r.temp_status[0].sensor_status != 2196*3db86aabSstevel DP_SENSOR_DATA_AVAILABLE) 2197*3db86aabSstevel env_sensor.sensor_status = ENVMON_INACCESSIBLE; 2198*3db86aabSstevel env_sensor.value = 2199*3db86aabSstevel rmc_temp_r.temp_status[0].value; 2200*3db86aabSstevel env_sensor.lowthresholds.warning = 2201*3db86aabSstevel rmc_temp_r.temp_status[0].low_warning; 2202*3db86aabSstevel env_sensor.lowthresholds.shutdown = 2203*3db86aabSstevel rmc_temp_r.temp_status[0].low_soft_shutdown; 2204*3db86aabSstevel env_sensor.lowthresholds.poweroff = 2205*3db86aabSstevel rmc_temp_r.temp_status[0].low_hard_shutdown; 2206*3db86aabSstevel env_sensor.highthresholds.warning = 2207*3db86aabSstevel rmc_temp_r.temp_status[0].high_warning; 2208*3db86aabSstevel env_sensor.highthresholds.shutdown = 2209*3db86aabSstevel rmc_temp_r.temp_status[0].high_soft_shutdown; 2210*3db86aabSstevel env_sensor.highthresholds.poweroff = 2211*3db86aabSstevel rmc_temp_r.temp_status[0].high_hard_shutdown; 2212*3db86aabSstevel } 2213*3db86aabSstevel if (env_sensor.sensor_status != ENVMON_SENSOR_OK || 2214*3db86aabSstevel rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) 2215*3db86aabSstevel set_val_unav(&env_sensor); 2216*3db86aabSstevel 2217*3db86aabSstevel if (ddi_copyout((caddr_t)&env_sensor, (caddr_t)arg, 2218*3db86aabSstevel sizeof (envmon_sensor_t), mode) != 0) 2219*3db86aabSstevel return (EFAULT); 2220*3db86aabSstevel break; 2221*3db86aabSstevel 2222*3db86aabSstevel 2223*3db86aabSstevel case ENVMONIOCFAN: 2224*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_fan, 2225*3db86aabSstevel sizeof (envmon_fan_t), mode) != 0) 2226*3db86aabSstevel return (EFAULT); 2227*3db86aabSstevel 2228*3db86aabSstevel /* see if we've got fan handles cached */ 2229*3db86aabSstevel LOCK_CACHE 2230*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 2231*3db86aabSstevel 2232*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2233*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2234*3db86aabSstevel RMCLOMV_FAN_SENS)) == NULL)) { 2235*3db86aabSstevel env_fan.next_id.name[0] = '\0'; 2236*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2237*3db86aabSstevel } else if (env_fan.id.name[0] == '\0') { 2238*3db86aabSstevel /* request for first handle */ 2239*3db86aabSstevel if (section->num_entries == 0) 2240*3db86aabSstevel env_fan.next_id.name[0] = '\0'; 2241*3db86aabSstevel else 2242*3db86aabSstevel env_fan.next_id = 2243*3db86aabSstevel section->entry[0].handle_name; 2244*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2245*3db86aabSstevel } else { 2246*3db86aabSstevel /* ensure name is properly terminated */ 2247*3db86aabSstevel env_fan.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2248*3db86aabSstevel if (get_sensor_by_name(section, env_fan.id.name, 2249*3db86aabSstevel &index) != 0) { 2250*3db86aabSstevel env_fan.next_id.name[0] = '\0'; 2251*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2252*3db86aabSstevel } else if (index + 1 < section->num_entries) 2253*3db86aabSstevel env_fan.next_id = 2254*3db86aabSstevel section->entry[index + 1].handle_name; 2255*3db86aabSstevel else 2256*3db86aabSstevel env_fan.next_id.name[0] = '\0'; 2257*3db86aabSstevel } 2258*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 2259*3db86aabSstevel /* 2260*3db86aabSstevel * user correctly identified a sensor, note its 2261*3db86aabSstevel * handle value and request the sensor value 2262*3db86aabSstevel */ 2263*3db86aabSstevel rmc_fan.handle = section->entry[index].handle; 2264*3db86aabSstevel } 2265*3db86aabSstevel RELEASE_CACHE 2266*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error || 2267*3db86aabSstevel rmclomv_do_cmd(DP_GET_FAN_STATUS, DP_GET_FAN_STATUS_R, 2268*3db86aabSstevel sizeof (rmc_fan_r), (intptr_t)&rmc_fan, 2269*3db86aabSstevel (intptr_t)&rmc_fan_r) != 0)) { 2270*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 2271*3db86aabSstevel } 2272*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && 2273*3db86aabSstevel (rmc_fan_r.fan_status[0].sensor_status == 2274*3db86aabSstevel DP_SENSOR_NOT_PRESENT)) { 2275*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2276*3db86aabSstevel } 2277*3db86aabSstevel if ((env_fan.sensor_status = sensor_status) == 2278*3db86aabSstevel ENVMON_SENSOR_OK) { 2279*3db86aabSstevel if ((rmc_fan_r.fan_status[0].flag & 2280*3db86aabSstevel DP_FAN_PRESENCE) == 0) 2281*3db86aabSstevel env_fan.sensor_status = ENVMON_NOT_PRESENT; 2282*3db86aabSstevel if (rmc_fan_r.fan_status[0].sensor_status != 2283*3db86aabSstevel DP_SENSOR_DATA_AVAILABLE) 2284*3db86aabSstevel env_fan.sensor_status |= ENVMON_INACCESSIBLE; 2285*3db86aabSstevel if (env_fan.sensor_status == ENVMON_SENSOR_OK) { 2286*3db86aabSstevel /* 2287*3db86aabSstevel * copy results into buffer for user 2288*3db86aabSstevel */ 2289*3db86aabSstevel env_fan.speed = 2290*3db86aabSstevel rmc_fan_r.fan_status[0].speed; 2291*3db86aabSstevel env_fan.lowthresholds.warning = 2292*3db86aabSstevel rmc_fan_r.fan_status[0].minspeed; 2293*3db86aabSstevel env_fan.lowthresholds.shutdown = 2294*3db86aabSstevel ENVMON_VAL_UNAVAILABLE; 2295*3db86aabSstevel env_fan.lowthresholds.poweroff = 2296*3db86aabSstevel ENVMON_VAL_UNAVAILABLE; 2297*3db86aabSstevel if ((rmc_fan_r.fan_status[0].flag & 2298*3db86aabSstevel DP_FAN_SPEED_VAL_UNIT) == 0) 2299*3db86aabSstevel bcopy(str_rpm, env_fan.units, 2300*3db86aabSstevel sizeof (str_rpm)); 2301*3db86aabSstevel else 2302*3db86aabSstevel bcopy(str_percent, env_fan.units, 2303*3db86aabSstevel sizeof (str_percent)); 2304*3db86aabSstevel } 2305*3db86aabSstevel } 2306*3db86aabSstevel if (env_fan.sensor_status != ENVMON_SENSOR_OK || 2307*3db86aabSstevel rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) 2308*3db86aabSstevel set_fan_unav(&env_fan); 2309*3db86aabSstevel 2310*3db86aabSstevel if (ddi_copyout((caddr_t)&env_fan, (caddr_t)arg, 2311*3db86aabSstevel sizeof (envmon_fan_t), mode) != 0) 2312*3db86aabSstevel return (EFAULT); 2313*3db86aabSstevel break; 2314*3db86aabSstevel 2315*3db86aabSstevel case ENVMONIOCAMPIND: 2316*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_ind, 2317*3db86aabSstevel sizeof (envmon_indicator_t), mode) != 0) 2318*3db86aabSstevel return (EFAULT); 2319*3db86aabSstevel 2320*3db86aabSstevel /* see if we've got amp indicator handles cached */ 2321*3db86aabSstevel LOCK_CACHE 2322*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 2323*3db86aabSstevel 2324*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2325*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2326*3db86aabSstevel RMCLOMV_AMP_IND)) == NULL)) { 2327*3db86aabSstevel RELEASE_CACHE 2328*3db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, &rmc_psu, 2329*3db86aabSstevel &rmc_psu_r, RMCLOMV_AMP_IND)); 2330*3db86aabSstevel } else if (env_ind.id.name[0] == '\0') { 2331*3db86aabSstevel /* request for first handle */ 2332*3db86aabSstevel if (section->num_entries == 0) { 2333*3db86aabSstevel RELEASE_CACHE 2334*3db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, 2335*3db86aabSstevel &rmc_psu, &rmc_psu_r, RMCLOMV_AMP_IND)); 2336*3db86aabSstevel } 2337*3db86aabSstevel env_ind.next_id = section->entry[0].handle_name; 2338*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2339*3db86aabSstevel } else { 2340*3db86aabSstevel /* ensure name is properly terminated */ 2341*3db86aabSstevel env_ind.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2342*3db86aabSstevel if (get_sensor_by_name(section, env_ind.id.name, 2343*3db86aabSstevel &index) != 0) { 2344*3db86aabSstevel RELEASE_CACHE 2345*3db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, 2346*3db86aabSstevel &rmc_psu, &rmc_psu_r, RMCLOMV_AMP_IND)); 2347*3db86aabSstevel } 2348*3db86aabSstevel if (index + 1 < section->num_entries) { 2349*3db86aabSstevel env_ind.next_id = 2350*3db86aabSstevel section->entry[index + 1].handle_name; 2351*3db86aabSstevel } else { 2352*3db86aabSstevel rmclomv_cache_section_t *sub_section = 2353*3db86aabSstevel rmclomv_find_section(rmclomv_subcache, 2354*3db86aabSstevel RMCLOMV_AMP_IND); 2355*3db86aabSstevel if ((sub_section == NULL) || 2356*3db86aabSstevel (sub_section->num_entries == 0)) 2357*3db86aabSstevel env_ind.next_id.name[0] = '\0'; 2358*3db86aabSstevel else 2359*3db86aabSstevel env_ind.next_id = 2360*3db86aabSstevel sub_section->entry[0].handle_name; 2361*3db86aabSstevel } 2362*3db86aabSstevel } 2363*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 2364*3db86aabSstevel /* 2365*3db86aabSstevel * user correctly identified an indicator, note its 2366*3db86aabSstevel * handle value and request the indicator status 2367*3db86aabSstevel */ 2368*3db86aabSstevel rmc_ampi.handle = section->entry[index].handle; 2369*3db86aabSstevel } 2370*3db86aabSstevel RELEASE_CACHE 2371*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error || 2372*3db86aabSstevel rmclomv_do_cmd(DP_GET_CIRCUIT_BRKS, DP_GET_CIRCUIT_BRKS_R, 2373*3db86aabSstevel sizeof (rmc_ampi_r), (intptr_t)&rmc_ampi, 2374*3db86aabSstevel (intptr_t)&rmc_ampi_r) != 0)) { 2375*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 2376*3db86aabSstevel } 2377*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && 2378*3db86aabSstevel (rmc_ampi_r.circuit_brk_status[0].sensor_status == 2379*3db86aabSstevel DP_SENSOR_NOT_PRESENT)) { 2380*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2381*3db86aabSstevel } 2382*3db86aabSstevel if ((env_ind.sensor_status = sensor_status) == 2383*3db86aabSstevel ENVMON_SENSOR_OK) { 2384*3db86aabSstevel /* 2385*3db86aabSstevel * copy results into buffer for user 2386*3db86aabSstevel */ 2387*3db86aabSstevel if (rmc_ampi_r.circuit_brk_status[0].sensor_status != 2388*3db86aabSstevel DP_SENSOR_DATA_AVAILABLE) 2389*3db86aabSstevel env_ind.sensor_status = ENVMON_INACCESSIBLE; 2390*3db86aabSstevel env_ind.condition = 2391*3db86aabSstevel rmc_ampi_r.circuit_brk_status[0].status; 2392*3db86aabSstevel } 2393*3db86aabSstevel 2394*3db86aabSstevel /* 2395*3db86aabSstevel * If rmclomv_rmc_error is set there is no way 2396*3db86aabSstevel * that we read information from RSC. Just copy 2397*3db86aabSstevel * out an inaccessible evironmental. 2398*3db86aabSstevel */ 2399*3db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) { 2400*3db86aabSstevel env_ind.sensor_status = ENVMON_INACCESSIBLE; 2401*3db86aabSstevel env_ind.condition = ENVMON_INACCESSIBLE; 2402*3db86aabSstevel } 2403*3db86aabSstevel 2404*3db86aabSstevel if (ddi_copyout((caddr_t)&env_ind, (caddr_t)arg, 2405*3db86aabSstevel sizeof (envmon_indicator_t), mode) != 0) 2406*3db86aabSstevel return (EFAULT); 2407*3db86aabSstevel break; 2408*3db86aabSstevel 2409*3db86aabSstevel case ENVMONIOCHPU: 2410*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_hpu, 2411*3db86aabSstevel sizeof (envmon_hpu_t), mode) != 0) 2412*3db86aabSstevel return (EFAULT); 2413*3db86aabSstevel 2414*3db86aabSstevel /* see if we've got hpu handles cached */ 2415*3db86aabSstevel LOCK_CACHE 2416*3db86aabSstevel 2417*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2418*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2419*3db86aabSstevel RMCLOMV_HPU_IND)) == NULL)) { 2420*3db86aabSstevel RELEASE_CACHE 2421*3db86aabSstevel return (EAGAIN); 2422*3db86aabSstevel } 2423*3db86aabSstevel 2424*3db86aabSstevel /* 2425*3db86aabSstevel * At this point the cache is locked and section points to 2426*3db86aabSstevel * the section relating to hpus. 2427*3db86aabSstevel */ 2428*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 2429*3db86aabSstevel if (env_hpu.id.name[0] == '\0') { 2430*3db86aabSstevel /* request for first handle */ 2431*3db86aabSstevel if (section->num_entries == 0) 2432*3db86aabSstevel env_hpu.next_id.name[0] = '\0'; 2433*3db86aabSstevel else 2434*3db86aabSstevel env_hpu.next_id = 2435*3db86aabSstevel section->entry[0].handle_name; 2436*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2437*3db86aabSstevel } else { 2438*3db86aabSstevel /* ensure name is properly terminated */ 2439*3db86aabSstevel env_hpu.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2440*3db86aabSstevel if (get_sensor_by_name(section, env_hpu.id.name, 2441*3db86aabSstevel &index) != 0) { 2442*3db86aabSstevel env_hpu.next_id.name[0] = '\0'; 2443*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2444*3db86aabSstevel } else if (index + 1 < section->num_entries) 2445*3db86aabSstevel env_hpu.next_id = 2446*3db86aabSstevel section->entry[index + 1].handle_name; 2447*3db86aabSstevel else 2448*3db86aabSstevel env_hpu.next_id.name[0] = '\0'; 2449*3db86aabSstevel } 2450*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 2451*3db86aabSstevel /* 2452*3db86aabSstevel * user correctly identified an hpu, note its 2453*3db86aabSstevel * handle value and request the hpu status 2454*3db86aabSstevel */ 2455*3db86aabSstevel rmc_fru.handle = section->entry[index].handle; 2456*3db86aabSstevel special = section->entry[index].ind_mask; 2457*3db86aabSstevel } 2458*3db86aabSstevel RELEASE_CACHE 2459*3db86aabSstevel if ((env_hpu.sensor_status = sensor_status) == 2460*3db86aabSstevel ENVMON_SENSOR_OK) { 2461*3db86aabSstevel env_hpu.fru_status = ENVMON_FRU_PRESENT; 2462*3db86aabSstevel 2463*3db86aabSstevel if (special != 0) { 2464*3db86aabSstevel /* this is the pseudo SC node */ 2465*3db86aabSstevel mutex_enter(&rmclomv_state_lock); 2466*3db86aabSstevel switch (rmclomv_rmc_state) { 2467*3db86aabSstevel case RMCLOMV_RMCSTATE_OK: 2468*3db86aabSstevel break; 2469*3db86aabSstevel case RMCLOMV_RMCSTATE_FAILED: 2470*3db86aabSstevel env_hpu.fru_status = ENVMON_FRU_FAULT; 2471*3db86aabSstevel break; 2472*3db86aabSstevel case RMCLOMV_RMCSTATE_DOWNLOAD: 2473*3db86aabSstevel env_hpu.fru_status = 2474*3db86aabSstevel ENVMON_FRU_DOWNLOAD; 2475*3db86aabSstevel break; 2476*3db86aabSstevel default: 2477*3db86aabSstevel env_hpu.sensor_status = 2478*3db86aabSstevel ENVMON_INACCESSIBLE; 2479*3db86aabSstevel break; 2480*3db86aabSstevel } 2481*3db86aabSstevel mutex_exit(&rmclomv_state_lock); 2482*3db86aabSstevel } else if (rmclomv_rmc_error || 2483*3db86aabSstevel rmclomv_do_cmd(DP_GET_FRU_STATUS, 2484*3db86aabSstevel DP_GET_FRU_STATUS_R, sizeof (rmc_fru_r), 2485*3db86aabSstevel (intptr_t)&rmc_fru, (intptr_t)&rmc_fru_r) != 0) { 2486*3db86aabSstevel env_hpu.sensor_status = ENVMON_INACCESSIBLE; 2487*3db86aabSstevel } else { 2488*3db86aabSstevel /* 2489*3db86aabSstevel * copy results into buffer for user 2490*3db86aabSstevel */ 2491*3db86aabSstevel if (rmc_fru_r.fru_status[0].presence == 0) { 2492*3db86aabSstevel env_hpu.sensor_status = 2493*3db86aabSstevel ENVMON_NOT_PRESENT; 2494*3db86aabSstevel env_hpu.fru_status = 2495*3db86aabSstevel ENVMON_FRU_NOT_PRESENT; 2496*3db86aabSstevel } else if (rmc_fru_r.fru_status[0].sensor_status 2497*3db86aabSstevel != DP_SENSOR_DATA_AVAILABLE) { 2498*3db86aabSstevel env_hpu.sensor_status = 2499*3db86aabSstevel ENVMON_INACCESSIBLE; 2500*3db86aabSstevel } else { 2501*3db86aabSstevel uint8_t status = 2502*3db86aabSstevel rmc_fru_r.fru_status[0].status; 2503*3db86aabSstevel if (status == DP_FRU_STATUS_UNKNOWN) { 2504*3db86aabSstevel env_hpu.sensor_status = 2505*3db86aabSstevel ENVMON_INACCESSIBLE; 2506*3db86aabSstevel } else if (status != DP_FRU_STATUS_OK) { 2507*3db86aabSstevel env_hpu.fru_status = 2508*3db86aabSstevel ENVMON_FRU_FAULT; 2509*3db86aabSstevel } 2510*3db86aabSstevel } 2511*3db86aabSstevel } 2512*3db86aabSstevel } 2513*3db86aabSstevel 2514*3db86aabSstevel /* 2515*3db86aabSstevel * If rmclomv_rmc_error is set there is no way 2516*3db86aabSstevel * that we read information from RSC. Just copy 2517*3db86aabSstevel * out an inaccessible environmental. 2518*3db86aabSstevel */ 2519*3db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) { 2520*3db86aabSstevel env_hpu.sensor_status = ENVMON_INACCESSIBLE; 2521*3db86aabSstevel env_hpu.fru_status = ENVMON_INACCESSIBLE; 2522*3db86aabSstevel } 2523*3db86aabSstevel 2524*3db86aabSstevel if (ddi_copyout((caddr_t)&env_hpu, (caddr_t)arg, 2525*3db86aabSstevel sizeof (envmon_hpu_t), mode) != 0) 2526*3db86aabSstevel return (EFAULT); 2527*3db86aabSstevel break; 2528*3db86aabSstevel 2529*3db86aabSstevel case ENVMONIOCGETLED: 2530*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_ledinfo, 2531*3db86aabSstevel sizeof (envmon_led_info_t), mode) != 0) 2532*3db86aabSstevel return (EFAULT); 2533*3db86aabSstevel 2534*3db86aabSstevel /* see if we've got LED handles cached */ 2535*3db86aabSstevel LOCK_CACHE 2536*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 2537*3db86aabSstevel 2538*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2539*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2540*3db86aabSstevel RMCLOMV_LED_IND)) == NULL)) { 2541*3db86aabSstevel env_ledinfo.next_id.name[0] = '\0'; 2542*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2543*3db86aabSstevel } else if (env_ledinfo.id.name[0] == '\0') { 2544*3db86aabSstevel /* request for first handle */ 2545*3db86aabSstevel if (section->num_entries == 0) 2546*3db86aabSstevel env_ledinfo.next_id.name[0] = '\0'; 2547*3db86aabSstevel else 2548*3db86aabSstevel env_ledinfo.next_id = 2549*3db86aabSstevel section->entry[0].handle_name; 2550*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2551*3db86aabSstevel } else { 2552*3db86aabSstevel /* ensure name is properly terminated */ 2553*3db86aabSstevel env_ledinfo.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2554*3db86aabSstevel if (get_sensor_by_name(section, env_ledinfo.id.name, 2555*3db86aabSstevel &index) != 0) { 2556*3db86aabSstevel env_ledinfo.next_id.name[0] = '\0'; 2557*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2558*3db86aabSstevel } else if (index + 1 < section->num_entries) 2559*3db86aabSstevel env_ledinfo.next_id = 2560*3db86aabSstevel section->entry[index + 1].handle_name; 2561*3db86aabSstevel else 2562*3db86aabSstevel env_ledinfo.next_id.name[0] = '\0'; 2563*3db86aabSstevel } 2564*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 2565*3db86aabSstevel /* 2566*3db86aabSstevel * user correctly identified a LED, note its 2567*3db86aabSstevel * handle value and request the LED status 2568*3db86aabSstevel */ 2569*3db86aabSstevel rmc_led.handle = section->entry[index].handle; 2570*3db86aabSstevel } 2571*3db86aabSstevel RELEASE_CACHE 2572*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error || 2573*3db86aabSstevel rmclomv_do_cmd(DP_GET_LED_STATE, DP_GET_LED_STATE_R, 2574*3db86aabSstevel sizeof (rmc_led_r), (intptr_t)&rmc_led, 2575*3db86aabSstevel (intptr_t)&rmc_led_r) != 0)) { 2576*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 2577*3db86aabSstevel } 2578*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && 2579*3db86aabSstevel (rmc_led_r.led_state[0].sensor_status == 2580*3db86aabSstevel DP_SENSOR_NOT_PRESENT)) { 2581*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2582*3db86aabSstevel } 2583*3db86aabSstevel if ((env_ledinfo.sensor_status = sensor_status) == 2584*3db86aabSstevel ENVMON_SENSOR_OK) { 2585*3db86aabSstevel /* 2586*3db86aabSstevel * copy results into buffer for user 2587*3db86aabSstevel * start with some defaults then override 2588*3db86aabSstevel */ 2589*3db86aabSstevel env_ledinfo.sensor_status = ENVMON_SENSOR_OK; 2590*3db86aabSstevel env_ledinfo.led_state = ENVMON_LED_OFF; 2591*3db86aabSstevel env_ledinfo.led_color = ENVMON_LED_CLR_NONE; 2592*3db86aabSstevel 2593*3db86aabSstevel if (rmc_led_r.led_state[0].sensor_status != 2594*3db86aabSstevel DP_SENSOR_DATA_AVAILABLE) 2595*3db86aabSstevel env_ledinfo.sensor_status = ENVMON_INACCESSIBLE; 2596*3db86aabSstevel else { 2597*3db86aabSstevel dp_led_state_t ledState; 2598*3db86aabSstevel ledState = rmc_led_r.led_state[0]; 2599*3db86aabSstevel env_ledinfo.led_color = (int8_t)ledState.colour; 2600*3db86aabSstevel 2601*3db86aabSstevel switch (ledState.state) { 2602*3db86aabSstevel case (rsci8)DP_LED_OFF: 2603*3db86aabSstevel break; 2604*3db86aabSstevel case (rsci8)DP_LED_ON: 2605*3db86aabSstevel env_ledinfo.led_state = ENVMON_LED_ON; 2606*3db86aabSstevel break; 2607*3db86aabSstevel case (rsci8)DP_LED_BLINKING: 2608*3db86aabSstevel env_ledinfo.led_state = 2609*3db86aabSstevel ENVMON_LED_BLINKING; 2610*3db86aabSstevel break; 2611*3db86aabSstevel case (rsci8)DP_LED_FLASHING: 2612*3db86aabSstevel env_ledinfo.led_state = 2613*3db86aabSstevel ENVMON_LED_FLASHING; 2614*3db86aabSstevel break; 2615*3db86aabSstevel default: 2616*3db86aabSstevel break; 2617*3db86aabSstevel } 2618*3db86aabSstevel } 2619*3db86aabSstevel } 2620*3db86aabSstevel 2621*3db86aabSstevel /* 2622*3db86aabSstevel * If rmclomv_rmc_error is set there is no way 2623*3db86aabSstevel * that we read information from RSC. Just copy 2624*3db86aabSstevel * out an inaccessible environmental. 2625*3db86aabSstevel */ 2626*3db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) { 2627*3db86aabSstevel env_ledinfo.sensor_status = ENVMON_INACCESSIBLE; 2628*3db86aabSstevel env_ledinfo.led_state = ENVMON_INACCESSIBLE; 2629*3db86aabSstevel } 2630*3db86aabSstevel 2631*3db86aabSstevel if (ddi_copyout((caddr_t)&env_ledinfo, (caddr_t)arg, 2632*3db86aabSstevel sizeof (envmon_led_info_t), mode) != 0) 2633*3db86aabSstevel return (EFAULT); 2634*3db86aabSstevel break; 2635*3db86aabSstevel 2636*3db86aabSstevel case ENVMONIOCSETLED: 2637*3db86aabSstevel if ((mode & FWRITE) == 0) 2638*3db86aabSstevel return (EACCES); 2639*3db86aabSstevel if (drv_priv(cred_p) != 0) 2640*3db86aabSstevel return (EPERM); 2641*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_ledctl, 2642*3db86aabSstevel sizeof (envmon_led_ctl_t), mode) != 0) 2643*3db86aabSstevel return (EFAULT); 2644*3db86aabSstevel if (env_ledctl.led_state < RMCLOMV_MIN_LED_STATE || 2645*3db86aabSstevel env_ledctl.led_state > RMCLOMV_MAX_LED_STATE) 2646*3db86aabSstevel return (EINVAL); 2647*3db86aabSstevel /* 2648*3db86aabSstevel * Ensure name is properly terminated. 2649*3db86aabSstevel */ 2650*3db86aabSstevel env_ledctl.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2651*3db86aabSstevel 2652*3db86aabSstevel /* see if we've got LED handles cached */ 2653*3db86aabSstevel LOCK_CACHE 2654*3db86aabSstevel 2655*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2656*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2657*3db86aabSstevel RMCLOMV_LED_IND)) == NULL) || 2658*3db86aabSstevel (get_sensor_by_name(section, env_ledctl.id.name, 2659*3db86aabSstevel &index) != 0)) { 2660*3db86aabSstevel RELEASE_CACHE 2661*3db86aabSstevel return (EINVAL); /* no such LED */ 2662*3db86aabSstevel } 2663*3db86aabSstevel /* 2664*3db86aabSstevel * user correctly identified a LED, note its handle value 2665*3db86aabSstevel */ 2666*3db86aabSstevel rmc_setled.handle = section->entry[index].handle; 2667*3db86aabSstevel RELEASE_CACHE 2668*3db86aabSstevel switch (env_ledctl.led_state) { 2669*3db86aabSstevel case ENVMON_LED_ON: 2670*3db86aabSstevel rmc_setled.state = DP_LED_ON; 2671*3db86aabSstevel break; 2672*3db86aabSstevel case ENVMON_LED_BLINKING: 2673*3db86aabSstevel rmc_setled.state = DP_LED_BLINKING; 2674*3db86aabSstevel break; 2675*3db86aabSstevel case ENVMON_LED_FLASHING: 2676*3db86aabSstevel rmc_setled.state = DP_LED_FLASHING; 2677*3db86aabSstevel break; 2678*3db86aabSstevel default: 2679*3db86aabSstevel rmc_setled.state = DP_LED_OFF; 2680*3db86aabSstevel break; 2681*3db86aabSstevel } 2682*3db86aabSstevel retval = rmclomv_do_cmd(DP_SET_LED_STATE, DP_SET_LED_STATE_R, 2683*3db86aabSstevel sizeof (rmc_setled_r), (intptr_t)&rmc_setled, 2684*3db86aabSstevel (intptr_t)&rmc_setled_r); 2685*3db86aabSstevel 2686*3db86aabSstevel if (retval != 0) { 2687*3db86aabSstevel break; 2688*3db86aabSstevel } 2689*3db86aabSstevel 2690*3db86aabSstevel if (rmc_setled_r.status != 0) { 2691*3db86aabSstevel cmn_err(CE_WARN, "ENVMONIOCSETLED: \"%s\" status: 0x%x", 2692*3db86aabSstevel env_ledctl.id.name, rmc_setled_r.status); 2693*3db86aabSstevel return (EIO); 2694*3db86aabSstevel } 2695*3db86aabSstevel break; 2696*3db86aabSstevel 2697*3db86aabSstevel case ENVMONIOCGETKEYSW: 2698*3db86aabSstevel { 2699*3db86aabSstevel enum rmc_keyswitch_pos rmc_pos = real_key_position; 2700*3db86aabSstevel envmon_keysw_pos_t envmon_pos; 2701*3db86aabSstevel 2702*3db86aabSstevel /* 2703*3db86aabSstevel * Yes, I know this is ugly, but the V210 has no keyswitch, 2704*3db86aabSstevel * even though the ALOM returns a value for it 2705*3db86aabSstevel */ 2706*3db86aabSstevel if (strcmp(platform, "SUNW,Sun-Fire-V210") == 0) { 2707*3db86aabSstevel return (ENOTSUP); 2708*3db86aabSstevel } 2709*3db86aabSstevel 2710*3db86aabSstevel switch (rmc_pos) { 2711*3db86aabSstevel 2712*3db86aabSstevel case RMC_KEYSWITCH_POS_NORMAL: 2713*3db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_NORMAL; 2714*3db86aabSstevel break; 2715*3db86aabSstevel case RMC_KEYSWITCH_POS_DIAG: 2716*3db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_DIAG; 2717*3db86aabSstevel break; 2718*3db86aabSstevel case RMC_KEYSWITCH_POS_LOCKED: 2719*3db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_LOCKED; 2720*3db86aabSstevel break; 2721*3db86aabSstevel case RMC_KEYSWITCH_POS_OFF: 2722*3db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_OFF; 2723*3db86aabSstevel break; 2724*3db86aabSstevel default: 2725*3db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_UNKNOWN; 2726*3db86aabSstevel break; 2727*3db86aabSstevel } 2728*3db86aabSstevel 2729*3db86aabSstevel if (ddi_copyout((caddr_t)&envmon_pos, (caddr_t)arg, 2730*3db86aabSstevel sizeof (envmon_pos), mode) != 0) 2731*3db86aabSstevel return (EFAULT); 2732*3db86aabSstevel break; 2733*3db86aabSstevel } 2734*3db86aabSstevel 2735*3db86aabSstevel case ENVMONIOCGETALARM: 2736*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_alarminfo, 2737*3db86aabSstevel sizeof (envmon_alarm_info_t), mode) != 0) 2738*3db86aabSstevel return (EFAULT); 2739*3db86aabSstevel 2740*3db86aabSstevel /* see if we've got ALARM handles cached */ 2741*3db86aabSstevel LOCK_CACHE 2742*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 2743*3db86aabSstevel 2744*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2745*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2746*3db86aabSstevel RMCLOMV_ALARM_IND)) == NULL)) { 2747*3db86aabSstevel env_alarminfo.next_id.name[0] = '\0'; 2748*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2749*3db86aabSstevel } else if (env_alarminfo.id.name[0] == '\0') { 2750*3db86aabSstevel /* request for first handle */ 2751*3db86aabSstevel if (section->num_entries == 0) 2752*3db86aabSstevel env_alarminfo.next_id.name[0] = '\0'; 2753*3db86aabSstevel else 2754*3db86aabSstevel env_alarminfo.next_id = 2755*3db86aabSstevel section->entry[0].handle_name; 2756*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2757*3db86aabSstevel } else { 2758*3db86aabSstevel /* ensure name is properly terminated */ 2759*3db86aabSstevel env_alarminfo.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2760*3db86aabSstevel if (get_sensor_by_name(section, env_alarminfo.id.name, 2761*3db86aabSstevel &index) != 0) { 2762*3db86aabSstevel env_alarminfo.next_id.name[0] = '\0'; 2763*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 2764*3db86aabSstevel } else if (index + 1 < section->num_entries) 2765*3db86aabSstevel env_alarminfo.next_id = 2766*3db86aabSstevel section->entry[index + 1].handle_name; 2767*3db86aabSstevel else 2768*3db86aabSstevel env_alarminfo.next_id.name[0] = '\0'; 2769*3db86aabSstevel } 2770*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 2771*3db86aabSstevel /* 2772*3db86aabSstevel * user correctly identified a ALARM, note its 2773*3db86aabSstevel * handle value and request the ALARM status 2774*3db86aabSstevel */ 2775*3db86aabSstevel rmc_alarm.handle = section->entry[index].handle; 2776*3db86aabSstevel } 2777*3db86aabSstevel RELEASE_CACHE 2778*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && 2779*3db86aabSstevel (rmclomv_rmc_error || 2780*3db86aabSstevel rmclomv_do_cmd(DP_GET_ALARM_STATE, DP_GET_ALARM_STATE_R, 2781*3db86aabSstevel sizeof (rmc_alarm_r), (intptr_t)&rmc_alarm, 2782*3db86aabSstevel (intptr_t)&rmc_alarm_r) != 0)) { 2783*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 2784*3db86aabSstevel } 2785*3db86aabSstevel if ((env_alarminfo.sensor_status = sensor_status) == 2786*3db86aabSstevel ENVMON_SENSOR_OK) { 2787*3db86aabSstevel /* 2788*3db86aabSstevel * copy results into buffer for user 2789*3db86aabSstevel * start with some defaults then override 2790*3db86aabSstevel */ 2791*3db86aabSstevel env_alarminfo.sensor_status = ENVMON_SENSOR_OK; 2792*3db86aabSstevel env_alarminfo.alarm_state = ENVMON_ALARM_OFF; 2793*3db86aabSstevel 2794*3db86aabSstevel if (rmc_alarm_r.alarm_state[0].sensor_status != 2795*3db86aabSstevel DP_SENSOR_DATA_AVAILABLE) 2796*3db86aabSstevel env_alarminfo.sensor_status = 2797*3db86aabSstevel ENVMON_INACCESSIBLE; 2798*3db86aabSstevel else { 2799*3db86aabSstevel dp_alarm_state_t alarmState; 2800*3db86aabSstevel alarmState = rmc_alarm_r.alarm_state[0]; 2801*3db86aabSstevel 2802*3db86aabSstevel switch (alarmState.state) { 2803*3db86aabSstevel case DP_ALARM_OFF: 2804*3db86aabSstevel break; 2805*3db86aabSstevel case DP_ALARM_ON: 2806*3db86aabSstevel env_alarminfo.alarm_state = 2807*3db86aabSstevel ENVMON_ALARM_ON; 2808*3db86aabSstevel break; 2809*3db86aabSstevel default: 2810*3db86aabSstevel break; 2811*3db86aabSstevel } 2812*3db86aabSstevel } 2813*3db86aabSstevel } 2814*3db86aabSstevel 2815*3db86aabSstevel /* 2816*3db86aabSstevel * If rmclomv_rmc_error is set there is no way 2817*3db86aabSstevel * that we read information from RSC. Just copy 2818*3db86aabSstevel * out an inaccessible environmental. 2819*3db86aabSstevel */ 2820*3db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) { 2821*3db86aabSstevel env_alarminfo.sensor_status = ENVMON_INACCESSIBLE; 2822*3db86aabSstevel env_alarminfo.alarm_state = ENVMON_INACCESSIBLE; 2823*3db86aabSstevel } 2824*3db86aabSstevel 2825*3db86aabSstevel if (ddi_copyout((caddr_t)&env_alarminfo, (caddr_t)arg, 2826*3db86aabSstevel sizeof (envmon_alarm_info_t), mode) != 0) 2827*3db86aabSstevel return (EFAULT); 2828*3db86aabSstevel break; 2829*3db86aabSstevel 2830*3db86aabSstevel case ENVMONIOCSETALARM: 2831*3db86aabSstevel if ((mode & FWRITE) == 0) 2832*3db86aabSstevel return (EACCES); 2833*3db86aabSstevel if (drv_priv(cred_p) != 0) 2834*3db86aabSstevel return (EPERM); 2835*3db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_alarmctl, 2836*3db86aabSstevel sizeof (envmon_alarm_ctl_t), mode) != 0) 2837*3db86aabSstevel return (EFAULT); 2838*3db86aabSstevel if (env_alarmctl.alarm_state < RMCLOMV_MIN_ALARM_STATE || 2839*3db86aabSstevel env_alarmctl.alarm_state > RMCLOMV_MAX_ALARM_STATE) 2840*3db86aabSstevel return (EINVAL); 2841*3db86aabSstevel /* 2842*3db86aabSstevel * Ensure name is properly terminated. 2843*3db86aabSstevel */ 2844*3db86aabSstevel env_alarmctl.id.name[ENVMON_MAXNAMELEN - 1] = '\0'; 2845*3db86aabSstevel 2846*3db86aabSstevel /* see if we've got ALARM handles cached */ 2847*3db86aabSstevel LOCK_CACHE 2848*3db86aabSstevel 2849*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 2850*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 2851*3db86aabSstevel RMCLOMV_ALARM_IND)) == NULL) || 2852*3db86aabSstevel (get_sensor_by_name(section, env_alarmctl.id.name, 2853*3db86aabSstevel &index) != 0)) { 2854*3db86aabSstevel RELEASE_CACHE 2855*3db86aabSstevel return (EINVAL); /* no such ALARM */ 2856*3db86aabSstevel } 2857*3db86aabSstevel /* 2858*3db86aabSstevel * user correctly identified a ALARM, note its handle value 2859*3db86aabSstevel */ 2860*3db86aabSstevel rmc_setalarm.handle = section->entry[index].handle; 2861*3db86aabSstevel RELEASE_CACHE 2862*3db86aabSstevel rmc_setalarm.state = (rsci8)env_alarmctl.alarm_state; 2863*3db86aabSstevel retval = rmclomv_do_cmd(DP_SET_ALARM_STATE, 2864*3db86aabSstevel DP_SET_ALARM_STATE_R, 2865*3db86aabSstevel sizeof (rmc_setalarm_r), 2866*3db86aabSstevel (intptr_t)&rmc_setalarm, 2867*3db86aabSstevel (intptr_t)&rmc_setalarm_r); 2868*3db86aabSstevel 2869*3db86aabSstevel if (retval != 0) { 2870*3db86aabSstevel break; 2871*3db86aabSstevel } 2872*3db86aabSstevel 2873*3db86aabSstevel if (rmc_setalarm_r.status != 0) { 2874*3db86aabSstevel cmn_err(CE_WARN, "ENVMONIOCSETALARM: \"%s\" status: " 2875*3db86aabSstevel "0x%x", env_alarmctl.id.name, 2876*3db86aabSstevel rmc_setalarm_r.status); 2877*3db86aabSstevel return (EIO); 2878*3db86aabSstevel } 2879*3db86aabSstevel break; 2880*3db86aabSstevel 2881*3db86aabSstevel case ENVMONIOCCHASSISSERIALNUM: 2882*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_SDP_VERSION, 2883*3db86aabSstevel DP_GET_SDP_VERSION_R, sizeof (rmc_sdpver_r), 2884*3db86aabSstevel NULL, (intptr_t)&rmc_sdpver_r); 2885*3db86aabSstevel 2886*3db86aabSstevel if (retval != 0) { 2887*3db86aabSstevel cmn_err(CE_WARN, "DP_GET_SDP_VERSION failed, ret=%d\n", 2888*3db86aabSstevel retval); 2889*3db86aabSstevel break; 2890*3db86aabSstevel } else if (rmc_sdpver_r.version < SDP_RESPONDS_TO_ALL_CMDS) { 2891*3db86aabSstevel retval = ENOTSUP; 2892*3db86aabSstevel break; 2893*3db86aabSstevel } 2894*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_CHASSIS_SERIALNUM, 2895*3db86aabSstevel DP_GET_CHASSIS_SERIALNUM_R, sizeof (rmc_serialnum_r), 2896*3db86aabSstevel NULL, (intptr_t)&rmc_serialnum_r); 2897*3db86aabSstevel 2898*3db86aabSstevel if (retval != 0) { 2899*3db86aabSstevel break; 2900*3db86aabSstevel } 2901*3db86aabSstevel bcopy(rmc_serialnum_r.chassis_serial_number, 2902*3db86aabSstevel chassis.serial_number, 2903*3db86aabSstevel sizeof (rmc_serialnum_r.chassis_serial_number)); 2904*3db86aabSstevel 2905*3db86aabSstevel if (ddi_copyout((caddr_t)&chassis, (caddr_t)arg, 2906*3db86aabSstevel sizeof (chassis), mode) != 0) { 2907*3db86aabSstevel return (EFAULT); 2908*3db86aabSstevel } 2909*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 2910*3db86aabSstevel break; 2911*3db86aabSstevel 2912*3db86aabSstevel default: 2913*3db86aabSstevel retval = ENOTSUP; 2914*3db86aabSstevel break; 2915*3db86aabSstevel } 2916*3db86aabSstevel 2917*3db86aabSstevel return (retval); 2918*3db86aabSstevel } 2919*3db86aabSstevel 2920*3db86aabSstevel /* ARGSUSED */ 2921*3db86aabSstevel static void 2922*3db86aabSstevel rmclomv_checkrmc(caddr_t arg) 2923*3db86aabSstevel { 2924*3db86aabSstevel callb_cpr_t cprinfo; 2925*3db86aabSstevel int err; 2926*3db86aabSstevel int retries; 2927*3db86aabSstevel int state; 2928*3db86aabSstevel dp_get_sysinfo_r_t sysinfo; 2929*3db86aabSstevel 2930*3db86aabSstevel CALLB_CPR_INIT(&cprinfo, &rmclomv_checkrmc_lock, callb_generic_cpr, 2931*3db86aabSstevel "rmclomv_checkrmc"); 2932*3db86aabSstevel 2933*3db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock); 2934*3db86aabSstevel for (;;) { 2935*3db86aabSstevel /* 2936*3db86aabSstevel * Initial entry to this for loop is made with 2937*3db86aabSstevel * rmclomv_checkrmc_sig set to RMCLOMV_PROCESS_NOW. So the 2938*3db86aabSstevel * following while loop drops through the first time. A 2939*3db86aabSstevel * timeout call is made just before polling the RMC. Its 2940*3db86aabSstevel * interrupt routine sustains this loop by injecting additional 2941*3db86aabSstevel * state changes and cv events. 2942*3db86aabSstevel */ 2943*3db86aabSstevel /* 2944*3db86aabSstevel * Wait for someone to tell me to continue. 2945*3db86aabSstevel */ 2946*3db86aabSstevel while (rmclomv_checkrmc_sig == RMCLOMV_CHECKRMC_WAIT) { 2947*3db86aabSstevel CALLB_CPR_SAFE_BEGIN(&cprinfo); 2948*3db86aabSstevel cv_wait(&rmclomv_checkrmc_sig_cv, 2949*3db86aabSstevel &rmclomv_checkrmc_lock); 2950*3db86aabSstevel CALLB_CPR_SAFE_END(&cprinfo, &rmclomv_checkrmc_lock); 2951*3db86aabSstevel } 2952*3db86aabSstevel 2953*3db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock); 2954*3db86aabSstevel /* 2955*3db86aabSstevel * mustn't hold same lock as timeout called with 2956*3db86aabSstevel * when cancelling timer 2957*3db86aabSstevel */ 2958*3db86aabSstevel if (timer_id != 0) { 2959*3db86aabSstevel (void) untimeout(timer_id); 2960*3db86aabSstevel timer_id = 0; 2961*3db86aabSstevel } 2962*3db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock); 2963*3db86aabSstevel 2964*3db86aabSstevel /* RMCLOMV_CHECKRMC_EXITNOW implies signal by _detach(). */ 2965*3db86aabSstevel if (rmclomv_checkrmc_sig == RMCLOMV_CHECKRMC_EXITNOW) { 2966*3db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_WAIT; 2967*3db86aabSstevel 2968*3db86aabSstevel /* rmclomv_checkrmc_lock is held at this point! */ 2969*3db86aabSstevel CALLB_CPR_EXIT(&cprinfo); 2970*3db86aabSstevel 2971*3db86aabSstevel thread_exit(); 2972*3db86aabSstevel /* NOTREACHED */ 2973*3db86aabSstevel } 2974*3db86aabSstevel 2975*3db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_WAIT; 2976*3db86aabSstevel 2977*3db86aabSstevel /* 2978*3db86aabSstevel * If the RMC is not responding, rmclomv_do_cmd() takes a 2979*3db86aabSstevel * long time and eventually times out. We conclude that the 2980*3db86aabSstevel * RMC is broken if it doesn't respond to a number of polls 2981*3db86aabSstevel * made 60 secs apart. So that the rmclomv_do_cmd() time-out 2982*3db86aabSstevel * period isn't added to our 60 second timer, make the 2983*3db86aabSstevel * timeout() call before calling rmclomv_do_cmd(). 2984*3db86aabSstevel */ 2985*3db86aabSstevel if (timer_id == 0) { 2986*3db86aabSstevel timer_id = timeout(rmclomv_checkrmc_wakeup, NULL, 2987*3db86aabSstevel 60 * drv_usectohz(1000000)); 2988*3db86aabSstevel } 2989*3db86aabSstevel 2990*3db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock); 2991*3db86aabSstevel 2992*3db86aabSstevel err = rmclomv_do_cmd(DP_GET_SYSINFO, DP_GET_SYSINFO_R, 2993*3db86aabSstevel sizeof (sysinfo), NULL, (intptr_t)&sysinfo); 2994*3db86aabSstevel if (err == 0) { 2995*3db86aabSstevel mutex_enter(&rmclomv_state_lock); 2996*3db86aabSstevel state = rmclomv_rmc_state; 2997*3db86aabSstevel /* successful poll, reset fail count */ 2998*3db86aabSstevel rmclomv_rmcfailcount = 0; 2999*3db86aabSstevel mutex_exit(&rmclomv_state_lock); 3000*3db86aabSstevel 3001*3db86aabSstevel if (state != RMCLOMV_RMCSTATE_OK) { 3002*3db86aabSstevel rmclomv_refresh_wakeup(); 3003*3db86aabSstevel } 3004*3db86aabSstevel } 3005*3db86aabSstevel if ((err != 0) && 3006*3db86aabSstevel (rmclomv_rmc_error != RMCLOMV_RMCSTATE_DOWNLOAD)) { 3007*3db86aabSstevel /* 3008*3db86aabSstevel * Failed response or no response from RMC. 3009*3db86aabSstevel * Count the failure. 3010*3db86aabSstevel * If threshold exceeded, send a DR event. 3011*3db86aabSstevel */ 3012*3db86aabSstevel mutex_enter(&rmclomv_state_lock); 3013*3db86aabSstevel retries = rmclomv_rmcfailcount; 3014*3db86aabSstevel state = rmclomv_rmc_state; 3015*3db86aabSstevel if (retries == RMCLOMV_RMCFAILTHRESHOLD) 3016*3db86aabSstevel rmclomv_rmc_state = RMCLOMV_RMCSTATE_FAILED; 3017*3db86aabSstevel if (rmclomv_rmcfailcount <= RMCLOMV_RMCFAILTHRESHOLD) 3018*3db86aabSstevel rmclomv_rmcfailcount++; 3019*3db86aabSstevel mutex_exit(&rmclomv_state_lock); 3020*3db86aabSstevel 3021*3db86aabSstevel if (retries == RMCLOMV_RMCFAILTHRESHOLD) { 3022*3db86aabSstevel cmn_err(CE_WARN, "SC %s responding", 3023*3db86aabSstevel state == RMCLOMV_RMCSTATE_OK ? 3024*3db86aabSstevel "has stopped" : "is not"); 3025*3db86aabSstevel refresh_name_cache(B_TRUE); 3026*3db86aabSstevel rmclomv_dr_data_handler(str_sc, SE_NO_HINT); 3027*3db86aabSstevel } 3028*3db86aabSstevel } 3029*3db86aabSstevel 3030*3db86aabSstevel /* 3031*3db86aabSstevel * Re-enter the lock to prepare for another iteration. 3032*3db86aabSstevel * We must have the lock here to protect rmclomv_checkrmc_sig. 3033*3db86aabSstevel */ 3034*3db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock); 3035*3db86aabSstevel } 3036*3db86aabSstevel } 3037*3db86aabSstevel 3038*3db86aabSstevel static void 3039*3db86aabSstevel rmclomv_checkrmc_start(void) 3040*3db86aabSstevel { 3041*3db86aabSstevel kthread_t *tp; 3042*3db86aabSstevel 3043*3db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock); 3044*3db86aabSstevel 3045*3db86aabSstevel if (rmclomv_checkrmc_tid == 0) { 3046*3db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_PROCESSNOW; 3047*3db86aabSstevel 3048*3db86aabSstevel tp = thread_create(NULL, 0, rmclomv_checkrmc, NULL, 0, 3049*3db86aabSstevel &p0, TS_RUN, maxclsyspri); 3050*3db86aabSstevel rmclomv_checkrmc_tid = tp->t_did; 3051*3db86aabSstevel } 3052*3db86aabSstevel 3053*3db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock); 3054*3db86aabSstevel } 3055*3db86aabSstevel 3056*3db86aabSstevel static void 3057*3db86aabSstevel rmclomv_checkrmc_destroy(void) 3058*3db86aabSstevel { 3059*3db86aabSstevel kt_did_t tid; 3060*3db86aabSstevel 3061*3db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock); 3062*3db86aabSstevel tid = rmclomv_checkrmc_tid; 3063*3db86aabSstevel if (tid != 0) { 3064*3db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_EXITNOW; 3065*3db86aabSstevel cv_signal(&rmclomv_checkrmc_sig_cv); 3066*3db86aabSstevel rmclomv_checkrmc_tid = 0; 3067*3db86aabSstevel } 3068*3db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock); 3069*3db86aabSstevel 3070*3db86aabSstevel /* 3071*3db86aabSstevel * Wait for rmclomv_checkrmc() to finish 3072*3db86aabSstevel */ 3073*3db86aabSstevel if (tid != 0) 3074*3db86aabSstevel thread_join(tid); 3075*3db86aabSstevel } 3076*3db86aabSstevel 3077*3db86aabSstevel /*ARGSUSED*/ 3078*3db86aabSstevel static void 3079*3db86aabSstevel rmclomv_checkrmc_wakeup(void *arg) 3080*3db86aabSstevel { 3081*3db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock); 3082*3db86aabSstevel 3083*3db86aabSstevel if (rmclomv_checkrmc_sig != RMCLOMV_CHECKRMC_EXITNOW) 3084*3db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_PROCESSNOW; 3085*3db86aabSstevel cv_signal(&rmclomv_checkrmc_sig_cv); 3086*3db86aabSstevel 3087*3db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock); 3088*3db86aabSstevel } 3089*3db86aabSstevel 3090*3db86aabSstevel /* ARGSUSED */ 3091*3db86aabSstevel static void 3092*3db86aabSstevel rmclomv_refresh(caddr_t arg) 3093*3db86aabSstevel { 3094*3db86aabSstevel void (*plat_nodename_set_fun)(void); 3095*3db86aabSstevel sig_state_t *current_sgn_p; 3096*3db86aabSstevel callb_cpr_t cprinfo; 3097*3db86aabSstevel int state; 3098*3db86aabSstevel 3099*3db86aabSstevel CALLB_CPR_INIT(&cprinfo, &rmclomv_refresh_lock, callb_generic_cpr, 3100*3db86aabSstevel "rmclomv_refresh"); 3101*3db86aabSstevel 3102*3db86aabSstevel delay(drv_usectohz(5000000)); 3103*3db86aabSstevel mutex_enter(&rmclomv_refresh_lock); 3104*3db86aabSstevel for (;;) { 3105*3db86aabSstevel 3106*3db86aabSstevel /* 3107*3db86aabSstevel * Wait for someone to tell me to continue. 3108*3db86aabSstevel */ 3109*3db86aabSstevel while (rmclomv_refresh_sig == RMCLOMV_REFRESH_WAIT) { 3110*3db86aabSstevel CALLB_CPR_SAFE_BEGIN(&cprinfo); 3111*3db86aabSstevel cv_wait(&rmclomv_refresh_sig_cv, &rmclomv_refresh_lock); 3112*3db86aabSstevel CALLB_CPR_SAFE_END(&cprinfo, &rmclomv_refresh_lock); 3113*3db86aabSstevel } 3114*3db86aabSstevel 3115*3db86aabSstevel /* RMCLOMV_REFRESH_EXITNOW implies signal by _detach(). */ 3116*3db86aabSstevel if (rmclomv_refresh_sig == RMCLOMV_REFRESH_EXITNOW) { 3117*3db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_WAIT; 3118*3db86aabSstevel 3119*3db86aabSstevel /* rmclomv_refresh_lock is held at this point! */ 3120*3db86aabSstevel CALLB_CPR_EXIT(&cprinfo); 3121*3db86aabSstevel 3122*3db86aabSstevel thread_exit(); 3123*3db86aabSstevel /* NOTREACHED */ 3124*3db86aabSstevel } 3125*3db86aabSstevel 3126*3db86aabSstevel ASSERT(rmclomv_refresh_sig == RMCLOMV_REFRESH_PROCESSNOW); 3127*3db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_WAIT; 3128*3db86aabSstevel 3129*3db86aabSstevel mutex_exit(&rmclomv_refresh_lock); 3130*3db86aabSstevel 3131*3db86aabSstevel refresh_name_cache(B_FALSE); 3132*3db86aabSstevel 3133*3db86aabSstevel /* 3134*3db86aabSstevel * We're not going to access rmclomv_sysinfo_data here, 3135*3db86aabSstevel * so there's no point in locking it before reading 3136*3db86aabSstevel * rmclomv_sysinfo_valid. Also this avoids holding two 3137*3db86aabSstevel * locks at once and the concommitant worry about deadlocks. 3138*3db86aabSstevel */ 3139*3db86aabSstevel if (rmclomv_sysinfo_valid) { 3140*3db86aabSstevel /* 3141*3db86aabSstevel * We've just successfully read the RMC sysinfo 3142*3db86aabSstevel * so the RMC must be operational. Update its 3143*3db86aabSstevel * state and if it was previously not OK, refresh 3144*3db86aabSstevel * nodename, CPU signatures and watchdog settings. 3145*3db86aabSstevel */ 3146*3db86aabSstevel mutex_enter(&rmclomv_state_lock); 3147*3db86aabSstevel rmclomv_rmcfailcount = 0; 3148*3db86aabSstevel state = rmclomv_rmc_state; 3149*3db86aabSstevel rmclomv_rmc_state = RMCLOMV_RMCSTATE_OK; 3150*3db86aabSstevel mutex_exit(&rmclomv_state_lock); 3151*3db86aabSstevel 3152*3db86aabSstevel if (state != RMCLOMV_RMCSTATE_OK) { 3153*3db86aabSstevel rmclomv_dr_data_handler(str_sc, SE_NO_HINT); 3154*3db86aabSstevel if (state == RMCLOMV_RMCSTATE_FAILED) { 3155*3db86aabSstevel cmn_err(CE_NOTE, "SC recovered"); 3156*3db86aabSstevel } 3157*3db86aabSstevel } 3158*3db86aabSstevel 3159*3db86aabSstevel if (utsname.nodename[0] != 0) { 3160*3db86aabSstevel plat_nodename_set_fun = 3161*3db86aabSstevel (void (*)(void))modgetsymvalue( 3162*3db86aabSstevel "plat_nodename_set", 0); 3163*3db86aabSstevel if (plat_nodename_set_fun != NULL) 3164*3db86aabSstevel plat_nodename_set_fun(); 3165*3db86aabSstevel } 3166*3db86aabSstevel 3167*3db86aabSstevel current_sgn_p = (sig_state_t *)modgetsymvalue( 3168*3db86aabSstevel "current_sgn", 0); 3169*3db86aabSstevel 3170*3db86aabSstevel if ((current_sgn_p != NULL) && 3171*3db86aabSstevel (current_sgn_p->state_t.sig != 0)) { 3172*3db86aabSstevel CPU_SIGNATURE(current_sgn_p->state_t.sig, 3173*3db86aabSstevel current_sgn_p->state_t.state, 3174*3db86aabSstevel current_sgn_p->state_t.sub_state, -1); 3175*3db86aabSstevel 3176*3db86aabSstevel if (!(boothowto & RB_DEBUG)) { 3177*3db86aabSstevel send_watchdog_msg(last_watchdog_msg); 3178*3db86aabSstevel } 3179*3db86aabSstevel } 3180*3db86aabSstevel } 3181*3db86aabSstevel 3182*3db86aabSstevel /* 3183*3db86aabSstevel * update keyswitch value in case it changed while the 3184*3db86aabSstevel * RMC was out of action 3185*3db86aabSstevel */ 3186*3db86aabSstevel LOCK_CACHE 3187*3db86aabSstevel if (rmclomv_sysinfo_valid) { 3188*3db86aabSstevel real_key_position = rmclomv_sysinfo_data.keyswitch; 3189*3db86aabSstevel if ((real_key_position != RMC_KEYSWITCH_POS_UNKNOWN) && 3190*3db86aabSstevel (real_key_position <= RMC_KEYSWITCH_POS_OFF)) { 3191*3db86aabSstevel key_position = real_key_position; 3192*3db86aabSstevel } else { 3193*3db86aabSstevel /* treat unknown key position as locked */ 3194*3db86aabSstevel key_position = RMC_KEYSWITCH_POS_LOCKED; 3195*3db86aabSstevel } 3196*3db86aabSstevel } else { 3197*3db86aabSstevel /* treat unreadable key position as locked */ 3198*3db86aabSstevel key_position = RMC_KEYSWITCH_POS_LOCKED; 3199*3db86aabSstevel real_key_position = RMC_KEYSWITCH_POS_UNKNOWN; 3200*3db86aabSstevel } 3201*3db86aabSstevel RELEASE_CACHE 3202*3db86aabSstevel 3203*3db86aabSstevel /* 3204*3db86aabSstevel * Re-enter the lock to prepare for another iteration. 3205*3db86aabSstevel * We must have the lock here to protect rmclomv_refresh_sig. 3206*3db86aabSstevel */ 3207*3db86aabSstevel mutex_enter(&rmclomv_refresh_lock); 3208*3db86aabSstevel } 3209*3db86aabSstevel } 3210*3db86aabSstevel 3211*3db86aabSstevel static void 3212*3db86aabSstevel rmclomv_refresh_start(void) 3213*3db86aabSstevel { 3214*3db86aabSstevel kthread_t *tp; 3215*3db86aabSstevel 3216*3db86aabSstevel mutex_enter(&rmclomv_refresh_lock); 3217*3db86aabSstevel 3218*3db86aabSstevel if (rmclomv_refresh_tid == 0) { 3219*3db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_PROCESSNOW; 3220*3db86aabSstevel 3221*3db86aabSstevel tp = thread_create(NULL, 0, rmclomv_refresh, NULL, 0, 3222*3db86aabSstevel &p0, TS_RUN, maxclsyspri); 3223*3db86aabSstevel rmclomv_refresh_tid = tp->t_did; 3224*3db86aabSstevel } 3225*3db86aabSstevel 3226*3db86aabSstevel mutex_exit(&rmclomv_refresh_lock); 3227*3db86aabSstevel } 3228*3db86aabSstevel 3229*3db86aabSstevel static void 3230*3db86aabSstevel rmclomv_refresh_destroy(void) 3231*3db86aabSstevel { 3232*3db86aabSstevel kt_did_t tid; 3233*3db86aabSstevel 3234*3db86aabSstevel mutex_enter(&rmclomv_refresh_lock); 3235*3db86aabSstevel tid = rmclomv_refresh_tid; 3236*3db86aabSstevel if (tid != 0) { 3237*3db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_EXITNOW; 3238*3db86aabSstevel cv_signal(&rmclomv_refresh_sig_cv); 3239*3db86aabSstevel rmclomv_refresh_tid = 0; 3240*3db86aabSstevel } 3241*3db86aabSstevel mutex_exit(&rmclomv_refresh_lock); 3242*3db86aabSstevel 3243*3db86aabSstevel /* 3244*3db86aabSstevel * Wait for rmclomv_refresh() to finish 3245*3db86aabSstevel */ 3246*3db86aabSstevel if (tid != 0) 3247*3db86aabSstevel thread_join(tid); 3248*3db86aabSstevel } 3249*3db86aabSstevel 3250*3db86aabSstevel static void 3251*3db86aabSstevel rmclomv_refresh_wakeup(void) 3252*3db86aabSstevel { 3253*3db86aabSstevel mutex_enter(&rmclomv_refresh_lock); 3254*3db86aabSstevel 3255*3db86aabSstevel if (rmclomv_refresh_sig != RMCLOMV_REFRESH_EXITNOW) 3256*3db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_PROCESSNOW; 3257*3db86aabSstevel cv_signal(&rmclomv_refresh_sig_cv); 3258*3db86aabSstevel 3259*3db86aabSstevel mutex_exit(&rmclomv_refresh_lock); 3260*3db86aabSstevel } 3261*3db86aabSstevel 3262*3db86aabSstevel static void 3263*3db86aabSstevel send_watchdog_msg(int msg) 3264*3db86aabSstevel { 3265*3db86aabSstevel rmc_comm_msg_t request; 3266*3db86aabSstevel dp_set_host_watchdog_t watchdog_msg; 3267*3db86aabSstevel 3268*3db86aabSstevel if (rmclomv_watchdog_mode) 3269*3db86aabSstevel return; 3270*3db86aabSstevel 3271*3db86aabSstevel watchdog_msg.enable = msg; 3272*3db86aabSstevel request.msg_type = DP_SET_HOST_WATCHDOG; 3273*3db86aabSstevel request.msg_len = sizeof (watchdog_msg); 3274*3db86aabSstevel request.msg_buf = (caddr_t)&watchdog_msg; 3275*3db86aabSstevel (void) rmc_comm_request_nowait(&request, (msg == 1) ? 3276*3db86aabSstevel RMC_COMM_DREQ_URGENT : 0); 3277*3db86aabSstevel } 3278*3db86aabSstevel 3279*3db86aabSstevel /*ARGSUSED*/ 3280*3db86aabSstevel static uint_t 3281*3db86aabSstevel rmc_set_watchdog_timer(uint_t timeoutval) 3282*3db86aabSstevel { 3283*3db86aabSstevel ASSERT(MUTEX_HELD(&tod_lock)); 3284*3db86aabSstevel 3285*3db86aabSstevel if ((watchdog_enable == 0) || (watchdog_available == 0)) { 3286*3db86aabSstevel return (0); 3287*3db86aabSstevel } 3288*3db86aabSstevel 3289*3db86aabSstevel /* 3290*3db86aabSstevel * If boothowto has RB_DEBUG set we never want to set the watchdog 3291*3db86aabSstevel * support on. 3292*3db86aabSstevel */ 3293*3db86aabSstevel if (boothowto & RB_DEBUG) { 3294*3db86aabSstevel return (0); 3295*3db86aabSstevel } 3296*3db86aabSstevel 3297*3db86aabSstevel /* 3298*3db86aabSstevel * When the watchdog is shut off last_watchdog_msg goes from a 3299*3db86aabSstevel * 0 to a 1. So we must test to see that last_watchdog_msg is 3300*3db86aabSstevel * set to 1 indicating that watchdog was shut off and 3301*3db86aabSstevel * After which we set last_watchdog_msg back to 0 so that we do not 3302*3db86aabSstevel * run this code 3303*3db86aabSstevel * again. 3304*3db86aabSstevel */ 3305*3db86aabSstevel if (last_watchdog_msg == 1) { 3306*3db86aabSstevel send_watchdog_msg(0); 3307*3db86aabSstevel last_watchdog_msg = 0; 3308*3db86aabSstevel } 3309*3db86aabSstevel 3310*3db86aabSstevel pmugpio_watchdog_pat(); 3311*3db86aabSstevel 3312*3db86aabSstevel watchdog_activated = 1; 3313*3db86aabSstevel 3314*3db86aabSstevel return (1); 3315*3db86aabSstevel } 3316*3db86aabSstevel 3317*3db86aabSstevel static uint_t 3318*3db86aabSstevel rmc_clear_watchdog_timer(void) 3319*3db86aabSstevel { 3320*3db86aabSstevel ASSERT(MUTEX_HELD(&tod_lock)); 3321*3db86aabSstevel if ((watchdog_activated == 0) || (boothowto & RB_DEBUG)) 3322*3db86aabSstevel return (0); 3323*3db86aabSstevel 3324*3db86aabSstevel send_watchdog_msg(1); 3325*3db86aabSstevel last_watchdog_msg = 1; 3326*3db86aabSstevel watchdog_activated = 0; 3327*3db86aabSstevel 3328*3db86aabSstevel return (0); 3329*3db86aabSstevel } 3330*3db86aabSstevel 3331*3db86aabSstevel static void 3332*3db86aabSstevel plat_timesync(void *arg) 3333*3db86aabSstevel { 3334*3db86aabSstevel timestruc_t now; 3335*3db86aabSstevel todinfo_t tod; 3336*3db86aabSstevel rmc_comm_msg_t request; 3337*3db86aabSstevel dp_set_date_time_t set_time_msg; 3338*3db86aabSstevel int retval; 3339*3db86aabSstevel timestruc_t ts; 3340*3db86aabSstevel dp_get_date_time_r_t *date_and_time_info; 3341*3db86aabSstevel int buffer[DATE_TIME_MSG_SIZE]; 3342*3db86aabSstevel 3343*3db86aabSstevel /* Is the system coming up? */ 3344*3db86aabSstevel if (arg != NULL) { 3345*3db86aabSstevel /* Request the time from the RMC clock. */ 3346*3db86aabSstevel retval = rmclomv_do_cmd(DP_GET_DATE_TIME, DP_GET_DATE_TIME_R, 3347*3db86aabSstevel DATE_TIME_MSG_SIZE, NULL, (intptr_t)&buffer); 3348*3db86aabSstevel 3349*3db86aabSstevel /* 3350*3db86aabSstevel * If we were able to get the time lets set the local clock. 3351*3db86aabSstevel * The time returned from RMC is in Unix time format. 3352*3db86aabSstevel * 3353*3db86aabSstevel * If we couldn't get the time we'll accept the drift so as not 3354*3db86aabSstevel * to cause congestion on the I2C bus or cause boot 3355*3db86aabSstevel * performance regressions. 3356*3db86aabSstevel */ 3357*3db86aabSstevel if (retval == RCNOERR) { 3358*3db86aabSstevel date_and_time_info = (dp_get_date_time_r_t *)buffer; 3359*3db86aabSstevel ts.tv_sec = date_and_time_info->current_datetime; 3360*3db86aabSstevel ts.tv_nsec = 0; 3361*3db86aabSstevel mutex_enter(&tod_lock); 3362*3db86aabSstevel tod_set(ts); 3363*3db86aabSstevel set_hrestime(&ts); 3364*3db86aabSstevel mutex_exit(&tod_lock); 3365*3db86aabSstevel } 3366*3db86aabSstevel } 3367*3db86aabSstevel 3368*3db86aabSstevel gethrestime(&now); 3369*3db86aabSstevel mutex_enter(&tod_lock); 3370*3db86aabSstevel tod = utc_to_tod(now.tv_sec); 3371*3db86aabSstevel mutex_exit(&tod_lock); 3372*3db86aabSstevel 3373*3db86aabSstevel set_time_msg.year = tod.tod_year; 3374*3db86aabSstevel set_time_msg.month = tod.tod_month - 1; 3375*3db86aabSstevel set_time_msg.day = tod.tod_day; 3376*3db86aabSstevel set_time_msg.hour = tod.tod_hour; 3377*3db86aabSstevel set_time_msg.minute = tod.tod_min; 3378*3db86aabSstevel set_time_msg.second = tod.tod_sec; 3379*3db86aabSstevel 3380*3db86aabSstevel request.msg_type = DP_SET_DATE_TIME; 3381*3db86aabSstevel request.msg_len = sizeof (set_time_msg); 3382*3db86aabSstevel request.msg_buf = (caddr_t)&set_time_msg; 3383*3db86aabSstevel 3384*3db86aabSstevel (void) rmc_comm_request_nowait(&request, 0); 3385*3db86aabSstevel 3386*3db86aabSstevel (void) timeout(plat_timesync, NULL, timesync_interval); 3387*3db86aabSstevel } 3388*3db86aabSstevel 3389*3db86aabSstevel /* 3390*3db86aabSstevel * Interfaces to get/set alarm relays from outside 3391*3db86aabSstevel */ 3392*3db86aabSstevel int 3393*3db86aabSstevel rmclomv_alarm_get(int alarm_type, int *alarm_state) 3394*3db86aabSstevel { 3395*3db86aabSstevel rmclomv_cache_section_t *section; 3396*3db86aabSstevel int index; 3397*3db86aabSstevel uint16_t sensor_status; 3398*3db86aabSstevel dp_get_alarm_state_t u_rmc_alarm; 3399*3db86aabSstevel dp_get_alarm_state_r_t u_rmc_alarm_r; 3400*3db86aabSstevel 3401*3db86aabSstevel /* see if we've got ALARM handles cached */ 3402*3db86aabSstevel LOCK_CACHE 3403*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 3404*3db86aabSstevel 3405*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 3406*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 3407*3db86aabSstevel RMCLOMV_ALARM_IND)) == NULL)) { 3408*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 3409*3db86aabSstevel } 3410*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 3411*3db86aabSstevel /* 3412*3db86aabSstevel * user correctly identified a ALARM, note its 3413*3db86aabSstevel * handle value and request the ALARM status 3414*3db86aabSstevel */ 3415*3db86aabSstevel index = alarm_type; 3416*3db86aabSstevel if (index >= section->num_entries) 3417*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 3418*3db86aabSstevel else 3419*3db86aabSstevel u_rmc_alarm.handle = section->entry[index].handle; 3420*3db86aabSstevel } 3421*3db86aabSstevel RELEASE_CACHE 3422*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error || 3423*3db86aabSstevel rmclomv_do_cmd(DP_GET_ALARM_STATE, DP_GET_ALARM_STATE_R, 3424*3db86aabSstevel sizeof (u_rmc_alarm_r), (intptr_t)&u_rmc_alarm, 3425*3db86aabSstevel (intptr_t)&u_rmc_alarm_r) != 0)) { 3426*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 3427*3db86aabSstevel } 3428*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 3429*3db86aabSstevel /* 3430*3db86aabSstevel * copy results into buffer for user 3431*3db86aabSstevel * start with some defaults then override 3432*3db86aabSstevel */ 3433*3db86aabSstevel *alarm_state = 0; 3434*3db86aabSstevel 3435*3db86aabSstevel if (u_rmc_alarm_r.alarm_state[0].sensor_status != 3436*3db86aabSstevel DP_SENSOR_DATA_AVAILABLE) 3437*3db86aabSstevel return (ENXIO); 3438*3db86aabSstevel else { 3439*3db86aabSstevel dp_alarm_state_t alarmState; 3440*3db86aabSstevel alarmState = u_rmc_alarm_r.alarm_state[0]; 3441*3db86aabSstevel 3442*3db86aabSstevel switch (alarmState.state) { 3443*3db86aabSstevel case DP_ALARM_OFF: 3444*3db86aabSstevel break; 3445*3db86aabSstevel case DP_ALARM_ON: 3446*3db86aabSstevel *alarm_state = 1; 3447*3db86aabSstevel break; 3448*3db86aabSstevel default: 3449*3db86aabSstevel break; 3450*3db86aabSstevel } 3451*3db86aabSstevel } 3452*3db86aabSstevel } else 3453*3db86aabSstevel return (ENXIO); 3454*3db86aabSstevel 3455*3db86aabSstevel return (0); 3456*3db86aabSstevel } 3457*3db86aabSstevel 3458*3db86aabSstevel int 3459*3db86aabSstevel rmclomv_alarm_set(int alarm_type, int new_state) 3460*3db86aabSstevel { 3461*3db86aabSstevel rmclomv_cache_section_t *section; 3462*3db86aabSstevel int index; 3463*3db86aabSstevel uint16_t sensor_status; 3464*3db86aabSstevel dp_set_alarm_state_t u_rmc_setalarm; 3465*3db86aabSstevel dp_set_alarm_state_r_t u_rmc_setalarm_r; 3466*3db86aabSstevel 3467*3db86aabSstevel /* see if we've got ALARM handles cached */ 3468*3db86aabSstevel LOCK_CACHE 3469*3db86aabSstevel sensor_status = ENVMON_SENSOR_OK; 3470*3db86aabSstevel 3471*3db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) || 3472*3db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache, 3473*3db86aabSstevel RMCLOMV_ALARM_IND)) == NULL)) { 3474*3db86aabSstevel sensor_status = ENVMON_NOT_PRESENT; 3475*3db86aabSstevel } 3476*3db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) { 3477*3db86aabSstevel /* 3478*3db86aabSstevel * user correctly identified a ALARM, note its 3479*3db86aabSstevel * handle value and request the ALARM status 3480*3db86aabSstevel */ 3481*3db86aabSstevel index = alarm_type; 3482*3db86aabSstevel if (index >= section->num_entries) 3483*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 3484*3db86aabSstevel else { 3485*3db86aabSstevel u_rmc_setalarm.handle = section->entry[index].handle; 3486*3db86aabSstevel u_rmc_setalarm.state = new_state; 3487*3db86aabSstevel } 3488*3db86aabSstevel } 3489*3db86aabSstevel RELEASE_CACHE 3490*3db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && 3491*3db86aabSstevel (rmclomv_rmc_error || 3492*3db86aabSstevel rmclomv_do_cmd(DP_SET_ALARM_STATE, DP_SET_ALARM_STATE_R, 3493*3db86aabSstevel sizeof (u_rmc_setalarm_r), (intptr_t)&u_rmc_setalarm, 3494*3db86aabSstevel (intptr_t)&u_rmc_setalarm_r) != 0)) { 3495*3db86aabSstevel sensor_status = ENVMON_INACCESSIBLE; 3496*3db86aabSstevel } 3497*3db86aabSstevel 3498*3db86aabSstevel if (u_rmc_setalarm_r.status != DP_SET_ALARM_OK) { 3499*3db86aabSstevel return (EIO); 3500*3db86aabSstevel } 3501*3db86aabSstevel 3502*3db86aabSstevel if (sensor_status != ENVMON_SENSOR_OK) { 3503*3db86aabSstevel return (ENXIO); 3504*3db86aabSstevel } 3505*3db86aabSstevel 3506*3db86aabSstevel return (0); 3507*3db86aabSstevel } 3508