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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 * ENVCTRLTWO_ Environment Monitoring driver for i2c on Javelin
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/signal.h>
35 #include <sys/errno.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>
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>
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
);
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
);
77 /* Driver private routines */
79 static int envctrl_get_cpu_temp(struct envctrlunit
*, int);
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
*,
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
*,
108 static int envctrl_read_chip(struct envctrlunit
*, int, int, int,
110 static int envctrl_write_chip(struct envctrlunit
*, int, int, int,
112 static int envctrl_check_tempr_levels(struct envctrlunit
*,
113 int, uint8_t *, int);
114 static void envctrl_update_fanspeed(struct envctrlunit
*);
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
*);
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
)();
131 static void *envctrlsoft_statep
;
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
;
140 static int power_flt_led_lit
= 0;
142 extern void pci_thermal_rem_intr(dev_info_t
*, uint_t
);
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
;
157 * Temperature levels :
158 * green = OK - no action needed
159 * yellow = warning - display warning message and poll faster
160 * red = critical - shutdown system
162 enum levels
{green
, yellow
, red
};
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
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
173 #define MAX_FAN_SPEED 255
176 #define ENVCTRL_UE250_INTR_LATCH_INIT0 0xFE
177 #define ENVCTRL_UE250_INTR_LATCH_INIT1 0xFF
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
};
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 */
195 nodev
, /* cb_write */
196 envctrl_ioctl
, /* cb_ioctl */
197 nodev
, /* cb_devmap */
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 */
207 * Declare ops vectors for auto configuration.
209 struct dev_ops envctrltwo_ops
= {
210 DEVO_REV
, /* devo_rev */
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 */
224 extern struct mod_ops mod_driverops
;
226 static struct modldrv envctrlmodldrv
= {
227 &mod_driverops
, /* type of module - driver */
228 "I2C ENVCTRLTWO_driver",
232 static struct modlinkage envctrlmodlinkage
= {
243 if ((error
= mod_install(&envctrlmodlinkage
)) == 0) {
244 (void) ddi_soft_state_init(&envctrlsoft_statep
,
245 sizeof (struct envctrlunit
), 1);
256 if ((error
= mod_remove(&envctrlmodlinkage
)) == 0)
257 ddi_soft_state_fini(&envctrlsoft_statep
);
263 _info(struct modinfo
*modinfop
)
265 return (mod_info(&envctrlmodlinkage
, modinfop
));
269 envctrl_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
271 register int instance
;
274 register struct envctrlunit
*unitp
;
275 struct ddi_device_acc_attr attr
;
281 status
= len
= tblsz
= 0;
283 attr
.devacc_attr_version
= DDI_DEVICE_ATTR_V0
;
284 attr
.devacc_attr_dataorder
= DDI_STRICTORDER_ACC
;
286 attr
.devacc_attr_endian_flags
= DDI_STRUCTURE_LE_ACC
;
288 instance
= ddi_get_instance(dip
);
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
);
301 unitp
->suspended
= 0;
302 unitp
->initting
= B_TRUE
;
303 envctrl_init_bus(unitp
);
304 unitp
->initting
= B_FALSE
;
306 envctrl_ps_probe(unitp
);
307 envctrl_probe_cpus(unitp
);
308 mutex_exit(&unitp
->umutex
);
310 return (DDI_SUCCESS
);
313 return (DDI_FAILURE
);
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);
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.
327 drv_usectohz(ENVCTRL_UE250_OVERTEMP_TIMEOUT_USEC
/ 6);
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
);
335 unitp
= ddi_get_soft_state(envctrlsoft_statep
, instance
);
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
);
346 * If the PCI nexus has added a thermal interrupt, we first need
347 * to remove that interrupt handler.
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.
354 pci_thermal_rem_intr(dip
, (uint_t
)0);
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
);
365 mutex_init(&unitp
->umutex
, NULL
, MUTEX_DRIVER
,
366 (void *)unitp
->ic_trap_cookie
);
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
);
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
);
385 (void) sprintf(name
, "envctrltwo%d", instance
);
387 if (ddi_create_priv_minor_node(dip
, name
, S_IFCHR
, instance
,
388 DDI_PSEUDO
, 0, PRIV_SYS_CONFIG
, PRIV_SYS_CONFIG
, 0666) ==
393 mutex_enter(&unitp
->umutex
);
396 * Javelin will not have a workstation configuration so activity
397 * LED will always blink.
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
;
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;
413 unitp
->num_temps_present
= 6;
414 unitp
->num_fans_present
= 1;
417 mutex_exit(&unitp
->umutex
);
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
) {
422 "%s%d: Unable to read cpu-temp-factors property",
423 ddi_get_name(dip
), instance
);
424 return (DDI_NOT_WELL_FORMED
);
426 tblsz
= (sizeof (_cpu_temps
) / sizeof (uchar_t
));
428 if (len
<= tblsz
&& status
== DDI_PROP_SUCCESS
) {
429 for (i
= 0; i
< len
; i
++) {
430 _cpu_temps
[i
+2] = creg_prop
[i
];
433 _cpu_temps
[0] = _cpu_temps
[1] = _cpu_temps
[2];
435 ddi_prop_free((void *)creg_prop
);
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
) {
440 "%s%d: Unable to read cpu-fan-speeds property",
441 ddi_get_name(dip
), instance
);
442 return (DDI_NOT_WELL_FORMED
);
444 tblsz
= (sizeof (_cpu_fan_speeds
) / sizeof (uchar_t
));
446 if (len
<= tblsz
&& status
== DDI_PROP_SUCCESS
) {
447 for (i
= 0; i
< len
; i
++) {
448 _cpu_fan_speeds
[i
+2] = creg_prop
[i
];
451 _cpu_fan_speeds
[0] = _cpu_fan_speeds
[1] = _cpu_fan_speeds
[2];
453 ddi_prop_free((void *)creg_prop
);
455 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
456 "thermisters", &creg_prop
, &len
) != DDI_PROP_SUCCESS
) {
458 "%s%d: Unable to read thermisters property",
459 ddi_get_name(dip
), instance
);
460 return (DDI_NOT_WELL_FORMED
);
463 mutex_enter(&unitp
->umutex
);
466 for (i
= 0; i
< JAV_MAX_TEMP_SENSORS
; i
++) {
468 unitp
->temp_kstats
[k
].type
= sensor_types
[i
];
470 t_addr
[k
] = creg_prop
[j
] << 24 | creg_prop
[j
+1] << 16 |
471 creg_prop
[j
+2] << 8 | creg_prop
[j
+3];
474 t_port
[k
] = creg_prop
[j
] << 24 | creg_prop
[j
+1] << 16 |
475 creg_prop
[j
+2] << 8 | creg_prop
[j
+3];
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];
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];
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];
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];
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];
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
++;
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
] ==
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 */
522 ddi_prop_free((void *)creg_prop
);
524 /* initialize the envctrl bus controller */
526 unitp
->initting
= B_TRUE
;
527 envctrl_init_bus(unitp
);
528 DPRINTF1("envctrl_attach(): Completed initialization of PCF8584");
529 unitp
->initting
= B_FALSE
;
532 unitp
->timeout_id
= 0;
533 unitp
->blink_timeout_id
= 0;
535 unitp
->fan_failed
= 0;
536 unitp
->fan_kstats
.fans_ok
= B_TRUE
;
537 unitp
->tempr_warning
= 0;
539 envctrl_ps_probe(unitp
);
541 unitp
->initting
= B_TRUE
;
542 envctrl_fan_fail_service(unitp
);
543 unitp
->initting
= B_FALSE
;
546 * Fans could be blasting, turn them down.
549 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8591
, EHC_DEV2
, 0,
551 if (status
== DDI_FAILURE
)
552 cmn_err(CE_WARN
, "%s%d: Write to PCF8591 (SETFAN) failed\n",
553 ddi_get_name(dip
), instance
);
556 * we need to init the fan kstats before the tempr_poll
558 envctrl_add_kstats(unitp
);
559 envctrl_init_encl_kstats(unitp
);
560 envctrl_check_disk_kstats(unitp
);
562 envctrl_update_fanspeed(unitp
);
563 idle_fanspeed
= unitp
->fan_kstats
.fanspeed
;
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
);
571 fspval
= ENVCTRL_UE250_FSP_ACTIVE
;
572 (void) envctrl_set_fsp(unitp
, &fspval
);
575 mutex_exit(&unitp
->umutex
);
577 envctrl_tempr_poll((void *)unitp
);
580 * interpose envctrl's abort sequence handler
582 if (envctrl_handler
) {
583 abort_seq_handler
= envctrl_abort_seq_handler
;
588 return (DDI_SUCCESS
);
591 ddi_remove_intr(dip
, (uint_t
)1, unitp
->ic_trap_cookie
);
593 ddi_remove_intr(dip
, (uint_t
)0, unitp
->ic_trap_cookie
);
596 mutex_destroy(&unitp
->umutex
);
599 if (unitp
->ctlr_handle
)
600 ddi_regs_map_free(&unitp
->ctlr_handle
);
602 cmn_err(CE_WARN
, "%s%d: attach failed\n", ddi_get_name(dip
), instance
);
604 return (DDI_FAILURE
);
609 envctrl_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
612 register struct envctrlunit
*unitp
;
614 instance
= ddi_get_instance(dip
);
615 unitp
= ddi_get_soft_state(envctrlsoft_statep
, instance
);
619 if (envctrl_allow_detach
) {
621 if (unitp
->psksp
!= NULL
) {
622 kstat_delete(unitp
->psksp
);
624 if (unitp
->fanksp
!= NULL
) {
625 kstat_delete(unitp
->fanksp
);
627 if (unitp
->enclksp
!= NULL
) {
628 kstat_delete(unitp
->enclksp
);
630 if (unitp
->tempksp
!= NULL
) {
631 kstat_delete(unitp
->tempksp
);
633 if (unitp
->diskksp
!= NULL
) {
634 kstat_delete(unitp
->diskksp
);
637 if (unitp
->timeout_id
!= 0) {
638 (void) untimeout(unitp
->timeout_id
);
639 unitp
->timeout_id
= 0;
641 if (unitp
->blink_timeout_id
!= 0) {
642 (void) untimeout(unitp
->blink_timeout_id
);
643 unitp
->blink_timeout_id
= 0;
646 ddi_remove_minor_node(dip
, NULL
);
648 ddi_remove_intr(dip
, (uint_t
)0, unitp
->ic_trap_cookie
);
649 ddi_remove_intr(dip
, (uint_t
)1, unitp
->ic_trap_cookie
);
651 ddi_regs_map_free(&unitp
->ctlr_handle
);
653 mutex_destroy(&unitp
->umutex
);
655 return (DDI_SUCCESS
);
657 return (DDI_FAILURE
);
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
);
670 unitp
->suspended
= 1;
671 mutex_exit(&unitp
->umutex
);
672 return (DDI_SUCCESS
);
675 cmn_err(CE_WARN
, "%s%d: suspend general fault\n",
676 ddi_get_name(dip
), instance
);
677 return (DDI_FAILURE
);
683 envctrl_getinfo(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
,
686 dev_t dev
= (dev_t
)arg
;
687 struct envctrlunit
*unitp
;
690 instance
= getminor(dev
);
698 case DDI_INFO_DEVT2DEVINFO
:
699 if ((unitp
= (struct envctrlunit
*)
700 ddi_get_soft_state(envctrlsoft_statep
,
701 instance
)) != NULL
) {
702 *result
= unitp
->dip
;
709 case DDI_INFO_DEVT2INSTANCE
:
710 *result
= (void *)(uintptr_t)instance
;
723 envctrl_open(dev_t
*dev
, int flag
, int otyp
, cred_t
*cred_p
)
725 struct envctrlunit
*unitp
;
727 register int instance
;
729 instance
= getminor(*dev
);
732 unitp
= (struct envctrlunit
*)
733 ddi_get_soft_state(envctrlsoft_statep
, instance
);
738 if (otyp
!= OTYP_CHR
)
741 mutex_enter(&unitp
->umutex
);
744 if ((unitp
->oflag
& FWRITE
)) {
745 mutex_exit(&unitp
->umutex
);
748 unitp
->oflag
|= FWRITE
;
752 mutex_exit(&unitp
->umutex
);
758 envctrl_close(dev_t dev
, int flag
, int otyp
, cred_t
*cred_p
)
760 struct envctrlunit
*unitp
;
761 register int instance
;
763 instance
= getminor(dev
);
766 unitp
= (struct envctrlunit
*)
767 ddi_get_soft_state(envctrlsoft_statep
, instance
);
771 mutex_enter(&unitp
->umutex
);
773 unitp
->oflag
= B_FALSE
;
774 unitp
->current_mode
= ENVCTRL_NORMAL_MODE
;
776 mutex_exit(&unitp
->umutex
);
777 return (DDI_SUCCESS
);
782 * standard put procedure for envctrl
785 envctrl_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int flag
, cred_t
*cred_p
,
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
;
800 instance
= getminor(dev
);
801 unitp
= (struct envctrlunit
*)
802 ddi_get_soft_state(envctrlsoft_statep
, instance
);
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
)
818 case ENVCTRL_IOC_SETMODE
:
820 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&wdval
, sizeof (uint8_t),
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
);
833 (timeout(envctrl_tempr_poll
,
834 (caddr_t
)unitp
, overtemp_timeout_hz
));
836 if (wdval
== ENVCTRL_NORMAL_MODE
) {
838 * Fans could be blasting, turn them down.
841 status
= envctrl_write_chip(unitp
,
842 ENVCTRL_PCF8591
, EHC_DEV2
, 0,
844 if (status
== DDI_FAILURE
)
846 "%s%d: Write to PCF8591 "
847 "(SETMODE) failed\n",
848 driver_name
, unitp
->instance
);
851 * This delay allows the fans to time to
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
;
860 mutex_exit(&unitp
->umutex
);
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
)) {
872 case ENVCTRL_IOC_RESETTMPR
:
874 * For diags, cancel the curent temp poll
875 * and reset it for a new one.
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;
882 envctrl_tempr_poll((void *)unitp
);
887 case ENVCTRL_IOC_GETTEMP2
:
888 /* Get the user buffer address */
890 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&temp
,
891 sizeof (struct envctrl_chip
), flag
)) {
895 if (((temp
.chip_num
!= ENVCTRL_DEV2
) &&
896 (temp
.chip_num
!= ENVCTRL_DEV7
)) ||
897 (temp
.index
> EHC_PCF8591_CH_3
)) {
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
) {
907 "%s%d: Read from PCF8591 (IOC_GETTEMP) failed",
908 driver_name
, unitp
->instance
);
912 if (ddi_copyout((caddr_t
)&temp
, (caddr_t
)arg
,
913 sizeof (struct envctrl_chip
), flag
)) {
917 case ENVCTRL_IOC_SETTEMP
:
920 case ENVCTRL_IOC_SETWDT
:
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
)) {
931 if ((fanspeed
.type
!= ENVCTRL_PCF8591
) ||
932 (fanspeed
.chip_num
!= ENVCTRL_DEV2
) ||
933 (fanspeed
.index
> EHC_PCF8591_CH_3
)) {
937 mutex_enter(&unitp
->umutex
);
938 status
= envctrl_set_fanspeed(unitp
, &fanspeed
);
939 if (status
== DDI_FAILURE
) {
941 "%s%d: Write to PCF8591 "
942 "(IOC_SETFAN) failed",
943 driver_name
, unitp
->instance
);
946 mutex_exit(&unitp
->umutex
);
951 case ENVCTRL_IOC_GETFAN2
:
952 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&a_fanspeed
,
953 sizeof (struct envctrl_chip
), flag
)) {
957 if ((a_fanspeed
.type
!= ENVCTRL_PCF8591
) ||
958 (a_fanspeed
.chip_num
!= ENVCTRL_DEV2
) ||
959 (a_fanspeed
.index
!= EHC_PCF8591_CH_1
)) {
963 mutex_enter(&unitp
->umutex
);
964 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8591
,
965 a_fanspeed
.chip_num
, a_fanspeed
.index
,
967 mutex_exit(&unitp
->umutex
);
968 if (status
== DDI_FAILURE
) {
970 "%s%d: Read of PCF8591 (IOC_GETFAN) failed",
971 driver_name
, unitp
->instance
);
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.
981 if ((tfanspeed
= ((int)a_fanspeed
.val
* JAV_FAN_SPEED_SF_NUM
) /
982 JAV_FAN_SPEED_SF_DEN
) > 255)
983 a_fanspeed
.val
= 255;
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
)) {
992 case ENVCTRL_IOC_SETFSP2
:
993 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&envcchip
,
994 sizeof (struct envctrl_chip
), flag
)) {
998 if ((envcchip
.type
!= ENVCTRL_PCF8574A
) ||
999 (envcchip
.chip_num
!= ENVCTRL_DEV6
)) {
1003 wdval
= envcchip
.val
;
1004 mutex_enter(&unitp
->umutex
);
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
1012 if (unitp
->current_mode
== ENVCTRL_NORMAL_MODE
) {
1013 if (wdval
& ~ENVCTRL_UE250_FSP_USRMASK
) {
1014 mutex_exit(&unitp
->umutex
);
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
) {
1025 "%s%d: Read of PCF8574A (IOC_SETFSP) failed",
1026 driver_name
, unitp
->instance
);
1030 case ENVCTRL_IOC_GETFSP2
:
1031 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&envcchip
,
1032 sizeof (struct envctrl_chip
), flag
)) {
1036 if ((envcchip
.type
!= ENVCTRL_PCF8574A
) ||
1037 (envcchip
.chip_num
!= ENVCTRL_DEV6
)) {
1041 mutex_enter(&unitp
->umutex
);
1042 status
= envctrl_get_fpm_status(unitp
, &wdval
);
1043 mutex_exit(&unitp
->umutex
);
1044 if (status
== DDI_FAILURE
) {
1046 "%s%d: Read of PCF8574A (IOC_GETFSP) failed",
1047 driver_name
, unitp
->instance
);
1050 envcchip
.val
= wdval
;
1051 if (ddi_copyout((caddr_t
)&envcchip
, (caddr_t
)arg
,
1052 sizeof (struct envctrl_chip
), flag
)) {
1057 case ENVCTRL_IOC_SETDSKLED2
:
1058 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&ledchip
,
1059 sizeof (struct envctrl_chip
), flag
)) {
1063 if ((ledchip
.type
!= ENVCTRL_PCF8574A
) ||
1064 (ledchip
.chip_num
!= ENVCTRL_DEV7
)) {
1068 mutex_enter(&unitp
->umutex
);
1069 if (envctrl_set_dskled(unitp
, &ledchip
)) {
1072 mutex_exit(&unitp
->umutex
);
1074 case ENVCTRL_IOC_GETDSKLED2
:
1075 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&ledchip
,
1076 sizeof (struct envctrl_chip
), flag
)) {
1080 if ((ledchip
.type
!= ENVCTRL_PCF8574A
) ||
1081 (ledchip
.chip_num
!= ENVCTRL_DEV7
)) {
1085 mutex_enter(&unitp
->umutex
);
1086 if (envctrl_get_dskled(unitp
, &ledchip
)) {
1089 if (ddi_copyout((caddr_t
)&ledchip
, (caddr_t
)arg
,
1090 sizeof (struct envctrl_chip
), flag
)) {
1094 mutex_exit(&unitp
->umutex
);
1096 case ENVCTRL_IOC_SETRAW
:
1097 if (unitp
->current_mode
!= ENVCTRL_DIAG_MODE
) {
1101 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&temp
,
1102 sizeof (struct envctrl_chip
), flag
)) {
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
) {
1111 "%s%d: Write to chip (IOC_SETRAW) failed",
1112 driver_name
, unitp
->instance
);
1115 mutex_exit(&unitp
->umutex
);
1117 case ENVCTRL_IOC_GETRAW
:
1118 if (ddi_copyin((caddr_t
)arg
, (caddr_t
)&temp
,
1119 sizeof (struct envctrl_chip
), flag
)) {
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
) {
1128 "%s%d: Read of chip (IOC_GETRAW) failed",
1129 driver_name
, unitp
->instance
);
1132 mutex_exit(&unitp
->umutex
);
1133 if (ddi_copyout((caddr_t
)&temp
, (caddr_t
)arg
,
1134 sizeof (struct envctrl_chip
), flag
)) {
1146 envctrl_bus_isr(caddr_t arg
)
1148 struct envctrlunit
*unitp
= (struct envctrlunit
*)(void *)arg
;
1149 int ic
= DDI_INTR_UNCLAIMED
;
1151 mutex_enter(&unitp
->umutex
);
1157 mutex_exit(&unitp
->umutex
);
1162 envctrl_dev_isr(caddr_t arg
)
1164 struct envctrlunit
*unitp
= (struct envctrlunit
*)(void *)arg
;
1169 static int spurious_intr_count
= 0;
1171 ic
= DDI_INTR_UNCLAIMED
;
1173 mutex_enter(&unitp
->umutex
);
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
1183 * -------------------------
1185 * -------------------------
1186 * P7 P6 P5 P4 P3 P2 P1 P0
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
1198 status
= ehc_read_pcf8574a((struct ehc_envcunit
*)unitp
,
1199 ENVCTRL_UE250_PCF8574A_BASE_ADDR
| EHC_DEV0
,
1203 * This extra read is needed since the first read is discarded
1204 * and the second read seems to return 0xFF.
1206 if (recv_data
== 0xFF) {
1207 status
= ehc_read_pcf8574a((struct ehc_envcunit
*)unitp
,
1208 ENVCTRL_UE250_PCF8574A_BASE_ADDR
| EHC_DEV0
,
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
1218 if (status
== DDI_FAILURE
) {
1220 if (retrys
< envctrl_max_retries
) {
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
;
1232 } while (status
!= DDI_SUCCESS
);
1234 DPRINTF1("Interrupt routine called, interrupt = %X\n", recv_data
);
1235 if (!(recv_data
& EHC_PCF8574_PORT0
)) {
1236 ic
= DDI_INTR_CLAIMED
;
1239 if (!(recv_data
& EHC_PCF8574_PORT1
)) {
1240 DPRINTF1("Temperature interrupt detected\n");
1241 (void) envctrl_check_sys_temperatures(unitp
);
1244 * Clear the interrupt latches
1246 envctrl_intr_latch_clr(unitp
);
1248 ic
= DDI_INTR_CLAIMED
;
1251 if (!(recv_data
& EHC_PCF8574_PORT2
)) {
1252 DPRINTF1("Disk interrupt detected\n");
1253 envctrl_check_disk_kstats(unitp
);
1254 ic
= DDI_INTR_CLAIMED
;
1257 if (!(recv_data
& EHC_PCF8574_PORT3
)) {
1258 ic
= DDI_INTR_CLAIMED
;
1261 if (!(recv_data
& EHC_PCF8574_PORT4
)) {
1263 * Check for a fan fail
1265 DPRINTF1("Fan interrupt detected\n");
1266 envctrl_fan_fail_service(unitp
);
1269 * Clear the interrupt latches
1271 envctrl_intr_latch_clr(unitp
);
1273 ic
= DDI_INTR_CLAIMED
;
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
;
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
;
1288 if (!(recv_data
& EHC_PCF8574_PORT7
)) {
1289 ic
= DDI_INTR_CLAIMED
;
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.
1298 if ((recv_data
== 0xFF)) {
1299 if (spurious_intr_count
== 255)
1301 "%s%d: Received 256 spurious interrupts\n",
1302 driver_name
, unitp
->instance
);
1303 spurious_intr_count
++;
1304 ic
= DDI_INTR_CLAIMED
;
1306 spurious_intr_count
= 0;
1308 mutex_exit(&unitp
->umutex
);
1315 envctrl_read_chip(struct envctrlunit
*unitp
, int type
, int chip_num
, int port
,
1316 uint8_t *data
, int num
)
1318 int retrys
= 0, autoincr
= 0;
1322 * If more than one read is requested, set auto-increment bit
1328 if (type
== ENVCTRL_PCF8574A
) {
1329 status
= ehc_read_pcf8574a((struct ehc_envcunit
*)unitp
,
1330 ENVCTRL_UE250_PCF8574A_BASE_ADDR
| chip_num
,
1332 } else if (type
== ENVCTRL_PCF8574
) {
1333 status
= ehc_read_pcf8574((struct ehc_envcunit
*)unitp
,
1334 ENVCTRL_UE250_PCF8574_BASE_ADDR
| chip_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
);
1342 * If the bus hangs, attempt a recovery
1344 if (status
== DDI_FAILURE
) {
1346 if (retrys
< envctrl_max_retries
) {
1349 ehc_init_pcf8584((struct ehc_envcunit
*)unitp
);
1353 } while (status
!= DDI_SUCCESS
);
1359 envctrl_write_chip(struct envctrlunit
*unitp
, int type
, int chip_num
, int port
,
1360 uint8_t *data
, int num
)
1362 int retrys
= 0, autoincr
= 0;
1366 * Incase some applications mistakenly include the chips base addr
1368 chip_num
= chip_num
& 0xF;
1371 * If more than one write is requested, set auto-increment bit
1377 if (type
== ENVCTRL_PCF8574A
) {
1378 status
= ehc_write_pcf8574a(
1379 (struct ehc_envcunit
*)unitp
,
1380 ENVCTRL_UE250_PCF8574A_BASE_ADDR
| chip_num
,
1382 } else if (type
== ENVCTRL_PCF8574
) {
1383 status
= ehc_write_pcf8574((struct ehc_envcunit
*)unitp
,
1384 ENVCTRL_UE250_PCF8574_BASE_ADDR
| chip_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
);
1393 * If the bus hangs, attempt a recovery
1395 if (status
== DDI_FAILURE
) {
1397 if (retrys
< envctrl_max_retries
) {
1400 ehc_init_pcf8584((struct ehc_envcunit
*)unitp
);
1404 } while (status
!= DDI_SUCCESS
);
1411 envctrl_get_cpu_temp(struct envctrlunit
*unitp
, int cpunum
)
1416 ASSERT(MUTEX_HELD(&unitp
->umutex
));
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
1426 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8591
, EHC_DEV7
, cpunum
,
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);
1434 return (_cpu_temps
[recv_data
]);
1439 envctrl_tempr_poll(void *arg
)
1441 int diag_flag
= 0, status
;
1442 struct envctrlunit
*unitp
= (struct envctrlunit
*)arg
;
1444 mutex_enter(&unitp
->umutex
);
1446 if (unitp
->shutdown
== B_TRUE
) {
1447 (void) power_down("Fatal System Environmental Control Error");
1451 * Clear the interrupt latches
1453 envctrl_intr_latch_clr(unitp
);
1455 envctrl_reset_dflop(unitp
);
1456 envctrl_enable_devintrs(unitp
);
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.
1462 if (unitp
->current_mode
== ENVCTRL_DIAG_MODE
) {
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
);
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
) {
1475 "%s%d: Failure detected during temperature poll",
1476 driver_name
, unitp
->instance
);
1479 if (diag_flag
== 0) {
1480 envctrl_fan_fail_service(unitp
);
1483 /* Turn of the power fault LED if ps_ok is asserted */
1484 envctrl_ps_probe(unitp
);
1486 /* now have this thread sleep for a while */
1487 if ((unitp
->fan_failed
== B_TRUE
) || (unitp
->tempr_warning
== B_TRUE
)) {
1489 * A thermal warning or fan failure condition exists.
1490 * Temperature poll thread will run every 10 seconds.
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
));
1498 * No thermal warning or fan failure condition exists.
1499 * This thread is set to run every 60 seconds.
1501 unitp
->timeout_id
= (timeout(envctrl_tempr_poll
,
1502 (caddr_t
)unitp
, overtemp_timeout_hz
));
1505 mutex_exit(&unitp
->umutex
);
1509 envctrl_led_blink(void *arg
)
1511 uint8_t val
, tmpval
;
1513 struct envctrlunit
*unitp
= (struct envctrlunit
*)arg
;
1515 mutex_enter(&unitp
->umutex
);
1517 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV6
,
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
);
1529 if (unitp
->present_led_state
== B_TRUE
) {
1531 * Now we need to "or" in fault bits of the FSP
1532 * module for the mass storage fault led.
1535 val
= (val
& ~(EHC_PCF8574_PORT4
) | JAV_FSP_MASK
);
1536 unitp
->present_led_state
= B_FALSE
;
1538 val
= (val
| EHC_PCF8574_PORT4
| JAV_FSP_MASK
);
1539 unitp
->present_led_state
= B_TRUE
;
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
1551 if (tmpval
& ENVCTRL_UE250_FSP_PS_ERR
) {
1552 if (power_flt_led_lit
== 0) {
1554 * Turn off power fault bit in the FSP byte.
1556 tmpval
&= ~(ENVCTRL_UE250_FSP_PS_ERR
);
1561 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV6
,
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
);
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
));
1577 mutex_exit(&unitp
->umutex
);
1581 envctrl_check_sys_temperatures(struct envctrlunit
*unitp
)
1584 enum levels warning_level
, level
;
1586 int status
, warning_count
= 0;
1589 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8591
, EHC_DEV2
,
1591 if (status
== DDI_FAILURE
) {
1592 cmn_err(CE_WARN
, "%s%d: Temperature read failed (PDB)",
1593 driver_name
, unitp
->instance
);
1597 warning_level
= envctrl_check_tempr_levels(unitp
, EHC_DEV2
,
1598 buf
, warning_count
);
1599 level
= warning_level
;
1601 if (warning_level
!= green
) {
1602 if (warning_count
== 0) {
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
;
1618 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8591
, EHC_DEV7
,
1620 if (status
== DDI_FAILURE
) {
1621 cmn_err(CE_WARN
, "%s%d: Temperature read failed (MBD)",
1622 driver_name
, unitp
->instance
);
1626 warning_level
= envctrl_check_tempr_levels(unitp
, EHC_DEV7
,
1627 buf
+4, warning_count
);
1629 if (warning_level
!= green
) {
1630 if (warning_count
== 0) {
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
;
1642 } else if ((level
== green
) && (unitp
->tempr_warning
== B_TRUE
)) {
1644 * Current tempr. poll shows all levels normal.
1645 * If the previous poll showed warning levels, we need
1646 * to clear that status
1649 "TEMPERATURE NORMAL: all sensors back to normal readings");
1650 unitp
->tempr_warning
= B_FALSE
;
1653 status
= envctrl_get_fpm_status(unitp
, &fspval
);
1654 if (status
== DDI_FAILURE
) {
1656 "%s%d: Read of Front Status Panel LEDs failed",
1657 driver_name
, unitp
->instance
);
1660 if ((unitp
->tempr_warning
== B_TRUE
) || (unitp
->shutdown
== B_TRUE
))
1661 fspval
|= (ENVCTRL_UE250_FSP_TEMP_ERR
|
1662 ENVCTRL_UE250_FSP_GEN_ERR
);
1664 if (envctrl_isother_fault_led(unitp
, fspval
,
1665 ENVCTRL_UE250_FSP_TEMP_ERR
)) {
1666 fspval
&= ~(ENVCTRL_UE250_FSP_TEMP_ERR
);
1668 fspval
&= ~(ENVCTRL_UE250_FSP_TEMP_ERR
|
1669 ENVCTRL_UE250_FSP_GEN_ERR
);
1672 status
= envctrl_set_fsp(unitp
, &fspval
);
1673 if (status
== DDI_FAILURE
) {
1675 "%s%d: Setting of Front Status Panel LEDs failed",
1676 driver_name
, unitp
->instance
);
1680 * Have this thread run again in about 10 seconds
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
));
1694 envctrl_check_tempr_levels(struct envctrlunit
*unitp
, int chip_num
,
1695 uint8_t *data
, int count
)
1697 uint_t temp_degree_c
;
1699 enum levels warning_level
= green
;
1705 for (i
= 0; i
< 4; i
++) {
1706 if (chip_num
== EHC_DEV2
) {
1708 tval
= ((int)data
[i
] * JAV_FAN_SPEED_SF_NUM
) /
1709 JAV_FAN_SPEED_SF_DEN
;
1711 unitp
->fan_kstats
.fanspeed
= 255;
1713 unitp
->fan_kstats
.fanspeed
= tval
;
1714 DPRINTF1("device %X, fan = %d %d\n", chip_num
,
1715 unitp
->fan_kstats
.fanspeed
, data
[i
]);
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
)
1726 while ((((t_addr
[j
] & 0xF) != chip_num
) || (t_port
[j
] != i
)) &&
1727 (j
< unitp
->num_temps_present
))
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
]];
1733 temp_degree_c
= ((int)data
[i
] * t_scale_num
[j
]) /
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.
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
]])
1752 data
[ENVCTRL_UE250_CPU0_PORT
]];
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
)
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
)
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
;
1772 unitp
->fan_kstats
.fanspeed
= 255;
1774 unitp
->fan_kstats
.fanspeed
= tval
;
1777 DPRINTF1("device %X, temp = %d %d loc = %s\n", chip_num
,
1778 temp_degree_c
, data
[i
], unitp
->temp_kstats
[j
].label
);
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
;
1788 "TEMPERATURE WARNING: %d degrees "
1789 "celsius at location %s",
1790 temp_degree_c
, unitp
->temp_kstats
[j
].label
);
1792 if (temp_degree_c
>=
1793 unitp
->temp_kstats
[j
].shutdown_threshold
) {
1794 if (warning_level
< red
)
1795 warning_level
= red
;
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
)
1803 "System shutdown in "
1808 return (warning_level
);
1812 envctrl_update_fanspeed(struct envctrlunit
*unitp
)
1818 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8591
, EHC_DEV2
,
1820 if (status
== DDI_FAILURE
) {
1821 cmn_err(CE_WARN
, "%s%d: Fan speed read failed ",
1822 driver_name
, unitp
->instance
);
1825 tval
= ((int)buf
[ENVCTRL_PORT1
] * JAV_FAN_SPEED_SF_NUM
) /
1826 JAV_FAN_SPEED_SF_DEN
;
1828 unitp
->fan_kstats
.fanspeed
= 255;
1830 unitp
->fan_kstats
.fanspeed
= tval
;
1833 /* called with mutex held */
1835 envctrl_fan_fail_service(struct envctrlunit
*unitp
)
1837 uint8_t recv_data
, fpmstat
;
1842 * The fan fail interrupt is read from address 0x70
1843 * on the envctrl bus.
1846 ASSERT(MUTEX_HELD(&unitp
->umutex
));
1849 * Clear the interrupt latches to handle spurious interrupts
1851 envctrl_intr_latch_clr(unitp
);
1854 status
= ehc_read_pcf8574a((struct ehc_envcunit
*)unitp
,
1855 ENVCTRL_UE250_PCF8574A_BASE_ADDR
| EHC_DEV0
,
1858 * This extra read is needed since the first read is discarded
1859 * and the second read seems to return 0xFF.
1861 if (recv_data
== 0xFF) {
1862 status
= ehc_read_pcf8574a((struct ehc_envcunit
*)unitp
,
1863 ENVCTRL_UE250_PCF8574A_BASE_ADDR
| EHC_DEV0
,
1867 if (status
== DDI_FAILURE
) {
1869 if (retrys
< envctrl_max_retries
) {
1873 "%s%d: Read of PCF8574A (INTFAN) failed",
1874 driver_name
, unitp
->instance
);
1875 ehc_init_pcf8584((struct ehc_envcunit
*)unitp
);
1879 } while (status
!= DDI_SUCCESS
);
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
)
1886 "Fan failure has been cleared\n");
1887 unitp
->fan_kstats
.fans_ok
= B_TRUE
;
1889 * Clear general fault LED if no other faults
1891 status
= envctrl_get_fpm_status(unitp
, &fpmstat
);
1892 if (status
== DDI_FAILURE
) {
1894 "%s%d: Read of Front Status "
1895 "Panel LEDs failed",
1896 driver_name
, unitp
->instance
);
1898 if (!(envctrl_isother_fault_led(unitp
, fpmstat
, 0))) {
1899 fpmstat
&= ~(ENVCTRL_UE250_FSP_GEN_ERR
);
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
);
1911 * This should be set after envctrl_isother_fault_led()
1914 unitp
->fan_failed
= B_FALSE
;
1917 if (unitp
->fan_failed
== B_FALSE
) {
1918 if (unitp
->current_mode
== ENVCTRL_NORMAL_MODE
)
1920 "Fan failure has been detected");
1921 unitp
->fan_failed
= B_TRUE
;
1922 unitp
->fan_kstats
.fans_ok
= B_FALSE
;
1924 * Set general fault LED
1926 status
= envctrl_get_fpm_status(unitp
, &fpmstat
);
1927 if (status
== DDI_FAILURE
) {
1929 "%s%d: Read of Front Status "
1930 "Panel LEDs failed",
1931 driver_name
, unitp
->instance
);
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
);
1942 * A fan failure condition exists.
1943 * Temperature poll thread should run every 10 seconds.
1945 if (unitp
->timeout_id
!= 0) {
1946 (void) untimeout(unitp
->timeout_id
);
1948 (timeout(envctrl_tempr_poll
,
1949 (caddr_t
)unitp
, warning_timeout_hz
));
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
1968 envctrl_PS_intr_service(struct envctrlunit
*unitp
)
1971 ASSERT(MUTEX_HELD(&unitp
->umutex
));
1973 if (unitp
->current_mode
== ENVCTRL_DIAG_MODE
) {
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
1983 unitp
->pshotplug_id
= (timeout(envctrl_pshotplug_poll
,
1984 (caddr_t
)unitp
, pshotplug_timeout_hz
));
1989 envctrl_init_bus(struct envctrlunit
*unitp
)
1991 ehc_init_pcf8584((struct ehc_envcunit
*)unitp
);
1994 * Clear the interrupt latches
1996 envctrl_intr_latch_clr(unitp
);
1998 envctrl_reset_dflop(unitp
);
2000 envctrl_enable_devintrs(unitp
);
2003 /* called with mutex held */
2005 envctrl_reset_dflop(struct envctrlunit
*unitp
)
2010 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2012 value
= ENVCTRL_UE250_DFLOP_INIT0
;
2013 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV0
,
2015 if (status
== DDI_FAILURE
) {
2016 cmn_err(CE_WARN
, "%s%d: Write to PCF8574A (DFLOP_INIT0) failed",
2017 driver_name
, unitp
->instance
);
2020 value
= ENVCTRL_UE250_DFLOP_INIT1
;
2021 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV0
,
2023 if (status
== DDI_FAILURE
) {
2024 cmn_err(CE_WARN
, "%s%d: Write to PCF8574A (DFLOP_INIT1) failed",
2025 driver_name
, unitp
->instance
);
2029 /* called with mutex held */
2031 envctrl_enable_devintrs(struct envctrlunit
*unitp
)
2036 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2038 value
= ENVCTRL_UE250_DEVINTR_INIT0
;
2039 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV0
,
2041 if (status
== DDI_FAILURE
) {
2042 cmn_err(CE_WARN
, "%s%d: Write to PCF8574A (INTR_INIT0) failed",
2043 driver_name
, unitp
->instance
);
2046 value
= ENVCTRL_UE250_DEVINTR_INIT1
;
2047 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV0
,
2049 if (status
== DDI_FAILURE
) {
2050 cmn_err(CE_WARN
, "%s%d: Write to PCF8574A (INTR_INIT1) failed",
2051 driver_name
, unitp
->instance
);
2056 envctrl_intr_latch_clr(struct envctrlunit
*unitp
)
2061 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2063 value
= ENVCTRL_UE250_INTR_LATCH_INIT0
;
2064 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV0
,
2066 if (status
== DDI_FAILURE
) {
2067 cmn_err(CE_WARN
, "%s%d: Write to PCF8574A (INTR_LATCH0) failed",
2068 driver_name
, unitp
->instance
);
2071 value
= ENVCTRL_UE250_INTR_LATCH_INIT1
;
2072 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV0
,
2074 if (status
== DDI_FAILURE
) {
2075 cmn_err(CE_WARN
, "%s%d: Write to PCF8574A (INTR_LATCH1) failed",
2076 driver_name
, unitp
->instance
);
2080 /* Called with unitp mutex held */
2082 envctrl_ps_probe(struct envctrlunit
*unitp
)
2085 uint8_t recv_data
, fpmstat
;
2087 int ps_error
= 0, ps_present_port
, power_ok_port
;
2091 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2093 unitp
->num_ps_present
= 0;
2095 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV1
,
2097 if (status
== DDI_FAILURE
) {
2098 cmn_err(CE_WARN
, "%s%d: Read of PCF8574 (PS) failed",
2099 driver_name
, unitp
->instance
);
2103 for (i
= 0, j
= 0; i
< ENVCTRL_UE250_MAXPS
; i
++) {
2104 unitp
->ps_kstats
[i
].slot
= -1;
2107 * Port 0 = PS0 Present
2108 * Port 1 = PS1 Present
2118 * Port 0 = PS Present
2119 * Port is pulled LOW "0" to indicate
2125 ps_present_port
= EHC_PCF8574_PORT0
;
2126 power_ok_port
= EHC_PCF8574_PORT4
;
2129 ps_present_port
= EHC_PCF8574_PORT1
;
2130 power_ok_port
= EHC_PCF8574_PORT5
;
2134 if (!(recv_data
& ps_present_port
)) {
2135 /* update unit kstat array */
2136 unitp
->ps_kstats
[j
].slot
= i
;
2137 ++unitp
->num_ps_present
;
2141 "Power Supply %d inserted\n", i
);
2145 if (!(recv_data
& power_ok_port
)) {
2147 "Power Supply %d NOT okay\n", i
);
2148 unitp
->ps_kstats
[j
].ps_ok
= B_FALSE
;
2152 unitp
->ps_kstats
[j
].ps_ok
= B_TRUE
;
2155 "Power Supply %d okay\n", i
);
2159 if (!(recv_data
& EHC_PCF8574_PORT2
)) {
2161 "PS %d Shouln't interrupt\n", i
);
2165 if (!(recv_data
& EHC_PCF8574_PORT3
)) {
2167 "PS %d Shouln't interrupt\n", i
);
2171 if (!(recv_data
& EHC_PCF8574_PORT6
)) {
2173 "PS %d Shouln't interrupt\n", i
);
2177 if (!(recv_data
& EHC_PCF8574_PORT7
)) {
2179 "PS %d Shouln't interrupt\n", i
);
2186 "Power Supply %d removed\n", i
);
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
);
2198 fpmstat
|= (ENVCTRL_UE250_FSP_PS_ERR
|
2199 ENVCTRL_UE250_FSP_GEN_ERR
);
2201 if (envctrl_isother_fault_led(unitp
, fpmstat
,
2202 ENVCTRL_UE250_FSP_PS_ERR
)) {
2203 fpmstat
&= ~(ENVCTRL_UE250_FSP_PS_ERR
);
2205 fpmstat
&= ~(ENVCTRL_UE250_FSP_PS_ERR
|
2206 ENVCTRL_UE250_FSP_GEN_ERR
);
2209 status
= envctrl_set_fsp(unitp
, &fpmstat
);
2210 if (status
== DDI_FAILURE
) {
2212 "%s%d: Setting of Front Status Panel LEDs failed",
2213 driver_name
, unitp
->instance
);
2217 power_flt_led_lit
= 1;
2219 power_flt_led_lit
= 0;
2224 * consider key switch position when handling an abort sequence
2227 envctrl_abort_seq_handler(char *msg
)
2229 struct envctrlunit
*unitp
;
2234 * Find the instance of the device available on this host.
2235 * Note that there may be only one, but the instance may
2238 for (i
= 0; i
< MAX_DEVS
; i
++) {
2239 if (unitp
= (struct envctrlunit
*)
2240 ddi_get_soft_state(envctrlsoft_statep
, i
))
2246 secure
= unitp
->encl_kstats
.value
;
2248 if ((secure
& ENVCTRL_UE250_FSP_KEYMASK
) ==
2249 ENVCTRL_UE250_FSP_KEYLOCKED
) {
2251 "%s%d: ignoring debug enter sequence\n",
2252 driver_name
, unitp
->instance
);
2254 if (envctrl_debug_flags
) {
2255 cmn_err(CE_CONT
, "%s%d: allowing debug enter\n",
2256 driver_name
, unitp
->instance
);
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
2268 envctrl_get_fpm_status(struct envctrlunit
*unitp
, uint8_t *val
)
2273 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2275 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV6
,
2277 if (status
== DDI_FAILURE
) {
2278 cmn_err(CE_WARN
, "%s%d: Read from PCF8574A (FSP) failed",
2279 driver_name
, unitp
->instance
);
2283 recv_data
= ~recv_data
;
2284 if (val
!= (uint8_t *)NULL
)
2288 unitp
->encl_kstats
.value
= recv_data
;
2294 envctrl_set_fsp(struct envctrlunit
*unitp
, uint8_t *val
)
2297 int status
= DDI_SUCCESS
;
2298 uint8_t confirm_val
= 0, confirm_val_hold
;
2299 int confirm_count
= 0, confirm_max
= 20;
2301 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2303 value
= ENVCTRL_UE250_FSP_OFF
; /* init all values to off */
2306 * strip off bits that are R/O
2308 value
= (~(ENVCTRL_UE250_FSP_KEYMASK
| ENVCTRL_UE250_FSP_POMASK
) &
2311 confirm_val_hold
= value
;
2315 while (confirm_count
< confirm_max
) {
2316 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV6
,
2318 if (status
== DDI_FAILURE
) {
2319 cmn_err(CE_WARN
, "%s%d: Write to PCF8574A (FSP) failed",
2320 driver_name
, unitp
->instance
);
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.
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
) {
2335 "%s%d: Read of PCF8574A (FSP) failed",
2336 driver_name
, unitp
->instance
);
2338 } else if (confirm_val
!= confirm_val_hold
) {
2344 * Set was confirmed.
2350 if (confirm_count
== confirm_max
)
2351 status
= DDI_FAILURE
;
2358 envctrl_get_dskled(struct envctrlunit
*unitp
, struct envctrl_chip
*chip
)
2362 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2364 if (chip
->chip_num
!= EHC_DEV7
||
2365 chip
->type
!= ENVCTRL_PCF8574A
) {
2366 return (DDI_FAILURE
);
2369 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV7
,
2371 if (status
== DDI_FAILURE
) {
2372 cmn_err(CE_WARN
, "%s%d: Read of PCF8574A (DISKFL) failed",
2373 driver_name
, unitp
->instance
);
2375 chip
->val
= ~chip
->val
;
2381 envctrl_set_dskled(struct envctrlunit
*unitp
, struct envctrl_chip
*chip
)
2385 struct envctrl_chip confirm_chip
;
2386 uint8_t confirm_val_hold
;
2387 int confirm_count
= 0, confirm_max
= 20;
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
2394 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2397 if (chip
->chip_num
!= EHC_DEV7
)
2398 return (DDI_FAILURE
);
2400 if (chip
->type
!= ENVCTRL_PCF8574A
)
2401 return (DDI_FAILURE
);
2403 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV6
,
2405 if (status
== DDI_FAILURE
) {
2406 cmn_err(CE_WARN
, "%s%d: Read of PCF8574A (FSP) failed",
2407 driver_name
, unitp
->instance
);
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
);
2417 val
&= ~(ENVCTRL_UE250_FSP_DISK_ERR
|
2418 ENVCTRL_UE250_FSP_GEN_ERR
);
2420 val
= (val
& ~(ENVCTRL_UE250_FSP_DISK_ERR
|
2421 ENVCTRL_UE250_FSP_GEN_ERR
));
2423 val
= (val
| (ENVCTRL_UE250_FSP_DISK_ERR
|
2424 ENVCTRL_UE250_FSP_GEN_ERR
));
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
);
2435 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV5
,
2437 if (status
== DDI_FAILURE
) {
2438 cmn_err(CE_WARN
, "%s%d: Read of PCF8574A (DISKFL) failed",
2439 driver_name
, unitp
->instance
);
2443 envctrl_update_disk_kstats(unitp
, val
, ~(chip
->val
));
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. ;-)
2452 confirm_val_hold
= chip
->val
;
2454 chip
->val
= ~(chip
->val
);
2456 while (confirm_count
< confirm_max
) {
2457 status
= envctrl_write_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV7
,
2459 if (status
== DDI_FAILURE
) {
2460 cmn_err(CE_WARN
, "%s%d: Write PCF8574A (DISKFL) failed",
2461 driver_name
, unitp
->instance
);
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.
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
) {
2477 } else if (confirm_chip
.val
!= confirm_val_hold
) {
2483 * Set was confirmed.
2489 if (confirm_count
== confirm_max
)
2490 return (DDI_FAILURE
);
2492 return (DDI_SUCCESS
);
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).
2502 envctrl_set_fanspeed(struct envctrlunit
*unitp
, struct envctrl_chip
*fanspeed
)
2504 int readback_speed
, max_speed
;
2506 int confirm_count
= 0, confirm_max
= 20;
2507 uint8_t fanspeed_hold
;
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
);
2516 "%s%d: Set fanspeed failed", driver_name
,
2520 drv_usecwait(100000);
2521 envctrl_update_fanspeed(unitp
);
2522 readback_speed
= unitp
->fan_kstats
.fanspeed
;
2523 if (fanspeed_hold
> idle_fanspeed
) {
2525 (fanspeed
->val
+ FAN_DRIFT
>
2526 MAX_FAN_SPEED
) ? MAX_FAN_SPEED
:
2527 (fanspeed
->val
+ FAN_DRIFT
);
2528 if ((readback_speed
< fanspeed
->val
-
2530 (readback_speed
> max_speed
)) {
2540 if (confirm_count
== confirm_max
)
2541 return (DDI_FAILURE
);
2543 return (DDI_SUCCESS
);
2547 envctrl_add_kstats(struct envctrlunit
*unitp
)
2550 ASSERT(MUTEX_HELD(&unitp
->umutex
));
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
);
2561 unitp
->enclksp
->ks_update
= envctrl_encl_kstat_update
;
2562 unitp
->enclksp
->ks_private
= (void *)unitp
;
2563 kstat_install(unitp
->enclksp
);
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
);
2575 unitp
->fanksp
->ks_update
= envctrl_fanstat_kstat_update
;
2576 unitp
->fanksp
->ks_private
= (void *)unitp
;
2577 kstat_install(unitp
->fanksp
);
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
);
2588 unitp
->psksp
->ks_update
= envctrl_ps_kstat_update
;
2589 unitp
->psksp
->ks_private
= (void *)unitp
;
2590 kstat_install(unitp
->psksp
);
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
);
2601 unitp
->tempksp
->ks_update
= envctrl_temp_kstat_update
;
2602 unitp
->tempksp
->ks_private
= (void *)unitp
;
2603 kstat_install(unitp
->tempksp
);
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
);
2614 unitp
->diskksp
->ks_update
= envctrl_disk_kstat_update
;
2615 unitp
->diskksp
->ks_private
= (void *)unitp
;
2616 kstat_install(unitp
->diskksp
);
2621 envctrl_ps_kstat_update(kstat_t
*ksp
, int rw
)
2623 struct envctrlunit
*unitp
;
2628 unitp
= (struct envctrlunit
*)ksp
->ks_private
;
2630 mutex_enter(&unitp
->umutex
);
2631 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2633 kstatp
= (char *)ksp
->ks_data
;
2635 if (rw
== KSTAT_WRITE
) {
2636 mutex_exit(&unitp
->umutex
);
2640 unitp
->psksp
->ks_ndata
= unitp
->num_ps_present
;
2641 bcopy((caddr_t
)&unitp
->ps_kstats
, kstatp
,
2642 sizeof (unitp
->ps_kstats
));
2644 mutex_exit(&unitp
->umutex
);
2645 return (DDI_SUCCESS
);
2649 envctrl_fanstat_kstat_update(kstat_t
*ksp
, int rw
)
2651 struct envctrlunit
*unitp
;
2654 kstatp
= (char *)ksp
->ks_data
;
2655 unitp
= (struct envctrlunit
*)ksp
->ks_private
;
2657 mutex_enter(&unitp
->umutex
);
2658 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2660 if (rw
== KSTAT_WRITE
) {
2661 mutex_exit(&unitp
->umutex
);
2664 unitp
->fanksp
->ks_ndata
= unitp
->num_fans_present
;
2665 bcopy((caddr_t
)&unitp
->fan_kstats
, kstatp
,
2666 sizeof (unitp
->fan_kstats
));
2668 mutex_exit(&unitp
->umutex
);
2669 return (DDI_SUCCESS
);
2673 envctrl_encl_kstat_update(kstat_t
*ksp
, int rw
)
2675 struct envctrlunit
*unitp
;
2680 kstatp
= (char *)ksp
->ks_data
;
2681 unitp
= (struct envctrlunit
*)ksp
->ks_private
;
2683 mutex_enter(&unitp
->umutex
);
2684 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2686 if (rw
== KSTAT_WRITE
) {
2687 mutex_exit(&unitp
->umutex
);
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
));
2697 mutex_exit(&unitp
->umutex
);
2698 return (DDI_SUCCESS
);
2702 envctrl_temp_kstat_update(kstat_t
*ksp
, int rw
)
2704 struct envctrlunit
*unitp
;
2707 kstatp
= (char *)ksp
->ks_data
;
2708 unitp
= (struct envctrlunit
*)ksp
->ks_private
;
2710 mutex_enter(&unitp
->umutex
);
2711 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2713 if (rw
== KSTAT_WRITE
) {
2714 mutex_exit(&unitp
->umutex
);
2717 unitp
->tempksp
->ks_ndata
= unitp
->num_temps_present
;
2718 bcopy((caddr_t
)unitp
->temp_kstats
, kstatp
,
2719 sizeof (unitp
->temp_kstats
));
2721 mutex_exit(&unitp
->umutex
);
2722 return (DDI_SUCCESS
);
2726 envctrl_disk_kstat_update(kstat_t
*ksp
, int rw
)
2728 struct envctrlunit
*unitp
;
2731 kstatp
= (char *)ksp
->ks_data
;
2732 unitp
= (struct envctrlunit
*)ksp
->ks_private
;
2734 mutex_enter(&unitp
->umutex
);
2735 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2737 if (rw
== KSTAT_WRITE
) {
2738 mutex_exit(&unitp
->umutex
);
2741 unitp
->diskksp
->ks_ndata
= unitp
->num_disks_present
;
2742 bcopy((caddr_t
)unitp
->disk_kstats
, kstatp
,
2743 sizeof (unitp
->disk_kstats
));
2745 mutex_exit(&unitp
->umutex
);
2746 return (DDI_SUCCESS
);
2750 envctrl_init_encl_kstats(struct envctrlunit
*unitp
)
2755 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2757 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV6
,
2759 if (status
== DDI_FAILURE
) {
2760 cmn_err(CE_WARN
, "%s%d: Read of PCF8574A (FSP) failed",
2761 driver_name
, unitp
->instance
);
2765 unitp
->encl_kstats
.value
= val
;
2769 envctrl_check_disk_kstats(struct envctrlunit
*unitp
)
2771 uint8_t diskpr
, diskfl
;
2774 ASSERT(MUTEX_HELD(&unitp
->umutex
));
2776 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV5
,
2778 if (status
== DDI_FAILURE
) {
2779 cmn_err(CE_WARN
, "%s%d: Read of PCF8574A (DISKPR) failed",
2780 driver_name
, unitp
->instance
);
2783 status
= envctrl_read_chip(unitp
, ENVCTRL_PCF8574A
, EHC_DEV7
,
2785 if (status
== DDI_FAILURE
) {
2786 cmn_err(CE_WARN
, "%s%d: Read of PCF8574A (DISKFL) failed",
2787 driver_name
, unitp
->instance
);
2790 envctrl_update_disk_kstats(unitp
, diskpr
, diskfl
);
2795 envctrl_update_disk_kstats(struct envctrlunit
*unitp
, uint8_t diskpr
,
2798 int i
, j
, count
= 0;
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
)) {
2804 unitp
->disk_kstats
[count
].disk_ok
= 0;
2806 unitp
->disk_kstats
[count
].disk_ok
= 1;
2807 unitp
->disk_kstats
[count
].slot
= i
;
2812 unitp
->num_disks_present
= count
;
2816 envctrl_probe_cpus(struct envctrlunit
*unitp
)
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
2833 for (instance
= 0; instance
< ENVCTRL_MAX_CPUS
; instance
++) {
2834 unitp
->cpu_pr_location
[instance
] = B_FALSE
;
2837 ddi_walk_devs(ddi_root_node(), envctrl_match_cpu
, unitp
);
2841 envctrl_match_cpu(dev_info_t
*dip
, void *arg
)
2847 struct envctrlunit
*unitp
= (struct envctrlunit
*)arg
;
2849 (void) sprintf(name
, "%s", ENVCTRL_ULTRA1CPU_STRING
);
2850 (void) sprintf(name1
, "%s", ENVCTRL_ULTRA2CPU_STRING
);
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",
2857 cmn_err(CE_WARN
, "%s%d: no cpu upa-portid",
2858 driver_name
, unitp
->instance
);
2860 unitp
->cpu_pr_location
[cpu_slot
] = B_TRUE
;
2861 unitp
->num_cpus_present
++;
2865 return (DDI_WALK_CONTINUE
);
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".
2881 envctrl_isother_fault_led(struct envctrlunit
*unitp
, uint8_t fspval
,
2884 int status
= B_FALSE
;
2887 fspval
= (fspval
& ~(thisled
));
2889 if ((unitp
->fan_failed
== B_TRUE
) && thisled
!= 0) {
2891 } else if (fspval
& ENVCTRL_UE250_FSP_DISK_ERR
) {
2893 } else if (fspval
& ENVCTRL_UE250_FSP_PS_ERR
) {
2895 } else if (fspval
& ENVCTRL_UE250_FSP_TEMP_ERR
) {
2902 envctrl_pshotplug_poll(void *arg
)
2904 struct envctrlunit
*unitp
= (struct envctrlunit
*)arg
;
2906 mutex_enter(&unitp
->umutex
);
2908 envctrl_ps_probe(unitp
);
2910 mutex_exit(&unitp
->umutex
);