1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * ENVCTRLTWO_ Environment Monitoring driver for i2c on Javelin 31 * 32 */ 33 #include <sys/param.h> 34 #include <sys/types.h> 35 #include <sys/signal.h> 36 #include <sys/errno.h> 37 #include <sys/file.h> 38 #include <sys/termio.h> 39 #include <sys/termios.h> 40 #include <sys/cmn_err.h> 41 #include <sys/stream.h> 42 #include <sys/strsun.h> 43 #include <sys/stropts.h> 44 #include <sys/strtty.h> 45 #include <sys/debug.h> 46 #include <sys/eucioctl.h> 47 #include <sys/cred.h> 48 #include <sys/uio.h> 49 #include <sys/stat.h> 50 #include <sys/kmem.h> 51 52 #include <sys/ddi.h> 53 #include <sys/sunddi.h> 54 #include <sys/obpdefs.h> 55 #include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */ 56 #include <sys/modctl.h> /* for modldrv */ 57 #include <sys/stat.h> /* ddi_create_minor_node S_IFCHR */ 58 #include <sys/open.h> /* for open params. */ 59 #include <sys/uio.h> /* for read/write */ 60 #include <sys/envctrl_gen.h> /* user level generic visible definitions */ 61 #include <sys/envctrl_ue250.h> /* user level UE250 visible definitions */ 62 #include <javelin/sys/envctrltwo.h> /* definitions for Javelin */ 63 #include <io/envctrl_targets.c> 64 #include <sys/priv_names.h> 65 66 /* driver entry point fn definitions */ 67 static int envctrl_open(dev_t *, int, int, cred_t *); 68 static int envctrl_close(dev_t, int, int, cred_t *); 69 static int envctrl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 70 static uint_t envctrl_bus_isr(caddr_t); 71 static uint_t envctrl_dev_isr(caddr_t); 72 73 /* configuration entry point fn definitions */ 74 static int envctrl_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 75 static int envctrl_attach(dev_info_t *, ddi_attach_cmd_t); 76 static int envctrl_detach(dev_info_t *, ddi_detach_cmd_t); 77 78 /* Driver private routines */ 79 #ifdef GET_CPU_TEMP 80 static int envctrl_get_cpu_temp(struct envctrlunit *, int); 81 #endif 82 static void envctrl_fan_fail_service(struct envctrlunit *); 83 static void envctrl_PS_intr_service(struct envctrlunit *); 84 static void envctrl_ps_probe(struct envctrlunit *); 85 static void envctrl_tempr_poll(void *); 86 static void envctrl_pshotplug_poll(void *); 87 static void envctrl_led_blink(void *); 88 static void envctrl_init_bus(struct envctrlunit *); 89 static void envctrl_reset_dflop(struct envctrlunit *); 90 static void envctrl_enable_devintrs(struct envctrlunit *); 91 static void envctrl_intr_latch_clr(struct envctrlunit *); 92 static void envctrl_abort_seq_handler(char *msg); 93 static int envctrl_get_fpm_status(struct envctrlunit *, uint8_t *); 94 static int envctrl_set_fsp(struct envctrlunit *, uint8_t *); 95 static int envctrl_set_dskled(struct envctrlunit *, 96 struct envctrl_chip *); 97 static int envctrl_get_dskled(struct envctrlunit *, 98 struct envctrl_chip *); 99 static int envctrl_set_fanspeed(struct envctrlunit *, 100 struct envctrl_chip *); 101 static void envctrl_probe_cpus(struct envctrlunit *); 102 static int envctrl_match_cpu(dev_info_t *, void *); 103 static int envctrl_isother_fault_led(struct envctrlunit *, 104 uint8_t, uint8_t); 105 static int envctrl_check_sys_temperatures(struct envctrlunit *); 106 static void envctrl_check_disk_kstats(struct envctrlunit *); 107 static void envctrl_update_disk_kstats(struct envctrlunit *, 108 uint8_t, uint8_t); 109 static int envctrl_read_chip(struct envctrlunit *, int, int, int, 110 uint8_t *, int); 111 static int envctrl_write_chip(struct envctrlunit *, int, int, int, 112 uint8_t *, int); 113 static int envctrl_check_tempr_levels(struct envctrlunit *, 114 int, uint8_t *, int); 115 static void envctrl_update_fanspeed(struct envctrlunit *); 116 117 /* Kstat routines */ 118 static void envctrl_add_kstats(struct envctrlunit *); 119 static int envctrl_ps_kstat_update(kstat_t *, int); 120 static int envctrl_fanstat_kstat_update(kstat_t *, int); 121 static int envctrl_encl_kstat_update(kstat_t *, int); 122 static int envctrl_temp_kstat_update(kstat_t *, int); 123 static int envctrl_disk_kstat_update(kstat_t *, int); 124 static void envctrl_init_encl_kstats(struct envctrlunit *); 125 126 extern void power_down(const char *); 127 extern int prom_getprop(); 128 extern int prom_getproplen(); 129 extern void prom_printf(const char *fmt, ...); 130 extern void (*abort_seq_handler)(); 131 132 static void *envctrlsoft_statep; 133 134 static char driver_name[] = "envctrltwo"; 135 static uchar_t _cpu_temps[256]; 136 static uchar_t _cpu_fan_speeds[256]; 137 static int psok[2] = {-1, -1}; 138 static int pspr[2] = {-1, -1}; 139 static uint8_t idle_fanspeed; 140 141 static int power_flt_led_lit = 0; 142 143 extern void pci_thermal_rem_intr(dev_info_t *, uint_t); 144 145 /* Local Variables */ 146 /* Indicates whether or not the overtemp thread has been started */ 147 static int envctrl_debug_flags = 0; 148 static int envctrl_power_off_overide = 0; 149 static int envctrl_max_retries = 200; 150 static int envctrl_allow_detach = 0; 151 static int envctrl_numcpus = 1; 152 static int envctrl_handler = 1; /* 1 is the default */ 153 static clock_t overtemp_timeout_hz; 154 static clock_t blink_timeout_hz; 155 static clock_t pshotplug_timeout_hz; 156 static clock_t warning_timeout_hz; 157 /* 158 * Temperature levels : 159 * green = OK - no action needed 160 * yellow = warning - display warning message and poll faster 161 * red = critical - shutdown system 162 */ 163 enum levels {green, yellow, red}; 164 165 #define DPRINTF1 if (envctrl_debug_flags && (envctrl_debug_flags & 0x1)) printf 166 #define DPRINTF2 if (envctrl_debug_flags && (envctrl_debug_flags & 0x2)) printf 167 #define DPRINTF3 if (envctrl_debug_flags && (envctrl_debug_flags & 0x4)) printf 168 169 #define JAV_FAN_SPEED_SF_NUM 107 170 #define JAV_FAN_SPEED_SF_DEN 100 171 #define JAV_MAX_TEMP_SENSORS 6 172 #define JAV_FSP_MASK 0xC0 173 #define FAN_DRIFT 25 174 #define MAX_FAN_SPEED 255 175 #define MAX_DEVS 16 176 177 #define ENVCTRL_UE250_INTR_LATCH_INIT0 0xFE 178 #define ENVCTRL_UE250_INTR_LATCH_INIT1 0xFF 179 180 static int t_scale_num[8]; 181 static int t_scale_den[8]; 182 static uint8_t t_addr[8]; 183 static uint8_t t_port[8]; 184 static int sensor_types[] = { ENVCTRL_UE250_CPU0_SENSOR, 185 ENVCTRL_UE250_CPU1_SENSOR, ENVCTRL_UE250_MB0_SENSOR, 186 ENVCTRL_UE250_MB1_SENSOR, ENVCTRL_UE250_PDB_SENSOR, 187 ENVCTRL_UE250_SCSI_SENSOR }; 188 189 static struct cb_ops envctrl_cb_ops = { 190 envctrl_open, /* cb_open */ 191 envctrl_close, /* cb_close */ 192 nodev, /* cb_strategy */ 193 nodev, /* cb_print */ 194 nodev, /* cb_dump */ 195 nodev, /* cb_read */ 196 nodev, /* cb_write */ 197 envctrl_ioctl, /* cb_ioctl */ 198 nodev, /* cb_devmap */ 199 nodev, /* cb_mmap */ 200 nodev, /* cb_segmap */ 201 nochpoll, /* cb_chpoll */ 202 ddi_prop_op, /* cb_prop_op */ 203 NULL, /* cb_stream */ 204 (int)(D_NEW | D_MP) /* cb_flag */ 205 }; 206 207 /* 208 * Declare ops vectors for auto configuration. 209 */ 210 struct dev_ops envctrltwo_ops = { 211 DEVO_REV, /* devo_rev */ 212 0, /* devo_refcnt */ 213 envctrl_getinfo, /* devo_getinfo */ 214 nulldev, /* devo_identify */ 215 nulldev, /* devo_probe */ 216 envctrl_attach, /* devo_attach */ 217 envctrl_detach, /* devo_detach */ 218 nodev, /* devo_reset */ 219 &envctrl_cb_ops, /* devo_cb_ops */ 220 (struct bus_ops *)NULL, /* devo_bus_ops */ 221 nulldev /* devo_power */ 222 }; 223 224 extern struct mod_ops mod_driverops; 225 226 static struct modldrv envctrlmodldrv = { 227 &mod_driverops, /* type of module - driver */ 228 "I2C ENVCTRLTWO_driver: %I%", 229 &envctrltwo_ops, 230 }; 231 232 static struct modlinkage envctrlmodlinkage = { 233 MODREV_1, 234 &envctrlmodldrv, 235 0 236 }; 237 238 int 239 _init(void) 240 { 241 register int error; 242 243 if ((error = mod_install(&envctrlmodlinkage)) == 0) { 244 (void) ddi_soft_state_init(&envctrlsoft_statep, 245 sizeof (struct envctrlunit), 1); 246 } 247 248 return (error); 249 } 250 251 int 252 _fini(void) 253 { 254 register int error; 255 256 if ((error = mod_remove(&envctrlmodlinkage)) == 0) 257 ddi_soft_state_fini(&envctrlsoft_statep); 258 259 return (error); 260 } 261 262 int 263 _info(struct modinfo *modinfop) 264 { 265 return (mod_info(&envctrlmodlinkage, modinfop)); 266 } 267 268 static int 269 envctrl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 270 { 271 register int instance; 272 char name[16]; 273 uint8_t fspval; 274 register struct envctrlunit *unitp; 275 struct ddi_device_acc_attr attr; 276 uchar_t *creg_prop; 277 uint_t len, tblsz; 278 int i, j, k, status; 279 uint8_t fanspeed; 280 281 status = len = tblsz = 0; 282 283 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 284 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 285 286 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 287 288 instance = ddi_get_instance(dip); 289 290 switch (cmd) { 291 case DDI_ATTACH: 292 break; 293 case DDI_RESUME: 294 if (!(unitp = ddi_get_soft_state(envctrlsoft_statep, instance))) 295 return (DDI_FAILURE); 296 mutex_enter(&unitp->umutex); 297 if (!unitp->suspended) { 298 mutex_exit(&unitp->umutex); 299 return (DDI_FAILURE); 300 } 301 unitp->suspended = 0; 302 unitp->initting = B_TRUE; 303 envctrl_init_bus(unitp); 304 unitp->initting = B_FALSE; 305 306 envctrl_ps_probe(unitp); 307 envctrl_probe_cpus(unitp); 308 mutex_exit(&unitp->umutex); 309 310 return (DDI_SUCCESS); 311 312 default: 313 return (DDI_FAILURE); 314 } 315 316 /* Set up timer values */ 317 overtemp_timeout_hz = drv_usectohz(ENVCTRL_UE250_OVERTEMP_TIMEOUT_USEC); 318 blink_timeout_hz = drv_usectohz(ENVCTRL_UE250_BLINK_TIMEOUT_USEC); 319 pshotplug_timeout_hz = 320 drv_usectohz(ENVCTRL_UE250_BLINK_TIMEOUT_USEC * 2); 321 /* 322 * On a cooling failure, either a fan failure or temperature 323 * exceeding a WARNING level, the temperature poll thread 324 * will run every 6 seconds. 325 */ 326 warning_timeout_hz = 327 drv_usectohz(ENVCTRL_UE250_OVERTEMP_TIMEOUT_USEC / 6); 328 329 if (ddi_soft_state_zalloc(envctrlsoft_statep, instance) != 0) { 330 cmn_err(CE_WARN, "%s%d: failed to zalloc softstate\n", 331 ddi_get_name(dip), instance); 332 goto failed; 333 } 334 335 unitp = ddi_get_soft_state(envctrlsoft_statep, instance); 336 337 if (ddi_regs_map_setup(dip, 0, (caddr_t *)&unitp->bus_ctl_regs, 0, 338 sizeof (struct ehc_pcd8584_regs), &attr, 339 &unitp->ctlr_handle) != DDI_SUCCESS) { 340 cmn_err(CE_WARN, "%s%d: failed to map in bus_control regs\n", 341 ddi_get_name(dip), instance); 342 return (DDI_FAILURE); 343 } 344 345 /* 346 * If the PCI nexus has added a thermal interrupt, we first need 347 * to remove that interrupt handler. 348 * 349 * WARNING: Removing another driver's interrupt handler is not 350 * allowed. The pci_thermal_rem_intr() call below is needed to retain 351 * the legacy behavior on Javelin systems. 352 */ 353 354 pci_thermal_rem_intr(dip, (uint_t)0); 355 356 /* add interrupts */ 357 358 if (ddi_get_iblock_cookie(dip, 1, 359 &unitp->ic_trap_cookie) != DDI_SUCCESS) { 360 cmn_err(CE_WARN, "%s%d: ddi_get_iblock_cookie FAILED \n", 361 ddi_get_name(dip), instance); 362 goto failed; 363 } 364 365 mutex_init(&unitp->umutex, NULL, MUTEX_DRIVER, 366 (void *)unitp->ic_trap_cookie); 367 368 369 if (ddi_add_intr(dip, 0, &unitp->ic_trap_cookie, NULL, envctrl_bus_isr, 370 (caddr_t)unitp) != DDI_SUCCESS) { 371 cmn_err(CE_WARN, "%s%d: failed to add hard intr \n", 372 ddi_get_name(dip), instance); 373 goto remlock; 374 } 375 376 377 if (ddi_add_intr(dip, 1, &unitp->ic_trap_cookie, NULL, envctrl_dev_isr, 378 (caddr_t)unitp) != DDI_SUCCESS) { 379 cmn_err(CE_WARN, "%s%d: failed to add hard intr \n", 380 ddi_get_name(dip), instance); 381 goto remhardintr; 382 } 383 384 385 (void) sprintf(name, "envctrltwo%d", instance); 386 387 if (ddi_create_priv_minor_node(dip, name, S_IFCHR, instance, 388 DDI_PSEUDO, 0, PRIV_SYS_CONFIG, PRIV_SYS_CONFIG, 0666) == 389 DDI_FAILURE) { 390 goto remhardintr1; 391 } 392 393 mutex_enter(&unitp->umutex); 394 395 /* 396 * Javelin will not have a workstation configuration so activity 397 * LED will always blink. 398 */ 399 unitp->activity_led_blink = B_TRUE; 400 unitp->shutdown = B_FALSE; 401 unitp->num_ps_present = 0; 402 unitp->num_encl_present = 1; 403 unitp->current_mode = ENVCTRL_NORMAL_MODE; 404 if (envctrl_numcpus > 1) { 405 unitp->num_cpus_present = envctrl_numcpus; 406 } 407 envctrl_probe_cpus(unitp); 408 if ((unitp->cpu_pr_location[ENVCTRL_CPU0] == B_FALSE) || 409 (unitp->cpu_pr_location[ENVCTRL_CPU1] == B_FALSE)) 410 /* Only one CPU in the system */ 411 unitp->num_temps_present = 5; 412 else 413 unitp->num_temps_present = 6; 414 unitp->num_fans_present = 1; 415 unitp->dip = dip; 416 417 mutex_exit(&unitp->umutex); 418 419 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 420 "cpu-temp-factors", &creg_prop, &len) != DDI_PROP_SUCCESS) { 421 cmn_err(CE_WARN, 422 "%s%d: Unable to read cpu-temp-factors property", 423 ddi_get_name(dip), instance); 424 return (DDI_NOT_WELL_FORMED); 425 } 426 tblsz = (sizeof (_cpu_temps) / sizeof (uchar_t)); 427 428 if (len <= tblsz && status == DDI_PROP_SUCCESS) { 429 for (i = 0; i < len; i++) { 430 _cpu_temps[i+2] = creg_prop[i]; 431 } 432 } 433 _cpu_temps[0] = _cpu_temps[1] = _cpu_temps[2]; 434 435 ddi_prop_free((void *)creg_prop); 436 437 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 438 "cpu-fan-speeds", &creg_prop, &len) != DDI_PROP_SUCCESS) { 439 cmn_err(CE_WARN, 440 "%s%d: Unable to read cpu-fan-speeds property", 441 ddi_get_name(dip), instance); 442 return (DDI_NOT_WELL_FORMED); 443 } 444 tblsz = (sizeof (_cpu_fan_speeds) / sizeof (uchar_t)); 445 446 if (len <= tblsz && status == DDI_PROP_SUCCESS) { 447 for (i = 0; i < len; i++) { 448 _cpu_fan_speeds[i+2] = creg_prop[i]; 449 } 450 } 451 _cpu_fan_speeds[0] = _cpu_fan_speeds[1] = _cpu_fan_speeds[2]; 452 453 ddi_prop_free((void *)creg_prop); 454 455 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 456 "thermisters", &creg_prop, &len) != DDI_PROP_SUCCESS) { 457 cmn_err(CE_WARN, 458 "%s%d: Unable to read thermisters property", 459 ddi_get_name(dip), instance); 460 return (DDI_NOT_WELL_FORMED); 461 } 462 463 mutex_enter(&unitp->umutex); 464 465 j = 0; k = 0; 466 for (i = 0; i < JAV_MAX_TEMP_SENSORS; i++) { 467 /* Type */ 468 unitp->temp_kstats[k].type = sensor_types[i]; 469 /* Address */ 470 t_addr[k] = creg_prop[j] << 24 | creg_prop[j+1] << 16 | 471 creg_prop[j+2] << 8 | creg_prop[j+3]; 472 j += 4; 473 /* Port */ 474 t_port[k] = creg_prop[j] << 24 | creg_prop[j+1] << 16 | 475 creg_prop[j+2] << 8 | creg_prop[j+3]; 476 j += 4; 477 /* Min */ 478 unitp->temp_kstats[k].min = 479 creg_prop[j] << 24 | creg_prop[j+1] << 16 | 480 creg_prop[j+2] << 8 | creg_prop[j+3]; 481 j += 4; 482 /* Warning threshold */ 483 unitp->temp_kstats[k].warning_threshold = 484 creg_prop[j] << 24 | creg_prop[j+1] << 16 | 485 creg_prop[j+2] << 8 | creg_prop[j+3]; 486 j += 4; 487 /* Shutdown threshold */ 488 unitp->temp_kstats[k].shutdown_threshold = 489 creg_prop[j] << 24 | creg_prop[j+1] << 16 | 490 creg_prop[j+2] << 8 | creg_prop[j+3]; 491 j += 4; 492 /* Numerator of scale factor */ 493 t_scale_num[k] = creg_prop[j] << 24 | creg_prop[j+1] << 16 | 494 creg_prop[j+2] << 8 | creg_prop[j+3]; 495 j += 4; 496 /* Denominator of scale factor */ 497 t_scale_den[k] = creg_prop[j] << 24 | creg_prop[j+1] << 16 | 498 creg_prop[j+2] << 8 | creg_prop[j+3]; 499 j += 4; 500 bcopy((caddr_t)&creg_prop[j], unitp->temp_kstats[k].label, 501 (size_t)sizeof (&creg_prop[j])); 502 while (creg_prop[j] != '\0') j++; 503 j++; 504 if (t_addr[k] == ENVCTRL_UE250_CPU_TEMP_DEV) { 505 if (((t_port[k] == ENVCTRL_UE250_CPU0_PORT) && 506 (unitp->cpu_pr_location[ENVCTRL_CPU0] == B_FALSE)) || 507 ((t_port[k] == ENVCTRL_UE250_CPU1_PORT) && 508 (unitp->cpu_pr_location[ENVCTRL_CPU1] == B_FALSE))) 509 /* Don't increment the kstat line count */ 510 #ifdef lint 511 k = k; 512 #else 513 ; 514 #endif 515 else 516 k++; 517 } else 518 k++; 519 } 520 521 ddi_prop_free((void *)creg_prop); 522 523 /* initialize the envctrl bus controller */ 524 525 unitp->initting = B_TRUE; 526 envctrl_init_bus(unitp); 527 DPRINTF1("envctrl_attach(): Completed initialization of PCF8584"); 528 unitp->initting = B_FALSE; 529 drv_usecwait(1000); 530 531 unitp->timeout_id = 0; 532 unitp->blink_timeout_id = 0; 533 534 unitp->fan_failed = 0; 535 unitp->fan_kstats.fans_ok = B_TRUE; 536 unitp->tempr_warning = 0; 537 538 envctrl_ps_probe(unitp); 539 540 unitp->initting = B_TRUE; 541 envctrl_fan_fail_service(unitp); 542 unitp->initting = B_FALSE; 543 544 /* 545 * Fans could be blasting, turn them down. 546 */ 547 fanspeed = 0x0; 548 status = envctrl_write_chip(unitp, ENVCTRL_PCF8591, EHC_DEV2, 0, 549 &fanspeed, 1); 550 if (status == DDI_FAILURE) 551 cmn_err(CE_WARN, "%s%d: Write to PCF8591 (SETFAN) failed\n", 552 ddi_get_name(dip), instance); 553 554 /* 555 * we need to init the fan kstats before the tempr_poll 556 */ 557 envctrl_add_kstats(unitp); 558 envctrl_init_encl_kstats(unitp); 559 envctrl_check_disk_kstats(unitp); 560 561 envctrl_update_fanspeed(unitp); 562 idle_fanspeed = unitp->fan_kstats.fanspeed; 563 564 if (unitp->activity_led_blink == B_TRUE) { 565 unitp->present_led_state = B_FALSE; 566 mutex_exit(&unitp->umutex); 567 envctrl_led_blink((void *)unitp); 568 mutex_enter(&unitp->umutex); 569 } else { 570 fspval = ENVCTRL_UE250_FSP_ACTIVE; 571 (void) envctrl_set_fsp(unitp, &fspval); 572 } 573 574 mutex_exit(&unitp->umutex); 575 576 envctrl_tempr_poll((void *)unitp); 577 578 /* 579 * interpose envctrl's abort sequence handler 580 */ 581 if (envctrl_handler) { 582 abort_seq_handler = envctrl_abort_seq_handler; 583 } 584 585 ddi_report_dev(dip); 586 587 return (DDI_SUCCESS); 588 589 remhardintr1: 590 ddi_remove_intr(dip, (uint_t)1, unitp->ic_trap_cookie); 591 remhardintr: 592 ddi_remove_intr(dip, (uint_t)0, unitp->ic_trap_cookie); 593 594 remlock: 595 mutex_destroy(&unitp->umutex); 596 597 failed: 598 if (unitp->ctlr_handle) 599 ddi_regs_map_free(&unitp->ctlr_handle); 600 601 cmn_err(CE_WARN, "%s%d: attach failed\n", ddi_get_name(dip), instance); 602 603 return (DDI_FAILURE); 604 605 } 606 607 static int 608 envctrl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 609 { 610 int instance; 611 register struct envctrlunit *unitp; 612 613 instance = ddi_get_instance(dip); 614 unitp = ddi_get_soft_state(envctrlsoft_statep, instance); 615 616 switch (cmd) { 617 case DDI_DETACH: 618 if (envctrl_allow_detach) { 619 620 if (unitp->psksp != NULL) { 621 kstat_delete(unitp->psksp); 622 } 623 if (unitp->fanksp != NULL) { 624 kstat_delete(unitp->fanksp); 625 } 626 if (unitp->enclksp != NULL) { 627 kstat_delete(unitp->enclksp); 628 } 629 if (unitp->tempksp != NULL) { 630 kstat_delete(unitp->tempksp); 631 } 632 if (unitp->diskksp != NULL) { 633 kstat_delete(unitp->diskksp); 634 } 635 636 if (unitp->timeout_id != 0) { 637 (void) untimeout(unitp->timeout_id); 638 unitp->timeout_id = 0; 639 } 640 if (unitp->blink_timeout_id != 0) { 641 (void) untimeout(unitp->blink_timeout_id); 642 unitp->blink_timeout_id = 0; 643 } 644 645 ddi_remove_minor_node(dip, NULL); 646 647 ddi_remove_intr(dip, (uint_t)0, unitp->ic_trap_cookie); 648 ddi_remove_intr(dip, (uint_t)1, unitp->ic_trap_cookie); 649 650 ddi_regs_map_free(&unitp->ctlr_handle); 651 652 mutex_destroy(&unitp->umutex); 653 654 return (DDI_SUCCESS); 655 } else { 656 return (DDI_FAILURE); 657 } 658 659 case DDI_SUSPEND: 660 if (!(unitp = ddi_get_soft_state(envctrlsoft_statep, instance))) 661 return (DDI_FAILURE); 662 mutex_enter(&unitp->umutex); 663 if (unitp->suspended) { 664 cmn_err(CE_WARN, "%s%d: envctrltwo already suspended\n", 665 ddi_get_name(dip), instance); 666 mutex_exit(&unitp->umutex); 667 return (DDI_FAILURE); 668 } 669 unitp->suspended = 1; 670 mutex_exit(&unitp->umutex); 671 return (DDI_SUCCESS); 672 673 default: 674 cmn_err(CE_WARN, "%s%d: suspend general fault\n", 675 ddi_get_name(dip), instance); 676 return (DDI_FAILURE); 677 } 678 679 680 } 681 int 682 envctrl_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 683 void **result) 684 { 685 dev_t dev = (dev_t)arg; 686 struct envctrlunit *unitp; 687 int instance, ret; 688 689 instance = getminor(dev); 690 691 #ifdef lint 692 dip = dip; 693 #endif 694 695 696 switch (infocmd) { 697 case DDI_INFO_DEVT2DEVINFO: 698 if ((unitp = (struct envctrlunit *) 699 ddi_get_soft_state(envctrlsoft_statep, 700 instance)) != NULL) { 701 *result = unitp->dip; 702 ret = DDI_SUCCESS; 703 } else { 704 *result = NULL; 705 ret = DDI_FAILURE; 706 } 707 break; 708 case DDI_INFO_DEVT2INSTANCE: 709 *result = (void *)(uintptr_t)instance; 710 ret = DDI_SUCCESS; 711 break; 712 default: 713 ret = DDI_FAILURE; 714 break; 715 } 716 717 return (ret); 718 } 719 720 /* ARGSUSED1 */ 721 static int 722 envctrl_open(dev_t *dev, int flag, int otyp, cred_t *cred_p) 723 { 724 struct envctrlunit *unitp; 725 int status = 0; 726 register int instance; 727 728 instance = getminor(*dev); 729 if (instance < 0) 730 return (ENXIO); 731 unitp = (struct envctrlunit *) 732 ddi_get_soft_state(envctrlsoft_statep, instance); 733 734 if (unitp == NULL) 735 return (ENXIO); 736 737 if (otyp != OTYP_CHR) 738 return (EINVAL); 739 740 mutex_enter(&unitp->umutex); 741 742 if (flag & FWRITE) { 743 if ((unitp->oflag & FWRITE)) { 744 mutex_exit(&unitp->umutex); 745 return (EBUSY); 746 } else { 747 unitp->oflag |= FWRITE; 748 } 749 } 750 751 mutex_exit(&unitp->umutex); 752 return (status); 753 } 754 755 /*ARGSUSED1*/ 756 static int 757 envctrl_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 758 { 759 struct envctrlunit *unitp; 760 register int instance; 761 762 instance = getminor(dev); 763 if (instance < 0) 764 return (ENXIO); 765 unitp = (struct envctrlunit *) 766 ddi_get_soft_state(envctrlsoft_statep, instance); 767 if (unitp == NULL) 768 return (ENXIO); 769 770 mutex_enter(&unitp->umutex); 771 772 unitp->oflag = B_FALSE; 773 unitp->current_mode = ENVCTRL_NORMAL_MODE; 774 775 mutex_exit(&unitp->umutex); 776 return (DDI_SUCCESS); 777 } 778 779 780 /* 781 * standard put procedure for envctrl 782 */ 783 static int 784 envctrl_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, 785 int *rvalp) 786 { 787 struct envctrlunit *unitp; 788 register int instance; 789 uint8_t wdval, tempr; 790 struct envctrl_chip fanspeed; 791 struct envctrl_chip ledchip, envcchip; 792 struct envctrl_chip temp, a_fanspeed; 793 int rval = 0, status, tfanspeed; 794 795 #ifdef lint 796 cred_p = cred_p; 797 rvalp = rvalp; 798 #endif 799 instance = getminor(dev); 800 unitp = (struct envctrlunit *) 801 ddi_get_soft_state(envctrlsoft_statep, instance); 802 803 if ((cmd == ENVCTRL_IOC_SETFAN2) || 804 (cmd == ENVCTRL_IOC_GETFAN2) || 805 (cmd == ENVCTRL_IOC_SETMODE) || 806 (cmd == ENVCTRL_IOC_GETMODE) || 807 (cmd == ENVCTRL_IOC_GETTEMP2) || 808 (cmd == ENVCTRL_IOC_SETFSP2) || 809 (cmd == ENVCTRL_IOC_GETFSP2) || 810 (cmd == ENVCTRL_IOC_RESETTMPR) || 811 (cmd == ENVCTRL_IOC_SETDSKLED2) || 812 (cmd == ENVCTRL_IOC_GETDSKLED2)) 813 if ((caddr_t)arg == NULL) 814 return (EFAULT); 815 816 switch (cmd) { 817 case ENVCTRL_IOC_SETMODE: 818 /* Set mode */ 819 if (ddi_copyin((caddr_t)arg, (caddr_t)&wdval, sizeof (uint8_t), 820 flag)) { 821 rval = EFAULT; 822 break; 823 } 824 if (wdval == ENVCTRL_DIAG_MODE || 825 wdval == ENVCTRL_NORMAL_MODE) { 826 mutex_enter(&unitp->umutex); 827 unitp->current_mode = wdval; 828 if (unitp->timeout_id != 0 && 829 wdval == ENVCTRL_DIAG_MODE) { 830 (void) untimeout(unitp->timeout_id); 831 unitp->timeout_id = 832 (timeout(envctrl_tempr_poll, 833 (caddr_t)unitp, overtemp_timeout_hz)); 834 } 835 if (wdval == ENVCTRL_NORMAL_MODE) { 836 /* 837 * Fans could be blasting, turn them down. 838 */ 839 tempr = 0x0; 840 status = envctrl_write_chip(unitp, 841 ENVCTRL_PCF8591, EHC_DEV2, 0, 842 &tempr, 1); 843 if (status == DDI_FAILURE) 844 cmn_err(CE_WARN, 845 "%s%d: Write to PCF8591 (SETMODE) failed\n", 846 driver_name, unitp->instance); 847 848 /* 849 * This delay allows the fans to time to 850 * change speed 851 */ 852 drv_usecwait(100000); 853 (void) envctrl_check_sys_temperatures(unitp); 854 unitp->current_mode = ENVCTRL_DIAG_MODE; 855 envctrl_fan_fail_service(unitp); 856 unitp->current_mode = ENVCTRL_NORMAL_MODE; 857 } 858 mutex_exit(&unitp->umutex); 859 } else { 860 rval = EINVAL; 861 } 862 break; 863 case ENVCTRL_IOC_GETMODE: 864 wdval = unitp->current_mode; 865 if (ddi_copyout((caddr_t)&wdval, (caddr_t)arg, 866 sizeof (uint8_t), flag)) { 867 rval = EFAULT; 868 } 869 break; 870 case ENVCTRL_IOC_RESETTMPR: 871 /* 872 * For diags, cancel the curent temp poll 873 * and reset it for a new one. 874 */ 875 if (unitp->current_mode == ENVCTRL_DIAG_MODE) { 876 if (unitp->timeout_id != 0) { 877 (void) untimeout(unitp->timeout_id); 878 unitp->timeout_id = 0; 879 } 880 envctrl_tempr_poll((void *)unitp); 881 } else { 882 rval = EINVAL; 883 } 884 break; 885 case ENVCTRL_IOC_GETTEMP2: 886 /* Get the user buffer address */ 887 888 if (ddi_copyin((caddr_t)arg, (caddr_t)&temp, 889 sizeof (struct envctrl_chip), flag)) { 890 rval = EFAULT; 891 break; 892 } 893 if (((temp.chip_num != ENVCTRL_DEV2) && 894 (temp.chip_num != ENVCTRL_DEV7)) || 895 (temp.index > EHC_PCF8591_CH_3)) { 896 rval = EINVAL; 897 break; 898 } 899 mutex_enter(&unitp->umutex); 900 status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, 901 temp.chip_num, temp.index, &temp.val, 1); 902 mutex_exit(&unitp->umutex); 903 if (status == DDI_FAILURE) { 904 cmn_err(CE_WARN, 905 "%s%d: Read from PCF8591 (IOC_GETTEMP) failed", 906 driver_name, unitp->instance); 907 rval = EINVAL; 908 break; 909 } 910 if (ddi_copyout((caddr_t)&temp, (caddr_t)arg, 911 sizeof (struct envctrl_chip), flag)) { 912 rval = EFAULT; 913 } 914 break; 915 case ENVCTRL_IOC_SETTEMP: 916 rval = EINVAL; 917 break; 918 case ENVCTRL_IOC_SETWDT: 919 rval = EINVAL; 920 break; 921 case ENVCTRL_IOC_SETFAN2: 922 /* NOTE: need to sanity check values coming from userland */ 923 if (unitp->current_mode == ENVCTRL_DIAG_MODE) { 924 if (ddi_copyin((caddr_t)arg, (caddr_t)&fanspeed, 925 sizeof (struct envctrl_chip), flag)) { 926 rval = EFAULT; 927 break; 928 } 929 if ((fanspeed.type != ENVCTRL_PCF8591) || 930 (fanspeed.chip_num != ENVCTRL_DEV2) || 931 (fanspeed.index > EHC_PCF8591_CH_3)) { 932 rval = EINVAL; 933 break; 934 } 935 mutex_enter(&unitp->umutex); 936 status = envctrl_set_fanspeed(unitp, &fanspeed); 937 if (status == DDI_FAILURE) { 938 cmn_err(CE_WARN, 939 "%s%d: Write to PCF8591 (IOC_SETFAN) failed", 940 driver_name, unitp->instance); 941 rval = EINVAL; 942 } 943 mutex_exit(&unitp->umutex); 944 } else { 945 rval = EINVAL; 946 } 947 break; 948 case ENVCTRL_IOC_GETFAN2: 949 if (ddi_copyin((caddr_t)arg, (caddr_t)&a_fanspeed, 950 sizeof (struct envctrl_chip), flag)) { 951 rval = EFAULT; 952 break; 953 } 954 if ((a_fanspeed.type != ENVCTRL_PCF8591) || 955 (a_fanspeed.chip_num != ENVCTRL_DEV2) || 956 (a_fanspeed.index != EHC_PCF8591_CH_1)) { 957 rval = EINVAL; 958 break; 959 } 960 mutex_enter(&unitp->umutex); 961 status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, 962 a_fanspeed.chip_num, a_fanspeed.index, 963 &a_fanspeed.val, 1); 964 mutex_exit(&unitp->umutex); 965 if (status == DDI_FAILURE) { 966 cmn_err(CE_WARN, 967 "%s%d: Read of PCF8591 (IOC_GETFAN) failed", 968 driver_name, unitp->instance); 969 rval = EINVAL; 970 break; 971 } 972 /* 973 * Due to hardware limitation, the actual fan speed 974 * is always a little less than what it was set to by 975 * software. Hence, we scale up the read fan speed value 976 * to more closely match the set value. 977 */ 978 if ((tfanspeed = ((int)a_fanspeed.val * JAV_FAN_SPEED_SF_NUM) / 979 JAV_FAN_SPEED_SF_DEN) > 255) 980 a_fanspeed.val = 255; 981 else 982 a_fanspeed.val = tfanspeed & 0xFF; 983 unitp->fan_kstats.fanspeed = a_fanspeed.val; 984 if (ddi_copyout((caddr_t)&a_fanspeed, (caddr_t)arg, 985 sizeof (struct envctrl_chip), flag)) { 986 rval = EFAULT; 987 } 988 break; 989 case ENVCTRL_IOC_SETFSP2: 990 if (ddi_copyin((caddr_t)arg, (caddr_t)&envcchip, 991 sizeof (struct envctrl_chip), flag)) { 992 rval = EFAULT; 993 break; 994 } 995 if ((envcchip.type != ENVCTRL_PCF8574A) || 996 (envcchip.chip_num != ENVCTRL_DEV6)) { 997 rval = EINVAL; 998 break; 999 } 1000 wdval = envcchip.val; 1001 mutex_enter(&unitp->umutex); 1002 /* 1003 * If a user is in normal mode and they try 1004 * to set anything other than a disk fault or 1005 * a gen fault it is an invalid operation. 1006 * in diag mode we allow everything to be 1007 * twiddled. 1008 */ 1009 if (unitp->current_mode == ENVCTRL_NORMAL_MODE) { 1010 if (wdval & ~ENVCTRL_UE250_FSP_USRMASK) { 1011 mutex_exit(&unitp->umutex); 1012 rval = EINVAL; 1013 break; 1014 } 1015 } 1016 if (wdval & ENVCTRL_UE250_FSP_PS_ERR) 1017 power_flt_led_lit = 1; 1018 status = envctrl_set_fsp(unitp, &wdval); 1019 mutex_exit(&unitp->umutex); 1020 if (status == DDI_FAILURE) { 1021 cmn_err(CE_WARN, 1022 "%s%d: Read of PCF8574A (IOC_SETFSP) failed", 1023 driver_name, unitp->instance); 1024 rval = EINVAL; 1025 } 1026 break; 1027 case ENVCTRL_IOC_GETFSP2: 1028 if (ddi_copyin((caddr_t)arg, (caddr_t)&envcchip, 1029 sizeof (struct envctrl_chip), flag)) { 1030 rval = EFAULT; 1031 break; 1032 } 1033 if ((envcchip.type != ENVCTRL_PCF8574A) || 1034 (envcchip.chip_num != ENVCTRL_DEV6)) { 1035 rval = EINVAL; 1036 break; 1037 } 1038 mutex_enter(&unitp->umutex); 1039 status = envctrl_get_fpm_status(unitp, &wdval); 1040 mutex_exit(&unitp->umutex); 1041 if (status == DDI_FAILURE) { 1042 cmn_err(CE_WARN, 1043 "%s%d: Read of PCF8574A (IOC_GETFSP) failed", 1044 driver_name, unitp->instance); 1045 rval = EINVAL; 1046 } else { 1047 envcchip.val = wdval; 1048 if (ddi_copyout((caddr_t)&envcchip, (caddr_t)arg, 1049 sizeof (struct envctrl_chip), flag)) { 1050 rval = EFAULT; 1051 } 1052 } 1053 break; 1054 case ENVCTRL_IOC_SETDSKLED2: 1055 if (ddi_copyin((caddr_t)arg, (caddr_t)&ledchip, 1056 sizeof (struct envctrl_chip), flag)) { 1057 rval = EFAULT; 1058 break; 1059 } 1060 if ((ledchip.type != ENVCTRL_PCF8574A) || 1061 (ledchip.chip_num != ENVCTRL_DEV7)) { 1062 rval = EINVAL; 1063 break; 1064 } 1065 mutex_enter(&unitp->umutex); 1066 if (envctrl_set_dskled(unitp, &ledchip)) { 1067 rval = EINVAL; 1068 } 1069 mutex_exit(&unitp->umutex); 1070 break; 1071 case ENVCTRL_IOC_GETDSKLED2: 1072 if (ddi_copyin((caddr_t)arg, (caddr_t)&ledchip, 1073 sizeof (struct envctrl_chip), flag)) { 1074 rval = EFAULT; 1075 break; 1076 } 1077 if ((ledchip.type != ENVCTRL_PCF8574A) || 1078 (ledchip.chip_num != ENVCTRL_DEV7)) { 1079 rval = EINVAL; 1080 break; 1081 } 1082 mutex_enter(&unitp->umutex); 1083 if (envctrl_get_dskled(unitp, &ledchip)) { 1084 rval = EINVAL; 1085 } else { 1086 if (ddi_copyout((caddr_t)&ledchip, (caddr_t)arg, 1087 sizeof (struct envctrl_chip), flag)) { 1088 rval = EFAULT; 1089 } 1090 } 1091 mutex_exit(&unitp->umutex); 1092 break; 1093 case ENVCTRL_IOC_SETRAW: 1094 if (unitp->current_mode != ENVCTRL_DIAG_MODE) { 1095 rval = EINVAL; 1096 break; 1097 } 1098 if (ddi_copyin((caddr_t)arg, (caddr_t)&temp, 1099 sizeof (struct envctrl_chip), flag)) { 1100 rval = EFAULT; 1101 break; 1102 } 1103 mutex_enter(&unitp->umutex); 1104 status = envctrl_write_chip(unitp, temp.type, temp.chip_num, 1105 temp.index, &temp.val, 1); 1106 if (status == DDI_FAILURE) { 1107 cmn_err(CE_WARN, 1108 "%s%d: Write to chip (IOC_SETRAW) failed", 1109 driver_name, unitp->instance); 1110 rval = EINVAL; 1111 } 1112 mutex_exit(&unitp->umutex); 1113 break; 1114 case ENVCTRL_IOC_GETRAW: 1115 if (ddi_copyin((caddr_t)arg, (caddr_t)&temp, 1116 sizeof (struct envctrl_chip), flag)) { 1117 rval = EFAULT; 1118 break; 1119 } 1120 mutex_enter(&unitp->umutex); 1121 status = envctrl_read_chip(unitp, temp.type, temp.chip_num, 1122 temp.index, &temp.val, 1); 1123 if (status == DDI_FAILURE) { 1124 cmn_err(CE_WARN, 1125 "%s%d: Read of chip (IOC_GETRAW) failed", 1126 driver_name, unitp->instance); 1127 rval = EINVAL; 1128 } 1129 mutex_exit(&unitp->umutex); 1130 if (ddi_copyout((caddr_t)&temp, (caddr_t)arg, 1131 sizeof (struct envctrl_chip), flag)) { 1132 rval = EFAULT; 1133 } 1134 break; 1135 default: 1136 rval = EINVAL; 1137 } 1138 1139 return (rval); 1140 } 1141 1142 uint_t 1143 envctrl_bus_isr(caddr_t arg) 1144 { 1145 struct envctrlunit *unitp = (struct envctrlunit *)(void *)arg; 1146 int ic = DDI_INTR_UNCLAIMED; 1147 1148 mutex_enter(&unitp->umutex); 1149 1150 /* 1151 * NOT USED 1152 */ 1153 1154 mutex_exit(&unitp->umutex); 1155 return (ic); 1156 } 1157 1158 uint_t 1159 envctrl_dev_isr(caddr_t arg) 1160 { 1161 struct envctrlunit *unitp = (struct envctrlunit *)(void *)arg; 1162 uint8_t recv_data; 1163 int ic; 1164 int retrys = 0; 1165 int status; 1166 static int spurious_intr_count = 0; 1167 1168 ic = DDI_INTR_UNCLAIMED; 1169 1170 mutex_enter(&unitp->umutex); 1171 1172 1173 /* 1174 * First check to see if it is an interrupt for us by 1175 * looking at the "ganged" interrupt and vector 1176 * according to the major type 1177 * 0x70 is the addr of the ganged interrupt controller. 1178 * Address map for the port byte read is as follows 1179 * MSB 1180 * ------------------------- 1181 * | | | | | | | | | 1182 * ------------------------- 1183 * P7 P6 P5 P4 P3 P2 P1 P0 1184 * P0 = Spare 1185 * P1 = Thermal Interrupt 1186 * P2 = Disk Interrupt 1187 * P3 = Interrupt clock enable 1188 * P4 = Fan Fail Interrupt 1189 * P5 = Front Panel Interrupt 1190 * P6 = Power Supply Interrupt 1191 * P7 = Enable Interrupts 1192 */ 1193 1194 do { 1195 status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp, 1196 ENVCTRL_UE250_PCF8574A_BASE_ADDR | EHC_DEV0, 1197 &recv_data, 1); 1198 1199 /* 1200 * This extra read is needed since the first read is discarded 1201 * and the second read seems to return 0xFF. 1202 */ 1203 if (recv_data == 0xFF) { 1204 status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp, 1205 ENVCTRL_UE250_PCF8574A_BASE_ADDR | EHC_DEV0, 1206 &recv_data, 1); 1207 } 1208 1209 /* 1210 * if the i2c bus is hung it is imperative that this 1211 * be cleared on an interrupt or else it will 1212 * hang the system with continuous interrupts 1213 */ 1214 1215 if (status == DDI_FAILURE) { 1216 drv_usecwait(1000); 1217 if (retrys < envctrl_max_retries) { 1218 retrys++; 1219 } else { 1220 cmn_err(CE_WARN, 1221 "%s%d: Read of PCF8574A (INT) failed\n", 1222 driver_name, unitp->instance); 1223 ehc_init_pcf8584((struct ehc_envcunit *)unitp); 1224 mutex_exit(&unitp->umutex); 1225 ic = DDI_INTR_CLAIMED; 1226 return (ic); 1227 } 1228 } 1229 } while (status != DDI_SUCCESS); 1230 1231 DPRINTF1("Interrupt routine called, interrupt = %X\n", recv_data); 1232 if (!(recv_data & EHC_PCF8574_PORT0)) { 1233 ic = DDI_INTR_CLAIMED; 1234 } 1235 1236 if (!(recv_data & EHC_PCF8574_PORT1)) { 1237 DPRINTF1("Temperature interrupt detected\n"); 1238 (void) envctrl_check_sys_temperatures(unitp); 1239 1240 /* 1241 * Clear the interrupt latches 1242 */ 1243 envctrl_intr_latch_clr(unitp); 1244 1245 ic = DDI_INTR_CLAIMED; 1246 } 1247 1248 if (!(recv_data & EHC_PCF8574_PORT2)) { 1249 DPRINTF1("Disk interrupt detected\n"); 1250 envctrl_check_disk_kstats(unitp); 1251 ic = DDI_INTR_CLAIMED; 1252 } 1253 1254 if (!(recv_data & EHC_PCF8574_PORT3)) { 1255 ic = DDI_INTR_CLAIMED; 1256 } 1257 1258 if (!(recv_data & EHC_PCF8574_PORT4)) { 1259 /* 1260 * Check for a fan fail 1261 */ 1262 DPRINTF1("Fan interrupt detected\n"); 1263 envctrl_fan_fail_service(unitp); 1264 1265 /* 1266 * Clear the interrupt latches 1267 */ 1268 envctrl_intr_latch_clr(unitp); 1269 1270 ic = DDI_INTR_CLAIMED; 1271 } 1272 1273 if (!(recv_data & EHC_PCF8574_PORT5)) { 1274 DPRINTF1("Keyswitch interrupt detected\n"); 1275 (void) envctrl_get_fpm_status(unitp, (uint8_t *)NULL); 1276 ic = DDI_INTR_CLAIMED; 1277 } 1278 1279 if (!(recv_data & EHC_PCF8574_PORT6)) { 1280 DPRINTF1("Power supply interrupt detected\n"); 1281 envctrl_PS_intr_service(unitp); 1282 ic = DDI_INTR_CLAIMED; 1283 } 1284 1285 if (!(recv_data & EHC_PCF8574_PORT7)) { 1286 ic = DDI_INTR_CLAIMED; 1287 } 1288 1289 /* 1290 * The interrupt routine got called but the interrupt chip 1291 * shows no interrupt present. If this happens more than 256 1292 * times in a row, there is probably some hardware problem so 1293 * send a warning message to the console. 1294 */ 1295 if ((recv_data == 0xFF)) { 1296 if (spurious_intr_count == 255) 1297 cmn_err(CE_WARN, 1298 "%s%d: Received 256 spurious interrupts\n", 1299 driver_name, unitp->instance); 1300 spurious_intr_count++; 1301 ic = DDI_INTR_CLAIMED; 1302 } else 1303 spurious_intr_count = 0; 1304 1305 mutex_exit(&unitp->umutex); 1306 return (ic); 1307 1308 } 1309 1310 1311 static int 1312 envctrl_read_chip(struct envctrlunit *unitp, int type, int chip_num, int port, 1313 uint8_t *data, int num) 1314 { 1315 int retrys = 0, autoincr = 0; 1316 int status; 1317 1318 /* 1319 * If more than one read is requested, set auto-increment bit 1320 */ 1321 if (num > 1) 1322 autoincr = 1; 1323 1324 do { 1325 if (type == ENVCTRL_PCF8574A) { 1326 status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp, 1327 ENVCTRL_UE250_PCF8574A_BASE_ADDR | chip_num, 1328 data, num); 1329 } else if (type == ENVCTRL_PCF8574) { 1330 status = ehc_read_pcf8574((struct ehc_envcunit *)unitp, 1331 ENVCTRL_UE250_PCF8574_BASE_ADDR | chip_num, 1332 data, num); 1333 } else if (type == ENVCTRL_PCF8591) { 1334 status = ehc_read_pcf8591((struct ehc_envcunit *)unitp, 1335 ENVCTRL_UE250_PCF8591_BASE_ADDR | chip_num, 1336 port, autoincr, 0, 1, data, num); 1337 } 1338 /* 1339 * If the bus hangs, attempt a recovery 1340 */ 1341 if (status == DDI_FAILURE) { 1342 drv_usecwait(1000); 1343 if (retrys < envctrl_max_retries) { 1344 retrys++; 1345 } else { 1346 ehc_init_pcf8584((struct ehc_envcunit *)unitp); 1347 break; 1348 } 1349 } 1350 } while (status != DDI_SUCCESS); 1351 1352 return (status); 1353 } 1354 1355 static int 1356 envctrl_write_chip(struct envctrlunit *unitp, int type, int chip_num, int port, 1357 uint8_t *data, int num) 1358 { 1359 int retrys = 0, autoincr = 0; 1360 int status; 1361 1362 /* 1363 * Incase some applications mistakenly include the chips base addr 1364 */ 1365 chip_num = chip_num & 0xF; 1366 1367 /* 1368 * If more than one write is requested, set auto-increment bit 1369 */ 1370 if (num > 1) 1371 autoincr = 1; 1372 1373 do { 1374 if (type == ENVCTRL_PCF8574A) { 1375 status = ehc_write_pcf8574a( 1376 (struct ehc_envcunit *)unitp, 1377 ENVCTRL_UE250_PCF8574A_BASE_ADDR | chip_num, 1378 data, num); 1379 } else if (type == ENVCTRL_PCF8574) { 1380 status = ehc_write_pcf8574((struct ehc_envcunit *)unitp, 1381 ENVCTRL_UE250_PCF8574_BASE_ADDR | chip_num, 1382 data, num); 1383 } else if (type == ENVCTRL_PCF8591) { 1384 status = ehc_write_pcf8591((struct ehc_envcunit *)unitp, 1385 ENVCTRL_UE250_PCF8591_BASE_ADDR | chip_num, 1386 port, autoincr, 0, 1, data, num); 1387 } 1388 1389 /* 1390 * If the bus hangs, attempt a recovery 1391 */ 1392 if (status == DDI_FAILURE) { 1393 drv_usecwait(1000); 1394 if (retrys < envctrl_max_retries) { 1395 retrys++; 1396 } else { 1397 ehc_init_pcf8584((struct ehc_envcunit *)unitp); 1398 break; 1399 } 1400 } 1401 } while (status != DDI_SUCCESS); 1402 1403 return (status); 1404 } 1405 1406 #ifdef GET_CPU_TEMP 1407 static int 1408 envctrl_get_cpu_temp(struct envctrlunit *unitp, int cpunum) 1409 { 1410 uint8_t recv_data; 1411 int status; 1412 1413 ASSERT(MUTEX_HELD(&unitp->umutex)); 1414 1415 /* 1416 * This routine takes in the number of the port that 1417 * we want to read in the 8591. This should be the 1418 * location of the CPU thermistor for one of the 2 1419 * cpu's. It will return a normalized value 1420 * to the caller. 1421 */ 1422 1423 status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, EHC_DEV7, cpunum, 1424 &recv_data, 1); 1425 if (status == DDI_FAILURE) { 1426 cmn_err(CE_WARN, "%s%d: CPU TEMP read failed\n", 1427 driver_name, unitp->instance); 1428 return (ENVCTRL_UE250_MAX_CPU_TEMP - 10); 1429 } 1430 1431 return (_cpu_temps[recv_data]); 1432 } 1433 #endif 1434 1435 static void 1436 envctrl_tempr_poll(void *arg) 1437 { 1438 int diag_flag = 0, status; 1439 struct envctrlunit *unitp = (struct envctrlunit *)arg; 1440 1441 mutex_enter(&unitp->umutex); 1442 1443 if (unitp->shutdown == B_TRUE) { 1444 (void) power_down("Fatal System Environmental Control Error"); 1445 } 1446 1447 /* 1448 * Clear the interrupt latches 1449 */ 1450 envctrl_intr_latch_clr(unitp); 1451 1452 envctrl_reset_dflop(unitp); 1453 envctrl_enable_devintrs(unitp); 1454 /* 1455 * if we are in diag mode and the temp poll thread goes off, 1456 * this means that the system is too heavily loaded and the 60 second 1457 * window to execute the test is failing. 1458 */ 1459 if (unitp->current_mode == ENVCTRL_DIAG_MODE) { 1460 diag_flag++; 1461 if (envctrl_debug_flags) { 1462 cmn_err(CE_WARN, "%s%d: " 1463 "Tempr poll went off while in DIAG MODE\n", 1464 driver_name, unitp->instance); 1465 } 1466 } 1467 unitp->current_mode = ENVCTRL_NORMAL_MODE; 1468 DPRINTF1("envctrl_tempr_poll(): Checking system temps\n"); 1469 status = envctrl_check_sys_temperatures(unitp); 1470 if (status == DDI_FAILURE) { 1471 cmn_err(CE_WARN, 1472 "%s%d: Failure detected during temperature poll", 1473 driver_name, unitp->instance); 1474 } 1475 1476 if (diag_flag == 0) { 1477 envctrl_fan_fail_service(unitp); 1478 } 1479 1480 /* Turn of the power fault LED if ps_ok is asserted */ 1481 envctrl_ps_probe(unitp); 1482 1483 /* now have this thread sleep for a while */ 1484 if ((unitp->fan_failed == B_TRUE) || (unitp->tempr_warning == B_TRUE)) { 1485 /* 1486 * A thermal warning or fan failure condition exists. 1487 * Temperature poll thread will run every 10 seconds. 1488 */ 1489 if (unitp->timeout_id != 0) 1490 (void) untimeout(unitp->timeout_id); 1491 unitp->timeout_id = (timeout(envctrl_tempr_poll, 1492 (caddr_t)unitp, warning_timeout_hz)); 1493 } else { 1494 /* 1495 * No thermal warning or fan failure condition exists. 1496 * This thread is set to run every 60 seconds. 1497 */ 1498 unitp->timeout_id = (timeout(envctrl_tempr_poll, 1499 (caddr_t)unitp, overtemp_timeout_hz)); 1500 } 1501 1502 mutex_exit(&unitp->umutex); 1503 } 1504 1505 static void 1506 envctrl_led_blink(void *arg) 1507 { 1508 uint8_t val, tmpval; 1509 int status; 1510 struct envctrlunit *unitp = (struct envctrlunit *)arg; 1511 1512 mutex_enter(&unitp->umutex); 1513 1514 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6, 1515 0, &val, 1); 1516 if (status == DDI_FAILURE) { 1517 cmn_err(CE_WARN, "%s%d: Failed to read FSP LEDs", 1518 driver_name, unitp->instance); 1519 /* now have this thread sleep for a while */ 1520 unitp->blink_timeout_id = (timeout(envctrl_led_blink, 1521 (caddr_t)unitp, blink_timeout_hz)); 1522 mutex_exit(&unitp->umutex); 1523 return; 1524 } 1525 1526 if (unitp->present_led_state == B_TRUE) { 1527 /* 1528 * Now we need to "or" in fault bits of the FSP 1529 * module for the mass storage fault led. 1530 * and set it. 1531 */ 1532 val = (val & ~(EHC_PCF8574_PORT4) | JAV_FSP_MASK); 1533 unitp->present_led_state = B_FALSE; 1534 } else { 1535 val = (val | EHC_PCF8574_PORT4 | JAV_FSP_MASK); 1536 unitp->present_led_state = B_TRUE; 1537 } 1538 1539 /* 1540 * A static global variable, power_flt_led_lit, is used to keep 1541 * track of periods when the software has lit the power fault LED. 1542 * Whenever the power fault LED is lit and this variable is not set, 1543 * then the power fault LED has been lit by hardware. In this case 1544 * mask out the power fault LED in the byte. This is a fix for 1545 * bug 4144872. 1546 */ 1547 tmpval = ~val; 1548 if (tmpval & ENVCTRL_UE250_FSP_PS_ERR) { 1549 if (power_flt_led_lit == 0) { 1550 /* 1551 * Turn off power fault bit in the FSP byte. 1552 */ 1553 tmpval &= ~(ENVCTRL_UE250_FSP_PS_ERR); 1554 } 1555 } 1556 val = ~tmpval; 1557 1558 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6, 1559 0, &val, 1); 1560 if (status == DDI_FAILURE) { 1561 cmn_err(CE_WARN, "%s%d: Failed to blink activity LED", 1562 driver_name, unitp->instance); 1563 /* now have this thread sleep for a while */ 1564 unitp->blink_timeout_id = (timeout(envctrl_led_blink, 1565 (caddr_t)unitp, blink_timeout_hz)); 1566 mutex_exit(&unitp->umutex); 1567 return; 1568 } 1569 1570 /* now have this thread sleep for a while */ 1571 unitp->blink_timeout_id = (timeout(envctrl_led_blink, 1572 (caddr_t)unitp, blink_timeout_hz)); 1573 1574 mutex_exit(&unitp->umutex); 1575 } 1576 1577 static int 1578 envctrl_check_sys_temperatures(struct envctrlunit *unitp) 1579 { 1580 uint8_t buf[8]; 1581 enum levels warning_level, level; 1582 uint8_t fspval; 1583 int status, warning_count = 0; 1584 1585 retrytemp1: 1586 status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, EHC_DEV2, 1587 0, buf, 4); 1588 if (status == DDI_FAILURE) { 1589 cmn_err(CE_WARN, "%s%d: Temperature read failed (PDB)", 1590 driver_name, unitp->instance); 1591 return (status); 1592 } 1593 1594 warning_level = envctrl_check_tempr_levels(unitp, EHC_DEV2, 1595 buf, warning_count); 1596 level = warning_level; 1597 1598 if (warning_level != green) { 1599 if (warning_count == 0) { 1600 warning_count++; 1601 drv_usecwait(1000); 1602 goto retrytemp1; 1603 } 1604 if (warning_level == yellow) 1605 unitp->tempr_warning = B_TRUE; 1606 else if (warning_level == red) { 1607 unitp->tempr_warning = B_TRUE; 1608 if (!envctrl_power_off_overide) 1609 unitp->shutdown = B_TRUE; 1610 } 1611 } 1612 1613 warning_count = 0; 1614 retrytemp2: 1615 status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, EHC_DEV7, 1616 0, buf+4, 4); 1617 if (status == DDI_FAILURE) { 1618 cmn_err(CE_WARN, "%s%d: Temperature read failed (MBD)", 1619 driver_name, unitp->instance); 1620 return (status); 1621 } 1622 1623 warning_level = envctrl_check_tempr_levels(unitp, EHC_DEV7, 1624 buf+4, warning_count); 1625 1626 if (warning_level != green) { 1627 if (warning_count == 0) { 1628 warning_count++; 1629 drv_usecwait(1000); 1630 goto retrytemp2; 1631 } 1632 if ((warning_level == yellow) && (unitp->shutdown == B_FALSE)) 1633 unitp->tempr_warning = B_TRUE; 1634 else if (warning_level == red) { 1635 unitp->tempr_warning = B_TRUE; 1636 if (!envctrl_power_off_overide) 1637 unitp->shutdown = B_TRUE; 1638 } 1639 } else if ((level == green) && (unitp->tempr_warning == B_TRUE)) { 1640 /* 1641 * Current tempr. poll shows all levels normal. 1642 * If the previous poll showed warning levels, we need 1643 * to clear that status 1644 */ 1645 cmn_err(CE_NOTE, 1646 "TEMPERATURE NORMAL: all sensors back to normal readings"); 1647 unitp->tempr_warning = B_FALSE; 1648 } 1649 1650 status = envctrl_get_fpm_status(unitp, &fspval); 1651 if (status == DDI_FAILURE) { 1652 cmn_err(CE_WARN, 1653 "%s%d: Read of Front Status Panel LEDs failed", 1654 driver_name, unitp->instance); 1655 } 1656 1657 if ((unitp->tempr_warning == B_TRUE) || (unitp->shutdown == B_TRUE)) 1658 fspval |= (ENVCTRL_UE250_FSP_TEMP_ERR | 1659 ENVCTRL_UE250_FSP_GEN_ERR); 1660 else { 1661 if (envctrl_isother_fault_led(unitp, fspval, 1662 ENVCTRL_UE250_FSP_TEMP_ERR)) { 1663 fspval &= ~(ENVCTRL_UE250_FSP_TEMP_ERR); 1664 } else { 1665 fspval &= ~(ENVCTRL_UE250_FSP_TEMP_ERR | 1666 ENVCTRL_UE250_FSP_GEN_ERR); 1667 } 1668 } 1669 status = envctrl_set_fsp(unitp, &fspval); 1670 if (status == DDI_FAILURE) { 1671 cmn_err(CE_WARN, 1672 "%s%d: Setting of Front Status Panel LEDs failed", 1673 driver_name, unitp->instance); 1674 } 1675 1676 /* 1677 * Have this thread run again in about 10 seconds 1678 */ 1679 if (unitp->tempr_warning == B_TRUE) { 1680 if (unitp->timeout_id != 0) { 1681 (void) untimeout(unitp->timeout_id); 1682 unitp->timeout_id = (timeout(envctrl_tempr_poll, 1683 (caddr_t)unitp, warning_timeout_hz)); 1684 } 1685 } 1686 1687 return (status); 1688 } 1689 1690 static int 1691 envctrl_check_tempr_levels(struct envctrlunit *unitp, int chip_num, 1692 uint8_t *data, int count) 1693 { 1694 uint_t temp_degree_c; 1695 uint8_t buf[8]; 1696 enum levels warning_level = green; 1697 int i, j; 1698 int status; 1699 uint8_t fanspeed; 1700 int tval; 1701 1702 for (i = 0; i < 4; i++) { 1703 if (chip_num == EHC_DEV2) { 1704 if (i == 1) { 1705 tval = ((int)data[i] * JAV_FAN_SPEED_SF_NUM) / 1706 JAV_FAN_SPEED_SF_DEN; 1707 if (tval > 255) 1708 unitp->fan_kstats.fanspeed = 255; 1709 else 1710 unitp->fan_kstats.fanspeed = tval; 1711 DPRINTF1("device %X, fan = %d %d\n", chip_num, 1712 unitp->fan_kstats.fanspeed, data[i]); 1713 continue; 1714 } else if (i == 2) 1715 continue; 1716 } 1717 if ((chip_num == EHC_DEV7) && ((i == ENVCTRL_UE250_CPU0_PORT) || 1718 (i == ENVCTRL_UE250_CPU1_PORT))) 1719 if (unitp->cpu_pr_location[i] == B_FALSE) 1720 continue; 1721 1722 j = 0; 1723 while ((((t_addr[j] & 0xF) != chip_num) || (t_port[j] != i)) && 1724 (j < unitp->num_temps_present)) 1725 j++; 1726 if ((chip_num == EHC_DEV7) && ((i == ENVCTRL_UE250_CPU0_PORT) || 1727 (i == ENVCTRL_UE250_CPU1_PORT))) 1728 temp_degree_c = _cpu_temps[data[i]]; 1729 else 1730 temp_degree_c = ((int)data[i] * t_scale_num[j]) / 1731 t_scale_den[j]; 1732 1733 /* 1734 * Javelin hardware will not control fan speeds based on 1735 * cpu temperature values because the voltages corresponding 1736 * to the cpu temperatures are based on an inverted scale 1737 * compared to the ambient temperatures and thus can be 1738 * fed to the same fan control circuit. As a result, it 1739 * has been decided that software will control fan speed 1740 * if cpu temperatures rise. 1741 */ 1742 if ((chip_num == EHC_DEV7) && ((i == ENVCTRL_UE250_CPU0_PORT) || 1743 (i == ENVCTRL_UE250_CPU1_PORT)) && 1744 (unitp->current_mode == ENVCTRL_NORMAL_MODE)) { 1745 if (_cpu_fan_speeds[data[ENVCTRL_UE250_CPU0_PORT]] > 1746 _cpu_fan_speeds[data[ENVCTRL_UE250_CPU1_PORT]]) 1747 fanspeed = 1748 _cpu_fan_speeds[data[ENVCTRL_UE250_CPU0_PORT]]; 1749 else 1750 fanspeed = 1751 _cpu_fan_speeds[data[ENVCTRL_UE250_CPU1_PORT]]; 1752 status = envctrl_write_chip(unitp, ENVCTRL_PCF8591, 1753 EHC_DEV2, 0, &fanspeed, 1); 1754 if (status == DDI_FAILURE) 1755 cmn_err(CE_WARN, 1756 "%s%d: Write to PCF8591 (SETFAN) failed\n", 1757 driver_name, unitp->instance); 1758 status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, 1759 EHC_DEV2, 0, buf, 4); 1760 if (status == DDI_FAILURE) 1761 cmn_err(CE_WARN, 1762 "%s%d: Fan speed read failed (PDB)", 1763 driver_name, unitp->instance); 1764 tval = ((int)buf[1] * JAV_FAN_SPEED_SF_NUM) / 1765 JAV_FAN_SPEED_SF_DEN; 1766 if (tval > 255) 1767 unitp->fan_kstats.fanspeed = 255; 1768 else 1769 unitp->fan_kstats.fanspeed = tval; 1770 } 1771 1772 DPRINTF1("device %X, temp = %d %d loc = %s\n", chip_num, 1773 temp_degree_c, data[i], unitp->temp_kstats[j].label); 1774 1775 unitp->temp_kstats[j].value = temp_degree_c; 1776 if ((temp_degree_c >= 1777 unitp->temp_kstats[j].warning_threshold) || 1778 (temp_degree_c < unitp->temp_kstats[j].min)) { 1779 if (warning_level < yellow) 1780 warning_level = yellow; 1781 if (count != 0) 1782 cmn_err(CE_WARN, 1783 "TEMPERATURE WARNING: %d degrees celsius at location %s", 1784 temp_degree_c, unitp->temp_kstats[j].label); 1785 } 1786 if (temp_degree_c >= 1787 unitp->temp_kstats[j].shutdown_threshold) { 1788 if (warning_level < red) 1789 warning_level = red; 1790 if (count != 0) { 1791 cmn_err(CE_WARN, 1792 "TEMPERATURE CRITICAL: %d degrees celsius at location %s", 1793 temp_degree_c, unitp->temp_kstats[j].label); 1794 if (!envctrl_power_off_overide) 1795 cmn_err(CE_WARN, 1796 "System shutdown in 10 seconds ..."); 1797 } 1798 } 1799 } 1800 return (warning_level); 1801 } 1802 1803 static void 1804 envctrl_update_fanspeed(struct envctrlunit *unitp) 1805 { 1806 uint8_t buf[8]; 1807 int tval; 1808 int status; 1809 1810 status = envctrl_read_chip(unitp, ENVCTRL_PCF8591, EHC_DEV2, 1811 0, buf, 4); 1812 if (status == DDI_FAILURE) { 1813 cmn_err(CE_WARN, "%s%d: Fan speed read failed ", 1814 driver_name, unitp->instance); 1815 } 1816 1817 tval = ((int)buf[ENVCTRL_PORT1] * JAV_FAN_SPEED_SF_NUM) / 1818 JAV_FAN_SPEED_SF_DEN; 1819 if (tval > 255) 1820 unitp->fan_kstats.fanspeed = 255; 1821 else 1822 unitp->fan_kstats.fanspeed = tval; 1823 } 1824 1825 /* called with mutex held */ 1826 static void 1827 envctrl_fan_fail_service(struct envctrlunit *unitp) 1828 { 1829 uint8_t recv_data, fpmstat; 1830 int retrys = 0; 1831 int status; 1832 1833 /* 1834 * The fan fail interrupt is read from address 0x70 1835 * on the envctrl bus. 1836 */ 1837 1838 ASSERT(MUTEX_HELD(&unitp->umutex)); 1839 1840 /* 1841 * Clear the interrupt latches to handle spurious interrupts 1842 */ 1843 envctrl_intr_latch_clr(unitp); 1844 1845 do { 1846 status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp, 1847 ENVCTRL_UE250_PCF8574A_BASE_ADDR | EHC_DEV0, 1848 &recv_data, 1); 1849 /* 1850 * This extra read is needed since the first read is discarded 1851 * and the second read seems to return 0xFF. 1852 */ 1853 if (recv_data == 0xFF) { 1854 status = ehc_read_pcf8574a((struct ehc_envcunit *)unitp, 1855 ENVCTRL_UE250_PCF8574A_BASE_ADDR | EHC_DEV0, 1856 &recv_data, 1); 1857 } 1858 1859 if (status == DDI_FAILURE) { 1860 drv_usecwait(1000); 1861 if (retrys < envctrl_max_retries) { 1862 retrys++; 1863 } else { 1864 cmn_err(CE_WARN, 1865 "%s%d: Read of PCF8574A (INTFAN) failed", 1866 driver_name, unitp->instance); 1867 ehc_init_pcf8584((struct ehc_envcunit *)unitp); 1868 return; 1869 } 1870 } 1871 } while (status != DDI_SUCCESS); 1872 1873 /* If the fan fail interrupt is now absent */ 1874 if (recv_data & EHC_PCF8574_PORT4) { 1875 if (unitp->fan_failed == B_TRUE) { 1876 if (unitp->current_mode == ENVCTRL_NORMAL_MODE) 1877 cmn_err(CE_CONT, 1878 "Fan failure has been cleared\n"); 1879 unitp->fan_kstats.fans_ok = B_TRUE; 1880 /* 1881 * Clear general fault LED if no other faults 1882 */ 1883 status = envctrl_get_fpm_status(unitp, &fpmstat); 1884 if (status == DDI_FAILURE) { 1885 cmn_err(CE_WARN, 1886 "%s%d: Read of Front Status Panel LEDs failed", 1887 driver_name, unitp->instance); 1888 } 1889 if (!(envctrl_isother_fault_led(unitp, fpmstat, 0))) { 1890 fpmstat &= ~(ENVCTRL_UE250_FSP_GEN_ERR); 1891 } 1892 if (unitp->shutdown != B_TRUE) { 1893 status = envctrl_set_fsp(unitp, &fpmstat); 1894 if (status == DDI_FAILURE) { 1895 cmn_err(CE_WARN, "%s%d: " 1896 "Setting of Front Status Panel LEDs failed", 1897 driver_name, unitp->instance); 1898 } 1899 } 1900 /* 1901 * This should be set after envctrl_isother_fault_led() 1902 * is called 1903 */ 1904 unitp->fan_failed = B_FALSE; 1905 } 1906 } else { 1907 if (unitp->fan_failed == B_FALSE) { 1908 if (unitp->current_mode == ENVCTRL_NORMAL_MODE) 1909 cmn_err(CE_WARN, 1910 "Fan failure has been detected"); 1911 unitp->fan_failed = B_TRUE; 1912 unitp->fan_kstats.fans_ok = B_FALSE; 1913 /* 1914 * Set general fault LED 1915 */ 1916 status = envctrl_get_fpm_status(unitp, &fpmstat); 1917 if (status == DDI_FAILURE) { 1918 cmn_err(CE_WARN, 1919 "%s%d: Read of Front Status Panel LEDs failed", 1920 driver_name, unitp->instance); 1921 return; 1922 } 1923 fpmstat |= ENVCTRL_UE250_FSP_GEN_ERR; 1924 status = envctrl_set_fsp(unitp, &fpmstat); 1925 if (status == DDI_FAILURE) { 1926 cmn_err(CE_WARN, "%s%d: " 1927 "Setting of Front Status Panel LEDs failed", 1928 driver_name, unitp->instance); 1929 } 1930 /* 1931 * A fan failure condition exists. 1932 * Temperature poll thread should run every 10 seconds. 1933 */ 1934 if (unitp->timeout_id != 0) { 1935 (void) untimeout(unitp->timeout_id); 1936 unitp->timeout_id = (timeout(envctrl_tempr_poll, 1937 (caddr_t)unitp, warning_timeout_hz)); 1938 } 1939 } 1940 } 1941 } 1942 1943 /* 1944 * Check for power supply insertion and failure. 1945 * This is a bit tricky, because a power supply insertion will 1946 * cause the ps_ok line to go active as well as PS present in the 1947 * new supply. If we detect an insertion clear 1948 * interrupts, disable interrupts, wait for a couple of seconds 1949 * come back and see if the PSOK bit is set, PS_PRESENT is set 1950 * and the share fail interrupts are gone. If not this is a 1951 * real load share fail event. 1952 * Called with mutex held 1953 */ 1954 1955 static void 1956 envctrl_PS_intr_service(struct envctrlunit *unitp) 1957 { 1958 1959 ASSERT(MUTEX_HELD(&unitp->umutex)); 1960 1961 if (unitp->current_mode == ENVCTRL_DIAG_MODE) { 1962 return; 1963 } 1964 1965 /* 1966 * setup a timeout thread to poll the ps after a 1967 * couple of seconds. This allows for the PS to settle 1968 * and doesn't report false errors on a hotplug 1969 */ 1970 1971 unitp->pshotplug_id = (timeout(envctrl_pshotplug_poll, 1972 (caddr_t)unitp, pshotplug_timeout_hz)); 1973 1974 } 1975 1976 static void 1977 envctrl_init_bus(struct envctrlunit *unitp) 1978 { 1979 ehc_init_pcf8584((struct ehc_envcunit *)unitp); 1980 1981 /* 1982 * Clear the interrupt latches 1983 */ 1984 envctrl_intr_latch_clr(unitp); 1985 1986 envctrl_reset_dflop(unitp); 1987 1988 envctrl_enable_devintrs(unitp); 1989 } 1990 1991 /* called with mutex held */ 1992 static void 1993 envctrl_reset_dflop(struct envctrlunit *unitp) 1994 { 1995 int status; 1996 uint8_t value; 1997 1998 ASSERT(MUTEX_HELD(&unitp->umutex)); 1999 2000 value = ENVCTRL_UE250_DFLOP_INIT0; 2001 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0, 2002 0, &value, 1); 2003 if (status == DDI_FAILURE) { 2004 cmn_err(CE_WARN, "%s%d: Write to PCF8574A (DFLOP_INIT0) failed", 2005 driver_name, unitp->instance); 2006 } 2007 2008 value = ENVCTRL_UE250_DFLOP_INIT1; 2009 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0, 2010 0, &value, 1); 2011 if (status == DDI_FAILURE) { 2012 cmn_err(CE_WARN, "%s%d: Write to PCF8574A (DFLOP_INIT1) failed", 2013 driver_name, unitp->instance); 2014 } 2015 } 2016 2017 /* called with mutex held */ 2018 static void 2019 envctrl_enable_devintrs(struct envctrlunit *unitp) 2020 { 2021 int status; 2022 uint8_t value; 2023 2024 ASSERT(MUTEX_HELD(&unitp->umutex)); 2025 2026 value = ENVCTRL_UE250_DEVINTR_INIT0; 2027 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0, 2028 0, &value, 1); 2029 if (status == DDI_FAILURE) { 2030 cmn_err(CE_WARN, "%s%d: Write to PCF8574A (INTR_INIT0) failed", 2031 driver_name, unitp->instance); 2032 } 2033 2034 value = ENVCTRL_UE250_DEVINTR_INIT1; 2035 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0, 2036 0, &value, 1); 2037 if (status == DDI_FAILURE) { 2038 cmn_err(CE_WARN, "%s%d: Write to PCF8574A (INTR_INIT1) failed", 2039 driver_name, unitp->instance); 2040 } 2041 } 2042 2043 static void 2044 envctrl_intr_latch_clr(struct envctrlunit *unitp) 2045 { 2046 int status; 2047 uint8_t value; 2048 2049 ASSERT(MUTEX_HELD(&unitp->umutex)); 2050 2051 value = ENVCTRL_UE250_INTR_LATCH_INIT0; 2052 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0, 2053 0, &value, 1); 2054 if (status == DDI_FAILURE) { 2055 cmn_err(CE_WARN, "%s%d: Write to PCF8574A (INTR_LATCH0) failed", 2056 driver_name, unitp->instance); 2057 } 2058 2059 value = ENVCTRL_UE250_INTR_LATCH_INIT1; 2060 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV0, 2061 0, &value, 1); 2062 if (status == DDI_FAILURE) { 2063 cmn_err(CE_WARN, "%s%d: Write to PCF8574A (INTR_LATCH1) failed", 2064 driver_name, unitp->instance); 2065 } 2066 } 2067 2068 /* Called with unitp mutex held */ 2069 static void 2070 envctrl_ps_probe(struct envctrlunit *unitp) 2071 { 2072 2073 uint8_t recv_data, fpmstat; 2074 int i, j; 2075 int ps_error = 0, ps_present_port, power_ok_port; 2076 int status; 2077 2078 2079 ASSERT(MUTEX_HELD(&unitp->umutex)); 2080 2081 unitp->num_ps_present = 0; 2082 2083 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV1, 2084 0, &recv_data, 1); 2085 if (status == DDI_FAILURE) { 2086 cmn_err(CE_WARN, "%s%d: Read of PCF8574 (PS) failed", 2087 driver_name, unitp->instance); 2088 return; 2089 } 2090 2091 for (i = 0, j = 0; i < ENVCTRL_UE250_MAXPS; i++) { 2092 unitp->ps_kstats[i].slot = -1; 2093 2094 /* 2095 * Port 0 = PS0 Present 2096 * Port 1 = PS1 Present 2097 * Port 2 = SPARE 2098 * Port 3 = SPARE 2099 * Port 4 = PS0 OK 2100 * Port 5 = PS1 OK 2101 * Port 6 = SPARE 2102 * Port 7 = SPARE 2103 */ 2104 2105 /* 2106 * Port 0 = PS Present 2107 * Port is pulled LOW "0" to indicate 2108 * present. 2109 */ 2110 2111 switch (i) { 2112 case 0: 2113 ps_present_port = EHC_PCF8574_PORT0; 2114 power_ok_port = EHC_PCF8574_PORT4; 2115 break; 2116 case 1: 2117 ps_present_port = EHC_PCF8574_PORT1; 2118 power_ok_port = EHC_PCF8574_PORT5; 2119 break; 2120 } 2121 2122 if (!(recv_data & ps_present_port)) { 2123 /* update unit kstat array */ 2124 unitp->ps_kstats[j].slot = i; 2125 ++unitp->num_ps_present; 2126 2127 if (pspr[i] == 0) { 2128 cmn_err(CE_NOTE, 2129 "Power Supply %d inserted\n", i); 2130 } 2131 pspr[i] = 1; 2132 2133 if (!(recv_data & power_ok_port)) { 2134 cmn_err(CE_WARN, 2135 "Power Supply %d NOT okay\n", i); 2136 unitp->ps_kstats[j].ps_ok = B_FALSE; 2137 ps_error++; 2138 psok[i] = 0; 2139 } else { 2140 unitp->ps_kstats[j].ps_ok = B_TRUE; 2141 if (psok[i] == 0) 2142 cmn_err(CE_NOTE, 2143 "Power Supply %d okay\n", i); 2144 psok[i] = 1; 2145 } 2146 2147 if (!(recv_data & EHC_PCF8574_PORT2)) { 2148 cmn_err(CE_WARN, 2149 "PS %d Shouln't interrupt\n", i); 2150 ps_error++; 2151 } 2152 2153 if (!(recv_data & EHC_PCF8574_PORT3)) { 2154 cmn_err(CE_WARN, 2155 "PS %d Shouln't interrupt\n", i); 2156 ps_error++; 2157 } 2158 2159 if (!(recv_data & EHC_PCF8574_PORT6)) { 2160 cmn_err(CE_WARN, 2161 "PS %d Shouln't interrupt\n", i); 2162 ps_error++; 2163 } 2164 2165 if (!(recv_data & EHC_PCF8574_PORT7)) { 2166 cmn_err(CE_WARN, 2167 "PS %d Shouln't interrupt\n", i); 2168 ps_error++; 2169 } 2170 j++; 2171 } else { 2172 if (pspr[i] == 1) { 2173 cmn_err(CE_NOTE, 2174 "Power Supply %d removed\n", i); 2175 } 2176 pspr[i] = 0; 2177 } 2178 } 2179 2180 status = envctrl_get_fpm_status(unitp, &fpmstat); 2181 if (status == DDI_FAILURE) { 2182 cmn_err(CE_WARN, "%s%d: Read of Front Status Panel LEDs failed", 2183 driver_name, unitp->instance); 2184 } 2185 if (ps_error) { 2186 fpmstat |= (ENVCTRL_UE250_FSP_PS_ERR | 2187 ENVCTRL_UE250_FSP_GEN_ERR); 2188 } else { 2189 if (envctrl_isother_fault_led(unitp, fpmstat, 2190 ENVCTRL_UE250_FSP_PS_ERR)) { 2191 fpmstat &= ~(ENVCTRL_UE250_FSP_PS_ERR); 2192 } else { 2193 fpmstat &= ~(ENVCTRL_UE250_FSP_PS_ERR | 2194 ENVCTRL_UE250_FSP_GEN_ERR); 2195 } 2196 } 2197 status = envctrl_set_fsp(unitp, &fpmstat); 2198 if (status == DDI_FAILURE) { 2199 cmn_err(CE_WARN, 2200 "%s%d: Setting of Front Status Panel LEDs failed", 2201 driver_name, unitp->instance); 2202 } 2203 2204 if (ps_error) { 2205 power_flt_led_lit = 1; 2206 } else { 2207 power_flt_led_lit = 0; 2208 } 2209 } 2210 2211 /* 2212 * consider key switch position when handling an abort sequence 2213 */ 2214 static void 2215 envctrl_abort_seq_handler(char *msg) 2216 { 2217 struct envctrlunit *unitp; 2218 int i; 2219 uint8_t secure = 0; 2220 2221 /* 2222 * Find the instance of the device available on this host. 2223 * Note that there may be only one, but the instance may 2224 * not be zero. 2225 */ 2226 for (i = 0; i < MAX_DEVS; i++) { 2227 if (unitp = (struct envctrlunit *) 2228 ddi_get_soft_state(envctrlsoft_statep, i)) 2229 break; 2230 } 2231 2232 ASSERT(unitp); 2233 2234 secure = unitp->encl_kstats.value; 2235 2236 if ((secure & ENVCTRL_UE250_FSP_KEYMASK) == 2237 ENVCTRL_UE250_FSP_KEYLOCKED) { 2238 cmn_err(CE_CONT, 2239 "%s%d: ignoring debug enter sequence\n", 2240 driver_name, unitp->instance); 2241 } else { 2242 if (envctrl_debug_flags) { 2243 cmn_err(CE_CONT, "%s%d: allowing debug enter\n", 2244 driver_name, unitp->instance); 2245 } 2246 debug_enter(msg); 2247 } 2248 } 2249 2250 /* 2251 * get the front Panel module LED and keyswitch status. 2252 * this part is addressed at 0x7C on the i2c bus. 2253 * called with mutex held 2254 */ 2255 static int 2256 envctrl_get_fpm_status(struct envctrlunit *unitp, uint8_t *val) 2257 { 2258 uint8_t recv_data; 2259 int status; 2260 2261 ASSERT(MUTEX_HELD(&unitp->umutex)); 2262 2263 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6, 2264 0, &recv_data, 1); 2265 if (status == DDI_FAILURE) { 2266 cmn_err(CE_WARN, "%s%d: Read from PCF8574A (FSP) failed", 2267 driver_name, unitp->instance); 2268 return (status); 2269 } 2270 2271 recv_data = ~recv_data; 2272 if (val != (uint8_t *)NULL) 2273 *val = recv_data; 2274 2275 /* Update kstats */ 2276 unitp->encl_kstats.value = recv_data; 2277 2278 return (status); 2279 } 2280 2281 static int 2282 envctrl_set_fsp(struct envctrlunit *unitp, uint8_t *val) 2283 { 2284 uint8_t value; 2285 int status = DDI_SUCCESS; 2286 uint8_t confirm_val = 0, confirm_val_hold; 2287 int confirm_count = 0, confirm_max = 20; 2288 2289 ASSERT(MUTEX_HELD(&unitp->umutex)); 2290 2291 value = ENVCTRL_UE250_FSP_OFF; /* init all values to off */ 2292 2293 /* 2294 * strip off bits that are R/O 2295 */ 2296 value = (~(ENVCTRL_UE250_FSP_KEYMASK | ENVCTRL_UE250_FSP_POMASK) & 2297 (*val)); 2298 2299 confirm_val_hold = value; 2300 2301 value = ~value; 2302 2303 while (confirm_count < confirm_max) { 2304 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6, 2305 0, &value, 1); 2306 if (status == DDI_FAILURE) { 2307 cmn_err(CE_WARN, "%s%d: Write to PCF8574A (FSP) failed", 2308 driver_name, unitp->instance); 2309 break; 2310 } else { 2311 /* 2312 * Sometimes the i2c hardware status is not 2313 * completely dependable as far as reporting 2314 * a condition where the set does not take 2315 * place. So we read back the set value to 2316 * confirm what we set. 2317 */ 2318 status = envctrl_get_fpm_status(unitp, &confirm_val); 2319 confirm_val = ~(ENVCTRL_UE250_FSP_KEYMASK | 2320 ENVCTRL_UE250_FSP_POMASK) & confirm_val; 2321 if (status == DDI_FAILURE) { 2322 cmn_err(CE_WARN, 2323 "%s%d: Read of PCF8574A (FSP) failed", 2324 driver_name, unitp->instance); 2325 break; 2326 } else if (confirm_val != confirm_val_hold) { 2327 confirm_count++; 2328 drv_usecwait(1000); 2329 continue; 2330 } else 2331 /* 2332 * Set was confirmed. 2333 */ 2334 break; 2335 } 2336 } 2337 2338 if (confirm_count == confirm_max) 2339 status = DDI_FAILURE; 2340 2341 return (status); 2342 2343 } 2344 2345 static int 2346 envctrl_get_dskled(struct envctrlunit *unitp, struct envctrl_chip *chip) 2347 { 2348 int status; 2349 2350 ASSERT(MUTEX_HELD(&unitp->umutex)); 2351 2352 if (chip->chip_num != EHC_DEV7 || 2353 chip->type != ENVCTRL_PCF8574A) { 2354 return (DDI_FAILURE); 2355 } 2356 2357 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV7, 2358 0, &chip->val, 1); 2359 if (status == DDI_FAILURE) { 2360 cmn_err(CE_WARN, "%s%d: Read of PCF8574A (DISKFL) failed", 2361 driver_name, unitp->instance); 2362 } 2363 chip->val = ~chip->val; 2364 2365 return (status); 2366 } 2367 2368 static int 2369 envctrl_set_dskled(struct envctrlunit *unitp, struct envctrl_chip *chip) 2370 { 2371 uint8_t val; 2372 int status; 2373 struct envctrl_chip confirm_chip; 2374 uint8_t confirm_val_hold; 2375 int confirm_count = 0, confirm_max = 20; 2376 2377 /* 2378 * We need to check the type of disk led being set. If it 2379 * is a 4 slot backplane then the upper 4 bits (7, 6, 5, 4) are 2380 * invalid. 2381 */ 2382 ASSERT(MUTEX_HELD(&unitp->umutex)); 2383 2384 2385 if (chip->chip_num != EHC_DEV7) 2386 return (DDI_FAILURE); 2387 2388 if (chip->type != ENVCTRL_PCF8574A) 2389 return (DDI_FAILURE); 2390 2391 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6, 2392 0, &val, 1); 2393 if (status == DDI_FAILURE) { 2394 cmn_err(CE_WARN, "%s%d: Read of PCF8574A (FSP) failed", 2395 driver_name, unitp->instance); 2396 return (status); 2397 } 2398 2399 val = ~val; 2400 if ((chip->val & 0x3F) == 0) { 2401 if (!(envctrl_isother_fault_led(unitp, val, 2402 ENVCTRL_UE250_FSP_DISK_ERR))) { 2403 val &= ~(ENVCTRL_UE250_FSP_DISK_ERR); 2404 } else { 2405 val &= ~(ENVCTRL_UE250_FSP_DISK_ERR | 2406 ENVCTRL_UE250_FSP_GEN_ERR); 2407 } 2408 val = (val & ~(ENVCTRL_UE250_FSP_DISK_ERR | 2409 ENVCTRL_UE250_FSP_GEN_ERR)); 2410 } else { 2411 val = (val | (ENVCTRL_UE250_FSP_DISK_ERR | 2412 ENVCTRL_UE250_FSP_GEN_ERR)); 2413 } 2414 2415 status = envctrl_set_fsp(unitp, &val); 2416 if (status == DDI_FAILURE) { 2417 cmn_err(CE_WARN, "%s%d: Write to PCF8574A (FSP) failed", 2418 driver_name, unitp->instance); 2419 return (status); 2420 } 2421 2422 2423 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV5, 2424 0, &val, 1); 2425 if (status == DDI_FAILURE) { 2426 cmn_err(CE_WARN, "%s%d: Read of PCF8574A (DISKFL) failed", 2427 driver_name, unitp->instance); 2428 return (status); 2429 } 2430 2431 envctrl_update_disk_kstats(unitp, val, ~(chip->val)); 2432 2433 /* 2434 * we take the ones compliment of the val passed in 2435 * because the hardware thinks that a "low" or "0" 2436 * is the way to indicate a fault. of course software 2437 * knows that a 1 is a TRUE state or fault. ;-) 2438 */ 2439 2440 confirm_val_hold = chip->val; 2441 2442 chip->val = ~(chip->val); 2443 2444 while (confirm_count < confirm_max) { 2445 status = envctrl_write_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV7, 2446 0, &chip->val, 1); 2447 if (status == DDI_FAILURE) { 2448 cmn_err(CE_WARN, "%s%d: Write PCF8574A (DISKFL) failed", 2449 driver_name, unitp->instance); 2450 return (status); 2451 } else { 2452 /* 2453 * Sometimes the i2c hardware status is not 2454 * completely dependable as far as reporting 2455 * a condition where the set does not take 2456 * place. So we read back the set value to 2457 * confirm what we set. 2458 */ 2459 confirm_chip.type = chip->type; 2460 confirm_chip.chip_num = chip->chip_num; 2461 confirm_chip.index = chip->index; 2462 status = envctrl_get_dskled(unitp, &confirm_chip); 2463 if (status != DDI_SUCCESS) { 2464 return (status); 2465 } else if (confirm_chip.val != confirm_val_hold) { 2466 confirm_count++; 2467 drv_usecwait(1000); 2468 continue; 2469 } else 2470 /* 2471 * Set was confirmed. 2472 */ 2473 break; 2474 } 2475 } 2476 2477 if (confirm_count == confirm_max) 2478 return (DDI_FAILURE); 2479 2480 return (DDI_SUCCESS); 2481 } 2482 2483 /* 2484 * After setting the fan speed, we read back the fan speed to confirm 2485 * that the new value is within an acceptable range, else we retry. 2486 * We do not confirm the fan speed if the set value is below the 2487 * hardware determined speed (based on system temeratures). 2488 */ 2489 static int 2490 envctrl_set_fanspeed(struct envctrlunit *unitp, struct envctrl_chip *fanspeed) 2491 { 2492 int readback_speed, max_speed; 2493 int status; 2494 int confirm_count = 0, confirm_max = 20; 2495 uint8_t fanspeed_hold; 2496 2497 fanspeed_hold = fanspeed->val; 2498 while (confirm_count < confirm_max) { 2499 status = envctrl_write_chip(unitp, ENVCTRL_PCF8591, 2500 EHC_DEV2, 0, &fanspeed->val, 1); 2501 if (status == DDI_FAILURE) { 2502 envctrl_fan_fail_service(unitp); 2503 cmn_err(CE_WARN, 2504 "%s%d: Set fanspeed failed", driver_name, 2505 unitp->instance); 2506 return (status); 2507 } else { 2508 drv_usecwait(100000); 2509 envctrl_update_fanspeed(unitp); 2510 readback_speed = unitp->fan_kstats.fanspeed; 2511 if (fanspeed_hold > idle_fanspeed) { 2512 max_speed = 2513 (fanspeed->val + FAN_DRIFT > MAX_FAN_SPEED) ? 2514 MAX_FAN_SPEED : (fanspeed->val + FAN_DRIFT); 2515 if ((readback_speed < fanspeed->val - 2516 FAN_DRIFT) || 2517 (readback_speed > max_speed)) { 2518 confirm_count++; 2519 drv_usecwait(1000); 2520 continue; 2521 } 2522 } 2523 break; 2524 } 2525 } 2526 2527 if (confirm_count == confirm_max) 2528 return (DDI_FAILURE); 2529 2530 return (DDI_SUCCESS); 2531 } 2532 2533 static void 2534 envctrl_add_kstats(struct envctrlunit *unitp) 2535 { 2536 2537 ASSERT(MUTEX_HELD(&unitp->umutex)); 2538 2539 if ((unitp->enclksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance, 2540 ENVCTRL_KSTAT_ENCL, "misc", KSTAT_TYPE_RAW, 2541 sizeof (unitp->encl_kstats), 2542 KSTAT_FLAG_PERSISTENT)) == NULL) { 2543 cmn_err(CE_WARN, "%s%d: encl raw kstat_create failed", 2544 driver_name, unitp->instance); 2545 return; 2546 } 2547 2548 unitp->enclksp->ks_update = envctrl_encl_kstat_update; 2549 unitp->enclksp->ks_private = (void *)unitp; 2550 kstat_install(unitp->enclksp); 2551 2552 2553 if ((unitp->fanksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance, 2554 ENVCTRL_KSTAT_FANSTAT, "misc", KSTAT_TYPE_RAW, 2555 sizeof (unitp->fan_kstats), 2556 KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) == NULL) { 2557 cmn_err(CE_WARN, "%s%d: fans kstat_create failed", 2558 driver_name, unitp->instance); 2559 return; 2560 } 2561 2562 unitp->fanksp->ks_update = envctrl_fanstat_kstat_update; 2563 unitp->fanksp->ks_private = (void *)unitp; 2564 kstat_install(unitp->fanksp); 2565 2566 if ((unitp->psksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance, 2567 ENVCTRL_KSTAT_PSNAME2, "misc", KSTAT_TYPE_RAW, 2568 sizeof (unitp->ps_kstats), 2569 KSTAT_FLAG_PERSISTENT)) == NULL) { 2570 cmn_err(CE_WARN, "%s%d: ps name kstat_create failed", 2571 driver_name, unitp->instance); 2572 return; 2573 } 2574 2575 unitp->psksp->ks_update = envctrl_ps_kstat_update; 2576 unitp->psksp->ks_private = (void *)unitp; 2577 kstat_install(unitp->psksp); 2578 2579 if ((unitp->tempksp = kstat_create(ENVCTRL_MODULE_NAME, 2580 unitp->instance, ENVCTRL_KSTAT_TEMPERATURE, "misc", KSTAT_TYPE_RAW, 2581 sizeof (unitp->temp_kstats), 2582 KSTAT_FLAG_PERSISTENT)) == NULL) { 2583 cmn_err(CE_WARN, "%s%d: temp name kstat_create failed", 2584 driver_name, unitp->instance); 2585 return; 2586 } 2587 2588 unitp->tempksp->ks_update = envctrl_temp_kstat_update; 2589 unitp->tempksp->ks_private = (void *)unitp; 2590 kstat_install(unitp->tempksp); 2591 2592 if ((unitp->diskksp = kstat_create(ENVCTRL_MODULE_NAME, 2593 unitp->instance, ENVCTRL_KSTAT_DISK, "misc", KSTAT_TYPE_RAW, 2594 sizeof (unitp->disk_kstats), 2595 KSTAT_FLAG_PERSISTENT)) == NULL) { 2596 cmn_err(CE_WARN, "%s%d: disk name kstat_create failed", 2597 driver_name, unitp->instance); 2598 return; 2599 } 2600 2601 unitp->diskksp->ks_update = envctrl_disk_kstat_update; 2602 unitp->diskksp->ks_private = (void *)unitp; 2603 kstat_install(unitp->diskksp); 2604 2605 } 2606 2607 static int 2608 envctrl_ps_kstat_update(kstat_t *ksp, int rw) 2609 { 2610 struct envctrlunit *unitp; 2611 char *kstatp; 2612 2613 2614 2615 unitp = (struct envctrlunit *)ksp->ks_private; 2616 2617 mutex_enter(&unitp->umutex); 2618 ASSERT(MUTEX_HELD(&unitp->umutex)); 2619 2620 kstatp = (char *)ksp->ks_data; 2621 2622 if (rw == KSTAT_WRITE) { 2623 mutex_exit(&unitp->umutex); 2624 return (EACCES); 2625 } else { 2626 2627 unitp->psksp->ks_ndata = unitp->num_ps_present; 2628 bcopy((caddr_t)&unitp->ps_kstats, kstatp, 2629 sizeof (unitp->ps_kstats)); 2630 } 2631 mutex_exit(&unitp->umutex); 2632 return (DDI_SUCCESS); 2633 } 2634 2635 static int 2636 envctrl_fanstat_kstat_update(kstat_t *ksp, int rw) 2637 { 2638 struct envctrlunit *unitp; 2639 char *kstatp; 2640 2641 kstatp = (char *)ksp->ks_data; 2642 unitp = (struct envctrlunit *)ksp->ks_private; 2643 2644 mutex_enter(&unitp->umutex); 2645 ASSERT(MUTEX_HELD(&unitp->umutex)); 2646 2647 if (rw == KSTAT_WRITE) { 2648 mutex_exit(&unitp->umutex); 2649 return (EACCES); 2650 } else { 2651 unitp->fanksp->ks_ndata = unitp->num_fans_present; 2652 bcopy((caddr_t)&unitp->fan_kstats, kstatp, 2653 sizeof (unitp->fan_kstats)); 2654 } 2655 mutex_exit(&unitp->umutex); 2656 return (DDI_SUCCESS); 2657 } 2658 2659 static int 2660 envctrl_encl_kstat_update(kstat_t *ksp, int rw) 2661 { 2662 struct envctrlunit *unitp; 2663 char *kstatp; 2664 int status; 2665 2666 2667 kstatp = (char *)ksp->ks_data; 2668 unitp = (struct envctrlunit *)ksp->ks_private; 2669 2670 mutex_enter(&unitp->umutex); 2671 ASSERT(MUTEX_HELD(&unitp->umutex)); 2672 2673 if (rw == KSTAT_WRITE) { 2674 mutex_exit(&unitp->umutex); 2675 return (EACCES); 2676 } else { 2677 2678 unitp->enclksp->ks_ndata = unitp->num_encl_present; 2679 status = envctrl_get_fpm_status(unitp, (uint8_t *)NULL); 2680 if (status == DDI_SUCCESS) 2681 bcopy((caddr_t)&unitp->encl_kstats, kstatp, 2682 sizeof (unitp->encl_kstats)); 2683 } 2684 mutex_exit(&unitp->umutex); 2685 return (DDI_SUCCESS); 2686 } 2687 2688 static int 2689 envctrl_temp_kstat_update(kstat_t *ksp, int rw) 2690 { 2691 struct envctrlunit *unitp; 2692 char *kstatp; 2693 2694 kstatp = (char *)ksp->ks_data; 2695 unitp = (struct envctrlunit *)ksp->ks_private; 2696 2697 mutex_enter(&unitp->umutex); 2698 ASSERT(MUTEX_HELD(&unitp->umutex)); 2699 2700 if (rw == KSTAT_WRITE) { 2701 mutex_exit(&unitp->umutex); 2702 return (EACCES); 2703 } else { 2704 unitp->tempksp->ks_ndata = unitp->num_temps_present; 2705 bcopy((caddr_t)unitp->temp_kstats, kstatp, 2706 sizeof (unitp->temp_kstats)); 2707 } 2708 mutex_exit(&unitp->umutex); 2709 return (DDI_SUCCESS); 2710 } 2711 2712 static int 2713 envctrl_disk_kstat_update(kstat_t *ksp, int rw) 2714 { 2715 struct envctrlunit *unitp; 2716 char *kstatp; 2717 2718 kstatp = (char *)ksp->ks_data; 2719 unitp = (struct envctrlunit *)ksp->ks_private; 2720 2721 mutex_enter(&unitp->umutex); 2722 ASSERT(MUTEX_HELD(&unitp->umutex)); 2723 2724 if (rw == KSTAT_WRITE) { 2725 mutex_exit(&unitp->umutex); 2726 return (EACCES); 2727 } else { 2728 unitp->diskksp->ks_ndata = unitp->num_disks_present; 2729 bcopy((caddr_t)unitp->disk_kstats, kstatp, 2730 sizeof (unitp->disk_kstats)); 2731 } 2732 mutex_exit(&unitp->umutex); 2733 return (DDI_SUCCESS); 2734 } 2735 2736 static void 2737 envctrl_init_encl_kstats(struct envctrlunit *unitp) 2738 { 2739 uint8_t val; 2740 int status; 2741 2742 ASSERT(MUTEX_HELD(&unitp->umutex)); 2743 2744 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV6, 2745 0, &val, 1); 2746 if (status == DDI_FAILURE) { 2747 cmn_err(CE_WARN, "%s%d: Read of PCF8574A (FSP) failed", 2748 driver_name, unitp->instance); 2749 return; 2750 } 2751 2752 unitp->encl_kstats.value = val; 2753 } 2754 2755 static void 2756 envctrl_check_disk_kstats(struct envctrlunit *unitp) 2757 { 2758 uint8_t diskpr, diskfl; 2759 int status; 2760 2761 ASSERT(MUTEX_HELD(&unitp->umutex)); 2762 2763 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV5, 2764 0, &diskpr, 1); 2765 if (status == DDI_FAILURE) { 2766 cmn_err(CE_WARN, "%s%d: Read of PCF8574A (DISKPR) failed", 2767 driver_name, unitp->instance); 2768 } 2769 2770 status = envctrl_read_chip(unitp, ENVCTRL_PCF8574A, EHC_DEV7, 2771 0, &diskfl, 1); 2772 if (status == DDI_FAILURE) { 2773 cmn_err(CE_WARN, "%s%d: Read of PCF8574A (DISKFL) failed", 2774 driver_name, unitp->instance); 2775 } 2776 2777 envctrl_update_disk_kstats(unitp, diskpr, diskfl); 2778 2779 } 2780 2781 static void 2782 envctrl_update_disk_kstats(struct envctrlunit *unitp, uint8_t diskpr, 2783 uint8_t diskfl) 2784 { 2785 int i, j, count = 0; 2786 2787 DPRINTF1("diskpr = %X, diskfl = %X\n", diskpr, diskfl); 2788 for (i = 0, j = 1; i < ENVCTRL_UE250_MAX_DISKS; i++, j = j << 1) { 2789 if (!(diskpr & j)) { 2790 if (!(diskfl & j)) 2791 unitp->disk_kstats[count].disk_ok = 0; 2792 else 2793 unitp->disk_kstats[count].disk_ok = 1; 2794 unitp->disk_kstats[count].slot = i; 2795 count++; 2796 } 2797 } 2798 2799 unitp->num_disks_present = count; 2800 } 2801 2802 static void 2803 envctrl_probe_cpus(struct envctrlunit *unitp) 2804 { 2805 int instance; 2806 2807 /* 2808 * The cpu search is as follows: 2809 * If there is only 1 CPU module it is named as 2810 * SUNW,UltraSPARC. If this is a match we still don't 2811 * know what slot the cpu module is in therefore 2812 * we need to check the "upa-portid" property. 2813 * If we have more than 1 cpu, then they are appended by 2814 * instance numbers and slot locations. e.g. 2815 * SUNW,UltraSPARC@1,0 (slot 1). it would have been 2816 * nice to have the naming consistent for one CPU e.g. 2817 * SUNW,UltraSPARC@0,0...sigh 2818 */ 2819 2820 for (instance = 0; instance < ENVCTRL_MAX_CPUS; instance++) { 2821 unitp->cpu_pr_location[instance] = B_FALSE; 2822 } 2823 2824 ddi_walk_devs(ddi_root_node(), envctrl_match_cpu, unitp); 2825 } 2826 2827 static int 2828 envctrl_match_cpu(dev_info_t *dip, void *arg) 2829 { 2830 2831 int cpu_slot; 2832 char name[32]; 2833 char name1[32]; 2834 struct envctrlunit *unitp = (struct envctrlunit *)arg; 2835 2836 (void) sprintf(name, "%s", ENVCTRL_ULTRA1CPU_STRING); 2837 (void) sprintf(name1, "%s", ENVCTRL_ULTRA2CPU_STRING); 2838 2839 if ((strcmp(ddi_node_name(dip), name) == 0) || 2840 (strcmp(ddi_node_name(dip), name1) == 0)) { 2841 if ((cpu_slot = (int)ddi_getprop(DDI_DEV_T_ANY, dip, 2842 DDI_PROP_DONTPASS, "upa-portid", 2843 -1)) == -1) { 2844 cmn_err(CE_WARN, "%s%d: no cpu upa-portid", 2845 driver_name, unitp->instance); 2846 } else { 2847 unitp->cpu_pr_location[cpu_slot] = B_TRUE; 2848 unitp->num_cpus_present++; 2849 } 2850 } 2851 2852 return (DDI_WALK_CONTINUE); 2853 } 2854 2855 /* 2856 * This routine returns TRUE if some other error condition 2857 * has set the GEN_ERR FAULT LED. Tp further complicate this 2858 * LED panel we have overloaded the GEN_ERR LED to indicate 2859 * that a fan fault has occurred without having a fan fault 2860 * LED as does all other error conditions. So we just take the 2861 * software state and return true. The whole purpose of this functon 2862 * is to tell us wehther or not we can shut off the GEN_FAULT LED. 2863 * NOTE: this ledval is usually one of the following FSP vals 2864 * EXCEPT in the case of the fan fail.. we pass in a "0". 2865 */ 2866 2867 static int 2868 envctrl_isother_fault_led(struct envctrlunit *unitp, uint8_t fspval, 2869 uint8_t thisled) 2870 { 2871 int status = B_FALSE; 2872 2873 if (fspval != 0) { 2874 fspval = (fspval & ~(thisled)); 2875 } 2876 if ((unitp->fan_failed == B_TRUE) && thisled != 0) { 2877 status = B_TRUE; 2878 } else if (fspval & ENVCTRL_UE250_FSP_DISK_ERR) { 2879 status = B_TRUE; 2880 } else if (fspval & ENVCTRL_UE250_FSP_PS_ERR) { 2881 status = B_TRUE; 2882 } else if (fspval & ENVCTRL_UE250_FSP_TEMP_ERR) { 2883 status = B_TRUE; 2884 } 2885 return (status); 2886 } 2887 2888 static void 2889 envctrl_pshotplug_poll(void *arg) 2890 { 2891 struct envctrlunit *unitp = (struct envctrlunit *)arg; 2892 2893 mutex_enter(&unitp->umutex); 2894 2895 envctrl_ps_probe(unitp); 2896 2897 mutex_exit(&unitp->umutex); 2898 } 2899