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