xref: /illumos-gate/usr/src/uts/sun4u/sunfire/io/sysctrl.c (revision ef150c2b133e57069ae0f58d5d80cef8980ac9c3)
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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
26  */
27 
28 /*
29  * Copyright 2023 Oxide Computer Company
30  */
31 
32 
33 #include <sys/types.h>
34 #include <sys/conf.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 #include <sys/ddi_impldefs.h>
38 #include <sys/sunndi.h>
39 #include <sys/ndi_impldefs.h>
40 #include <sys/obpdefs.h>
41 #include <sys/cmn_err.h>
42 #include <sys/errno.h>
43 #include <sys/kmem.h>
44 #include <sys/debug.h>
45 #include <sys/sysmacros.h>
46 #include <sys/ivintr.h>
47 #include <sys/autoconf.h>
48 #include <sys/intreg.h>
49 #include <sys/proc.h>
50 #include <sys/modctl.h>
51 #include <sys/callb.h>
52 #include <sys/file.h>
53 #include <sys/open.h>
54 #include <sys/stat.h>
55 #include <sys/fhc.h>
56 #include <sys/sysctrl.h>
57 #include <sys/jtag.h>
58 #include <sys/ac.h>
59 #include <sys/simmstat.h>
60 #include <sys/clock.h>
61 #include <sys/promif.h>
62 #include <sys/promimpl.h>
63 #include <sys/sunndi.h>
64 #include <sys/machsystm.h>
65 
66 /* Useful debugging Stuff */
67 #ifdef DEBUG
68 int sysc_debug_info = 1;
69 int sysc_debug_print_level = 0;
70 #endif
71 
72 /*
73  * Function prototypes
74  */
75 static int sysctrl_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
76 		void **result);
77 
78 static int sysctrl_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
79 
80 static int sysctrl_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
81 
82 static int sysctrl_open(dev_t *, int, int, cred_t *);
83 
84 static int sysctrl_close(dev_t, int, int, cred_t *);
85 
86 static int sysctrl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
87 
88 static uint_t system_high_handler(caddr_t arg);
89 
90 static uint_t spur_delay(caddr_t arg);
91 
92 static void spur_retry(void *);
93 
94 static uint_t spur_reenable(caddr_t arg);
95 
96 static void spur_long_timeout(void *);
97 
98 static uint_t spur_clear_count(caddr_t arg);
99 
100 static uint_t ac_fail_handler(caddr_t arg);
101 
102 static void ac_fail_retry(void *);
103 
104 static uint_t ac_fail_reenable(caddr_t arg);
105 
106 static uint_t ps_fail_int_handler(caddr_t arg);
107 
108 static uint_t ps_fail_poll_handler(caddr_t arg);
109 
110 static uint_t ps_fail_handler(struct sysctrl_soft_state *softsp, int fromint);
111 
112 enum power_state compute_power_state(struct sysctrl_soft_state *softsp,
113 					int plus_load);
114 
115 static void ps_log_state_change(struct sysctrl_soft_state *softsp,
116 					int index, int present);
117 
118 static void ps_log_pres_change(struct sysctrl_soft_state *softsp,
119 					int index, int present);
120 
121 static void ps_fail_retry(void *);
122 
123 static uint_t pps_fanfail_handler(caddr_t arg);
124 
125 static void pps_fanfail_retry(void *);
126 
127 static uint_t pps_fanfail_reenable(caddr_t arg);
128 
129 static void pps_fan_poll(void *);
130 
131 static void pps_fan_state_change(struct sysctrl_soft_state *softsp,
132 					int index, int fan_ok);
133 
134 static uint_t bd_insert_handler(caddr_t arg);
135 
136 static void bd_insert_timeout(void *);
137 
138 static void bd_remove_timeout(void *);
139 
140 static uint_t bd_insert_normal(caddr_t arg);
141 
142 static void sysctrl_add_kstats(struct sysctrl_soft_state *softsp);
143 
144 static int sysctrl_kstat_update(kstat_t *ksp, int rw);
145 
146 static int psstat_kstat_update(kstat_t *, int);
147 
148 static void init_remote_console_uart(struct sysctrl_soft_state *);
149 
150 static void blink_led_timeout(void *);
151 
152 static uint_t blink_led_handler(caddr_t arg);
153 
154 static void sysctrl_thread_wakeup(void *type);
155 
156 static void sysctrl_overtemp_poll(void);
157 
158 static void sysctrl_keyswitch_poll(void);
159 
160 static void update_key_state(struct sysctrl_soft_state *);
161 
162 static void sysctrl_abort_seq_handler(char *msg);
163 
164 static void nvram_update_powerfail(struct sysctrl_soft_state *softsp);
165 
166 static void toggle_board_green_leds(int);
167 
168 void bd_remove_poll(struct sysctrl_soft_state *);
169 
170 static void sysc_slot_info(int nslots, int *start, int *limit, int *incr);
171 
172 extern void sysc_board_connect_supported_init(void);
173 
174 static void rcons_reinit(struct sysctrl_soft_state *softsp);
175 
176 /*
177  * Configuration data structures
178  */
179 static struct cb_ops sysctrl_cb_ops = {
180 	sysctrl_open,		/* open */
181 	sysctrl_close,		/* close */
182 	nulldev,		/* strategy */
183 	nulldev,		/* print */
184 	nulldev,		/* dump */
185 	nulldev,		/* read */
186 	nulldev,		/* write */
187 	sysctrl_ioctl,		/* ioctl */
188 	nodev,			/* devmap */
189 	nodev,			/* mmap */
190 	nodev,			/* segmap */
191 	nochpoll,		/* poll */
192 	ddi_prop_op,		/* cb_prop_op */
193 	0,			/* streamtab */
194 	D_MP|D_NEW,		/* Driver compatibility flag */
195 	CB_REV,			/* rev */
196 	nodev,			/* cb_aread */
197 	nodev			/* cb_awrite */
198 };
199 
200 static struct dev_ops sysctrl_ops = {
201 	DEVO_REV,		/* devo_rev */
202 	0,			/* refcnt */
203 	sysctrl_info,		/* getinfo */
204 	nulldev,		/* identify */
205 	nulldev,		/* probe */
206 	sysctrl_attach,		/* attach */
207 	sysctrl_detach,		/* detach */
208 	nulldev,		/* reset */
209 	&sysctrl_cb_ops,	/* cb_ops */
210 	(struct bus_ops *)0,	/* bus_ops */
211 	nulldev,		/* power */
212 	ddi_quiesce_not_supported,	/* devo_quiesce */
213 };
214 
215 void *sysctrlp;				/* sysctrl soft state hook */
216 
217 /* # of ticks to silence spurious interrupts */
218 static clock_t spur_timeout_hz;
219 
220 /* # of ticks to count spurious interrupts to print message */
221 static clock_t spur_long_timeout_hz;
222 
223 /* # of ticks between AC failure polling */
224 static clock_t ac_timeout_hz;
225 
226 /* # of ticks between Power Supply Failure polling */
227 static clock_t ps_fail_timeout_hz;
228 
229 /*
230  * # of ticks between Peripheral Power Supply failure polling
231  * (used both for interrupt retry timeout and polling function)
232  */
233 static clock_t pps_fan_timeout_hz;
234 
235 /* # of ticks delay after board insert interrupt */
236 static clock_t bd_insert_delay_hz;
237 
238 /* # of secs to wait before restarting poll if we cannot clear interrupts */
239 static clock_t bd_insert_retry_hz;
240 
241 /* # of secs between Board Removal polling */
242 static clock_t bd_remove_timeout_hz;
243 
244 /* # of secs between toggle of OS LED */
245 static clock_t blink_led_timeout_hz;
246 
247 /* overtemp polling routine timeout delay */
248 static clock_t overtemp_timeout_hz;
249 
250 /* key switch polling routine timeout delay */
251 static clock_t keyswitch_timeout_hz;
252 
253 /* Specify which system interrupt condition to monitor */
254 int enable_sys_interrupt = SYS_AC_PWR_FAIL_EN | SYS_PPS_FAN_FAIL_EN |
255 			SYS_PS_FAIL_EN | SYS_SBRD_PRES_EN;
256 
257 /* Should the overtemp_poll thread be running? */
258 static int sysctrl_do_overtemp_thread = 1;
259 
260 /* Should the keyswitch_poll thread be running? */
261 static int sysctrl_do_keyswitch_thread = 1;
262 
263 /*
264  * This timeout ID is for board remove polling routine. It is
265  * protected by the fhc_bdlist mutex.
266  * XXX - This will not work for wildfire. A different scheme must be
267  * used since there will be multiple sysctrl nodes, each with its
268  * own list of hotplugged boards to scan.
269  */
270 static timeout_id_t bd_remove_to_id = 0;
271 
272 /*
273  * If this is set, the system will not shutdown when insufficient power
274  * condition persists.
275  */
276 int disable_insufficient_power_reboot = 0;
277 
278 /*
279  * Set this to enable suspend/resume
280  */
281 int sysctrl_enable_detach_suspend = 0;
282 
283 /*
284  * Set this to reflect the OBP initialized HOTPLUG_DISABLED_PROPERTY and
285  * during dynamic detection
286  */
287 int sysctrl_hotplug_disabled = FALSE;
288 
289 /* Indicates whether or not the overtemp thread has been started */
290 static int sysctrl_overtemp_thread_started = 0;
291 
292 /* Indicates whether or not the key switch thread has been started */
293 static int sysctrl_keyswitch_thread_started = 0;
294 
295 /* *Mutex used to protect the soft state list */
296 static kmutex_t sslist_mutex;
297 
298 /* The CV is used to wakeup the overtemp thread when needed. */
299 static kcondvar_t overtemp_cv;
300 
301 /* The CV is used to wakeup the key switch thread when needed. */
302 static kcondvar_t keyswitch_cv;
303 
304 /* This mutex is used to protect the sysctrl_ddi_branch_init variable */
305 static kmutex_t sysctrl_branch_mutex;
306 
307 /*
308  * This variable is set after all existing branches in the system have
309  * been discovered and held via e_ddi_branch_hold(). This happens on
310  * first open() of any sysctrl minor node.
311  */
312 static int sysctrl_ddi_branch_init;
313 
314 /*
315  * Linked list of all syctrl soft state structures.
316  * Used for polling sysctrl state changes, i.e. temperature.
317  */
318 struct sysctrl_soft_state *sys_list = NULL;
319 
320 extern struct mod_ops mod_driverops;
321 
322 static struct modldrv modldrv = {
323 	&mod_driverops,		/* Type of module.  This one is a driver */
324 	"Clock Board",		/* name of module */
325 	&sysctrl_ops,		/* driver ops */
326 };
327 
328 static struct modlinkage modlinkage = {
329 	MODREV_1,		/* rev */
330 	(void *)&modldrv,
331 	NULL
332 };
333 
334 /*
335  * These are the module initialization routines.
336  */
337 
338 int
339 _init(void)
340 {
341 	int error;
342 
343 	if ((error = ddi_soft_state_init(&sysctrlp,
344 	    sizeof (struct sysctrl_soft_state), 1)) != 0)
345 		return (error);
346 
347 	error = mod_install(&modlinkage);
348 	if (error != 0) {
349 		ddi_soft_state_fini(&sysctrlp);
350 		return (error);
351 	}
352 
353 	mutex_init(&sysctrl_branch_mutex, NULL, MUTEX_DRIVER, NULL);
354 
355 	return (0);
356 }
357 
358 int
359 _fini(void)
360 {
361 	int error;
362 
363 	if ((error = mod_remove(&modlinkage)) != 0)
364 		return (error);
365 
366 	ddi_soft_state_fini(&sysctrlp);
367 
368 	mutex_destroy(&sysctrl_branch_mutex);
369 
370 	return (0);
371 }
372 
373 int
374 _info(struct modinfo *modinfop)
375 {
376 	return (mod_info(&modlinkage, modinfop));
377 }
378 
379 /* ARGSUSED */
380 static int
381 sysctrl_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
382 {
383 	dev_t	dev;
384 	int	instance;
385 
386 	if (infocmd == DDI_INFO_DEVT2INSTANCE) {
387 		dev = (dev_t)arg;
388 		instance = GETINSTANCE(dev);
389 		*result = (void *)(uintptr_t)instance;
390 		return (DDI_SUCCESS);
391 	}
392 	return (DDI_FAILURE);
393 }
394 
395 static int
396 sysctrl_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
397 {
398 	struct sysctrl_soft_state *softsp;
399 	int instance;
400 	uchar_t tmp_reg;
401 	dev_info_t *dip;
402 	char *propval;
403 	int proplen;
404 	int slot_num;
405 	int start;		/* start index for scan loop */
406 	int limit;		/* board number limit for scan loop */
407 	int incr;		/* amount to incr each pass thru loop */
408 	void set_clockbrd_info(void);
409 
410 
411 	switch (cmd) {
412 	case DDI_ATTACH:
413 		break;
414 
415 	case DDI_RESUME:
416 		/* XXX see sysctrl:DDI_SUSPEND for special h/w treatment */
417 		return (DDI_SUCCESS);
418 
419 	default:
420 		return (DDI_FAILURE);
421 	}
422 
423 	instance = ddi_get_instance(devi);
424 
425 	if (ddi_soft_state_zalloc(sysctrlp, instance) != DDI_SUCCESS)
426 		return (DDI_FAILURE);
427 
428 	softsp = GETSOFTC(instance);
429 
430 	/* Set the dip in the soft state */
431 	softsp->dip = devi;
432 
433 	/* Set up the parent dip */
434 	softsp->pdip = ddi_get_parent(softsp->dip);
435 
436 	DPRINTF(SYSCTRL_ATTACH_DEBUG, ("sysctrl: devi= 0x%p\n, softsp=0x%p\n",
437 	    (void *)devi, (void *)softsp));
438 
439 	/* First set all of the timeout values */
440 	spur_timeout_hz = drv_usectohz(SPUR_TIMEOUT_USEC);
441 	spur_long_timeout_hz = drv_usectohz(SPUR_LONG_TIMEOUT_USEC);
442 	ac_timeout_hz = drv_usectohz(AC_TIMEOUT_USEC);
443 	ps_fail_timeout_hz = drv_usectohz(PS_FAIL_TIMEOUT_USEC);
444 	pps_fan_timeout_hz = drv_usectohz(PPS_FAN_TIMEOUT_USEC);
445 	bd_insert_delay_hz = drv_usectohz(BRD_INSERT_DELAY_USEC);
446 	bd_insert_retry_hz = drv_usectohz(BRD_INSERT_RETRY_USEC);
447 	bd_remove_timeout_hz = drv_usectohz(BRD_REMOVE_TIMEOUT_USEC);
448 	blink_led_timeout_hz = drv_usectohz(BLINK_LED_TIMEOUT_USEC);
449 	overtemp_timeout_hz = drv_usectohz(OVERTEMP_TIMEOUT_SEC * MICROSEC);
450 	keyswitch_timeout_hz = drv_usectohz(KEYSWITCH_TIMEOUT_USEC);
451 
452 	/*
453 	 * Map in the registers sets that OBP hands us. According
454 	 * to the sun4u device tree spec., the register sets are as
455 	 * follows:
456 	 *
457 	 *	0	Clock Frequency Registers (contains the bit
458 	 *		for enabling the remote console reset)
459 	 *	1	Misc (has all the registers that we need
460 	 *	2	Clock Version Register
461 	 */
462 	if (ddi_map_regs(softsp->dip, 0,
463 	    (caddr_t *)&softsp->clk_freq1, 0, 0)) {
464 		cmn_err(CE_WARN, "sysctrl%d: unable to map clock frequency "
465 		    "registers", instance);
466 		goto bad0;
467 	}
468 
469 	if (ddi_map_regs(softsp->dip, 1,
470 	    (caddr_t *)&softsp->csr, 0, 0)) {
471 		cmn_err(CE_WARN, "sysctrl%d: unable to map internal"
472 		    "registers", instance);
473 		goto bad1;
474 	}
475 
476 	/*
477 	 * There is a new register for newer vintage clock board nodes,
478 	 * OBP register set 2 in the clock board node.
479 	 *
480 	 */
481 	(void) ddi_map_regs(softsp->dip, 2, (caddr_t *)&softsp->clk_ver, 0, 0);
482 
483 	/*
484 	 * Fill in the virtual addresses of the registers in the
485 	 * sysctrl_soft_state structure. We do not want to calculate
486 	 * them on the fly. This way we waste a little memory, but
487 	 * avoid bugs down the road.
488 	 */
489 	softsp->clk_freq2 = (uchar_t *)((caddr_t)softsp->clk_freq1 +
490 	    SYS_OFF_CLK_FREQ2);
491 
492 	softsp->status1 = (uchar_t *)((caddr_t)softsp->csr +
493 	    SYS_OFF_STAT1);
494 
495 	softsp->status2 = (uchar_t *)((caddr_t)softsp->csr +
496 	    SYS_OFF_STAT2);
497 
498 	softsp->ps_stat = (uchar_t *)((caddr_t)softsp->csr +
499 	    SYS_OFF_PSSTAT);
500 
501 	softsp->ps_pres = (uchar_t *)((caddr_t)softsp->csr +
502 	    SYS_OFF_PSPRES);
503 
504 	softsp->pppsr = (uchar_t *)((caddr_t)softsp->csr +
505 	    SYS_OFF_PPPSR);
506 
507 	softsp->temp_reg = (uchar_t *)((caddr_t)softsp->csr +
508 	    SYS_OFF_TEMP);
509 
510 	set_clockbrd_info();
511 
512 	/*
513 	 * Enable the hardware watchdog gate on the clock board if
514 	 * map_wellknown has detected that watchdog timer is available
515 	 * and user wants it to be enabled.
516 	 */
517 	if (watchdog_available && watchdog_enable)
518 		*(softsp->clk_freq2) |= TOD_RESET_EN;
519 	else
520 		*(softsp->clk_freq2) &= ~TOD_RESET_EN;
521 
522 	/* Check for inherited faults from the PROM. */
523 	if (*softsp->csr & SYS_LED_MID) {
524 		reg_fault(0, FT_PROM, FT_SYSTEM);
525 	}
526 
527 	/*
528 	 * calculate and cache the number of slots on this system
529 	 */
530 	switch (SYS_TYPE(*softsp->status1)) {
531 	case SYS_16_SLOT:
532 		softsp->nslots = 16;
533 		break;
534 
535 	case SYS_8_SLOT:
536 		softsp->nslots = 8;
537 		break;
538 
539 	case SYS_4_SLOT:
540 		/* check the clk_version register - if the ptr is valid */
541 		if ((softsp->clk_ver != NULL) &&
542 		    (SYS_TYPE2(*softsp->clk_ver) == SYS_PLUS_SYSTEM)) {
543 			softsp->nslots = 5;
544 		} else {
545 			softsp->nslots = 4;
546 		}
547 		break;
548 
549 	case SYS_TESTBED:
550 	default:
551 		softsp->nslots = 0;
552 		break;
553 	}
554 
555 
556 	/* create the fault list kstat */
557 	create_ft_kstats(instance);
558 
559 	/*
560 	 * Do a priming read on the ADC, and throw away the first value
561 	 * read. This is a feature of the ADC hardware. After a power cycle
562 	 * it does not contains valid data until a read occurs.
563 	 */
564 	tmp_reg = *(softsp->temp_reg);
565 
566 	/* Wait 30 usec for ADC hardware to stabilize. */
567 	DELAY(30);
568 
569 	/* shut off all interrupt sources */
570 	*(softsp->csr) &= ~(SYS_PPS_FAN_FAIL_EN | SYS_PS_FAIL_EN |
571 	    SYS_AC_PWR_FAIL_EN | SYS_SBRD_PRES_EN);
572 	tmp_reg = *(softsp->csr);
573 #ifdef lint
574 	tmp_reg = tmp_reg;
575 #endif
576 
577 	/*
578 	 * Now register our high interrupt with the system.
579 	 */
580 	if (ddi_add_intr(devi, 0, &softsp->iblock,
581 	    &softsp->idevice, (uint_t (*)(caddr_t))nulldev, NULL) !=
582 	    DDI_SUCCESS)
583 		goto bad2;
584 
585 	mutex_init(&softsp->csr_mutex, NULL, MUTEX_DRIVER,
586 	    (void *)softsp->iblock);
587 
588 	ddi_remove_intr(devi, 0, softsp->iblock);
589 
590 	if (ddi_add_intr(devi, 0, &softsp->iblock,
591 	    &softsp->idevice, system_high_handler, (caddr_t)softsp) !=
592 	    DDI_SUCCESS)
593 		goto bad3;
594 
595 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_id,
596 	    &softsp->spur_int_c, NULL, spur_delay, (caddr_t)softsp) !=
597 	    DDI_SUCCESS)
598 		goto bad4;
599 
600 	mutex_init(&softsp->spur_int_lock, NULL, MUTEX_DRIVER,
601 	    (void *)softsp->spur_int_c);
602 
603 
604 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_high_id,
605 	    NULL, NULL, spur_reenable, (caddr_t)softsp) != DDI_SUCCESS)
606 		goto bad5;
607 
608 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_long_to_id,
609 	    NULL, NULL, spur_clear_count, (caddr_t)softsp) != DDI_SUCCESS)
610 		goto bad6;
611 
612 	/*
613 	 * Now register low-level ac fail handler
614 	 */
615 	if (ddi_add_softintr(devi, DDI_SOFTINT_HIGH, &softsp->ac_fail_id,
616 	    NULL, NULL, ac_fail_handler, (caddr_t)softsp) != DDI_SUCCESS)
617 		goto bad7;
618 
619 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->ac_fail_high_id,
620 	    NULL, NULL, ac_fail_reenable, (caddr_t)softsp) != DDI_SUCCESS)
621 		goto bad8;
622 
623 	/*
624 	 * Now register low-level ps fail handler
625 	 */
626 
627 	if (ddi_add_softintr(devi, DDI_SOFTINT_HIGH, &softsp->ps_fail_int_id,
628 	    &softsp->ps_fail_c, NULL, ps_fail_int_handler, (caddr_t)softsp) !=
629 	    DDI_SUCCESS)
630 		goto bad9;
631 
632 	mutex_init(&softsp->ps_fail_lock, NULL, MUTEX_DRIVER,
633 	    (void *)softsp->ps_fail_c);
634 
635 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->ps_fail_poll_id,
636 	    NULL, NULL, ps_fail_poll_handler, (caddr_t)softsp) !=
637 	    DDI_SUCCESS)
638 		goto bad10;
639 
640 	/*
641 	 * Now register low-level pps fan fail handler
642 	 */
643 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->pps_fan_id,
644 	    NULL, NULL, pps_fanfail_handler, (caddr_t)softsp) !=
645 	    DDI_SUCCESS)
646 		goto bad11;
647 
648 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->pps_fan_high_id,
649 	    NULL, NULL, pps_fanfail_reenable, (caddr_t)softsp) !=
650 	    DDI_SUCCESS)
651 		goto bad12;
652 
653 	/*
654 	 * Based upon a check for a current share backplane, advise
655 	 * that system does not support hot plug
656 	 *
657 	 */
658 	if ((*(softsp->pppsr) & SYS_NOT_CURRENT_S) != 0) {
659 		cmn_err(CE_NOTE, "Hot Plug not supported in this system");
660 		sysctrl_hotplug_disabled = TRUE;
661 	}
662 
663 	/*
664 	 * If the trigger circuit is busted or the NOT_BRD_PRES line
665 	 * is stuck then OBP will publish this property stating that
666 	 * hot plug is not available.  If this happens we will complain
667 	 * to the console and register a system fault.  We will also
668 	 * not enable the board insert interrupt for this session.
669 	 */
670 	if (ddi_prop_op(DDI_DEV_T_ANY, softsp->dip, PROP_LEN_AND_VAL_ALLOC,
671 	    DDI_PROP_DONTPASS, HOTPLUG_DISABLED_PROPERTY,
672 	    (caddr_t)&propval, &proplen) == DDI_PROP_SUCCESS) {
673 		cmn_err(CE_WARN, "Hot Plug Unavailable [%s]", propval);
674 		reg_fault(0, FT_HOT_PLUG, FT_SYSTEM);
675 		sysctrl_hotplug_disabled = TRUE;
676 		enable_sys_interrupt &= ~SYS_SBRD_PRES_EN;
677 		kmem_free(propval, proplen);
678 	}
679 
680 	sysc_board_connect_supported_init();
681 
682 	fhc_bd_sc_register(sysc_policy_update, softsp);
683 
684 	sysc_slot_info(softsp->nslots, &start, &limit, &incr);
685 
686 	/* Prime the board list. */
687 	fhc_bdlist_prime(start, limit, incr);
688 
689 	/*
690 	 * Set up a board remove timeout call.
691 	 */
692 	(void) fhc_bdlist_lock(-1);
693 
694 	DPRINTF(SYSCTRL_ATTACH_DEBUG,
695 	    ("attach: start bd_remove_poll()..."));
696 
697 	bd_remove_poll(softsp);
698 	fhc_bdlist_unlock();
699 
700 	/*
701 	 * Now register low-level board insert handler
702 	 */
703 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->sbrd_pres_id,
704 	    NULL, NULL, bd_insert_handler, (caddr_t)softsp) != DDI_SUCCESS)
705 		goto bad13;
706 
707 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->sbrd_gone_id,
708 	    NULL, NULL, bd_insert_normal, (caddr_t)softsp) != DDI_SUCCESS)
709 		goto bad14;
710 
711 	/*
712 	 * Now register led blink handler (interrupt level)
713 	 */
714 	if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->blink_led_id,
715 	    &softsp->sys_led_c, NULL, blink_led_handler, (caddr_t)softsp) !=
716 	    DDI_SUCCESS)
717 		goto bad15;
718 	mutex_init(&softsp->sys_led_lock, NULL, MUTEX_DRIVER,
719 	    (void *)softsp->sys_led_c);
720 
721 	/* initialize the bit field for all pps fans to assumed good */
722 	softsp->pps_fan_saved = softsp->pps_fan_external_state =
723 	    SYS_AC_FAN_OK | SYS_KEYSW_FAN_OK;
724 
725 	/* prime the power supply state machines */
726 	if (enable_sys_interrupt & SYS_PS_FAIL_EN)
727 		ddi_trigger_softintr(softsp->ps_fail_poll_id);
728 
729 
730 	/* kick off the OS led blinker */
731 	softsp->sys_led = FALSE;
732 	ddi_trigger_softintr(softsp->blink_led_id);
733 
734 	/* Now enable selected interrupt sources */
735 	mutex_enter(&softsp->csr_mutex);
736 	*(softsp->csr) |= enable_sys_interrupt &
737 	    (SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
738 	    SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
739 	tmp_reg = *(softsp->csr);
740 #ifdef lint
741 	tmp_reg = tmp_reg;
742 #endif
743 	mutex_exit(&softsp->csr_mutex);
744 
745 	/* Initialize the temperature */
746 	init_temp_arrays(&softsp->tempstat);
747 
748 	/*
749 	 * initialize key switch shadow state
750 	 */
751 	softsp->key_shadow = KEY_BOOT;
752 
753 	/*
754 	 * Now add this soft state structure to the front of the linked list
755 	 * of soft state structures.
756 	 */
757 	if (sys_list == (struct sysctrl_soft_state *)NULL) {
758 		mutex_init(&sslist_mutex, NULL, MUTEX_DEFAULT, NULL);
759 	}
760 	mutex_enter(&sslist_mutex);
761 	softsp->next = sys_list;
762 	sys_list = softsp;
763 	mutex_exit(&sslist_mutex);
764 
765 	/* Setup the kstats for this device */
766 	sysctrl_add_kstats(softsp);
767 
768 	/* kick off the PPS fan poll routine */
769 	pps_fan_poll(softsp);
770 
771 	if (sysctrl_overtemp_thread_started == 0) {
772 		/*
773 		 * set up the overtemp condition variable before
774 		 * starting the thread.
775 		 */
776 		cv_init(&overtemp_cv, NULL, CV_DRIVER, NULL);
777 
778 		/*
779 		 * start up the overtemp polling thread
780 		 */
781 		(void) thread_create(NULL, 0, (void (*)())sysctrl_overtemp_poll,
782 		    NULL, 0, &p0, TS_RUN, minclsyspri);
783 		sysctrl_overtemp_thread_started++;
784 	}
785 
786 	if (sysctrl_keyswitch_thread_started == 0) {
787 		extern void (*abort_seq_handler)();
788 
789 		/*
790 		 * interpose sysctrl's abort sequence handler
791 		 */
792 		abort_seq_handler = sysctrl_abort_seq_handler;
793 
794 		/*
795 		 * set up the key switch condition variable before
796 		 * starting the thread
797 		 */
798 		cv_init(&keyswitch_cv, NULL, CV_DRIVER, NULL);
799 
800 		/*
801 		 * start up the key switch polling thread
802 		 */
803 		(void) thread_create(NULL, 0,
804 		    (void (*)())sysctrl_keyswitch_poll, NULL, 0, &p0,
805 		    TS_RUN, minclsyspri);
806 		sysctrl_keyswitch_thread_started++;
807 	}
808 
809 	/*
810 	 * perform initialization to allow setting of powerfail-time
811 	 */
812 	if ((dip = ddi_find_devinfo("options", -1, 0)) == NULL)
813 		softsp->options_nodeid = (pnode_t)0;
814 	else
815 		softsp->options_nodeid = (pnode_t)ddi_get_nodeid(dip);
816 
817 	DPRINTF(SYSCTRL_ATTACH_DEBUG,
818 	    ("sysctrl: Creating devices start:%d, limit:%d, incr:%d\n",
819 	    start, limit, incr));
820 
821 	/*
822 	 * Create minor node for each system attachment points
823 	 */
824 	for (slot_num = start; slot_num < limit; slot_num = slot_num + incr) {
825 		char name[30];
826 		(void) sprintf(name, "slot%d", slot_num);
827 		if (ddi_create_minor_node(devi, name, S_IFCHR,
828 		    (PUTINSTANCE(instance) | slot_num),
829 		    DDI_NT_ATTACHMENT_POINT, 0) == DDI_FAILURE) {
830 			cmn_err(CE_WARN, "sysctrl%d: \"%s\" "
831 			    "ddi_create_minor_node failed",
832 			    instance, name);
833 			goto bad16;
834 		}
835 	}
836 
837 	ddi_report_dev(devi);
838 
839 	/*
840 	 * Remote console is inherited from POST
841 	 */
842 	if ((*(softsp->clk_freq2) & RCONS_UART_EN) == 0) {
843 		softsp->enable_rcons_atboot = FALSE;
844 		cmn_err(CE_WARN, "Remote console not active");
845 	} else
846 		softsp->enable_rcons_atboot = TRUE;
847 
848 	return (DDI_SUCCESS);
849 
850 bad16:
851 	cv_destroy(&keyswitch_cv);
852 	cv_destroy(&overtemp_cv);
853 	mutex_destroy(&sslist_mutex);
854 	mutex_destroy(&softsp->sys_led_lock);
855 	ddi_remove_softintr(softsp->blink_led_id);
856 bad15:
857 	ddi_remove_softintr(softsp->sbrd_gone_id);
858 bad14:
859 	ddi_remove_softintr(softsp->sbrd_pres_id);
860 bad13:
861 	ddi_remove_softintr(softsp->pps_fan_high_id);
862 bad12:
863 	ddi_remove_softintr(softsp->pps_fan_id);
864 bad11:
865 	ddi_remove_softintr(softsp->ps_fail_poll_id);
866 bad10:
867 	mutex_destroy(&softsp->ps_fail_lock);
868 	ddi_remove_softintr(softsp->ps_fail_int_id);
869 bad9:
870 	ddi_remove_softintr(softsp->ac_fail_high_id);
871 bad8:
872 	ddi_remove_softintr(softsp->ac_fail_id);
873 bad7:
874 	ddi_remove_softintr(softsp->spur_long_to_id);
875 bad6:
876 	ddi_remove_softintr(softsp->spur_high_id);
877 bad5:
878 	mutex_destroy(&softsp->spur_int_lock);
879 	ddi_remove_softintr(softsp->spur_id);
880 bad4:
881 	ddi_remove_intr(devi, 0, softsp->iblock);
882 bad3:
883 	mutex_destroy(&softsp->csr_mutex);
884 bad2:
885 	ddi_unmap_regs(softsp->dip, 1, (caddr_t *)&softsp->csr, 0, 0);
886 	if (softsp->clk_ver != NULL)
887 		ddi_unmap_regs(softsp->dip, 2, (caddr_t *)&softsp->clk_ver,
888 		    0, 0);
889 bad1:
890 	ddi_unmap_regs(softsp->dip, 0, (caddr_t *)&softsp->clk_freq1, 0, 0);
891 
892 bad0:
893 	ddi_soft_state_free(sysctrlp, instance);
894 	ddi_remove_minor_node(dip, NULL);
895 	cmn_err(CE_WARN,
896 	    "sysctrl%d: Initialization failure. Some system level events,"
897 	    " {AC Fail, Fan Failure, PS Failure} not detected", instance);
898 	return (DDI_FAILURE);
899 }
900 
901 struct sysc_hold {
902 	int start;
903 	int limit;
904 	int incr;
905 	int hold;
906 };
907 
908 static int
909 sysctrl_hold_rele_branches(dev_info_t *dip, void *arg)
910 {
911 	int *rp, len, slot, i;
912 	struct sysc_hold *ap = (struct sysc_hold *)arg;
913 
914 	/*
915 	 * For Sunfire, top nodes on board are always children of root dip
916 	 */
917 	ASSERT(ddi_get_parent(dip) == ddi_root_node());
918 
919 	/*
920 	 * Skip non-PROM and "central" nodes
921 	 */
922 	if (!ndi_dev_is_prom_node(dip) ||
923 	    strcmp(ddi_node_name(dip), "central") == 0)
924 		return (DDI_WALK_PRUNECHILD);
925 
926 	/*
927 	 * Extract board # from reg property.
928 	 */
929 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
930 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg", (caddr_t)&rp, &len)
931 	    != DDI_SUCCESS) {
932 		DPRINTF(SYSC_DEBUG, ("devinfo node %s(%p) has no reg"
933 		    " property\n", ddi_node_name(dip), (void *)dip));
934 		return (DDI_WALK_PRUNECHILD);
935 	}
936 
937 	slot = (*rp - 0x1c0) >> 2;
938 	kmem_free(rp, len);
939 
940 	ASSERT(ap->start >= 0 && ap->start < ap->limit);
941 
942 	for (i = ap->start; i < ap->limit; i = i + ap->incr) {
943 		if (i == slot)
944 			break;
945 	}
946 
947 	if (i >= ap->limit) {
948 		DPRINTF(SYSC_DEBUG, ("sysctrl_hold_rele: Invalid board # (%d)"
949 		    " for node %s(%p)\n", slot, ddi_node_name(dip),
950 		    (void *)dip));
951 		return (DDI_WALK_PRUNECHILD);
952 	}
953 
954 	if (ap->hold) {
955 		ASSERT(!e_ddi_branch_held(dip));
956 		e_ddi_branch_hold(dip);
957 	} else {
958 		ASSERT(e_ddi_branch_held(dip));
959 		e_ddi_branch_rele(dip);
960 	}
961 
962 	return (DDI_WALK_PRUNECHILD);
963 }
964 
965 /* ARGSUSED */
966 static int
967 sysctrl_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
968 {
969 #ifdef	SYSCTRL_SUPPORTS_DETACH
970 	dev_info_t			*rdip;
971 	struct sysc_hold		arg = {0};
972 	struct sysctrl_soft_state	*softsp;
973 #endif	/* SYSCTRL_SUPPORTS_DETACH */
974 
975 	if (sysctrl_enable_detach_suspend == FALSE)
976 		return (DDI_FAILURE);
977 
978 	switch (cmd) {
979 	case DDI_SUSPEND:
980 		/*
981 		 * XXX we don't presently save the state of the remote
982 		 * console because it is a constant function of POST.
983 		 * XXX we don't deal with the hardware watchdog here
984 		 * either.  It should be handled in hardclk.
985 		 */
986 		return (DDI_SUCCESS);
987 
988 	case DDI_DETACH:
989 		break;
990 	default:
991 		return (DDI_FAILURE);
992 	}
993 
994 #ifdef	SYSCTRL_SUPPORTS_DETACH
995 
996 	/*
997 	 * XXX If sysctrl ever supports detach, this code should be enabled
998 	 * This is only the portion of the detach code dealing with
999 	 * the DDI branch routines. Other parts of detach will need
1000 	 * to be added.
1001 	 */
1002 
1003 	/*
1004 	 * Walk immediate children of root devinfo node, releasing holds
1005 	 * on branches acquired in first sysctrl_open().
1006 	 */
1007 
1008 	instance = ddi_get_instance(dip);
1009 	softsp = GETSOFTC(instance);
1010 
1011 	if (softsp == NULL) {
1012 		cmn_err(CE_WARN, "sysctrl%d device not attached", instance);
1013 		return (DDI_FAILURE);
1014 	}
1015 
1016 	sysc_slot_info(softsp->nslots, &arg.start, &arg.limit, &arg.incr);
1017 
1018 	arg.hold = 0;
1019 
1020 	rdip = ddi_root_node();
1021 
1022 	ndi_devi_enter(rdip);
1023 	ddi_walk_devs(ddi_get_child(rdip), sysctrl_hold_rele_branches, &arg);
1024 	ndi_devi_exit(rdip);
1025 
1026 	sysctrl_ddi_branch_init = 0;
1027 
1028 	return (DDI_SUCCESS);
1029 #endif	/* SYSCTRL_SUPPORTS_DETACH */
1030 
1031 	return (DDI_FAILURE);
1032 }
1033 
1034 /* ARGSUSED */
1035 static int
1036 sysctrl_open(dev_t *devp, int flag, int otyp, cred_t *credp)
1037 {
1038 	int		instance;
1039 	int		slot;
1040 	dev_t		dev;
1041 	dev_info_t	*rdip;
1042 	struct sysc_hold arg = {0};
1043 	struct sysctrl_soft_state *softsp;
1044 
1045 	dev = *devp;
1046 
1047 	/*
1048 	 * We checked against the instance softstate structure since there
1049 	 * will only be one instance of sysctrl (clock board) in UEXX00
1050 	 *
1051 	 * Since we only create minor devices for existing slots on a
1052 	 * particular system, we don't need to worry about non-exist slot.
1053 	 */
1054 
1055 	instance = GETINSTANCE(dev);
1056 	slot = GETSLOT(dev);
1057 
1058 	/* Is the instance attached? */
1059 	if ((softsp = GETSOFTC(instance)) == NULL) {
1060 		cmn_err(CE_WARN, "sysctrl%d device not attached", instance);
1061 		return (ENXIO);
1062 	}
1063 
1064 	/* verify that otyp is appropriate */
1065 	if (otyp != OTYP_CHR) {
1066 		return (EINVAL);
1067 	}
1068 
1069 	if (!fhc_bd_valid(slot))
1070 		return (ENXIO);
1071 
1072 	/*
1073 	 * On first open of a sysctrl minor walk immediate children of the
1074 	 * devinfo root node and hold all branches of interest.
1075 	 */
1076 	mutex_enter(&sysctrl_branch_mutex);
1077 	if (!sysctrl_ddi_branch_init) {
1078 
1079 		sysctrl_ddi_branch_init = 1;
1080 
1081 		sysc_slot_info(softsp->nslots, &arg.start, &arg.limit,
1082 		    &arg.incr);
1083 		arg.hold = 1;
1084 
1085 		rdip = ddi_root_node();
1086 
1087 		ndi_devi_enter(rdip);
1088 		ddi_walk_devs(ddi_get_child(rdip), sysctrl_hold_rele_branches,
1089 		    &arg);
1090 		ndi_devi_exit(rdip);
1091 	}
1092 	mutex_exit(&sysctrl_branch_mutex);
1093 
1094 	return (DDI_SUCCESS);
1095 }
1096 
1097 /* ARGSUSED */
1098 static int
1099 sysctrl_close(dev_t devp, int flag, int otyp, cred_t *credp)
1100 {
1101 	return (DDI_SUCCESS);
1102 }
1103 
1104 /*
1105  * This function will acquire the lock and set the in_transition
1106  * bit for the specified slot.  If the slot is being used,
1107  * we return FALSE; else set in_transition and return TRUE.
1108  */
1109 static int
1110 sysc_enter_transition(int slot)
1111 {
1112 	fhc_bd_t	*list;
1113 	sysc_cfga_stat_t *sysc_stat_lk;
1114 	fhc_bd_t	*glist;
1115 	sysc_cfga_stat_t *sysc_stat_gk;
1116 
1117 	/* mutex lock the structure */
1118 	list = fhc_bdlist_lock(slot);
1119 	if ((slot != -1) && (list == NULL)) {
1120 		fhc_bdlist_unlock();
1121 		return (FALSE);
1122 	}
1123 
1124 	glist = fhc_bd_clock();
1125 	if (slot == -1)
1126 		list = glist;
1127 
1128 	/* change the in_transition bit */
1129 	sysc_stat_lk = &list->sc;
1130 	sysc_stat_gk = &glist->sc;
1131 	if ((sysc_stat_lk->in_transition == TRUE) ||
1132 	    (sysc_stat_gk->in_transition == TRUE)) {
1133 		fhc_bdlist_unlock();
1134 		return (FALSE);
1135 	} else {
1136 		sysc_stat_lk->in_transition = TRUE;
1137 		return (TRUE);
1138 	}
1139 }
1140 
1141 /*
1142  * This function will release the lock and clear the in_transition
1143  * bit for the specified slot.
1144  */
1145 static void
1146 sysc_exit_transition(int slot)
1147 {
1148 	fhc_bd_t	*list;
1149 	sysc_cfga_stat_t *sysc_stat_lk;
1150 
1151 	ASSERT(fhc_bdlist_locked());
1152 
1153 	if (slot == -1)
1154 		list = fhc_bd_clock();
1155 	else
1156 		list = fhc_bd(slot);
1157 	sysc_stat_lk = &list->sc;
1158 	ASSERT(sysc_stat_lk->in_transition == TRUE);
1159 	sysc_stat_lk->in_transition = FALSE;
1160 	fhc_bdlist_unlock();
1161 }
1162 
1163 static int
1164 sysc_pkt_init(sysc_cfga_pkt_t *pkt, intptr_t arg, int flag)
1165 {
1166 #ifdef _MULTI_DATAMODEL
1167 	if (ddi_model_convert_from(flag & FMODELS) == DDI_MODEL_ILP32) {
1168 		sysc_cfga_cmd32_t sysc_cmd32;
1169 
1170 		if (ddi_copyin((void *)arg, &sysc_cmd32,
1171 		    sizeof (sysc_cfga_cmd32_t), flag) != 0) {
1172 			return (EFAULT);
1173 		}
1174 		pkt->cmd_cfga.force = sysc_cmd32.force;
1175 		pkt->cmd_cfga.test = sysc_cmd32.test;
1176 		pkt->cmd_cfga.arg = sysc_cmd32.arg;
1177 		pkt->cmd_cfga.errtype = sysc_cmd32.errtype;
1178 		pkt->cmd_cfga.outputstr =
1179 		    (char *)(uintptr_t)sysc_cmd32.outputstr;
1180 	} else
1181 #endif /* _MULTI_DATAMODEL */
1182 	if (ddi_copyin((void *)arg, &(pkt->cmd_cfga),
1183 	    sizeof (sysc_cfga_cmd_t), flag) != 0) {
1184 		return (EFAULT);
1185 	}
1186 	pkt->errbuf = kmem_zalloc(SYSC_OUTPUT_LEN, KM_SLEEP);
1187 	return (0);
1188 }
1189 
1190 static int
1191 sysc_pkt_fini(sysc_cfga_pkt_t *pkt, intptr_t arg, int flag)
1192 {
1193 	int ret = TRUE;
1194 
1195 #ifdef _MULTI_DATAMODEL
1196 	if (ddi_model_convert_from(flag & FMODELS) == DDI_MODEL_ILP32) {
1197 
1198 		if (ddi_copyout(&(pkt->cmd_cfga.errtype),
1199 		    (void *)&(((sysc_cfga_cmd32_t *)arg)->errtype),
1200 		    sizeof (sysc_err_t), flag) != 0) {
1201 			ret = FALSE;
1202 		}
1203 	} else
1204 #endif
1205 	if (ddi_copyout(&(pkt->cmd_cfga.errtype),
1206 	    (void *)&(((sysc_cfga_cmd_t *)arg)->errtype),
1207 	    sizeof (sysc_err_t), flag) != 0) {
1208 		ret = FALSE;
1209 	}
1210 
1211 	if ((ret != FALSE) && ((pkt->cmd_cfga.outputstr != NULL) &&
1212 	    (ddi_copyout(pkt->errbuf, pkt->cmd_cfga.outputstr,
1213 	    SYSC_OUTPUT_LEN, flag) != 0))) {
1214 			ret = FALSE;
1215 	}
1216 
1217 	kmem_free(pkt->errbuf, SYSC_OUTPUT_LEN);
1218 	return (ret);
1219 }
1220 
1221 /* ARGSUSED */
1222 static int
1223 sysctrl_ioctl(dev_t devt, int cmd, intptr_t arg, int flag, cred_t *cred_p,
1224     int *rval_p)
1225 {
1226 	struct sysctrl_soft_state *softsp;
1227 	sysc_cfga_pkt_t sysc_pkt;
1228 	fhc_bd_t *fhc_list = NULL;
1229 	sysc_cfga_stat_t *sc_list = NULL;
1230 	fhc_bd_t *bdp;
1231 	sysc_cfga_stat_t *sc = NULL;
1232 	int instance;
1233 	int slot;
1234 	int retval = 0;
1235 	int i;
1236 
1237 	instance = GETINSTANCE(devt);
1238 	softsp = GETSOFTC(instance);
1239 	if (softsp == NULL) {
1240 		cmn_err(CE_CONT,
1241 		    "sysctrl_ioctl(%d): NULL softstate ptr!\n",
1242 		    (int)GETSLOT(devt));
1243 		return (ENXIO);
1244 	}
1245 
1246 	slot = GETSLOT(devt);
1247 
1248 	/*
1249 	 * First switch is to do correct locking and do ddi_copyin()
1250 	 */
1251 	switch (cmd) {
1252 	case SYSC_CFGA_CMD_GETSTATUS:
1253 		/* mutex lock the whole list */
1254 		if (sysc_enter_transition(-1) != TRUE) {
1255 			retval = EBUSY;
1256 			goto cleanup_exit;
1257 		}
1258 
1259 		/* allocate the memory before acquiring mutex */
1260 		fhc_list = kmem_zalloc(sizeof (fhc_bd_t) * fhc_max_boards(),
1261 		    KM_SLEEP);
1262 
1263 		sc_list = kmem_zalloc(sizeof (sysc_cfga_stat_t) *
1264 		    fhc_max_boards(), KM_SLEEP);
1265 
1266 		break;
1267 
1268 	case SYSC_CFGA_CMD_EJECT:
1269 	case SYSC_CFGA_CMD_INSERT:
1270 		retval = ENOTSUP;
1271 		goto cleanup_exit;
1272 
1273 	case SYSC_CFGA_CMD_CONNECT:
1274 	case SYSC_CFGA_CMD_DISCONNECT:
1275 	case SYSC_CFGA_CMD_UNCONFIGURE:
1276 	case SYSC_CFGA_CMD_CONFIGURE:
1277 	case SYSC_CFGA_CMD_TEST:
1278 	case SYSC_CFGA_CMD_TEST_SET_COND:
1279 	case SYSC_CFGA_CMD_QUIESCE_TEST:
1280 
1281 		/* ioctls allowed if caller has write permission */
1282 		if (!(flag & FWRITE)) {
1283 			retval = EPERM;
1284 			goto cleanup_exit;
1285 		}
1286 
1287 		retval = sysc_pkt_init(&sysc_pkt, arg, flag);
1288 		if (retval != 0)
1289 			goto cleanup_exit;
1290 
1291 		/* grasp lock and set in_transition bit */
1292 		if (sysc_enter_transition(cmd == SYSC_CFGA_CMD_QUIESCE_TEST
1293 		    ? -1 : slot) != TRUE) {
1294 			retval = EBUSY;
1295 			SYSC_ERR_SET(&sysc_pkt, SYSC_ERR_INTRANS);
1296 			goto cleanup_copyout;
1297 		}
1298 
1299 		/* get the status structure for the slot */
1300 		bdp = fhc_bd(slot);
1301 		sc = &bdp->sc;
1302 		break;
1303 
1304 	/* POSIX definition: return ENOTTY if unsupported command */
1305 	default:
1306 		retval = ENOTTY;
1307 		goto cleanup_exit;
1308 	}
1309 
1310 	/*
1311 	 * Second switch is to call the underlayer workhorse.
1312 	 */
1313 	switch (cmd) {
1314 	case SYSC_CFGA_CMD_GETSTATUS:
1315 		for (i = 0; i < fhc_max_boards(); i++) {
1316 			if (fhc_bd_valid(i)) {
1317 				bdp = fhc_bd(i);
1318 				if (fhc_bd_is_jtag_master(i))
1319 					bdp->sc.no_detach = 1;
1320 				else
1321 					bdp->sc.no_detach = 0;
1322 				bcopy((caddr_t)&bdp->sc,
1323 				    &sc_list[i], sizeof (sysc_cfga_stat_t));
1324 			} else {
1325 				sc_list[i].board = -1;
1326 				sc_list[i].rstate = SYSC_CFGA_RSTATE_EMPTY;
1327 			}
1328 		}
1329 
1330 		sysc_exit_transition(-1);
1331 
1332 		break;
1333 
1334 	case SYSC_CFGA_CMD_EJECT:
1335 	case SYSC_CFGA_CMD_INSERT:
1336 		retval = ENOTSUP;
1337 		goto cleanup_exit;
1338 
1339 	case SYSC_CFGA_CMD_CONNECT:
1340 		retval = sysc_policy_connect(softsp, &sysc_pkt, sc);
1341 		sysc_exit_transition(slot);
1342 		break;
1343 
1344 	case SYSC_CFGA_CMD_DISCONNECT:
1345 		retval = sysc_policy_disconnect(softsp, &sysc_pkt, sc);
1346 		sysc_exit_transition(slot);
1347 		break;
1348 
1349 	case SYSC_CFGA_CMD_UNCONFIGURE:
1350 		retval = sysc_policy_unconfigure(softsp, &sysc_pkt, sc);
1351 		sysc_exit_transition(slot);
1352 		break;
1353 
1354 	case SYSC_CFGA_CMD_CONFIGURE:
1355 		retval = sysc_policy_configure(softsp, &sysc_pkt, sc);
1356 		sysc_exit_transition(slot);
1357 		break;
1358 
1359 	case SYSC_CFGA_CMD_TEST:
1360 		retval = fhc_bd_test(slot, &sysc_pkt);
1361 		sysc_exit_transition(slot);
1362 		break;
1363 
1364 	case SYSC_CFGA_CMD_TEST_SET_COND:
1365 		retval = fhc_bd_test_set_cond(slot, &sysc_pkt);
1366 		sysc_exit_transition(slot);
1367 		break;
1368 
1369 	case SYSC_CFGA_CMD_QUIESCE_TEST:
1370 		sysctrl_suspend_prepare();
1371 		fhc_bdlist_unlock();
1372 
1373 		if (sysctrl_suspend(&sysc_pkt) == DDI_SUCCESS) {
1374 			sysctrl_resume(&sysc_pkt);
1375 		} else {
1376 			retval = EBUSY;
1377 		}
1378 
1379 		(void) fhc_bdlist_lock(-1);
1380 		sysc_exit_transition(-1);
1381 		break;
1382 
1383 	default:
1384 		retval = ENOTTY;
1385 		goto cleanup_exit;
1386 	}
1387 
1388 cleanup_copyout:
1389 	/*
1390 	 * 3rd switch is to do appropriate copyout and reset locks
1391 	 */
1392 	switch (cmd) {
1393 	case SYSC_CFGA_CMD_GETSTATUS:
1394 		if (ddi_copyout(sc_list, (void *)arg,
1395 		    sizeof (sysc_cfga_stat_t) * fhc_max_boards(),
1396 		    flag) != 0) {
1397 			retval = EFAULT;
1398 		}
1399 
1400 		/* cleanup memory */
1401 		kmem_free(fhc_list, sizeof (fhc_bd_t) * fhc_max_boards());
1402 		kmem_free(sc_list, sizeof (sysc_cfga_stat_t) *
1403 		    fhc_max_boards());
1404 		break;
1405 
1406 	case SYSC_CFGA_CMD_EJECT:
1407 	case SYSC_CFGA_CMD_INSERT:
1408 		retval = ENOTSUP;
1409 		break;
1410 
1411 	case SYSC_CFGA_CMD_CONNECT:
1412 	case SYSC_CFGA_CMD_DISCONNECT:
1413 	case SYSC_CFGA_CMD_UNCONFIGURE:
1414 	case SYSC_CFGA_CMD_CONFIGURE:
1415 	case SYSC_CFGA_CMD_TEST:
1416 	case SYSC_CFGA_CMD_TEST_SET_COND:
1417 	case SYSC_CFGA_CMD_QUIESCE_TEST:
1418 		if (sysc_pkt_fini(&sysc_pkt, arg, flag) != TRUE)
1419 			return (EFAULT);
1420 		break;
1421 
1422 	default:
1423 		retval = ENOTTY;
1424 		break;
1425 	}
1426 
1427 cleanup_exit:
1428 	return (retval);
1429 }
1430 
1431 /*
1432  * system_high_handler()
1433  * This routine handles system interrupts.
1434  *
1435  * This routine goes through all the interrupt sources and masks
1436  * off the enable bit if interrupting.  Because of the special
1437  * nature of the pps fan source bits, we also cache the state
1438  * of the fan bits for that special case.
1439  *
1440  * The rest of the work is done in the low level handlers
1441  */
1442 static uint_t
1443 system_high_handler(caddr_t arg)
1444 {
1445 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1446 	uchar_t csr;
1447 	uchar_t status2;
1448 	uchar_t tmp_reg;
1449 	int serviced = 0;
1450 
1451 	ASSERT(softsp);
1452 
1453 	mutex_enter(&softsp->csr_mutex);
1454 
1455 	/* read in the hardware registers */
1456 	csr = *(softsp->csr);
1457 	status2 = *(softsp->status2);
1458 
1459 	if (csr & SYS_AC_PWR_FAIL_EN) {
1460 		if (status2 & SYS_AC_FAIL) {
1461 
1462 			/* save the powerfail state in nvram */
1463 			nvram_update_powerfail(softsp);
1464 
1465 			/* disable this interrupt source */
1466 			csr &= ~SYS_AC_PWR_FAIL_EN;
1467 
1468 			ddi_trigger_softintr(softsp->ac_fail_id);
1469 			serviced++;
1470 		}
1471 	}
1472 
1473 	if (csr & SYS_PS_FAIL_EN) {
1474 		if ((*(softsp->ps_stat) != 0xff) ||
1475 		    ((~status2) & (SYS_PPS0_OK | SYS_CLK_33_OK |
1476 		    SYS_CLK_50_OK)) ||
1477 		    (~(*(softsp->pppsr)) & SYS_PPPSR_BITS)) {
1478 
1479 			/* disable this interrupt source */
1480 			csr &= ~SYS_PS_FAIL_EN;
1481 
1482 			ddi_trigger_softintr(softsp->ps_fail_int_id);
1483 			serviced++;
1484 		}
1485 	}
1486 
1487 	if (csr & SYS_PPS_FAN_FAIL_EN) {
1488 		if (status2 & SYS_RACK_FANFAIL ||
1489 		    !(status2 & SYS_AC_FAN_OK) ||
1490 		    !(status2 & SYS_KEYSW_FAN_OK)) {
1491 
1492 			/*
1493 			 * we must cache the fan status because it goes
1494 			 * away when we disable interrupts !?!?!
1495 			 */
1496 			softsp->pps_fan_saved = status2;
1497 
1498 			/* disable this interrupt source */
1499 			csr &= ~SYS_PPS_FAN_FAIL_EN;
1500 
1501 			ddi_trigger_softintr(softsp->pps_fan_id);
1502 			serviced++;
1503 		}
1504 	}
1505 
1506 	if (csr & SYS_SBRD_PRES_EN) {
1507 		if (!(*(softsp->status1) & SYS_NOT_BRD_PRES)) {
1508 
1509 			/* disable this interrupt source */
1510 			csr &= ~SYS_SBRD_PRES_EN;
1511 
1512 			ddi_trigger_softintr(softsp->sbrd_pres_id);
1513 			serviced++;
1514 		}
1515 	}
1516 
1517 	if (!serviced) {
1518 
1519 		/*
1520 		 * if we get here than it is likely that contact bounce
1521 		 * is messing with us.  so, we need to shut this interrupt
1522 		 * up for a while to let the contacts settle down.
1523 		 * Then we will re-enable the interrupts that are enabled
1524 		 * right now.  The trick is to disable the appropriate
1525 		 * interrupts and then to re-enable them correctly, even
1526 		 * though intervening handlers might have been working.
1527 		 */
1528 
1529 		/* remember all interrupts that could have caused it */
1530 		softsp->saved_en_state |= csr &
1531 		    (SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
1532 		    SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
1533 
1534 		/* and then turn them off */
1535 		csr &= ~(SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
1536 		    SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
1537 
1538 		/* and then bump the counter */
1539 		softsp->spur_count++;
1540 
1541 		/* and kick off the timeout */
1542 		ddi_trigger_softintr(softsp->spur_id);
1543 	}
1544 
1545 	/* update the real csr */
1546 	*(softsp->csr) = csr;
1547 	tmp_reg = *(softsp->csr);
1548 #ifdef lint
1549 	tmp_reg = tmp_reg;
1550 #endif
1551 	mutex_exit(&softsp->csr_mutex);
1552 
1553 	return (DDI_INTR_CLAIMED);
1554 }
1555 
1556 /*
1557  * we've detected a spurious interrupt.
1558  * determine if we should log a message and if we need another timeout
1559  */
1560 static uint_t
1561 spur_delay(caddr_t arg)
1562 {
1563 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1564 
1565 	ASSERT(softsp);
1566 
1567 	/* do we need to complain? */
1568 	mutex_enter(&softsp->csr_mutex);
1569 
1570 	/* NOTE: this is == because we want one message per long timeout */
1571 	if (softsp->spur_count == MAX_SPUR_COUNT) {
1572 		char buf[128];
1573 
1574 		/* print out the candidates known at this time */
1575 		/* XXX not perfect because of re-entrant nature but close */
1576 		buf[0] = '\0';
1577 		if (softsp->saved_en_state & SYS_AC_PWR_FAIL_EN)
1578 			(void) strcat(buf, "AC FAIL");
1579 		if (softsp->saved_en_state & SYS_PPS_FAN_FAIL_EN)
1580 			(void) strcat(buf, buf[0] ? "|PPS FANS" : "PPS FANS");
1581 		if (softsp->saved_en_state & SYS_PS_FAIL_EN)
1582 			(void) strcat(buf, buf[0] ? "|PS FAIL" : "PS FAIL");
1583 		if (softsp->saved_en_state & SYS_SBRD_PRES_EN)
1584 			(void) strcat(buf,
1585 			    buf[0] ? "|BOARD INSERT" : "BOARD INSERT");
1586 
1587 		/*
1588 		 * This is a high level mutex, therefore it needs to be
1589 		 * dropped before calling cmn_err.
1590 		 */
1591 		mutex_exit(&softsp->csr_mutex);
1592 
1593 		cmn_err(CE_WARN, "sysctrl%d: unserviced interrupt."
1594 		    " possible sources [%s].",
1595 		    ddi_get_instance(softsp->dip), buf);
1596 	} else
1597 		mutex_exit(&softsp->csr_mutex);
1598 
1599 	mutex_enter(&softsp->spur_int_lock);
1600 
1601 	/* do we need to start the short timeout? */
1602 	if (softsp->spur_timeout_id == 0) {
1603 		softsp->spur_timeout_id = timeout(spur_retry, softsp,
1604 		    spur_timeout_hz);
1605 	}
1606 
1607 	/* do we need to start the long timeout? */
1608 	if (softsp->spur_long_timeout_id == 0) {
1609 		softsp->spur_long_timeout_id = timeout(spur_long_timeout,
1610 		    softsp, spur_long_timeout_hz);
1611 	}
1612 
1613 	mutex_exit(&softsp->spur_int_lock);
1614 
1615 	return (DDI_INTR_CLAIMED);
1616 }
1617 
1618 /*
1619  * spur_retry
1620  *
1621  * this routine simply triggers the interrupt which will re-enable
1622  * the interrupts disabled by the spurious int detection.
1623  */
1624 static void
1625 spur_retry(void *arg)
1626 {
1627 	struct sysctrl_soft_state *softsp = arg;
1628 
1629 	ASSERT(softsp);
1630 
1631 	ddi_trigger_softintr(softsp->spur_high_id);
1632 
1633 	mutex_enter(&softsp->spur_int_lock);
1634 	softsp->spur_timeout_id = 0;
1635 	mutex_exit(&softsp->spur_int_lock);
1636 }
1637 
1638 /*
1639  * spur_reenable
1640  *
1641  * OK, we've been slient for a while.   Go ahead and re-enable the
1642  * interrupts that were enabled at the time of the spurious detection.
1643  */
1644 static uint_t
1645 spur_reenable(caddr_t arg)
1646 {
1647 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1648 	uchar_t tmp_reg;
1649 
1650 	ASSERT(softsp);
1651 
1652 	mutex_enter(&softsp->csr_mutex);
1653 
1654 	/* reenable those who were spurious candidates */
1655 	*(softsp->csr) |= softsp->saved_en_state &
1656 	    (SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
1657 	    SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
1658 	tmp_reg = *(softsp->csr);
1659 #ifdef lint
1660 	tmp_reg = tmp_reg;
1661 #endif
1662 
1663 	/* clear out the saved state */
1664 	softsp->saved_en_state = 0;
1665 
1666 	mutex_exit(&softsp->csr_mutex);
1667 
1668 	return (DDI_INTR_CLAIMED);
1669 }
1670 
1671 /*
1672  * spur_long_timeout
1673  *
1674  * this routine merely resets the spurious interrupt counter thus ending
1675  * the interval of interest.  of course this is done by triggering a
1676  * softint because the counter is protected by an interrupt mutex.
1677  */
1678 static void
1679 spur_long_timeout(void *arg)
1680 {
1681 	struct sysctrl_soft_state *softsp = arg;
1682 
1683 	ASSERT(softsp);
1684 
1685 	ddi_trigger_softintr(softsp->spur_long_to_id);
1686 
1687 	mutex_enter(&softsp->spur_int_lock);
1688 	softsp->spur_long_timeout_id = 0;
1689 	mutex_exit(&softsp->spur_int_lock);
1690 }
1691 
1692 /*
1693  * spur_clear_count
1694  *
1695  * simply clear out the spurious interrupt counter.
1696  *
1697  * softint level only
1698  */
1699 static uint_t
1700 spur_clear_count(caddr_t arg)
1701 {
1702 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1703 
1704 	ASSERT(softsp);
1705 
1706 	mutex_enter(&softsp->csr_mutex);
1707 	softsp->spur_count = 0;
1708 	mutex_exit(&softsp->csr_mutex);
1709 
1710 	return (DDI_INTR_CLAIMED);
1711 }
1712 
1713 /*
1714  * ac_fail_handler
1715  *
1716  * This routine polls the AC power failure bit in the system status2
1717  * register.  If we get to this routine, then we sensed an ac fail
1718  * condition.  Note the fact and check again in a few.
1719  *
1720  * Called as softint from high interrupt.
1721  */
1722 static uint_t
1723 ac_fail_handler(caddr_t arg)
1724 {
1725 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1726 
1727 	ASSERT(softsp);
1728 
1729 	cmn_err(CE_WARN, "%s failure detected", ft_str_table[FT_AC_PWR]);
1730 	reg_fault(0, FT_AC_PWR, FT_SYSTEM);
1731 	(void) timeout(ac_fail_retry, softsp, ac_timeout_hz);
1732 
1733 	return (DDI_INTR_CLAIMED);
1734 }
1735 
1736 /*
1737  * The timeout from ac_fail_handler() that checks to see if the
1738  * condition persists.
1739  */
1740 static void
1741 ac_fail_retry(void *arg)
1742 {
1743 	struct sysctrl_soft_state *softsp = arg;
1744 
1745 	ASSERT(softsp);
1746 
1747 	if (*softsp->status2 & SYS_AC_FAIL) {	/* still bad? */
1748 		(void) timeout(ac_fail_retry, softsp, ac_timeout_hz);
1749 	} else {
1750 		cmn_err(CE_NOTE, "%s failure no longer detected",
1751 		    ft_str_table[FT_AC_PWR]);
1752 		clear_fault(0, FT_AC_PWR, FT_SYSTEM);
1753 		ddi_trigger_softintr(softsp->ac_fail_high_id);
1754 	}
1755 }
1756 
1757 /*
1758  * The interrupt routine that we use to re-enable the interrupt.
1759  * Called from ddi_trigger_softint() in the ac_fail_retry() when
1760  * the AC is better.
1761  */
1762 static uint_t
1763 ac_fail_reenable(caddr_t arg)
1764 {
1765 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1766 	uchar_t tmp_reg;
1767 
1768 	ASSERT(softsp);
1769 
1770 	mutex_enter(&softsp->csr_mutex);
1771 	*(softsp->csr) |= SYS_AC_PWR_FAIL_EN;
1772 	tmp_reg = *(softsp->csr);
1773 #ifdef lint
1774 	tmp_reg = tmp_reg;
1775 #endif
1776 	mutex_exit(&softsp->csr_mutex);
1777 
1778 	return (DDI_INTR_CLAIMED);
1779 }
1780 
1781 /*
1782  * ps_fail_int_handler
1783  *
1784  * Handle power supply failure interrupt.
1785  *
1786  * This wrapper is called as softint from hardware interrupt routine.
1787  */
1788 static uint_t
1789 ps_fail_int_handler(caddr_t arg)
1790 {
1791 	return (ps_fail_handler((struct sysctrl_soft_state *)arg, 1));
1792 }
1793 
1794 /*
1795  * ps_fail_poll_handler
1796  *
1797  * Handle power supply failure interrupt.
1798  *
1799  * This wrapper is called as softint from power supply poll routine.
1800  */
1801 static uint_t
1802 ps_fail_poll_handler(caddr_t arg)
1803 {
1804 	return (ps_fail_handler((struct sysctrl_soft_state *)arg, 0));
1805 }
1806 
1807 /*
1808  * ps_fail_handler
1809  *
1810  * This routine checks all eight of the board power supplies that are
1811  * installed plus the Peripheral power supply and the two DC OK. Since the
1812  * hardware bits are not enough to indicate Power Supply failure
1813  * vs. being turned off via software, the driver must maintain a
1814  * shadow state for the Power Supply status and monitor all changes.
1815  *
1816  * Called as a softint only.
1817  */
1818 static uint_t
1819 ps_fail_handler(struct sysctrl_soft_state *softsp, int fromint)
1820 {
1821 	int i;
1822 	struct ps_state *pstatp;
1823 	int poll_needed = 0;
1824 	uchar_t ps_stat, ps_pres, status1, status2, pppsr;
1825 	uchar_t tmp_reg;
1826 	enum power_state current_power_state;
1827 
1828 	ASSERT(softsp);
1829 
1830 	/* pre-read the hardware state */
1831 	ps_stat = *softsp->ps_stat;
1832 	ps_pres = *softsp->ps_pres;
1833 	status1 = *softsp->status1;
1834 	status2 = *softsp->status2;
1835 	pppsr	= *softsp->pppsr;
1836 
1837 	(void) fhc_bdlist_lock(-1);
1838 
1839 	mutex_enter(&softsp->ps_fail_lock);
1840 
1841 	for (i = 0, pstatp = &softsp->ps_stats[0]; i < SYS_PS_COUNT;
1842 	    i++, pstatp++) {
1843 		int	temp_psok;
1844 		int	temp_pres;
1845 		int	is_precharge = FALSE;
1846 		int	is_fan_assy = FALSE;
1847 
1848 		/*
1849 		 * pre-compute the presence and ok bits for this
1850 		 * power supply from the hardware registers.
1851 		 * NOTE: 4-slot pps1 is the same as core ps 7...
1852 		 */
1853 		switch (i) {
1854 		/* the core power supplies */
1855 		case 0: case 1: case 2: case 3:
1856 		case 4: case 5: case 6: case 7:
1857 			temp_pres = !((ps_pres >> i) & 0x1);
1858 			temp_psok = (ps_stat >> i) & 0x1;
1859 			break;
1860 
1861 		/* the first peripheral power supply */
1862 		case SYS_PPS0_INDEX:
1863 			temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1864 			temp_psok = status2 & SYS_PPS0_OK;
1865 			break;
1866 
1867 		/* shared 3.3v clock power */
1868 		case SYS_CLK_33_INDEX:
1869 			temp_pres = TRUE;
1870 			temp_psok = status2 & SYS_CLK_33_OK;
1871 			break;
1872 
1873 		/* shared 5.0v clock power */
1874 		case SYS_CLK_50_INDEX:
1875 			temp_pres = TRUE;
1876 			temp_psok = status2 & SYS_CLK_50_OK;
1877 			break;
1878 
1879 		/* peripheral 5v */
1880 		case SYS_V5_P_INDEX:
1881 			temp_pres = !(status1 & SYS_NOT_PPS0_PRES) ||
1882 			    ((IS4SLOT(softsp->nslots) ||
1883 			    IS5SLOT(softsp->nslots)) &&
1884 			    !(ps_pres & SYS_NOT_PPS1_PRES));
1885 			temp_psok = pppsr & SYS_V5_P_OK;
1886 			break;
1887 
1888 		/* peripheral 12v */
1889 		case SYS_V12_P_INDEX:
1890 			temp_pres = !(status1 & SYS_NOT_PPS0_PRES) ||
1891 			    ((IS4SLOT(softsp->nslots) ||
1892 			    IS5SLOT(softsp->nslots)) &&
1893 			    !(ps_pres & SYS_NOT_PPS1_PRES));
1894 			temp_psok = pppsr & SYS_V12_P_OK;
1895 			break;
1896 
1897 		/* aux 5v */
1898 		case SYS_V5_AUX_INDEX:
1899 			temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1900 			temp_psok = pppsr & SYS_V5_AUX_OK;
1901 			break;
1902 
1903 		/* peripheral 5v precharge */
1904 		case SYS_V5_P_PCH_INDEX:
1905 			temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1906 			temp_psok = pppsr & SYS_V5_P_PCH_OK;
1907 			is_precharge = TRUE;
1908 			break;
1909 
1910 		/* peripheral 12v precharge */
1911 		case SYS_V12_P_PCH_INDEX:
1912 			temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1913 			temp_psok = pppsr & SYS_V12_P_PCH_OK;
1914 			is_precharge = TRUE;
1915 			break;
1916 
1917 		/* 3.3v precharge */
1918 		case SYS_V3_PCH_INDEX:
1919 			temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1920 			temp_psok = pppsr & SYS_V3_PCH_OK;
1921 			is_precharge = TRUE;
1922 			break;
1923 
1924 		/* 5v precharge */
1925 		case SYS_V5_PCH_INDEX:
1926 			temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1927 			temp_psok = pppsr & SYS_V5_PCH_OK;
1928 			is_precharge = TRUE;
1929 			break;
1930 
1931 		/* peripheral fan assy */
1932 		case SYS_P_FAN_INDEX:
1933 			temp_pres = (IS4SLOT(softsp->nslots) ||
1934 			    IS5SLOT(softsp->nslots)) &&
1935 			    !(status1 & SYS_NOT_P_FAN_PRES);
1936 			temp_psok = softsp->pps_fan_saved &
1937 			    SYS_AC_FAN_OK;
1938 			is_fan_assy = TRUE;
1939 			break;
1940 		}
1941 
1942 		/* *** Phase 1 -- power supply presence tests *** */
1943 
1944 		/* do we know the presence status for this power supply? */
1945 		if (pstatp->pshadow == PRES_UNKNOWN) {
1946 			pstatp->pshadow = temp_pres ? PRES_IN : PRES_OUT;
1947 			pstatp->dcshadow = temp_pres ? PS_BOOT : PS_OUT;
1948 		} else {
1949 			/* has the ps presence state changed? */
1950 			if (!temp_pres ^ (pstatp->pshadow == PRES_IN)) {
1951 				pstatp->pctr = 0;
1952 			} else {
1953 				/* a change! are we counting? */
1954 				if (pstatp->pctr == 0) {
1955 					pstatp->pctr = PS_PRES_CHANGE_TICKS;
1956 				} else if (--pstatp->pctr == 0) {
1957 					pstatp->pshadow = temp_pres ?
1958 					    PRES_IN : PRES_OUT;
1959 					pstatp->dcshadow = temp_pres ?
1960 					    PS_UNKNOWN : PS_OUT;
1961 
1962 					/*
1963 					 * Now we know the state has
1964 					 * changed, so we should log it.
1965 					 */
1966 					ps_log_pres_change(softsp,
1967 					    i, temp_pres);
1968 				}
1969 			}
1970 		}
1971 
1972 		/* *** Phase 2 -- power supply status tests *** */
1973 
1974 		/* check if the Power Supply is removed or same as before */
1975 		if ((pstatp->dcshadow == PS_OUT) ||
1976 		    ((pstatp->dcshadow == PS_OK) && temp_psok) ||
1977 		    ((pstatp->dcshadow == PS_FAIL) && !temp_psok)) {
1978 			pstatp->dcctr = 0;
1979 		} else {
1980 
1981 			/* OK, a change, do we start the timer? */
1982 			if (pstatp->dcctr == 0) {
1983 				switch (pstatp->dcshadow) {
1984 				case PS_BOOT:
1985 					pstatp->dcctr = PS_FROM_BOOT_TICKS;
1986 					break;
1987 
1988 				case PS_UNKNOWN:
1989 					pstatp->dcctr = is_fan_assy ?
1990 					    PS_P_FAN_FROM_UNKNOWN_TICKS :
1991 					    PS_FROM_UNKNOWN_TICKS;
1992 					break;
1993 
1994 				case PS_OK:
1995 					pstatp->dcctr = is_precharge ?
1996 					    PS_PCH_FROM_OK_TICKS :
1997 					    PS_FROM_OK_TICKS;
1998 					break;
1999 
2000 				case PS_FAIL:
2001 					pstatp->dcctr = PS_FROM_FAIL_TICKS;
2002 					break;
2003 
2004 				default:
2005 					panic("sysctrl%d: Unknown Power "
2006 					    "Supply State %d", pstatp->dcshadow,
2007 					    ddi_get_instance(softsp->dip));
2008 				}
2009 			}
2010 
2011 			/* has the ticker expired? */
2012 			if (--pstatp->dcctr == 0) {
2013 
2014 				/* we'll skip OK messages during boot */
2015 				if (!((pstatp->dcshadow == PS_BOOT) &&
2016 				    temp_psok)) {
2017 					ps_log_state_change(softsp,
2018 					    i, temp_psok);
2019 				}
2020 
2021 				/*
2022 				 * remote console interface has to be
2023 				 * reinitialized on the rising edge V5_AUX
2024 				 * when it is NOT boot. At the boot time an
2025 				 * an error condition exists if it was not
2026 				 * enabled before.
2027 				 */
2028 				if ((i == SYS_V5_AUX_INDEX) &&
2029 				    (pstatp->dcshadow != PS_BOOT) &&
2030 				    (softsp->enable_rcons_atboot)) {
2031 					if (temp_psok)
2032 						rcons_reinit(softsp);
2033 					else
2034 						/* disable rconsole */
2035 						*(softsp->clk_freq2) &=
2036 						    ~RCONS_UART_EN;
2037 					tmp_reg = *(softsp->csr);
2038 #ifdef lint
2039 					tmp_reg = tmp_reg;
2040 #endif
2041 
2042 				}
2043 
2044 				/* regardless, update the shadow state */
2045 				pstatp->dcshadow = temp_psok ? PS_OK : PS_FAIL;
2046 
2047 				/* always update board condition */
2048 				sysc_policy_update(softsp, NULL,
2049 				    SYSC_EVT_BD_PS_CHANGE);
2050 
2051 			}
2052 		}
2053 
2054 		/*
2055 		 * We will need to continue polling for three reasons:
2056 		 * - a failing power supply is detected and we haven't yet
2057 		 *   determined the power supplies existence.
2058 		 * - the power supply is just installed and we're waiting
2059 		 *   to give it a change to power up,
2060 		 * - a failed power supply state is recognized
2061 		 *
2062 		 * NOTE: PS_FAIL shadow state is not the same as !temp_psok
2063 		 * because of the persistence of PS_FAIL->PS_OK.
2064 		 */
2065 		if (!temp_psok ||
2066 		    (pstatp->dcshadow == PS_UNKNOWN) ||
2067 		    (pstatp->dcshadow == PS_FAIL)) {
2068 			poll_needed++;
2069 		}
2070 	}
2071 
2072 	/*
2073 	 * Now, get the current power state for this instance.
2074 	 * If the current state is different than what was known, complain.
2075 	 */
2076 	current_power_state = compute_power_state(softsp, 0);
2077 
2078 	if (softsp->power_state != current_power_state) {
2079 		switch (current_power_state) {
2080 		case BELOW_MINIMUM:
2081 			cmn_err(CE_WARN,
2082 			    "Insufficient power available to system");
2083 			if (!disable_insufficient_power_reboot) {
2084 				cmn_err(CE_WARN, "System reboot in %d seconds",
2085 				    PS_INSUFFICIENT_COUNTDOWN_SEC);
2086 			}
2087 			reg_fault(1, FT_INSUFFICIENT_POWER, FT_SYSTEM);
2088 			softsp->power_countdown = PS_POWER_COUNTDOWN_TICKS;
2089 			break;
2090 
2091 		case MINIMUM:
2092 			/* If we came from REDUNDANT, complain */
2093 			if (softsp->power_state == REDUNDANT) {
2094 				cmn_err(CE_WARN, "Redundant power lost");
2095 			/* If we came from BELOW_MINIMUM, hurrah! */
2096 			} else if (softsp->power_state == BELOW_MINIMUM) {
2097 				cmn_err(CE_NOTE, "Minimum power available");
2098 				clear_fault(1, FT_INSUFFICIENT_POWER,
2099 				    FT_SYSTEM);
2100 			}
2101 			break;
2102 
2103 		case REDUNDANT:
2104 			/* If we aren't from boot, spread the good news */
2105 			if (softsp->power_state != BOOT) {
2106 				cmn_err(CE_NOTE, "Redundant power available");
2107 				clear_fault(1, FT_INSUFFICIENT_POWER,
2108 				    FT_SYSTEM);
2109 			}
2110 			break;
2111 
2112 		default:
2113 			break;
2114 		}
2115 		softsp->power_state = current_power_state;
2116 		sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2117 	}
2118 
2119 	mutex_exit(&softsp->ps_fail_lock);
2120 
2121 	fhc_bdlist_unlock();
2122 
2123 	/*
2124 	 * Are we in insufficient powerstate?
2125 	 * If so, is it time to take action?
2126 	 */
2127 	if (softsp->power_state == BELOW_MINIMUM &&
2128 	    softsp->power_countdown > 0 && --(softsp->power_countdown) == 0 &&
2129 	    !disable_insufficient_power_reboot) {
2130 		cmn_err(CE_WARN,
2131 		    "Insufficient power. System Reboot Started...");
2132 
2133 		fhc_reboot();
2134 	}
2135 
2136 	/*
2137 	 * If we don't have ps problems that need to be polled for, then
2138 	 * enable interrupts.
2139 	 */
2140 	if (!poll_needed) {
2141 		mutex_enter(&softsp->csr_mutex);
2142 		*(softsp->csr) |= SYS_PS_FAIL_EN;
2143 		tmp_reg = *(softsp->csr);
2144 #ifdef lint
2145 		tmp_reg = tmp_reg;
2146 #endif
2147 		mutex_exit(&softsp->csr_mutex);
2148 	}
2149 
2150 	/*
2151 	 * Only the polling loop re-triggers the polling loop timeout
2152 	 */
2153 	if (!fromint) {
2154 		(void) timeout(ps_fail_retry, softsp, ps_fail_timeout_hz);
2155 	}
2156 
2157 	return (DDI_INTR_CLAIMED);
2158 }
2159 
2160 /*
2161  * Compute the current power configuration for this system.
2162  * Disk boards and Clock boards are not counted.
2163  *
2164  * This function must be called with the ps_fail_lock held.
2165  */
2166 enum power_state
2167 compute_power_state(struct sysctrl_soft_state *softsp, int plus_load)
2168 {
2169 	int i;
2170 	int ok_supply_count = 0;
2171 	int load_count = 0;
2172 	int minimum_power_count;
2173 	int pps_ok;
2174 	fhc_bd_t *list;
2175 
2176 	ASSERT(mutex_owned(&softsp->ps_fail_lock));
2177 
2178 	/*
2179 	 * Walk down the interesting power supplies and
2180 	 * count the operational power units
2181 	 */
2182 	for (i = 0; i < 8; i++) {
2183 		/*
2184 		 * power supply id 7 on a 4 or 5 slot system is PPS1.
2185 		 * don't include it in the redundant core power calculation.
2186 		 */
2187 		if (i == 7 &&
2188 		    (IS4SLOT(softsp->nslots) || IS5SLOT(softsp->nslots)))
2189 			continue;
2190 
2191 		if (softsp->ps_stats[i].dcshadow == PS_OK)
2192 			ok_supply_count++;
2193 	}
2194 
2195 	/* Note the state of the PPS... */
2196 	pps_ok = (softsp->ps_stats[SYS_PPS0_INDEX].dcshadow == PS_OK);
2197 
2198 	/*
2199 	 * Dynamically compute the load count in the system.
2200 	 * Don't count disk boards or boards in low power state.
2201 	 */
2202 	for (list = fhc_bd_first(); list; list = fhc_bd_next(list)) {
2203 		ASSERT(list->sc.type != CLOCK_BOARD);
2204 		if (list->sc.rstate == SYSC_CFGA_RSTATE_CONNECTED) {
2205 			load_count++;
2206 		}
2207 	}
2208 
2209 	load_count += plus_load;
2210 	/*
2211 	 * If we are 8 slot and we have 7 or 8 boards, then the PPS
2212 	 * can count as a power supply...
2213 	 */
2214 	if (IS8SLOT(softsp->nslots) && load_count >= 7 && pps_ok)
2215 		ok_supply_count++;
2216 
2217 	/*
2218 	 * This is to cover the corner case of a UE3500 having 5
2219 	 * boards installed and still giving it N+1 power status.
2220 	 */
2221 	if (IS5SLOT(softsp->nslots) && (load_count >= 5))
2222 		ok_supply_count++;
2223 
2224 	/*
2225 	 * Determine our power situation.  This is a simple step
2226 	 * function right now:
2227 	 *
2228 	 * minimum power count = min(7, floor((board count + 1) / 2))
2229 	 */
2230 	minimum_power_count = (load_count + 1) / 2;
2231 	if (minimum_power_count > 7)
2232 		minimum_power_count = 7;
2233 
2234 	if (ok_supply_count > minimum_power_count)
2235 		return (REDUNDANT);
2236 	else if (ok_supply_count == minimum_power_count)
2237 		return (MINIMUM);
2238 	else
2239 		return (BELOW_MINIMUM);
2240 }
2241 
2242 /*
2243  * log the change of power supply presence
2244  */
2245 static void
2246 ps_log_pres_change(struct sysctrl_soft_state *softsp, int index, int present)
2247 {
2248 	char	*trans = present ? "Installed" : "Removed";
2249 
2250 	switch (index) {
2251 	/* the core power supplies (except for 7) */
2252 	case 0: case 1: case 2: case 3:
2253 	case 4: case 5: case 6:
2254 		cmn_err(CE_NOTE, "%s %d %s", ft_str_table[FT_CORE_PS], index,
2255 		    trans);
2256 		if (!present) {
2257 			clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2258 			sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2259 		}
2260 		break;
2261 
2262 	/* power supply 7 / pps 1 */
2263 	case 7:
2264 		if (IS4SLOT(softsp->nslots) || IS5SLOT(softsp->nslots)) {
2265 			cmn_err(CE_NOTE, "%s 1 %s", ft_str_table[FT_PPS],
2266 			    trans);
2267 			if (!present) {
2268 			clear_fault(1, FT_PPS, FT_SYSTEM);
2269 			}
2270 		} else {
2271 			cmn_err(CE_NOTE, "%s %d %s", ft_str_table[FT_CORE_PS],
2272 			    index, trans);
2273 			if (!present) {
2274 			clear_fault(7, FT_CORE_PS, FT_SYSTEM);
2275 			sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2276 			}
2277 		}
2278 		break;
2279 
2280 	/* the peripheral power supply 0 */
2281 	case SYS_PPS0_INDEX:
2282 		cmn_err(CE_NOTE, "%s 0 %s", ft_str_table[FT_PPS], trans);
2283 		if (!present) {
2284 			clear_fault(0, FT_PPS, FT_SYSTEM);
2285 			sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2286 		}
2287 		break;
2288 
2289 	/* the peripheral rack fan assy */
2290 	case SYS_P_FAN_INDEX:
2291 		cmn_err(CE_NOTE, "%s %s", ft_str_table[FT_PPS_FAN], trans);
2292 		if (!present) {
2293 			clear_fault(0, FT_PPS_FAN, FT_SYSTEM);
2294 		}
2295 		break;
2296 
2297 	/* we don't mention a change of presence state for any other power */
2298 	}
2299 }
2300 
2301 /*
2302  * log the change of power supply status
2303  */
2304 static void
2305 ps_log_state_change(struct sysctrl_soft_state *softsp, int index, int ps_ok)
2306 {
2307 	int level = ps_ok ? CE_NOTE : CE_WARN;
2308 	char *s = ps_ok ? "OK" : "Failing";
2309 
2310 	switch (index) {
2311 	/* the core power supplies (except 7) */
2312 	case 0: case 1: case 2: case 3:
2313 	case 4: case 5: case 6:
2314 		cmn_err(level, "%s %d %s", ft_str_table[FT_CORE_PS], index, s);
2315 		if (ps_ok) {
2316 			clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2317 		} else {
2318 			reg_fault(index, FT_CORE_PS, FT_SYSTEM);
2319 		}
2320 		break;
2321 
2322 	/* power supply 7 / pps 1 */
2323 	case 7:
2324 		if (IS4SLOT(softsp->nslots) || IS5SLOT(softsp->nslots)) {
2325 			cmn_err(level, "%s 1 %s", ft_str_table[FT_PPS], s);
2326 			if (ps_ok) {
2327 				clear_fault(1, FT_PPS, FT_SYSTEM);
2328 			} else {
2329 				reg_fault(1, FT_PPS, FT_SYSTEM);
2330 			}
2331 		} else {
2332 			cmn_err(level, "%s %d %s", ft_str_table[FT_CORE_PS],
2333 			    index, s);
2334 			if (ps_ok) {
2335 				clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2336 			} else {
2337 				reg_fault(index, FT_CORE_PS, FT_SYSTEM);
2338 			}
2339 		}
2340 		break;
2341 
2342 	/* the peripheral power supply */
2343 	case SYS_PPS0_INDEX:
2344 		cmn_err(level, "%s %s", ft_str_table[FT_PPS], s);
2345 		if (ps_ok) {
2346 			clear_fault(0, FT_PPS, FT_SYSTEM);
2347 		} else {
2348 			reg_fault(0, FT_PPS, FT_SYSTEM);
2349 		}
2350 		break;
2351 
2352 	/* shared 3.3v clock power */
2353 	case SYS_CLK_33_INDEX:
2354 		cmn_err(level, "%s %s", ft_str_table[FT_CLK_33], s);
2355 		if (ps_ok) {
2356 			clear_fault(0, FT_CLK_33, FT_SYSTEM);
2357 		} else {
2358 			reg_fault(0, FT_CLK_33, FT_SYSTEM);
2359 		}
2360 		break;
2361 
2362 	/* shared 5.0v clock power */
2363 	case SYS_CLK_50_INDEX:
2364 		cmn_err(level, "%s %s", ft_str_table[FT_CLK_50], s);
2365 		if (ps_ok) {
2366 			clear_fault(0, FT_CLK_50, FT_SYSTEM);
2367 		} else {
2368 			reg_fault(0, FT_CLK_50, FT_SYSTEM);
2369 		}
2370 		break;
2371 
2372 	/* peripheral 5v */
2373 	case SYS_V5_P_INDEX:
2374 		cmn_err(level, "%s %s", ft_str_table[FT_V5_P], s);
2375 		if (ps_ok) {
2376 			clear_fault(0, FT_V5_P, FT_SYSTEM);
2377 		} else {
2378 			reg_fault(0, FT_V5_P, FT_SYSTEM);
2379 		}
2380 		break;
2381 
2382 	/* peripheral 12v */
2383 	case SYS_V12_P_INDEX:
2384 		cmn_err(level, "%s %s", ft_str_table[FT_V12_P], s);
2385 		if (ps_ok) {
2386 			clear_fault(0, FT_V12_P, FT_SYSTEM);
2387 		} else {
2388 			reg_fault(0, FT_V12_P, FT_SYSTEM);
2389 		}
2390 		break;
2391 
2392 	/* aux 5v */
2393 	case SYS_V5_AUX_INDEX:
2394 		cmn_err(level, "%s %s", ft_str_table[FT_V5_AUX], s);
2395 		if (ps_ok) {
2396 			clear_fault(0, FT_V5_AUX, FT_SYSTEM);
2397 		} else {
2398 			reg_fault(0, FT_V5_AUX, FT_SYSTEM);
2399 		}
2400 		break;
2401 
2402 	/* peripheral 5v precharge */
2403 	case SYS_V5_P_PCH_INDEX:
2404 		cmn_err(level, "%s %s", ft_str_table[FT_V5_P_PCH], s);
2405 		if (ps_ok) {
2406 			clear_fault(0, FT_V5_P_PCH, FT_SYSTEM);
2407 		} else {
2408 			reg_fault(0, FT_V5_P_PCH, FT_SYSTEM);
2409 		}
2410 		break;
2411 
2412 	/* peripheral 12v precharge */
2413 	case SYS_V12_P_PCH_INDEX:
2414 		cmn_err(level, "%s %s", ft_str_table[FT_V12_P_PCH], s);
2415 		if (ps_ok) {
2416 			clear_fault(0, FT_V12_P_PCH, FT_SYSTEM);
2417 		} else {
2418 			reg_fault(0, FT_V12_P_PCH, FT_SYSTEM);
2419 		}
2420 		break;
2421 
2422 	/* 3.3v precharge */
2423 	case SYS_V3_PCH_INDEX:
2424 		cmn_err(level, "%s %s", ft_str_table[FT_V3_PCH], s);
2425 		if (ps_ok) {
2426 			clear_fault(0, FT_V3_PCH, FT_SYSTEM);
2427 		} else {
2428 			reg_fault(0, FT_V3_PCH, FT_SYSTEM);
2429 		}
2430 		break;
2431 
2432 	/* 5v precharge */
2433 	case SYS_V5_PCH_INDEX:
2434 		cmn_err(level, "%s %s", ft_str_table[FT_V5_PCH], s);
2435 		if (ps_ok) {
2436 			clear_fault(0, FT_V5_PCH, FT_SYSTEM);
2437 		} else {
2438 			reg_fault(0, FT_V5_PCH, FT_SYSTEM);
2439 		}
2440 		break;
2441 
2442 	/* peripheral power supply fans */
2443 	case SYS_P_FAN_INDEX:
2444 		cmn_err(level, "%s %s", ft_str_table[FT_PPS_FAN], s);
2445 		if (ps_ok) {
2446 			clear_fault(0, FT_PPS_FAN, FT_SYSTEM);
2447 		} else {
2448 			reg_fault(0, FT_PPS_FAN, FT_SYSTEM);
2449 		}
2450 		break;
2451 	}
2452 }
2453 
2454 /*
2455  * The timeout from ps_fail_handler() that simply re-triggers a check
2456  * of the ps condition.
2457  */
2458 static void
2459 ps_fail_retry(void *arg)
2460 {
2461 	struct sysctrl_soft_state *softsp = arg;
2462 
2463 	ASSERT(softsp);
2464 
2465 	ddi_trigger_softintr(softsp->ps_fail_poll_id);
2466 }
2467 
2468 /*
2469  * pps_fanfail_handler
2470  *
2471  * This routine is called from the high level handler.
2472  */
2473 static uint_t
2474 pps_fanfail_handler(caddr_t arg)
2475 {
2476 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2477 
2478 	ASSERT(softsp);
2479 
2480 	/* always check again in a bit by re-enabling the fan interrupt */
2481 	(void) timeout(pps_fanfail_retry, softsp, pps_fan_timeout_hz);
2482 
2483 	return (DDI_INTR_CLAIMED);
2484 }
2485 
2486 /*
2487  * After a bit of waiting, we simply re-enable the interrupt to
2488  * see if we get another one.  The softintr triggered routine does
2489  * the dirty work for us since it runs in the interrupt context.
2490  */
2491 static void
2492 pps_fanfail_retry(void *arg)
2493 {
2494 	struct sysctrl_soft_state *softsp = arg;
2495 
2496 	ASSERT(softsp);
2497 
2498 	ddi_trigger_softintr(softsp->pps_fan_high_id);
2499 }
2500 
2501 /*
2502  * The other half of the retry handler run from the interrupt context
2503  */
2504 static uint_t
2505 pps_fanfail_reenable(caddr_t arg)
2506 {
2507 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2508 	uchar_t tmp_reg;
2509 
2510 	ASSERT(softsp);
2511 
2512 	mutex_enter(&softsp->csr_mutex);
2513 
2514 	/*
2515 	 * re-initialize the bit field for all pps fans to assumed good.
2516 	 * If the fans are still bad, we're going to get an immediate system
2517 	 * interrupt which will put the correct state back anyway.
2518 	 *
2519 	 * NOTE: the polling routines that use this state understand the
2520 	 * pulse resulting from above...
2521 	 */
2522 	softsp->pps_fan_saved = SYS_AC_FAN_OK | SYS_KEYSW_FAN_OK;
2523 
2524 	*(softsp->csr) |= SYS_PPS_FAN_FAIL_EN;
2525 	tmp_reg = *(softsp->csr);
2526 #ifdef lint
2527 	tmp_reg = tmp_reg;
2528 #endif
2529 	mutex_exit(&softsp->csr_mutex);
2530 
2531 	return (DDI_INTR_CLAIMED);
2532 }
2533 
2534 /*
2535  *
2536  * Poll the hardware shadow state to determine the pps fan status.
2537  * The shadow state is maintained by the system_high handler and its
2538  * associated pps_* functions (above).
2539  *
2540  * There is a short time interval where the shadow state is pulsed to
2541  * the OK state even when the fans are bad.  However, this polling
2542  * routine has some built in hysteresis to filter out those _normal_
2543  * events.
2544  */
2545 static void
2546 pps_fan_poll(void *arg)
2547 {
2548 	struct sysctrl_soft_state *softsp = arg;
2549 	int i;
2550 
2551 	ASSERT(softsp);
2552 
2553 	for (i = 0; i < SYS_PPS_FAN_COUNT; i++) {
2554 		int fanfail = FALSE;
2555 
2556 		/* determine fan status */
2557 		switch (i) {
2558 		case RACK:
2559 			fanfail = softsp->pps_fan_saved & SYS_RACK_FANFAIL;
2560 			break;
2561 
2562 		case AC:
2563 			/*
2564 			 * Don't bother polling the AC fan on 4 and 5 slot
2565 			 * systems.
2566 			 * Rather, it is handled by the power supply loop.
2567 			 */
2568 			fanfail = !(IS4SLOT(softsp->nslots) ||
2569 			    IS5SLOT(softsp->nslots)) &&
2570 			    !(softsp->pps_fan_saved & SYS_AC_FAN_OK);
2571 			break;
2572 
2573 		case KEYSW:
2574 			/*
2575 			 * This signal is not usable if aux5v is missing
2576 			 * so we will synthesize a failed fan when aux5v
2577 			 * fails or when pps0 is out.
2578 			 * The 4 and 5 slot systems behave the same.
2579 			 */
2580 			fanfail = (!(IS4SLOT(softsp->nslots) ||
2581 			    IS5SLOT(softsp->nslots)) &&
2582 			    (softsp->ps_stats[SYS_V5_AUX_INDEX].dcshadow !=
2583 			    PS_OK)) ||
2584 			    !(softsp->pps_fan_saved & SYS_KEYSW_FAN_OK);
2585 			break;
2586 
2587 		}
2588 
2589 		/* is the fan bad? */
2590 		if (fanfail) {
2591 
2592 			/* is this condition different than we know? */
2593 			if (softsp->pps_fan_state_count[i] == 0) {
2594 
2595 				/* log the change to failed */
2596 				pps_fan_state_change(softsp, i, FALSE);
2597 			}
2598 
2599 			/* always restart the fan OK counter */
2600 			softsp->pps_fan_state_count[i] = PPS_FROM_FAIL_TICKS;
2601 		} else {
2602 
2603 			/* do we currently know the fan is bad? */
2604 			if (softsp->pps_fan_state_count[i]) {
2605 
2606 				/* yes, but has it been stable? */
2607 				if (--softsp->pps_fan_state_count[i] == 0) {
2608 
2609 					/* log the change to OK */
2610 					pps_fan_state_change(softsp, i, TRUE);
2611 				}
2612 			}
2613 		}
2614 	}
2615 
2616 	/* always check again in a bit by re-enabling the fan interrupt */
2617 	(void) timeout(pps_fan_poll, softsp, pps_fan_timeout_hz);
2618 }
2619 
2620 /*
2621  * pps_fan_state_change()
2622  *
2623  * Log the changed fan condition and update the external status.
2624  */
2625 static void
2626 pps_fan_state_change(struct sysctrl_soft_state *softsp, int index, int fan_ok)
2627 {
2628 	char *fan_type;
2629 	char *state = fan_ok ? "fans OK" : "fan failure detected";
2630 
2631 	switch (index) {
2632 	case RACK:
2633 		/* 4 and 5 slot systems behave the same */
2634 		fan_type = (IS4SLOT(softsp->nslots) ||
2635 		    IS5SLOT(softsp->nslots)) ?
2636 		    "Disk Drive" : "Rack Exhaust";
2637 		if (fan_ok) {
2638 			softsp->pps_fan_external_state &= ~SYS_RACK_FANFAIL;
2639 			clear_fault(0, (IS4SLOT(softsp->nslots) ||
2640 			    IS5SLOT(softsp->nslots)) ? FT_DSK_FAN :
2641 			    FT_RACK_EXH, FT_SYSTEM);
2642 		} else {
2643 			softsp->pps_fan_external_state |= SYS_RACK_FANFAIL;
2644 			reg_fault(0, (IS4SLOT(softsp->nslots) ||
2645 			    IS5SLOT(softsp->nslots)) ? FT_DSK_FAN :
2646 			    FT_RACK_EXH, FT_SYSTEM);
2647 		}
2648 		break;
2649 
2650 	case AC:
2651 		fan_type = "AC Box";
2652 		if (fan_ok) {
2653 			softsp->pps_fan_external_state |= SYS_AC_FAN_OK;
2654 			clear_fault(0, FT_AC_FAN, FT_SYSTEM);
2655 		} else {
2656 			softsp->pps_fan_external_state &= ~SYS_AC_FAN_OK;
2657 			reg_fault(0, FT_AC_FAN, FT_SYSTEM);
2658 		}
2659 		break;
2660 
2661 	case KEYSW:
2662 		fan_type = "Keyswitch";
2663 		if (fan_ok) {
2664 			softsp->pps_fan_external_state |= SYS_KEYSW_FAN_OK;
2665 			clear_fault(0, FT_KEYSW_FAN, FT_SYSTEM);
2666 		} else {
2667 			softsp->pps_fan_external_state &= ~SYS_KEYSW_FAN_OK;
2668 			reg_fault(0, FT_KEYSW_FAN, FT_SYSTEM);
2669 		}
2670 		break;
2671 	default:
2672 		fan_type = "[invalid fan id]";
2673 		break;
2674 	}
2675 
2676 	/* now log the state change */
2677 	cmn_err(fan_ok ? CE_NOTE : CE_WARN, "%s %s", fan_type, state);
2678 }
2679 
2680 static uint_t
2681 bd_insert_handler(caddr_t arg)
2682 {
2683 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2684 
2685 	ASSERT(softsp);
2686 
2687 	DPRINTF(SYSCTRL_ATTACH_DEBUG, ("bd_insert_handler()"));
2688 
2689 	(void) timeout(bd_insert_timeout, softsp, bd_insert_delay_hz);
2690 
2691 	return (DDI_INTR_CLAIMED);
2692 }
2693 
2694 void
2695 bd_remove_poll(struct sysctrl_soft_state *softsp)
2696 {
2697 	ASSERT(fhc_bdlist_locked());
2698 
2699 	if (!bd_remove_to_id) {
2700 		bd_remove_to_id = timeout(bd_remove_timeout, softsp,
2701 		    bd_remove_timeout_hz);
2702 	} else {
2703 		DPRINTF(SYSCTRL_ATTACH_DEBUG,
2704 		    ("bd_remove_poll ignoring start request"));
2705 	}
2706 }
2707 
2708 /*
2709  * bd_insert_timeout()
2710  *
2711  * This routine handles the board insert interrupt. It is called from a
2712  * timeout so that it does not run at interrupt level. The main job
2713  * of this routine is to find hotplugged boards and de-assert the
2714  * board insert interrupt coming from the board. For hotplug phase I,
2715  * the routine also powers down the board.
2716  * JTAG scan is used to find boards which have been inserted.
2717  * All other control of the boards is also done by JTAG scan.
2718  */
2719 static void
2720 bd_insert_timeout(void *arg)
2721 {
2722 	struct sysctrl_soft_state *softsp = arg;
2723 	int found;
2724 
2725 	ASSERT(softsp);
2726 
2727 	if (sysctrl_hotplug_disabled) {
2728 		sysc_policy_update(softsp, NULL, SYSC_EVT_BD_HP_DISABLED);
2729 	} else {
2730 		/*
2731 		 * Lock the board list mutex. Keep it locked until all work
2732 		 * is done.
2733 		 */
2734 		(void) fhc_bdlist_lock(-1);
2735 
2736 		found = fhc_bd_insert_scan();
2737 
2738 		if (found) {
2739 			DPRINTF(SYSCTRL_ATTACH_DEBUG,
2740 			    ("bd_insert_timeout starting bd_remove_poll()"));
2741 			bd_remove_poll(softsp);
2742 		}
2743 
2744 		fhc_bdlist_unlock();
2745 	}
2746 
2747 	/*
2748 	 * Enable interrupts.
2749 	 */
2750 	ddi_trigger_softintr(softsp->sbrd_gone_id);
2751 }
2752 
2753 static void
2754 bd_remove_timeout(void *arg)
2755 {
2756 	struct sysctrl_soft_state *softsp = arg;
2757 	int keep_polling;
2758 
2759 	ASSERT(softsp);
2760 
2761 	/*
2762 	 * Lock the board list mutex. Keep it locked until all work
2763 	 * is done.
2764 	 */
2765 	(void) fhc_bdlist_lock(-1);
2766 
2767 	bd_remove_to_id = 0;	/* delete our timeout ID */
2768 
2769 	keep_polling = fhc_bd_remove_scan();
2770 
2771 	if (keep_polling) {
2772 		bd_remove_poll(softsp);
2773 	} else {
2774 		DPRINTF(SYSCTRL_ATTACH_DEBUG, ("exiting bd_remove_poll."));
2775 	}
2776 
2777 	fhc_bdlist_unlock();
2778 }
2779 
2780 static uint_t
2781 bd_insert_normal(caddr_t arg)
2782 {
2783 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2784 	uchar_t tmp_reg;
2785 
2786 	ASSERT(softsp);
2787 
2788 	/* has the condition been removed? */
2789 	/* XXX add deglitch state machine here */
2790 	if (!(*(softsp->status1) & SYS_NOT_BRD_PRES)) {
2791 		/* check again in a few */
2792 		(void) timeout(bd_insert_timeout, softsp, bd_insert_retry_hz);
2793 	} else {
2794 		/* Turn on the enable bit for this interrupt */
2795 		mutex_enter(&softsp->csr_mutex);
2796 		*(softsp->csr) |= SYS_SBRD_PRES_EN;
2797 		/* flush the hardware store buffer */
2798 		tmp_reg = *(softsp->csr);
2799 #ifdef lint
2800 		tmp_reg = tmp_reg;
2801 #endif
2802 		mutex_exit(&softsp->csr_mutex);
2803 	}
2804 
2805 	return (DDI_INTR_CLAIMED);
2806 }
2807 
2808 /*
2809  * blink LED handler.
2810  *
2811  * The actual bit manipulation needs to occur at interrupt level
2812  * because we need access to the CSR with its CSR mutex
2813  */
2814 static uint_t
2815 blink_led_handler(caddr_t arg)
2816 {
2817 	struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2818 	uchar_t tmp_reg;
2819 
2820 	ASSERT(softsp);
2821 
2822 	mutex_enter(&softsp->csr_mutex);
2823 
2824 	/*
2825 	 * XXX - The lock for the sys_led is not held here. If more
2826 	 * complicated tasks are done with the System LED, then
2827 	 * locking should be done here.
2828 	 */
2829 
2830 	/* read the hardware register. */
2831 	tmp_reg = *(softsp->csr);
2832 
2833 	/* Only turn on the OS System LED bit if the softsp state is on. */
2834 	if (softsp->sys_led) {
2835 		tmp_reg |= SYS_LED_RIGHT;
2836 	} else {
2837 		tmp_reg &= ~SYS_LED_RIGHT;
2838 	}
2839 
2840 	/* Turn on the yellow LED if system fault status is set. */
2841 	if (softsp->sys_fault) {
2842 		tmp_reg |= SYS_LED_MID;
2843 	} else {
2844 		tmp_reg &= ~SYS_LED_MID;
2845 	}
2846 
2847 	/* write to the hardware register */
2848 	*(softsp->csr) = tmp_reg;
2849 
2850 	/* flush the hardware store buffer */
2851 	tmp_reg = *(softsp->csr);
2852 #ifdef lint
2853 	tmp_reg = tmp_reg;
2854 #endif
2855 	mutex_exit(&softsp->csr_mutex);
2856 
2857 	(void) timeout(blink_led_timeout, softsp, blink_led_timeout_hz);
2858 
2859 	return (DDI_INTR_CLAIMED);
2860 }
2861 
2862 /*
2863  * simply re-trigger the interrupt handler on led timeout
2864  */
2865 static void
2866 blink_led_timeout(void *arg)
2867 {
2868 	struct sysctrl_soft_state *softsp = arg;
2869 	int led_state;
2870 
2871 	ASSERT(softsp);
2872 
2873 	/*
2874 	 * Process the system fault list here. This is where the driver
2875 	 * must decide what yellow LEDs to turn on if any. The fault
2876 	 * list is walked and each fhc_list entry is updated with it's
2877 	 * yellow LED status. This info is used later by the routine
2878 	 * toggle_board_green_leds().
2879 	 *
2880 	 * The variable system_fault is non-zero if any non-
2881 	 * suppressed faults are found in the system.
2882 	 */
2883 	softsp->sys_fault = process_fault_list();
2884 
2885 	/* blink the system board OS LED */
2886 	mutex_enter(&softsp->sys_led_lock);
2887 	softsp->sys_led = !softsp->sys_led;
2888 	led_state = softsp->sys_led;
2889 	mutex_exit(&softsp->sys_led_lock);
2890 
2891 	toggle_board_green_leds(led_state);
2892 
2893 	ddi_trigger_softintr(softsp->blink_led_id);
2894 }
2895 
2896 void
2897 toggle_board_green_leds(int led_state)
2898 {
2899 	fhc_bd_t *list;
2900 
2901 	(void) fhc_bdlist_lock(-1);
2902 	for (list = fhc_bd_first(); list; list = fhc_bd_next(list)) {
2903 		uint_t value = 0;
2904 
2905 		if (list->sc.in_transition ||
2906 		    (list->sc.rstate != SYSC_CFGA_RSTATE_CONNECTED))
2907 			continue;
2908 
2909 		ASSERT(list->sc.type != CLOCK_BOARD);
2910 		ASSERT(list->sc.type != DISK_BOARD);
2911 		ASSERT(list->softsp);
2912 
2913 		if ((list->sc.ostate == SYSC_CFGA_OSTATE_CONFIGURED) &&
2914 		    led_state)
2915 			value |= FHC_LED_RIGHT;
2916 
2917 		if (list->fault)
2918 			value |= FHC_LED_MID;
2919 		else
2920 			value &= ~FHC_LED_MID;
2921 
2922 		update_board_leds(list, FHC_LED_RIGHT|FHC_LED_MID, value);
2923 	}
2924 	fhc_bdlist_unlock();
2925 }
2926 
2927 /*
2928  * timestamp an AC power failure in nvram
2929  */
2930 static void
2931 nvram_update_powerfail(struct sysctrl_soft_state *softsp)
2932 {
2933 	char buf[80];
2934 	int len = 0;
2935 
2936 	numtos(gethrestime_sec(), buf);
2937 
2938 	if (softsp->options_nodeid) {
2939 		len = prom_setprop(softsp->options_nodeid, "powerfail-time",
2940 		    buf, strlen(buf)+1);
2941 	}
2942 
2943 	if (len <= 0) {
2944 		cmn_err(CE_WARN, "sysctrl%d: failed to set powerfail-time "
2945 		    "to %s\n", ddi_get_instance(softsp->dip), buf);
2946 	}
2947 }
2948 
2949 void
2950 sysctrl_add_kstats(struct sysctrl_soft_state *softsp)
2951 {
2952 	struct kstat	*ksp;		/* Generic sysctrl kstats */
2953 	struct kstat	*pksp;		/* Power Supply kstat */
2954 	struct kstat	*tksp;		/* Sysctrl temperatrure kstat */
2955 	struct kstat	*ttsp;		/* Sysctrl temperature test kstat */
2956 
2957 	if ((ksp = kstat_create("unix", ddi_get_instance(softsp->dip),
2958 	    SYSCTRL_KSTAT_NAME, "misc", KSTAT_TYPE_NAMED,
2959 	    sizeof (struct sysctrl_kstat) / sizeof (kstat_named_t),
2960 	    KSTAT_FLAG_PERSISTENT)) == NULL) {
2961 		cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
2962 		    ddi_get_instance(softsp->dip));
2963 	} else {
2964 		struct sysctrl_kstat *sysksp;
2965 
2966 		sysksp = (struct sysctrl_kstat *)(ksp->ks_data);
2967 
2968 		/* now init the named kstats */
2969 		kstat_named_init(&sysksp->csr, CSR_KSTAT_NAMED,
2970 		    KSTAT_DATA_CHAR);
2971 
2972 		kstat_named_init(&sysksp->status1, STAT1_KSTAT_NAMED,
2973 		    KSTAT_DATA_CHAR);
2974 
2975 		kstat_named_init(&sysksp->status2, STAT2_KSTAT_NAMED,
2976 		    KSTAT_DATA_CHAR);
2977 
2978 		kstat_named_init(&sysksp->clk_freq2, CLK_FREQ2_KSTAT_NAMED,
2979 		    KSTAT_DATA_CHAR);
2980 
2981 		kstat_named_init(&sysksp->fan_status, FAN_KSTAT_NAMED,
2982 		    KSTAT_DATA_CHAR);
2983 
2984 		kstat_named_init(&sysksp->key_status, KEY_KSTAT_NAMED,
2985 		    KSTAT_DATA_CHAR);
2986 
2987 		kstat_named_init(&sysksp->power_state, POWER_KSTAT_NAMED,
2988 		    KSTAT_DATA_INT32);
2989 
2990 		kstat_named_init(&sysksp->clk_ver, CLK_VER_KSTAT_NAME,
2991 		    KSTAT_DATA_CHAR);
2992 
2993 		ksp->ks_update = sysctrl_kstat_update;
2994 		ksp->ks_private = (void *)softsp;
2995 		kstat_install(ksp);
2996 	}
2997 
2998 	if ((tksp = kstat_create("unix", CLOCK_BOARD_INDEX,
2999 	    OVERTEMP_KSTAT_NAME, "misc", KSTAT_TYPE_RAW,
3000 	    sizeof (struct temp_stats), KSTAT_FLAG_PERSISTENT)) == NULL) {
3001 		cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
3002 			ddi_get_instance(softsp->dip));
3003 	} else {
3004 		tksp->ks_update = overtemp_kstat_update;
3005 		tksp->ks_private = (void *)&softsp->tempstat;
3006 		kstat_install(tksp);
3007 	}
3008 
3009 	if ((ttsp = kstat_create("unix", CLOCK_BOARD_INDEX,
3010 	    TEMP_OVERRIDE_KSTAT_NAME, "misc", KSTAT_TYPE_RAW, sizeof (short),
3011 	    KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) == NULL) {
3012 		cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
3013 		    ddi_get_instance(softsp->dip));
3014 	} else {
3015 		ttsp->ks_update = temp_override_kstat_update;
3016 		ttsp->ks_private = (void *)&softsp->tempstat.override;
3017 		kstat_install(ttsp);
3018 	}
3019 
3020 	if ((pksp = kstat_create("unix", ddi_get_instance(softsp->dip),
3021 	    PSSHAD_KSTAT_NAME, "misc", KSTAT_TYPE_RAW,
3022 	    SYS_PS_COUNT, KSTAT_FLAG_PERSISTENT)) == NULL) {
3023 		cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
3024 		    ddi_get_instance(softsp->dip));
3025 	} else {
3026 		pksp->ks_update = psstat_kstat_update;
3027 		pksp->ks_private = (void *)softsp;
3028 		kstat_install(pksp);
3029 	}
3030 }
3031 
3032 static int
3033 sysctrl_kstat_update(kstat_t *ksp, int rw)
3034 {
3035 	struct sysctrl_kstat *sysksp;
3036 	struct sysctrl_soft_state *softsp;
3037 
3038 	sysksp = (struct sysctrl_kstat *)(ksp->ks_data);
3039 	softsp = (struct sysctrl_soft_state *)(ksp->ks_private);
3040 
3041 	/* this is a read-only kstat. Exit on a write */
3042 
3043 	if (rw == KSTAT_WRITE) {
3044 		return (EACCES);
3045 	} else {
3046 		/*
3047 		 * copy the current state of the hardware into the
3048 		 * kstat structure.
3049 		 */
3050 		sysksp->csr.value.c[0] = *(softsp->csr);
3051 		sysksp->status1.value.c[0] = *(softsp->status1);
3052 		sysksp->status2.value.c[0] = *(softsp->status2);
3053 		sysksp->clk_freq2.value.c[0] = *(softsp->clk_freq2);
3054 
3055 		sysksp->fan_status.value.c[0] = softsp->pps_fan_external_state;
3056 		sysksp->key_status.value.c[0] = softsp->key_shadow;
3057 		sysksp->power_state.value.i32 = softsp->power_state;
3058 
3059 		/*
3060 		 * non-existence of the clock version register returns the
3061 		 * value 0xff when the hardware register location is read
3062 		 */
3063 		if (softsp->clk_ver != NULL)
3064 			sysksp->clk_ver.value.c[0] = *(softsp->clk_ver);
3065 		else
3066 			sysksp->clk_ver.value.c[0] = (char)0xff;
3067 	}
3068 	return (0);
3069 }
3070 
3071 static int
3072 psstat_kstat_update(kstat_t *ksp, int rw)
3073 {
3074 	struct sysctrl_soft_state *softsp;
3075 	uchar_t *ptr = (uchar_t *)(ksp->ks_data);
3076 	int ps;
3077 
3078 	softsp = (struct sysctrl_soft_state *)(ksp->ks_private);
3079 
3080 	if (rw == KSTAT_WRITE) {
3081 		return (EACCES);
3082 	} else {
3083 		for (ps = 0; ps < SYS_PS_COUNT; ps++) {
3084 			*ptr++ = softsp->ps_stats[ps].dcshadow;
3085 		}
3086 	}
3087 	return (0);
3088 }
3089 
3090 static void
3091 sysctrl_thread_wakeup(void *arg)
3092 {
3093 	int type = (int)(uintptr_t)arg;
3094 
3095 	/*
3096 	 * grab mutex to guarantee that our wakeup call
3097 	 * arrives after we go to sleep -- so we can't sleep forever.
3098 	 */
3099 	mutex_enter(&sslist_mutex);
3100 	switch (type) {
3101 	case OVERTEMP_POLL:
3102 		cv_signal(&overtemp_cv);
3103 		break;
3104 	case KEYSWITCH_POLL:
3105 		cv_signal(&keyswitch_cv);
3106 		break;
3107 	default:
3108 		cmn_err(CE_WARN, "sysctrl: invalid type %d to wakeup\n", type);
3109 		break;
3110 	}
3111 	mutex_exit(&sslist_mutex);
3112 }
3113 
3114 static void
3115 sysctrl_overtemp_poll(void)
3116 {
3117 	struct sysctrl_soft_state *list;
3118 	callb_cpr_t cprinfo;
3119 
3120 	CALLB_CPR_INIT(&cprinfo, &sslist_mutex, callb_generic_cpr, "overtemp");
3121 
3122 	/* The overtemp data structures are protected by a mutex. */
3123 	mutex_enter(&sslist_mutex);
3124 
3125 	while (sysctrl_do_overtemp_thread) {
3126 
3127 		for (list = sys_list; list != NULL; list = list->next) {
3128 			if (list->temp_reg != NULL) {
3129 				update_temp(list->pdip, &list->tempstat,
3130 				    *(list->temp_reg));
3131 			}
3132 		}
3133 
3134 		CALLB_CPR_SAFE_BEGIN(&cprinfo);
3135 
3136 		/* now have this thread sleep for a while */
3137 		(void) timeout(sysctrl_thread_wakeup, (void *)OVERTEMP_POLL,
3138 		    overtemp_timeout_hz);
3139 
3140 		cv_wait(&overtemp_cv, &sslist_mutex);
3141 
3142 		CALLB_CPR_SAFE_END(&cprinfo, &sslist_mutex);
3143 	}
3144 	CALLB_CPR_EXIT(&cprinfo);
3145 	thread_exit();
3146 	/* NOTREACHED */
3147 }
3148 
3149 static void
3150 sysctrl_keyswitch_poll(void)
3151 {
3152 	struct sysctrl_soft_state *list;
3153 	callb_cpr_t cprinfo;
3154 
3155 	CALLB_CPR_INIT(&cprinfo, &sslist_mutex, callb_generic_cpr, "keyswitch");
3156 
3157 	/* The keyswitch data strcutures are protected by a mutex. */
3158 	mutex_enter(&sslist_mutex);
3159 
3160 	while (sysctrl_do_keyswitch_thread) {
3161 
3162 		for (list = sys_list; list != NULL; list = list->next) {
3163 			if (list->status1 != NULL)
3164 				update_key_state(list);
3165 		}
3166 
3167 		CALLB_CPR_SAFE_BEGIN(&cprinfo);
3168 
3169 		/* now have this thread sleep for a while */
3170 		(void) timeout(sysctrl_thread_wakeup, (void *)KEYSWITCH_POLL,
3171 		    keyswitch_timeout_hz);
3172 
3173 		cv_wait(&keyswitch_cv, &sslist_mutex);
3174 
3175 		CALLB_CPR_SAFE_END(&cprinfo, &sslist_mutex);
3176 	}
3177 	CALLB_CPR_EXIT(&cprinfo);
3178 	thread_exit();
3179 	/* NOTREACHED */
3180 }
3181 
3182 /*
3183  * check the key switch position for state changes
3184  */
3185 static void
3186 update_key_state(struct sysctrl_soft_state *list)
3187 {
3188 	enum keyswitch_state key;
3189 
3190 	/*
3191 	 * snapshot current hardware key position
3192 	 */
3193 	if (*(list->status1) & SYS_NOT_SECURE)
3194 		key = KEY_NOT_SECURE;
3195 	else
3196 		key = KEY_SECURE;
3197 
3198 	/*
3199 	 * check for state transition
3200 	 */
3201 	if (key != list->key_shadow) {
3202 
3203 		/*
3204 		 * handle state transition
3205 		 */
3206 		switch (list->key_shadow) {
3207 		case KEY_BOOT:
3208 			cmn_err(CE_CONT, "?sysctrl%d: Key switch is%sin the "
3209 			    "secure position\n", ddi_get_instance(list->dip),
3210 			    (key == KEY_SECURE) ? " " : " not ");
3211 			list->key_shadow = key;
3212 			break;
3213 		case KEY_SECURE:
3214 		case KEY_NOT_SECURE:
3215 			cmn_err(CE_NOTE, "sysctrl%d: Key switch has changed"
3216 			    " to the %s position",
3217 			    ddi_get_instance(list->dip),
3218 			    (key == KEY_SECURE) ? "secure" : "not-secure");
3219 			list->key_shadow = key;
3220 			break;
3221 		default:
3222 			cmn_err(CE_CONT,
3223 			    "?sysctrl%d: Key switch is in an unknown position,"
3224 			    "treated as being in the %s position\n",
3225 			    ddi_get_instance(list->dip),
3226 			    (list->key_shadow == KEY_SECURE) ?
3227 			    "secure" : "not-secure");
3228 			break;
3229 		}
3230 	}
3231 }
3232 
3233 /*
3234  * consider key switch position when handling an abort sequence
3235  */
3236 static void
3237 sysctrl_abort_seq_handler(char *msg)
3238 {
3239 	struct sysctrl_soft_state *list;
3240 	uint_t secure = 0;
3241 	char buf[64], inst[4];
3242 
3243 
3244 	/*
3245 	 * if any of the key switch positions are secure,
3246 	 * then disallow entry to the prom/debugger
3247 	 */
3248 	mutex_enter(&sslist_mutex);
3249 	buf[0] = (char)0;
3250 	for (list = sys_list; list != NULL; list = list->next) {
3251 		if (!(*(list->status1) & SYS_NOT_SECURE)) {
3252 			if (secure++)
3253 				(void) strcat(buf, ",");
3254 			/*
3255 			 * XXX: later, replace instance number with nodeid
3256 			 */
3257 			(void) sprintf(inst, "%d", ddi_get_instance(list->dip));
3258 			(void) strcat(buf, inst);
3259 		}
3260 	}
3261 	mutex_exit(&sslist_mutex);
3262 
3263 	if (secure) {
3264 		cmn_err(CE_CONT,
3265 		    "!sysctrl(%s): ignoring debug enter sequence\n", buf);
3266 	} else {
3267 		cmn_err(CE_CONT, "!sysctrl: allowing debug enter\n");
3268 		debug_enter(msg);
3269 	}
3270 }
3271 
3272 #define	TABLE_END	0xFF
3273 
3274 struct uart_cmd {
3275 	uchar_t reg;
3276 	uchar_t data;
3277 };
3278 
3279 /*
3280  * Time constant defined by this formula:
3281  *	((4915200/32)/(baud) -2)
3282  */
3283 
3284 struct uart_cmd uart_table[] = {
3285 	{ 0x09, 0xc0 },	/* Force hardware reset */
3286 	{ 0x04, 0x46 },	/* X16 clock mode, 1 stop bit/char, no parity */
3287 	{ 0x03, 0xc0 },	/* Rx is 8 bits/char */
3288 	{ 0x05, 0xe2 },	/* DTR, Tx is 8 bits/char, RTS */
3289 	{ 0x09, 0x02 },	/* No vector returned on interrupt */
3290 	{ 0x0b, 0x55 },	/* Rx Clock = Tx Clock = BR generator = ~TRxC OUT */
3291 	{ 0x0c, 0x0e },	/* Time Constant = 0x000e for 9600 baud */
3292 	{ 0x0d, 0x00 },	/* High byte of time constant */
3293 	{ 0x0e, 0x02 },	/* BR generator comes from Z-SCC's PCLK input */
3294 	{ 0x03, 0xc1 },	/* Rx is 8 bits/char, Rx is enabled */
3295 	{ 0x05, 0xea },	/* DTR, Tx is 8 bits/char, Tx is enabled, RTS */
3296 	{ 0x0e, 0x03 },	/* BR comes from PCLK, BR generator is enabled */
3297 	{ 0x00, 0x30 },	/* Error reset */
3298 	{ 0x00, 0x30 },	/* Error reset */
3299 	{ 0x00, 0x10 },	/* external status reset */
3300 	{ 0x03, 0xc1 },	/* Rx is 8 bits/char, Rx is enabled */
3301 	{ TABLE_END, 0x0 }
3302 };
3303 
3304 static void
3305 init_remote_console_uart(struct sysctrl_soft_state *softsp)
3306 {
3307 	int i = 0;
3308 
3309 	/*
3310 	 * Serial chip expects software to write to the control
3311 	 * register first with the desired register number. Then
3312 	 * write to the control register with the desired data.
3313 	 * So walk thru table writing the register/data pairs to
3314 	 * the serial port chip.
3315 	 */
3316 	while (uart_table[i].reg != TABLE_END) {
3317 		*(softsp->rcons_ctl) = uart_table[i].reg;
3318 		*(softsp->rcons_ctl) = uart_table[i].data;
3319 		i++;
3320 	}
3321 }
3322 
3323 /*
3324  * return the slot information of the system
3325  *
3326  * function take a sysctrl_soft_state, so it's ready for sunfire+
3327  * change which requires 2 registers to decide the system type.
3328  */
3329 static void
3330 sysc_slot_info(int nslots, int *start, int *limit, int *incr)
3331 {
3332 	switch (nslots) {
3333 	case 8:
3334 		*start = 0;
3335 		*limit = 8;
3336 		*incr = 1;
3337 		break;
3338 	case 5:
3339 		*start = 1;
3340 		*limit = 10;
3341 		*incr = 2;
3342 		break;
3343 	case 4:
3344 		*start = 1;
3345 		*limit = 8;
3346 		*incr = 2;
3347 		break;
3348 	case 0:
3349 	case 16:
3350 	default:
3351 		*start = 0;
3352 		*limit = 16;
3353 		*incr = 1;
3354 		break;
3355 	}
3356 }
3357 
3358 /*
3359  * reinitialize the Remote Console on the clock board
3360  *
3361  * with V5_AUX power outage the Remote Console ends up in
3362  * unknown state and has to be reinitilized if it was enabled
3363  * initially.
3364  */
3365 static void
3366 rcons_reinit(struct sysctrl_soft_state *softsp)
3367 {
3368 	uchar_t tmp_reg;
3369 
3370 	if (!(softsp->rcons_ctl))
3371 		/*
3372 		 * There is no OBP register set for the remote console UART,
3373 		 * so offset from the last register set, the misc register
3374 		 * set, in order to map in the remote console UART.
3375 		 */
3376 		if (ddi_map_regs(softsp->dip, 1, (caddr_t *)&softsp->rcons_ctl,
3377 		    RMT_CONS_OFFSET, RMT_CONS_LEN)) {
3378 			cmn_err(CE_WARN, "Unable to reinitialize "
3379 			    "remote console.");
3380 			return;
3381 		}
3382 
3383 
3384 	/* Disable the remote console reset control bits. */
3385 	*(softsp->clk_freq2) &= ~RCONS_UART_EN;
3386 
3387 	/* flush the hardware buffers */
3388 	tmp_reg = *(softsp->csr);
3389 
3390 	/*
3391 	 * Program the UART to watch ttya console.
3392 	 */
3393 	init_remote_console_uart(softsp);
3394 
3395 	/* Now enable the remote console reset control bits. */
3396 	*(softsp->clk_freq2) |= RCONS_UART_EN;
3397 
3398 	/* flush the hardware buffers */
3399 	tmp_reg = *(softsp->csr);
3400 
3401 	/* print some info for user to watch */
3402 	cmn_err(CE_NOTE, "Remote console reinitialized");
3403 #ifdef lint
3404 	tmp_reg = tmp_reg;
3405 #endif
3406 }
3407