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