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