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