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