3db86aab554edbb4244c8d1a1c90f152eee768afstevel * CDDL HEADER START
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The contents of this file are subject to the terms of the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Common Development and Distribution License (the "License").
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * You may not use this file except in compliance with the License.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * See the License for the specific language governing permissions
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and limitations under the License.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * When distributing Covered Code, include this CDDL HEADER in each
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If applicable, add the following below this CDDL HEADER, with the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * fields enclosed by brackets "[]" replaced with your own identifying
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * information: Portions Copyright [yyyy] [name of copyright owner]
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * CDDL HEADER END
193974072f41a843678abf5f61979c748687e66bSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Use is subject to license terms.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * ENVCTRLTWO_ Environment Monitoring driver for i2c on Javelin
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/stat.h> /* ddi_create_minor_node S_IFCHR */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/envctrl_gen.h> /* user level generic visible definitions */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/envctrl_ue250.h> /* user level UE250 visible definitions */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <javelin/sys/envctrltwo.h> /* definitions for Javelin */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* driver entry point fn definitions */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* configuration entry point fn definitions */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_attach(dev_info_t *, ddi_attach_cmd_t);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_detach(dev_info_t *, ddi_detach_cmd_t);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* Driver private routines */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_get_cpu_temp(struct envctrlunit *, int);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_fan_fail_service(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_PS_intr_service(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_tempr_poll(void *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_pshotplug_poll(void *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_led_blink(void *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_reset_dflop(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_enable_devintrs(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_intr_latch_clr(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_get_fpm_status(struct envctrlunit *, uint8_t *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_set_fsp(struct envctrlunit *, uint8_t *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_isother_fault_led(struct envctrlunit *,
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_check_sys_temperatures(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_check_disk_kstats(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_update_disk_kstats(struct envctrlunit *,
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_read_chip(struct envctrlunit *, int, int, int,
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_write_chip(struct envctrlunit *, int, int, int,
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_check_tempr_levels(struct envctrlunit *,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int, uint8_t *, int);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_update_fanspeed(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* Kstat routines */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_fanstat_kstat_update(kstat_t *, int);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void envctrl_init_encl_kstats(struct envctrlunit *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelextern void power_down(const char *);
3db86aab554edbb4244c8d1a1c90f152eee768afstevelextern void (*abort_seq_handler)();
3db86aab554edbb4244c8d1a1c90f152eee768afstevelextern void pci_thermal_rem_intr(dev_info_t *, uint_t);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* Local Variables */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* Indicates whether or not the overtemp thread has been started */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int envctrl_handler = 1; /* 1 is the default */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Temperature levels :
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * green = OK - no action needed
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * yellow = warning - display warning message and poll faster
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * red = critical - shutdown system
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define DPRINTF1 if (envctrl_debug_flags && (envctrl_debug_flags & 0x1)) printf
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define DPRINTF2 if (envctrl_debug_flags && (envctrl_debug_flags & 0x2)) printf
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define DPRINTF3 if (envctrl_debug_flags && (envctrl_debug_flags & 0x4)) printf
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int sensor_types[] = { ENVCTRL_UE250_CPU0_SENSOR,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Declare ops vectors for auto configuration.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* devo_refcnt */
193974072f41a843678abf5f61979c748687e66bSherry Moore "I2C ENVCTRLTWO_driver",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((error = mod_install(&envctrlmodlinkage)) == 0) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (!(unitp = ddi_get_soft_state(envctrlsoft_statep, instance)))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Set up timer values */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel overtemp_timeout_hz = drv_usectohz(ENVCTRL_UE250_OVERTEMP_TIMEOUT_USEC);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel blink_timeout_hz = drv_usectohz(ENVCTRL_UE250_BLINK_TIMEOUT_USEC);
193974072f41a843678abf5f61979c748687e66bSherry Moore drv_usectohz(ENVCTRL_UE250_BLINK_TIMEOUT_USEC * 2);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * On a cooling failure, either a fan failure or temperature
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * exceeding a WARNING level, the temperature poll thread
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * will run every 6 seconds.
193974072f41a843678abf5f61979c748687e66bSherry Moore drv_usectohz(ENVCTRL_UE250_OVERTEMP_TIMEOUT_USEC / 6);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_soft_state_zalloc(envctrlsoft_statep, instance) != 0) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: failed to zalloc softstate\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp = ddi_get_soft_state(envctrlsoft_statep, instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_regs_map_setup(dip, 0, (caddr_t *)&unitp->bus_ctl_regs, 0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: failed to map in bus_control regs\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If the PCI nexus has added a thermal interrupt, we first need
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * to remove that interrupt handler.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * WARNING: Removing another driver's interrupt handler is not
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * allowed. The pci_thermal_rem_intr() call below is needed to retain
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the legacy behavior on Javelin systems.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* add interrupts */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: ddi_get_iblock_cookie FAILED \n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_add_intr(dip, 0, &unitp->ic_trap_cookie, NULL, envctrl_bus_isr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_add_intr(dip, 1, &unitp->ic_trap_cookie, NULL, envctrl_dev_isr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_create_priv_minor_node(dip, name, S_IFCHR, instance,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DDI_PSEUDO, 0, PRIV_SYS_CONFIG, PRIV_SYS_CONFIG, 0666) ==
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Javelin will not have a workstation configuration so activity
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * LED will always blink.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((unitp->cpu_pr_location[ENVCTRL_CPU0] == B_FALSE) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (unitp->cpu_pr_location[ENVCTRL_CPU1] == B_FALSE))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Only one CPU in the system */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "cpu-temp-factors", &creg_prop, &len) != DDI_PROP_SUCCESS) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Unable to read cpu-temp-factors property",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (i = 0; i < len; i++) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "cpu-fan-speeds", &creg_prop, &len) != DDI_PROP_SUCCESS) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Unable to read cpu-fan-speeds property",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel tblsz = (sizeof (_cpu_fan_speeds) / sizeof (uchar_t));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (i = 0; i < len; i++) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _cpu_fan_speeds[0] = _cpu_fan_speeds[1] = _cpu_fan_speeds[2];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "thermisters", &creg_prop, &len) != DDI_PROP_SUCCESS) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Unable to read thermisters property",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel j = 0; k = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (i = 0; i < JAV_MAX_TEMP_SENSORS; i++) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Address */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel t_addr[k] = creg_prop[j] << 24 | creg_prop[j+1] << 16 |
3db86aab554edbb4244c8d1a1c90f152eee768afstevel t_port[k] = creg_prop[j] << 24 | creg_prop[j+1] << 16 |
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Warning threshold */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Shutdown threshold */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Numerator of scale factor */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel t_scale_num[k] = creg_prop[j] << 24 | creg_prop[j+1] << 16 |
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Denominator of scale factor */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel t_scale_den[k] = creg_prop[j] << 24 | creg_prop[j+1] << 16 |
3db86aab554edbb4244c8d1a1c90f152eee768afstevel bcopy((caddr_t)&creg_prop[j], unitp->temp_kstats[k].label,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Don't increment the kstat line count */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* initialize the envctrl bus controller */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DPRINTF1("envctrl_attach(): Completed initialization of PCF8584");
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Fans could be blasting, turn them down.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8591, EHC_DEV2, 0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8591 (SETFAN) failed\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we need to init the fan kstats before the tempr_poll
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * interpose envctrl's abort sequence handler
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_remove_intr(dip, (uint_t)1, unitp->ic_trap_cookie);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_remove_intr(dip, (uint_t)0, unitp->ic_trap_cookie);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: attach failed\n", ddi_get_name(dip), instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp = ddi_get_soft_state(envctrlsoft_statep, instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_remove_intr(dip, (uint_t)0, unitp->ic_trap_cookie);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_remove_intr(dip, (uint_t)1, unitp->ic_trap_cookie);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (!(unitp = ddi_get_soft_state(envctrlsoft_statep, instance)))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: envctrltwo already suspended\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* ARGSUSED1 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_open(dev_t *dev, int flag, int otyp, cred_t *cred_p)
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_soft_state(envctrlsoft_statep, instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*ARGSUSED1*/
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_soft_state(envctrlsoft_statep, instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * standard put procedure for envctrl
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p,
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_soft_state(envctrlsoft_statep, instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Set mode */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_copyin((caddr_t)arg, (caddr_t)&wdval, sizeof (uint8_t),
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Fans could be blasting, turn them down.
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Write to PCF8591 "
193974072f41a843678abf5f61979c748687e66bSherry Moore "(SETMODE) failed\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This delay allows the fans to time to
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * change speed
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * For diags, cancel the curent temp poll
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and reset it for a new one.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Get the user buffer address */
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read from PCF8591 (IOC_GETTEMP) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* NOTE: need to sanity check values coming from userland */
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Write to PCF8591 "
193974072f41a843678abf5f61979c748687e66bSherry Moore "(IOC_SETFAN) failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read of PCF8591 (IOC_GETFAN) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Due to hardware limitation, the actual fan speed
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * is always a little less than what it was set to by
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * software. Hence, we scale up the read fan speed value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * to more closely match the set value.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((tfanspeed = ((int)a_fanspeed.val * JAV_FAN_SPEED_SF_NUM) /
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If a user is in normal mode and they try
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * to set anything other than a disk fault or
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * a gen fault it is an invalid operation.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * in diag mode we allow everything to be
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * twiddled.
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read of PCF8574A (IOC_SETFSP) failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read of PCF8574A (IOC_GETFSP) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, temp.type, temp.chip_num,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Write to chip (IOC_SETRAW) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, temp.type, temp.chip_num,
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read of chip (IOC_GETRAW) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct envctrlunit *unitp = (struct envctrlunit *)(void *)arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct envctrlunit *unitp = (struct envctrlunit *)(void *)arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * First check to see if it is an interrupt for us by
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * looking at the "ganged" interrupt and vector
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * according to the major type
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * 0x70 is the addr of the ganged interrupt controller.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Address map for the port byte read is as follows
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * -------------------------
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * | | | | | | | | |
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * -------------------------
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P7 P6 P5 P4 P3 P2 P1 P0
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P0 = Spare
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P1 = Thermal Interrupt
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P2 = Disk Interrupt
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P3 = Interrupt clock enable
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P4 = Fan Fail Interrupt
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P5 = Front Panel Interrupt
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P6 = Power Supply Interrupt
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * P7 = Enable Interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This extra read is needed since the first read is discarded
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and the second read seems to return 0xFF.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * if the i2c bus is hung it is imperative that this
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * be cleared on an interrupt or else it will
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * hang the system with continuous interrupts
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read of PCF8574A (INT) failed\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DPRINTF1("Interrupt routine called, interrupt = %X\n", recv_data);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Clear the interrupt latches
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for a fan fail
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Clear the interrupt latches
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) envctrl_get_fpm_status(unitp, (uint8_t *)NULL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The interrupt routine got called but the interrupt chip
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * shows no interrupt present. If this happens more than 256
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * times in a row, there is probably some hardware problem so
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * send a warning message to the console.
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Received 256 spurious interrupts\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_read_chip(struct envctrlunit *unitp, int type, int chip_num, int port,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If more than one read is requested, set auto-increment bit
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_read_pcf8574((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_read_pcf8591((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If the bus hangs, attempt a recovery
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_write_chip(struct envctrlunit *unitp, int type, int chip_num, int port,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Incase some applications mistakenly include the chips base addr
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If more than one write is requested, set auto-increment bit
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_write_pcf8574((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_write_pcf8591((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If the bus hangs, attempt a recovery
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_get_cpu_temp(struct envctrlunit *unitp, int cpunum)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This routine takes in the number of the port that
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we want to read in the 8591. This should be the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * location of the CPU thermistor for one of the 2
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * cpu's. It will return a normalized value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * to the caller.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, EHC_DEV7, cpunum,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct envctrlunit *unitp = (struct envctrlunit *)arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) power_down("Fatal System Environmental Control Error");
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Clear the interrupt latches
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * if we are in diag mode and the temp poll thread goes off,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * this means that the system is too heavily loaded and the 60 second
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * window to execute the test is failing.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "Tempr poll went off while in DIAG MODE\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DPRINTF1("envctrl_tempr_poll(): Checking system temps\n");
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Failure detected during temperature poll",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Turn of the power fault LED if ps_ok is asserted */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* now have this thread sleep for a while */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((unitp->fan_failed == B_TRUE) || (unitp->tempr_warning == B_TRUE)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * A thermal warning or fan failure condition exists.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Temperature poll thread will run every 10 seconds.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * No thermal warning or fan failure condition exists.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This thread is set to run every 60 seconds.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct envctrlunit *unitp = (struct envctrlunit *)arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* now have this thread sleep for a while */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->blink_timeout_id = (timeout(envctrl_led_blink,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Now we need to "or" in fault bits of the FSP
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * module for the mass storage fault led.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and set it.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * A static global variable, power_flt_led_lit, is used to keep
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * track of periods when the software has lit the power fault LED.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Whenever the power fault LED is lit and this variable is not set,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * then the power fault LED has been lit by hardware. In this case
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * mask out the power fault LED in the byte. This is a fix for
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * bug 4144872.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Turn off power fault bit in the FSP byte.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Failed to blink activity LED",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* now have this thread sleep for a while */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->blink_timeout_id = (timeout(envctrl_led_blink,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* now have this thread sleep for a while */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->blink_timeout_id = (timeout(envctrl_led_blink,
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_check_sys_temperatures(struct envctrlunit *unitp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, EHC_DEV2,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Temperature read failed (PDB)",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel warning_level = envctrl_check_tempr_levels(unitp, EHC_DEV2,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, EHC_DEV7,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Temperature read failed (MBD)",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel warning_level = envctrl_check_tempr_levels(unitp, EHC_DEV7,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((warning_level == yellow) && (unitp->shutdown == B_FALSE))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else if ((level == green) && (unitp->tempr_warning == B_TRUE)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Current tempr. poll shows all levels normal.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If the previous poll showed warning levels, we need
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * to clear that status
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "TEMPERATURE NORMAL: all sensors back to normal readings");
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read of Front Status Panel LEDs failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((unitp->tempr_warning == B_TRUE) || (unitp->shutdown == B_TRUE))
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Setting of Front Status Panel LEDs failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Have this thread run again in about 10 seconds
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_check_tempr_levels(struct envctrlunit *unitp, int chip_num,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (i = 0; i < 4; i++) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (i == 1) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else if (i == 2)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((chip_num == EHC_DEV7) && ((i == ENVCTRL_UE250_CPU0_PORT) ||
3db86aab554edbb4244c8d1a1c90f152eee768afstevel while ((((t_addr[j] & 0xF) != chip_num) || (t_port[j] != i)) &&
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((chip_num == EHC_DEV7) && ((i == ENVCTRL_UE250_CPU0_PORT) ||
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Javelin hardware will not control fan speeds based on
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * cpu temperature values because the voltages corresponding
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * to the cpu temperatures are based on an inverted scale
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * compared to the ambient temperatures and thus can be
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * fed to the same fan control circuit. As a result, it
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * has been decided that software will control fan speed
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * if cpu temperatures rise.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((chip_num == EHC_DEV7) && ((i == ENVCTRL_UE250_CPU0_PORT) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (unitp->current_mode == ENVCTRL_NORMAL_MODE)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore _cpu_fan_speeds[data[ENVCTRL_UE250_CPU1_PORT]])
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Write to PCF8591 (SETFAN) failed\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Fan speed read failed (PDB)",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DPRINTF1("device %X, temp = %d %d loc = %s\n", chip_num,
193974072f41a843678abf5f61979c748687e66bSherry Moore temp_degree_c, data[i], unitp->temp_kstats[j].label);
193974072f41a843678abf5f61979c748687e66bSherry Moore "TEMPERATURE WARNING: %d degrees "
193974072f41a843678abf5f61979c748687e66bSherry Moore "celsius at location %s",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (count != 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "TEMPERATURE CRITICAL: %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "degrees celsius at location %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore "System shutdown in "
193974072f41a843678abf5f61979c748687e66bSherry Moore "10 seconds ...");
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, EHC_DEV2,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel tval = ((int)buf[ENVCTRL_PORT1] * JAV_FAN_SPEED_SF_NUM) /
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* called with mutex held */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The fan fail interrupt is read from address 0x70
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * on the envctrl bus.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Clear the interrupt latches to handle spurious interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This extra read is needed since the first read is discarded
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and the second read seems to return 0xFF.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "%s%d: Read of PCF8574A (INTFAN) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* If the fan fail interrupt is now absent */
193974072f41a843678abf5f61979c748687e66bSherry Moore "Fan failure has been cleared\n");
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Clear general fault LED if no other faults
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read of Front Status "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Panel LEDs failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (!(envctrl_isother_fault_led(unitp, fpmstat, 0))) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "Setting of Front Status "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Panel LEDs failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This should be set after envctrl_isother_fault_led()
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * is called
193974072f41a843678abf5f61979c748687e66bSherry Moore "Fan failure has been detected");
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Set general fault LED
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Read of Front Status "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Panel LEDs failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore "Setting of Front Status Panel LEDs failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * A fan failure condition exists.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Temperature poll thread should run every 10 seconds.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for power supply insertion and failure.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This is a bit tricky, because a power supply insertion will
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * cause the ps_ok line to go active as well as PS present in the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * new supply. If we detect an insertion clear
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * interrupts, disable interrupts, wait for a couple of seconds
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * come back and see if the PSOK bit is set, PS_PRESENT is set
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and the share fail interrupts are gone. If not this is a
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * real load share fail event.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Called with mutex held
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * setup a timeout thread to poll the ps after a
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * couple of seconds. This allows for the PS to settle
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and doesn't report false errors on a hotplug
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->pshotplug_id = (timeout(envctrl_pshotplug_poll,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Clear the interrupt latches
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* called with mutex held */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8574A (DFLOP_INIT0) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8574A (DFLOP_INIT1) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* called with mutex held */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8574A (INTR_INIT0) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8574A (INTR_INIT1) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8574A (INTR_LATCH0) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8574A (INTR_LATCH1) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/* Called with unitp mutex held */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV1,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read of PCF8574 (PS) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (i = 0, j = 0; i < ENVCTRL_UE250_MAXPS; i++) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 0 = PS0 Present
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 1 = PS1 Present
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 2 = SPARE
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 3 = SPARE
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 4 = PS0 OK
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 5 = PS1 OK
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 6 = SPARE
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 7 = SPARE
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port 0 = PS Present
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Port is pulled LOW "0" to indicate
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (i) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* update unit kstat array */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (pspr[i] == 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "Power Supply %d inserted\n", i);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "Power Supply %d NOT okay\n", i);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (psok[i] == 0)
193974072f41a843678abf5f61979c748687e66bSherry Moore "Power Supply %d okay\n", i);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "PS %d Shouln't interrupt\n", i);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "PS %d Shouln't interrupt\n", i);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "PS %d Shouln't interrupt\n", i);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "PS %d Shouln't interrupt\n", i);
193974072f41a843678abf5f61979c748687e66bSherry Moore "Power Supply %d removed\n", i);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read of Front Status Panel LEDs failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: Setting of Front Status Panel LEDs failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * consider key switch position when handling an abort sequence
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Find the instance of the device available on this host.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Note that there may be only one, but the instance may
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * not be zero.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (i = 0; i < MAX_DEVS; i++) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s%d: ignoring debug enter sequence\n",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * get the front Panel module LED and keyswitch status.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * this part is addressed at 0x7C on the i2c bus.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * called with mutex held
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_get_fpm_status(struct envctrlunit *unitp, uint8_t *val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read from PCF8574A (FSP) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /* Update kstats */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_set_fsp(struct envctrlunit *unitp, uint8_t *val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel value = ENVCTRL_UE250_FSP_OFF; /* init all values to off */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * strip off bits that are R/O
3db86aab554edbb4244c8d1a1c90f152eee768afstevel value = (~(ENVCTRL_UE250_FSP_KEYMASK | ENVCTRL_UE250_FSP_POMASK) &
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8574A (FSP) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Sometimes the i2c hardware status is not
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * completely dependable as far as reporting
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * a condition where the set does not take
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * place. So we read back the set value to
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * confirm what we set.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_get_fpm_status(unitp, &confirm_val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "%s%d: Read of PCF8574A (FSP) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Set was confirmed.
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_get_dskled(struct envctrlunit *unitp, struct envctrl_chip *chip)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV7,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read of PCF8574A (DISKFL) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_set_dskled(struct envctrlunit *unitp, struct envctrl_chip *chip)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * We need to check the type of disk led being set. If it
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * is a 4 slot backplane then the upper 4 bits (7, 6, 5, 4) are
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read of PCF8574A (FSP) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write to PCF8574A (FSP) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV5,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read of PCF8574A (DISKFL) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel envctrl_update_disk_kstats(unitp, val, ~(chip->val));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we take the ones compliment of the val passed in
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * because the hardware thinks that a "low" or "0"
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * is the way to indicate a fault. of course software
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * knows that a 1 is a TRUE state or fault. ;-)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV7,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Write PCF8574A (DISKFL) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Sometimes the i2c hardware status is not
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * completely dependable as far as reporting
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * a condition where the set does not take
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * place. So we read back the set value to
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * confirm what we set.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Set was confirmed.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * After setting the fan speed, we read back the fan speed to confirm
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * that the new value is within an acceptable range, else we retry.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * We do not confirm the fan speed if the set value is below the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * hardware determined speed (based on system temeratures).
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_set_fanspeed(struct envctrlunit *unitp, struct envctrl_chip *fanspeed)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((unitp->enclksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: encl raw kstat_create failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->enclksp->ks_update = envctrl_encl_kstat_update;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((unitp->fanksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) == NULL) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->fanksp->ks_update = envctrl_fanstat_kstat_update;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((unitp->psksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: ps name kstat_create failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((unitp->tempksp = kstat_create(ENVCTRL_MODULE_NAME,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->instance, ENVCTRL_KSTAT_TEMPERATURE, "misc", KSTAT_TYPE_RAW,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: temp name kstat_create failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->tempksp->ks_update = envctrl_temp_kstat_update;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((unitp->diskksp = kstat_create(ENVCTRL_MODULE_NAME,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->instance, ENVCTRL_KSTAT_DISK, "misc", KSTAT_TYPE_RAW,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: disk name kstat_create failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel unitp->diskksp->ks_update = envctrl_disk_kstat_update;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_get_fpm_status(unitp, (uint8_t *)NULL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read of PCF8574A (FSP) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV5,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read of PCF8574A (DISKPR) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV7,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN, "%s%d: Read of PCF8574A (DISKFL) failed",
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_update_disk_kstats(struct envctrlunit *unitp, uint8_t diskpr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DPRINTF1("diskpr = %X, diskfl = %X\n", diskpr, diskfl);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (i = 0, j = 1; i < ENVCTRL_UE250_MAX_DISKS; i++, j = j << 1) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (!(diskpr & j)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (!(diskfl & j))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The cpu search is as follows:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If there is only 1 CPU module it is named as
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * SUNW,UltraSPARC. If this is a match we still don't
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * know what slot the cpu module is in therefore
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we need to check the "upa-portid" property.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If we have more than 1 cpu, then they are appended by
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * instance numbers and slot locations. e.g.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * SUNW,UltraSPARC@1,0 (slot 1). it would have been
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * nice to have the naming consistent for one CPU e.g.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * SUNW,UltraSPARC@0,0...sigh
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (instance = 0; instance < ENVCTRL_MAX_CPUS; instance++) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_walk_devs(ddi_root_node(), envctrl_match_cpu, unitp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct envctrlunit *unitp = (struct envctrlunit *)arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) sprintf(name, "%s", ENVCTRL_ULTRA1CPU_STRING);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) sprintf(name1, "%s", ENVCTRL_ULTRA2CPU_STRING);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This routine returns TRUE if some other error condition
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * has set the GEN_ERR FAULT LED. Tp further complicate this
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * LED panel we have overloaded the GEN_ERR LED to indicate
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * that a fan fault has occurred without having a fan fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * LED as does all other error conditions. So we just take the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * software state and return true. The whole purpose of this functon
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * is to tell us wehther or not we can shut off the GEN_FAULT LED.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * NOTE: this ledval is usually one of the following FSP vals
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * EXCEPT in the case of the fan fail.. we pass in a "0".
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenvctrl_isother_fault_led(struct envctrlunit *unitp, uint8_t fspval,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (fspval != 0) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct envctrlunit *unitp = (struct envctrlunit *)arg;