13db86aabSstevel /*
23db86aabSstevel * CDDL HEADER START
33db86aabSstevel *
43db86aabSstevel * The contents of this file are subject to the terms of the
53db86aabSstevel * Common Development and Distribution License (the "License").
63db86aabSstevel * You may not use this file except in compliance with the License.
73db86aabSstevel *
83db86aabSstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93db86aabSstevel * or http://www.opensolaris.org/os/licensing.
103db86aabSstevel * See the License for the specific language governing permissions
113db86aabSstevel * and limitations under the License.
123db86aabSstevel *
133db86aabSstevel * When distributing Covered Code, include this CDDL HEADER in each
143db86aabSstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153db86aabSstevel * If applicable, add the following below this CDDL HEADER, with the
163db86aabSstevel * fields enclosed by brackets "[]" replaced with your own identifying
173db86aabSstevel * information: Portions Copyright [yyyy] [name of copyright owner]
183db86aabSstevel *
193db86aabSstevel * CDDL HEADER END
203db86aabSstevel */
213db86aabSstevel
223db86aabSstevel /*
2319397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
243db86aabSstevel * Use is subject to license terms.
253db86aabSstevel */
263db86aabSstevel
273db86aabSstevel
283db86aabSstevel #include <sys/types.h>
293db86aabSstevel #include <sys/stat.h>
303db86aabSstevel #include <sys/conf.h>
313db86aabSstevel #include <sys/modctl.h>
323db86aabSstevel #include <sys/callb.h>
333db86aabSstevel #include <sys/strlog.h>
343db86aabSstevel #include <sys/cyclic.h>
353db86aabSstevel #include <sys/rmc_comm_dp.h>
363db86aabSstevel #include <sys/rmc_comm_dp_boot.h>
373db86aabSstevel #include <sys/rmc_comm_drvintf.h>
383db86aabSstevel #include <sys/rmc_comm.h>
393db86aabSstevel #include <sys/machsystm.h>
403db86aabSstevel #include <sys/sysevent.h>
413db86aabSstevel #include <sys/sysevent/dr.h>
423db86aabSstevel #include <sys/sysevent/env.h>
433db86aabSstevel #include <sys/sysevent/eventdefs.h>
443db86aabSstevel #include <sys/file.h>
453db86aabSstevel #include <sys/disp.h>
463db86aabSstevel #include <sys/reboot.h>
473db86aabSstevel #include <sys/envmon.h>
483db86aabSstevel #include <sys/rmclomv_impl.h>
493db86aabSstevel #include <sys/cpu_sgnblk_defs.h>
503db86aabSstevel #include <sys/utsname.h>
513db86aabSstevel #include <sys/systeminfo.h>
523db86aabSstevel #include <sys/ddi.h>
533db86aabSstevel #include <sys/time.h>
543db86aabSstevel #include <sys/promif.h>
55*c5d54b67SRichard Lowe #include <sys/sysmacros.h>
563db86aabSstevel
573db86aabSstevel #define RMCRESBUFLEN 1024
583db86aabSstevel #define DATE_TIME_MSG_SIZE 78
593db86aabSstevel #define RMCLOMV_WATCHDOG_MODE "rmclomv-watchdog-mode"
60f594b28aSjfrank #define DELAY_TIME 5000000 /* 5 seconds, in microseconds */
61f594b28aSjfrank #define CPU_SIGNATURE_DELAY_TIME 5000000 /* 5 secs, in microsecs */
623db86aabSstevel
633db86aabSstevel extern void pmugpio_watchdog_pat();
643db86aabSstevel
653db86aabSstevel extern int watchdog_activated;
663db86aabSstevel static int last_watchdog_msg = 1;
673db86aabSstevel extern int watchdog_enable;
683db86aabSstevel extern int boothowto;
693db86aabSstevel
703db86aabSstevel int rmclomv_watchdog_mode;
713db86aabSstevel
723db86aabSstevel /*
733db86aabSstevel * functions local to this driver.
743db86aabSstevel */
753db86aabSstevel static int rmclomv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
763db86aabSstevel void **resultp);
773db86aabSstevel static int rmclomv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
783db86aabSstevel static int rmclomv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
793db86aabSstevel static uint_t rmclomv_break_intr(caddr_t arg);
803db86aabSstevel static int rmclomv_add_intr_handlers(void);
813db86aabSstevel static int rmclomv_remove_intr_handlers(void);
823db86aabSstevel static uint_t rmclomv_event_data_handler(char *);
833db86aabSstevel static void rmclomv_dr_data_handler(const char *, int);
843db86aabSstevel static int rmclomv_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p);
853db86aabSstevel static int rmclomv_close(dev_t dev, int flag, int otyp, cred_t *cred_p);
863db86aabSstevel static int rmclomv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
873db86aabSstevel cred_t *cred_p, int *rval_p);
883db86aabSstevel static void rmclomv_checkrmc_start(void);
893db86aabSstevel static void rmclomv_checkrmc_destroy(void);
903db86aabSstevel static void rmclomv_checkrmc_wakeup(void *);
913db86aabSstevel static void rmclomv_refresh_start(void);
923db86aabSstevel static void rmclomv_refresh_destroy(void);
933db86aabSstevel static void rmclomv_refresh_wakeup(void);
943db86aabSstevel static void rmclomv_reset_cache(rmclomv_cache_section_t *new_chain,
953db86aabSstevel rmclomv_cache_section_t *new_subchain, dp_get_sysinfo_r_t *sysinfo);
963db86aabSstevel static rmclomv_cache_section_t *rmclomv_find_section(
973db86aabSstevel rmclomv_cache_section_t *start, uint16_t sensor);
983db86aabSstevel static rmclomv_cache_section_t *create_cache_section(int sensor_type, int num);
993db86aabSstevel static int get_sensor_by_name(const rmclomv_cache_section_t *section,
1003db86aabSstevel const char *name, int *index);
1013db86aabSstevel static int validate_section_entry(rmclomv_cache_section_t *section,
1023db86aabSstevel int index);
1033db86aabSstevel static int add_names_to_section(rmclomv_cache_section_t *section);
1043db86aabSstevel static void free_section(rmclomv_cache_section_t *section);
1053db86aabSstevel static void add_section(rmclomv_cache_section_t **head,
1063db86aabSstevel rmclomv_cache_section_t *section);
1073db86aabSstevel static int rmclomv_do_cmd(int req_cmd, int resp_cmd, int resp_len,
1083db86aabSstevel intptr_t arg_req, intptr_t arg_res);
1093db86aabSstevel static void refresh_name_cache(int force_fail);
1103db86aabSstevel static void set_val_unav(envmon_sensor_t *sensor);
1113db86aabSstevel static void set_fan_unav(envmon_fan_t *fan);
1123db86aabSstevel static int do_psu_cmd(intptr_t arg, int mode, envmon_indicator_t *env_ind,
1133db86aabSstevel dp_get_psu_status_t *rmc_psu, dp_get_psu_status_r_t *rmc_psu_r,
1143db86aabSstevel int detector_type);
1153db86aabSstevel static uint_t rmc_set_watchdog_timer(uint_t timeoutval);
1163db86aabSstevel static uint_t rmc_clear_watchdog_timer(void);
1173db86aabSstevel static void send_watchdog_msg(int msg);
1183db86aabSstevel static void plat_timesync(void *arg);
1193db86aabSstevel
120da14cebeSEric Cheng static kmutex_t timesync_lock;
121da14cebeSEric Cheng static clock_t timesync_interval = 0;
122da14cebeSEric Cheng static timeout_id_t timesync_tid = 0;
123da14cebeSEric Cheng
1243db86aabSstevel /*
1253db86aabSstevel * Driver entry points
1263db86aabSstevel */
1273db86aabSstevel static struct cb_ops rmclomv_cb_ops = {
1283db86aabSstevel rmclomv_open, /* open */
1293db86aabSstevel rmclomv_close, /* close */
1303db86aabSstevel nodev, /* strategy() */
1313db86aabSstevel nodev, /* print() */
1323db86aabSstevel nodev, /* dump() */
1333db86aabSstevel nodev, /* read() */
1343db86aabSstevel nodev, /* write() */
1353db86aabSstevel rmclomv_ioctl, /* ioctl() */
1363db86aabSstevel nodev, /* devmap() */
1373db86aabSstevel nodev, /* mmap() */
1383db86aabSstevel ddi_segmap, /* segmap() */
1393db86aabSstevel nochpoll, /* poll() */
1403db86aabSstevel ddi_prop_op, /* prop_op() */
1413db86aabSstevel NULL, /* cb_str */
1423db86aabSstevel D_NEW | D_MP /* cb_flag */
1433db86aabSstevel };
1443db86aabSstevel
1453db86aabSstevel
1463db86aabSstevel static struct dev_ops rmclomv_ops = {
1473db86aabSstevel DEVO_REV,
1483db86aabSstevel 0, /* ref count */
1493db86aabSstevel rmclomv_getinfo, /* getinfo() */
1503db86aabSstevel nulldev, /* identify() */
1513db86aabSstevel nulldev, /* probe() */
1523db86aabSstevel rmclomv_attach, /* attach() */
1533db86aabSstevel rmclomv_detach, /* detach */
1543db86aabSstevel nodev, /* reset */
1553db86aabSstevel &rmclomv_cb_ops, /* pointer to cb_ops structure */
1563db86aabSstevel (struct bus_ops *)NULL,
15719397407SSherry Moore nulldev, /* power() */
15819397407SSherry Moore ddi_quiesce_not_supported, /* devo_quiesce */
1593db86aabSstevel };
1603db86aabSstevel
1613db86aabSstevel /*
1623db86aabSstevel * Loadable module support.
1633db86aabSstevel */
1643db86aabSstevel extern struct mod_ops mod_driverops;
1653db86aabSstevel
1663db86aabSstevel static struct modldrv modldrv = {
1673db86aabSstevel &mod_driverops, /* Type of module. This is a driver */
16819397407SSherry Moore "rmclomv control driver", /* Name of the module */
1693db86aabSstevel &rmclomv_ops /* pointer to the dev_ops structure */
1703db86aabSstevel };
1713db86aabSstevel
1723db86aabSstevel static struct modlinkage modlinkage = {
1733db86aabSstevel MODREV_1,
1743db86aabSstevel &modldrv,
1753db86aabSstevel NULL
1763db86aabSstevel };
1773db86aabSstevel
1783db86aabSstevel /*
1793db86aabSstevel * Device info
1803db86aabSstevel */
1813db86aabSstevel static dev_info_t *rmclomv_dip = NULL;
1823db86aabSstevel static int rmclomv_break_requested = B_FALSE;
1833db86aabSstevel static ddi_softintr_t rmclomv_softintr_id;
1843db86aabSstevel static ddi_iblock_cookie_t rmclomv_soft_iblock_cookie;
1853db86aabSstevel
1863db86aabSstevel extern void (*abort_seq_handler)();
1873db86aabSstevel /* key_position is effective key-position. Set to locked if unknown */
1883db86aabSstevel static rsci8 key_position = RMC_KEYSWITCH_POS_LOCKED;
1893db86aabSstevel /* real_key_position starts off as unknown and records value actually seen */
1903db86aabSstevel static rsci8 real_key_position = RMC_KEYSWITCH_POS_UNKNOWN;
1913db86aabSstevel static void rmclomv_abort_seq_handler(char *msg);
1923db86aabSstevel
1933db86aabSstevel /*
1943db86aabSstevel * mutexes which protect the interrupt handlers.
1953db86aabSstevel */
1963db86aabSstevel static kmutex_t rmclomv_event_hdlr_lock;
1973db86aabSstevel static kmutex_t rmclomv_refresh_lock;
1983db86aabSstevel static kcondvar_t rmclomv_refresh_sig_cv;
1993db86aabSstevel static kmutex_t rmclomv_checkrmc_lock;
2003db86aabSstevel static kcondvar_t rmclomv_checkrmc_sig_cv;
2013db86aabSstevel
2023db86aabSstevel /*
2033db86aabSstevel * mutex to protect the handle_name cache
2043db86aabSstevel */
2053db86aabSstevel static kmutex_t rmclomv_cache_lock;
2063db86aabSstevel
2073db86aabSstevel /*
2083db86aabSstevel * mutex to protect the RMC state
2093db86aabSstevel */
2103db86aabSstevel static kmutex_t rmclomv_state_lock;
2113db86aabSstevel
2123db86aabSstevel /*
2133db86aabSstevel * Payloads of the event handlers.
2143db86aabSstevel */
2153db86aabSstevel static dp_event_notification_t rmclomv_event_payload;
2163db86aabSstevel static rmc_comm_msg_t rmclomv_event_payload_msg;
2173db86aabSstevel
2183db86aabSstevel /*
2193db86aabSstevel * Checkrmc commands..
2203db86aabSstevel */
2213db86aabSstevel #define RMCLOMV_CHECKRMC_EXITNOW (-1)
2223db86aabSstevel #define RMCLOMV_CHECKRMC_WAIT 0
2233db86aabSstevel #define RMCLOMV_CHECKRMC_PROCESSNOW 1
2243db86aabSstevel
2253db86aabSstevel /*
2263db86aabSstevel * Checkrmc thread state
2273db86aabSstevel */
2283db86aabSstevel static int rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_WAIT;
2293db86aabSstevel static kt_did_t rmclomv_checkrmc_tid = 0;
2303db86aabSstevel
2313db86aabSstevel /*
2323db86aabSstevel * RMC state data
2333db86aabSstevel */
2343db86aabSstevel #define RMCLOMV_RMCSTATE_UNKNOWN 0
2353db86aabSstevel #define RMCLOMV_RMCSTATE_OK 1
2363db86aabSstevel #define RMCLOMV_RMCSTATE_FAILED 2
2373db86aabSstevel #define RMCLOMV_RMCSTATE_DOWNLOAD 3
2383db86aabSstevel
2393db86aabSstevel /*
2403db86aabSstevel * RMC error indicator values (status from last RMC command)
2413db86aabSstevel */
2423db86aabSstevel #define RMCLOMV_RMCERROR_NONE 0
2433db86aabSstevel
2443db86aabSstevel /* fail RMC after 5 minutes without a good response */
2453db86aabSstevel #define RMCLOMV_RMCFAILTHRESHOLD 5
2463db86aabSstevel
2473db86aabSstevel /*
2483db86aabSstevel * rmclomv_rmc_state is the state reported in OperationalStatus.
2493db86aabSstevel * rmclomv_rmc_error reflects the result of the last RMC interaction.
2503db86aabSstevel * rmclomv_rmcfailcount is used by the rmclomv_checkrmc thread to count
2513db86aabSstevel * failures in its regular status polls. Once RMCLOMV_RMCFAILTHRESHOLD
2523db86aabSstevel * is reached, rmclomv_rmc_state is marked as RMCLOMV_RMCSTATE_FAILED.
2533db86aabSstevel */
2543db86aabSstevel static int rmclomv_rmc_state = RMCLOMV_RMCSTATE_UNKNOWN;
2553db86aabSstevel static int rmclomv_rmc_error = RMCLOMV_RMCERROR_NONE;
2563db86aabSstevel static int rmclomv_rmcfailcount;
2573db86aabSstevel
2583db86aabSstevel /*
2593db86aabSstevel * Refresh commands..
2603db86aabSstevel */
2613db86aabSstevel #define RMCLOMV_REFRESH_EXITNOW (-1)
2623db86aabSstevel #define RMCLOMV_REFRESH_WAIT 0
2633db86aabSstevel #define RMCLOMV_REFRESH_PROCESSNOW 1
2643db86aabSstevel
2653db86aabSstevel /*
2663db86aabSstevel * Refresh thread state
2673db86aabSstevel */
2683db86aabSstevel static int rmclomv_refresh_sig = RMCLOMV_REFRESH_WAIT;
2693db86aabSstevel static kt_did_t rmclomv_refresh_tid = 0;
2703db86aabSstevel
2713db86aabSstevel /*
2723db86aabSstevel * timeout id
2733db86aabSstevel */
2743db86aabSstevel static timeout_id_t timer_id;
2753db86aabSstevel
2763db86aabSstevel /*
2773db86aabSstevel * Handle-name cache
2783db86aabSstevel */
2793db86aabSstevel #define LOCK_CACHE mutex_enter(&rmclomv_cache_lock);
2803db86aabSstevel #define RELEASE_CACHE mutex_exit(&rmclomv_cache_lock);
2813db86aabSstevel static rmclomv_cache_section_t *rmclomv_cache; /* main handle-names */
2823db86aabSstevel static rmclomv_cache_section_t *rmclomv_subcache; /* derived names */
2833db86aabSstevel static dp_get_sysinfo_r_t rmclomv_sysinfo_data;
2843db86aabSstevel static boolean_t rmclomv_sysinfo_valid;
2853db86aabSstevel static int rmclomv_cache_valid;
2863db86aabSstevel
2873db86aabSstevel extern pri_t maxclsyspri;
2883db86aabSstevel
2893db86aabSstevel /*
2903db86aabSstevel * static strings
2913db86aabSstevel */
2923db86aabSstevel static const char str_percent[] = "%";
2933db86aabSstevel static const char str_rpm[] = " rpm";
2943db86aabSstevel static const char str_ip_volts_ind[] = "P_PWR";
2953db86aabSstevel static const char str_ip2_volts_ind[] = "P_PWR2";
2963db86aabSstevel static const char str_ff_pok_ind[] = "FF_POK";
2973db86aabSstevel static const char str_vlo_volts_ind[] = "FF_UV";
2983db86aabSstevel static const char str_vhi_volts_ind[] = "FF_OV";
2993db86aabSstevel static const char str_chi_amps_ind[] = "FF_OC";
3003db86aabSstevel static const char str_chi_nr_ind[] = "FF_NR";
3013db86aabSstevel static const char str_ot_tmpr_ind[] = "FF_OT";
3023db86aabSstevel static const char str_fan_ind[] = "FF_FAN";
3033db86aabSstevel static const char str_pdct_fan_ind[] = "FF_PDCT_FAN";
3043db86aabSstevel static const char str_sc[] = "SC";
3053db86aabSstevel
3063db86aabSstevel int
_init(void)3073db86aabSstevel _init(void)
3083db86aabSstevel {
3093db86aabSstevel int error = 0;
3103db86aabSstevel
3113db86aabSstevel mutex_init(&rmclomv_event_hdlr_lock, NULL, MUTEX_DEFAULT, NULL);
3123db86aabSstevel mutex_init(&rmclomv_checkrmc_lock, NULL, MUTEX_DRIVER, NULL);
3133db86aabSstevel mutex_init(&rmclomv_refresh_lock, NULL, MUTEX_DRIVER, NULL);
3143db86aabSstevel mutex_init(&rmclomv_cache_lock, NULL, MUTEX_DRIVER, NULL);
3153db86aabSstevel mutex_init(&rmclomv_state_lock, NULL, MUTEX_DRIVER, NULL);
316da14cebeSEric Cheng mutex_init(×ync_lock, NULL, MUTEX_DEFAULT, NULL);
3173db86aabSstevel cv_init(&rmclomv_checkrmc_sig_cv, NULL, CV_DRIVER, NULL);
3183db86aabSstevel cv_init(&rmclomv_refresh_sig_cv, NULL, CV_DRIVER, NULL);
3193db86aabSstevel
3203db86aabSstevel error = mod_install(&modlinkage);
3213db86aabSstevel if (error) {
3223db86aabSstevel cv_destroy(&rmclomv_refresh_sig_cv);
3233db86aabSstevel cv_destroy(&rmclomv_checkrmc_sig_cv);
3243db86aabSstevel mutex_destroy(&rmclomv_state_lock);
3253db86aabSstevel mutex_destroy(&rmclomv_cache_lock);
3263db86aabSstevel mutex_destroy(&rmclomv_refresh_lock);
3273db86aabSstevel mutex_destroy(&rmclomv_checkrmc_lock);
3283db86aabSstevel mutex_destroy(&rmclomv_event_hdlr_lock);
3293db86aabSstevel }
3303db86aabSstevel return (error);
3313db86aabSstevel }
3323db86aabSstevel
3333db86aabSstevel
3343db86aabSstevel int
_info(struct modinfo * modinfop)3353db86aabSstevel _info(struct modinfo *modinfop)
3363db86aabSstevel {
3373db86aabSstevel return (mod_info(&modlinkage, modinfop));
3383db86aabSstevel }
3393db86aabSstevel
3403db86aabSstevel
3413db86aabSstevel int
_fini(void)3423db86aabSstevel _fini(void)
3433db86aabSstevel {
3443db86aabSstevel int error = 0;
3453db86aabSstevel
3463db86aabSstevel error = mod_remove(&modlinkage);
3473db86aabSstevel if (error)
3483db86aabSstevel return (error);
3493db86aabSstevel cv_destroy(&rmclomv_refresh_sig_cv);
3503db86aabSstevel cv_destroy(&rmclomv_checkrmc_sig_cv);
351da14cebeSEric Cheng mutex_destroy(×ync_lock);
3523db86aabSstevel mutex_destroy(&rmclomv_state_lock);
3533db86aabSstevel mutex_destroy(&rmclomv_cache_lock);
3543db86aabSstevel mutex_destroy(&rmclomv_refresh_lock);
3553db86aabSstevel mutex_destroy(&rmclomv_checkrmc_lock);
3563db86aabSstevel mutex_destroy(&rmclomv_event_hdlr_lock);
3573db86aabSstevel return (error);
3583db86aabSstevel }
3593db86aabSstevel
3603db86aabSstevel
3613db86aabSstevel /* ARGSUSED */
3623db86aabSstevel static int
rmclomv_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)3633db86aabSstevel rmclomv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
3643db86aabSstevel {
3653db86aabSstevel minor_t m = getminor((dev_t)arg);
3663db86aabSstevel
3673db86aabSstevel switch (cmd) {
3683db86aabSstevel case DDI_INFO_DEVT2DEVINFO:
3693db86aabSstevel if ((m != 0) || (rmclomv_dip == NULL)) {
3703db86aabSstevel *resultp = NULL;
3713db86aabSstevel return (DDI_FAILURE);
3723db86aabSstevel }
3733db86aabSstevel *resultp = rmclomv_dip;
3743db86aabSstevel return (DDI_SUCCESS);
3753db86aabSstevel case DDI_INFO_DEVT2INSTANCE:
3763db86aabSstevel *resultp = (void *)(uintptr_t)m;
3773db86aabSstevel return (DDI_SUCCESS);
3783db86aabSstevel default:
3793db86aabSstevel return (DDI_FAILURE);
3803db86aabSstevel }
3813db86aabSstevel }
3823db86aabSstevel
3833db86aabSstevel
3843db86aabSstevel static int
rmclomv_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)3853db86aabSstevel rmclomv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3863db86aabSstevel {
3873db86aabSstevel int instance;
3883db86aabSstevel int err;
3893db86aabSstevel char *wdog_state;
3903db86aabSstevel int attaching = 1;
3913db86aabSstevel
3923db86aabSstevel switch (cmd) {
3933db86aabSstevel case DDI_ATTACH:
3943db86aabSstevel /*
3953db86aabSstevel * only allow one instance
3963db86aabSstevel */
3973db86aabSstevel instance = ddi_get_instance(dip);
3983db86aabSstevel if (instance != 0)
3993db86aabSstevel return (DDI_FAILURE);
4003db86aabSstevel
4013db86aabSstevel err = ddi_create_minor_node(dip, "rmclomv", S_IFCHR,
4023db86aabSstevel instance, DDI_PSEUDO, NULL);
4033db86aabSstevel if (err != DDI_SUCCESS)
4043db86aabSstevel return (DDI_FAILURE);
4053db86aabSstevel
4063db86aabSstevel /*
4073db86aabSstevel * Register with rmc_comm to prevent it being detached
4083db86aabSstevel * (in the unlikely event that its attach succeeded on a
4093db86aabSstevel * platform whose platmod doesn't lock it down).
4103db86aabSstevel */
4113db86aabSstevel err = rmc_comm_register();
4123db86aabSstevel if (err != DDI_SUCCESS) {
4133db86aabSstevel ddi_remove_minor_node(dip, NULL);
4143db86aabSstevel return (DDI_FAILURE);
4153db86aabSstevel }
4163db86aabSstevel
4173db86aabSstevel /* Remember the dev info */
4183db86aabSstevel rmclomv_dip = dip;
4193db86aabSstevel
4203db86aabSstevel /*
4213db86aabSstevel * Add the handlers which watch for unsolicited messages
4223db86aabSstevel * and post event to Sysevent Framework.
4233db86aabSstevel */
4243db86aabSstevel err = rmclomv_add_intr_handlers();
4253db86aabSstevel if (err != DDI_SUCCESS) {
4263db86aabSstevel rmc_comm_unregister();
4273db86aabSstevel ddi_remove_minor_node(dip, NULL);
4283db86aabSstevel rmclomv_dip = NULL;
4293db86aabSstevel return (DDI_FAILURE);
4303db86aabSstevel }
4313db86aabSstevel
4323db86aabSstevel rmclomv_checkrmc_start();
4333db86aabSstevel rmclomv_refresh_start();
4343db86aabSstevel
4353db86aabSstevel abort_seq_handler = rmclomv_abort_seq_handler;
4363db86aabSstevel ddi_report_dev(dip);
4373db86aabSstevel
4383db86aabSstevel /*
4393db86aabSstevel * Check whether we have an application watchdog
4403db86aabSstevel */
4413db86aabSstevel if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
4423db86aabSstevel DDI_PROP_DONTPASS, RMCLOMV_WATCHDOG_MODE,
4433db86aabSstevel &wdog_state) == DDI_PROP_SUCCESS) {
4443db86aabSstevel if (strcmp(wdog_state, "app") == 0) {
4453db86aabSstevel rmclomv_watchdog_mode = 1;
4463db86aabSstevel watchdog_enable = 0;
4473db86aabSstevel }
4483db86aabSstevel else
4493db86aabSstevel rmclomv_watchdog_mode = 0;
4503db86aabSstevel ddi_prop_free(wdog_state);
4513db86aabSstevel }
4523db86aabSstevel
4533db86aabSstevel tod_ops.tod_set_watchdog_timer = rmc_set_watchdog_timer;
4543db86aabSstevel tod_ops.tod_clear_watchdog_timer = rmc_clear_watchdog_timer;
4553db86aabSstevel
4563db86aabSstevel /*
4573db86aabSstevel * Now is a good time to activate hardware watchdog
4583db86aabSstevel * (if one exists).
4593db86aabSstevel */
4603db86aabSstevel mutex_enter(&tod_lock);
4613db86aabSstevel if (watchdog_enable && tod_ops.tod_set_watchdog_timer != NULL)
4623db86aabSstevel err = tod_ops.tod_set_watchdog_timer(0);
4633db86aabSstevel mutex_exit(&tod_lock);
4643db86aabSstevel if (err != 0)
4653db86aabSstevel printf("Hardware watchdog enabled\n");
4663db86aabSstevel
4673db86aabSstevel /*
4683db86aabSstevel * Set time interval and start timesync routine.
4693db86aabSstevel * Also just this once set the Solaris clock
4703db86aabSstevel * to the RMC clock.
4713db86aabSstevel */
4723db86aabSstevel timesync_interval = drv_usectohz(5*60 * MICROSEC);
4733db86aabSstevel plat_timesync((void *) &attaching);
4743db86aabSstevel
4753db86aabSstevel return (DDI_SUCCESS);
4763db86aabSstevel case DDI_RESUME:
4773db86aabSstevel return (DDI_SUCCESS);
4783db86aabSstevel default:
4793db86aabSstevel return (DDI_FAILURE);
4803db86aabSstevel }
4813db86aabSstevel }
4823db86aabSstevel
4833db86aabSstevel
4843db86aabSstevel static int
rmclomv_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)4853db86aabSstevel rmclomv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
4863db86aabSstevel {
487da14cebeSEric Cheng timeout_id_t tid;
4883db86aabSstevel int instance;
4893db86aabSstevel int err;
4903db86aabSstevel
4913db86aabSstevel switch (cmd) {
4923db86aabSstevel case DDI_DETACH:
4933db86aabSstevel instance = ddi_get_instance(dip);
4943db86aabSstevel if (instance != 0)
4953db86aabSstevel return (DDI_FAILURE);
4963db86aabSstevel
4973db86aabSstevel /*
4983db86aabSstevel * Remove the handlers which watch for unsolicited messages
4993db86aabSstevel * and post event to Sysevent Framework.
5003db86aabSstevel */
5013db86aabSstevel err = rmclomv_remove_intr_handlers();
5023db86aabSstevel if (err != DDI_SUCCESS) {
5033db86aabSstevel cmn_err(CE_WARN, "Failed to remove event handlers");
5043db86aabSstevel return (DDI_FAILURE);
5053db86aabSstevel }
5063db86aabSstevel rmclomv_checkrmc_destroy();
5073db86aabSstevel rmclomv_refresh_destroy();
5083db86aabSstevel rmclomv_reset_cache(NULL, NULL, NULL);
5093db86aabSstevel ddi_remove_minor_node(dip, NULL);
5103db86aabSstevel
511da14cebeSEric Cheng mutex_enter(×ync_lock);
512da14cebeSEric Cheng tid = timesync_tid;
513da14cebeSEric Cheng timesync_tid = 0;
514da14cebeSEric Cheng timesync_interval = 0;
515da14cebeSEric Cheng mutex_exit(×ync_lock);
516da14cebeSEric Cheng (void) untimeout(tid);
517da14cebeSEric Cheng
5183db86aabSstevel /* Forget the dev info */
5193db86aabSstevel rmclomv_dip = NULL;
5203db86aabSstevel rmc_comm_unregister();
5213db86aabSstevel return (DDI_SUCCESS);
5223db86aabSstevel case DDI_SUSPEND:
5233db86aabSstevel return (DDI_SUCCESS);
5243db86aabSstevel default:
5253db86aabSstevel return (DDI_FAILURE);
5263db86aabSstevel }
5273db86aabSstevel }
5283db86aabSstevel
5293db86aabSstevel static int
rmclomv_add_intr_handlers()5303db86aabSstevel rmclomv_add_intr_handlers()
5313db86aabSstevel {
5323db86aabSstevel int err;
5333db86aabSstevel
5343db86aabSstevel if (ddi_get_soft_iblock_cookie(rmclomv_dip, DDI_SOFTINT_HIGH,
5353db86aabSstevel &rmclomv_soft_iblock_cookie) != DDI_SUCCESS) {
5363db86aabSstevel return (DDI_FAILURE);
5373db86aabSstevel }
5383db86aabSstevel err = ddi_add_softintr(rmclomv_dip, DDI_SOFTINT_HIGH,
5393db86aabSstevel &rmclomv_softintr_id, &rmclomv_soft_iblock_cookie, NULL,
5403db86aabSstevel rmclomv_break_intr, NULL);
5413db86aabSstevel if (err != DDI_SUCCESS)
5423db86aabSstevel return (DDI_FAILURE);
5433db86aabSstevel rmclomv_event_payload_msg.msg_buf = (caddr_t)&rmclomv_event_payload;
5443db86aabSstevel rmclomv_event_payload_msg.msg_len = sizeof (rmclomv_event_payload);
5453db86aabSstevel err = rmc_comm_reg_intr(DP_RMC_EVENTS, rmclomv_event_data_handler,
5463db86aabSstevel &rmclomv_event_payload_msg, NULL, &rmclomv_event_hdlr_lock);
5473db86aabSstevel if (err != 0) {
5483db86aabSstevel ddi_remove_softintr(rmclomv_softintr_id);
5493db86aabSstevel return (DDI_FAILURE);
5503db86aabSstevel }
5513db86aabSstevel return (DDI_SUCCESS);
5523db86aabSstevel }
5533db86aabSstevel
5543db86aabSstevel static int
rmclomv_remove_intr_handlers(void)5553db86aabSstevel rmclomv_remove_intr_handlers(void)
5563db86aabSstevel {
5573db86aabSstevel int err = rmc_comm_unreg_intr(DP_RMC_EVENTS,
5583db86aabSstevel rmclomv_event_data_handler);
5593db86aabSstevel if (err != 0) {
5603db86aabSstevel cmn_err(CE_WARN, "Failed to unregister DP_RMC_EVENTS "
5613db86aabSstevel "handler. Err=%d", err);
5623db86aabSstevel return (DDI_FAILURE);
5633db86aabSstevel }
5643db86aabSstevel ddi_remove_softintr(rmclomv_softintr_id);
5653db86aabSstevel return (DDI_SUCCESS);
5663db86aabSstevel }
5673db86aabSstevel
5683db86aabSstevel static void
rmclomv_abort_seq_handler(char * msg)5693db86aabSstevel rmclomv_abort_seq_handler(char *msg)
5703db86aabSstevel {
5713db86aabSstevel if (key_position == RMC_KEYSWITCH_POS_LOCKED)
5723db86aabSstevel cmn_err(CE_CONT, "KEY in LOCKED position, "
5733db86aabSstevel "ignoring debug enter sequence");
5743db86aabSstevel else {
5753db86aabSstevel rmclomv_break_requested = B_TRUE;
5763db86aabSstevel if (msg != NULL)
5773db86aabSstevel prom_printf("%s\n", msg);
5783db86aabSstevel
5793db86aabSstevel ddi_trigger_softintr(rmclomv_softintr_id);
5803db86aabSstevel }
5813db86aabSstevel }
5823db86aabSstevel
5833db86aabSstevel /* ARGSUSED */
5843db86aabSstevel static uint_t
rmclomv_break_intr(caddr_t arg)5853db86aabSstevel rmclomv_break_intr(caddr_t arg)
5863db86aabSstevel {
5873db86aabSstevel if (rmclomv_break_requested) {
5883db86aabSstevel rmclomv_break_requested = B_FALSE;
5893db86aabSstevel debug_enter(NULL);
5903db86aabSstevel return (DDI_INTR_CLAIMED);
5913db86aabSstevel }
5923db86aabSstevel
5933db86aabSstevel return (DDI_INTR_UNCLAIMED);
5943db86aabSstevel }
5953db86aabSstevel
5963db86aabSstevel /*
5973db86aabSstevel * Create a cache section structure
5983db86aabSstevel */
5993db86aabSstevel static rmclomv_cache_section_t *
create_cache_section(int sensor_type,int num)6003db86aabSstevel create_cache_section(int sensor_type, int num)
6013db86aabSstevel {
6023db86aabSstevel size_t len = offsetof(rmclomv_cache_section_t, entry[0]) +
6033db86aabSstevel num * sizeof (rmclomv_cache_entry_t);
6043db86aabSstevel rmclomv_cache_section_t *ptr = kmem_zalloc(len, KM_SLEEP);
6053db86aabSstevel ptr->next_section = NULL;
6063db86aabSstevel ptr->sensor_type = sensor_type;
6073db86aabSstevel ptr->num_entries = num;
6083db86aabSstevel ptr->section_len = len;
6093db86aabSstevel return (ptr);
6103db86aabSstevel }
6113db86aabSstevel
6123db86aabSstevel /*
6133db86aabSstevel * Free a cache_section.
6143db86aabSstevel */
6153db86aabSstevel static void
free_section(rmclomv_cache_section_t * section)6163db86aabSstevel free_section(rmclomv_cache_section_t *section)
6173db86aabSstevel {
6183db86aabSstevel size_t len = section->section_len;
6193db86aabSstevel kmem_free(section, len);
6203db86aabSstevel }
6213db86aabSstevel
6223db86aabSstevel /*
6233db86aabSstevel * adds supplied section to end of cache chain
6243db86aabSstevel * must be called with cache locked
6253db86aabSstevel */
6263db86aabSstevel static void
add_section(rmclomv_cache_section_t ** head,rmclomv_cache_section_t * section)6273db86aabSstevel add_section(rmclomv_cache_section_t **head, rmclomv_cache_section_t *section)
6283db86aabSstevel {
6293db86aabSstevel section->next_section = *head;
6303db86aabSstevel *head = section;
6313db86aabSstevel }
6323db86aabSstevel
6333db86aabSstevel /*
6343db86aabSstevel * This function releases all cache sections and exchanges the two
6353db86aabSstevel * chain heads for new values.
6363db86aabSstevel */
6373db86aabSstevel static void
rmclomv_reset_cache(rmclomv_cache_section_t * new_chain,rmclomv_cache_section_t * new_subchain,dp_get_sysinfo_r_t * sysinfo)6383db86aabSstevel rmclomv_reset_cache(rmclomv_cache_section_t *new_chain,
6393db86aabSstevel rmclomv_cache_section_t *new_subchain, dp_get_sysinfo_r_t *sysinfo)
6403db86aabSstevel {
6413db86aabSstevel rmclomv_cache_section_t *first;
6423db86aabSstevel rmclomv_cache_section_t *sub_first;
6433db86aabSstevel rmclomv_cache_section_t *next;
6443db86aabSstevel
6453db86aabSstevel LOCK_CACHE
6463db86aabSstevel
6473db86aabSstevel rmclomv_cache_valid = (new_chain != NULL);
6483db86aabSstevel first = rmclomv_cache;
6493db86aabSstevel rmclomv_cache = new_chain;
6503db86aabSstevel sub_first = rmclomv_subcache;
6513db86aabSstevel rmclomv_subcache = new_subchain;
6523db86aabSstevel
6533db86aabSstevel if (sysinfo == NULL)
6543db86aabSstevel bzero(&rmclomv_sysinfo_data, sizeof (rmclomv_sysinfo_data));
6553db86aabSstevel else
6563db86aabSstevel bcopy(sysinfo, &rmclomv_sysinfo_data,
6573db86aabSstevel sizeof (rmclomv_sysinfo_data));
6583db86aabSstevel
6593db86aabSstevel rmclomv_sysinfo_valid = (sysinfo != NULL);
6603db86aabSstevel
6613db86aabSstevel RELEASE_CACHE
6623db86aabSstevel
6633db86aabSstevel while (first != NULL) {
6643db86aabSstevel next = first->next_section;
6653db86aabSstevel free_section(first);
6663db86aabSstevel first = next;
6673db86aabSstevel }
6683db86aabSstevel
6693db86aabSstevel while (sub_first != NULL) {
6703db86aabSstevel next = sub_first->next_section;
6713db86aabSstevel free_section(sub_first);
6723db86aabSstevel sub_first = next;
6733db86aabSstevel }
6743db86aabSstevel }
6753db86aabSstevel
6763db86aabSstevel /*
6773db86aabSstevel * cache must be locked before calling rmclomv_find_section
6783db86aabSstevel */
6793db86aabSstevel static rmclomv_cache_section_t *
rmclomv_find_section(rmclomv_cache_section_t * start,uint16_t sensor)6803db86aabSstevel rmclomv_find_section(rmclomv_cache_section_t *start, uint16_t sensor)
6813db86aabSstevel {
6823db86aabSstevel rmclomv_cache_section_t *next = start;
6833db86aabSstevel
6843db86aabSstevel while ((next != NULL) && (next->sensor_type != sensor))
6853db86aabSstevel next = next->next_section;
6863db86aabSstevel
6873db86aabSstevel return (next);
6883db86aabSstevel }
6893db86aabSstevel
6903db86aabSstevel /*
6913db86aabSstevel * Return a string presenting the keyswitch position
6923db86aabSstevel * For unknown values returns "Unknown"
6933db86aabSstevel */
6943db86aabSstevel static char *
rmclomv_key_position(enum rmc_keyswitch_pos pos)6953db86aabSstevel rmclomv_key_position(enum rmc_keyswitch_pos pos)
6963db86aabSstevel {
6973db86aabSstevel switch (pos) {
6983db86aabSstevel
6993db86aabSstevel case RMC_KEYSWITCH_POS_NORMAL:
7003db86aabSstevel return ("NORMAL");
7013db86aabSstevel case RMC_KEYSWITCH_POS_DIAG:
7023db86aabSstevel return ("DIAG");
7033db86aabSstevel case RMC_KEYSWITCH_POS_LOCKED:
7043db86aabSstevel return ("LOCKED");
7053db86aabSstevel case RMC_KEYSWITCH_POS_OFF:
7063db86aabSstevel return ("STBY");
7073db86aabSstevel default:
7083db86aabSstevel return ("UNKNOWN");
7093db86aabSstevel }
7103db86aabSstevel }
7113db86aabSstevel
7123db86aabSstevel /*
7133db86aabSstevel * The sensor id name is sought in the supplied section and if found
7143db86aabSstevel * its index within the section is written to *index.
7153db86aabSstevel * Return value is zero for success, otherwise -1.
7163db86aabSstevel * The cache must be locked before calling get_sensor_by_name
7173db86aabSstevel */
7183db86aabSstevel static int
get_sensor_by_name(const rmclomv_cache_section_t * section,const char * name,int * index)7193db86aabSstevel get_sensor_by_name(const rmclomv_cache_section_t *section,
7203db86aabSstevel const char *name, int *index)
7213db86aabSstevel {
7223db86aabSstevel int i;
7233db86aabSstevel
7243db86aabSstevel for (i = 0; i < section->num_entries; i++) {
7253db86aabSstevel if (strcmp(name, section->entry[i].handle_name.name) == 0) {
7263db86aabSstevel *index = i;
7273db86aabSstevel return (0);
7283db86aabSstevel }
7293db86aabSstevel }
7303db86aabSstevel
7313db86aabSstevel *index = 0;
7323db86aabSstevel return (-1);
7333db86aabSstevel }
7343db86aabSstevel
7353db86aabSstevel /*
7363db86aabSstevel * fills in the envmon_handle name
7373db86aabSstevel * if it is unknown (not cached), the dp_handle_t is returned as a hex-digit
7383db86aabSstevel * string
7393db86aabSstevel */
7403db86aabSstevel static void
rmclomv_hdl_to_envhdl(dp_handle_t hdl,envmon_handle_t * envhdl)7413db86aabSstevel rmclomv_hdl_to_envhdl(dp_handle_t hdl, envmon_handle_t *envhdl)
7423db86aabSstevel {
7433db86aabSstevel rmclomv_cache_section_t *next;
7443db86aabSstevel int i;
7453db86aabSstevel
7463db86aabSstevel LOCK_CACHE
7473db86aabSstevel
7483db86aabSstevel for (next = rmclomv_cache; next != NULL; next = next->next_section) {
7493db86aabSstevel for (i = 0; i < next->num_entries; i++) {
7503db86aabSstevel if (next->entry[i].handle == hdl) {
7513db86aabSstevel *envhdl = next->entry[i].handle_name;
7523db86aabSstevel RELEASE_CACHE
7533db86aabSstevel return;
7543db86aabSstevel }
7553db86aabSstevel }
7563db86aabSstevel }
7573db86aabSstevel
7583db86aabSstevel /*
7593db86aabSstevel * Sought handle not currently cached.
7603db86aabSstevel */
7613db86aabSstevel RELEASE_CACHE
7623db86aabSstevel
7633db86aabSstevel (void) snprintf(envhdl->name, sizeof (envhdl->name),
7643db86aabSstevel "Unknown SC node 0x%x", hdl);
7653db86aabSstevel }
7663db86aabSstevel
7673db86aabSstevel static void
rmclomv_dr_data_handler(const char * fru_name,int hint)7683db86aabSstevel rmclomv_dr_data_handler(const char *fru_name, int hint)
7693db86aabSstevel {
7703db86aabSstevel int err = 0;
7713db86aabSstevel nvlist_t *attr_list;
7723db86aabSstevel char attach_pnt[MAXPATHLEN];
7733db86aabSstevel
7743db86aabSstevel (void) snprintf(attach_pnt, sizeof (attach_pnt), "%s", fru_name);
7753db86aabSstevel
7763db86aabSstevel err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
7773db86aabSstevel if (err != 0) {
7783db86aabSstevel cmn_err(CE_WARN,
7793db86aabSstevel "Failed to allocate name-value list for %s event", EC_DR);
7803db86aabSstevel return;
7813db86aabSstevel }
7823db86aabSstevel
7833db86aabSstevel err = nvlist_add_string(attr_list, DR_AP_ID, attach_pnt);
7843db86aabSstevel if (err != 0) {
7853db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s event",
7863db86aabSstevel DR_AP_ID, EC_DR);
7873db86aabSstevel nvlist_free(attr_list);
7883db86aabSstevel return;
7893db86aabSstevel }
7903db86aabSstevel
7913db86aabSstevel /*
7923db86aabSstevel * Add the hint
7933db86aabSstevel */
7943db86aabSstevel err = nvlist_add_string(attr_list, DR_HINT, SE_HINT2STR(hint));
7953db86aabSstevel if (err != 0) {
7963db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s event",
7973db86aabSstevel DR_HINT, EC_DR);
7983db86aabSstevel nvlist_free(attr_list);
7993db86aabSstevel return;
8003db86aabSstevel }
8013db86aabSstevel
8023db86aabSstevel err = ddi_log_sysevent(rmclomv_dip, DDI_VENDOR_SUNW, EC_DR,
8033db86aabSstevel ESC_DR_AP_STATE_CHANGE, attr_list, NULL, DDI_NOSLEEP);
8043db86aabSstevel if (err != 0) {
8053db86aabSstevel cmn_err(CE_WARN, "Failed to log %s/%s event",
8063db86aabSstevel DR_AP_ID, EC_DR);
8073db86aabSstevel }
8083db86aabSstevel
8093db86aabSstevel nvlist_free(attr_list);
8103db86aabSstevel }
8113db86aabSstevel
8123db86aabSstevel static void
fan_sysevent(char * fru_name,char * sensor_name,int sub_event)8133db86aabSstevel fan_sysevent(char *fru_name, char *sensor_name, int sub_event)
8143db86aabSstevel {
8153db86aabSstevel nvlist_t *attr_list;
8163db86aabSstevel char fan_str[MAXNAMELEN];
8173db86aabSstevel int err;
8183db86aabSstevel
8193db86aabSstevel err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
8203db86aabSstevel if (err != 0) {
8213db86aabSstevel cmn_err(CE_WARN,
8223db86aabSstevel "Failed to allocate name-value list for %s/%s event",
8233db86aabSstevel EC_ENV, ESC_ENV_FAN);
8243db86aabSstevel return;
8253db86aabSstevel }
8263db86aabSstevel
8273db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_ID, fru_name);
8283db86aabSstevel if (err != 0) {
8293db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
8303db86aabSstevel ENV_FRU_ID, EC_ENV, ESC_ENV_FAN);
8313db86aabSstevel nvlist_free(attr_list);
8323db86aabSstevel return;
8333db86aabSstevel }
8343db86aabSstevel
8353db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_RESOURCE_ID, sensor_name);
8363db86aabSstevel if (err != 0) {
8373db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
8383db86aabSstevel ENV_FRU_RESOURCE_ID, EC_ENV, ESC_ENV_FAN);
8393db86aabSstevel nvlist_free(attr_list);
8403db86aabSstevel return;
8413db86aabSstevel }
8423db86aabSstevel
8433db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_DEVICE, ENV_RESERVED_ATTR);
8443db86aabSstevel if (err != 0) {
8453db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
8463db86aabSstevel ENV_FRU_DEVICE, EC_ENV, ESC_ENV_FAN);
8473db86aabSstevel nvlist_free(attr_list);
8483db86aabSstevel return;
8493db86aabSstevel }
8503db86aabSstevel
8513db86aabSstevel err = nvlist_add_int32(attr_list, ENV_FRU_STATE,
8523db86aabSstevel (sub_event == RMC_ENV_FAULT_EVENT) ? ENV_FAILED : ENV_OK);
8533db86aabSstevel if (err != 0) {
8543db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
8553db86aabSstevel ENV_FRU_STATE, EC_ENV, ESC_ENV_FAN);
8563db86aabSstevel nvlist_free(attr_list);
8573db86aabSstevel return;
8583db86aabSstevel }
8593db86aabSstevel
8603db86aabSstevel if (sub_event == RMC_ENV_FAULT_EVENT) {
8613db86aabSstevel (void) snprintf(fan_str, sizeof (fan_str),
8623db86aabSstevel "fan %s/%s is now failed", fru_name, sensor_name);
8633db86aabSstevel } else {
8643db86aabSstevel (void) snprintf(fan_str, sizeof (fan_str),
8653db86aabSstevel "fan %s/%s is now ok", fru_name, sensor_name);
8663db86aabSstevel }
8673db86aabSstevel err = nvlist_add_string(attr_list, ENV_MSG, fan_str);
8683db86aabSstevel if (err != 0) {
8693db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
8703db86aabSstevel ENV_MSG, EC_ENV, ESC_ENV_FAN);
8713db86aabSstevel nvlist_free(attr_list);
8723db86aabSstevel return;
8733db86aabSstevel }
8743db86aabSstevel
8753db86aabSstevel err = ddi_log_sysevent(rmclomv_dip, DDI_VENDOR_SUNW, EC_ENV,
8763db86aabSstevel ESC_ENV_FAN, attr_list, NULL, DDI_NOSLEEP);
8773db86aabSstevel if (err != 0) {
8783db86aabSstevel cmn_err(CE_WARN, "Failed to log %s/%s event",
8793db86aabSstevel EC_ENV, ESC_ENV_FAN);
8803db86aabSstevel }
8813db86aabSstevel
8823db86aabSstevel cmn_err(CE_NOTE, "%s", fan_str);
8833db86aabSstevel nvlist_free(attr_list);
8843db86aabSstevel }
8853db86aabSstevel
8863db86aabSstevel static void
threshold_sysevent(char * fru_name,char * sensor_name,int sub_event,char event_type)8873db86aabSstevel threshold_sysevent(char *fru_name, char *sensor_name, int sub_event,
8883db86aabSstevel char event_type)
8893db86aabSstevel {
8903db86aabSstevel nvlist_t *attr_list;
8913db86aabSstevel int err;
8923db86aabSstevel char *subclass;
8933db86aabSstevel char sensor_str[MAXNAMELEN];
8943db86aabSstevel
8953db86aabSstevel subclass = (event_type == 'T') ? ESC_ENV_TEMP : ESC_ENV_POWER;
8963db86aabSstevel
8973db86aabSstevel err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_NOSLEEP);
8983db86aabSstevel if (err != 0) {
8993db86aabSstevel cmn_err(CE_WARN,
9003db86aabSstevel "Failed to allocate name-value list for %s/%s event",
9013db86aabSstevel EC_ENV, subclass);
9023db86aabSstevel return;
9033db86aabSstevel }
9043db86aabSstevel
9053db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_ID, fru_name);
9063db86aabSstevel if (err != 0) {
9073db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
9083db86aabSstevel ENV_FRU_ID, EC_ENV, subclass);
9093db86aabSstevel nvlist_free(attr_list);
9103db86aabSstevel return;
9113db86aabSstevel }
9123db86aabSstevel
9133db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_RESOURCE_ID, sensor_name);
9143db86aabSstevel if (err != 0) {
9153db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
9163db86aabSstevel ENV_FRU_RESOURCE_ID, EC_ENV, subclass);
9173db86aabSstevel nvlist_free(attr_list);
9183db86aabSstevel return;
9193db86aabSstevel }
9203db86aabSstevel
9213db86aabSstevel err = nvlist_add_string(attr_list, ENV_FRU_DEVICE, ENV_RESERVED_ATTR);
9223db86aabSstevel if (err != 0) {
9233db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
9243db86aabSstevel ENV_FRU_DEVICE, EC_ENV, subclass);
9253db86aabSstevel nvlist_free(attr_list);
9263db86aabSstevel return;
9273db86aabSstevel }
9283db86aabSstevel
9293db86aabSstevel switch (sub_event) {
9303db86aabSstevel case RMC_ENV_OK_EVENT:
9313db86aabSstevel err = nvlist_add_int32(attr_list, ENV_FRU_STATE, ENV_OK);
9323db86aabSstevel break;
9333db86aabSstevel case RMC_ENV_WARNING_THRESHOLD_EVENT:
9343db86aabSstevel err = nvlist_add_int32(attr_list, ENV_FRU_STATE, ENV_WARNING);
9353db86aabSstevel break;
9363db86aabSstevel case RMC_ENV_SHUTDOWN_THRESHOLD_EVENT:
9373db86aabSstevel err = nvlist_add_int32(attr_list, ENV_FRU_STATE, ENV_FAILED);
9383db86aabSstevel break;
9393db86aabSstevel }
9403db86aabSstevel if (err != 0) {
9413db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
9423db86aabSstevel ENV_FRU_STATE, EC_ENV, subclass);
9433db86aabSstevel nvlist_free(attr_list);
9443db86aabSstevel return;
9453db86aabSstevel }
9463db86aabSstevel
9473db86aabSstevel switch (sub_event) {
9483db86aabSstevel case RMC_ENV_OK_EVENT:
9493db86aabSstevel (void) snprintf(sensor_str, sizeof (sensor_str),
9503db86aabSstevel "sensor %s/%s is now ok", fru_name,
9513db86aabSstevel sensor_name);
9523db86aabSstevel break;
9533db86aabSstevel case RMC_ENV_WARNING_THRESHOLD_EVENT:
9543db86aabSstevel (void) snprintf(sensor_str, sizeof (sensor_str),
9553db86aabSstevel "sensor %s/%s is now outside warning thresholds", fru_name,
9563db86aabSstevel sensor_name);
9573db86aabSstevel break;
9583db86aabSstevel case RMC_ENV_SHUTDOWN_THRESHOLD_EVENT:
9593db86aabSstevel (void) snprintf(sensor_str, sizeof (sensor_str),
9603db86aabSstevel "sensor %s/%s is now outside shutdown thresholds", fru_name,
9613db86aabSstevel sensor_name);
9623db86aabSstevel break;
9633db86aabSstevel }
9643db86aabSstevel err = nvlist_add_string(attr_list, ENV_MSG, sensor_str);
9653db86aabSstevel if (err != 0) {
9663db86aabSstevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s/%s event",
9673db86aabSstevel ENV_MSG, EC_ENV, subclass);
9683db86aabSstevel nvlist_free(attr_list);
9693db86aabSstevel return;
9703db86aabSstevel }
9713db86aabSstevel
9723db86aabSstevel err = ddi_log_sysevent(rmclomv_dip, DDI_VENDOR_SUNW, EC_ENV,
9733db86aabSstevel subclass, attr_list, NULL, DDI_NOSLEEP);
9743db86aabSstevel if (err != 0) {
9753db86aabSstevel cmn_err(CE_WARN, "Failed to log %s/%s event",
9763db86aabSstevel EC_ENV, subclass);
9773db86aabSstevel }
9783db86aabSstevel
9793db86aabSstevel cmn_err(CE_NOTE, "%s", sensor_str);
9803db86aabSstevel nvlist_free(attr_list);
9813db86aabSstevel }
9823db86aabSstevel
9833db86aabSstevel static uint_t
rmclomv_event_data_handler(char * arg)9843db86aabSstevel rmclomv_event_data_handler(char *arg)
9853db86aabSstevel {
9863db86aabSstevel dp_event_notification_t *payload;
9873db86aabSstevel rmc_comm_msg_t *msg;
9883db86aabSstevel envmon_handle_t envhdl;
9893db86aabSstevel int hint;
9903db86aabSstevel char *ptr, *save_ptr;
9913db86aabSstevel
9923db86aabSstevel if (arg == NULL) {
9933db86aabSstevel return (DDI_INTR_CLAIMED);
9943db86aabSstevel }
9953db86aabSstevel
9963db86aabSstevel msg = (rmc_comm_msg_t *)arg;
9973db86aabSstevel if (msg->msg_buf == NULL) {
9983db86aabSstevel return (DDI_INTR_CLAIMED);
9993db86aabSstevel }
10003db86aabSstevel
10013db86aabSstevel payload = (dp_event_notification_t *)msg->msg_buf;
10023db86aabSstevel switch (payload->event) {
10033db86aabSstevel
10043db86aabSstevel case RMC_KEYSWITCH_EVENT:
10053db86aabSstevel real_key_position = payload->event_info.ev_keysw.key_position;
10063db86aabSstevel cmn_err(CE_NOTE, "keyswitch change event - state = %s",
10073db86aabSstevel rmclomv_key_position(real_key_position));
10083db86aabSstevel if ((real_key_position != RMC_KEYSWITCH_POS_UNKNOWN) &&
10093db86aabSstevel (real_key_position <= RMC_KEYSWITCH_POS_OFF)) {
10103db86aabSstevel key_position = real_key_position;
10113db86aabSstevel } else {
10123db86aabSstevel /* treat unknown key position as locked */
10133db86aabSstevel key_position = RMC_KEYSWITCH_POS_LOCKED;
10143db86aabSstevel }
10153db86aabSstevel break;
10163db86aabSstevel
10173db86aabSstevel case RMC_HPU_EVENT:
10183db86aabSstevel /*
10193db86aabSstevel * send appropriate sysevent
10203db86aabSstevel */
10213db86aabSstevel switch (payload->event_info.ev_hpunot.sub_event) {
10223db86aabSstevel case RMC_HPU_REMOVE_EVENT:
10233db86aabSstevel hint = SE_HINT_REMOVE;
10243db86aabSstevel break;
10253db86aabSstevel case RMC_HPU_INSERT_EVENT:
10263db86aabSstevel hint = SE_HINT_INSERT;
10273db86aabSstevel break;
10283db86aabSstevel default:
10293db86aabSstevel hint = SE_NO_HINT;
10303db86aabSstevel break;
10313db86aabSstevel }
10323db86aabSstevel rmclomv_hdl_to_envhdl(payload->event_info.ev_hpunot.hpu_hdl,
10333db86aabSstevel &envhdl);
10343db86aabSstevel rmclomv_dr_data_handler(envhdl.name, hint);
10353db86aabSstevel break;
10363db86aabSstevel
10373db86aabSstevel case RMC_INIT_EVENT:
10383db86aabSstevel /*
10393db86aabSstevel * Wake up the refresh thread.
10403db86aabSstevel */
10413db86aabSstevel rmclomv_refresh_wakeup();
10423db86aabSstevel
10433db86aabSstevel /*
10443db86aabSstevel * Wake up the checkrmc thread for an early indication to PICL
10453db86aabSstevel */
10463db86aabSstevel rmclomv_checkrmc_wakeup(NULL);
10473db86aabSstevel break;
10483db86aabSstevel
10493db86aabSstevel case RMC_ENV_EVENT:
10503db86aabSstevel rmclomv_hdl_to_envhdl(payload->event_info.ev_envnot.env_hdl,
10513db86aabSstevel &envhdl);
10523db86aabSstevel
10533db86aabSstevel /* split name into fru name and sensor name */
10543db86aabSstevel ptr = strchr(envhdl.name, '.');
10553db86aabSstevel
10563db86aabSstevel /* must have at least one '.' */
10573db86aabSstevel if (ptr == NULL)
10583db86aabSstevel break;
10593db86aabSstevel
10603db86aabSstevel /* find last '.' - convert the others to '/' */
10613db86aabSstevel for (;;) {
10623db86aabSstevel save_ptr = ptr;
10633db86aabSstevel ptr = strchr(ptr, '.');
10643db86aabSstevel if (ptr == NULL) {
10653db86aabSstevel ptr = save_ptr;
10663db86aabSstevel break;
10673db86aabSstevel }
10683db86aabSstevel *save_ptr = '/';
10693db86aabSstevel }
10703db86aabSstevel *ptr = '\0';
10713db86aabSstevel ptr++;
10723db86aabSstevel /* is it a voltage or temperature sensor? */
10733db86aabSstevel if ((*ptr == 'V' || *ptr == 'T') && *(ptr + 1) == '_') {
10743db86aabSstevel switch (payload->event_info.ev_envnot.sub_event) {
10753db86aabSstevel case RMC_ENV_WARNING_THRESHOLD_EVENT:
10763db86aabSstevel case RMC_ENV_SHUTDOWN_THRESHOLD_EVENT:
10773db86aabSstevel case RMC_ENV_OK_EVENT:
10783db86aabSstevel threshold_sysevent(envhdl.name, ptr,
10793db86aabSstevel payload->event_info.ev_envnot.sub_event,
10803db86aabSstevel *ptr);
10813db86aabSstevel break;
10823db86aabSstevel default:
10833db86aabSstevel break;
10843db86aabSstevel }
10853db86aabSstevel }
10863db86aabSstevel
10873db86aabSstevel /*
10883db86aabSstevel * is it a fan sensor?
10893db86aabSstevel * Fan sensor names end either in RS, F0 or F1
10903db86aabSstevel */
10913db86aabSstevel if ((*ptr == 'R' && *(ptr + 1) == 'S' && *(ptr + 2) == '\0') ||
10923db86aabSstevel (*ptr == 'F' && *(ptr + 1) == '0' && *(ptr + 2) == '\0') ||
10933db86aabSstevel (*ptr == 'F' && *(ptr + 1) == '1' && *(ptr + 2) == '\0')) {
10943db86aabSstevel switch (payload->event_info.ev_envnot.sub_event) {
10953db86aabSstevel case RMC_ENV_FAULT_EVENT:
10963db86aabSstevel case RMC_ENV_OK_EVENT:
10973db86aabSstevel fan_sysevent(envhdl.name, ptr,
10983db86aabSstevel payload->event_info.ev_envnot.sub_event);
10993db86aabSstevel break;
11003db86aabSstevel default:
11013db86aabSstevel break;
11023db86aabSstevel }
11033db86aabSstevel }
11043db86aabSstevel break;
11053db86aabSstevel
11063db86aabSstevel case RMC_LOG_EVENT:
11073db86aabSstevel {
11083db86aabSstevel int level = 10;
11093db86aabSstevel int flags = SL_NOTE | SL_CONSOLE;
11103db86aabSstevel char *message =
11113db86aabSstevel (char *)payload->event_info.ev_rmclog.log_record;
11123db86aabSstevel
11133db86aabSstevel message[ payload->event_info.ev_rmclog.log_record_size] = '\0';
11143db86aabSstevel
11153db86aabSstevel /*
11163db86aabSstevel * Logs have a 10 character prefix - specifying the severity of
11173db86aabSstevel * the event being logged. Thus all the magic number 10s down
11183db86aabSstevel * here
11193db86aabSstevel */
11203db86aabSstevel if (0 == strncmp("CRITICAL: ", message, 10)) {
11213db86aabSstevel message += 10;
11223db86aabSstevel level = 0;
11233db86aabSstevel flags = SL_FATAL | SL_ERROR | SL_CONSOLE;
11243db86aabSstevel } else if (0 == strncmp("MAJOR: ", message, 10)) {
11253db86aabSstevel message += 10;
11263db86aabSstevel level = 5;
11273db86aabSstevel flags = SL_WARN | SL_ERROR | SL_CONSOLE;
11283db86aabSstevel } else if (0 == strncmp("MINOR: ", message, 10)) {
11293db86aabSstevel message += 10;
11303db86aabSstevel level = 10;
11313db86aabSstevel flags = SL_NOTE | SL_CONSOLE;
11323db86aabSstevel }
11333db86aabSstevel
11343db86aabSstevel (void) strlog(0, 0, level, flags, message);
11353db86aabSstevel break;
11363db86aabSstevel }
11373db86aabSstevel
11383db86aabSstevel default:
11393db86aabSstevel return (DDI_INTR_CLAIMED);
11403db86aabSstevel }
11413db86aabSstevel
11423db86aabSstevel return (DDI_INTR_CLAIMED);
11433db86aabSstevel }
11443db86aabSstevel
11453db86aabSstevel /*ARGSUSED*/
11463db86aabSstevel static int
rmclomv_open(dev_t * dev_p,int flag,int otyp,cred_t * cred_p)11473db86aabSstevel rmclomv_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
11483db86aabSstevel {
11493db86aabSstevel int error = 0;
11503db86aabSstevel int instance = getminor(*dev_p);
11513db86aabSstevel
11523db86aabSstevel if (instance != 0)
11533db86aabSstevel return (ENXIO);
11543db86aabSstevel
11553db86aabSstevel if ((flag & FWRITE) != 0 && (error = drv_priv(cred_p)) != 0)
11563db86aabSstevel return (error);
11573db86aabSstevel
11583db86aabSstevel return (0);
11593db86aabSstevel }
11603db86aabSstevel
11613db86aabSstevel /*ARGSUSED*/
11623db86aabSstevel static int
rmclomv_close(dev_t dev,int flag,int otyp,cred_t * cred_p)11633db86aabSstevel rmclomv_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
11643db86aabSstevel {
11653db86aabSstevel return (DDI_SUCCESS);
11663db86aabSstevel }
11673db86aabSstevel
11683db86aabSstevel static int
rmclomv_do_cmd(int req_cmd,int resp_cmd,int resp_len,intptr_t arg_req,intptr_t arg_res)11693db86aabSstevel rmclomv_do_cmd(int req_cmd, int resp_cmd, int resp_len, intptr_t arg_req,
11703db86aabSstevel intptr_t arg_res)
11713db86aabSstevel {
11723db86aabSstevel rmc_comm_msg_t request, *reqp = &request;
11733db86aabSstevel rmc_comm_msg_t response, *resp = &response;
11743db86aabSstevel int rv = 0;
11753db86aabSstevel
11763db86aabSstevel bzero((caddr_t)&request, sizeof (request));
11773db86aabSstevel reqp->msg_type = req_cmd;
11783db86aabSstevel reqp->msg_buf = (caddr_t)arg_req;
11793db86aabSstevel bzero((caddr_t)&response, sizeof (response));
11803db86aabSstevel resp->msg_type = resp_cmd;
11813db86aabSstevel resp->msg_buf = (caddr_t)arg_res;
11823db86aabSstevel resp->msg_len = resp_len;
11833db86aabSstevel
11843db86aabSstevel switch (req_cmd) {
11853db86aabSstevel case DP_GET_SYSINFO:
11863db86aabSstevel resp->msg_len = sizeof (dp_get_sysinfo_r_t);
11873db86aabSstevel break;
11883db86aabSstevel case DP_GET_EVENT_LOG:
11893db86aabSstevel resp->msg_len = sizeof (dp_get_event_log_r_t);
11903db86aabSstevel break;
11913db86aabSstevel case DP_GET_VOLTS:
11923db86aabSstevel reqp->msg_len = sizeof (dp_get_volts_t);
11933db86aabSstevel break;
11943db86aabSstevel case DP_GET_TEMPERATURES:
11953db86aabSstevel reqp->msg_len = sizeof (dp_get_temperatures_t);
11963db86aabSstevel break;
11973db86aabSstevel case DP_GET_CIRCUIT_BRKS:
11983db86aabSstevel reqp->msg_len = sizeof (dp_get_circuit_brks_t);
11993db86aabSstevel break;
12003db86aabSstevel case DP_GET_FAN_STATUS:
12013db86aabSstevel reqp->msg_len = sizeof (dp_get_fan_status_t);
12023db86aabSstevel break;
12033db86aabSstevel case DP_GET_PSU_STATUS:
12043db86aabSstevel reqp->msg_len = sizeof (dp_get_psu_status_t);
12053db86aabSstevel break;
12063db86aabSstevel case DP_GET_LED_STATE:
12073db86aabSstevel reqp->msg_len = sizeof (dp_get_led_state_t);
12083db86aabSstevel break;
12093db86aabSstevel case DP_SET_LED_STATE:
12103db86aabSstevel reqp->msg_len = sizeof (dp_set_led_state_t);
12113db86aabSstevel break;
12123db86aabSstevel case DP_GET_FRU_STATUS:
12133db86aabSstevel reqp->msg_len = sizeof (dp_get_fru_status_t);
12143db86aabSstevel break;
12153db86aabSstevel case DP_GET_HANDLE_NAME:
12163db86aabSstevel reqp->msg_len = sizeof (dp_get_handle_name_t);
12173db86aabSstevel break;
12183db86aabSstevel case DP_GET_ALARM_STATE:
12193db86aabSstevel reqp->msg_len = sizeof (dp_get_alarm_state_t);
12203db86aabSstevel break;
12213db86aabSstevel case DP_SET_ALARM_STATE:
12223db86aabSstevel reqp->msg_len = sizeof (dp_set_alarm_state_t);
12233db86aabSstevel break;
12243db86aabSstevel case DP_GET_SDP_VERSION:
12253db86aabSstevel resp->msg_len = sizeof (dp_get_sdp_version_r_t);
12263db86aabSstevel break;
12273db86aabSstevel case DP_GET_CHASSIS_SERIALNUM:
12283db86aabSstevel reqp->msg_len = 0;
12293db86aabSstevel break;
12303db86aabSstevel case DP_GET_DATE_TIME:
12313db86aabSstevel reqp->msg_len = 0;
12323db86aabSstevel break;
12333db86aabSstevel default:
12343db86aabSstevel return (EINVAL);
12353db86aabSstevel }
12363db86aabSstevel
12373db86aabSstevel rv = rmc_comm_request_response(reqp, resp,
12383db86aabSstevel RMCLOMV_DEFAULT_MAX_MBOX_WAIT_TIME);
12393db86aabSstevel
12403db86aabSstevel if (rv != RCNOERR) {
12413db86aabSstevel /*
12423db86aabSstevel * RMC returned an error or failed to respond.
12433db86aabSstevel * Where the RMC itself is implicated, rmclomv_rmc_error
12443db86aabSstevel * is set non-zero. It is cleared after an error free exchange.
12453db86aabSstevel * Two failure cases are distinguished:
12463db86aabSstevel * RMCLOMV_RMCSTATE_FAILED and RMCLOMV_RMCSTATE_DOWNLOAD.
12473db86aabSstevel */
12483db86aabSstevel switch (rv) {
12493db86aabSstevel case RCENOSOFTSTATE:
12503db86aabSstevel /* invalid/NULL soft state structure */
12513db86aabSstevel return (EIO);
12523db86aabSstevel case RCENODATALINK:
12533db86aabSstevel /*
12543db86aabSstevel * firmware download in progress,
12553db86aabSstevel * can you come back later?
12563db86aabSstevel */
12573db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_DOWNLOAD;
12583db86aabSstevel rmclomv_rmc_state = RMCLOMV_RMCSTATE_DOWNLOAD;
12593db86aabSstevel return (EAGAIN);
12603db86aabSstevel case RCENOMEM:
12613db86aabSstevel /* memory problems */
12623db86aabSstevel return (ENOMEM);
12633db86aabSstevel case RCECANTRESEND:
12643db86aabSstevel /* resend failed */
12653db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED;
12663db86aabSstevel return (EIO);
12673db86aabSstevel case RCEMAXRETRIES:
12683db86aabSstevel /* reply not received - retries exceeded */
12693db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED;
12703db86aabSstevel return (EINTR);
12713db86aabSstevel case RCETIMEOUT:
12723db86aabSstevel /* reply not received - command has timed out */
12733db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED;
12743db86aabSstevel return (EINTR);
12753db86aabSstevel case RCEINVCMD:
12763db86aabSstevel /* data protocol cmd not supported */
12773db86aabSstevel return (ENOTSUP);
12783db86aabSstevel case RCEINVARG:
12793db86aabSstevel /* invalid argument(s) */
12803db86aabSstevel return (ENOTSUP);
12813db86aabSstevel case RCEGENERIC:
12823db86aabSstevel /* generic error */
12833db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED;
12843db86aabSstevel return (EIO);
12853db86aabSstevel default:
12863db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCSTATE_FAILED;
12873db86aabSstevel return (EIO);
12883db86aabSstevel }
12893db86aabSstevel }
12903db86aabSstevel
12913db86aabSstevel rmclomv_rmc_error = RMCLOMV_RMCERROR_NONE;
12923db86aabSstevel return (0);
12933db86aabSstevel }
12943db86aabSstevel
12953db86aabSstevel /*
12963db86aabSstevel * validate_section_entry checks that the entry at the specified index
12973db86aabSstevel * is valid and not duplicated by an entry above. If these tests fail
12983db86aabSstevel * the entry is removed and B_FALSE returned. Otherwise returns B_TRUE.
12993db86aabSstevel */
13003db86aabSstevel static int
validate_section_entry(rmclomv_cache_section_t * section,int index)13013db86aabSstevel validate_section_entry(rmclomv_cache_section_t *section, int index)
13023db86aabSstevel {
13033db86aabSstevel int i;
13043db86aabSstevel rmclomv_cache_entry_t *entry;
13053db86aabSstevel
13063db86aabSstevel for (i = index; i < section->num_entries; i++) {
13073db86aabSstevel entry = §ion->entry[i];
13083db86aabSstevel if (entry->handle_name.name[0] == '\0') {
13093db86aabSstevel cmn_err(CE_WARN,
13103db86aabSstevel "rmclomv: empty handle_name, handle 0x%x type %x",
13113db86aabSstevel entry->handle, section->sensor_type);
13123db86aabSstevel } else if (entry->ind_mask != 0) {
13133db86aabSstevel continue; /* skip special entries */
13143db86aabSstevel } else if (entry->handle == DP_NULL_HANDLE) {
13153db86aabSstevel cmn_err(CE_WARN,
13163db86aabSstevel "rmclomv: null handle id for \"%s\" type %x",
13173db86aabSstevel entry->handle_name.name, section->sensor_type);
13183db86aabSstevel } else if (i == index) {
13193db86aabSstevel continue;
13203db86aabSstevel } else if (section->entry[index].handle == entry->handle) {
13213db86aabSstevel cmn_err(CE_WARN,
13223db86aabSstevel "rmclomv: duplicate handle 0x%x type %x",
13233db86aabSstevel entry->handle, section->sensor_type);
13243db86aabSstevel } else if (strcmp(entry->handle_name.name,
13253db86aabSstevel section->entry[index].handle_name.name) == 0) {
13263db86aabSstevel cmn_err(CE_WARN,
13273db86aabSstevel "rmclomv: duplicate handle_name \"%s\", "
13283db86aabSstevel "handle 0x%x type %x", entry->handle_name.name,
13293db86aabSstevel entry->handle, section->sensor_type);
13303db86aabSstevel } else
13313db86aabSstevel continue;
13323db86aabSstevel
13333db86aabSstevel /*
13343db86aabSstevel * need to remove the entry at index
13353db86aabSstevel */
13363db86aabSstevel section->num_entries--;
13373db86aabSstevel
13383db86aabSstevel for (i = index; i < section->num_entries; i++) {
13393db86aabSstevel section->entry[i] = section->entry[i + 1];
13403db86aabSstevel }
13413db86aabSstevel
13423db86aabSstevel return (B_FALSE);
13433db86aabSstevel }
13443db86aabSstevel
13453db86aabSstevel return (B_TRUE);
13463db86aabSstevel }
13473db86aabSstevel
13483db86aabSstevel /*
13493db86aabSstevel * Populate a section containing handles with corresponding names
13503db86aabSstevel * The supplied section structure must not be publically visible and the
13513db86aabSstevel * name cache must not be locked either (because RMC i/o is required).
13523db86aabSstevel *
13533db86aabSstevel * This is the place where a sanity check is applied. Entries containing
13543db86aabSstevel * duplicate handles, duplicate names or empty names are removed and the
13553db86aabSstevel * structure is compacted. As a result num_entries may be reduced.
13563db86aabSstevel */
13573db86aabSstevel static int
add_names_to_section(rmclomv_cache_section_t * section)13583db86aabSstevel add_names_to_section(rmclomv_cache_section_t *section)
13593db86aabSstevel {
13603db86aabSstevel int retval = 0;
13613db86aabSstevel int ditched = B_FALSE;
13623db86aabSstevel int index;
13633db86aabSstevel dp_get_handle_name_r_t handle_name_r;
13643db86aabSstevel rmclomv_cache_entry_t *entry;
13653db86aabSstevel
13663db86aabSstevel for (index = 0; index < section->num_entries; index++) {
13673db86aabSstevel entry = §ion->entry[index];
13683db86aabSstevel if (entry->ind_mask != 0)
13693db86aabSstevel continue; /* skip special entries */
13703db86aabSstevel handle_name_r.handle = entry->handle;
13713db86aabSstevel retval = rmclomv_do_cmd(DP_GET_HANDLE_NAME,
13723db86aabSstevel DP_GET_HANDLE_NAME_R, sizeof (handle_name_r),
13733db86aabSstevel (intptr_t)&handle_name_r, (intptr_t)&handle_name_r);
13743db86aabSstevel if (retval == 0)
13753db86aabSstevel bcopy(handle_name_r.name,
13763db86aabSstevel entry->handle_name.name, DP_MAX_HANDLE_NAME);
13773db86aabSstevel }
13783db86aabSstevel
13793db86aabSstevel /*
13803db86aabSstevel * now ditch invalid and duplicate entries
13813db86aabSstevel */
13823db86aabSstevel for (index = 0; index < section->num_entries; index++) {
13833db86aabSstevel while (validate_section_entry(section, index) == B_FALSE)
13843db86aabSstevel ditched = B_TRUE;
13853db86aabSstevel }
13863db86aabSstevel
13873db86aabSstevel if (ditched)
13883db86aabSstevel cmn_err(CE_WARN, "Retaining %d nodes of type %d",
13893db86aabSstevel section->num_entries, section->sensor_type);
13903db86aabSstevel
13913db86aabSstevel return (retval);
13923db86aabSstevel }
13933db86aabSstevel
13943db86aabSstevel /*
13953db86aabSstevel * The supplied (PSU) cache section is traversed and entries are created
13963db86aabSstevel * for the individual indicators belonging to a PSU. These entries are
13973db86aabSstevel * placed in a private chain. The caller, subsequently acquires the
13983db86aabSstevel * cache lock and copies the chain head to make it public.
13993db86aabSstevel * The handle-names for PSU indicators are derived from the parent PSU
14003db86aabSstevel * handle-name.
14013db86aabSstevel * NOTE: add_names_to_section() may have reduced psu_section->num_entries
14023db86aabSstevel * so DON'T USE psu_resp->num_psus
14033db86aabSstevel */
14043db86aabSstevel static void
make_psu_subsections(rmclomv_cache_section_t * psu_section,rmclomv_cache_section_t ** chain_head,dp_get_psu_status_r_t * psu_resp)14053db86aabSstevel make_psu_subsections(rmclomv_cache_section_t *psu_section,
14063db86aabSstevel rmclomv_cache_section_t **chain_head, dp_get_psu_status_r_t *psu_resp)
14073db86aabSstevel {
14083db86aabSstevel int index;
14093db86aabSstevel int subindex = 0;
14103db86aabSstevel rmclomv_cache_section_t *subsection;
14113db86aabSstevel rmclomv_cache_entry_t *src_entry;
14123db86aabSstevel rmclomv_cache_entry_t *dst_entry;
14133db86aabSstevel
14143db86aabSstevel subsection = create_cache_section(RMCLOMV_VOLT_IND,
14153db86aabSstevel RMCLOMV_MAX_VI_PER_PSU * psu_section->num_entries);
14163db86aabSstevel for (index = 0; index < psu_section->num_entries; index++) {
14173db86aabSstevel src_entry = &psu_section->entry[index];
14183db86aabSstevel if ((psu_resp->psu_status[index].mask &
14193db86aabSstevel DP_PSU_INPUT_STATUS) != 0) {
14203db86aabSstevel dst_entry = &subsection->entry[subindex++];
14213db86aabSstevel dst_entry->handle = src_entry->handle;
14223db86aabSstevel dst_entry->ind_mask = DP_PSU_INPUT_STATUS;
14233db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
14243db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
14253db86aabSstevel src_entry->handle_name.name,
14263db86aabSstevel str_ip_volts_ind);
14273db86aabSstevel }
14283db86aabSstevel
14293db86aabSstevel if ((psu_resp->psu_status[index].mask &
14303db86aabSstevel DP_PSU_SEC_INPUT_STATUS) != 0) {
14313db86aabSstevel dst_entry = &subsection->entry[subindex++];
14323db86aabSstevel dst_entry->handle = src_entry->handle;
14333db86aabSstevel dst_entry->ind_mask = DP_PSU_SEC_INPUT_STATUS;
14343db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
14353db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
14363db86aabSstevel src_entry->handle_name.name,
14373db86aabSstevel str_ip2_volts_ind);
14383db86aabSstevel }
14393db86aabSstevel
14403db86aabSstevel if ((psu_resp->psu_status[index].mask &
14413db86aabSstevel DP_PSU_OUTPUT_STATUS) != 0) {
14423db86aabSstevel dst_entry = &subsection->entry[subindex++];
14433db86aabSstevel dst_entry->handle = src_entry->handle;
14443db86aabSstevel dst_entry->ind_mask = DP_PSU_OUTPUT_STATUS;
14453db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
14463db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
14473db86aabSstevel src_entry->handle_name.name,
14483db86aabSstevel str_ff_pok_ind);
14493db86aabSstevel }
14503db86aabSstevel
14513db86aabSstevel if ((psu_resp->psu_status[index].mask &
14523db86aabSstevel DP_PSU_OUTPUT_VLO_STATUS) != 0) {
14533db86aabSstevel dst_entry = &subsection->entry[subindex++];
14543db86aabSstevel dst_entry->handle = src_entry->handle;
14553db86aabSstevel dst_entry->ind_mask = DP_PSU_OUTPUT_VLO_STATUS;
14563db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
14573db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
14583db86aabSstevel src_entry->handle_name.name,
14593db86aabSstevel str_vlo_volts_ind);
14603db86aabSstevel }
14613db86aabSstevel
14623db86aabSstevel if ((psu_resp->psu_status[index].mask &
14633db86aabSstevel DP_PSU_OUTPUT_VHI_STATUS) != 0) {
14643db86aabSstevel dst_entry = &subsection->entry[subindex++];
14653db86aabSstevel dst_entry->handle = src_entry->handle;
14663db86aabSstevel dst_entry->ind_mask = DP_PSU_OUTPUT_VHI_STATUS;
14673db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
14683db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
14693db86aabSstevel src_entry->handle_name.name,
14703db86aabSstevel str_vhi_volts_ind);
14713db86aabSstevel }
14723db86aabSstevel }
14733db86aabSstevel /*
14743db86aabSstevel * Adjust number of entries value in cache section
14753db86aabSstevel * to match the facts.
14763db86aabSstevel */
14773db86aabSstevel subsection->num_entries = subindex;
14783db86aabSstevel add_section(chain_head, subsection);
14793db86aabSstevel
14803db86aabSstevel subsection = create_cache_section(RMCLOMV_AMP_IND,
14813db86aabSstevel RMCLOMV_MAX_CI_PER_PSU * psu_section->num_entries);
14823db86aabSstevel subindex = 0;
14833db86aabSstevel for (index = 0; index < psu_section->num_entries; index++) {
14843db86aabSstevel int mask = psu_resp->psu_status[index].mask;
14853db86aabSstevel src_entry = &psu_section->entry[index];
14863db86aabSstevel if ((mask & DP_PSU_OUTPUT_AHI_STATUS) != 0) {
14873db86aabSstevel dst_entry = &subsection->entry[subindex++];
14883db86aabSstevel dst_entry->handle = src_entry->handle;
14893db86aabSstevel dst_entry->ind_mask = DP_PSU_OUTPUT_AHI_STATUS;
14903db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
14913db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
14923db86aabSstevel src_entry->handle_name.name,
14933db86aabSstevel str_chi_amps_ind);
14943db86aabSstevel }
14953db86aabSstevel if ((mask & DP_PSU_NR_WARNING) != 0) {
14963db86aabSstevel dst_entry = &subsection->entry[subindex++];
14973db86aabSstevel dst_entry->handle = src_entry->handle;
14983db86aabSstevel dst_entry->ind_mask = DP_PSU_NR_WARNING;
14993db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
15003db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
15013db86aabSstevel src_entry->handle_name.name,
15023db86aabSstevel str_chi_nr_ind);
15033db86aabSstevel }
15043db86aabSstevel }
15053db86aabSstevel subsection->num_entries = subindex;
15063db86aabSstevel add_section(chain_head, subsection);
15073db86aabSstevel
15083db86aabSstevel subsection = create_cache_section(RMCLOMV_TEMP_IND,
15093db86aabSstevel psu_section->num_entries);
15103db86aabSstevel subindex = 0;
15113db86aabSstevel for (index = 0; index < psu_section->num_entries; index++) {
15123db86aabSstevel if ((psu_resp->psu_status[index].mask &
15133db86aabSstevel DP_PSU_OVERTEMP_FAULT) != 0) {
15143db86aabSstevel src_entry = &psu_section->entry[index];
15153db86aabSstevel dst_entry = &subsection->entry[subindex++];
15163db86aabSstevel dst_entry->handle = src_entry->handle;
15173db86aabSstevel dst_entry->ind_mask = DP_PSU_OVERTEMP_FAULT;
15183db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
15193db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
15203db86aabSstevel src_entry->handle_name.name,
15213db86aabSstevel str_ot_tmpr_ind);
15223db86aabSstevel }
15233db86aabSstevel }
15243db86aabSstevel subsection->num_entries = subindex;
15253db86aabSstevel add_section(chain_head, subsection);
15263db86aabSstevel
15273db86aabSstevel subsection = create_cache_section(RMCLOMV_FAN_IND,
15283db86aabSstevel RMCLOMV_MAX_FI_PER_PSU * psu_section->num_entries);
15293db86aabSstevel subindex = 0;
15303db86aabSstevel for (index = 0; index < psu_section->num_entries; index++) {
15313db86aabSstevel int mask = psu_resp->psu_status[index].mask;
15323db86aabSstevel src_entry = &psu_section->entry[index];
15333db86aabSstevel if ((mask & DP_PSU_FAN_FAULT) != 0) {
15343db86aabSstevel dst_entry = &subsection->entry[subindex++];
15353db86aabSstevel dst_entry->handle = src_entry->handle;
15363db86aabSstevel dst_entry->ind_mask = DP_PSU_FAN_FAULT;
15373db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
15383db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
15393db86aabSstevel src_entry->handle_name.name, str_fan_ind);
15403db86aabSstevel }
15413db86aabSstevel if ((mask & DP_PSU_PDCT_FAN) != 0) {
15423db86aabSstevel dst_entry = &subsection->entry[subindex++];
15433db86aabSstevel dst_entry->handle = src_entry->handle;
15443db86aabSstevel dst_entry->ind_mask = DP_PSU_PDCT_FAN;
15453db86aabSstevel (void) snprintf(dst_entry->handle_name.name,
15463db86aabSstevel ENVMON_MAXNAMELEN, "%s.%s",
15473db86aabSstevel src_entry->handle_name.name, str_pdct_fan_ind);
15483db86aabSstevel }
15493db86aabSstevel }
15503db86aabSstevel subsection->num_entries = subindex;
15513db86aabSstevel add_section(chain_head, subsection);
15523db86aabSstevel }
15533db86aabSstevel
15543db86aabSstevel static void
refresh_name_cache(int force_fail)15553db86aabSstevel refresh_name_cache(int force_fail)
15563db86aabSstevel {
15573db86aabSstevel union {
15583db86aabSstevel dp_get_volts_t u_volts_cmd;
15593db86aabSstevel dp_get_temperatures_t u_temp_cmd;
15603db86aabSstevel dp_get_circuit_brks_t u_ampi_cmd;
15613db86aabSstevel dp_get_fan_status_t u_fan_cmd;
15623db86aabSstevel dp_get_psu_status_t u_psu_cmd;
15633db86aabSstevel dp_get_fru_status_t u_fru_cmd;
15643db86aabSstevel dp_get_led_state_t u_led_cmd;
15653db86aabSstevel dp_set_led_state_t u_setled_cmd;
15663db86aabSstevel dp_get_alarm_state_t u_alarm_cmd;
15673db86aabSstevel dp_set_alarm_state_t u_setalarm_cmd;
15683db86aabSstevel } rmc_cmdbuf;
15693db86aabSstevel
15703db86aabSstevel /* defines for accessing union fields */
15713db86aabSstevel #define volts_cmd rmc_cmdbuf.u_volts_cmd
15723db86aabSstevel #define temp_cmd rmc_cmdbuf.u_temp_cmd
15733db86aabSstevel #define ampi_cmd rmc_cmdbuf.u_ampi_cmd
15743db86aabSstevel #define fan_cmd rmc_cmdbuf.u_fan_cmd
15753db86aabSstevel #define psu_cmd rmc_cmdbuf.u_psu_cmd
15763db86aabSstevel #define fru_cmd rmc_cmdbuf.u_fru_cmd
15773db86aabSstevel #define led_cmd rmc_cmdbuf.u_led_cmd
15783db86aabSstevel #define setled_cmd rmc_cmdbuf.u_setled_cmd
15793db86aabSstevel #define alarm_cmd rmc_cmdbuf.u_alarm_cmd
15803db86aabSstevel #define setalarm_cmd rmc_cmdbuf.u_setalarm_cmd
15813db86aabSstevel
15823db86aabSstevel /*
15833db86aabSstevel * Data area to read sensor data into
15843db86aabSstevel */
15853db86aabSstevel static union {
15863db86aabSstevel char reservation[RMCRESBUFLEN];
15873db86aabSstevel dp_get_volts_r_t u_volts_r;
15883db86aabSstevel dp_get_temperatures_r_t u_temp_r;
15893db86aabSstevel dp_get_circuit_brks_r_t u_ampi_r;
15903db86aabSstevel dp_get_fan_status_r_t u_fan_r;
15913db86aabSstevel dp_get_psu_status_r_t u_psu_r;
15923db86aabSstevel dp_get_fru_status_r_t u_fru_r;
15933db86aabSstevel dp_get_led_state_r_t u_led_r;
15943db86aabSstevel dp_set_led_state_r_t u_setled_r;
15953db86aabSstevel dp_get_alarm_state_r_t u_alarm_r;
15963db86aabSstevel dp_set_alarm_state_r_t u_setalarm_r;
15973db86aabSstevel } rmc_sensbuf;
15983db86aabSstevel
15993db86aabSstevel /* defines for accessing union fields */
16003db86aabSstevel #define volts_r rmc_sensbuf.u_volts_r
16013db86aabSstevel #define temp_r rmc_sensbuf.u_temp_r
16023db86aabSstevel #define ampi_r rmc_sensbuf.u_ampi_r
16033db86aabSstevel #define fan_r rmc_sensbuf.u_fan_r
16043db86aabSstevel #define psu_r rmc_sensbuf.u_psu_r
16053db86aabSstevel #define fru_r rmc_sensbuf.u_fru_r
16063db86aabSstevel #define led_r rmc_sensbuf.u_led_r
16073db86aabSstevel #define setled_r rmc_sensbuf.u_setled_r
16083db86aabSstevel #define alarm_r rmc_sensbuf.u_alarm_r
16093db86aabSstevel #define setalarm_r rmc_sensbuf.u_setalarm_r
16103db86aabSstevel
16113db86aabSstevel int retval = force_fail;
16123db86aabSstevel int retval1 = retval;
16133db86aabSstevel int index;
16143db86aabSstevel rmclomv_cache_section_t *my_chain = NULL;
16153db86aabSstevel rmclomv_cache_section_t *derived_chain = NULL;
16163db86aabSstevel rmclomv_cache_section_t *section;
16173db86aabSstevel rmclomv_cache_section_t *psu_section;
16183db86aabSstevel rmclomv_cache_section_t *fru_section;
16193db86aabSstevel dp_get_sysinfo_r_t sysinfo;
16203db86aabSstevel rmclomv_cache_entry_t *entry;
16213db86aabSstevel
16223db86aabSstevel if (retval == 0) {
16233db86aabSstevel retval = rmclomv_do_cmd(DP_GET_SYSINFO, DP_GET_SYSINFO_R,
16243db86aabSstevel sizeof (sysinfo), NULL, (intptr_t)&sysinfo);
16253db86aabSstevel }
16263db86aabSstevel if (retval == 0) {
16273db86aabSstevel fru_cmd.handle = DP_NULL_HANDLE;
16283db86aabSstevel retval = rmclomv_do_cmd(DP_GET_FRU_STATUS, DP_GET_FRU_STATUS_R,
16293db86aabSstevel RMCRESBUFLEN, (intptr_t)&fru_cmd, (intptr_t)&fru_r);
16303db86aabSstevel }
16313db86aabSstevel if (retval != 0)
16323db86aabSstevel fru_r.num_frus = 0;
16333db86aabSstevel
16343db86aabSstevel /*
16353db86aabSstevel * Reserve space for special additional entries in the FRU section
16363db86aabSstevel */
16373db86aabSstevel fru_section = create_cache_section(RMCLOMV_HPU_IND,
16383db86aabSstevel RMCLOMV_NUM_SPECIAL_FRUS + fru_r.num_frus);
16393db86aabSstevel
16403db86aabSstevel /*
16413db86aabSstevel * add special entry for RMC itself
16423db86aabSstevel */
16433db86aabSstevel entry = &fru_section->entry[0];
16443db86aabSstevel (void) snprintf(entry->handle_name.name, sizeof (envmon_handle_t),
16453db86aabSstevel "SC");
16463db86aabSstevel entry->handle = 0;
16473db86aabSstevel entry->ind_mask = 1; /* flag as a special entry */
16483db86aabSstevel
16493db86aabSstevel /*
16503db86aabSstevel * populate any other FRU entries
16513db86aabSstevel */
16523db86aabSstevel for (index = 0; index < fru_r.num_frus; index++) {
16533db86aabSstevel fru_section->entry[RMCLOMV_NUM_SPECIAL_FRUS + index].handle =
16543db86aabSstevel fru_r.fru_status[index].handle;
16553db86aabSstevel fru_section->entry[RMCLOMV_NUM_SPECIAL_FRUS + index].ind_mask =
16563db86aabSstevel 0;
16573db86aabSstevel }
16583db86aabSstevel
16593db86aabSstevel my_chain = fru_section;
16603db86aabSstevel
16613db86aabSstevel if (retval == 0) {
16623db86aabSstevel volts_cmd.handle = DP_NULL_HANDLE;
16633db86aabSstevel retval = rmclomv_do_cmd(DP_GET_VOLTS, DP_GET_VOLTS_R,
16643db86aabSstevel RMCRESBUFLEN, (intptr_t)&volts_cmd, (intptr_t)&volts_r);
16653db86aabSstevel }
16663db86aabSstevel if (retval == 0) {
16673db86aabSstevel section = create_cache_section(RMCLOMV_VOLT_SENS,
16683db86aabSstevel volts_r.num_volts);
16693db86aabSstevel for (index = 0; index < volts_r.num_volts; index++) {
16703db86aabSstevel section->entry[index].handle =
16713db86aabSstevel volts_r.volt_status[index].handle;
16723db86aabSstevel }
16733db86aabSstevel add_section(&my_chain, section);
16743db86aabSstevel }
16753db86aabSstevel if (retval == 0) {
16763db86aabSstevel temp_cmd.handle = DP_NULL_HANDLE;
16773db86aabSstevel retval = rmclomv_do_cmd(DP_GET_TEMPERATURES,
16783db86aabSstevel DP_GET_TEMPERATURES_R, RMCRESBUFLEN,
16793db86aabSstevel (intptr_t)&temp_cmd, (intptr_t)&temp_r);
16803db86aabSstevel }
16813db86aabSstevel if (retval == 0) {
16823db86aabSstevel section = create_cache_section(RMCLOMV_TEMP_SENS,
16833db86aabSstevel temp_r.num_temps);
16843db86aabSstevel for (index = 0; index < temp_r.num_temps; index++) {
16853db86aabSstevel section->entry[index].handle =
16863db86aabSstevel temp_r.temp_status[index].handle;
16873db86aabSstevel }
16883db86aabSstevel add_section(&my_chain, section);
16893db86aabSstevel }
16903db86aabSstevel if (retval == 0) {
16913db86aabSstevel fan_cmd.handle = DP_NULL_HANDLE;
16923db86aabSstevel retval = rmclomv_do_cmd(DP_GET_FAN_STATUS, DP_GET_FAN_STATUS_R,
16933db86aabSstevel RMCRESBUFLEN, (intptr_t)&fan_cmd, (intptr_t)&fan_r);
16943db86aabSstevel }
16953db86aabSstevel if (retval == 0) {
16963db86aabSstevel section = create_cache_section(RMCLOMV_FAN_SENS,
16973db86aabSstevel fan_r.num_fans);
16983db86aabSstevel for (index = 0; index < fan_r.num_fans; index++) {
16993db86aabSstevel section->entry[index].handle =
17003db86aabSstevel fan_r.fan_status[index].handle;
17013db86aabSstevel }
17023db86aabSstevel add_section(&my_chain, section);
17033db86aabSstevel }
17043db86aabSstevel if (retval == 0) {
17053db86aabSstevel ampi_cmd.handle = DP_NULL_HANDLE;
17063db86aabSstevel retval = rmclomv_do_cmd(DP_GET_CIRCUIT_BRKS,
17073db86aabSstevel DP_GET_CIRCUIT_BRKS_R, RMCRESBUFLEN,
17083db86aabSstevel (intptr_t)&i_cmd, (intptr_t)&i_r);
17093db86aabSstevel }
17103db86aabSstevel if (retval == 0) {
17113db86aabSstevel section = create_cache_section(RMCLOMV_AMP_IND,
17123db86aabSstevel ampi_r.num_circuit_brks);
17133db86aabSstevel for (index = 0; index < ampi_r.num_circuit_brks; index++) {
17143db86aabSstevel section->entry[index].handle =
17153db86aabSstevel ampi_r.circuit_brk_status[index].handle;
17163db86aabSstevel }
17173db86aabSstevel add_section(&my_chain, section);
17183db86aabSstevel }
17193db86aabSstevel if (retval == 0) {
17203db86aabSstevel led_cmd.handle = DP_NULL_HANDLE;
17213db86aabSstevel retval = rmclomv_do_cmd(DP_GET_LED_STATE, DP_GET_LED_STATE_R,
17223db86aabSstevel RMCRESBUFLEN, (intptr_t)&led_cmd, (intptr_t)&led_r);
17233db86aabSstevel }
17243db86aabSstevel if (retval == 0) {
17253db86aabSstevel section = create_cache_section(RMCLOMV_LED_IND,
17263db86aabSstevel led_r.num_leds);
17273db86aabSstevel for (index = 0; index < led_r.num_leds; index++) {
17283db86aabSstevel section->entry[index].handle =
17293db86aabSstevel led_r.led_state[index].handle;
17303db86aabSstevel }
17313db86aabSstevel add_section(&my_chain, section);
17323db86aabSstevel }
17333db86aabSstevel /*
17343db86aabSstevel * The command DP_GET_ALARM_STATE may not be valid on
17353db86aabSstevel * some RMC versions, so we ignore the return value
17363db86aabSstevel * and proceed
17373db86aabSstevel */
17383db86aabSstevel if (retval == 0) {
17393db86aabSstevel alarm_cmd.handle = DP_NULL_HANDLE;
17403db86aabSstevel retval1 = rmclomv_do_cmd(DP_GET_ALARM_STATE,
17413db86aabSstevel DP_GET_ALARM_STATE_R, RMCRESBUFLEN,
17423db86aabSstevel (intptr_t)&alarm_cmd, (intptr_t)&alarm_r);
17433db86aabSstevel if ((retval1 == 0) && alarm_r.num_alarms) {
17443db86aabSstevel section = create_cache_section(RMCLOMV_ALARM_IND,
17453db86aabSstevel alarm_r.num_alarms);
17463db86aabSstevel for (index = 0; index < alarm_r.num_alarms; index++) {
17473db86aabSstevel section->entry[index].handle =
17483db86aabSstevel alarm_r.alarm_state[index].handle;
17493db86aabSstevel }
17503db86aabSstevel add_section(&my_chain, section);
17513db86aabSstevel }
17523db86aabSstevel }
17533db86aabSstevel if (retval == 0) {
17543db86aabSstevel psu_cmd.handle = DP_NULL_HANDLE;
17553db86aabSstevel retval = rmclomv_do_cmd(DP_GET_PSU_STATUS, DP_GET_PSU_STATUS_R,
17563db86aabSstevel RMCRESBUFLEN, (intptr_t)&psu_cmd, (intptr_t)&psu_r);
17573db86aabSstevel }
17583db86aabSstevel if (retval == 0) {
17593db86aabSstevel /*
17603db86aabSstevel * WARNING:
17613db86aabSstevel * =======
17623db86aabSstevel * The PSUs must be probed last so that the response data
17633db86aabSstevel * (psu_r) is available for make_psu_subsections() below.
17643db86aabSstevel * Note that all the responses share the same data area
17653db86aabSstevel * which is declared as a union.
17663db86aabSstevel */
17673db86aabSstevel psu_section = create_cache_section(RMCLOMV_PSU_IND,
17683db86aabSstevel psu_r.num_psus);
17693db86aabSstevel for (index = 0; index < psu_r.num_psus; index++) {
17703db86aabSstevel psu_section->entry[index].handle =
17713db86aabSstevel psu_r.psu_status[index].handle;
17723db86aabSstevel }
17733db86aabSstevel add_section(&my_chain, psu_section);
17743db86aabSstevel }
17753db86aabSstevel if (retval == 0) {
17763db86aabSstevel for (section = my_chain;
17773db86aabSstevel section != NULL;
17783db86aabSstevel section = section->next_section) {
17793db86aabSstevel retval = add_names_to_section(section);
17803db86aabSstevel if (retval != 0) {
17813db86aabSstevel break;
17823db86aabSstevel }
17833db86aabSstevel }
17843db86aabSstevel }
17853db86aabSstevel
17863db86aabSstevel /*
17873db86aabSstevel * now add nodes derived from PSUs
17883db86aabSstevel */
17893db86aabSstevel if (retval == 0) {
17903db86aabSstevel make_psu_subsections(psu_section, &derived_chain, &psu_r);
17913db86aabSstevel /*
17923db86aabSstevel * name cache sections all set, exchange new for old
17933db86aabSstevel */
17943db86aabSstevel rmclomv_reset_cache(my_chain, derived_chain, &sysinfo);
17953db86aabSstevel } else {
17963db86aabSstevel /*
17973db86aabSstevel * RMC is not responding, ditch any existing cache
17983db86aabSstevel * and just leave the special SC FRU node
17993db86aabSstevel */
18003db86aabSstevel rmclomv_reset_cache(my_chain, NULL, NULL);
18013db86aabSstevel }
18023db86aabSstevel }
18033db86aabSstevel
18043db86aabSstevel static void
set_val_unav(envmon_sensor_t * sensor)18053db86aabSstevel set_val_unav(envmon_sensor_t *sensor)
18063db86aabSstevel {
18073db86aabSstevel sensor->value = ENVMON_VAL_UNAVAILABLE;
18083db86aabSstevel sensor->lowthresholds.warning = ENVMON_VAL_UNAVAILABLE;
18093db86aabSstevel sensor->lowthresholds.shutdown = ENVMON_VAL_UNAVAILABLE;
18103db86aabSstevel sensor->lowthresholds.poweroff = ENVMON_VAL_UNAVAILABLE;
18113db86aabSstevel sensor->highthresholds.warning = ENVMON_VAL_UNAVAILABLE;
18123db86aabSstevel sensor->highthresholds.shutdown = ENVMON_VAL_UNAVAILABLE;
18133db86aabSstevel sensor->highthresholds.poweroff = ENVMON_VAL_UNAVAILABLE;
18143db86aabSstevel }
18153db86aabSstevel
18163db86aabSstevel static void
set_fan_unav(envmon_fan_t * fan)18173db86aabSstevel set_fan_unav(envmon_fan_t *fan)
18183db86aabSstevel {
18193db86aabSstevel fan->speed = ENVMON_VAL_UNAVAILABLE;
18203db86aabSstevel fan->units[0] = '\0';
18213db86aabSstevel fan->lowthresholds.warning = ENVMON_VAL_UNAVAILABLE;
18223db86aabSstevel fan->lowthresholds.shutdown = ENVMON_VAL_UNAVAILABLE;
18233db86aabSstevel fan->lowthresholds.poweroff = ENVMON_VAL_UNAVAILABLE;
18243db86aabSstevel }
18253db86aabSstevel
18263db86aabSstevel static int
do_psu_cmd(intptr_t arg,int mode,envmon_indicator_t * env_ind,dp_get_psu_status_t * rmc_psu,dp_get_psu_status_r_t * rmc_psu_r,int detector_type)18273db86aabSstevel do_psu_cmd(intptr_t arg, int mode, envmon_indicator_t *env_ind,
18283db86aabSstevel dp_get_psu_status_t *rmc_psu, dp_get_psu_status_r_t *rmc_psu_r,
18293db86aabSstevel int detector_type)
18303db86aabSstevel {
18313db86aabSstevel int index;
18323db86aabSstevel uint16_t sensor_status;
18333db86aabSstevel rmclomv_cache_section_t *section;
18343db86aabSstevel uint16_t indicator_mask;
18353db86aabSstevel
18363db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)env_ind,
18373db86aabSstevel sizeof (envmon_indicator_t), mode) != 0)
18383db86aabSstevel return (EFAULT);
18393db86aabSstevel
18403db86aabSstevel /* ensure we've got PSU handles cached */
18413db86aabSstevel LOCK_CACHE
18423db86aabSstevel
18433db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
18443db86aabSstevel section = rmclomv_find_section(rmclomv_subcache, detector_type);
18453db86aabSstevel if (env_ind->id.name[0] == '\0') {
18463db86aabSstevel /* request for first handle */
18473db86aabSstevel if ((section == NULL) || (section->num_entries == 0))
18483db86aabSstevel env_ind->next_id.name[0] = '\0';
18493db86aabSstevel else
18503db86aabSstevel env_ind->next_id = section->entry[0].handle_name;
18513db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
18523db86aabSstevel } else {
18533db86aabSstevel /* ensure name is properly terminated */
18543db86aabSstevel env_ind->id.name[ENVMON_MAXNAMELEN - 1] = '\0';
18553db86aabSstevel if ((section == NULL) || (get_sensor_by_name(section,
18563db86aabSstevel env_ind->id.name, &index)) != 0) {
18573db86aabSstevel env_ind->next_id.name[0] = '\0';
18583db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
18593db86aabSstevel } else if (index + 1 < section->num_entries)
18603db86aabSstevel env_ind->next_id =
18613db86aabSstevel section->entry[index + 1].handle_name;
18623db86aabSstevel else
18633db86aabSstevel env_ind->next_id.name[0] = '\0';
18643db86aabSstevel }
18653db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
18663db86aabSstevel /*
18673db86aabSstevel * user correctly identified a sensor, note its
18683db86aabSstevel * handle value and request the indicator status
18693db86aabSstevel */
18703db86aabSstevel rmc_psu->handle = section->entry[index].handle;
18713db86aabSstevel indicator_mask = section->entry[index].ind_mask;
18723db86aabSstevel }
18733db86aabSstevel
18743db86aabSstevel RELEASE_CACHE
18753db86aabSstevel
18763db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error ||
18773db86aabSstevel rmclomv_do_cmd(DP_GET_PSU_STATUS, DP_GET_PSU_STATUS_R,
18783db86aabSstevel sizeof (dp_get_psu_status_r_t), (intptr_t)rmc_psu,
18793db86aabSstevel (intptr_t)rmc_psu_r) != 0)) {
18803db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
18813db86aabSstevel }
18823db86aabSstevel if ((env_ind->sensor_status = sensor_status) == ENVMON_SENSOR_OK) {
18833db86aabSstevel /*
18843db86aabSstevel * copy results into buffer for user
18853db86aabSstevel */
18863db86aabSstevel if ((rmc_psu_r->psu_status[0].flag & DP_PSU_PRESENCE) == 0)
18873db86aabSstevel env_ind->sensor_status |= ENVMON_NOT_PRESENT;
18883db86aabSstevel if (rmc_psu_r->psu_status[0].sensor_status !=
18893db86aabSstevel DP_SENSOR_DATA_AVAILABLE)
18903db86aabSstevel env_ind->sensor_status |= ENVMON_INACCESSIBLE;
18913db86aabSstevel env_ind->condition =
18923db86aabSstevel (rmc_psu_r->psu_status[0].flag & indicator_mask) == 0 ?
18933db86aabSstevel 0 : 1;
18943db86aabSstevel }
18953db86aabSstevel
18963db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE)
18973db86aabSstevel env_ind->sensor_status = ENVMON_INACCESSIBLE;
18983db86aabSstevel
18993db86aabSstevel if (ddi_copyout((caddr_t)env_ind, (caddr_t)arg,
19003db86aabSstevel sizeof (envmon_indicator_t), mode) != 0)
19013db86aabSstevel return (EFAULT);
19023db86aabSstevel
19033db86aabSstevel return (0);
19043db86aabSstevel }
19053db86aabSstevel
19063db86aabSstevel /*ARGSUSED*/
19073db86aabSstevel static int
rmclomv_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rval_p)19083db86aabSstevel rmclomv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
19093db86aabSstevel int *rval_p)
19103db86aabSstevel {
19113db86aabSstevel int instance = getminor(dev);
19123db86aabSstevel envmon_sysinfo_t lomv_sysinfo;
19133db86aabSstevel union {
19143db86aabSstevel envmon_sensor_t u_env_sensor;
19153db86aabSstevel envmon_indicator_t u_env_ind;
19163db86aabSstevel envmon_fan_t u_env_fan;
19173db86aabSstevel envmon_led_info_t u_env_ledinfo;
19183db86aabSstevel envmon_led_ctl_t u_env_ledctl;
19193db86aabSstevel envmon_hpu_t u_env_hpu;
19203db86aabSstevel envmon_alarm_info_t u_env_alarminfo;
19213db86aabSstevel envmon_alarm_ctl_t u_env_alarmctl;
19223db86aabSstevel } env_buf;
19233db86aabSstevel #define env_sensor env_buf.u_env_sensor
19243db86aabSstevel #define env_ind env_buf.u_env_ind
19253db86aabSstevel #define env_fan env_buf.u_env_fan
19263db86aabSstevel #define env_ledinfo env_buf.u_env_ledinfo
19273db86aabSstevel #define env_ledctl env_buf.u_env_ledctl
19283db86aabSstevel #define env_hpu env_buf.u_env_hpu
19293db86aabSstevel #define env_alarminfo env_buf.u_env_alarminfo
19303db86aabSstevel #define env_alarmctl env_buf.u_env_alarmctl
19313db86aabSstevel
19323db86aabSstevel union {
19333db86aabSstevel dp_get_volts_t u_rmc_volts;
19343db86aabSstevel dp_get_temperatures_t u_rmc_temp;
19353db86aabSstevel dp_get_circuit_brks_t u_rmc_ampi;
19363db86aabSstevel dp_get_fan_status_t u_rmc_fan;
19373db86aabSstevel dp_get_psu_status_t u_rmc_psu;
19383db86aabSstevel dp_get_fru_status_t u_rmc_fru;
19393db86aabSstevel dp_get_led_state_t u_rmc_led;
19403db86aabSstevel dp_set_led_state_t u_rmc_setled;
19413db86aabSstevel dp_get_alarm_state_t u_rmc_alarm;
19423db86aabSstevel dp_set_alarm_state_t u_rmc_setalarm;
19433db86aabSstevel } rmc_reqbuf;
19443db86aabSstevel #define rmc_volts rmc_reqbuf.u_rmc_volts
19453db86aabSstevel #define rmc_temp rmc_reqbuf.u_rmc_temp
19463db86aabSstevel #define rmc_ampi rmc_reqbuf.u_rmc_ampi
19473db86aabSstevel #define rmc_fan rmc_reqbuf.u_rmc_fan
19483db86aabSstevel #define rmc_psu rmc_reqbuf.u_rmc_psu
19493db86aabSstevel #define rmc_fru rmc_reqbuf.u_rmc_fru
19503db86aabSstevel #define rmc_led rmc_reqbuf.u_rmc_led
19513db86aabSstevel #define rmc_setled rmc_reqbuf.u_rmc_setled
19523db86aabSstevel #define rmc_alarm rmc_reqbuf.u_rmc_alarm
19533db86aabSstevel #define rmc_setalarm rmc_reqbuf.u_rmc_setalarm
19543db86aabSstevel
19553db86aabSstevel union {
19563db86aabSstevel dp_get_volts_r_t u_rmc_volts_r;
19573db86aabSstevel dp_get_temperatures_r_t u_rmc_temp_r;
19583db86aabSstevel dp_get_circuit_brks_r_t u_rmc_ampi_r;
19593db86aabSstevel dp_get_fan_status_r_t u_rmc_fan_r;
19603db86aabSstevel dp_get_psu_status_r_t u_rmc_psu_r;
19613db86aabSstevel dp_get_fru_status_r_t u_rmc_fru_r;
19623db86aabSstevel dp_get_led_state_r_t u_rmc_led_r;
19633db86aabSstevel dp_set_led_state_r_t u_rmc_setled_r;
19643db86aabSstevel dp_get_alarm_state_r_t u_rmc_alarm_r;
19653db86aabSstevel dp_set_alarm_state_r_t u_rmc_setalarm_r;
19663db86aabSstevel dp_get_sdp_version_r_t u_rmc_sdpversion_r;
19673db86aabSstevel dp_get_serialnum_r_t u_rmc_serialnum_r;
19683db86aabSstevel } rmc_resbuf;
19693db86aabSstevel #define rmc_volts_r rmc_resbuf.u_rmc_volts_r
19703db86aabSstevel #define rmc_temp_r rmc_resbuf.u_rmc_temp_r
19713db86aabSstevel #define rmc_ampi_r rmc_resbuf.u_rmc_ampi_r
19723db86aabSstevel #define rmc_fan_r rmc_resbuf.u_rmc_fan_r
19733db86aabSstevel #define rmc_psu_r rmc_resbuf.u_rmc_psu_r
19743db86aabSstevel #define rmc_fru_r rmc_resbuf.u_rmc_fru_r
19753db86aabSstevel #define rmc_led_r rmc_resbuf.u_rmc_led_r
19763db86aabSstevel #define rmc_setled_r rmc_resbuf.u_rmc_setled_r
19773db86aabSstevel #define rmc_alarm_r rmc_resbuf.u_rmc_alarm_r
19783db86aabSstevel #define rmc_setalarm_r rmc_resbuf.u_rmc_setalarm_r
19793db86aabSstevel #define rmc_sdpver_r rmc_resbuf.u_rmc_sdpversion_r
19803db86aabSstevel #define rmc_serialnum_r rmc_resbuf.u_rmc_serialnum_r
19813db86aabSstevel
19823db86aabSstevel int retval = 0;
19833db86aabSstevel int special = 0;
19843db86aabSstevel int index;
19853db86aabSstevel uint16_t sensor_status;
19863db86aabSstevel rmclomv_cache_section_t *section;
19873db86aabSstevel envmon_chassis_t chassis;
19883db86aabSstevel
19893db86aabSstevel if (instance != 0)
19903db86aabSstevel return (ENXIO);
19913db86aabSstevel
19923db86aabSstevel switch (cmd) {
19933db86aabSstevel case ENVMONIOCSYSINFO:
19943db86aabSstevel
19953db86aabSstevel LOCK_CACHE
19963db86aabSstevel
19973db86aabSstevel /*
19983db86aabSstevel * A number of OK/not_OK indicators are supported by PSUs
19993db86aabSstevel * (voltage, current, fan, temperature). So the maximum
20003db86aabSstevel * number of such indicators relates to the maximum number
20013db86aabSstevel * of power-supplies.
20023db86aabSstevel */
20033db86aabSstevel if (rmclomv_sysinfo_valid) {
20043db86aabSstevel lomv_sysinfo.maxVoltSens = rmclomv_sysinfo_data.maxVolt;
20053db86aabSstevel lomv_sysinfo.maxVoltInd =
20063db86aabSstevel RMCLOMV_MAX_VI_PER_PSU *
20073db86aabSstevel rmclomv_sysinfo_data.maxPSU;
20083db86aabSstevel /*
20093db86aabSstevel * the ALOM-Solaris interface does not include
20103db86aabSstevel * amp sensors, so we can hard code this value
20113db86aabSstevel */
20123db86aabSstevel lomv_sysinfo.maxAmpSens = 0;
20133db86aabSstevel lomv_sysinfo.maxAmpInd =
20143db86aabSstevel rmclomv_sysinfo_data.maxCircuitBrks +
20153db86aabSstevel (RMCLOMV_MAX_CI_PER_PSU *
20163db86aabSstevel rmclomv_sysinfo_data.maxPSU);
20173db86aabSstevel lomv_sysinfo.maxTempSens = rmclomv_sysinfo_data.maxTemp;
20183db86aabSstevel lomv_sysinfo.maxTempInd =
20193db86aabSstevel (RMCLOMV_MAX_TI_PER_PSU *
20203db86aabSstevel rmclomv_sysinfo_data.maxPSU);
20213db86aabSstevel lomv_sysinfo.maxFanSens = rmclomv_sysinfo_data.maxFan;
20223db86aabSstevel lomv_sysinfo.maxFanInd =
20233db86aabSstevel RMCLOMV_MAX_FI_PER_PSU *
20243db86aabSstevel rmclomv_sysinfo_data.maxPSU;
20253db86aabSstevel lomv_sysinfo.maxLED = rmclomv_sysinfo_data.maxLED;
20263db86aabSstevel lomv_sysinfo.maxHPU = RMCLOMV_NUM_SPECIAL_FRUS +
20273db86aabSstevel rmclomv_sysinfo_data.maxFRU;
20283db86aabSstevel } else {
20293db86aabSstevel bzero(&lomv_sysinfo, sizeof (lomv_sysinfo));
20303db86aabSstevel lomv_sysinfo.maxHPU = 1; /* just the SC node */
20313db86aabSstevel }
20323db86aabSstevel
20333db86aabSstevel RELEASE_CACHE
20343db86aabSstevel
20353db86aabSstevel if (ddi_copyout((caddr_t)&lomv_sysinfo, (caddr_t)arg,
20363db86aabSstevel sizeof (lomv_sysinfo), mode) != 0)
20373db86aabSstevel return (EFAULT);
20383db86aabSstevel break;
20393db86aabSstevel
20403db86aabSstevel case ENVMONIOCVOLTSENSOR:
20413db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_sensor,
20423db86aabSstevel sizeof (envmon_sensor_t), mode) != 0)
20433db86aabSstevel return (EFAULT);
20443db86aabSstevel
20453db86aabSstevel /* see if we've got volts handles cached */
20463db86aabSstevel LOCK_CACHE
20473db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
20483db86aabSstevel
20493db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
20503db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
20513db86aabSstevel RMCLOMV_VOLT_SENS)) == NULL)) {
20523db86aabSstevel env_sensor.next_id.name[0] = '\0';
20533db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
20543db86aabSstevel } else if (env_sensor.id.name[0] == '\0') {
20553db86aabSstevel /* request for first handle */
20563db86aabSstevel if (section->num_entries == 0)
20573db86aabSstevel env_sensor.next_id.name[0] = '\0';
20583db86aabSstevel else
20593db86aabSstevel env_sensor.next_id =
20603db86aabSstevel section->entry[0].handle_name;
20613db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
20623db86aabSstevel } else {
20633db86aabSstevel /* ensure name is properly terminated */
20643db86aabSstevel env_sensor.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
20653db86aabSstevel if (get_sensor_by_name(section, env_sensor.id.name,
20663db86aabSstevel &index) != 0) {
20673db86aabSstevel env_sensor.next_id.name[0] = '\0';
20683db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
20693db86aabSstevel } else if (index + 1 < section->num_entries)
20703db86aabSstevel env_sensor.next_id =
20713db86aabSstevel section->entry[index + 1].handle_name;
20723db86aabSstevel else
20733db86aabSstevel env_sensor.next_id.name[0] = '\0';
20743db86aabSstevel }
20753db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
20763db86aabSstevel /*
20773db86aabSstevel * user correctly identified a sensor, note its
20783db86aabSstevel * handle value and request the sensor value
20793db86aabSstevel */
20803db86aabSstevel rmc_volts.handle = section->entry[index].handle;
20813db86aabSstevel }
20823db86aabSstevel RELEASE_CACHE
20833db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error ||
20843db86aabSstevel rmclomv_do_cmd(DP_GET_VOLTS, DP_GET_VOLTS_R,
20853db86aabSstevel sizeof (rmc_volts_r), (intptr_t)&rmc_volts,
20863db86aabSstevel (intptr_t)&rmc_volts_r) != 0)) {
20873db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
20883db86aabSstevel }
20893db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) &&
20903db86aabSstevel (rmc_volts_r.volt_status[0].sensor_status ==
20913db86aabSstevel DP_SENSOR_NOT_PRESENT)) {
20923db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
20933db86aabSstevel }
20943db86aabSstevel if ((env_sensor.sensor_status = sensor_status) ==
20953db86aabSstevel ENVMON_SENSOR_OK) {
20963db86aabSstevel /*
20973db86aabSstevel * copy results into buffer for user
20983db86aabSstevel */
20993db86aabSstevel if (rmc_volts_r.volt_status[0].sensor_status !=
21003db86aabSstevel DP_SENSOR_DATA_AVAILABLE)
21013db86aabSstevel env_sensor.sensor_status = ENVMON_INACCESSIBLE;
21023db86aabSstevel env_sensor.value =
21033db86aabSstevel rmc_volts_r.volt_status[0].reading;
21043db86aabSstevel env_sensor.lowthresholds.warning =
21053db86aabSstevel rmc_volts_r.volt_status[0].low_warning;
21063db86aabSstevel env_sensor.lowthresholds.shutdown =
21073db86aabSstevel rmc_volts_r.volt_status[0].low_soft_shutdown;
21083db86aabSstevel env_sensor.lowthresholds.poweroff =
21093db86aabSstevel rmc_volts_r.volt_status[0].low_hard_shutdown;
21103db86aabSstevel env_sensor.highthresholds.warning =
21113db86aabSstevel rmc_volts_r.volt_status[0].high_warning;
21123db86aabSstevel env_sensor.highthresholds.shutdown =
21133db86aabSstevel rmc_volts_r.volt_status[0].high_soft_shutdown;
21143db86aabSstevel env_sensor.highthresholds.poweroff =
21153db86aabSstevel rmc_volts_r.volt_status[0].high_hard_shutdown;
21163db86aabSstevel }
21173db86aabSstevel if (env_sensor.sensor_status != ENVMON_SENSOR_OK ||
21183db86aabSstevel rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE)
21193db86aabSstevel set_val_unav(&env_sensor);
21203db86aabSstevel
21213db86aabSstevel if (ddi_copyout((caddr_t)&env_sensor, (caddr_t)arg,
21223db86aabSstevel sizeof (envmon_sensor_t), mode) != 0)
21233db86aabSstevel return (EFAULT);
21243db86aabSstevel break;
21253db86aabSstevel
21263db86aabSstevel case ENVMONIOCVOLTIND:
21273db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, &rmc_psu, &rmc_psu_r,
21283db86aabSstevel RMCLOMV_VOLT_IND));
21293db86aabSstevel
21303db86aabSstevel case ENVMONIOCTEMPIND:
21313db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, &rmc_psu, &rmc_psu_r,
21323db86aabSstevel RMCLOMV_TEMP_IND));
21333db86aabSstevel
21343db86aabSstevel case ENVMONIOCFANIND:
21353db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, &rmc_psu, &rmc_psu_r,
21363db86aabSstevel RMCLOMV_FAN_IND));
21373db86aabSstevel
21383db86aabSstevel case ENVMONIOCAMPSENSOR:
21393db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_sensor,
21403db86aabSstevel sizeof (envmon_sensor_t), mode) != 0)
21413db86aabSstevel return (EFAULT);
21423db86aabSstevel
21433db86aabSstevel env_sensor.sensor_status = ENVMON_NOT_PRESENT;
21443db86aabSstevel env_sensor.next_id.name[0] = '\0';
21453db86aabSstevel
21463db86aabSstevel if (ddi_copyout((caddr_t)&env_sensor, (caddr_t)arg,
21473db86aabSstevel sizeof (envmon_sensor_t), mode) != 0)
21483db86aabSstevel return (EFAULT);
21493db86aabSstevel break;
21503db86aabSstevel
21513db86aabSstevel case ENVMONIOCTEMPSENSOR:
21523db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_sensor,
21533db86aabSstevel sizeof (envmon_sensor_t), mode) != 0)
21543db86aabSstevel return (EFAULT);
21553db86aabSstevel
21563db86aabSstevel /* see if we've got temperature handles cached */
21573db86aabSstevel LOCK_CACHE
21583db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
21593db86aabSstevel
21603db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
21613db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
21623db86aabSstevel RMCLOMV_TEMP_SENS)) == NULL)) {
21633db86aabSstevel env_sensor.next_id.name[0] = '\0';
21643db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
21653db86aabSstevel } else if (env_sensor.id.name[0] == '\0') {
21663db86aabSstevel /* request for first handle */
21673db86aabSstevel if (section->num_entries == 0)
21683db86aabSstevel env_sensor.next_id.name[0] = '\0';
21693db86aabSstevel else
21703db86aabSstevel env_sensor.next_id =
21713db86aabSstevel section->entry[0].handle_name;
21723db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
21733db86aabSstevel } else {
21743db86aabSstevel /* ensure name is properly terminated */
21753db86aabSstevel env_sensor.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
21763db86aabSstevel if (get_sensor_by_name(section, env_sensor.id.name,
21773db86aabSstevel &index) != 0) {
21783db86aabSstevel env_sensor.next_id.name[0] = '\0';
21793db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
21803db86aabSstevel } else if (index + 1 < section->num_entries)
21813db86aabSstevel env_sensor.next_id =
21823db86aabSstevel section->entry[index + 1].handle_name;
21833db86aabSstevel else
21843db86aabSstevel env_sensor.next_id.name[0] = '\0';
21853db86aabSstevel }
21863db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
21873db86aabSstevel /*
21883db86aabSstevel * user correctly identified a sensor, note its
21893db86aabSstevel * handle value and request the sensor value
21903db86aabSstevel */
21913db86aabSstevel rmc_temp.handle = section->entry[index].handle;
21923db86aabSstevel }
21933db86aabSstevel RELEASE_CACHE
21943db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error ||
21953db86aabSstevel rmclomv_do_cmd(DP_GET_TEMPERATURES, DP_GET_TEMPERATURES_R,
21963db86aabSstevel sizeof (rmc_temp_r), (intptr_t)&rmc_temp,
21973db86aabSstevel (intptr_t)&rmc_temp_r) != 0)) {
21983db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
21993db86aabSstevel }
22003db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) &&
22013db86aabSstevel (rmc_temp_r.temp_status[0].sensor_status ==
22023db86aabSstevel DP_SENSOR_NOT_PRESENT)) {
22033db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
22043db86aabSstevel }
22053db86aabSstevel if ((env_sensor.sensor_status = sensor_status) ==
22063db86aabSstevel ENVMON_SENSOR_OK) {
22073db86aabSstevel /*
22083db86aabSstevel * copy results into buffer for user
22093db86aabSstevel */
22103db86aabSstevel if (rmc_temp_r.temp_status[0].sensor_status !=
22113db86aabSstevel DP_SENSOR_DATA_AVAILABLE)
22123db86aabSstevel env_sensor.sensor_status = ENVMON_INACCESSIBLE;
22133db86aabSstevel env_sensor.value =
22143db86aabSstevel rmc_temp_r.temp_status[0].value;
22153db86aabSstevel env_sensor.lowthresholds.warning =
22163db86aabSstevel rmc_temp_r.temp_status[0].low_warning;
22173db86aabSstevel env_sensor.lowthresholds.shutdown =
22183db86aabSstevel rmc_temp_r.temp_status[0].low_soft_shutdown;
22193db86aabSstevel env_sensor.lowthresholds.poweroff =
22203db86aabSstevel rmc_temp_r.temp_status[0].low_hard_shutdown;
22213db86aabSstevel env_sensor.highthresholds.warning =
22223db86aabSstevel rmc_temp_r.temp_status[0].high_warning;
22233db86aabSstevel env_sensor.highthresholds.shutdown =
22243db86aabSstevel rmc_temp_r.temp_status[0].high_soft_shutdown;
22253db86aabSstevel env_sensor.highthresholds.poweroff =
22263db86aabSstevel rmc_temp_r.temp_status[0].high_hard_shutdown;
22273db86aabSstevel }
22283db86aabSstevel if (env_sensor.sensor_status != ENVMON_SENSOR_OK ||
22293db86aabSstevel rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE)
22303db86aabSstevel set_val_unav(&env_sensor);
22313db86aabSstevel
22323db86aabSstevel if (ddi_copyout((caddr_t)&env_sensor, (caddr_t)arg,
22333db86aabSstevel sizeof (envmon_sensor_t), mode) != 0)
22343db86aabSstevel return (EFAULT);
22353db86aabSstevel break;
22363db86aabSstevel
22373db86aabSstevel
22383db86aabSstevel case ENVMONIOCFAN:
22393db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_fan,
22403db86aabSstevel sizeof (envmon_fan_t), mode) != 0)
22413db86aabSstevel return (EFAULT);
22423db86aabSstevel
22433db86aabSstevel /* see if we've got fan handles cached */
22443db86aabSstevel LOCK_CACHE
22453db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
22463db86aabSstevel
22473db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
22483db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
22493db86aabSstevel RMCLOMV_FAN_SENS)) == NULL)) {
22503db86aabSstevel env_fan.next_id.name[0] = '\0';
22513db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
22523db86aabSstevel } else if (env_fan.id.name[0] == '\0') {
22533db86aabSstevel /* request for first handle */
22543db86aabSstevel if (section->num_entries == 0)
22553db86aabSstevel env_fan.next_id.name[0] = '\0';
22563db86aabSstevel else
22573db86aabSstevel env_fan.next_id =
22583db86aabSstevel section->entry[0].handle_name;
22593db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
22603db86aabSstevel } else {
22613db86aabSstevel /* ensure name is properly terminated */
22623db86aabSstevel env_fan.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
22633db86aabSstevel if (get_sensor_by_name(section, env_fan.id.name,
22643db86aabSstevel &index) != 0) {
22653db86aabSstevel env_fan.next_id.name[0] = '\0';
22663db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
22673db86aabSstevel } else if (index + 1 < section->num_entries)
22683db86aabSstevel env_fan.next_id =
22693db86aabSstevel section->entry[index + 1].handle_name;
22703db86aabSstevel else
22713db86aabSstevel env_fan.next_id.name[0] = '\0';
22723db86aabSstevel }
22733db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
22743db86aabSstevel /*
22753db86aabSstevel * user correctly identified a sensor, note its
22763db86aabSstevel * handle value and request the sensor value
22773db86aabSstevel */
22783db86aabSstevel rmc_fan.handle = section->entry[index].handle;
22793db86aabSstevel }
22803db86aabSstevel RELEASE_CACHE
22813db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error ||
22823db86aabSstevel rmclomv_do_cmd(DP_GET_FAN_STATUS, DP_GET_FAN_STATUS_R,
22833db86aabSstevel sizeof (rmc_fan_r), (intptr_t)&rmc_fan,
22843db86aabSstevel (intptr_t)&rmc_fan_r) != 0)) {
22853db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
22863db86aabSstevel }
22873db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) &&
22883db86aabSstevel (rmc_fan_r.fan_status[0].sensor_status ==
22893db86aabSstevel DP_SENSOR_NOT_PRESENT)) {
22903db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
22913db86aabSstevel }
22923db86aabSstevel if ((env_fan.sensor_status = sensor_status) ==
22933db86aabSstevel ENVMON_SENSOR_OK) {
22943db86aabSstevel if ((rmc_fan_r.fan_status[0].flag &
22953db86aabSstevel DP_FAN_PRESENCE) == 0)
22963db86aabSstevel env_fan.sensor_status = ENVMON_NOT_PRESENT;
22973db86aabSstevel if (rmc_fan_r.fan_status[0].sensor_status !=
22983db86aabSstevel DP_SENSOR_DATA_AVAILABLE)
22993db86aabSstevel env_fan.sensor_status |= ENVMON_INACCESSIBLE;
23003db86aabSstevel if (env_fan.sensor_status == ENVMON_SENSOR_OK) {
23013db86aabSstevel /*
23023db86aabSstevel * copy results into buffer for user
23033db86aabSstevel */
23043db86aabSstevel env_fan.speed =
23053db86aabSstevel rmc_fan_r.fan_status[0].speed;
23063db86aabSstevel env_fan.lowthresholds.warning =
23073db86aabSstevel rmc_fan_r.fan_status[0].minspeed;
23083db86aabSstevel env_fan.lowthresholds.shutdown =
23093db86aabSstevel ENVMON_VAL_UNAVAILABLE;
23103db86aabSstevel env_fan.lowthresholds.poweroff =
23113db86aabSstevel ENVMON_VAL_UNAVAILABLE;
23123db86aabSstevel if ((rmc_fan_r.fan_status[0].flag &
23133db86aabSstevel DP_FAN_SPEED_VAL_UNIT) == 0)
23143db86aabSstevel bcopy(str_rpm, env_fan.units,
23153db86aabSstevel sizeof (str_rpm));
23163db86aabSstevel else
23173db86aabSstevel bcopy(str_percent, env_fan.units,
23183db86aabSstevel sizeof (str_percent));
23193db86aabSstevel }
23203db86aabSstevel }
23213db86aabSstevel if (env_fan.sensor_status != ENVMON_SENSOR_OK ||
23223db86aabSstevel rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE)
23233db86aabSstevel set_fan_unav(&env_fan);
23243db86aabSstevel
23253db86aabSstevel if (ddi_copyout((caddr_t)&env_fan, (caddr_t)arg,
23263db86aabSstevel sizeof (envmon_fan_t), mode) != 0)
23273db86aabSstevel return (EFAULT);
23283db86aabSstevel break;
23293db86aabSstevel
23303db86aabSstevel case ENVMONIOCAMPIND:
23313db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_ind,
23323db86aabSstevel sizeof (envmon_indicator_t), mode) != 0)
23333db86aabSstevel return (EFAULT);
23343db86aabSstevel
23353db86aabSstevel /* see if we've got amp indicator handles cached */
23363db86aabSstevel LOCK_CACHE
23373db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
23383db86aabSstevel
23393db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
23403db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
23413db86aabSstevel RMCLOMV_AMP_IND)) == NULL)) {
23423db86aabSstevel RELEASE_CACHE
23433db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind, &rmc_psu,
23443db86aabSstevel &rmc_psu_r, RMCLOMV_AMP_IND));
23453db86aabSstevel } else if (env_ind.id.name[0] == '\0') {
23463db86aabSstevel /* request for first handle */
23473db86aabSstevel if (section->num_entries == 0) {
23483db86aabSstevel RELEASE_CACHE
23493db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind,
23503db86aabSstevel &rmc_psu, &rmc_psu_r, RMCLOMV_AMP_IND));
23513db86aabSstevel }
23523db86aabSstevel env_ind.next_id = section->entry[0].handle_name;
23533db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
23543db86aabSstevel } else {
23553db86aabSstevel /* ensure name is properly terminated */
23563db86aabSstevel env_ind.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
23573db86aabSstevel if (get_sensor_by_name(section, env_ind.id.name,
23583db86aabSstevel &index) != 0) {
23593db86aabSstevel RELEASE_CACHE
23603db86aabSstevel return (do_psu_cmd(arg, mode, &env_ind,
23613db86aabSstevel &rmc_psu, &rmc_psu_r, RMCLOMV_AMP_IND));
23623db86aabSstevel }
23633db86aabSstevel if (index + 1 < section->num_entries) {
23643db86aabSstevel env_ind.next_id =
23653db86aabSstevel section->entry[index + 1].handle_name;
23663db86aabSstevel } else {
23673db86aabSstevel rmclomv_cache_section_t *sub_section =
23683db86aabSstevel rmclomv_find_section(rmclomv_subcache,
23693db86aabSstevel RMCLOMV_AMP_IND);
23703db86aabSstevel if ((sub_section == NULL) ||
23713db86aabSstevel (sub_section->num_entries == 0))
23723db86aabSstevel env_ind.next_id.name[0] = '\0';
23733db86aabSstevel else
23743db86aabSstevel env_ind.next_id =
23753db86aabSstevel sub_section->entry[0].handle_name;
23763db86aabSstevel }
23773db86aabSstevel }
23783db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
23793db86aabSstevel /*
23803db86aabSstevel * user correctly identified an indicator, note its
23813db86aabSstevel * handle value and request the indicator status
23823db86aabSstevel */
23833db86aabSstevel rmc_ampi.handle = section->entry[index].handle;
23843db86aabSstevel }
23853db86aabSstevel RELEASE_CACHE
23863db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error ||
23873db86aabSstevel rmclomv_do_cmd(DP_GET_CIRCUIT_BRKS, DP_GET_CIRCUIT_BRKS_R,
23883db86aabSstevel sizeof (rmc_ampi_r), (intptr_t)&rmc_ampi,
23893db86aabSstevel (intptr_t)&rmc_ampi_r) != 0)) {
23903db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
23913db86aabSstevel }
23923db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) &&
23933db86aabSstevel (rmc_ampi_r.circuit_brk_status[0].sensor_status ==
23943db86aabSstevel DP_SENSOR_NOT_PRESENT)) {
23953db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
23963db86aabSstevel }
23973db86aabSstevel if ((env_ind.sensor_status = sensor_status) ==
23983db86aabSstevel ENVMON_SENSOR_OK) {
23993db86aabSstevel /*
24003db86aabSstevel * copy results into buffer for user
24013db86aabSstevel */
24023db86aabSstevel if (rmc_ampi_r.circuit_brk_status[0].sensor_status !=
24033db86aabSstevel DP_SENSOR_DATA_AVAILABLE)
24043db86aabSstevel env_ind.sensor_status = ENVMON_INACCESSIBLE;
24053db86aabSstevel env_ind.condition =
24063db86aabSstevel rmc_ampi_r.circuit_brk_status[0].status;
24073db86aabSstevel }
24083db86aabSstevel
24093db86aabSstevel /*
24103db86aabSstevel * If rmclomv_rmc_error is set there is no way
24113db86aabSstevel * that we read information from RSC. Just copy
24123db86aabSstevel * out an inaccessible evironmental.
24133db86aabSstevel */
24143db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) {
24153db86aabSstevel env_ind.sensor_status = ENVMON_INACCESSIBLE;
24163db86aabSstevel env_ind.condition = ENVMON_INACCESSIBLE;
24173db86aabSstevel }
24183db86aabSstevel
24193db86aabSstevel if (ddi_copyout((caddr_t)&env_ind, (caddr_t)arg,
24203db86aabSstevel sizeof (envmon_indicator_t), mode) != 0)
24213db86aabSstevel return (EFAULT);
24223db86aabSstevel break;
24233db86aabSstevel
24243db86aabSstevel case ENVMONIOCHPU:
24253db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_hpu,
24263db86aabSstevel sizeof (envmon_hpu_t), mode) != 0)
24273db86aabSstevel return (EFAULT);
24283db86aabSstevel
24293db86aabSstevel /* see if we've got hpu handles cached */
24303db86aabSstevel LOCK_CACHE
24313db86aabSstevel
24323db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
24333db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
24343db86aabSstevel RMCLOMV_HPU_IND)) == NULL)) {
24353db86aabSstevel RELEASE_CACHE
24363db86aabSstevel return (EAGAIN);
24373db86aabSstevel }
24383db86aabSstevel
24393db86aabSstevel /*
24403db86aabSstevel * At this point the cache is locked and section points to
24413db86aabSstevel * the section relating to hpus.
24423db86aabSstevel */
24433db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
24443db86aabSstevel if (env_hpu.id.name[0] == '\0') {
24453db86aabSstevel /* request for first handle */
24463db86aabSstevel if (section->num_entries == 0)
24473db86aabSstevel env_hpu.next_id.name[0] = '\0';
24483db86aabSstevel else
24493db86aabSstevel env_hpu.next_id =
24503db86aabSstevel section->entry[0].handle_name;
24513db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
24523db86aabSstevel } else {
24533db86aabSstevel /* ensure name is properly terminated */
24543db86aabSstevel env_hpu.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
24553db86aabSstevel if (get_sensor_by_name(section, env_hpu.id.name,
24563db86aabSstevel &index) != 0) {
24573db86aabSstevel env_hpu.next_id.name[0] = '\0';
24583db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
24593db86aabSstevel } else if (index + 1 < section->num_entries)
24603db86aabSstevel env_hpu.next_id =
24613db86aabSstevel section->entry[index + 1].handle_name;
24623db86aabSstevel else
24633db86aabSstevel env_hpu.next_id.name[0] = '\0';
24643db86aabSstevel }
24653db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
24663db86aabSstevel /*
24673db86aabSstevel * user correctly identified an hpu, note its
24683db86aabSstevel * handle value and request the hpu status
24693db86aabSstevel */
24703db86aabSstevel rmc_fru.handle = section->entry[index].handle;
24713db86aabSstevel special = section->entry[index].ind_mask;
24723db86aabSstevel }
24733db86aabSstevel RELEASE_CACHE
24743db86aabSstevel if ((env_hpu.sensor_status = sensor_status) ==
24753db86aabSstevel ENVMON_SENSOR_OK) {
24763db86aabSstevel env_hpu.fru_status = ENVMON_FRU_PRESENT;
24773db86aabSstevel
24783db86aabSstevel if (special != 0) {
24793db86aabSstevel /* this is the pseudo SC node */
24803db86aabSstevel mutex_enter(&rmclomv_state_lock);
24813db86aabSstevel switch (rmclomv_rmc_state) {
24823db86aabSstevel case RMCLOMV_RMCSTATE_OK:
24833db86aabSstevel break;
24843db86aabSstevel case RMCLOMV_RMCSTATE_FAILED:
24853db86aabSstevel env_hpu.fru_status = ENVMON_FRU_FAULT;
24863db86aabSstevel break;
24873db86aabSstevel case RMCLOMV_RMCSTATE_DOWNLOAD:
24883db86aabSstevel env_hpu.fru_status =
24893db86aabSstevel ENVMON_FRU_DOWNLOAD;
24903db86aabSstevel break;
24913db86aabSstevel default:
24923db86aabSstevel env_hpu.sensor_status =
24933db86aabSstevel ENVMON_INACCESSIBLE;
24943db86aabSstevel break;
24953db86aabSstevel }
24963db86aabSstevel mutex_exit(&rmclomv_state_lock);
24973db86aabSstevel } else if (rmclomv_rmc_error ||
24983db86aabSstevel rmclomv_do_cmd(DP_GET_FRU_STATUS,
24993db86aabSstevel DP_GET_FRU_STATUS_R, sizeof (rmc_fru_r),
25003db86aabSstevel (intptr_t)&rmc_fru, (intptr_t)&rmc_fru_r) != 0) {
25013db86aabSstevel env_hpu.sensor_status = ENVMON_INACCESSIBLE;
25023db86aabSstevel } else {
25033db86aabSstevel /*
25043db86aabSstevel * copy results into buffer for user
25053db86aabSstevel */
25063db86aabSstevel if (rmc_fru_r.fru_status[0].presence == 0) {
25073db86aabSstevel env_hpu.sensor_status =
25083db86aabSstevel ENVMON_NOT_PRESENT;
25093db86aabSstevel env_hpu.fru_status =
25103db86aabSstevel ENVMON_FRU_NOT_PRESENT;
25113db86aabSstevel } else if (rmc_fru_r.fru_status[0].sensor_status
25123db86aabSstevel != DP_SENSOR_DATA_AVAILABLE) {
25133db86aabSstevel env_hpu.sensor_status =
25143db86aabSstevel ENVMON_INACCESSIBLE;
25153db86aabSstevel } else {
25163db86aabSstevel uint8_t status =
25173db86aabSstevel rmc_fru_r.fru_status[0].status;
25183db86aabSstevel if (status == DP_FRU_STATUS_UNKNOWN) {
25193db86aabSstevel env_hpu.sensor_status =
25203db86aabSstevel ENVMON_INACCESSIBLE;
25213db86aabSstevel } else if (status != DP_FRU_STATUS_OK) {
25223db86aabSstevel env_hpu.fru_status =
25233db86aabSstevel ENVMON_FRU_FAULT;
25243db86aabSstevel }
25253db86aabSstevel }
25263db86aabSstevel }
25273db86aabSstevel }
25283db86aabSstevel
25293db86aabSstevel /*
25303db86aabSstevel * If rmclomv_rmc_error is set there is no way
25313db86aabSstevel * that we read information from RSC. Just copy
25323db86aabSstevel * out an inaccessible environmental.
25333db86aabSstevel */
25343db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) {
25353db86aabSstevel env_hpu.sensor_status = ENVMON_INACCESSIBLE;
25363db86aabSstevel env_hpu.fru_status = ENVMON_INACCESSIBLE;
25373db86aabSstevel }
25383db86aabSstevel
25393db86aabSstevel if (ddi_copyout((caddr_t)&env_hpu, (caddr_t)arg,
25403db86aabSstevel sizeof (envmon_hpu_t), mode) != 0)
25413db86aabSstevel return (EFAULT);
25423db86aabSstevel break;
25433db86aabSstevel
25443db86aabSstevel case ENVMONIOCGETLED:
25453db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_ledinfo,
25463db86aabSstevel sizeof (envmon_led_info_t), mode) != 0)
25473db86aabSstevel return (EFAULT);
25483db86aabSstevel
25493db86aabSstevel /* see if we've got LED handles cached */
25503db86aabSstevel LOCK_CACHE
25513db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
25523db86aabSstevel
25533db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
25543db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
25553db86aabSstevel RMCLOMV_LED_IND)) == NULL)) {
25563db86aabSstevel env_ledinfo.next_id.name[0] = '\0';
25573db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
25583db86aabSstevel } else if (env_ledinfo.id.name[0] == '\0') {
25593db86aabSstevel /* request for first handle */
25603db86aabSstevel if (section->num_entries == 0)
25613db86aabSstevel env_ledinfo.next_id.name[0] = '\0';
25623db86aabSstevel else
25633db86aabSstevel env_ledinfo.next_id =
25643db86aabSstevel section->entry[0].handle_name;
25653db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
25663db86aabSstevel } else {
25673db86aabSstevel /* ensure name is properly terminated */
25683db86aabSstevel env_ledinfo.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
25693db86aabSstevel if (get_sensor_by_name(section, env_ledinfo.id.name,
25703db86aabSstevel &index) != 0) {
25713db86aabSstevel env_ledinfo.next_id.name[0] = '\0';
25723db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
25733db86aabSstevel } else if (index + 1 < section->num_entries)
25743db86aabSstevel env_ledinfo.next_id =
25753db86aabSstevel section->entry[index + 1].handle_name;
25763db86aabSstevel else
25773db86aabSstevel env_ledinfo.next_id.name[0] = '\0';
25783db86aabSstevel }
25793db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
25803db86aabSstevel /*
25813db86aabSstevel * user correctly identified a LED, note its
25823db86aabSstevel * handle value and request the LED status
25833db86aabSstevel */
25843db86aabSstevel rmc_led.handle = section->entry[index].handle;
25853db86aabSstevel }
25863db86aabSstevel RELEASE_CACHE
25873db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error ||
25883db86aabSstevel rmclomv_do_cmd(DP_GET_LED_STATE, DP_GET_LED_STATE_R,
25893db86aabSstevel sizeof (rmc_led_r), (intptr_t)&rmc_led,
25903db86aabSstevel (intptr_t)&rmc_led_r) != 0)) {
25913db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
25923db86aabSstevel }
25933db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) &&
25943db86aabSstevel (rmc_led_r.led_state[0].sensor_status ==
25953db86aabSstevel DP_SENSOR_NOT_PRESENT)) {
25963db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
25973db86aabSstevel }
25983db86aabSstevel if ((env_ledinfo.sensor_status = sensor_status) ==
25993db86aabSstevel ENVMON_SENSOR_OK) {
26003db86aabSstevel /*
26013db86aabSstevel * copy results into buffer for user
26023db86aabSstevel * start with some defaults then override
26033db86aabSstevel */
26043db86aabSstevel env_ledinfo.sensor_status = ENVMON_SENSOR_OK;
26053db86aabSstevel env_ledinfo.led_state = ENVMON_LED_OFF;
26063db86aabSstevel env_ledinfo.led_color = ENVMON_LED_CLR_NONE;
26073db86aabSstevel
26083db86aabSstevel if (rmc_led_r.led_state[0].sensor_status !=
26093db86aabSstevel DP_SENSOR_DATA_AVAILABLE)
26103db86aabSstevel env_ledinfo.sensor_status = ENVMON_INACCESSIBLE;
26113db86aabSstevel else {
26123db86aabSstevel dp_led_state_t ledState;
26133db86aabSstevel ledState = rmc_led_r.led_state[0];
26143db86aabSstevel env_ledinfo.led_color = (int8_t)ledState.colour;
26153db86aabSstevel
26163db86aabSstevel switch (ledState.state) {
26173db86aabSstevel case (rsci8)DP_LED_OFF:
26183db86aabSstevel break;
26193db86aabSstevel case (rsci8)DP_LED_ON:
26203db86aabSstevel env_ledinfo.led_state = ENVMON_LED_ON;
26213db86aabSstevel break;
26223db86aabSstevel case (rsci8)DP_LED_BLINKING:
26233db86aabSstevel env_ledinfo.led_state =
26243db86aabSstevel ENVMON_LED_BLINKING;
26253db86aabSstevel break;
26263db86aabSstevel case (rsci8)DP_LED_FLASHING:
26273db86aabSstevel env_ledinfo.led_state =
26283db86aabSstevel ENVMON_LED_FLASHING;
26293db86aabSstevel break;
26303db86aabSstevel default:
26313db86aabSstevel break;
26323db86aabSstevel }
26333db86aabSstevel }
26343db86aabSstevel }
26353db86aabSstevel
26363db86aabSstevel /*
26373db86aabSstevel * If rmclomv_rmc_error is set there is no way
26383db86aabSstevel * that we read information from RSC. Just copy
26393db86aabSstevel * out an inaccessible environmental.
26403db86aabSstevel */
26413db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) {
26423db86aabSstevel env_ledinfo.sensor_status = ENVMON_INACCESSIBLE;
26433db86aabSstevel env_ledinfo.led_state = ENVMON_INACCESSIBLE;
26443db86aabSstevel }
26453db86aabSstevel
26463db86aabSstevel if (ddi_copyout((caddr_t)&env_ledinfo, (caddr_t)arg,
26473db86aabSstevel sizeof (envmon_led_info_t), mode) != 0)
26483db86aabSstevel return (EFAULT);
26493db86aabSstevel break;
26503db86aabSstevel
26513db86aabSstevel case ENVMONIOCSETLED:
26523db86aabSstevel if ((mode & FWRITE) == 0)
26533db86aabSstevel return (EACCES);
26543db86aabSstevel if (drv_priv(cred_p) != 0)
26553db86aabSstevel return (EPERM);
26563db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_ledctl,
26573db86aabSstevel sizeof (envmon_led_ctl_t), mode) != 0)
26583db86aabSstevel return (EFAULT);
26593db86aabSstevel if (env_ledctl.led_state < RMCLOMV_MIN_LED_STATE ||
26603db86aabSstevel env_ledctl.led_state > RMCLOMV_MAX_LED_STATE)
26613db86aabSstevel return (EINVAL);
26623db86aabSstevel /*
26633db86aabSstevel * Ensure name is properly terminated.
26643db86aabSstevel */
26653db86aabSstevel env_ledctl.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
26663db86aabSstevel
26673db86aabSstevel /* see if we've got LED handles cached */
26683db86aabSstevel LOCK_CACHE
26693db86aabSstevel
26703db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
26713db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
26723db86aabSstevel RMCLOMV_LED_IND)) == NULL) ||
26733db86aabSstevel (get_sensor_by_name(section, env_ledctl.id.name,
26743db86aabSstevel &index) != 0)) {
26753db86aabSstevel RELEASE_CACHE
26763db86aabSstevel return (EINVAL); /* no such LED */
26773db86aabSstevel }
26783db86aabSstevel /*
26793db86aabSstevel * user correctly identified a LED, note its handle value
26803db86aabSstevel */
26813db86aabSstevel rmc_setled.handle = section->entry[index].handle;
26823db86aabSstevel RELEASE_CACHE
26833db86aabSstevel switch (env_ledctl.led_state) {
26843db86aabSstevel case ENVMON_LED_ON:
26853db86aabSstevel rmc_setled.state = DP_LED_ON;
26863db86aabSstevel break;
26873db86aabSstevel case ENVMON_LED_BLINKING:
26883db86aabSstevel rmc_setled.state = DP_LED_BLINKING;
26893db86aabSstevel break;
26903db86aabSstevel case ENVMON_LED_FLASHING:
26913db86aabSstevel rmc_setled.state = DP_LED_FLASHING;
26923db86aabSstevel break;
26933db86aabSstevel default:
26943db86aabSstevel rmc_setled.state = DP_LED_OFF;
26953db86aabSstevel break;
26963db86aabSstevel }
26973db86aabSstevel retval = rmclomv_do_cmd(DP_SET_LED_STATE, DP_SET_LED_STATE_R,
26983db86aabSstevel sizeof (rmc_setled_r), (intptr_t)&rmc_setled,
26993db86aabSstevel (intptr_t)&rmc_setled_r);
27003db86aabSstevel
27013db86aabSstevel if (retval != 0) {
27023db86aabSstevel break;
27033db86aabSstevel }
27043db86aabSstevel
27053db86aabSstevel if (rmc_setled_r.status != 0) {
27063db86aabSstevel cmn_err(CE_WARN, "ENVMONIOCSETLED: \"%s\" status: 0x%x",
27073db86aabSstevel env_ledctl.id.name, rmc_setled_r.status);
27083db86aabSstevel return (EIO);
27093db86aabSstevel }
27103db86aabSstevel break;
27113db86aabSstevel
27123db86aabSstevel case ENVMONIOCGETKEYSW:
27133db86aabSstevel {
27143db86aabSstevel enum rmc_keyswitch_pos rmc_pos = real_key_position;
27153db86aabSstevel envmon_keysw_pos_t envmon_pos;
27163db86aabSstevel
27173db86aabSstevel /*
27183db86aabSstevel * Yes, I know this is ugly, but the V210 has no keyswitch,
27193db86aabSstevel * even though the ALOM returns a value for it
27203db86aabSstevel */
27213db86aabSstevel if (strcmp(platform, "SUNW,Sun-Fire-V210") == 0) {
27223db86aabSstevel return (ENOTSUP);
27233db86aabSstevel }
27243db86aabSstevel
27253db86aabSstevel switch (rmc_pos) {
27263db86aabSstevel
27273db86aabSstevel case RMC_KEYSWITCH_POS_NORMAL:
27283db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_NORMAL;
27293db86aabSstevel break;
27303db86aabSstevel case RMC_KEYSWITCH_POS_DIAG:
27313db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_DIAG;
27323db86aabSstevel break;
27333db86aabSstevel case RMC_KEYSWITCH_POS_LOCKED:
27343db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_LOCKED;
27353db86aabSstevel break;
27363db86aabSstevel case RMC_KEYSWITCH_POS_OFF:
27373db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_OFF;
27383db86aabSstevel break;
27393db86aabSstevel default:
27403db86aabSstevel envmon_pos = ENVMON_KEYSW_POS_UNKNOWN;
27413db86aabSstevel break;
27423db86aabSstevel }
27433db86aabSstevel
27443db86aabSstevel if (ddi_copyout((caddr_t)&envmon_pos, (caddr_t)arg,
27453db86aabSstevel sizeof (envmon_pos), mode) != 0)
27463db86aabSstevel return (EFAULT);
27473db86aabSstevel break;
27483db86aabSstevel }
27493db86aabSstevel
27503db86aabSstevel case ENVMONIOCGETALARM:
27513db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_alarminfo,
27523db86aabSstevel sizeof (envmon_alarm_info_t), mode) != 0)
27533db86aabSstevel return (EFAULT);
27543db86aabSstevel
27553db86aabSstevel /* see if we've got ALARM handles cached */
27563db86aabSstevel LOCK_CACHE
27573db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
27583db86aabSstevel
27593db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
27603db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
27613db86aabSstevel RMCLOMV_ALARM_IND)) == NULL)) {
27623db86aabSstevel env_alarminfo.next_id.name[0] = '\0';
27633db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
27643db86aabSstevel } else if (env_alarminfo.id.name[0] == '\0') {
27653db86aabSstevel /* request for first handle */
27663db86aabSstevel if (section->num_entries == 0)
27673db86aabSstevel env_alarminfo.next_id.name[0] = '\0';
27683db86aabSstevel else
27693db86aabSstevel env_alarminfo.next_id =
27703db86aabSstevel section->entry[0].handle_name;
27713db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
27723db86aabSstevel } else {
27733db86aabSstevel /* ensure name is properly terminated */
27743db86aabSstevel env_alarminfo.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
27753db86aabSstevel if (get_sensor_by_name(section, env_alarminfo.id.name,
27763db86aabSstevel &index) != 0) {
27773db86aabSstevel env_alarminfo.next_id.name[0] = '\0';
27783db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
27793db86aabSstevel } else if (index + 1 < section->num_entries)
27803db86aabSstevel env_alarminfo.next_id =
27813db86aabSstevel section->entry[index + 1].handle_name;
27823db86aabSstevel else
27833db86aabSstevel env_alarminfo.next_id.name[0] = '\0';
27843db86aabSstevel }
27853db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
27863db86aabSstevel /*
27873db86aabSstevel * user correctly identified a ALARM, note its
27883db86aabSstevel * handle value and request the ALARM status
27893db86aabSstevel */
27903db86aabSstevel rmc_alarm.handle = section->entry[index].handle;
27913db86aabSstevel }
27923db86aabSstevel RELEASE_CACHE
27933db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) &&
27943db86aabSstevel (rmclomv_rmc_error ||
27953db86aabSstevel rmclomv_do_cmd(DP_GET_ALARM_STATE, DP_GET_ALARM_STATE_R,
27963db86aabSstevel sizeof (rmc_alarm_r), (intptr_t)&rmc_alarm,
27973db86aabSstevel (intptr_t)&rmc_alarm_r) != 0)) {
27983db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
27993db86aabSstevel }
28003db86aabSstevel if ((env_alarminfo.sensor_status = sensor_status) ==
28013db86aabSstevel ENVMON_SENSOR_OK) {
28023db86aabSstevel /*
28033db86aabSstevel * copy results into buffer for user
28043db86aabSstevel * start with some defaults then override
28053db86aabSstevel */
28063db86aabSstevel env_alarminfo.sensor_status = ENVMON_SENSOR_OK;
28073db86aabSstevel env_alarminfo.alarm_state = ENVMON_ALARM_OFF;
28083db86aabSstevel
28093db86aabSstevel if (rmc_alarm_r.alarm_state[0].sensor_status !=
28103db86aabSstevel DP_SENSOR_DATA_AVAILABLE)
28113db86aabSstevel env_alarminfo.sensor_status =
28123db86aabSstevel ENVMON_INACCESSIBLE;
28133db86aabSstevel else {
28143db86aabSstevel dp_alarm_state_t alarmState;
28153db86aabSstevel alarmState = rmc_alarm_r.alarm_state[0];
28163db86aabSstevel
28173db86aabSstevel switch (alarmState.state) {
28183db86aabSstevel case DP_ALARM_OFF:
28193db86aabSstevel break;
28203db86aabSstevel case DP_ALARM_ON:
28213db86aabSstevel env_alarminfo.alarm_state =
28223db86aabSstevel ENVMON_ALARM_ON;
28233db86aabSstevel break;
28243db86aabSstevel default:
28253db86aabSstevel break;
28263db86aabSstevel }
28273db86aabSstevel }
28283db86aabSstevel }
28293db86aabSstevel
28303db86aabSstevel /*
28313db86aabSstevel * If rmclomv_rmc_error is set there is no way
28323db86aabSstevel * that we read information from RSC. Just copy
28333db86aabSstevel * out an inaccessible environmental.
28343db86aabSstevel */
28353db86aabSstevel if (rmclomv_rmc_error != RMCLOMV_RMCERROR_NONE) {
28363db86aabSstevel env_alarminfo.sensor_status = ENVMON_INACCESSIBLE;
28373db86aabSstevel env_alarminfo.alarm_state = ENVMON_INACCESSIBLE;
28383db86aabSstevel }
28393db86aabSstevel
28403db86aabSstevel if (ddi_copyout((caddr_t)&env_alarminfo, (caddr_t)arg,
28413db86aabSstevel sizeof (envmon_alarm_info_t), mode) != 0)
28423db86aabSstevel return (EFAULT);
28433db86aabSstevel break;
28443db86aabSstevel
28453db86aabSstevel case ENVMONIOCSETALARM:
28463db86aabSstevel if ((mode & FWRITE) == 0)
28473db86aabSstevel return (EACCES);
28483db86aabSstevel if (drv_priv(cred_p) != 0)
28493db86aabSstevel return (EPERM);
28503db86aabSstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&env_alarmctl,
28513db86aabSstevel sizeof (envmon_alarm_ctl_t), mode) != 0)
28523db86aabSstevel return (EFAULT);
28533db86aabSstevel if (env_alarmctl.alarm_state < RMCLOMV_MIN_ALARM_STATE ||
28543db86aabSstevel env_alarmctl.alarm_state > RMCLOMV_MAX_ALARM_STATE)
28553db86aabSstevel return (EINVAL);
28563db86aabSstevel /*
28573db86aabSstevel * Ensure name is properly terminated.
28583db86aabSstevel */
28593db86aabSstevel env_alarmctl.id.name[ENVMON_MAXNAMELEN - 1] = '\0';
28603db86aabSstevel
28613db86aabSstevel /* see if we've got ALARM handles cached */
28623db86aabSstevel LOCK_CACHE
28633db86aabSstevel
28643db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
28653db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
28663db86aabSstevel RMCLOMV_ALARM_IND)) == NULL) ||
28673db86aabSstevel (get_sensor_by_name(section, env_alarmctl.id.name,
28683db86aabSstevel &index) != 0)) {
28693db86aabSstevel RELEASE_CACHE
28703db86aabSstevel return (EINVAL); /* no such ALARM */
28713db86aabSstevel }
28723db86aabSstevel /*
28733db86aabSstevel * user correctly identified a ALARM, note its handle value
28743db86aabSstevel */
28753db86aabSstevel rmc_setalarm.handle = section->entry[index].handle;
28763db86aabSstevel RELEASE_CACHE
28773db86aabSstevel rmc_setalarm.state = (rsci8)env_alarmctl.alarm_state;
28783db86aabSstevel retval = rmclomv_do_cmd(DP_SET_ALARM_STATE,
28793db86aabSstevel DP_SET_ALARM_STATE_R,
28803db86aabSstevel sizeof (rmc_setalarm_r),
28813db86aabSstevel (intptr_t)&rmc_setalarm,
28823db86aabSstevel (intptr_t)&rmc_setalarm_r);
28833db86aabSstevel
28843db86aabSstevel if (retval != 0) {
28853db86aabSstevel break;
28863db86aabSstevel }
28873db86aabSstevel
28883db86aabSstevel if (rmc_setalarm_r.status != 0) {
28893db86aabSstevel cmn_err(CE_WARN, "ENVMONIOCSETALARM: \"%s\" status: "
28903db86aabSstevel "0x%x", env_alarmctl.id.name,
28913db86aabSstevel rmc_setalarm_r.status);
28923db86aabSstevel return (EIO);
28933db86aabSstevel }
28943db86aabSstevel break;
28953db86aabSstevel
28963db86aabSstevel case ENVMONIOCCHASSISSERIALNUM:
28973db86aabSstevel retval = rmclomv_do_cmd(DP_GET_SDP_VERSION,
28983db86aabSstevel DP_GET_SDP_VERSION_R, sizeof (rmc_sdpver_r),
28993db86aabSstevel NULL, (intptr_t)&rmc_sdpver_r);
29003db86aabSstevel
29013db86aabSstevel if (retval != 0) {
29023db86aabSstevel cmn_err(CE_WARN, "DP_GET_SDP_VERSION failed, ret=%d\n",
29033db86aabSstevel retval);
29043db86aabSstevel break;
29053db86aabSstevel } else if (rmc_sdpver_r.version < SDP_RESPONDS_TO_ALL_CMDS) {
29063db86aabSstevel retval = ENOTSUP;
29073db86aabSstevel break;
29083db86aabSstevel }
29093db86aabSstevel retval = rmclomv_do_cmd(DP_GET_CHASSIS_SERIALNUM,
29103db86aabSstevel DP_GET_CHASSIS_SERIALNUM_R, sizeof (rmc_serialnum_r),
29113db86aabSstevel NULL, (intptr_t)&rmc_serialnum_r);
29123db86aabSstevel
29133db86aabSstevel if (retval != 0) {
29143db86aabSstevel break;
29153db86aabSstevel }
29163db86aabSstevel bcopy(rmc_serialnum_r.chassis_serial_number,
29173db86aabSstevel chassis.serial_number,
29183db86aabSstevel sizeof (rmc_serialnum_r.chassis_serial_number));
29193db86aabSstevel
29203db86aabSstevel if (ddi_copyout((caddr_t)&chassis, (caddr_t)arg,
29213db86aabSstevel sizeof (chassis), mode) != 0) {
29223db86aabSstevel return (EFAULT);
29233db86aabSstevel }
29243db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
29253db86aabSstevel break;
29263db86aabSstevel
29273db86aabSstevel default:
29283db86aabSstevel retval = ENOTSUP;
29293db86aabSstevel break;
29303db86aabSstevel }
29313db86aabSstevel
29323db86aabSstevel return (retval);
29333db86aabSstevel }
29343db86aabSstevel
29353db86aabSstevel /* ARGSUSED */
29363db86aabSstevel static void
rmclomv_checkrmc(caddr_t arg)29373db86aabSstevel rmclomv_checkrmc(caddr_t arg)
29383db86aabSstevel {
29393db86aabSstevel callb_cpr_t cprinfo;
29403db86aabSstevel int err;
29413db86aabSstevel int retries;
29423db86aabSstevel int state;
29433db86aabSstevel dp_get_sysinfo_r_t sysinfo;
29443db86aabSstevel
29453db86aabSstevel CALLB_CPR_INIT(&cprinfo, &rmclomv_checkrmc_lock, callb_generic_cpr,
29463db86aabSstevel "rmclomv_checkrmc");
29473db86aabSstevel
29483db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock);
29493db86aabSstevel for (;;) {
29503db86aabSstevel /*
29513db86aabSstevel * Initial entry to this for loop is made with
29523db86aabSstevel * rmclomv_checkrmc_sig set to RMCLOMV_PROCESS_NOW. So the
29533db86aabSstevel * following while loop drops through the first time. A
29543db86aabSstevel * timeout call is made just before polling the RMC. Its
29553db86aabSstevel * interrupt routine sustains this loop by injecting additional
29563db86aabSstevel * state changes and cv events.
29573db86aabSstevel */
29583db86aabSstevel /*
29593db86aabSstevel * Wait for someone to tell me to continue.
29603db86aabSstevel */
29613db86aabSstevel while (rmclomv_checkrmc_sig == RMCLOMV_CHECKRMC_WAIT) {
29623db86aabSstevel CALLB_CPR_SAFE_BEGIN(&cprinfo);
29633db86aabSstevel cv_wait(&rmclomv_checkrmc_sig_cv,
29643db86aabSstevel &rmclomv_checkrmc_lock);
29653db86aabSstevel CALLB_CPR_SAFE_END(&cprinfo, &rmclomv_checkrmc_lock);
29663db86aabSstevel }
29673db86aabSstevel
29683db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock);
29693db86aabSstevel /*
29703db86aabSstevel * mustn't hold same lock as timeout called with
29713db86aabSstevel * when cancelling timer
29723db86aabSstevel */
29733db86aabSstevel if (timer_id != 0) {
29743db86aabSstevel (void) untimeout(timer_id);
29753db86aabSstevel timer_id = 0;
29763db86aabSstevel }
29773db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock);
29783db86aabSstevel
29793db86aabSstevel /* RMCLOMV_CHECKRMC_EXITNOW implies signal by _detach(). */
29803db86aabSstevel if (rmclomv_checkrmc_sig == RMCLOMV_CHECKRMC_EXITNOW) {
29813db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_WAIT;
29823db86aabSstevel
29833db86aabSstevel /* rmclomv_checkrmc_lock is held at this point! */
29843db86aabSstevel CALLB_CPR_EXIT(&cprinfo);
29853db86aabSstevel
29863db86aabSstevel thread_exit();
29873db86aabSstevel /* NOTREACHED */
29883db86aabSstevel }
29893db86aabSstevel
29903db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_WAIT;
29913db86aabSstevel
29923db86aabSstevel /*
29933db86aabSstevel * If the RMC is not responding, rmclomv_do_cmd() takes a
29943db86aabSstevel * long time and eventually times out. We conclude that the
29953db86aabSstevel * RMC is broken if it doesn't respond to a number of polls
29963db86aabSstevel * made 60 secs apart. So that the rmclomv_do_cmd() time-out
29973db86aabSstevel * period isn't added to our 60 second timer, make the
29983db86aabSstevel * timeout() call before calling rmclomv_do_cmd().
29993db86aabSstevel */
30003db86aabSstevel if (timer_id == 0) {
30013db86aabSstevel timer_id = timeout(rmclomv_checkrmc_wakeup, NULL,
30023db86aabSstevel 60 * drv_usectohz(1000000));
30033db86aabSstevel }
30043db86aabSstevel
30053db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock);
30063db86aabSstevel
30073db86aabSstevel err = rmclomv_do_cmd(DP_GET_SYSINFO, DP_GET_SYSINFO_R,
30083db86aabSstevel sizeof (sysinfo), NULL, (intptr_t)&sysinfo);
30093db86aabSstevel if (err == 0) {
30103db86aabSstevel mutex_enter(&rmclomv_state_lock);
30113db86aabSstevel state = rmclomv_rmc_state;
30123db86aabSstevel /* successful poll, reset fail count */
30133db86aabSstevel rmclomv_rmcfailcount = 0;
30143db86aabSstevel mutex_exit(&rmclomv_state_lock);
30153db86aabSstevel
30163db86aabSstevel if (state != RMCLOMV_RMCSTATE_OK) {
30173db86aabSstevel rmclomv_refresh_wakeup();
30183db86aabSstevel }
30193db86aabSstevel }
30203db86aabSstevel if ((err != 0) &&
30213db86aabSstevel (rmclomv_rmc_error != RMCLOMV_RMCSTATE_DOWNLOAD)) {
30223db86aabSstevel /*
30233db86aabSstevel * Failed response or no response from RMC.
30243db86aabSstevel * Count the failure.
30253db86aabSstevel * If threshold exceeded, send a DR event.
30263db86aabSstevel */
30273db86aabSstevel mutex_enter(&rmclomv_state_lock);
30283db86aabSstevel retries = rmclomv_rmcfailcount;
30293db86aabSstevel state = rmclomv_rmc_state;
30303db86aabSstevel if (retries == RMCLOMV_RMCFAILTHRESHOLD)
30313db86aabSstevel rmclomv_rmc_state = RMCLOMV_RMCSTATE_FAILED;
30323db86aabSstevel if (rmclomv_rmcfailcount <= RMCLOMV_RMCFAILTHRESHOLD)
30333db86aabSstevel rmclomv_rmcfailcount++;
30343db86aabSstevel mutex_exit(&rmclomv_state_lock);
30353db86aabSstevel
30363db86aabSstevel if (retries == RMCLOMV_RMCFAILTHRESHOLD) {
30373db86aabSstevel cmn_err(CE_WARN, "SC %s responding",
30383db86aabSstevel state == RMCLOMV_RMCSTATE_OK ?
30393db86aabSstevel "has stopped" : "is not");
30403db86aabSstevel refresh_name_cache(B_TRUE);
30413db86aabSstevel rmclomv_dr_data_handler(str_sc, SE_NO_HINT);
30423db86aabSstevel }
30433db86aabSstevel }
30443db86aabSstevel
30453db86aabSstevel /*
30463db86aabSstevel * Re-enter the lock to prepare for another iteration.
30473db86aabSstevel * We must have the lock here to protect rmclomv_checkrmc_sig.
30483db86aabSstevel */
30493db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock);
30503db86aabSstevel }
30513db86aabSstevel }
30523db86aabSstevel
30533db86aabSstevel static void
rmclomv_checkrmc_start(void)30543db86aabSstevel rmclomv_checkrmc_start(void)
30553db86aabSstevel {
30563db86aabSstevel kthread_t *tp;
30573db86aabSstevel
30583db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock);
30593db86aabSstevel
30603db86aabSstevel if (rmclomv_checkrmc_tid == 0) {
30613db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_PROCESSNOW;
30623db86aabSstevel
30633db86aabSstevel tp = thread_create(NULL, 0, rmclomv_checkrmc, NULL, 0,
30643db86aabSstevel &p0, TS_RUN, maxclsyspri);
30653db86aabSstevel rmclomv_checkrmc_tid = tp->t_did;
30663db86aabSstevel }
30673db86aabSstevel
30683db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock);
30693db86aabSstevel }
30703db86aabSstevel
30713db86aabSstevel static void
rmclomv_checkrmc_destroy(void)30723db86aabSstevel rmclomv_checkrmc_destroy(void)
30733db86aabSstevel {
30743db86aabSstevel kt_did_t tid;
30753db86aabSstevel
30763db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock);
30773db86aabSstevel tid = rmclomv_checkrmc_tid;
30783db86aabSstevel if (tid != 0) {
30793db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_EXITNOW;
30803db86aabSstevel cv_signal(&rmclomv_checkrmc_sig_cv);
30813db86aabSstevel rmclomv_checkrmc_tid = 0;
30823db86aabSstevel }
30833db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock);
30843db86aabSstevel
30853db86aabSstevel /*
30863db86aabSstevel * Wait for rmclomv_checkrmc() to finish
30873db86aabSstevel */
30883db86aabSstevel if (tid != 0)
30893db86aabSstevel thread_join(tid);
30903db86aabSstevel }
30913db86aabSstevel
30923db86aabSstevel /*ARGSUSED*/
30933db86aabSstevel static void
rmclomv_checkrmc_wakeup(void * arg)30943db86aabSstevel rmclomv_checkrmc_wakeup(void *arg)
30953db86aabSstevel {
30963db86aabSstevel mutex_enter(&rmclomv_checkrmc_lock);
30973db86aabSstevel
30983db86aabSstevel if (rmclomv_checkrmc_sig != RMCLOMV_CHECKRMC_EXITNOW)
30993db86aabSstevel rmclomv_checkrmc_sig = RMCLOMV_CHECKRMC_PROCESSNOW;
31003db86aabSstevel cv_signal(&rmclomv_checkrmc_sig_cv);
31013db86aabSstevel
31023db86aabSstevel mutex_exit(&rmclomv_checkrmc_lock);
31033db86aabSstevel }
31043db86aabSstevel
31053db86aabSstevel /* ARGSUSED */
31063db86aabSstevel static void
rmclomv_refresh(caddr_t arg)31073db86aabSstevel rmclomv_refresh(caddr_t arg)
31083db86aabSstevel {
31093db86aabSstevel void (*plat_nodename_set_fun)(void);
31103db86aabSstevel sig_state_t *current_sgn_p;
31113db86aabSstevel callb_cpr_t cprinfo;
31123db86aabSstevel int state;
3113f594b28aSjfrank int tmp_checkrmc_sig;
31143db86aabSstevel
31153db86aabSstevel CALLB_CPR_INIT(&cprinfo, &rmclomv_refresh_lock, callb_generic_cpr,
31163db86aabSstevel "rmclomv_refresh");
31173db86aabSstevel
3118f594b28aSjfrank /*
3119f594b28aSjfrank * Wait until the rmclomv_checkrmc() thread has had a chance to
3120f594b28aSjfrank * run its main loop. This is done so that rmclomv_refresh will
3121f594b28aSjfrank * only run its main loop once at start of day; otherwise, it may
3122f594b28aSjfrank * run twice and generate warning messages when redundantly populating
3123f594b28aSjfrank * its internal cache.
3124f594b28aSjfrank */
3125f594b28aSjfrank do {
3126f594b28aSjfrank delay(drv_usectohz(DELAY_TIME));
3127f594b28aSjfrank mutex_enter(&rmclomv_checkrmc_lock);
3128f594b28aSjfrank tmp_checkrmc_sig = rmclomv_checkrmc_sig;
3129f594b28aSjfrank mutex_exit(&rmclomv_checkrmc_lock);
3130f594b28aSjfrank } while (tmp_checkrmc_sig != RMCLOMV_CHECKRMC_WAIT);
3131f594b28aSjfrank
31323db86aabSstevel mutex_enter(&rmclomv_refresh_lock);
31333db86aabSstevel for (;;) {
31343db86aabSstevel
31353db86aabSstevel /*
31363db86aabSstevel * Wait for someone to tell me to continue.
31373db86aabSstevel */
31383db86aabSstevel while (rmclomv_refresh_sig == RMCLOMV_REFRESH_WAIT) {
31393db86aabSstevel CALLB_CPR_SAFE_BEGIN(&cprinfo);
31403db86aabSstevel cv_wait(&rmclomv_refresh_sig_cv, &rmclomv_refresh_lock);
31413db86aabSstevel CALLB_CPR_SAFE_END(&cprinfo, &rmclomv_refresh_lock);
31423db86aabSstevel }
31433db86aabSstevel
31443db86aabSstevel /* RMCLOMV_REFRESH_EXITNOW implies signal by _detach(). */
31453db86aabSstevel if (rmclomv_refresh_sig == RMCLOMV_REFRESH_EXITNOW) {
31463db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_WAIT;
31473db86aabSstevel
31483db86aabSstevel /* rmclomv_refresh_lock is held at this point! */
31493db86aabSstevel CALLB_CPR_EXIT(&cprinfo);
31503db86aabSstevel
31513db86aabSstevel thread_exit();
31523db86aabSstevel /* NOTREACHED */
31533db86aabSstevel }
31543db86aabSstevel
31553db86aabSstevel ASSERT(rmclomv_refresh_sig == RMCLOMV_REFRESH_PROCESSNOW);
31563db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_WAIT;
31573db86aabSstevel
31583db86aabSstevel mutex_exit(&rmclomv_refresh_lock);
31593db86aabSstevel
31603db86aabSstevel refresh_name_cache(B_FALSE);
31613db86aabSstevel
31623db86aabSstevel /*
31633db86aabSstevel * We're not going to access rmclomv_sysinfo_data here,
31643db86aabSstevel * so there's no point in locking it before reading
31653db86aabSstevel * rmclomv_sysinfo_valid. Also this avoids holding two
31663db86aabSstevel * locks at once and the concommitant worry about deadlocks.
31673db86aabSstevel */
31683db86aabSstevel if (rmclomv_sysinfo_valid) {
31693db86aabSstevel /*
31703db86aabSstevel * We've just successfully read the RMC sysinfo
31713db86aabSstevel * so the RMC must be operational. Update its
31723db86aabSstevel * state and if it was previously not OK, refresh
31733db86aabSstevel * nodename, CPU signatures and watchdog settings.
31743db86aabSstevel */
31753db86aabSstevel mutex_enter(&rmclomv_state_lock);
31763db86aabSstevel rmclomv_rmcfailcount = 0;
31773db86aabSstevel state = rmclomv_rmc_state;
31783db86aabSstevel rmclomv_rmc_state = RMCLOMV_RMCSTATE_OK;
31793db86aabSstevel mutex_exit(&rmclomv_state_lock);
31803db86aabSstevel
31813db86aabSstevel if (state != RMCLOMV_RMCSTATE_OK) {
31823db86aabSstevel rmclomv_dr_data_handler(str_sc, SE_NO_HINT);
31833db86aabSstevel if (state == RMCLOMV_RMCSTATE_FAILED) {
31843db86aabSstevel cmn_err(CE_NOTE, "SC recovered");
31853db86aabSstevel }
31863db86aabSstevel }
31873db86aabSstevel
31883db86aabSstevel if (utsname.nodename[0] != 0) {
31893db86aabSstevel plat_nodename_set_fun =
31903db86aabSstevel (void (*)(void))modgetsymvalue(
31913db86aabSstevel "plat_nodename_set", 0);
31923db86aabSstevel if (plat_nodename_set_fun != NULL)
31933db86aabSstevel plat_nodename_set_fun();
31943db86aabSstevel }
31953db86aabSstevel
31963db86aabSstevel current_sgn_p = (sig_state_t *)modgetsymvalue(
31973db86aabSstevel "current_sgn", 0);
31983db86aabSstevel
3199f594b28aSjfrank /*
3200f594b28aSjfrank * Delay before calling CPU_SIGNATURE, to allow
3201f594b28aSjfrank * any pending asynchronous communications (i.e.
3202f594b28aSjfrank * plat_timesync()) to complete. This helps to
3203f594b28aSjfrank * prevent the situation where the message associated
3204f594b28aSjfrank * with the CPU_SIGNATURE state cannot be sent to the
3205f594b28aSjfrank * system controller.
3206f594b28aSjfrank */
32073db86aabSstevel if ((current_sgn_p != NULL) &&
32083db86aabSstevel (current_sgn_p->state_t.sig != 0)) {
3209f594b28aSjfrank delay(drv_usectohz(CPU_SIGNATURE_DELAY_TIME));
32103db86aabSstevel CPU_SIGNATURE(current_sgn_p->state_t.sig,
32113db86aabSstevel current_sgn_p->state_t.state,
32123db86aabSstevel current_sgn_p->state_t.sub_state, -1);
32133db86aabSstevel
32143db86aabSstevel if (!(boothowto & RB_DEBUG)) {
3215f594b28aSjfrank /*
3216f594b28aSjfrank * Delay before calling
3217f594b28aSjfrank * send_watchdog_msg, to allow
3218f594b28aSjfrank * CPU_SIGNATURE() time to
3219f594b28aSjfrank * complete; this increases the
3220f594b28aSjfrank * chances of successfully sending
3221f594b28aSjfrank * the watchdog message to the
3222f594b28aSjfrank * system controller.
3223f594b28aSjfrank */
3224f594b28aSjfrank delay(drv_usectohz(
3225f594b28aSjfrank CPU_SIGNATURE_DELAY_TIME));
32263db86aabSstevel send_watchdog_msg(last_watchdog_msg);
32273db86aabSstevel }
32283db86aabSstevel }
32293db86aabSstevel }
32303db86aabSstevel
32313db86aabSstevel /*
32323db86aabSstevel * update keyswitch value in case it changed while the
32333db86aabSstevel * RMC was out of action
32343db86aabSstevel */
32353db86aabSstevel LOCK_CACHE
32363db86aabSstevel if (rmclomv_sysinfo_valid) {
32373db86aabSstevel real_key_position = rmclomv_sysinfo_data.keyswitch;
32383db86aabSstevel if ((real_key_position != RMC_KEYSWITCH_POS_UNKNOWN) &&
32393db86aabSstevel (real_key_position <= RMC_KEYSWITCH_POS_OFF)) {
32403db86aabSstevel key_position = real_key_position;
32413db86aabSstevel } else {
32423db86aabSstevel /* treat unknown key position as locked */
32433db86aabSstevel key_position = RMC_KEYSWITCH_POS_LOCKED;
32443db86aabSstevel }
32453db86aabSstevel } else {
32463db86aabSstevel /* treat unreadable key position as locked */
32473db86aabSstevel key_position = RMC_KEYSWITCH_POS_LOCKED;
32483db86aabSstevel real_key_position = RMC_KEYSWITCH_POS_UNKNOWN;
32493db86aabSstevel }
32503db86aabSstevel RELEASE_CACHE
32513db86aabSstevel
32523db86aabSstevel /*
32533db86aabSstevel * Re-enter the lock to prepare for another iteration.
32543db86aabSstevel * We must have the lock here to protect rmclomv_refresh_sig.
32553db86aabSstevel */
32563db86aabSstevel mutex_enter(&rmclomv_refresh_lock);
32573db86aabSstevel }
32583db86aabSstevel }
32593db86aabSstevel
32603db86aabSstevel static void
rmclomv_refresh_start(void)32613db86aabSstevel rmclomv_refresh_start(void)
32623db86aabSstevel {
32633db86aabSstevel kthread_t *tp;
32643db86aabSstevel
32653db86aabSstevel mutex_enter(&rmclomv_refresh_lock);
32663db86aabSstevel
32673db86aabSstevel if (rmclomv_refresh_tid == 0) {
32683db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_PROCESSNOW;
32693db86aabSstevel
32703db86aabSstevel tp = thread_create(NULL, 0, rmclomv_refresh, NULL, 0,
32713db86aabSstevel &p0, TS_RUN, maxclsyspri);
32723db86aabSstevel rmclomv_refresh_tid = tp->t_did;
32733db86aabSstevel }
32743db86aabSstevel
32753db86aabSstevel mutex_exit(&rmclomv_refresh_lock);
32763db86aabSstevel }
32773db86aabSstevel
32783db86aabSstevel static void
rmclomv_refresh_destroy(void)32793db86aabSstevel rmclomv_refresh_destroy(void)
32803db86aabSstevel {
32813db86aabSstevel kt_did_t tid;
32823db86aabSstevel
32833db86aabSstevel mutex_enter(&rmclomv_refresh_lock);
32843db86aabSstevel tid = rmclomv_refresh_tid;
32853db86aabSstevel if (tid != 0) {
32863db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_EXITNOW;
32873db86aabSstevel cv_signal(&rmclomv_refresh_sig_cv);
32883db86aabSstevel rmclomv_refresh_tid = 0;
32893db86aabSstevel }
32903db86aabSstevel mutex_exit(&rmclomv_refresh_lock);
32913db86aabSstevel
32923db86aabSstevel /*
32933db86aabSstevel * Wait for rmclomv_refresh() to finish
32943db86aabSstevel */
32953db86aabSstevel if (tid != 0)
32963db86aabSstevel thread_join(tid);
32973db86aabSstevel }
32983db86aabSstevel
32993db86aabSstevel static void
rmclomv_refresh_wakeup(void)33003db86aabSstevel rmclomv_refresh_wakeup(void)
33013db86aabSstevel {
33023db86aabSstevel mutex_enter(&rmclomv_refresh_lock);
33033db86aabSstevel
33043db86aabSstevel if (rmclomv_refresh_sig != RMCLOMV_REFRESH_EXITNOW)
33053db86aabSstevel rmclomv_refresh_sig = RMCLOMV_REFRESH_PROCESSNOW;
33063db86aabSstevel cv_signal(&rmclomv_refresh_sig_cv);
33073db86aabSstevel
33083db86aabSstevel mutex_exit(&rmclomv_refresh_lock);
33093db86aabSstevel }
33103db86aabSstevel
33113db86aabSstevel static void
send_watchdog_msg(int msg)33123db86aabSstevel send_watchdog_msg(int msg)
33133db86aabSstevel {
33143db86aabSstevel rmc_comm_msg_t request;
33153db86aabSstevel dp_set_host_watchdog_t watchdog_msg;
33163db86aabSstevel
33173db86aabSstevel if (rmclomv_watchdog_mode)
33183db86aabSstevel return;
33193db86aabSstevel
33203db86aabSstevel watchdog_msg.enable = msg;
33213db86aabSstevel request.msg_type = DP_SET_HOST_WATCHDOG;
33223db86aabSstevel request.msg_len = sizeof (watchdog_msg);
33233db86aabSstevel request.msg_buf = (caddr_t)&watchdog_msg;
33243db86aabSstevel (void) rmc_comm_request_nowait(&request, (msg == 1) ?
33253db86aabSstevel RMC_COMM_DREQ_URGENT : 0);
33263db86aabSstevel }
33273db86aabSstevel
33283db86aabSstevel /*ARGSUSED*/
33293db86aabSstevel static uint_t
rmc_set_watchdog_timer(uint_t timeoutval)33303db86aabSstevel rmc_set_watchdog_timer(uint_t timeoutval)
33313db86aabSstevel {
33323db86aabSstevel ASSERT(MUTEX_HELD(&tod_lock));
33333db86aabSstevel
33343db86aabSstevel if ((watchdog_enable == 0) || (watchdog_available == 0)) {
33353db86aabSstevel return (0);
33363db86aabSstevel }
33373db86aabSstevel
33383db86aabSstevel /*
33393db86aabSstevel * If boothowto has RB_DEBUG set we never want to set the watchdog
33403db86aabSstevel * support on.
33413db86aabSstevel */
33423db86aabSstevel if (boothowto & RB_DEBUG) {
33433db86aabSstevel return (0);
33443db86aabSstevel }
33453db86aabSstevel
33463db86aabSstevel /*
33473db86aabSstevel * When the watchdog is shut off last_watchdog_msg goes from a
33483db86aabSstevel * 0 to a 1. So we must test to see that last_watchdog_msg is
33493db86aabSstevel * set to 1 indicating that watchdog was shut off and
33503db86aabSstevel * After which we set last_watchdog_msg back to 0 so that we do not
33513db86aabSstevel * run this code
33523db86aabSstevel * again.
33533db86aabSstevel */
33543db86aabSstevel if (last_watchdog_msg == 1) {
33553db86aabSstevel send_watchdog_msg(0);
33563db86aabSstevel last_watchdog_msg = 0;
33573db86aabSstevel }
33583db86aabSstevel
33593db86aabSstevel pmugpio_watchdog_pat();
33603db86aabSstevel
33613db86aabSstevel watchdog_activated = 1;
33623db86aabSstevel
33633db86aabSstevel return (1);
33643db86aabSstevel }
33653db86aabSstevel
33663db86aabSstevel static uint_t
rmc_clear_watchdog_timer(void)33673db86aabSstevel rmc_clear_watchdog_timer(void)
33683db86aabSstevel {
33693db86aabSstevel ASSERT(MUTEX_HELD(&tod_lock));
33703db86aabSstevel if ((watchdog_activated == 0) || (boothowto & RB_DEBUG))
33713db86aabSstevel return (0);
33723db86aabSstevel
33733db86aabSstevel send_watchdog_msg(1);
33743db86aabSstevel last_watchdog_msg = 1;
33753db86aabSstevel watchdog_activated = 0;
33763db86aabSstevel
33773db86aabSstevel return (0);
33783db86aabSstevel }
33793db86aabSstevel
33803db86aabSstevel static void
plat_timesync(void * arg)33813db86aabSstevel plat_timesync(void *arg)
33823db86aabSstevel {
33833db86aabSstevel timestruc_t now;
33843db86aabSstevel todinfo_t tod;
33853db86aabSstevel rmc_comm_msg_t request;
33863db86aabSstevel dp_set_date_time_t set_time_msg;
33873db86aabSstevel int retval;
33883db86aabSstevel timestruc_t ts;
33893db86aabSstevel dp_get_date_time_r_t *date_and_time_info;
33903db86aabSstevel int buffer[DATE_TIME_MSG_SIZE];
33913db86aabSstevel
33923db86aabSstevel /* Is the system coming up? */
33933db86aabSstevel if (arg != NULL) {
33943db86aabSstevel /* Request the time from the RMC clock. */
33953db86aabSstevel retval = rmclomv_do_cmd(DP_GET_DATE_TIME, DP_GET_DATE_TIME_R,
33963db86aabSstevel DATE_TIME_MSG_SIZE, NULL, (intptr_t)&buffer);
33973db86aabSstevel
33983db86aabSstevel /*
33993db86aabSstevel * If we were able to get the time lets set the local clock.
34003db86aabSstevel * The time returned from RMC is in Unix time format.
34013db86aabSstevel *
34023db86aabSstevel * If we couldn't get the time we'll accept the drift so as not
34033db86aabSstevel * to cause congestion on the I2C bus or cause boot
34043db86aabSstevel * performance regressions.
34053db86aabSstevel */
34063db86aabSstevel if (retval == RCNOERR) {
34073db86aabSstevel date_and_time_info = (dp_get_date_time_r_t *)buffer;
34083db86aabSstevel ts.tv_sec = date_and_time_info->current_datetime;
34093db86aabSstevel ts.tv_nsec = 0;
34103db86aabSstevel mutex_enter(&tod_lock);
34113db86aabSstevel tod_set(ts);
34123db86aabSstevel set_hrestime(&ts);
34133db86aabSstevel mutex_exit(&tod_lock);
34143db86aabSstevel }
34153db86aabSstevel }
34163db86aabSstevel
34173db86aabSstevel gethrestime(&now);
34183db86aabSstevel mutex_enter(&tod_lock);
34193db86aabSstevel tod = utc_to_tod(now.tv_sec);
34203db86aabSstevel mutex_exit(&tod_lock);
34213db86aabSstevel
34223db86aabSstevel set_time_msg.year = tod.tod_year;
34233db86aabSstevel set_time_msg.month = tod.tod_month - 1;
34243db86aabSstevel set_time_msg.day = tod.tod_day;
34253db86aabSstevel set_time_msg.hour = tod.tod_hour;
34263db86aabSstevel set_time_msg.minute = tod.tod_min;
34273db86aabSstevel set_time_msg.second = tod.tod_sec;
34283db86aabSstevel
34293db86aabSstevel request.msg_type = DP_SET_DATE_TIME;
34303db86aabSstevel request.msg_len = sizeof (set_time_msg);
34313db86aabSstevel request.msg_buf = (caddr_t)&set_time_msg;
34323db86aabSstevel
34333db86aabSstevel (void) rmc_comm_request_nowait(&request, 0);
34343db86aabSstevel
3435da14cebeSEric Cheng mutex_enter(×ync_lock);
3436da14cebeSEric Cheng if (timesync_interval != 0)
3437da14cebeSEric Cheng timesync_tid = timeout(plat_timesync, NULL, timesync_interval);
3438da14cebeSEric Cheng mutex_exit(×ync_lock);
34393db86aabSstevel }
34403db86aabSstevel
34413db86aabSstevel /*
34423db86aabSstevel * Interfaces to get/set alarm relays from outside
34433db86aabSstevel */
34443db86aabSstevel int
rmclomv_alarm_get(int alarm_type,int * alarm_state)34453db86aabSstevel rmclomv_alarm_get(int alarm_type, int *alarm_state)
34463db86aabSstevel {
34473db86aabSstevel rmclomv_cache_section_t *section;
34483db86aabSstevel int index;
34493db86aabSstevel uint16_t sensor_status;
34503db86aabSstevel dp_get_alarm_state_t u_rmc_alarm;
34513db86aabSstevel dp_get_alarm_state_r_t u_rmc_alarm_r;
34523db86aabSstevel
34533db86aabSstevel /* see if we've got ALARM handles cached */
34543db86aabSstevel LOCK_CACHE
34553db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
34563db86aabSstevel
34573db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
34583db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
34593db86aabSstevel RMCLOMV_ALARM_IND)) == NULL)) {
34603db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
34613db86aabSstevel }
34623db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
34633db86aabSstevel /*
34643db86aabSstevel * user correctly identified a ALARM, note its
34653db86aabSstevel * handle value and request the ALARM status
34663db86aabSstevel */
34673db86aabSstevel index = alarm_type;
34683db86aabSstevel if (index >= section->num_entries)
34693db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
34703db86aabSstevel else
34713db86aabSstevel u_rmc_alarm.handle = section->entry[index].handle;
34723db86aabSstevel }
34733db86aabSstevel RELEASE_CACHE
34743db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) && (rmclomv_rmc_error ||
34753db86aabSstevel rmclomv_do_cmd(DP_GET_ALARM_STATE, DP_GET_ALARM_STATE_R,
34763db86aabSstevel sizeof (u_rmc_alarm_r), (intptr_t)&u_rmc_alarm,
34773db86aabSstevel (intptr_t)&u_rmc_alarm_r) != 0)) {
34783db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
34793db86aabSstevel }
34803db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
34813db86aabSstevel /*
34823db86aabSstevel * copy results into buffer for user
34833db86aabSstevel * start with some defaults then override
34843db86aabSstevel */
34853db86aabSstevel *alarm_state = 0;
34863db86aabSstevel
34873db86aabSstevel if (u_rmc_alarm_r.alarm_state[0].sensor_status !=
34883db86aabSstevel DP_SENSOR_DATA_AVAILABLE)
34893db86aabSstevel return (ENXIO);
34903db86aabSstevel else {
34913db86aabSstevel dp_alarm_state_t alarmState;
34923db86aabSstevel alarmState = u_rmc_alarm_r.alarm_state[0];
34933db86aabSstevel
34943db86aabSstevel switch (alarmState.state) {
34953db86aabSstevel case DP_ALARM_OFF:
34963db86aabSstevel break;
34973db86aabSstevel case DP_ALARM_ON:
34983db86aabSstevel *alarm_state = 1;
34993db86aabSstevel break;
35003db86aabSstevel default:
35013db86aabSstevel break;
35023db86aabSstevel }
35033db86aabSstevel }
35043db86aabSstevel } else
35053db86aabSstevel return (ENXIO);
35063db86aabSstevel
35073db86aabSstevel return (0);
35083db86aabSstevel }
35093db86aabSstevel
35103db86aabSstevel int
rmclomv_alarm_set(int alarm_type,int new_state)35113db86aabSstevel rmclomv_alarm_set(int alarm_type, int new_state)
35123db86aabSstevel {
35133db86aabSstevel rmclomv_cache_section_t *section;
35143db86aabSstevel int index;
35153db86aabSstevel uint16_t sensor_status;
35163db86aabSstevel dp_set_alarm_state_t u_rmc_setalarm;
35173db86aabSstevel dp_set_alarm_state_r_t u_rmc_setalarm_r;
35183db86aabSstevel
35193db86aabSstevel /* see if we've got ALARM handles cached */
35203db86aabSstevel LOCK_CACHE
35213db86aabSstevel sensor_status = ENVMON_SENSOR_OK;
35223db86aabSstevel
35233db86aabSstevel if ((rmclomv_cache_valid == B_FALSE) ||
35243db86aabSstevel ((section = rmclomv_find_section(rmclomv_cache,
35253db86aabSstevel RMCLOMV_ALARM_IND)) == NULL)) {
35263db86aabSstevel sensor_status = ENVMON_NOT_PRESENT;
35273db86aabSstevel }
35283db86aabSstevel if (sensor_status == ENVMON_SENSOR_OK) {
35293db86aabSstevel /*
35303db86aabSstevel * user correctly identified a ALARM, note its
35313db86aabSstevel * handle value and request the ALARM status
35323db86aabSstevel */
35333db86aabSstevel index = alarm_type;
35343db86aabSstevel if (index >= section->num_entries)
35353db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
35363db86aabSstevel else {
35373db86aabSstevel u_rmc_setalarm.handle = section->entry[index].handle;
35383db86aabSstevel u_rmc_setalarm.state = new_state;
35393db86aabSstevel }
35403db86aabSstevel }
35413db86aabSstevel RELEASE_CACHE
35423db86aabSstevel if ((sensor_status == ENVMON_SENSOR_OK) &&
35433db86aabSstevel (rmclomv_rmc_error ||
35443db86aabSstevel rmclomv_do_cmd(DP_SET_ALARM_STATE, DP_SET_ALARM_STATE_R,
35453db86aabSstevel sizeof (u_rmc_setalarm_r), (intptr_t)&u_rmc_setalarm,
35463db86aabSstevel (intptr_t)&u_rmc_setalarm_r) != 0)) {
35473db86aabSstevel sensor_status = ENVMON_INACCESSIBLE;
35483db86aabSstevel }
35493db86aabSstevel
35503db86aabSstevel if (u_rmc_setalarm_r.status != DP_SET_ALARM_OK) {
35513db86aabSstevel return (EIO);
35523db86aabSstevel }
35533db86aabSstevel
35543db86aabSstevel if (sensor_status != ENVMON_SENSOR_OK) {
35553db86aabSstevel return (ENXIO);
35563db86aabSstevel }
35573db86aabSstevel
35583db86aabSstevel return (0);
35593db86aabSstevel }
3560