envctrl.c revision 1341:6d7c4f090a72
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 * ENVCTRL_ Environment Monitoring driver for i2c
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.h>	/* Environment header */
61
62/* driver entry point fn definitions */
63static int 	envctrl_open(queue_t *, dev_t *, int, int, cred_t *);
64static int	envctrl_close(queue_t *, int, cred_t *);
65static uint_t 	envctrl_bus_isr(caddr_t);
66static uint_t 	envctrl_dev_isr(caddr_t);
67
68/* configuration entry point fn definitions */
69static int 	envctrl_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
70static int	envctrl_attach(dev_info_t *, ddi_attach_cmd_t);
71static int	envctrl_detach(dev_info_t *, ddi_detach_cmd_t);
72
73/* Driver private routines */
74static void	envctrl_init_bus(struct envctrlunit *);
75static int	envctrl_xmit(struct envctrlunit *, caddr_t *, int);
76static void	envctrl_recv(struct envctrlunit *, caddr_t *, int);
77static void	envctrl_get_sys_temperatures(struct envctrlunit *, uint8_t *);
78static int	envctrl_get_lm75_temp(struct envctrlunit *);
79static int	envctrl_get_ps_temp(struct envctrlunit *, uint8_t);
80static int	envctrl_get_cpu_temp(struct envctrlunit *, int);
81static void	envctrl_fan_fail_service(struct envctrlunit *);
82static void	envctrl_PS_intr_service(struct envctrlunit *, uint8_t);
83static void	envctrl_ps_probe(struct envctrlunit *);
84static void	envctrl_tempr_poll(void *);
85static void	envctrl_pshotplug_poll(void *);
86static void	envctrl_led_blink(void *);
87static void	envctrl_reset_dflop(struct envctrlunit *);
88static void	envctrl_enable_devintrs(struct envctrlunit *);
89static void	envctrl_stop_clock(struct envctrlunit *);
90static void	envctrl_reset_watchdog(struct envctrlunit *, uint8_t *);
91static void	envctrl_abort_seq_handler(char *msg);
92static uint8_t	envctrl_get_fpm_status(struct envctrlunit *);
93static void	envctrl_set_fsp(struct envctrlunit *, uint8_t *);
94static int	envctrl_set_dskled(struct envctrlunit *,
95				struct envctrl_pcf8574_chip *);
96static int	envctrl_get_dskled(struct envctrlunit *,
97				struct envctrl_pcf8574_chip *);
98static void	envctrl_probe_cpus(struct envctrlunit *);
99static int	envctrl_match_cpu(dev_info_t *, void *);
100static int	envctrl_isother_fault_led(struct envctrlunit *,
101		    uint8_t, uint8_t);
102
103/* Kstat routines */
104static void	envctrl_add_kstats(struct envctrlunit *);
105static int	envctrl_ps_kstat_update(kstat_t *, int);
106static int	envctrl_fanstat_kstat_update(kstat_t *, int);
107static int	envctrl_encl_kstat_update(kstat_t *, int);
108static void	envctrl_init_fan_kstats(struct envctrlunit *);
109static void	envctrl_init_encl_kstats(struct envctrlunit *);
110static void	envctrl_add_encl_kstats(struct envctrlunit *, int, int,
111			uint8_t);
112static void	envctrl_mod_encl_kstats(struct envctrlunit *, int, int,
113			uint8_t);
114
115
116/* Streams Routines */
117static int	envctrl_wput(queue_t *, mblk_t *);
118
119/* External routines */
120extern void power_down(const char *);
121extern int prom_getprop();
122extern int prom_getproplen();
123extern	void	prom_printf(const char *fmt, ...);
124extern void (*abort_seq_handler)();
125
126static void    *envctrlsoft_statep;
127
128/* Local Variables */
129/* Indicates whether or not the overtemp thread has been started */
130static int	envctrl_debug_flags = 0;
131static int	envctrl_afb_present = 0;
132static int	envctrl_power_off_overide = 0;
133static int	envctrl_max_retries = 100;
134static int	envctrl_allow_detach = 0;
135static int	envctrl_numcpus = 1;
136static int	envctrl_p0_enclosure = 0; /* set to 1 if it is a P0 */
137static int envctrl_handler = 1; /* 1 is the default */
138static clock_t overtemp_timeout_hz;
139static clock_t blink_timeout_hz;
140static clock_t pshotplug_timeout_hz;
141static int controller_present[] = {-1, -1, -1};
142#ifdef MULTIFAN
143static int	envctrl_fan_debug = 0;
144#endif
145static int 	eHc_debug = 0;
146static int	power_supply_previous_state[] = {-1, -1, -1};
147
148extern void	pci_thermal_rem_intr(dev_info_t *, uint_t);
149
150#define	LOOP_TIMEOUT 25
151#define	INIT_FAN_VAL 35
152#define	DCMNERR if (eHc_debug & 0x1) cmn_err
153#define	DCMN2ERR if (eHc_debug & 0x2) cmn_err
154#define	MAX_FAN_FAIL_RETRY 3
155
156uint8_t backaddrs[] = {ENVCTRL_PCF8574_DEV0, ENVCTRL_PCF8574_DEV1,
157    ENVCTRL_PCF8574_DEV2};
158
159struct module_info envctrlinfo = {
160	/* id, name, min pkt siz, max pkt siz, hi water, low water */
161	42, "envctrl", 0, 2048, (1024 * 20), (1024 * 1)
162};
163
164static struct qinit envctrl_rinit = {
165	putq, NULL, envctrl_open, envctrl_close, NULL, &envctrlinfo, NULL
166};
167
168static struct qinit envctrl_wint = {
169	envctrl_wput, NULL, envctrl_open, envctrl_close,
170	    NULL, &envctrlinfo, NULL
171};
172
173struct streamtab envctrl_str_info = {
174	&envctrl_rinit, &envctrl_wint, NULL, NULL
175};
176
177static struct cb_ops envctrl_cb_ops = {
178	nodev,			/* cb_open */
179	nodev,			/* cb_close */
180	nodev,			/* cb_strategy */
181	nodev,			/* cb_print */
182	nodev,			/* cb_dump */
183	nodev,			/* cb_read */
184	nodev,			/* cb_write */
185	nodev,			/* cb_ioctl */
186	nodev,			/* cb_devmap */
187	nodev,			/* cb_mmap */
188	nodev,			/* cb_segmap */
189	nochpoll,		/* cb_chpoll */
190	ddi_prop_op,		/* cb_prop_op */
191	&envctrl_str_info,	/* cb_stream */
192	D_MP			/* cb_flag */
193};
194
195/*
196 * Declare ops vectors for auto configuration.
197 */
198struct dev_ops  envctrl_ops = {
199	DEVO_REV,		/* devo_rev */
200	0,			/* devo_refcnt */
201	envctrl_getinfo,	/* devo_getinfo */
202	nulldev,		/* devo_identify */
203	nulldev,		/* devo_probe */
204	envctrl_attach,		/* devo_attach */
205	envctrl_detach,		/* devo_detach */
206	nodev,			/* devo_reset */
207	&envctrl_cb_ops,	/* devo_cb_ops */
208	(struct bus_ops *)NULL,	/* devo_bus_ops */
209	nulldev			/* devo_power */
210};
211
212extern struct mod_ops mod_driverops;
213
214static struct modldrv envctrlmodldrv = {
215	&mod_driverops,		/* type of module - driver */
216	"I2C ENVCTRL_driver: %I% %E%",
217	&envctrl_ops,
218};
219
220static struct modlinkage envctrlmodlinkage = {
221	MODREV_1,
222	&envctrlmodldrv,
223	0
224};
225
226/*
227 * The following defines are for the i2c protocol routines.
228 * This section of defines should be removed once the envctrl_targets.c
229 * file is included.
230 */
231
232#define	EHC_SUCCESS 0
233#define	EHC_FAILURE (-1)
234#define	EHC_NO_SLAVE_ACK 3
235
236#define	EHC_MAX_WAIT 7 /* decimal */
237
238#define	EHC_S1_PIN 0x80
239#define	EHC_S1_ES1 0x20
240#define	EHC_S1_ES0 0x40
241#define	EHC_S1_NBB 0x01
242#define	EHC_S1_ACK 0x01
243#define	EHC_S1_STA 0x04
244#define	EHC_S1_STO 0x02
245#define	EHC_S1_LRB 0x08
246#define	EHC_S1_BER 0x10
247#define	EHC_S1_LAB 0x02
248
249#define	EHC_S0_OWN 0x55
250#define	EHC_S0_CLK 0x1c
251
252#define	EHC_BYTE_READ 0x01
253
254#define	EHC_LONGEST_MSG 1000 /* decimal */
255
256/*
257 * PCF8591 Chip Used for temperature sensors
258 *
259 * Addressing Register definition.
260 * A0-A2 valid range is 0-7
261 *
262 *  7    6  5   4    3     2     1      0
263 * ------------------------------------------------
264 * | 1 | 0 | 0 | 1 | A2 | A1 | A0 | R/W |
265 * ------------------------------------------------
266 */
267
268
269#define	EHC_PCF8591_MAX_DEVS	0x08
270
271#define	EHC_DEV0	0x00
272#define	EHC_DEV1	0x02
273#define	EHC_DEV2	0x04
274#define	EHC_DEV3	0x06
275#define	EHC_DEV4	0x08
276#define	EHC_DEV5	0x0A
277#define	EHC_DEV6    	0x0C
278#define	EHC_DEV7	0x0E
279
280
281/*
282 * 		CONTROL OF CHIP
283 * PCF8591 Temp sensing control register definitions
284 *
285 *   7      6     5   4  3   2      1   0
286 * ---------------------------------------------
287 * | 0 | AOE | X | X | 0 | AIF | X | X |
288 * ---------------------------------------------
289 * AOE = Analog out enable.. not used on out implementation
290 * 5 & 4 = Analog Input Programming.. see data sheet for bits..
291 *
292 * AIF = Auto increment flag
293 * bits 1 & 0 are for the Chennel number.
294 */
295
296#define	EHC_PCF8591_ANALOG_OUTPUT_EN	0x40
297#define	EHC_PCF8591_ANALOG_INPUT_EN	0x00
298#define	EHC_PCF8591_READ_BIT		0x01
299
300
301#define	EHC_PCF8591_AUTO_INCR 0x04
302#define	EHC_PCF8591_OSCILATOR 0x40
303
304#define	EHC_PCF8591_MAX_PORTS	0x04
305
306#define	EHC_PCF8591_CH_0	0x00
307#define	EHC_PCF8591_CH_1	0x01
308#define	EHC_PCF8591_CH_2	0x02
309#define	EHC_PCF8591_CH_3	0x03
310
311
312/*
313 * PCF8574 Fan Fail, Power Supply Fail Detector
314 * This device is driven by interrupts. Each time it interrupts
315 * you must look at the CSR to see which ports caused the interrupt
316 * they are indicated by a 1.
317 *
318 * Address map of this chip
319 *
320 * -------------------------------------------
321 * | 0 | 1 | 1 | 1 | A2 | A1 | A0 | 0 |
322 * -------------------------------------------
323 *
324 */
325
326#define	EHC_PCF8574_PORT0	0x01
327#define	EHC_PCF8574_PORT1	0x02
328#define	EHC_PCF8574_PORT2	0x04
329#define	EHC_PCF8574_PORT3	0x08
330#define	EHC_PCF8574_PORT4	0x10
331#define	EHC_PCF8574_PORT5	0x20
332#define	EHC_PCF8574_PORT6	0x40
333#define	EHC_PCF8574_PORT7	0x80
334
335/*
336 * Defines for the PCF8583 Clock Calendar Chip.
337 */
338#define	EHC_PCF8583_READ_BIT	0x01
339#define	ALARM_CTR_REG_MINS	0x03
340#define	ALARM_REG_MINS		0x0B
341#define	ALARM_TIMER_REG		0x0F
342
343struct eHc_pcd8584_regs {
344	uint8_t s0;		/* Own Address S0' */
345	uint8_t s1;		/* Control Status register */
346	uint8_t clock_s2;	/* Clock programming register */
347};
348
349struct eHc_envcunit {
350	struct eHc_pcd8584_regs *bus_ctl_regs;
351	ddi_acc_handle_t ctlr_handle;
352	kmutex_t umutex;
353};
354
355
356/*
357 * Prototypes for static routines
358 */
359
360static int eHc_write_tda8444(struct eHc_envcunit *, int, int, int, uint8_t *,
361	int);
362static int eHc_read_pcf8591(struct eHc_envcunit *, int, int, int, int, int,
363	uint8_t *, int);
364static int eHc_read_pcf8574a(struct eHc_envcunit *, int, uint8_t *, int);
365static int eHc_write_pcf8574a(struct eHc_envcunit *, int, uint8_t *, int);
366static int eHc_read_pcf8574(struct eHc_envcunit *, int, uint8_t *, int);
367static int eHc_write_pcf8574(struct eHc_envcunit *, int, uint8_t *, int);
368static int eHc_read_lm75(struct eHc_envcunit *, int, uint8_t *, int);
369static int eHc_write_pcf8583(struct eHc_envcunit *, int, uint8_t *, int);
370
371static int eHc_start_pcf8584(struct eHc_envcunit *, uint8_t);
372static void eHc_stop_pcf8584(struct eHc_envcunit *);
373static int eHc_read_pcf8584(struct eHc_envcunit *, uint8_t *);
374static int eHc_write_pcf8584(struct eHc_envcunit *, uint8_t);
375static int eHc_after_read_pcf8584(struct eHc_envcunit *, uint8_t *);
376
377/*
378 * End of i2c protocol definitions section
379 */
380
381int
382_init(void)
383{
384	int    error;
385
386	if ((error = mod_install(&envctrlmodlinkage)) == 0) {
387		(void) ddi_soft_state_init(&envctrlsoft_statep,
388			sizeof (struct envctrlunit), 1);
389	}
390
391	return (error);
392}
393
394int
395_fini(void)
396{
397	int    error;
398
399	if ((error = mod_remove(&envctrlmodlinkage)) == 0)
400		ddi_soft_state_fini(&envctrlsoft_statep);
401
402	return (error);
403}
404
405int
406_info(struct modinfo *modinfop)
407{
408	return (mod_info(&envctrlmodlinkage, modinfop));
409}
410
411static int
412envctrl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
413{
414	int	instance;
415	char		name[16];
416	uint8_t fspval;
417	struct	envctrlunit *unitp;
418	struct ddi_device_acc_attr attr;
419	int *reg_prop;
420	uchar_t *creg_prop;
421	uint_t len, tblsz;
422	int i, cputemp, status;
423	uint8_t buf[3];
424
425	status = len = tblsz = 0;
426
427	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
428	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
429
430	attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
431
432	instance = ddi_get_instance(dip);
433
434	switch (cmd) {
435	case DDI_ATTACH:
436		break;
437	case DDI_RESUME:
438		if (!(unitp = ddi_get_soft_state(envctrlsoft_statep, instance)))
439			return (DDI_FAILURE);
440		mutex_enter(&unitp->umutex);
441		if (!unitp->suspended) {
442			mutex_exit(&unitp->umutex);
443			return (DDI_FAILURE);
444		}
445		unitp->suspended = 0;
446		mutex_exit(&unitp->umutex);
447		unitp->initting = B_TRUE;
448		envctrl_init_bus(unitp);
449		unitp->initting = B_FALSE;
450
451		mutex_enter(&unitp->umutex);
452		envctrl_ps_probe(unitp);
453		envctrl_probe_cpus(unitp);
454		mutex_exit(&unitp->umutex);
455
456		return (DDI_SUCCESS);
457
458	default:
459		return (DDI_FAILURE);
460	}
461
462	/* Set up timer values */
463	overtemp_timeout_hz = drv_usectohz(OVERTEMP_TIMEOUT_USEC);
464	blink_timeout_hz = drv_usectohz(BLINK_TIMEOUT_USEC);
465	pshotplug_timeout_hz = drv_usectohz(BLINK_TIMEOUT_USEC * 6);
466
467	if (ddi_soft_state_zalloc(envctrlsoft_statep, instance) != 0) {
468		cmn_err(CE_WARN, "envctrl failed to zalloc softstate\n");
469		goto failed;
470	}
471
472	unitp = ddi_get_soft_state(envctrlsoft_statep, instance);
473
474	if (ddi_regs_map_setup(dip, 0, (caddr_t *)&unitp->bus_ctl_regs, 0,
475			sizeof (struct envctrl_pcd8584_regs), &attr,
476			&unitp->ctlr_handle) != DDI_SUCCESS) {
477		cmn_err(CE_WARN, "I2c failed to map in bus_control regs\n");
478		return (DDI_FAILURE);
479	}
480
481	/*
482	 * If the PCI nexus has added a thermal interrupt, we first need
483	 * to remove that interrupt handler.
484	 *
485	 * WARNING: Removing another driver's interrupt handler is not
486	 * allowed. The pci_thermal_rem_intr() call below is needed to retain
487	 * the legacy behavior on Tazmo systems.
488	 */
489
490	pci_thermal_rem_intr(dip, (uint_t)0);
491
492	/* add interrupts */
493
494	if (ddi_get_iblock_cookie(dip, 1,
495			&unitp->ic_trap_cookie) != DDI_SUCCESS)  {
496		cmn_err(CE_WARN, "ddi_get_iblock_cookie FAILED \n");
497		goto failed;
498	}
499
500	mutex_init(&unitp->umutex, NULL, MUTEX_DRIVER,
501		(void *)unitp->ic_trap_cookie);
502
503
504	if (ddi_add_intr(dip, 0, &unitp->ic_trap_cookie, NULL, envctrl_bus_isr,
505			(caddr_t)unitp) != DDI_SUCCESS) {
506		cmn_err(CE_WARN, "envctrl_attach failed to add hard intr %d\n",
507			instance);
508		goto remlock;
509	}
510
511
512	if (ddi_add_intr(dip, 1, &unitp->ic_trap_cookie, NULL, envctrl_dev_isr,
513			(caddr_t)unitp) != DDI_SUCCESS) {
514		cmn_err(CE_WARN, "envctrl_attach failed to add hard intr %d\n",
515			instance);
516		goto remhardintr;
517	}
518
519
520	(void) sprintf(name, "envctrl%d", instance);
521
522	if (ddi_create_minor_node(dip, name, S_IFCHR, instance, DDI_PSEUDO,
523			NULL) == DDI_FAILURE) {
524		ddi_remove_minor_node(dip, NULL);
525		goto remhardintr1;
526	}
527
528	mutex_enter(&unitp->umutex);
529	switch (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
530	    ENVCTRL_LED_BLINK, -1)) {
531	case 1:
532		unitp->activity_led_blink = B_TRUE;
533		break;
534	case 0:
535	default:
536		unitp->activity_led_blink = B_FALSE;
537		break;
538	}
539	unitp->shutdown = B_FALSE;
540	unitp->num_ps_present = unitp->num_encl_present = 0;
541	unitp->num_fans_present = MIN_FAN_BANKS;
542	unitp->num_fans_failed = ENVCTRL_CHAR_ZERO;
543	unitp->AFB_present = B_TRUE;
544	unitp->dip = dip;
545
546#ifdef	DEBUG
547	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
548			DDI_PROP_DONTPASS, ENVCTRL_PANEL_LEDS_PR,
549			&reg_prop, &len) == DDI_PROP_SUCCESS)
550		ddi_prop_free((void *)reg_prop);
551	ASSERT(len != 0);
552
553	len = 0;
554
555	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
556			DDI_PROP_DONTPASS, ENVCTRL_PANEL_LEDS_STA,
557			&reg_prop, &len) == DDI_PROP_SUCCESS)
558		ddi_prop_free((void *)reg_prop);
559	ASSERT(len != 0);
560
561	len = 0;
562
563	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
564			DDI_PROP_DONTPASS, ENVCTRL_DISK_LEDS_STA,
565			&reg_prop, &len) == DDI_PROP_SUCCESS)
566		ddi_prop_free((void *)reg_prop);
567	ASSERT(len != 0);
568#endif	/* DEBUG */
569
570	/*
571	 * if we have prom fan tables, overide the static tables in
572	 * header file.
573	 */
574
575	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip,
576			DDI_PROP_DONTPASS, "cpu-fan-speeds",
577			&creg_prop, &len) == DDI_PROP_SUCCESS) {
578
579		tblsz = (sizeof (acme_cpu_fanspd) / sizeof (short));
580
581		if (len <= tblsz) {
582			for (i = 0; i < len; i++) {
583				acme_cpu_fanspd[i] = creg_prop[i];
584			}
585		}
586		ddi_prop_free((void *)creg_prop);
587	}
588
589	len = 0;
590
591	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip,
592			DDI_PROP_DONTPASS, "ps-fan-speeds",
593			&creg_prop, &len) == DDI_PROP_SUCCESS) {
594
595		tblsz = (sizeof (acme_ps_fanspd) / sizeof (short));
596
597		if (len <= tblsz) {
598			for (i = 0; i < len; i++) {
599				acme_ps_fanspd[i] = creg_prop[i];
600			}
601		}
602		ddi_prop_free((void *)creg_prop);
603	}
604
605	switch (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
606	    "fan-override", -1)) {
607	case 1:
608	case 2:
609		unitp->AFB_present = B_TRUE;
610		break;
611	case 0:
612	default:
613		unitp->AFB_present = B_FALSE;
614		break;
615	}
616
617	/* For debug */
618	if (envctrl_afb_present) {
619		unitp->AFB_present = B_TRUE;
620	}
621
622	if (unitp->AFB_present == B_TRUE)
623		unitp->num_fans_present++;
624
625	/* initialize the envctrl bus controller */
626	mutex_exit(&unitp->umutex);
627
628	unitp->initting = B_TRUE;
629	envctrl_init_bus(unitp);
630	unitp->initting = B_FALSE;
631	drv_usecwait(1000);
632
633	mutex_enter(&unitp->umutex);
634
635	/* Initialize the PCF8583 eggtimer registers */
636	buf[0] = ALARM_CTR_REG_MINS;
637	buf[1] = 0x0;
638	status = eHc_write_pcf8583((struct eHc_envcunit *)unitp,
639			PCF8583_BASE_ADDR | 0, buf, 2);
640	if (status != DDI_SUCCESS)
641		cmn_err(CE_WARN, "write to PCF8583 failed\n");
642
643	buf[0] = ALARM_REG_MINS;
644	buf[1] = 0x58;
645	status = eHc_write_pcf8583((struct eHc_envcunit *)unitp,
646			PCF8583_BASE_ADDR | 0, buf, 2);
647	if (status != DDI_SUCCESS)
648		cmn_err(CE_WARN, "write to PCF8583 failed\n");
649
650	buf[0] = ALARM_TIMER_REG;
651	buf[1] = 0x80;
652	status = eHc_write_pcf8583((struct eHc_envcunit *)unitp,
653			PCF8583_BASE_ADDR | 0, buf, 2);
654	if (status != DDI_SUCCESS)
655		cmn_err(CE_WARN, "write to PCF8583 failed\n");
656
657	unitp->timeout_id = 0;
658	unitp->blink_timeout_id = 0;
659
660	if (envctrl_numcpus > 1) {
661		unitp->num_cpus_present = envctrl_numcpus;
662	}
663	envctrl_probe_cpus(unitp);
664	envctrl_ps_probe(unitp);
665	/*
666	 * clear the fan failures, if any before we do
667	 * real work
668	 */
669
670	unitp->initting = B_TRUE;
671	envctrl_fan_fail_service(unitp);
672	unitp->initting = B_FALSE;
673
674	/*
675	 * we need to init the fan kstats before the tempr_poll
676	 */
677	envctrl_add_kstats(unitp);
678	envctrl_init_fan_kstats(unitp);
679	envctrl_init_encl_kstats(unitp);
680	if (unitp->activity_led_blink == B_TRUE) {
681		unitp->present_led_state = B_FALSE;
682		mutex_exit(&unitp->umutex);
683		envctrl_led_blink((void *)unitp);
684		mutex_enter(&unitp->umutex);
685	} else {
686		fspval = ENVCTRL_FSP_ACTIVE;
687		envctrl_set_fsp(unitp, &fspval);
688	}
689
690#ifndef TESTBED
691	for (i = 0; i < ENVCTRL_MAX_CPUS; i++) {
692		if (unitp->cpu_pr_location[i] == B_TRUE) {
693			cputemp = envctrl_get_cpu_temp(unitp, i);
694			envctrl_add_encl_kstats(unitp, ENVCTRL_ENCL_CPUTEMPR,
695			    i, cputemp);
696			if (cputemp >= MAX_CPU_TEMP) {
697				if (!(envctrl_power_off_overide)) {
698					cmn_err(CE_WARN,
699					    "CPU %d OVERHEATING!!", i);
700					unitp->shutdown = B_TRUE;
701				} else {
702					cmn_err(CE_WARN,
703					    "CPU %d OVERHEATING!!", i);
704				}
705			}
706		}
707	}
708#else
709	cputemp = envctrl_get_cpu_temp(unitp, 0);
710	envctrl_add_encl_kstats(unitp, ENVCTRL_ENCL_CPUTEMPR, INSTANCE_0,
711	    cputemp);
712#endif
713	mutex_exit(&unitp->umutex);
714
715	envctrl_tempr_poll((void *)unitp);
716
717	/*
718	 * interpose envctrl's abort sequence handler
719	 */
720	if (envctrl_handler) {
721		abort_seq_handler = envctrl_abort_seq_handler;
722	}
723
724	ddi_report_dev(dip);
725
726	return (DDI_SUCCESS);
727
728remhardintr1:
729	ddi_remove_intr(dip, (uint_t)1, unitp->ic_trap_cookie);
730remhardintr:
731	ddi_remove_intr(dip, (uint_t)0, unitp->ic_trap_cookie);
732
733remlock:
734	mutex_destroy(&unitp->umutex);
735
736failed:
737	if (unitp->ctlr_handle)
738		ddi_regs_map_free(&unitp->ctlr_handle);
739
740	cmn_err(CE_WARN, "envctrl_attach:failed.\n");
741
742	return (DDI_FAILURE);
743
744}
745
746static int
747envctrl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
748{
749	int		instance;
750	struct envctrlunit *unitp;
751
752	instance = ddi_get_instance(dip);
753	unitp = ddi_get_soft_state(envctrlsoft_statep, instance);
754
755	switch (cmd) {
756	case DDI_DETACH:
757		if (envctrl_allow_detach) {
758
759			if (unitp->psksp != NULL) {
760				kstat_delete(unitp->psksp);
761			}
762			if (unitp->fanksp != NULL) {
763				kstat_delete(unitp->fanksp);
764			}
765			if (unitp->enclksp != NULL) {
766				kstat_delete(unitp->enclksp);
767			}
768
769			if (unitp->timeout_id != 0) {
770				(void) untimeout(unitp->timeout_id);
771				unitp->timeout_id = 0;
772			}
773			if (unitp->blink_timeout_id != 0) {
774				(void) untimeout(unitp->blink_timeout_id);
775				unitp->blink_timeout_id = 0;
776			}
777
778			ddi_remove_minor_node(dip, NULL);
779
780			ddi_remove_intr(dip, (uint_t)0, unitp->ic_trap_cookie);
781			ddi_remove_intr(dip, (uint_t)1, unitp->ic_trap_cookie);
782
783			ddi_regs_map_free(&unitp->ctlr_handle);
784
785			mutex_destroy(&unitp->umutex);
786
787			return (DDI_SUCCESS);
788		} else {
789			return (DDI_FAILURE);
790		}
791
792	case DDI_SUSPEND:
793		if (!(unitp = ddi_get_soft_state(envctrlsoft_statep, instance)))
794		    return (DDI_FAILURE);
795		mutex_enter(&unitp->umutex);
796		if (unitp->suspended) {
797			cmn_err(CE_WARN, "envctrl already suspended\n");
798			mutex_exit(&unitp->umutex);
799			return (DDI_FAILURE);
800		}
801		unitp->suspended = 1;
802		mutex_exit(&unitp->umutex);
803		return (DDI_SUCCESS);
804
805	default:
806		cmn_err(CE_WARN, "envctrl suspend general fault\n");
807		return (DDI_FAILURE);
808	}
809
810
811}
812
813/* ARGSUSED */
814int
815envctrl_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
816    void **result)
817{
818	dev_t	dev = (dev_t)arg;
819	struct envctrlunit *unitp;
820	int	ret;
821	minor_t instance = getminor(dev);
822
823	switch (infocmd) {
824		case DDI_INFO_DEVT2DEVINFO:
825			if ((unitp = (struct envctrlunit *)
826				ddi_get_soft_state(envctrlsoft_statep,
827				    instance)) != NULL) {
828				*result = unitp->dip;
829				ret = DDI_SUCCESS;
830			} else {
831				*result = NULL;
832				ret = DDI_FAILURE;
833			}
834			break;
835		case DDI_INFO_DEVT2INSTANCE:
836			*result = (void *)(uintptr_t)instance;
837			ret = DDI_SUCCESS;
838			break;
839		default:
840			ret = DDI_FAILURE;
841			break;
842	}
843
844	return (ret);
845}
846
847/* ARGSUSED */
848static int
849envctrl_open(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *credp)
850{
851	struct envctrlunit *unitp;
852	int status = 0;
853	int	instance;
854
855	instance = getminor(*dev);
856	if (instance < 0)
857		return (ENXIO);
858	unitp = (struct envctrlunit *)
859		    ddi_get_soft_state(envctrlsoft_statep, instance);
860
861	if (unitp == NULL)
862		return (ENXIO);
863
864	mutex_enter(&unitp->umutex);
865
866	if (flag & FWRITE) {
867		if ((unitp->oflag & FWRITE)) {
868			mutex_exit(&unitp->umutex);
869			return (EBUSY);
870		} else {
871			unitp->oflag |= FWRITE;
872		}
873	}
874
875	q->q_ptr = WR(q)->q_ptr = (caddr_t)unitp;
876
877	/*
878	 * if device is open with O_NONBLOCK flag set, let read(2) return 0
879	 * if no data waiting to be read.  Writes will block on flow control.
880	 */
881
882	/* enable the stream */
883	qprocson(q);
884
885	unitp->readq = RD(q);
886	unitp->writeq = WR(q);
887	unitp->msg = (mblk_t *)NULL;
888
889	mutex_exit(&unitp->umutex);
890	return (status);
891}
892
893/* ARGSUSED */
894static int
895envctrl_close(queue_t *q, int flag, cred_t *cred_p)
896{
897	struct envctrlunit *unitp;
898
899	unitp = (struct envctrlunit *)q->q_ptr;
900
901	mutex_enter(&unitp->umutex);
902
903	unitp->oflag = B_FALSE;
904	unitp->current_mode = ENVCTRL_NORMAL_MODE;
905
906	/* disable the stream */
907	q->q_ptr = WR(q)->q_ptr = NULL;
908	qprocsoff(q);
909
910	mutex_exit(&unitp->umutex);
911	return (DDI_SUCCESS);
912}
913
914/*
915 * standard put procedure for envctrl
916 */
917static int
918envctrl_wput(queue_t *q, mblk_t *mp)
919{
920	struct msgb *mp1;
921	struct envctrlunit *unitp;
922	struct iocblk *iocp;
923	struct copyresp *csp;
924	struct envctrl_tda8444t_chip *fanspeed;
925	struct envctrl_pcf8574_chip *ledchip;
926	struct envctrl_pcf8591_chip *temp, *a_fanspeed;
927	struct copyreq *cqp;
928	int cmd;
929
930	unitp = (struct envctrlunit *)q->q_ptr;
931
932	switch (DB_TYPE(mp)) {
933
934	case M_DATA:
935
936		while (mp) {
937			DB_TYPE(mp) = M_DATA;
938			mp1 = unlinkb(mp);
939			mp->b_cont = NULL;
940			if ((mp->b_wptr - mp->b_rptr) <= 0) {
941				freemsg(mp);
942			} else {
943				(void) putq(q, mp);
944			}
945			mp = mp1;
946		}
947
948		break;
949
950	case M_IOCTL:
951	{
952		iocp = (struct iocblk *)(void *)mp->b_rptr;
953		cmd = iocp->ioc_cmd;
954
955		switch (cmd) {
956		case ENVCTRL_IOC_SETMODE:
957		case ENVCTRL_IOC_GETMODE:
958			if (iocp->ioc_count == TRANSPARENT) {
959				mcopyin(mp, *(caddr_t *)mp->b_cont->b_rptr,
960				    sizeof (uchar_t), NULL);
961				qreply(q, mp);
962			} else {
963				miocnak(q, mp, 0, EINVAL);
964			}
965			break;
966		case ENVCTRL_IOC_RESETTMPR:
967			/*
968			 * For diags, cancel the current temp poll
969			 * and reset it for a new one.
970			 */
971			if (unitp->current_mode == ENVCTRL_DIAG_MODE) {
972				if (unitp->timeout_id != 0) {
973					(void) untimeout(unitp->timeout_id);
974					unitp->timeout_id = 0;
975				}
976				envctrl_tempr_poll((void *)unitp);
977				miocack(q, mp, 0, 0);
978			} else {
979				miocnak(q, mp, 0, EINVAL);
980			}
981			break;
982		case ENVCTRL_IOC_GETTEMP:
983			if (iocp->ioc_count == TRANSPARENT) {
984				mcopyin(mp, *(caddr_t *)mp->b_cont->b_rptr,
985				    sizeof (struct envctrl_pcf8591_chip), NULL);
986				qreply(q, mp);
987			} else {
988				miocnak(q, mp, 0, EINVAL);
989			}
990			break;
991		case ENVCTRL_IOC_SETTEMP:
992			if (unitp->current_mode == ENVCTRL_DIAG_MODE &&
993			    iocp->ioc_count == TRANSPARENT) {
994				mcopyin(mp, *(caddr_t *)mp->b_cont->b_rptr,
995				    sizeof (uint8_t), NULL);
996				qreply(q, mp);
997			} else {
998				miocnak(q, mp, 0, EINVAL);
999			}
1000			break;
1001		case ENVCTRL_IOC_SETWDT:
1002			if (unitp->current_mode == ENVCTRL_DIAG_MODE &&
1003			    iocp->ioc_count == TRANSPARENT) {
1004				mcopyin(mp, *(caddr_t *)mp->b_cont->b_rptr,
1005				    sizeof (uint8_t), NULL);
1006				qreply(q, mp);
1007			} else {
1008				miocnak(q, mp, 0, EINVAL);
1009			}
1010			break;
1011		case ENVCTRL_IOC_SETFAN:
1012			/*
1013			 * we must be in diag mode before we can
1014			 * set any fan speeds.
1015			 */
1016			if (unitp->current_mode == ENVCTRL_DIAG_MODE &&
1017			    iocp->ioc_count == TRANSPARENT) {
1018				mcopyin(mp, *(caddr_t *)mp->b_cont->b_rptr,
1019				    sizeof (struct envctrl_tda8444t_chip),
1020				    NULL);
1021				qreply(q, mp);
1022			} else {
1023				miocnak(q, mp, 0, EINVAL);
1024			}
1025			break;
1026		case ENVCTRL_IOC_GETFAN:
1027			if (iocp->ioc_count == TRANSPARENT) {
1028				mcopyin(mp, *(caddr_t *)mp->b_cont->b_rptr,
1029				    sizeof (struct envctrl_pcf8591_chip), NULL);
1030				qreply(q, mp);
1031			} else {
1032				miocnak(q, mp, 0, EINVAL);
1033			}
1034			break;
1035		case ENVCTRL_IOC_SETFSP:
1036			if (iocp->ioc_count == TRANSPARENT) {
1037				mcopyin(mp, *(caddr_t *)mp->b_cont->b_rptr,
1038				    sizeof (uint8_t), NULL);
1039				qreply(q, mp);
1040			} else {
1041				miocnak(q, mp, 0, EINVAL);
1042			}
1043			break;
1044		case ENVCTRL_IOC_SETDSKLED:
1045		case ENVCTRL_IOC_GETDSKLED:
1046			if (iocp->ioc_count == TRANSPARENT) {
1047				mcopyin(mp, *(caddr_t *)mp->b_cont->b_rptr,
1048				    sizeof (struct envctrl_pcf8574_chip), NULL);
1049				qreply(q, mp);
1050			} else {
1051				miocnak(q, mp, 0, EINVAL);
1052			}
1053			break;
1054		default:
1055			miocnak(q, mp, 0, EINVAL);
1056			break;
1057		}
1058
1059		break;
1060
1061	}
1062	case M_IOCDATA:
1063	{
1064		uint8_t *tempr, *wdval;
1065		long state;
1066
1067		csp = (struct copyresp *)(void *)mp->b_rptr;
1068
1069		/*
1070		 * If copy request failed, quit now
1071		 */
1072		if (csp->cp_rval != 0) {
1073			miocnak(q, mp, 0, EINVAL);
1074			return (0);
1075		}
1076
1077		cqp = (struct copyreq *)(void *)mp->b_rptr;
1078
1079		cmd = csp->cp_cmd;
1080		state = (long)cqp->cq_private;
1081
1082		switch (cmd) {
1083		case ENVCTRL_IOC_SETFAN:
1084			fanspeed = (struct envctrl_tda8444t_chip *)
1085			    (void *)mp->b_cont->b_rptr;
1086			mutex_enter(&unitp->umutex);
1087			if (envctrl_xmit(unitp, (caddr_t *)(void *)fanspeed,
1088			    fanspeed->type) == DDI_FAILURE) {
1089				/*
1090				 * Fix for a ADF bug
1091				 * move mutex to after fan fail call
1092				 * bugid 4016121
1093				 */
1094				envctrl_fan_fail_service(unitp);
1095				mutex_exit(&unitp->umutex);
1096				miocnak(q, mp, 0, EINVAL);
1097			} else {
1098				mutex_exit(&unitp->umutex);
1099				miocack(q, mp, 0, 0);
1100			}
1101			break;
1102		case ENVCTRL_IOC_SETFSP:
1103			wdval = (uint8_t *)(void *)mp->b_cont->b_rptr;
1104			mutex_enter(&unitp->umutex);
1105			/*
1106			 * If a user is in normal mode and they try
1107			 * to set anything other than a disk fault or
1108			 * a gen fault it is an invalid operation.
1109			 * in diag mode we allow everything to be
1110			 * twiddled.
1111			 */
1112			if (unitp->current_mode == ENVCTRL_NORMAL_MODE) {
1113				if (*wdval & ~ENVCTRL_FSP_USRMASK) {
1114					mutex_exit(&unitp->umutex);
1115					miocnak(q, mp, 0, EINVAL);
1116					break;
1117				}
1118			}
1119			envctrl_set_fsp(unitp, wdval);
1120			mutex_exit(&unitp->umutex);
1121			miocack(q, mp, 0, 0);
1122			break;
1123		case ENVCTRL_IOC_SETDSKLED:
1124			ledchip = (struct envctrl_pcf8574_chip *)
1125			    (void *)mp->b_cont->b_rptr;
1126			mutex_enter(&unitp->umutex);
1127			if (envctrl_set_dskled(unitp, ledchip)) {
1128				miocnak(q, mp, 0, EINVAL);
1129			} else {
1130				miocack(q, mp, 0, 0);
1131			}
1132			mutex_exit(&unitp->umutex);
1133			break;
1134		case ENVCTRL_IOC_GETDSKLED:
1135			if (state  == -1) {
1136				miocack(q, mp, 0, 0);
1137				break;
1138			}
1139			ledchip = (struct envctrl_pcf8574_chip *)
1140			    (void *)mp->b_cont->b_rptr;
1141			mutex_enter(&unitp->umutex);
1142			if (envctrl_get_dskled(unitp, ledchip)) {
1143				miocnak(q, mp, 0, EINVAL);
1144			} else {
1145				mcopyout(mp, (void *)-1,
1146				    sizeof (struct envctrl_pcf8574_chip),
1147				    csp->cp_private, NULL);
1148				qreply(q, mp);
1149			}
1150			mutex_exit(&unitp->umutex);
1151			break;
1152		case ENVCTRL_IOC_GETTEMP:
1153			/* Get the user buffer address */
1154
1155			if (state  == -1) {
1156				miocack(q, mp, 0, 0);
1157				break;
1158			}
1159			temp = (struct envctrl_pcf8591_chip *)
1160			    (void *)mp->b_cont->b_rptr;
1161			mutex_enter(&unitp->umutex);
1162			envctrl_recv(unitp, (caddr_t *)(void *)temp, PCF8591);
1163			mutex_exit(&unitp->umutex);
1164			mcopyout(mp, (void *)-1,
1165			    sizeof (struct envctrl_pcf8591_chip),
1166			    csp->cp_private, NULL);
1167			qreply(q, mp);
1168			break;
1169		case ENVCTRL_IOC_GETFAN:
1170			/* Get the user buffer address */
1171
1172			if (state == -1) {
1173				miocack(q, mp, 0, 0);
1174				break;
1175			}
1176			a_fanspeed = (struct envctrl_pcf8591_chip *)
1177			    (void *)mp->b_cont->b_rptr;
1178			mutex_enter(&unitp->umutex);
1179			envctrl_recv(unitp, (caddr_t *)(void *)a_fanspeed,
1180				PCF8591);
1181			mutex_exit(&unitp->umutex);
1182			mcopyout(mp, (void *)-1,
1183			    sizeof (struct envctrl_pcf8591_chip),
1184			    csp->cp_private, NULL);
1185			qreply(q, mp);
1186			break;
1187		case ENVCTRL_IOC_SETTEMP:
1188			tempr = (uint8_t *)(void *)mp->b_cont->b_rptr;
1189			if (*tempr > MAX_DIAG_TEMPR) {
1190				miocnak(q, mp, 0, EINVAL);
1191			} else {
1192				mutex_enter(&unitp->umutex);
1193				envctrl_get_sys_temperatures(unitp, tempr);
1194				mutex_exit(&unitp->umutex);
1195				miocack(q, mp, 0, 0);
1196			}
1197			break;
1198		case ENVCTRL_IOC_SETWDT:
1199			/* reset watchdog timeout period */
1200			wdval = (uint8_t *)(void *)mp->b_cont->b_rptr;
1201			if (*wdval > MAX_CL_VAL) {
1202				miocnak(q, mp, 0, EINVAL);
1203			} else {
1204				mutex_enter(&unitp->umutex);
1205				envctrl_reset_watchdog(unitp, wdval);
1206				mutex_exit(&unitp->umutex);
1207				miocack(q, mp, 0, 0);
1208			}
1209			break;
1210		case ENVCTRL_IOC_GETMODE:
1211			/* Get the user buffer address */
1212
1213			if (state == -1) {
1214				miocack(q, mp, 0, 0);
1215				break;
1216			}
1217			tempr = (uchar_t *)(void *)mp->b_cont->b_rptr;
1218			*tempr = unitp->current_mode;
1219			mcopyout(mp, (void *)-1, sizeof (uchar_t),
1220			    csp->cp_private, NULL);
1221			qreply(q, mp);
1222			break;
1223		case ENVCTRL_IOC_SETMODE:
1224			/* Set mode */
1225			wdval = (uint8_t *)(void *)mp->b_cont->b_rptr;
1226			if (*wdval == ENVCTRL_DIAG_MODE || *wdval ==
1227			    ENVCTRL_NORMAL_MODE) {
1228				mutex_enter(&unitp->umutex);
1229				unitp->current_mode = *wdval;
1230				if (unitp->timeout_id != 0 &&
1231				    *wdval == ENVCTRL_DIAG_MODE) {
1232					(void) untimeout(unitp->timeout_id);
1233					unitp->timeout_id =
1234					    (timeout(envctrl_tempr_poll,
1235					(caddr_t)unitp, overtemp_timeout_hz));
1236
1237				}
1238				if (*wdval == ENVCTRL_NORMAL_MODE) {
1239					envctrl_get_sys_temperatures(unitp,
1240					    (uint8_t *)NULL);
1241					/*
1242					 * going to normal mode we
1243					 * need to go to diag mode
1244					 * just in case we have
1245					 * injected a fan fault. It
1246					 * may not be cleared and if
1247					 * we call fan_failsrvc it will
1248					 * power off the ystem if we are
1249					 * in NORMAL_MODE. Also we need
1250					 * to delay 1 bit of time here
1251					 * to  allow the fans to rotate
1252					 * back up and clear the intr
1253					 * after we get the sys temps.
1254					 */
1255					unitp->current_mode =
1256					    ENVCTRL_DIAG_MODE;
1257					envctrl_fan_fail_service(unitp);
1258					unitp->current_mode =
1259					    ENVCTRL_NORMAL_MODE;
1260				}
1261				mutex_exit(&unitp->umutex);
1262				miocack(q, mp, 0, 0);
1263			} else {
1264				miocnak(q, mp, 0, EINVAL);
1265			}
1266			break;
1267		default:
1268			freemsg(mp);
1269			break;
1270		}
1271
1272		break;
1273	}
1274
1275	case M_FLUSH:
1276		if (*mp->b_rptr & FLUSHR) {
1277			*mp->b_rptr &= ~FLUSHW;
1278			qreply(q, mp);
1279		} else {
1280			freemsg(mp);
1281		}
1282		break;
1283
1284	default:
1285		freemsg(mp);
1286		break;
1287	}
1288
1289	return (0);
1290}
1291
1292uint_t
1293envctrl_bus_isr(caddr_t arg)
1294{
1295	struct envctrlunit *unitp = (struct envctrlunit *)(void *)arg;
1296	int ic = DDI_INTR_UNCLAIMED;
1297
1298	mutex_enter(&unitp->umutex);
1299
1300	/*
1301	 * NOT USED
1302	 */
1303
1304	mutex_exit(&unitp->umutex);
1305	return (ic);
1306}
1307
1308uint_t
1309envctrl_dev_isr(caddr_t arg)
1310{
1311	struct envctrlunit *unitp = (struct envctrlunit *)(void *)arg;
1312	uint8_t recv_data;
1313	int ic;
1314	int retrys = 0;
1315	int status;
1316
1317	ic = DDI_INTR_UNCLAIMED;
1318
1319	mutex_enter(&unitp->umutex);
1320
1321	/*
1322	 * First check to see if it is an interrupt for us by
1323	 * looking at the "ganged" interrrupt and vector
1324	 * according to the major type
1325	 * 0x70 is the addr of the ganged interrupt controller.
1326	 * Address map for the port byte read is as follows
1327	 * MSB
1328	 * -------------------------
1329	 * |  |  |  |  |  |  |  |  |
1330	 * -------------------------
1331	 *  P7 P6 P5 P4 P3 P2 P1 P0
1332	 * P0 = Power Supply 1 intr
1333	 * P1 = Power Supply 2 intr
1334	 * P2 = Power Supply 3 intr
1335	 * P3 = Dlfop enable for fan sped set
1336	 * P4 = ENVCTRL_ Fan Fail intr
1337	 * P5 =	Front Panel Interrupt
1338	 * P6 = Power Fail Detect Low.
1339	 * P7 = Enable Interrupts to system
1340	 */
1341
1342retry:
1343
1344	status = eHc_read_pcf8574a((struct eHc_envcunit *)unitp,
1345		PCF8574A_BASE_ADDR | ENVCTRL_PCF8574_DEV0, &recv_data, 1);
1346
1347	/*
1348	 * This extra read is needed since the first read is discarded
1349	 * and the second read seems to return 0xFF.
1350	 */
1351	if (recv_data == 0xFF) {
1352		status = eHc_read_pcf8574a((struct eHc_envcunit *)unitp,
1353		PCF8574A_BASE_ADDR | ENVCTRL_PCF8574_DEV0, &recv_data, 1);
1354	}
1355	if (envctrl_debug_flags)
1356		cmn_err(CE_WARN, "envctrl_dev_isr: status= %d, data = %x\n",
1357			status, recv_data);
1358
1359	/*
1360	 * if the i2c bus is hung it is imperative that this
1361	 * be cleared on an interrupt or else it will
1362	 * hang the system with continuous interrupts
1363	 */
1364
1365	if (status == DDI_FAILURE) {
1366		drv_usecwait(1000);
1367		if (retrys < envctrl_max_retries) {
1368			retrys++;
1369			goto retry;
1370		} else {
1371			if (envctrl_debug_flags)
1372				cmn_err(CE_WARN,
1373				    "DEVISR FAILED received 0x%x\n", recv_data);
1374			mutex_exit(&unitp->umutex);
1375			envctrl_init_bus(unitp);
1376			mutex_enter(&unitp->umutex);
1377			envctrl_ps_probe(unitp);
1378			mutex_exit(&unitp->umutex);
1379			ic = DDI_INTR_CLAIMED;
1380			return (ic);
1381		}
1382	}
1383
1384	/*
1385	 * Port 0 = PS1 interrupt
1386	 * Port 1 = PS2 Interrupt
1387	 * Port 2 = PS3 Interrupt
1388	 * Port 3 = SPARE
1389	 * Port 4 = Fan Fail Intr
1390	 * Port 5 = Front Panle Module intr
1391	 * Port 6 = Keyswitch Intr
1392	 * Port 7 = ESINTR ENABLE ???
1393	 */
1394
1395	if (!(recv_data & ENVCTRL_PCF8574_PORT0)) {
1396		envctrl_PS_intr_service(unitp, PS1);
1397		ic = DDI_INTR_CLAIMED;
1398	}
1399
1400	if (!(recv_data & ENVCTRL_PCF8574_PORT1)) {
1401		envctrl_PS_intr_service(unitp, PS2);
1402		ic = DDI_INTR_CLAIMED;
1403	}
1404
1405	if (!(recv_data & ENVCTRL_PCF8574_PORT2)) {
1406		envctrl_PS_intr_service(unitp, PS3);
1407		ic = DDI_INTR_CLAIMED;
1408	}
1409
1410	if (!(recv_data & ENVCTRL_PCF8574_PORT3)) {
1411		ic = DDI_INTR_CLAIMED;
1412	}
1413
1414	if (!(recv_data & ENVCTRL_PCF8574_PORT4)) {
1415		/*
1416		 * Check for a fan fail
1417		 * Single fan fail
1418		 * shutdown system
1419		 */
1420		envctrl_fan_fail_service(unitp);
1421		ic = DDI_INTR_CLAIMED;
1422	}
1423
1424	if (!(recv_data & ENVCTRL_PCF8574_PORT5)) {
1425		(void) envctrl_get_fpm_status(unitp);
1426		ic = DDI_INTR_CLAIMED;
1427	}
1428
1429	if (!(recv_data & ENVCTRL_PCF8574_PORT6)) {
1430		ic = DDI_INTR_CLAIMED;
1431	}
1432
1433	if (!(recv_data & ENVCTRL_PCF8574_PORT7)) {
1434		ic = DDI_INTR_CLAIMED;
1435	}
1436
1437	if ((recv_data == 0xFF)) {
1438		ic = DDI_INTR_CLAIMED;
1439	}
1440
1441	mutex_exit(&unitp->umutex);
1442	return (ic);
1443
1444}
1445
1446static void
1447envctrl_init_bus(struct envctrlunit *unitp)
1448{
1449
1450	int i;
1451	uint8_t noval = NULL;
1452	struct envctrl_tda8444t_chip fan;
1453	int fans[] = {ENVCTRL_CPU_FANS, ENVCTRL_PS_FANS, ENVCTRL_AFB_FANS};
1454
1455	mutex_enter(&unitp->umutex);
1456	/* Sets the Mode to 808x type bus */
1457	ddi_put8(unitp->ctlr_handle,
1458	    &unitp->bus_ctl_regs->s0, ENVCTRL_CHAR_ZERO);
1459
1460	/* SET UP SLAVE ADDR XXX Required..send 0x80 */
1461
1462	ddi_put8(unitp->ctlr_handle, &unitp->bus_ctl_regs->s1,
1463	ENVCTRL_BUS_INIT0);
1464	(void) ddi_put8(unitp->ctlr_handle, &unitp->bus_ctl_regs->s0,
1465	ENVCTRL_BUS_INIT1);
1466
1467	/* Set the clock now */
1468	ddi_put8(unitp->ctlr_handle,
1469	    &unitp->bus_ctl_regs->s1, ENVCTRL_BUS_CLOCK0);
1470
1471	/* S0 is now S2  necause of the previous write to S1 */
1472	/* clock= 12MHz, SCL=90KHz */
1473	ddi_put8(unitp->ctlr_handle,
1474	    &unitp->bus_ctl_regs->s0, ENVCTRL_BUS_CLOCK1);
1475
1476	/* Enable serial interface */
1477	ddi_put8(unitp->ctlr_handle,
1478	    &unitp->bus_ctl_regs->s1, ENVCTRL_BUS_ESI);
1479
1480	envctrl_stop_clock(unitp);
1481
1482	/*
1483	 * This has been added here because the DAC is powered
1484	 * on at "0". When the reset_dflop routine is called
1485	 * this switched the  fans from blast to DAC control.
1486	 * if the DAC is at "0", then the fans momentarily lose
1487	 * power until the temp polling and fan set routine is
1488	 * first called. If the fans lose power, then there is
1489	 * a fan fault generated and the system will power off.
1490	 * We only want to do this IF the bus is first being
1491	 * initted. This will cause errors in Sunvts if we reset
1492	 * the fan speed under normal operation. Sometimes we need
1493	 * to be able to induce fan faults. Init bus is a common
1494	 * routine to unwedge the i2c bus in some cases.
1495	 */
1496
1497	if (unitp->initting == B_TRUE) {
1498		fan.chip_num = ENVCTRL_TDA8444T_DEV7;
1499		fan.val = INIT_FAN_VAL;
1500
1501		for (i = 0; i < sizeof (fans)/sizeof (int); i++) {
1502			fan.fan_num = fans[i];
1503			if ((fans[i] == ENVCTRL_AFB_FANS) &&
1504				(unitp->AFB_present == B_FALSE))
1505				continue;
1506			(void) envctrl_xmit(unitp, (caddr_t *)(void *)&fan,
1507				TDA8444T);
1508		}
1509	}
1510
1511	envctrl_reset_dflop(unitp);
1512
1513	envctrl_enable_devintrs(unitp);
1514
1515	unitp->current_mode = ENVCTRL_NORMAL_MODE;
1516	envctrl_reset_watchdog(unitp, &noval);
1517
1518	mutex_exit(&unitp->umutex);
1519}
1520
1521static int
1522envctrl_xmit(struct envctrlunit *unitp, caddr_t *data, int chip_type)
1523{
1524
1525	struct envctrl_tda8444t_chip *fanspeed;
1526	struct envctrl_pcf8574_chip *ioport;
1527	uint8_t slave_addr;
1528	uint8_t buf[2];
1529	int retrys = 0;
1530	int status;
1531
1532	ASSERT(MUTEX_HELD(&unitp->umutex));
1533
1534	switch (chip_type) {
1535	case TDA8444T:
1536
1537		fanspeed = (struct envctrl_tda8444t_chip *)data;
1538
1539		if (fanspeed->chip_num > ENVCTRL_FAN_ADDR_MAX) {
1540			return (DDI_FAILURE);
1541		}
1542
1543		if (fanspeed->fan_num > ENVCTRL_PORT7) {
1544			return (DDI_FAILURE);
1545		}
1546
1547		if (fanspeed->val > MAX_FAN_VAL) {
1548			return (DDI_FAILURE);
1549		}
1550
1551retry0:
1552		slave_addr = (TDA8444T_BASE_ADDR | fanspeed->chip_num);
1553		buf[0] = fanspeed->val;
1554
1555		status = eHc_write_tda8444((struct eHc_envcunit *)unitp,
1556			TDA8444T_BASE_ADDR | fanspeed->chip_num, 0xF,
1557			fanspeed->fan_num, buf, 1);
1558		if (status != DDI_SUCCESS) {
1559			drv_usecwait(1000);
1560			if (retrys < envctrl_max_retries) {
1561				retrys++;
1562				goto retry0;
1563			} else {
1564				mutex_exit(&unitp->umutex);
1565				envctrl_init_bus(unitp);
1566				mutex_enter(&unitp->umutex);
1567				if (envctrl_debug_flags)
1568					cmn_err(CE_WARN,
1569					    "envctrl_xmit: Write to TDA8444 " \
1570					    "failed\n");
1571				return (DDI_FAILURE);
1572			}
1573		}
1574
1575		/*
1576		 * Update the kstats.
1577		 */
1578		switch (fanspeed->fan_num) {
1579		case ENVCTRL_CPU_FANS:
1580			unitp->fan_kstats[ENVCTRL_FAN_TYPE_CPU].fanspeed =
1581			    fanspeed->val;
1582			break;
1583		case ENVCTRL_PS_FANS:
1584			unitp->fan_kstats[ENVCTRL_FAN_TYPE_PS].fanspeed =
1585			    fanspeed->val;
1586			break;
1587		case ENVCTRL_AFB_FANS:
1588			unitp->fan_kstats[ENVCTRL_FAN_TYPE_AFB].fanspeed =
1589			    fanspeed->val;
1590			break;
1591		default:
1592			break;
1593		}
1594		break;
1595	case PCF8574:
1596		ioport = (struct envctrl_pcf8574_chip *)data;
1597		buf[0] = ioport->val;
1598		if (ioport->chip_num > ENVCTRL_PCF8574_DEV7)
1599			return (DDI_FAILURE);
1600
1601retry:
1602		if (ioport->type == PCF8574A) {
1603			slave_addr = (PCF8574A_BASE_ADDR | ioport->chip_num);
1604			status =
1605				eHc_write_pcf8574a((struct eHc_envcunit *)unitp,
1606				PCF8574A_BASE_ADDR | ioport->chip_num, buf, 1);
1607		} else {
1608			slave_addr = (PCF8574_BASE_ADDR | ioport->chip_num);
1609			status = eHc_write_pcf8574((struct eHc_envcunit *)unitp,
1610				PCF8574_BASE_ADDR | ioport->chip_num, buf, 1);
1611		}
1612
1613		if (status != DDI_SUCCESS) {
1614			drv_usecwait(1000);
1615			if (retrys < envctrl_max_retries) {
1616				retrys++;
1617				goto retry;
1618			} else {
1619				mutex_exit(&unitp->umutex);
1620				envctrl_init_bus(unitp);
1621				mutex_enter(&unitp->umutex);
1622				if (envctrl_debug_flags)
1623					cmn_err(CE_WARN, "Write to PCF8574 " \
1624					    "failed, addr = %X\n", slave_addr);
1625				if (envctrl_debug_flags)
1626					cmn_err(CE_WARN, "envctrl_xmit: PCF8574\
1627						dev = %d, port = %d\n",
1628						ioport->chip_num, ioport->type);
1629				return (DDI_FAILURE);
1630			}
1631		}
1632		break;
1633
1634	default:
1635		return (DDI_FAILURE);
1636	}
1637
1638	return (DDI_SUCCESS);
1639}
1640
1641static void
1642envctrl_recv(struct envctrlunit *unitp, caddr_t *data, int chip_type)
1643{
1644
1645	struct envctrl_pcf8591_chip *temp;
1646	struct envctrl_pcf8574_chip *ioport;
1647	uint8_t slave_addr, recv_data;
1648	int retrys = 0;
1649	int status;
1650	uint8_t buf[1];
1651
1652	ASSERT(MUTEX_HELD(&unitp->umutex));
1653
1654	switch (chip_type) {
1655	case PCF8591:
1656		temp = (struct envctrl_pcf8591_chip *)data;
1657		slave_addr = (PCF8591_BASE_ADDR | temp->chip_num);
1658
1659retry:
1660		status = eHc_read_pcf8591((struct eHc_envcunit *)unitp,
1661			PCF8591_BASE_ADDR | temp->chip_num & 0xF,
1662			temp->sensor_num, 0, 0, 1, &recv_data, 1);
1663
1664		/*
1665		 * another place to catch the i2c bus hang on an 8591 read
1666		 * In this instance we will just return the data that is read
1667		 * after the max_retry because this could be a valid value.
1668		 */
1669		if (status != DDI_SUCCESS) {
1670			drv_usecwait(1000);
1671			if (retrys < envctrl_max_retries) {
1672				retrys++;
1673				goto retry;
1674			} else {
1675				mutex_exit(&unitp->umutex);
1676				envctrl_init_bus(unitp);
1677				mutex_enter(&unitp->umutex);
1678				if (envctrl_debug_flags)
1679					cmn_err(CE_WARN, "Read from PCF8591 " \
1680					    "failed, slave_addr = %x\n",
1681					    slave_addr);
1682			}
1683		}
1684		temp->temp_val = recv_data;
1685		break;
1686	case TDA8444T:
1687		printf("envctrl_recv: attempting to read TDA8444T\n");
1688		return;
1689	case PCF8574:
1690		ioport = (struct envctrl_pcf8574_chip *)data;
1691
1692retry1:
1693		if (ioport->chip_num > ENVCTRL_PCF8574_DEV7)
1694			cmn_err(CE_WARN, "envctrl: dev out of range 0x%x\n",
1695ioport->chip_num);
1696
1697		if (ioport->type == PCF8574A) {
1698			slave_addr = (PCF8574_READ_BIT | PCF8574A_BASE_ADDR |
1699			    ioport->chip_num);
1700			status = eHc_read_pcf8574a((struct eHc_envcunit *)unitp,
1701				PCF8574A_BASE_ADDR | ioport->chip_num, buf, 1);
1702		} else {
1703			slave_addr = (PCF8574_READ_BIT | PCF8574_BASE_ADDR |
1704			    ioport->chip_num);
1705			status = eHc_read_pcf8574((struct eHc_envcunit *)unitp,
1706				PCF8574_BASE_ADDR | ioport->chip_num, buf, 1);
1707		}
1708
1709		if (status != DDI_SUCCESS) {
1710			drv_usecwait(1000);
1711			if (retrys < envctrl_max_retries) {
1712				retrys++;
1713				goto retry1;
1714			} else {
1715				mutex_exit(&unitp->umutex);
1716				envctrl_init_bus(unitp);
1717				mutex_enter(&unitp->umutex);
1718				if (envctrl_debug_flags)
1719					cmn_err(CE_WARN, "Read from PCF8574 "\
1720					    "failed, addr = %X\n", slave_addr);
1721				if (envctrl_debug_flags)
1722					cmn_err(CE_WARN, "envctrl_recv: PCF8574\
1723						dev = %d, port = %d\n",
1724						ioport->chip_num, ioport->type);
1725			}
1726		}
1727		ioport->val = buf[0];
1728		break;
1729	default:
1730		break;
1731	}
1732}
1733
1734static int
1735envctrl_get_ps_temp(struct envctrlunit *unitp, uint8_t psaddr)
1736{
1737	uint8_t tempr;
1738	int i, retrys;
1739	int status;
1740	uint8_t buf[4];
1741
1742	ASSERT(MUTEX_HELD(&unitp->umutex));
1743
1744	tempr = 0;
1745	retrys = 0;
1746
1747retry:
1748	status = eHc_read_pcf8591((struct eHc_envcunit *)unitp,
1749			PCF8591_BASE_ADDR | psaddr & 0xF, 0, 1, 0, 1, buf, 4);
1750
1751	tempr = 0;
1752	for (i = 0; i < PCF8591_MAX_PORTS; i++) {
1753		/*
1754		 * The pcf8591 will return 0xff if no port
1755		 * is there.. this is bogus for setting temps.
1756		 * so just ignore it!
1757		 */
1758		if (envctrl_debug_flags) {
1759			cmn_err(CE_WARN, "PS addr 0x%x recvd 0x%x on port %d\n",
1760			    psaddr, buf[i], i);
1761		}
1762		if (buf[i] > tempr && buf[i] < MAX_PS_ADVAL) {
1763			tempr = buf[i];
1764		}
1765	}
1766
1767	/*
1768	 * This routine is a safeguard to make sure that if the
1769	 * powersupply temps cannot be read that we do something
1770	 * to make sure that the system will notify the user and
1771	 * it will stay running with the fans at 100%. The calling
1772	 * routine should take care of that.
1773	 */
1774	if (status != DDI_SUCCESS) {
1775		drv_usecwait(1000);
1776		if (retrys < envctrl_max_retries) {
1777			retrys++;
1778			goto retry;
1779		} else {
1780			mutex_exit(&unitp->umutex);
1781			envctrl_init_bus(unitp);
1782			mutex_enter(&unitp->umutex);
1783			if (envctrl_debug_flags)
1784				cmn_err(CE_WARN,
1785				    "Cannot read Power Supply Temps addr = %X",
1786				    psaddr);
1787			return (PS_DEFAULT_VAL);
1788		}
1789	}
1790
1791	return (ps_temps[tempr]);
1792}
1793
1794static int
1795envctrl_get_cpu_temp(struct envctrlunit *unitp, int cpunum)
1796{
1797	uint8_t recv_data;
1798	int retrys;
1799	int status;
1800
1801	ASSERT(MUTEX_HELD(&unitp->umutex));
1802
1803	/*
1804	 * This routine takes in the number of the port that
1805	 * we want to read in the 8591. This should be the
1806	 * location of the COU thermistor for one of the 4
1807	 * cpu's. It will return the temperature in degrees C
1808	 * to the caller.
1809	 */
1810
1811	retrys = 0;
1812
1813retry:
1814	status = eHc_read_pcf8591((struct eHc_envcunit *)unitp,
1815			PCF8591_BASE_ADDR | PCF8591_DEV7, cpunum, 0, 0, 0,
1816			&recv_data, 1);
1817
1818	/*
1819	 * We need to take a sledge hammer to the bus if we get back
1820	 * value of the chip. This means that the i2c bus got wedged.
1821	 * On the 1.4 systems this happens sometimes while running
1822	 * sunvts. We will return the max cpu temp minus 10 to make
1823	 * the fans run at full speed so that we don;t cook the
1824	 * system.
1825	 * At this point this is a workaround for hardware glitch.
1826	 */
1827	if (status == DDI_FAILURE) {
1828		drv_usecwait(1000);
1829		if (retrys < envctrl_max_retries) {
1830			retrys++;
1831			goto retry;
1832		} else {
1833			mutex_exit(&unitp->umutex);
1834			envctrl_init_bus(unitp);
1835			mutex_enter(&unitp->umutex);
1836			if (envctrl_debug_flags)
1837				cmn_err(CE_WARN, "envctrl CPU TEMP read " \
1838				    "failed\n");
1839			/* we don't want to power off the system */
1840			return (MAX_CPU_TEMP - 10);
1841		}
1842	}
1843
1844	return (cpu_temps[recv_data]);
1845}
1846
1847static int
1848envctrl_get_lm75_temp(struct envctrlunit *unitp)
1849{
1850
1851	int k;
1852	ushort_t lmval;
1853	uint8_t tmp1;
1854	uint8_t tmp2;
1855	int status;
1856	uint8_t buf[2];
1857
1858
1859	ASSERT(MUTEX_HELD(&unitp->umutex));
1860
1861	status = eHc_read_lm75((struct eHc_envcunit *)unitp,
1862		LM75_BASE_ADDR | LM75_CONFIG_ADDRA, buf, 2);
1863	if (status != DDI_SUCCESS)
1864		cmn_err(CE_WARN, "read of LM75 failed\n");
1865
1866	tmp1 = buf[0];
1867	tmp2 = buf[1];
1868
1869	/*
1870	 * Store the forst 8 bits in the upper nibble of the
1871	 * short, then store the lower 8 bits in the lower nibble
1872	 * of the short, shift 7 to the right to get the 9 bit value
1873	 * that the lm75 is really sending.
1874	 */
1875	lmval = tmp1 << 8;
1876	lmval = (lmval | tmp2);
1877	lmval = (lmval >> 7);
1878	/*
1879	 * Check the 9th bit to see if it is a negative
1880	 * temperature. If so change into 2's compliment
1881	 * and divide by 2 since each value is equal to a
1882	 * half degree strp in degrees C
1883	 */
1884	if (lmval & LM75_COMP_MASK) {
1885		tmp1 = (lmval & LM75_COMP_MASK_UPPER);
1886		tmp1 = -tmp1;
1887		tmp1 = tmp1/2;
1888		k = 0 - tmp1;
1889	} else {
1890		k = lmval /2;
1891	}
1892		return (k);
1893}
1894
1895
1896static void
1897envctrl_tempr_poll(void *arg)
1898{
1899	int diag_flag = 0;
1900	struct envctrlunit *unitp = (struct envctrlunit *)arg;
1901
1902	mutex_enter(&unitp->umutex);
1903
1904	if (unitp->shutdown == B_TRUE) {
1905		(void) power_down("Fatal System Environmental Control Error");
1906	}
1907
1908	/*
1909	 * if we are in diag mode and the temp poll thread goes off,
1910	 * this means that the system is too heavily loaded and the 60 second
1911	 * window to execute the test is failing. We will change the fanspeed
1912	 * but will not check for a fanfault. This will cause a system shutdown
1913	 * if the system has had a fanfault injected.
1914	 */
1915	if (unitp->current_mode == ENVCTRL_DIAG_MODE) {
1916		diag_flag++;
1917		if (envctrl_debug_flags) {
1918			cmn_err(CE_WARN,
1919			    "Tempr poll went off while in DIAG MODE");
1920		}
1921	}
1922	unitp->current_mode = ENVCTRL_NORMAL_MODE;
1923	envctrl_get_sys_temperatures(unitp, (uint8_t *)NULL);
1924	if (diag_flag == 0) {
1925		envctrl_fan_fail_service(unitp);
1926	}
1927	/* now have this thread sleep for a while */
1928	unitp->timeout_id = (timeout(envctrl_tempr_poll,
1929	    (caddr_t)unitp, overtemp_timeout_hz));
1930
1931	mutex_exit(&unitp->umutex);
1932}
1933
1934static void
1935envctrl_led_blink(void *arg)
1936{
1937	struct envctrl_pcf8574_chip fspchip;
1938	struct envctrlunit *unitp = (struct envctrlunit *)arg;
1939
1940	mutex_enter(&unitp->umutex);
1941
1942	fspchip.type = PCF8574A;
1943	fspchip.chip_num = ENVCTRL_PCF8574_DEV6; /* 0x01 port 1 */
1944	envctrl_recv(unitp, (caddr_t *)(void *)&fspchip, PCF8574);
1945
1946	if (unitp->present_led_state == B_TRUE) {
1947		/*
1948		 * Now we need to "or" in fault bits of the FSP
1949		 * module for the mass storage fault led.
1950		 * and set it.
1951		 */
1952		fspchip.val = (fspchip.val & ~(ENVCTRL_PCF8574_PORT4) |
1953				    0xC0);
1954		unitp->present_led_state = B_FALSE;
1955	} else {
1956		fspchip.val = (fspchip.val | ENVCTRL_PCF8574_PORT4 | 0xC0);
1957		unitp->present_led_state = B_TRUE;
1958	}
1959
1960	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&fspchip, PCF8574);
1961
1962	/* now have this thread sleep for a while */
1963	unitp->blink_timeout_id = (timeout(envctrl_led_blink,
1964	    (caddr_t)unitp, blink_timeout_hz));
1965
1966	mutex_exit(&unitp->umutex);
1967}
1968
1969/* called with mutex held */
1970static void
1971envctrl_get_sys_temperatures(struct envctrlunit *unitp, uint8_t *diag_tempr)
1972{
1973	int temperature, tmptemp, cputemp, hicputemp, ambtemp;
1974	int i;
1975	struct envctrl_tda8444t_chip fan;
1976	uint8_t psaddr[] = {PSTEMP3, PSTEMP2, PSTEMP1, PSTEMP0};
1977	uint8_t noval = NULL;
1978	uint8_t fspval;
1979
1980	ASSERT(MUTEX_HELD(&unitp->umutex));
1981
1982	fan.fan_num = ENVCTRL_CPU_FANS;
1983	fan.chip_num = ENVCTRL_TDA8444T_DEV7;
1984
1985	tmptemp = 0;	/* Right init value ?? */
1986
1987	/*
1988	 * THis routine is caled once every minute
1989	 * we wil re-se the watchdog timer each time
1990	 * we poll the temps. The watchdog timer is
1991	 * set up for 3 minutes. Should the kernel thread
1992	 * wedge, for some reason the watchdog will go off
1993	 * and blast the fans.
1994	 */
1995
1996	if (unitp->current_mode == ENVCTRL_DIAG_MODE) {
1997		unitp->current_mode = ENVCTRL_NORMAL_MODE;
1998		envctrl_reset_watchdog(unitp, &noval);
1999		unitp->current_mode = ENVCTRL_DIAG_MODE;
2000	} else {
2001		envctrl_reset_watchdog(unitp, &noval);
2002	}
2003
2004	/*
2005	 * we need to reset the dflop to allow the fans to be
2006	 * set if the watchdog goes of and the kernel resumes
2007	 * resetting the dflop alos resets the device interrupts
2008	 * we need to reenable them also.
2009	 */
2010	envctrl_reset_dflop(unitp);
2011
2012	envctrl_enable_devintrs(unitp);
2013
2014	/*
2015	 * If we are in diag mode we allow the system to be
2016	 * faked out as to what the temperature is
2017	 * to see if the fans speed up.
2018	 */
2019	if (unitp->current_mode == ENVCTRL_DIAG_MODE && diag_tempr != NULL) {
2020		if (unitp->timeout_id != 0) {
2021		    (void) untimeout(unitp->timeout_id);
2022		}
2023
2024		ambtemp = *diag_tempr;
2025		unitp->timeout_id = (timeout(envctrl_tempr_poll,
2026		    (caddr_t)unitp, overtemp_timeout_hz));
2027	} else {
2028		ambtemp = envctrl_get_lm75_temp(unitp);
2029		/*
2030		 * Sometimes when we read the temp it comes back bogus
2031		 * to fix this we just need to reset the envctrl bus
2032		 */
2033		if (ambtemp == -100) {
2034			mutex_exit(&unitp->umutex);
2035			envctrl_init_bus(unitp);
2036			mutex_enter(&unitp->umutex);
2037			ambtemp = envctrl_get_lm75_temp(unitp);
2038		}
2039	}
2040
2041	envctrl_mod_encl_kstats(unitp, ENVCTRL_ENCL_AMBTEMPR, INSTANCE_0,
2042	    ambtemp);
2043
2044	fspval = envctrl_get_fpm_status(unitp);
2045
2046	if (ambtemp > MAX_AMB_TEMP) {
2047		fspval |= (ENVCTRL_FSP_TEMP_ERR | ENVCTRL_FSP_GEN_ERR);
2048		if (!(envctrl_power_off_overide) &&
2049		    unitp->current_mode == ENVCTRL_NORMAL_MODE) {
2050			unitp->shutdown = B_TRUE;
2051		}
2052			if (unitp->current_mode == ENVCTRL_NORMAL_MODE) {
2053				cmn_err(CE_WARN,
2054			"Ambient Temperature is %d C, shutdown now\n",
2055				    ambtemp);
2056			}
2057	} else {
2058		if (envctrl_isother_fault_led(unitp, fspval,
2059			ENVCTRL_FSP_TEMP_ERR)) {
2060			fspval &= ~(ENVCTRL_FSP_TEMP_ERR);
2061		} else {
2062			fspval &= ~(ENVCTRL_FSP_TEMP_ERR | ENVCTRL_FSP_GEN_ERR);
2063		}
2064	}
2065
2066	envctrl_set_fsp(unitp, &fspval);
2067
2068	cputemp = hicputemp = 0;
2069#ifndef TESTBED
2070	for (i = 0; i < ENVCTRL_MAX_CPUS; i++) {
2071		if (unitp->cpu_pr_location[i] == B_TRUE) {
2072			cputemp = envctrl_get_cpu_temp(unitp, i);
2073			envctrl_mod_encl_kstats(unitp, ENVCTRL_ENCL_CPUTEMPR,
2074			    i, cputemp);
2075			if (cputemp >= MAX_CPU_TEMP) {
2076				if (!(envctrl_power_off_overide)) {
2077					unitp->shutdown = B_TRUE;
2078				}
2079				cmn_err(CE_WARN,
2080				    "CPU %d OVERHEATING!!!", i);
2081			}
2082
2083			if (cputemp > hicputemp) {
2084				hicputemp = cputemp;
2085			}
2086		}
2087	}
2088#else
2089	cputemp = envctrl_get_cpu_temp(unitp, 0);
2090	envctrl_mod_encl_kstats(unitp, ENVCTRL_ENCL_CPUTEMPR, 0, cputemp);
2091#endif
2092
2093	fspval = envctrl_get_fpm_status(unitp);
2094
2095	/*
2096	 * We first look at the ambient temp. If the system is at idle
2097	 * the cpu temps will be approx 20 degrees above ambient.
2098	 * If the cpu's rise above 20, then the CPU fans are set
2099	 * according to the cpu temp minus 20 degrees C.
2100	 */
2101	if (unitp->current_mode == ENVCTRL_DIAG_MODE && diag_tempr != NULL) {
2102		temperature = ambtemp;
2103	} else {
2104		temperature = hicputemp - CPU_AMB_RISE;
2105	}
2106
2107	if (temperature < 0) {
2108		fan.val = MAX_FAN_SPEED; 	/* blast it is out of range */
2109	} else if (temperature > MAX_AMB_TEMP) {
2110		fan.val = MAX_FAN_SPEED;
2111		fspval |= (ENVCTRL_FSP_TEMP_ERR | ENVCTRL_FSP_GEN_ERR);
2112
2113			if (unitp->current_mode == ENVCTRL_NORMAL_MODE) {
2114				cmn_err(CE_WARN,
2115				    "CPU Fans set to MAX. CPU Temp is %d C\n",
2116				    hicputemp);
2117			}
2118	} else if (ambtemp < MAX_AMB_TEMP) {
2119		if (!envctrl_p0_enclosure) {
2120			fan.val = acme_cpu_fanspd[temperature];
2121		} else {
2122			fan.val = fan_speed[temperature];
2123		}
2124		if (envctrl_isother_fault_led(unitp, fspval,
2125			ENVCTRL_FSP_TEMP_ERR)) {
2126			fspval &= ~(ENVCTRL_FSP_TEMP_ERR);
2127		} else {
2128			fspval &= ~(ENVCTRL_FSP_TEMP_ERR | ENVCTRL_FSP_GEN_ERR);
2129		}
2130	}
2131
2132	envctrl_set_fsp(unitp, &fspval);
2133
2134	/*
2135	 * Update temperature kstats. FSP kstats are updated in the
2136	 * set and get routine.
2137	 */
2138
2139	unitp->fan_kstats[ENVCTRL_FAN_TYPE_CPU].fanspeed = fan.val;
2140
2141	/* CPU FANS */
2142	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&fan, TDA8444T);
2143
2144	/* The afb Fan is always at max */
2145	if (unitp->AFB_present == B_TRUE) {
2146		fan.val = AFB_MAX;
2147		/* AFB FANS */
2148		unitp->fan_kstats[ENVCTRL_FAN_TYPE_AFB].fanspeed = fan.val;
2149		fan.fan_num = ENVCTRL_AFB_FANS;
2150		(void) envctrl_xmit(unitp, (caddr_t *)(void *)&fan, TDA8444T);
2151	}
2152
2153	/*
2154	 * Now set the Powersupply fans
2155	 */
2156
2157	tmptemp = temperature = 0;
2158	for (i = 0; i <= MAXPS; i++) {
2159		if (unitp->ps_present[i]) {
2160			tmptemp = envctrl_get_ps_temp(unitp, psaddr[i]);
2161			unitp->ps_kstats[i].ps_tempr = tmptemp & 0xFFFF;
2162			if (tmptemp > temperature) {
2163				temperature = tmptemp;
2164			}
2165			if (temperature >= MAX_PS_TEMP) {
2166				if (!(envctrl_power_off_overide)) {
2167					unitp->shutdown = B_TRUE;
2168				}
2169				cmn_err(CE_WARN,
2170				    "Power Supply %d OVERHEATING!!!\
2171				    Temp is %d C", i, temperature);
2172			}
2173		}
2174	}
2175
2176
2177	fan.fan_num = ENVCTRL_PS_FANS;
2178	if (temperature > PS_TEMP_WARN) {
2179		fspval = envctrl_get_fpm_status(unitp);
2180		fspval |= (ENVCTRL_FSP_TEMP_ERR | ENVCTRL_FSP_GEN_ERR);
2181		envctrl_set_fsp(unitp, &fspval);
2182		fan.val = MAX_FAN_SPEED;
2183		cmn_err(CE_WARN, "A Power Supply is close to  OVERHEATING!!!");
2184	} else {
2185		if (temperature - ambtemp > PS_AMB_RISE) {
2186			ambtemp = temperature - PS_AMB_RISE;
2187		}
2188		if (!envctrl_p0_enclosure) {
2189			fan.val = acme_ps_fanspd[ambtemp];
2190		} else {
2191			fan.val = ps_fans[ambtemp];
2192		}
2193	}
2194
2195	/*
2196	 * XXX add in error condition for ps overtemp
2197	 */
2198
2199	unitp->fan_kstats[ENVCTRL_FAN_TYPE_PS].fanspeed = fan.val;
2200	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&fan, TDA8444T);
2201}
2202
2203/* called with mutex held */
2204static void
2205envctrl_fan_fail_service(struct envctrlunit *unitp)
2206{
2207	uint8_t recv_data, fpmstat;
2208	int fantype;
2209	int psfanflt, cpufanflt, afbfanflt;
2210	int retries = 0, max_retry_count;
2211	int status;
2212
2213	psfanflt = cpufanflt = afbfanflt = 0;
2214	/*
2215	 * The fan fail sensor is located at address 0x70
2216	 * on the envctrl bus.
2217	 */
2218
2219	ASSERT(MUTEX_HELD(&unitp->umutex));
2220
2221retry:
2222	status = eHc_read_pcf8574a((struct eHc_envcunit *)unitp,
2223		PCF8574A_BASE_ADDR | ENVCTRL_PCF8574_DEV4, &recv_data, 1);
2224	if (status != DDI_SUCCESS)
2225		cmn_err(CE_WARN, "fan_fail_service: status = %d, data = %x\n",
2226			status, recv_data);
2227
2228	/*
2229	 * If all fan ports are high (0xff) then we don't have any
2230	 * fan faults. Reset the kstats
2231	 */
2232	if (recv_data == 0xff) {
2233		unitp->fan_kstats[ENVCTRL_FAN_TYPE_PS].fans_ok = B_TRUE;
2234		unitp->fan_kstats[ENVCTRL_FAN_TYPE_CPU].fans_ok = B_TRUE;
2235		unitp->fan_kstats[ENVCTRL_FAN_TYPE_AFB].fans_ok = B_TRUE;
2236		unitp->fan_kstats[ENVCTRL_FAN_TYPE_PS].fanflt_num = 0;
2237		unitp->fan_kstats[ENVCTRL_FAN_TYPE_CPU].fanflt_num = 0;
2238		unitp->fan_kstats[ENVCTRL_FAN_TYPE_AFB].fanflt_num = 0;
2239		unitp->num_fans_failed = 0;
2240		fpmstat = envctrl_get_fpm_status(unitp);
2241		if (!(envctrl_isother_fault_led(unitp, fpmstat, 0))) {
2242			fpmstat &= ~(ENVCTRL_FSP_GEN_ERR);
2243		}
2244		if (unitp->shutdown != B_TRUE) {
2245			envctrl_set_fsp(unitp, &fpmstat);
2246		}
2247		return;
2248	}
2249
2250	fantype = ENVCTRL_FAN_TYPE_PS;
2251
2252	if (!(recv_data & ENVCTRL_PCF8574_PORT0)) {
2253		psfanflt = PS_FAN_3;
2254	}
2255	if (!(recv_data & ENVCTRL_PCF8574_PORT1)) {
2256		psfanflt = PS_FAN_2;
2257	}
2258	if (!(recv_data & ENVCTRL_PCF8574_PORT2)) {
2259		psfanflt = PS_FAN_1;
2260	}
2261
2262	if (psfanflt != 0) {
2263		unitp->fan_kstats[fantype].fans_ok = B_FALSE;
2264		unitp->fan_kstats[fantype].fanflt_num = psfanflt - 1;
2265		if (retries == MAX_FAN_FAIL_RETRY && status == DDI_SUCCESS &&
2266		    unitp->current_mode == ENVCTRL_NORMAL_MODE) {
2267			cmn_err(CE_WARN, "PS Fan Number %d Failed",
2268			    psfanflt - 1);
2269		}
2270	} else {
2271		unitp->fan_kstats[fantype].fans_ok = B_TRUE;
2272		unitp->fan_kstats[fantype].fanflt_num = 0;
2273	}
2274
2275	fantype = ENVCTRL_FAN_TYPE_CPU;
2276
2277	if (!(recv_data & ENVCTRL_PCF8574_PORT3)) {
2278		cpufanflt = CPU_FAN_1;
2279	}
2280	if (!(recv_data & ENVCTRL_PCF8574_PORT4)) {
2281		cpufanflt = CPU_FAN_2;
2282	}
2283	if (!(recv_data & ENVCTRL_PCF8574_PORT5)) {
2284		cpufanflt = CPU_FAN_3;
2285	}
2286
2287	if (cpufanflt != 0) {
2288		unitp->fan_kstats[fantype].fans_ok = B_FALSE;
2289		unitp->fan_kstats[fantype].fanflt_num = cpufanflt - 1;
2290		if (retries == MAX_FAN_FAIL_RETRY && status == DDI_SUCCESS &&
2291		    unitp->current_mode == ENVCTRL_NORMAL_MODE) {
2292			cmn_err(CE_WARN, "CPU Fan Number %d Failed",
2293			    cpufanflt - 1);
2294		}
2295	} else {
2296		unitp->fan_kstats[fantype].fans_ok = B_TRUE;
2297		unitp->fan_kstats[fantype].fanflt_num = 0;
2298	}
2299
2300	if (!(recv_data & ENVCTRL_PCF8574_PORT6) &&
2301		(unitp->AFB_present == B_TRUE)) {
2302		/*
2303		 * If the afb is present and the afb fan fails,
2304		 * we need to power off or else it will melt!
2305		 * If it isn't present just log the error.
2306		 * We make the decision off of the afbfanflt
2307		 * flag later on in an if statement.
2308		 */
2309		afbfanflt++;
2310		unitp->fan_kstats[ENVCTRL_FAN_TYPE_AFB].fans_ok
2311		    = B_FALSE;
2312		unitp->fan_kstats[ENVCTRL_FAN_TYPE_AFB].fanflt_num =
2313		    AFB_FAN_1;
2314		if (unitp->current_mode == ENVCTRL_NORMAL_MODE) {
2315			cmn_err(CE_WARN, "AFB Fan Failed");
2316		}
2317
2318	}
2319
2320	/*
2321	 * If we have no Fan Faults Clear the LED's
2322	 * If we have fan faults set the Gen Fault LED.
2323	 */
2324	if (psfanflt == 0 && cpufanflt == 0 && afbfanflt == 0 &&
2325	    unitp->num_fans_failed != 0) {
2326		fpmstat = envctrl_get_fpm_status(unitp);
2327		if (!(envctrl_isother_fault_led(unitp,
2328		    fpmstat, 0))) {
2329			fpmstat &= ~(ENVCTRL_FSP_GEN_ERR);
2330		}
2331		envctrl_set_fsp(unitp, &fpmstat);
2332	} else if (psfanflt != 0 || cpufanflt != 0 || afbfanflt != 0) {
2333		fpmstat = envctrl_get_fpm_status(unitp);
2334		fpmstat |= ENVCTRL_FSP_GEN_ERR;
2335		envctrl_set_fsp(unitp, &fpmstat);
2336	}
2337
2338	if (unitp->AFB_present == B_FALSE) {
2339		afbfanflt = 0;
2340	}
2341
2342	if ((cpufanflt > 0 || psfanflt > 0 || afbfanflt > 0 ||
2343		(status != DDI_SUCCESS)) && !unitp->initting &&
2344		unitp->current_mode == ENVCTRL_NORMAL_MODE) {
2345		if (status != DDI_SUCCESS)
2346			max_retry_count = envctrl_max_retries;
2347		else
2348			max_retry_count = MAX_FAN_FAIL_RETRY;
2349		if (retries <= max_retry_count) {
2350			retries++;
2351			drv_usecwait(1000);
2352			if (retries == max_retry_count) {
2353				cmn_err(CE_WARN,
2354				    "Fan Fail is 0x%x, retries = %d\n",
2355				    recv_data, retries);
2356			}
2357			envctrl_get_sys_temperatures(unitp,
2358			    (uint8_t *)NULL);
2359			goto retry;
2360		}
2361		if (!(envctrl_power_off_overide)) {
2362			unitp->shutdown = B_TRUE;
2363		}
2364		cmn_err(CE_WARN, "Fan Failure(s), System Shutdown");
2365	}
2366
2367	unitp->num_fans_failed = (psfanflt + cpufanflt + afbfanflt);
2368
2369}
2370
2371/*
2372 * Check for power supply insertion and failure.
2373 * This is a bit tricky, because a power supply insertion will
2374 * trigger a load share interrupt as well as PS present in the
2375 * new supply. if we detect an insertion clear
2376 * interrupts, disable interrupts, wait for a couple of seconds
2377 * come back and see if the PSOK bit is set, PS_PRESENT is set
2378 * and the share fail interrupts are gone. If not this is a
2379 * real load share fail event.
2380 * Called with mutex held
2381 */
2382
2383static void
2384envctrl_PS_intr_service(struct envctrlunit *unitp, uint8_t psaddr)
2385{
2386	uint8_t recv_data;
2387	int status, retrys = 0;
2388
2389	ASSERT(MUTEX_HELD(&unitp->umutex));
2390
2391	if (unitp->current_mode == ENVCTRL_DIAG_MODE) {
2392		return;
2393	}
2394
2395retry:
2396	status = eHc_read_pcf8574a((struct eHc_envcunit *)unitp,
2397			PCF8574A_BASE_ADDR | psaddr & 0xF, &recv_data, 1);
2398	if (status != DDI_SUCCESS) {
2399		drv_usecwait(1000);
2400		if (retrys < envctrl_max_retries) {
2401			retrys++;
2402			goto retry;
2403		} else {
2404			mutex_exit(&unitp->umutex);
2405			envctrl_init_bus(unitp);
2406			mutex_enter(&unitp->umutex);
2407			if (envctrl_debug_flags)
2408				cmn_err(CE_WARN,
2409					"PS_intr_service: Read from 8574A " \
2410					    "failed\n");
2411		}
2412	}
2413
2414	/*
2415	 * setup a timeout thread to poll the ps after a
2416	 * couple of seconds. This allows for the PS to settle
2417	 * and doesn't report false errors on a hotplug
2418	 */
2419
2420	unitp->pshotplug_id = (timeout(envctrl_pshotplug_poll,
2421	    (caddr_t)unitp, pshotplug_timeout_hz));
2422
2423}
2424
2425/* called with mutex held */
2426static void
2427envctrl_reset_dflop(struct envctrlunit *unitp)
2428{
2429	struct envctrl_pcf8574_chip initval;
2430
2431	ASSERT(MUTEX_HELD(&unitp->umutex));
2432
2433	/*
2434	 * This initialization sequence allows a
2435	 * to change state to stop the fans from
2436	 * blastion upon poweron. If this isn't
2437	 * done the writes to the 8444 will not complete
2438	 * to the hardware because the dflop will
2439	 * be closed
2440	 */
2441	initval.chip_num = ENVCTRL_PCF8574_DEV0; /* 0x01 port 1 */
2442	initval.type = PCF8574A;
2443
2444	initval.val = ENVCTRL_DFLOP_INIT0;
2445	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&initval, PCF8574);
2446
2447	initval.val = ENVCTRL_DFLOP_INIT1;
2448	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&initval, PCF8574);
2449}
2450
2451static void
2452envctrl_add_encl_kstats(struct envctrlunit *unitp, int type,
2453    int instance, uint8_t val)
2454{
2455	int i = 0;
2456	boolean_t inserted = B_FALSE;
2457
2458	ASSERT(MUTEX_HELD(&unitp->umutex));
2459
2460	while (i < MAX_DEVS && inserted == B_FALSE) {
2461		if (unitp->encl_kstats[i].instance == I2C_NODEV) {
2462			unitp->encl_kstats[i].instance = instance;
2463			unitp->encl_kstats[i].type = type;
2464			unitp->encl_kstats[i].value = val;
2465			inserted = B_TRUE;
2466		}
2467		i++;
2468	}
2469	unitp->num_encl_present++;
2470}
2471
2472/* called with mutex held */
2473static void
2474envctrl_enable_devintrs(struct envctrlunit *unitp)
2475{
2476	struct envctrl_pcf8574_chip initval;
2477
2478	ASSERT(MUTEX_HELD(&unitp->umutex));
2479
2480	/*
2481	 * This initialization sequence allows a
2482	 * to change state to stop the fans from
2483	 * blastion upon poweron. If this isn't
2484	 * done the writes to the 8444 will not complete
2485	 * to the hardware because the dflop will
2486	 * be closed
2487	 */
2488	initval.chip_num = ENVCTRL_PCF8574_DEV0; /* 0x01 port 1 */
2489	initval.type = PCF8574A;
2490
2491	initval.val = ENVCTRL_DEVINTR_INTI0;
2492	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&initval, PCF8574);
2493
2494	/*
2495	 * set lowerbits all high p0 = PS1, p1 = PS2
2496	 * p2 = PS3 p4 = envctrl intr_ctrl
2497	 */
2498	initval.val = ENVCTRL_DEVINTR_INTI1;
2499	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&initval, PCF8574);
2500}
2501
2502/* called with mutex held */
2503static void
2504envctrl_stop_clock(struct envctrlunit *unitp)
2505{
2506	int status;
2507	uint8_t buf[2];
2508
2509	/*
2510	 * This routine talks to the PCF8583 which
2511	 * is a clock calendar chip on the envctrl bus.
2512	 * We use this chip as a watchdog timer for the
2513	 * fan control. At reset this chip pulses the interrupt
2514	 * line every 1 second. We need to be able to shut
2515	 * this off.
2516	 */
2517
2518	ASSERT(MUTEX_HELD(&unitp->umutex));
2519
2520	buf[0] = CLOCK_CSR_REG;
2521	buf[1] = CLOCK_DISABLE;
2522
2523	status = eHc_write_pcf8583((struct eHc_envcunit *)unitp,
2524			PCF8583_BASE_ADDR | 0, buf, 2);
2525	if (status != DDI_SUCCESS)
2526		cmn_err(CE_WARN, "write to PCF8583 failed\n");
2527}
2528
2529static void
2530envctrl_reset_watchdog(struct envctrlunit *unitp, uint8_t *wdval)
2531{
2532
2533	uint8_t w, r;
2534	uint8_t res = 0;
2535	int status;
2536	uint8_t buf[3];
2537
2538	ASSERT(MUTEX_HELD(&unitp->umutex));
2539
2540	/* the clock MUST be stopped before we re-set it */
2541	envctrl_stop_clock(unitp);
2542
2543	/*
2544	 * Reset the minutes counter to 0.
2545	 */
2546	buf[0] = ALARM_CTR_REG_MINS;
2547	buf[1] = 0x0;
2548	status = eHc_write_pcf8583((struct eHc_envcunit *)unitp,
2549			PCF8583_BASE_ADDR | 0, buf, 2);
2550	if (status != DDI_SUCCESS)
2551		cmn_err(CE_WARN, "write to PCF8583 failed\n");
2552
2553	/*
2554	 * set up the alarm timer for 3 minutes
2555	 * start by setting reg 8 ALARM_CTRL_REG
2556	 * If we are in diag mode, we set the timer in
2557	 * seconds. Valid values are 40-99. The timer
2558	 * counts up to 99. 40 would be 59 seconds
2559	 */
2560	buf[0] = CLOCK_ALARM_REG_A;
2561	if (unitp->current_mode == ENVCTRL_DIAG_MODE) {
2562		if (unitp->timeout_id != 0) {
2563			(void) untimeout(unitp->timeout_id);
2564			unitp->timeout_id = 0;
2565			unitp->timeout_id = (timeout(envctrl_tempr_poll,
2566			    (caddr_t)unitp, overtemp_timeout_hz));
2567		}
2568		buf[1] = CLOCK_ENABLE_TIMER_S;
2569	} else {
2570		buf[1] = CLOCK_ENABLE_TIMER;
2571	}
2572
2573	/* STEP 10: End Transmission */
2574	status = eHc_write_pcf8583((struct eHc_envcunit *)unitp,
2575			PCF8583_BASE_ADDR | 0, buf, 2);
2576	if (status != DDI_SUCCESS)
2577		cmn_err(CE_WARN, "Reset envctrl watchdog failed\n");
2578
2579	/*
2580	 * Now set up the alarm timer register it
2581	 * counts from 0-99 with an intr triggered
2582	 * when it gets to overflow.. or 99. It will
2583	 * also count from a pre-set value which is
2584	 * where we are seting from. We want a 3 minute fail
2585	 * safe so our value is 99-3 or 96.
2586	 * we are programming register 7 in the 8583.
2587	 */
2588
2589	buf[0] = ALARM_CTRL_REG;
2590	/*
2591	 * Allow the diagnostic to set the egg timer val.
2592	 * never allow it to be set greater than the default.
2593	 */
2594	if (unitp->current_mode == ENVCTRL_DIAG_MODE) {
2595		if (*wdval > MAX_CL_VAL) {
2596			buf[1] = EGG_TIMER_VAL;
2597		} else {
2598
2599			w = *wdval/10;
2600			r = *wdval%10;
2601
2602			res = res | r;
2603			res = (0x99 - (res | (w << 4)));
2604			buf[1] = res;
2605		}
2606	} else {
2607		buf[1] = EGG_TIMER_VAL;
2608	}
2609
2610	status = eHc_write_pcf8583((struct eHc_envcunit *)unitp,
2611			PCF8583_BASE_ADDR | 0, buf, 2);
2612	if (status != DDI_SUCCESS)
2613		cmn_err(CE_WARN, "Reset envctrl watchdog failed\n");
2614
2615
2616	/*
2617	 * Now that we have set up.. it is time
2618	 * to re-start the clock in the CSR.
2619	 */
2620
2621	buf[0] = CLOCK_CSR_REG;
2622	buf[1] = CLOCK_ENABLE;
2623	status = eHc_write_pcf8583((struct eHc_envcunit *)unitp,
2624			PCF8583_BASE_ADDR | 0, buf, 2);
2625	if (status != DDI_SUCCESS)
2626		cmn_err(CE_WARN, "Reset envctrl watchdog failed\n");
2627
2628}
2629
2630/* Called with unip mutex held */
2631static void
2632envctrl_ps_probe(struct envctrlunit *unitp)
2633{
2634
2635	uint8_t recv_data, fpmstat;
2636	uint8_t psaddr[] = {PS1, PS2, PS3, PSTEMP0};
2637	int i;
2638	int ps_error = 0, retrys = 0;
2639	int devaddr;
2640	int status;
2641	int twotimes = 0;
2642
2643	ASSERT(MUTEX_HELD(&unitp->umutex));
2644
2645	unitp->num_ps_present = 0;
2646
2647	for (i = 0; i <= MAXPS; i++) {
2648		unitp->ps_present[i] = B_FALSE;
2649		unitp->ps_kstats[i].ps_rating = 0;
2650		unitp->ps_kstats[i].ps_tempr = 0;
2651
2652		switch (psaddr[i]) {
2653		case PS1:
2654			devaddr = ENVCTRL_PCF8574_DEV3;
2655			break;
2656		case PS2:
2657			devaddr = ENVCTRL_PCF8574_DEV2;
2658			break;
2659		case PS3:
2660			devaddr = ENVCTRL_PCF8574_DEV1;
2661			break;
2662		case PSTEMP0:
2663			devaddr = 0;
2664			break;
2665		}
2666		retrys = 0;
2667retry:
2668		status = eHc_read_pcf8574a((struct eHc_envcunit *)unitp,
2669				PCF8574A_BASE_ADDR | devaddr, &recv_data, 1);
2670		if (status != DDI_SUCCESS) {
2671			drv_usecwait(1000);
2672			if (retrys < envctrl_max_retries) {
2673				retrys++;
2674				goto retry;
2675			} else {
2676				mutex_exit(&unitp->umutex);
2677				envctrl_init_bus(unitp);
2678				mutex_enter(&unitp->umutex);
2679				/*
2680				 * If we just reset the bus we need to reread
2681				 * the status.  If a second attempt still fails
2682				 * then report the read failure.
2683				 */
2684				if (twotimes == 0) {
2685					twotimes++;
2686					retrys = 0;
2687					goto retry;
2688				} else {
2689					cmn_err(CE_WARN,
2690					"PS_probe: Read from 8574A failed\n");
2691				}
2692			}
2693		}
2694
2695		/*
2696		 * Port 0 = PS Present
2697		 * Port 1 = PS Type
2698		 * Port 2 = PS Type
2699		 * Port 3 = PS TYpe
2700		 * Port 4 = DC Status
2701		 * Port 5 = Current Limit
2702		 * Port 6 = Current Share
2703		 * Port 7 = SPARE
2704		 */
2705
2706		/*
2707		 * Port 0 = PS Present
2708		 * Port is pulled LOW "0" to indicate
2709		 * present.
2710		 */
2711
2712		if (!(recv_data & ENVCTRL_PCF8574_PORT0)) {
2713			unitp->ps_present[i] = B_TRUE;
2714			/* update unit kstat array */
2715			unitp->ps_kstats[i].instance = i;
2716			unitp->ps_kstats[i].ps_tempr = ENVCTRL_INIT_TEMPR;
2717			++unitp->num_ps_present;
2718
2719			if (power_supply_previous_state[i] == 0) {
2720				cmn_err(CE_NOTE,
2721				    "Power Supply %d inserted\n", i);
2722			}
2723			power_supply_previous_state[i] = 1;
2724
2725			if (!(recv_data & ENVCTRL_PCF8574_PORT1)) {
2726				unitp->ps_kstats[i].ps_rating = ENVCTRL_PS_550;
2727			}
2728			if (!(recv_data & ENVCTRL_PCF8574_PORT2)) {
2729				unitp->ps_kstats[i].ps_rating = ENVCTRL_PS_650;
2730			}
2731			if (!(recv_data & ENVCTRL_PCF8574_PORT3)) {
2732				cmn_err(CE_WARN,
2733				    "Power Supply %d NOT okay\n", i);
2734				unitp->ps_kstats[i].ps_ok = B_FALSE;
2735				ps_error++;
2736			} else {
2737				unitp->ps_kstats[i].ps_ok = B_TRUE;
2738			}
2739			if (!(recv_data & ENVCTRL_PCF8574_PORT4)) {
2740				cmn_err(CE_WARN,
2741				    "Power Supply %d Overloaded\n", i);
2742				unitp->ps_kstats[i].limit_ok = B_FALSE;
2743				ps_error++;
2744			} else {
2745				unitp->ps_kstats[i].limit_ok = B_TRUE;
2746			}
2747			if (!(recv_data & ENVCTRL_PCF8574_PORT5)) {
2748				cmn_err(CE_WARN,
2749				    "Power Supply %d load share err\n", i);
2750				unitp->ps_kstats[i].curr_share_ok = B_FALSE;
2751				ps_error++;
2752			} else {
2753				unitp->ps_kstats[i].curr_share_ok = B_TRUE;
2754			}
2755
2756			if (!(recv_data & ENVCTRL_PCF8574_PORT6)) {
2757				cmn_err(CE_WARN,
2758				    "PS %d Shouln't interrupt\n", i);
2759				ps_error++;
2760			}
2761
2762			if (!(recv_data & ENVCTRL_PCF8574_PORT7)) {
2763				cmn_err(CE_WARN,
2764				    "PS %d Shouln't interrupt\n", i);
2765				ps_error++;
2766			}
2767		} else {
2768			/* No power supply present */
2769			if (power_supply_previous_state[i] == 1) {
2770				cmn_err(CE_NOTE,
2771				    "Power Supply %d removed\n", i);
2772			}
2773			power_supply_previous_state[i] = 0;
2774		}
2775	}
2776
2777	fpmstat = envctrl_get_fpm_status(unitp);
2778	if (ps_error) {
2779		fpmstat |= (ENVCTRL_FSP_PS_ERR | ENVCTRL_FSP_GEN_ERR);
2780	} else {
2781		if (envctrl_isother_fault_led(unitp, fpmstat,
2782			ENVCTRL_FSP_PS_ERR)) {
2783			fpmstat &= ~(ENVCTRL_FSP_PS_ERR);
2784		} else {
2785			fpmstat &= ~(ENVCTRL_FSP_PS_ERR |
2786			    ENVCTRL_FSP_GEN_ERR);
2787		}
2788
2789	}
2790	envctrl_set_fsp(unitp, &fpmstat);
2791
2792	/*
2793	 * We need to reset all of the fans etc when a supply is
2794	 * interrupted and added, but we don't want to reset the
2795	 * fans if we are in DIAG mode. This will mess up SUNVTS.
2796	 */
2797	if (unitp->current_mode == ENVCTRL_NORMAL_MODE) {
2798		envctrl_get_sys_temperatures(unitp, (uint8_t *)NULL);
2799	}
2800}
2801
2802/*
2803 * consider key switch position when handling an abort sequence
2804 */
2805static void
2806envctrl_abort_seq_handler(char *msg)
2807{
2808	struct envctrlunit *unitp;
2809	int i;
2810	uint8_t secure = 0;
2811
2812	/*
2813	 * Find the instance of the device available on this host.
2814	 * Note that there may be only one, but the instance may
2815	 * not be zero.
2816	 */
2817	for (i = 0; i < MAX_DEVS; i++) {
2818		if (unitp = (struct envctrlunit *)
2819				ddi_get_soft_state(envctrlsoft_statep, i))
2820			break;
2821	}
2822
2823	ASSERT(unitp);
2824
2825	for (i = 0; i < MAX_DEVS; i++) {
2826		if ((unitp->encl_kstats[i].type == ENVCTRL_ENCL_FSP) &&
2827			(unitp->encl_kstats[i].instance != I2C_NODEV)) {
2828			secure = unitp->encl_kstats[i].value;
2829			break;
2830		}
2831	}
2832
2833	/*
2834	 * take the logical not because we are in hardware mode only
2835	 */
2836
2837	if ((secure & ENVCTRL_FSP_KEYMASK) == ENVCTRL_FSP_KEYLOCKED) {
2838			cmn_err(CE_CONT,
2839			    "!envctrl: ignoring debug enter sequence\n");
2840	} else {
2841		if (envctrl_debug_flags) {
2842			cmn_err(CE_CONT, "!envctrl: allowing debug enter\n");
2843		}
2844		debug_enter(msg);
2845	}
2846}
2847
2848/*
2849 * get the front Panel module LED and keyswitch status.
2850 * this part is addressed at 0x7C on the i2c bus.
2851 * called with mutex held
2852 */
2853static uint8_t
2854envctrl_get_fpm_status(struct envctrlunit *unitp)
2855{
2856	uint8_t recv_data;
2857	int status, retrys = 0;
2858
2859	ASSERT(MUTEX_HELD(&unitp->umutex));
2860
2861retry:
2862	status = eHc_read_pcf8574a((struct eHc_envcunit *)unitp,
2863		PCF8574A_BASE_ADDR | ENVCTRL_PCF8574_DEV6, &recv_data, 1);
2864
2865	/*
2866	 * yet another place where a read can cause the
2867	 * the SDA line of the i2c bus to get stuck low.
2868	 * this funky sequence frees the SDA line.
2869	 */
2870	if (status != DDI_SUCCESS) {
2871		drv_usecwait(1000);
2872		if (retrys < envctrl_max_retries) {
2873			retrys++;
2874			goto retry;
2875		} else {
2876			mutex_exit(&unitp->umutex);
2877			envctrl_init_bus(unitp);
2878			mutex_enter(&unitp->umutex);
2879			if (envctrl_debug_flags)
2880				cmn_err(CE_WARN, "Read from PCF8574 (FPM) "\
2881				    "failed\n");
2882		}
2883	}
2884	recv_data = ~recv_data;
2885	envctrl_mod_encl_kstats(unitp, ENVCTRL_ENCL_FSP,
2886	    INSTANCE_0, recv_data);
2887
2888	return (recv_data);
2889}
2890
2891static void
2892envctrl_set_fsp(struct envctrlunit *unitp, uint8_t *val)
2893{
2894	struct envctrl_pcf8574_chip chip;
2895
2896	ASSERT(MUTEX_HELD(&unitp->umutex));
2897
2898	chip.val = ENVCTRL_FSP_OFF; /* init all values to off */
2899	chip.chip_num = ENVCTRL_PCF8574_DEV6; /* 0x01 port 1 */
2900	chip.type = PCF8574A;
2901
2902	/*
2903	 * strip off bits that are R/O
2904	 */
2905	chip.val = (~(ENVCTRL_FSP_KEYMASK | ENVCTRL_FSP_POMASK) & (*val));
2906
2907	chip.val = ~chip.val;
2908	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&chip, PCF8574);
2909
2910}
2911
2912static int
2913envctrl_get_dskled(struct envctrlunit *unitp, struct envctrl_pcf8574_chip *chip)
2914{
2915	uint_t oldtype;
2916
2917	ASSERT(MUTEX_HELD(&unitp->umutex));
2918
2919	if (chip->chip_num > ENVCTRL_PCF8574_DEV2 ||
2920		chip->type != ENVCTRL_ENCL_BACKPLANE4 &&
2921		chip->type != ENVCTRL_ENCL_BACKPLANE8) {
2922		return (DDI_FAILURE);
2923	}
2924	oldtype = chip->type;
2925	chip->type = PCF8574;
2926	envctrl_recv(unitp, (caddr_t *)(void *)chip, PCF8574);
2927	chip->type = oldtype;
2928	chip->val = ~chip->val;
2929
2930	return (DDI_SUCCESS);
2931}
2932static int
2933envctrl_set_dskled(struct envctrlunit *unitp, struct envctrl_pcf8574_chip *chip)
2934{
2935
2936	struct envctrl_pcf8574_chip fspchip;
2937	struct envctrl_pcf8574_chip backchip;
2938	int i, instance;
2939	int diskfault = 0;
2940	uint8_t controller_addr[] = {ENVCTRL_PCF8574_DEV0, ENVCTRL_PCF8574_DEV1,
2941	    ENVCTRL_PCF8574_DEV2};
2942
2943	/*
2944	 * We need to check the type of disk led being set. If it
2945	 * is a 4 slot backplane then the upper 4 bits (7, 6, 5, 4) are
2946	 * invalid.
2947	 */
2948	ASSERT(MUTEX_HELD(&unitp->umutex));
2949
2950
2951	if (chip->chip_num > ENVCTRL_PCF8574_DEV2 ||
2952		chip->val > ENVCTRL_DISK8LED_ALLOFF ||
2953		chip->val < ENVCTRL_CHAR_ZERO) {
2954		return (DDI_FAILURE);
2955	}
2956
2957	if (chip->type != ENVCTRL_ENCL_BACKPLANE4 &&
2958	    chip->type != ENVCTRL_ENCL_BACKPLANE8) {
2959		return (DDI_FAILURE);
2960	}
2961
2962	/*
2963	 * Check all of the other controllwes LED states to make sure
2964	 * that there are no disk faults. If so then if the user is
2965	 * clearing the disk faults on this contoller, turn off
2966	 * the mass storage fault led.
2967	 */
2968
2969	backchip.type = PCF8574;
2970	for (i = 0; i <= MAX_TAZ_CONTROLLERS; i++) {
2971		if (controller_present[i] == -1)
2972			continue;
2973		backchip.chip_num = controller_addr[i];
2974		envctrl_recv(unitp, (caddr_t *)(void *)&backchip, PCF8574);
2975		if (chip->chip_num == controller_addr[i]) {
2976			if (chip->val != ENVCTRL_CHAR_ZERO)
2977				diskfault++;
2978		} else if ((~backchip.val & 0xFF) != ENVCTRL_CHAR_ZERO) {
2979			diskfault++;
2980		}
2981	}
2982
2983	fspchip.type = PCF8574A;
2984	fspchip.chip_num = ENVCTRL_PCF8574_DEV6; /* 0x01 port 1 */
2985	envctrl_recv(unitp, (caddr_t *)(void *)&fspchip, PCF8574);
2986
2987	if (diskfault) {
2988		if (!(envctrl_isother_fault_led(unitp, fspchip.val & 0xFF,
2989			ENVCTRL_FSP_DISK_ERR))) {
2990			fspchip.val &= ~(ENVCTRL_FSP_DISK_ERR);
2991		} else {
2992			fspchip.val &= ~(ENVCTRL_FSP_DISK_ERR |
2993			    ENVCTRL_FSP_GEN_ERR);
2994		}
2995		fspchip.val = (fspchip.val &
2996		    ~(ENVCTRL_FSP_DISK_ERR | ENVCTRL_FSP_GEN_ERR));
2997	} else {
2998		fspchip.val = (fspchip.val |
2999		    (ENVCTRL_FSP_DISK_ERR | ENVCTRL_FSP_GEN_ERR));
3000	}
3001	fspchip.type = PCF8574A;
3002	fspchip.chip_num = ENVCTRL_PCF8574_DEV6; /* 0x01 port 1 */
3003	(void) envctrl_xmit(unitp, (caddr_t *)(void *)&fspchip, PCF8574);
3004
3005	for (i = 0; i < (sizeof (backaddrs) / sizeof (uint8_t)); i++) {
3006		if (chip->chip_num == backaddrs[i]) {
3007			instance =  i;
3008		}
3009	}
3010
3011	switch (chip->type) {
3012	case ENVCTRL_ENCL_BACKPLANE4:
3013		envctrl_mod_encl_kstats(unitp, ENVCTRL_ENCL_BACKPLANE4,
3014		    instance, chip->val);
3015		break;
3016	case ENVCTRL_ENCL_BACKPLANE8:
3017		envctrl_mod_encl_kstats(unitp, ENVCTRL_ENCL_BACKPLANE8,
3018		    instance, chip->val);
3019		break;
3020	default:
3021		break;
3022	}
3023	chip->type = PCF8574;
3024	/*
3025	 * we take the ones compliment of the val passed in
3026	 * because the hardware thinks that a "low" or "0"
3027	 * is the way to indicate a fault. of course software
3028	 * knows that a 1 is a TRUE state or fault. ;-)
3029	 */
3030	chip->val = ~(chip->val);
3031	(void) envctrl_xmit(unitp, (caddr_t *)(void *)chip, PCF8574);
3032	return (DDI_SUCCESS);
3033}
3034
3035void
3036envctrl_add_kstats(struct envctrlunit *unitp)
3037{
3038
3039	ASSERT(MUTEX_HELD(&unitp->umutex));
3040
3041	if ((unitp->enclksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance,
3042	    ENVCTRL_KSTAT_ENCL, "misc", KSTAT_TYPE_RAW,
3043	    sizeof (unitp->encl_kstats),
3044	    KSTAT_FLAG_PERSISTENT)) == NULL) {
3045		cmn_err(CE_WARN, "envctrl%d: encl raw kstat_create failed",
3046			unitp->instance);
3047		return;
3048	}
3049
3050	unitp->enclksp->ks_update = envctrl_encl_kstat_update;
3051	unitp->enclksp->ks_private = (void *)unitp;
3052	kstat_install(unitp->enclksp);
3053
3054
3055	if ((unitp->fanksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance,
3056	    ENVCTRL_KSTAT_FANSTAT, "misc", KSTAT_TYPE_RAW,
3057	    sizeof (unitp->fan_kstats),
3058	    KSTAT_FLAG_PERSISTENT)) == NULL) {
3059		cmn_err(CE_WARN, "envctrl%d: fans kstat_create failed",
3060			unitp->instance);
3061		return;
3062	}
3063
3064	unitp->fanksp->ks_update = envctrl_fanstat_kstat_update;
3065	unitp->fanksp->ks_private = (void *)unitp;
3066	kstat_install(unitp->fanksp);
3067
3068	if ((unitp->psksp = kstat_create(ENVCTRL_MODULE_NAME, unitp->instance,
3069	    ENVCTRL_KSTAT_PSNAME, "misc", KSTAT_TYPE_RAW,
3070	    sizeof (unitp->ps_kstats),
3071	    KSTAT_FLAG_PERSISTENT)) == NULL) {
3072		cmn_err(CE_WARN, "envctrl%d: ps name kstat_create failed",
3073			unitp->instance);
3074		return;
3075	}
3076
3077	unitp->psksp->ks_update = envctrl_ps_kstat_update;
3078	unitp->psksp->ks_private = (void *)unitp;
3079	kstat_install(unitp->psksp);
3080
3081}
3082
3083int
3084envctrl_ps_kstat_update(kstat_t *ksp, int rw)
3085{
3086	struct envctrlunit *unitp;
3087	char *kstatp;
3088
3089
3090
3091	unitp = (struct envctrlunit *)ksp->ks_private;
3092
3093	mutex_enter(&unitp->umutex);
3094	ASSERT(MUTEX_HELD(&unitp->umutex));
3095
3096	kstatp = (char *)ksp->ks_data;
3097
3098	if (rw == KSTAT_WRITE) {
3099		return (EACCES);
3100	} else {
3101
3102		unitp->psksp->ks_ndata = unitp->num_ps_present;
3103		bcopy(&unitp->ps_kstats, kstatp, sizeof (unitp->ps_kstats));
3104	}
3105	mutex_exit(&unitp->umutex);
3106	return (DDI_SUCCESS);
3107}
3108int
3109envctrl_fanstat_kstat_update(kstat_t *ksp, int rw)
3110{
3111	struct envctrlunit *unitp;
3112	char *kstatp;
3113
3114	kstatp = (char *)ksp->ks_data;
3115	unitp = (struct envctrlunit *)ksp->ks_private;
3116
3117	mutex_enter(&unitp->umutex);
3118	ASSERT(MUTEX_HELD(&unitp->umutex));
3119
3120	if (rw == KSTAT_WRITE) {
3121		return (EACCES);
3122	} else {
3123		unitp->fanksp->ks_ndata = unitp->num_fans_present;
3124		bcopy(unitp->fan_kstats, kstatp, sizeof (unitp->fan_kstats));
3125	}
3126	mutex_exit(&unitp->umutex);
3127	return (DDI_SUCCESS);
3128}
3129
3130int
3131envctrl_encl_kstat_update(kstat_t *ksp, int rw)
3132{
3133	struct envctrlunit *unitp;
3134	char *kstatp;
3135
3136
3137	kstatp = (char *)ksp->ks_data;
3138	unitp = (struct envctrlunit *)ksp->ks_private;
3139
3140	mutex_enter(&unitp->umutex);
3141	ASSERT(MUTEX_HELD(&unitp->umutex));
3142
3143	if (rw == KSTAT_WRITE) {
3144		return (EACCES);
3145	} else {
3146
3147		unitp->enclksp->ks_ndata = unitp->num_encl_present;
3148		(void) envctrl_get_fpm_status(unitp);
3149		/* XXX Need to ad disk updates too ??? */
3150		bcopy(unitp->encl_kstats, kstatp, sizeof (unitp->encl_kstats));
3151	}
3152	mutex_exit(&unitp->umutex);
3153	return (DDI_SUCCESS);
3154}
3155
3156/*
3157 * called with unitp lock held
3158 * type, fanspeed and fanflt will be set by the service routines
3159 */
3160static void
3161envctrl_init_fan_kstats(struct envctrlunit *unitp)
3162{
3163	int i;
3164
3165	ASSERT(MUTEX_HELD(&unitp->umutex));
3166
3167	for (i = 0; i < unitp->num_fans_present; i++) {
3168		unitp->fan_kstats[i].instance = 0;
3169		unitp->fan_kstats[i].type = 0;
3170		unitp->fan_kstats[i].fans_ok = B_TRUE;
3171		unitp->fan_kstats[i].fanflt_num = B_FALSE;
3172		unitp->fan_kstats[i].fanspeed = B_FALSE;
3173	}
3174
3175	unitp->fan_kstats[ENVCTRL_FAN_TYPE_PS].type = ENVCTRL_FAN_TYPE_PS;
3176	unitp->fan_kstats[ENVCTRL_FAN_TYPE_CPU].type = ENVCTRL_FAN_TYPE_CPU;
3177	if (unitp->AFB_present == B_TRUE)
3178		unitp->fan_kstats[ENVCTRL_FAN_TYPE_AFB].type =
3179			ENVCTRL_FAN_TYPE_AFB;
3180}
3181
3182static void
3183envctrl_init_encl_kstats(struct envctrlunit *unitp)
3184{
3185
3186	int i;
3187	uint8_t val;
3188	struct envctrl_pcf8574_chip chip;
3189	int *reg_prop;
3190	uint_t len = 0;
3191
3192	ASSERT(MUTEX_HELD(&unitp->umutex));
3193
3194	for (i = 0; i < MAX_DEVS; i++) {
3195		unitp->encl_kstats[i].instance = I2C_NODEV;
3196	}
3197
3198	/*
3199	 * add in kstats now
3200	 * We ALWAYS HAVE THE FOLLOWING
3201	 * 1. FSP
3202	 * 2. AMB TEMPR
3203	 * 3. (1) CPU TEMPR
3204	 * 4. (1) 4 slot disk backplane
3205	 * OPTIONAL
3206	 * 8 slot backplane
3207	 * more cpu's
3208	 */
3209
3210	chip.type = PCF8574A;
3211	chip.chip_num = ENVCTRL_PCF8574_DEV6; /* 0x01 port 1 */
3212	envctrl_recv(unitp, (caddr_t *)(void *)&chip, PCF8574);
3213
3214	envctrl_add_encl_kstats(unitp, ENVCTRL_ENCL_FSP, INSTANCE_0,
3215		chip.val & 0xFF);
3216
3217	val = envctrl_get_lm75_temp(unitp) & 0xFF;
3218	envctrl_add_encl_kstats(unitp, ENVCTRL_ENCL_AMBTEMPR, INSTANCE_0, val);
3219
3220	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, unitp->dip,
3221			DDI_PROP_DONTPASS, ENVCTRL_DISK_LEDS_PR,
3222			&reg_prop, &len) != DDI_PROP_SUCCESS) {
3223		cmn_err(CE_WARN, "prop lookup of %s failed\n",
3224			ENVCTRL_DISK_LEDS_PR);
3225		return;
3226	}
3227
3228	ASSERT(len != 0);
3229
3230	chip.type = PCF8574;
3231
3232	for (i = 0; i < len; i++) {
3233		chip.chip_num = backaddrs[i];
3234		if (reg_prop[i] == ENVCTRL_4SLOT_BACKPLANE) {
3235			envctrl_recv(unitp, (caddr_t *)(void *)&chip, PCF8574);
3236			envctrl_add_encl_kstats(unitp, ENVCTRL_ENCL_BACKPLANE4,
3237			    i, ~chip.val);
3238			controller_present[i] = 1;
3239		}
3240		if (reg_prop[i] == ENVCTRL_8SLOT_BACKPLANE) {
3241			envctrl_recv(unitp, (caddr_t *)(void *)&chip, PCF8574);
3242			envctrl_add_encl_kstats(unitp, ENVCTRL_ENCL_BACKPLANE8,
3243			    i, ~chip.val);
3244			controller_present[i] = 1;
3245		}
3246	}
3247	ddi_prop_free((void *)reg_prop);
3248
3249}
3250
3251static void
3252envctrl_mod_encl_kstats(struct envctrlunit *unitp, int type,
3253    int instance, uint8_t val)
3254{
3255	int i = 0;
3256	boolean_t inserted = B_FALSE;
3257
3258	ASSERT(MUTEX_HELD(&unitp->umutex));
3259
3260	while (i < MAX_DEVS && inserted == B_FALSE) {
3261		if (unitp->encl_kstats[i].instance == instance &&
3262		    unitp->encl_kstats[i].type == type) {
3263			unitp->encl_kstats[i].value = val;
3264			inserted = B_TRUE;
3265		}
3266		i++;
3267	}
3268}
3269
3270static void
3271envctrl_probe_cpus(struct envctrlunit *unitp)
3272{
3273	int instance;
3274
3275	/*
3276	 * The cpu search is as follows:
3277	 * If there is only 1 CPU module it is named as
3278	 * SUNW,UltraSPARC. If this is a match we still don't
3279	 * know what slot the cpu module is in therefore
3280	 * we need to check the "upa-portid" property.
3281	 * If we have more than 1 cpu, then they are appended by
3282	 * instance numbers and slot locations. e.g.
3283	 * SUNW,UltraSPARC@1,0 (slot 1). it would have been
3284	 * nice to have the naming consistent for one CPU e.g.
3285	 * SUNW,UltraSPARC@0,0...sigh
3286	 */
3287
3288	for (instance = 0; instance < ENVCTRL_MAX_CPUS; instance++) {
3289		unitp->cpu_pr_location[instance] = B_FALSE;
3290	}
3291
3292	ddi_walk_devs(ddi_root_node(), envctrl_match_cpu, unitp);
3293}
3294
3295static int
3296envctrl_match_cpu(dev_info_t *dip, void *arg)
3297{
3298
3299	int cpu_slot;
3300	char name[32];
3301	char name1[32];
3302	struct envctrlunit *unitp = (struct envctrlunit *)arg;
3303
3304	(void) sprintf(name, "%s", ENVCTRL_TAZCPU_STRING);
3305	(void) sprintf(name1, "%s", ENVCTRL_TAZBLKBRDCPU_STRING);
3306
3307	if ((strcmp(ddi_node_name(dip), name) == 0) ||
3308		(strcmp(ddi_node_name(dip), name1) == 0)) {
3309		if ((cpu_slot = (int)ddi_getprop(DDI_DEV_T_ANY, dip,
3310			    DDI_PROP_DONTPASS, "upa-portid",
3311				    -1)) == -1) {
3312			cmn_err(CE_WARN, "envctrl no cpu upa-portid");
3313		} else {
3314			unitp->cpu_pr_location[cpu_slot] = B_TRUE;
3315			unitp->num_cpus_present++;
3316		}
3317	}
3318
3319	return (DDI_WALK_CONTINUE);
3320}
3321
3322/*
3323 * This routine returns TRUE if some other error condition
3324 * has set the GEN_ERR FAULT LED. Tp further complicate this
3325 * LED panel we have overloaded the GEN_ERR LED to indicate
3326 * that a fan fault has occurred without having a fan fault
3327 * LED as does all other error conditions. So we just take the
3328 * software state and return true. The whole purpose of this functon
3329 * is to tell us wehther or not we can shut off the GEN_FAULT LED.
3330 * NOTE: this ledval is usually one of the following FSP vals
3331 * EXCEPT in the case of the fan fail.. we pass in a "0".
3332 */
3333
3334static int
3335envctrl_isother_fault_led(struct envctrlunit *unitp, uint8_t fspval,
3336    uint8_t thisled)
3337{
3338	int status = B_FALSE;
3339
3340	if (fspval != 0) {
3341		fspval = (fspval & ~(thisled));
3342	}
3343	if (unitp->num_fans_failed > 0 && thisled != 0) {
3344		status = B_TRUE;
3345	} else if (fspval & ENVCTRL_FSP_DISK_ERR) {
3346		status = B_TRUE;
3347	} else if (fspval & ENVCTRL_FSP_PS_ERR) {
3348		status = B_TRUE;
3349	} else if (fspval & ENVCTRL_FSP_TEMP_ERR) {
3350		status = B_TRUE;
3351	}
3352	return (status);
3353}
3354
3355static void
3356envctrl_pshotplug_poll(void *arg)
3357{
3358	struct envctrlunit *unitp = (struct envctrlunit *)arg;
3359
3360	mutex_enter(&unitp->umutex);
3361
3362	envctrl_ps_probe(unitp);
3363
3364	mutex_exit(&unitp->umutex);
3365}
3366
3367/*
3368 * The following routines implement the i2c protocol.
3369 * They should be removed once the envctrl_targets.c file is included.
3370 */
3371
3372/*
3373 * put host interface into master mode
3374 */
3375static int
3376eHc_start_pcf8584(struct eHc_envcunit *ehcp, uint8_t byteaddress)
3377{
3378	uint8_t poll_status;
3379	uint8_t discard;
3380	int i;
3381
3382	/* wait if bus is busy */
3383
3384	i = 0;
3385	do {
3386		drv_usecwait(1000);
3387		poll_status =
3388			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
3389		i++;
3390	} while (((poll_status & EHC_S1_NBB) == 0) && i < EHC_MAX_WAIT);
3391
3392	if (i == EHC_MAX_WAIT) {
3393		DCMNERR(CE_WARN, "eHc_start_pcf8584: I2C bus busy");
3394		return (EHC_FAILURE);
3395	}
3396
3397	if (poll_status & EHC_S1_BER) {
3398		DCMN2ERR(CE_WARN, "eHc_start_pcf8584: I2C bus error");
3399		return (EHC_FAILURE);
3400	}
3401
3402	if (poll_status & EHC_S1_LAB) {
3403		DCMN2ERR(CE_WARN, "eHc_start_pcf8584: Lost arbitration");
3404		return (EHC_FAILURE);
3405	}
3406
3407	/* load the slave address */
3408	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, byteaddress);
3409
3410	/* generate the "start condition" and clock out the slave address */
3411	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
3412		EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK);
3413
3414	/* wait for completion of transmission */
3415	i = 0;
3416	do {
3417		drv_usecwait(1000);
3418		poll_status =
3419			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
3420		i++;
3421	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
3422
3423	if (i == EHC_MAX_WAIT) {
3424		DCMNERR(CE_WARN, "eHc_start_pcf8584: I2C bus busy");
3425		return (EHC_FAILURE);
3426	}
3427
3428	if (poll_status & EHC_S1_BER) {
3429		DCMN2ERR(CE_WARN, "eHc_start_pcf8584: I2C bus error");
3430		return (EHC_FAILURE);
3431	}
3432
3433	if (poll_status & EHC_S1_LAB) {
3434		DCMN2ERR(CE_WARN, "eHc_start_pcf8584: Lost arbitration");
3435		return (EHC_FAILURE);
3436	}
3437
3438	if (poll_status & EHC_S1_LRB) {
3439		DCMNERR(CE_WARN, "eHc_start_pcf8584: No slave ACK");
3440		return (EHC_NO_SLAVE_ACK);
3441	}
3442
3443	/*
3444	 * If this is a read we are setting up for (as indicated by
3445	 * the least significant byte being set), read
3446	 * and discard the first byte off the bus - this
3447	 * is the slave address.
3448	 */
3449
3450	i = 0;
3451	if (byteaddress & EHC_BYTE_READ) {
3452		discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
3453#ifdef lint
3454		discard = discard;
3455#endif
3456
3457		/* wait for completion of transmission */
3458		do {
3459			drv_usecwait(1000);
3460			poll_status =
3461			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
3462			i++;
3463		} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
3464
3465		if (i == EHC_MAX_WAIT) {
3466			DCMNERR(CE_WARN, "eHc_start_pcf8584: I2C bus busy");
3467			return (EHC_FAILURE);
3468		}
3469
3470		if (poll_status & EHC_S1_BER) {
3471			DCMN2ERR(CE_WARN,
3472				"eHc_start_pcf8584: I2C bus error");
3473			return (EHC_FAILURE);
3474		}
3475
3476		if (poll_status & EHC_S1_LAB) {
3477			DCMN2ERR(CE_WARN,
3478				"eHc_start_pcf8584: Lost arbitration");
3479			return (EHC_FAILURE);
3480		}
3481	}
3482
3483	return (EHC_SUCCESS);
3484}
3485
3486/*
3487 * put host interface into slave/receiver mode
3488 */
3489static void
3490eHc_stop_pcf8584(struct eHc_envcunit *ehcp)
3491{
3492	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
3493		EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_STO | EHC_S1_ACK);
3494}
3495
3496static int
3497eHc_read_pcf8584(struct eHc_envcunit *ehcp, uint8_t *data)
3498{
3499	uint8_t poll_status;
3500	int i = 0;
3501
3502	/* Read the byte of interest */
3503	*data = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
3504
3505	/* wait for completion of transmission */
3506	do {
3507		drv_usecwait(1000);
3508		poll_status =
3509			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
3510		i++;
3511	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
3512
3513	if (i == EHC_MAX_WAIT) {
3514		DCMNERR(CE_WARN, "eHc_read_pcf8584: I2C bus busy");
3515		return (EHC_FAILURE);
3516	}
3517
3518	if (poll_status & EHC_S1_BER) {
3519		DCMN2ERR(CE_WARN, "eHc_read_pcf8584: I2C bus error");
3520		return (EHC_FAILURE);
3521	}
3522
3523	if (poll_status & EHC_S1_LAB) {
3524		DCMN2ERR(CE_WARN, "eHc_read_pcf8584: Lost arbitration");
3525		return (EHC_FAILURE);
3526	}
3527
3528	return (EHC_SUCCESS);
3529}
3530
3531/*
3532 * host interface is in transmitter state, thus mode is master/transmitter
3533 * NOTE to Bill: this check the LRB bit (only done in transmit mode).
3534 */
3535
3536static int
3537eHc_write_pcf8584(struct eHc_envcunit *ehcp, uint8_t data)
3538{
3539	uint8_t poll_status;
3540	int i = 0;
3541
3542	/* send the data, EHC_S1_PIN should go to "1" immediately */
3543	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, data);
3544
3545	/* wait for completion of transmission */
3546	do {
3547		drv_usecwait(1000);
3548		poll_status =
3549			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
3550		i++;
3551	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
3552
3553	if (i == EHC_MAX_WAIT) {
3554		DCMNERR(CE_WARN, "eHc_write_pcf8584: I2C bus busy");
3555		return (EHC_FAILURE);
3556	}
3557
3558	if (poll_status & EHC_S1_BER) {
3559		DCMN2ERR(CE_WARN, "eHc_write_pcf8584: I2C bus error");
3560		return (EHC_FAILURE);
3561	}
3562
3563	if (poll_status & EHC_S1_LAB) {
3564		DCMN2ERR(CE_WARN, "eHc_write_pcf8584: Lost arbitration");
3565		return (EHC_FAILURE);
3566	}
3567
3568	if (poll_status & EHC_S1_LRB) {
3569		DCMNERR(CE_WARN, "eHc_write_pcf8584: No slave ACK");
3570		return (EHC_NO_SLAVE_ACK);
3571	}
3572
3573	return (EHC_SUCCESS);
3574}
3575
3576static int
3577eHc_after_read_pcf8584(struct eHc_envcunit *ehcp, uint8_t *data)
3578{
3579	uint8_t discard;
3580	uint8_t poll_status;
3581	int i = 0;
3582
3583	/* set ACK in register S1 to 0 */
3584	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_ES0);
3585
3586	/*
3587	 * Read the "byte-before-the-last-byte" - sets PIN bit to '1'
3588	 */
3589
3590	*data = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
3591
3592	/* wait for completion of transmission */
3593	do {
3594		drv_usecwait(1000);
3595		poll_status =
3596			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
3597		i++;
3598	} while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
3599
3600	if (i == EHC_MAX_WAIT) {
3601		DCMNERR(CE_WARN, "eHc_after_read_pcf8584: I2C bus busy");
3602		return (EHC_FAILURE);
3603	}
3604
3605	if (poll_status & EHC_S1_BER) {
3606		DCMN2ERR(CE_WARN,
3607			"eHc_after_read_pcf8584: I2C bus error");
3608		return (EHC_FAILURE);
3609	}
3610
3611	if (poll_status & EHC_S1_LAB) {
3612		DCMN2ERR(CE_WARN, "eHc_after_read_pcf8584: Lost arbitration");
3613		return (EHC_FAILURE);
3614	}
3615
3616	/*
3617	 * Generate the "stop" condition.
3618	 */
3619	eHc_stop_pcf8584(ehcp);
3620
3621	/*
3622	 * Read the "last" byte.
3623	 */
3624	discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
3625#ifdef lint
3626	discard = discard;
3627#endif
3628
3629	return (EHC_SUCCESS);
3630}
3631
3632/*
3633 * Write to the TDA8444 chip.
3634 * byteaddress = chip type base address | chip offset address.
3635 */
3636static int
3637eHc_write_tda8444(struct eHc_envcunit *ehcp, int byteaddress, int instruction,
3638	int subaddress, uint8_t *buf, int size)
3639{
3640	uint8_t control;
3641	int i, status;
3642
3643	ASSERT((byteaddress & 0x1) == 0);
3644	ASSERT(subaddress < 8);
3645	ASSERT(instruction == 0xf || instruction == 0x0);
3646	ASSERT(MUTEX_HELD(&ehcp->umutex));
3647
3648	control = (instruction << 4) | subaddress;
3649
3650	if ((status = eHc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
3651		if (status == EHC_NO_SLAVE_ACK) {
3652			/*
3653			 * Send the "stop" condition.
3654			 */
3655			eHc_stop_pcf8584(ehcp);
3656		}
3657		return (EHC_FAILURE);
3658	}
3659
3660	if ((status = eHc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) {
3661		if (status == EHC_NO_SLAVE_ACK) {
3662		/*
3663		 * Send the "stop" condition.
3664		 */
3665		eHc_stop_pcf8584(ehcp);
3666		}
3667		return (EHC_FAILURE);
3668	}
3669
3670	for (i = 0; i < size; i++) {
3671		if ((status = eHc_write_pcf8584(ehcp, (buf[i] & 0x3f))) !=
3672			EHC_SUCCESS) {
3673			if (status == EHC_NO_SLAVE_ACK)
3674				eHc_stop_pcf8584(ehcp);
3675			return (EHC_FAILURE);
3676		}
3677	}
3678
3679	eHc_stop_pcf8584(ehcp);
3680
3681	return (EHC_SUCCESS);
3682}
3683
3684/*
3685 * Read from PCF8574A chip.
3686 * byteaddress = chip type base address | chip offset address.
3687 */
3688static int
3689eHc_read_pcf8574a(struct eHc_envcunit *ehcp, int byteaddress, uint8_t *buf,
3690	int size)
3691{
3692	int i;
3693	int status;
3694	uint8_t discard;
3695
3696	ASSERT((byteaddress & 0x1) == 0);
3697	ASSERT(MUTEX_HELD(&ehcp->umutex));
3698
3699	/*
3700	 * Put the bus into the start condition
3701	 */
3702	if ((status = eHc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
3703			EHC_SUCCESS) {
3704		if (status == EHC_NO_SLAVE_ACK) {
3705			/*
3706			 * Send the "stop" condition.
3707			 */
3708			eHc_stop_pcf8584(ehcp);
3709			/*
3710			 * Read the last byte - discard it.
3711			 */
3712			discard =
3713			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
3714#ifdef lint
3715			discard = discard;
3716#endif
3717		}
3718		return (EHC_FAILURE);
3719	}
3720
3721	for (i = 0; i < size - 1; i++) {
3722		if ((status = eHc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
3723			return (EHC_FAILURE);
3724		}
3725	}
3726
3727	/*
3728	 * Handle the part of the bus protocol which comes
3729	 * after a read, including reading the last byte.
3730	 */
3731
3732	if (eHc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
3733		return (EHC_FAILURE);
3734	}
3735
3736	return (EHC_SUCCESS);
3737}
3738
3739/*
3740 * Write to the PCF8574A chip.
3741 * byteaddress = chip type base address | chip offset address.
3742 */
3743static int
3744eHc_write_pcf8574a(struct eHc_envcunit *ehcp, int byteaddress, uint8_t *buf,
3745	int size)
3746{
3747	int i;
3748	int status;
3749
3750	ASSERT((byteaddress & 0x1) == 0);
3751	ASSERT(MUTEX_HELD(&ehcp->umutex));
3752
3753	/*
3754	 * Put the bus into the start condition (write)
3755	 */
3756	if ((status = eHc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
3757		if (status == EHC_NO_SLAVE_ACK) {
3758			/*
3759			 * Send the "stop" condition.
3760			 */
3761			eHc_stop_pcf8584(ehcp);
3762		}
3763		return (EHC_FAILURE);
3764	}
3765
3766	/*
3767	 * Send the data - poll as needed.
3768	 */
3769	for (i = 0; i < size; i++) {
3770		if ((status = eHc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
3771			if (status == EHC_NO_SLAVE_ACK)
3772				eHc_stop_pcf8584(ehcp);
3773			return (EHC_FAILURE);
3774		}
3775	}
3776
3777	/*
3778	 * Transmission complete - generate stop condition and
3779	 * put device back into slave receiver mode.
3780	 */
3781	eHc_stop_pcf8584(ehcp);
3782
3783	return (EHC_SUCCESS);
3784}
3785
3786/*
3787 * Read from the PCF8574 chip.
3788 * byteaddress = chip type base address | chip offset address.
3789 */
3790static int
3791eHc_read_pcf8574(struct eHc_envcunit *ehcp, int byteaddress, uint8_t *buf,
3792	int size)
3793{
3794	int i;
3795	int status;
3796	uint8_t discard;
3797
3798	ASSERT((byteaddress & 0x1) == 0);
3799	ASSERT(MUTEX_HELD(&ehcp->umutex));
3800
3801	/*
3802	 * Put the bus into the start condition
3803	 */
3804	if ((status = eHc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
3805			EHC_SUCCESS) {
3806		if (status == EHC_NO_SLAVE_ACK) {
3807			/*
3808			 * Send the "stop" condition.
3809			 */
3810			eHc_stop_pcf8584(ehcp);
3811			/*
3812			 * Read the last byte - discard it.
3813			 */
3814			discard =
3815			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
3816#ifdef lint
3817			discard = discard;
3818#endif
3819		}
3820		return (EHC_FAILURE);
3821	}
3822
3823	for (i = 0; i < size - 1; i++) {
3824		if ((status = eHc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
3825		return (EHC_FAILURE);
3826		}
3827	}
3828
3829	/*
3830	 * Handle the part of the bus protocol which comes
3831	 * after a read.
3832	 */
3833
3834	if (eHc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
3835		return (EHC_FAILURE);
3836	}
3837
3838	return (EHC_SUCCESS);
3839}
3840
3841/*
3842 * Write to the PCF8574 chip.
3843 * byteaddress = chip type base address | chip offset address.
3844 */
3845static int
3846eHc_write_pcf8574(struct eHc_envcunit *ehcp, int byteaddress, uint8_t *buf,
3847	int size)
3848{
3849	int i;
3850	int status;
3851
3852	ASSERT((byteaddress & 0x1) == 0);
3853	ASSERT(MUTEX_HELD(&ehcp->umutex));
3854
3855	/*
3856	 * Put the bus into the start condition (write)
3857	 */
3858	if ((status = eHc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
3859		if (status == EHC_NO_SLAVE_ACK) {
3860			/*
3861			 * Send the "stop" condition.
3862			 */
3863			eHc_stop_pcf8584(ehcp);
3864		}
3865		return (EHC_FAILURE);
3866	}
3867
3868	/*
3869	 * Send the data - poll as needed.
3870	 */
3871	for (i = 0; i < size; i++) {
3872		if ((status = eHc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
3873			if (status == EHC_NO_SLAVE_ACK)
3874				eHc_stop_pcf8584(ehcp);
3875			return (EHC_FAILURE);
3876		}
3877	}
3878	/*
3879	 * Transmission complete - generate stop condition and
3880	 * put device back into slave receiver mode.
3881	 */
3882	eHc_stop_pcf8584(ehcp);
3883
3884	return (EHC_SUCCESS);
3885}
3886
3887/*
3888 * Read from the LM75
3889 * byteaddress = chip type base address | chip offset address.
3890 */
3891static int
3892eHc_read_lm75(struct eHc_envcunit *ehcp, int byteaddress, uint8_t *buf,
3893	int size)
3894{
3895	int i;
3896	int status;
3897	uint8_t discard;
3898
3899	ASSERT((byteaddress & 0x1) == 0);
3900	ASSERT(MUTEX_HELD(&ehcp->umutex));
3901
3902	/*
3903	 * Put the bus into the start condition
3904	 */
3905	if ((status = eHc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) !=
3906			EHC_SUCCESS) {
3907		if (status == EHC_NO_SLAVE_ACK) {
3908			/*
3909			 * Send the stop condition.
3910			 */
3911			eHc_stop_pcf8584(ehcp);
3912			/*
3913			 * Read the last byte - discard it.
3914			 */
3915			discard =
3916			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
3917#ifdef lint
3918			discard = discard;
3919#endif
3920		}
3921		return (EHC_FAILURE);
3922	}
3923
3924	for (i = 0; i < size - 1; i++) {
3925		if ((status = eHc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
3926		return (EHC_FAILURE);
3927		}
3928	}
3929
3930	/*
3931	 * Handle the part of the bus protocol which comes
3932	 * after a read.
3933	 */
3934	if (eHc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
3935		return (EHC_FAILURE);
3936	}
3937
3938	return (EHC_SUCCESS);
3939}
3940
3941/*
3942 * Write to the PCF8583 chip.
3943 * byteaddress = chip type base address | chip offset address.
3944 */
3945static int
3946eHc_write_pcf8583(struct eHc_envcunit *ehcp, int byteaddress, uint8_t *buf,
3947	int size)
3948{
3949	int i;
3950	int status;
3951
3952	ASSERT((byteaddress & 0x1) == 0);
3953	ASSERT(MUTEX_HELD(&ehcp->umutex));
3954
3955	if ((status = eHc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
3956		if (status == EHC_NO_SLAVE_ACK) {
3957			/*
3958			 * Send the "stop" condition.
3959			 */
3960			eHc_stop_pcf8584(ehcp);
3961		}
3962		return (EHC_FAILURE);
3963	}
3964
3965	/*
3966	 * Send the data - poll as needed.
3967	 */
3968	for (i = 0; i < size; i++) {
3969		if ((status = eHc_write_pcf8584(ehcp, buf[i])) != EHC_SUCCESS) {
3970			if (status == EHC_NO_SLAVE_ACK)
3971				eHc_stop_pcf8584(ehcp);
3972			return (EHC_FAILURE);
3973		}
3974	}
3975
3976	/*
3977	 * Transmission complete - generate stop condition and
3978	 * put device back into slave receiver mode.
3979	 */
3980	eHc_stop_pcf8584(ehcp);
3981
3982	return (EHC_SUCCESS);
3983}
3984
3985/*
3986 * Read from the PCF8581 chip.
3987 * byteaddress = chip type base address | chip offset address.
3988 */
3989static int
3990eHc_read_pcf8591(struct eHc_envcunit *ehcp, int byteaddress, int channel,
3991	int autoinc, int amode, int aenable, uint8_t *buf, int size)
3992{
3993	int i;
3994	int status;
3995	uint8_t control;
3996	uint8_t discard;
3997
3998	ASSERT((byteaddress & 0x1) == 0);
3999	ASSERT(channel < 4);
4000	ASSERT(amode < 4);
4001	ASSERT(MUTEX_HELD(&ehcp->umutex));
4002
4003	/*
4004	 * Write the control word to the PCF8591.
4005	 * Follow the control word with a repeated START byte
4006	 * rather than a STOP so that reads can follow without giving
4007	 * up the bus.
4008	 */
4009
4010	control = ((aenable << 6) | (amode << 4) | (autoinc << 2) | channel);
4011
4012	if ((status = eHc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) {
4013		if (status == EHC_NO_SLAVE_ACK) {
4014			eHc_stop_pcf8584(ehcp);
4015		}
4016		return (EHC_FAILURE);
4017	}
4018
4019	if ((status = eHc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) {
4020		if (status == EHC_NO_SLAVE_ACK)
4021			eHc_stop_pcf8584(ehcp);
4022		return (EHC_FAILURE);
4023	}
4024
4025	/*
4026	 * The following two operations, 0x45 to S1, and the byteaddress
4027	 * to S0, will result in a repeated START being sent out on the bus.
4028	 * Refer to Fig.8 of Philips Semiconductors PCF8584 product spec.
4029	 */
4030
4031	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1,
4032		EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK);
4033
4034	ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0,
4035		EHC_BYTE_READ | byteaddress);
4036
4037	i = 0;
4038
4039	do {
4040		drv_usecwait(1000);
4041		status =
4042			ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1);
4043		i++;
4044	} while ((status & EHC_S1_PIN) && i < EHC_MAX_WAIT);
4045
4046	if (i == EHC_MAX_WAIT) {
4047		DCMNERR(CE_WARN, "eHc_read_pcf8591(): read of S1 failed");
4048		return (EHC_FAILURE);
4049	}
4050
4051	if (status & EHC_S1_LRB) {
4052		DCMNERR(CE_WARN, "eHc_read_pcf8591(): No slave ACK");
4053		/*
4054		 * Send the stop condition.
4055		 */
4056		eHc_stop_pcf8584(ehcp);
4057		/*
4058		 * Read the last byte - discard it.
4059		 */
4060		discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0);
4061#ifdef lint
4062		discard = discard;
4063#endif
4064		return (EHC_FAILURE);
4065	}
4066
4067	if (status & EHC_S1_BER) {
4068		DCMN2ERR(CE_WARN, "eHc_read_pcf8591(): Bus error");
4069		return (EHC_FAILURE);
4070	}
4071
4072	if (status & EHC_S1_LAB) {
4073		DCMN2ERR(CE_WARN, "eHc_read_pcf8591(): Lost Arbitration");
4074		return (EHC_FAILURE);
4075	}
4076
4077	/*
4078	 * Discard first read as per PCF8584 master receiver protocol.
4079	 * This is normally done in the eHc_start_pcf8584() routine.
4080	 */
4081	if ((status = eHc_read_pcf8584(ehcp, &discard)) != EHC_SUCCESS) {
4082		return (EHC_FAILURE);
4083	}
4084
4085	/* Discard second read as per PCF8591 protocol */
4086	if ((status = eHc_read_pcf8584(ehcp, &discard)) != EHC_SUCCESS) {
4087		return (EHC_FAILURE);
4088	}
4089
4090	for (i = 0; i < size - 1; i++) {
4091		if ((status = eHc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) {
4092			return (EHC_FAILURE);
4093		}
4094	}
4095
4096	if (eHc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) {
4097		return (EHC_FAILURE);
4098	}
4099
4100	return (EHC_SUCCESS);
4101}
4102