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