1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
26 */
27
28 /*
29 * Copyright 2023 Oxide Computer Company
30 */
31
32
33 #include <sys/types.h>
34 #include <sys/conf.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 #include <sys/ddi_impldefs.h>
38 #include <sys/sunndi.h>
39 #include <sys/ndi_impldefs.h>
40 #include <sys/obpdefs.h>
41 #include <sys/cmn_err.h>
42 #include <sys/errno.h>
43 #include <sys/kmem.h>
44 #include <sys/debug.h>
45 #include <sys/sysmacros.h>
46 #include <sys/ivintr.h>
47 #include <sys/autoconf.h>
48 #include <sys/intreg.h>
49 #include <sys/proc.h>
50 #include <sys/modctl.h>
51 #include <sys/callb.h>
52 #include <sys/file.h>
53 #include <sys/open.h>
54 #include <sys/stat.h>
55 #include <sys/fhc.h>
56 #include <sys/sysctrl.h>
57 #include <sys/jtag.h>
58 #include <sys/ac.h>
59 #include <sys/simmstat.h>
60 #include <sys/clock.h>
61 #include <sys/promif.h>
62 #include <sys/promimpl.h>
63 #include <sys/sunndi.h>
64 #include <sys/machsystm.h>
65
66 /* Useful debugging Stuff */
67 #ifdef DEBUG
68 int sysc_debug_info = 1;
69 int sysc_debug_print_level = 0;
70 #endif
71
72 /*
73 * Function prototypes
74 */
75 static int sysctrl_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
76 void **result);
77
78 static int sysctrl_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
79
80 static int sysctrl_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
81
82 static int sysctrl_open(dev_t *, int, int, cred_t *);
83
84 static int sysctrl_close(dev_t, int, int, cred_t *);
85
86 static int sysctrl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
87
88 static uint_t system_high_handler(caddr_t arg);
89
90 static uint_t spur_delay(caddr_t arg);
91
92 static void spur_retry(void *);
93
94 static uint_t spur_reenable(caddr_t arg);
95
96 static void spur_long_timeout(void *);
97
98 static uint_t spur_clear_count(caddr_t arg);
99
100 static uint_t ac_fail_handler(caddr_t arg);
101
102 static void ac_fail_retry(void *);
103
104 static uint_t ac_fail_reenable(caddr_t arg);
105
106 static uint_t ps_fail_int_handler(caddr_t arg);
107
108 static uint_t ps_fail_poll_handler(caddr_t arg);
109
110 static uint_t ps_fail_handler(struct sysctrl_soft_state *softsp, int fromint);
111
112 enum power_state compute_power_state(struct sysctrl_soft_state *softsp,
113 int plus_load);
114
115 static void ps_log_state_change(struct sysctrl_soft_state *softsp,
116 int index, int present);
117
118 static void ps_log_pres_change(struct sysctrl_soft_state *softsp,
119 int index, int present);
120
121 static void ps_fail_retry(void *);
122
123 static uint_t pps_fanfail_handler(caddr_t arg);
124
125 static void pps_fanfail_retry(void *);
126
127 static uint_t pps_fanfail_reenable(caddr_t arg);
128
129 static void pps_fan_poll(void *);
130
131 static void pps_fan_state_change(struct sysctrl_soft_state *softsp,
132 int index, int fan_ok);
133
134 static uint_t bd_insert_handler(caddr_t arg);
135
136 static void bd_insert_timeout(void *);
137
138 static void bd_remove_timeout(void *);
139
140 static uint_t bd_insert_normal(caddr_t arg);
141
142 static void sysctrl_add_kstats(struct sysctrl_soft_state *softsp);
143
144 static int sysctrl_kstat_update(kstat_t *ksp, int rw);
145
146 static int psstat_kstat_update(kstat_t *, int);
147
148 static void init_remote_console_uart(struct sysctrl_soft_state *);
149
150 static void blink_led_timeout(void *);
151
152 static uint_t blink_led_handler(caddr_t arg);
153
154 static void sysctrl_thread_wakeup(void *type);
155
156 static void sysctrl_overtemp_poll(void);
157
158 static void sysctrl_keyswitch_poll(void);
159
160 static void update_key_state(struct sysctrl_soft_state *);
161
162 static void sysctrl_abort_seq_handler(char *msg);
163
164 static void nvram_update_powerfail(struct sysctrl_soft_state *softsp);
165
166 static void toggle_board_green_leds(int);
167
168 void bd_remove_poll(struct sysctrl_soft_state *);
169
170 static void sysc_slot_info(int nslots, int *start, int *limit, int *incr);
171
172 extern void sysc_board_connect_supported_init(void);
173
174 static void rcons_reinit(struct sysctrl_soft_state *softsp);
175
176 /*
177 * Configuration data structures
178 */
179 static struct cb_ops sysctrl_cb_ops = {
180 sysctrl_open, /* open */
181 sysctrl_close, /* close */
182 nulldev, /* strategy */
183 nulldev, /* print */
184 nulldev, /* dump */
185 nulldev, /* read */
186 nulldev, /* write */
187 sysctrl_ioctl, /* ioctl */
188 nodev, /* devmap */
189 nodev, /* mmap */
190 nodev, /* segmap */
191 nochpoll, /* poll */
192 ddi_prop_op, /* cb_prop_op */
193 0, /* streamtab */
194 D_MP|D_NEW, /* Driver compatibility flag */
195 CB_REV, /* rev */
196 nodev, /* cb_aread */
197 nodev /* cb_awrite */
198 };
199
200 static struct dev_ops sysctrl_ops = {
201 DEVO_REV, /* devo_rev */
202 0, /* refcnt */
203 sysctrl_info, /* getinfo */
204 nulldev, /* identify */
205 nulldev, /* probe */
206 sysctrl_attach, /* attach */
207 sysctrl_detach, /* detach */
208 nulldev, /* reset */
209 &sysctrl_cb_ops, /* cb_ops */
210 (struct bus_ops *)0, /* bus_ops */
211 nulldev, /* power */
212 ddi_quiesce_not_supported, /* devo_quiesce */
213 };
214
215 void *sysctrlp; /* sysctrl soft state hook */
216
217 /* # of ticks to silence spurious interrupts */
218 static clock_t spur_timeout_hz;
219
220 /* # of ticks to count spurious interrupts to print message */
221 static clock_t spur_long_timeout_hz;
222
223 /* # of ticks between AC failure polling */
224 static clock_t ac_timeout_hz;
225
226 /* # of ticks between Power Supply Failure polling */
227 static clock_t ps_fail_timeout_hz;
228
229 /*
230 * # of ticks between Peripheral Power Supply failure polling
231 * (used both for interrupt retry timeout and polling function)
232 */
233 static clock_t pps_fan_timeout_hz;
234
235 /* # of ticks delay after board insert interrupt */
236 static clock_t bd_insert_delay_hz;
237
238 /* # of secs to wait before restarting poll if we cannot clear interrupts */
239 static clock_t bd_insert_retry_hz;
240
241 /* # of secs between Board Removal polling */
242 static clock_t bd_remove_timeout_hz;
243
244 /* # of secs between toggle of OS LED */
245 static clock_t blink_led_timeout_hz;
246
247 /* overtemp polling routine timeout delay */
248 static clock_t overtemp_timeout_hz;
249
250 /* key switch polling routine timeout delay */
251 static clock_t keyswitch_timeout_hz;
252
253 /* Specify which system interrupt condition to monitor */
254 int enable_sys_interrupt = SYS_AC_PWR_FAIL_EN | SYS_PPS_FAN_FAIL_EN |
255 SYS_PS_FAIL_EN | SYS_SBRD_PRES_EN;
256
257 /* Should the overtemp_poll thread be running? */
258 static int sysctrl_do_overtemp_thread = 1;
259
260 /* Should the keyswitch_poll thread be running? */
261 static int sysctrl_do_keyswitch_thread = 1;
262
263 /*
264 * This timeout ID is for board remove polling routine. It is
265 * protected by the fhc_bdlist mutex.
266 * XXX - This will not work for wildfire. A different scheme must be
267 * used since there will be multiple sysctrl nodes, each with its
268 * own list of hotplugged boards to scan.
269 */
270 static timeout_id_t bd_remove_to_id = 0;
271
272 /*
273 * If this is set, the system will not shutdown when insufficient power
274 * condition persists.
275 */
276 int disable_insufficient_power_reboot = 0;
277
278 /*
279 * Set this to enable suspend/resume
280 */
281 int sysctrl_enable_detach_suspend = 0;
282
283 /*
284 * Set this to reflect the OBP initialized HOTPLUG_DISABLED_PROPERTY and
285 * during dynamic detection
286 */
287 int sysctrl_hotplug_disabled = FALSE;
288
289 /* Indicates whether or not the overtemp thread has been started */
290 static int sysctrl_overtemp_thread_started = 0;
291
292 /* Indicates whether or not the key switch thread has been started */
293 static int sysctrl_keyswitch_thread_started = 0;
294
295 /* *Mutex used to protect the soft state list */
296 static kmutex_t sslist_mutex;
297
298 /* The CV is used to wakeup the overtemp thread when needed. */
299 static kcondvar_t overtemp_cv;
300
301 /* The CV is used to wakeup the key switch thread when needed. */
302 static kcondvar_t keyswitch_cv;
303
304 /* This mutex is used to protect the sysctrl_ddi_branch_init variable */
305 static kmutex_t sysctrl_branch_mutex;
306
307 /*
308 * This variable is set after all existing branches in the system have
309 * been discovered and held via e_ddi_branch_hold(). This happens on
310 * first open() of any sysctrl minor node.
311 */
312 static int sysctrl_ddi_branch_init;
313
314 /*
315 * Linked list of all syctrl soft state structures.
316 * Used for polling sysctrl state changes, i.e. temperature.
317 */
318 struct sysctrl_soft_state *sys_list = NULL;
319
320 extern struct mod_ops mod_driverops;
321
322 static struct modldrv modldrv = {
323 &mod_driverops, /* Type of module. This one is a driver */
324 "Clock Board", /* name of module */
325 &sysctrl_ops, /* driver ops */
326 };
327
328 static struct modlinkage modlinkage = {
329 MODREV_1, /* rev */
330 (void *)&modldrv,
331 NULL
332 };
333
334 /*
335 * These are the module initialization routines.
336 */
337
338 int
_init(void)339 _init(void)
340 {
341 int error;
342
343 if ((error = ddi_soft_state_init(&sysctrlp,
344 sizeof (struct sysctrl_soft_state), 1)) != 0)
345 return (error);
346
347 error = mod_install(&modlinkage);
348 if (error != 0) {
349 ddi_soft_state_fini(&sysctrlp);
350 return (error);
351 }
352
353 mutex_init(&sysctrl_branch_mutex, NULL, MUTEX_DRIVER, NULL);
354
355 return (0);
356 }
357
358 int
_fini(void)359 _fini(void)
360 {
361 int error;
362
363 if ((error = mod_remove(&modlinkage)) != 0)
364 return (error);
365
366 ddi_soft_state_fini(&sysctrlp);
367
368 mutex_destroy(&sysctrl_branch_mutex);
369
370 return (0);
371 }
372
373 int
_info(struct modinfo * modinfop)374 _info(struct modinfo *modinfop)
375 {
376 return (mod_info(&modlinkage, modinfop));
377 }
378
379 /* ARGSUSED */
380 static int
sysctrl_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)381 sysctrl_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
382 {
383 dev_t dev;
384 int instance;
385
386 if (infocmd == DDI_INFO_DEVT2INSTANCE) {
387 dev = (dev_t)arg;
388 instance = GETINSTANCE(dev);
389 *result = (void *)(uintptr_t)instance;
390 return (DDI_SUCCESS);
391 }
392 return (DDI_FAILURE);
393 }
394
395 static int
sysctrl_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)396 sysctrl_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
397 {
398 struct sysctrl_soft_state *softsp;
399 int instance;
400 uchar_t tmp_reg;
401 dev_info_t *dip;
402 char *propval;
403 int proplen;
404 int slot_num;
405 int start; /* start index for scan loop */
406 int limit; /* board number limit for scan loop */
407 int incr; /* amount to incr each pass thru loop */
408 void set_clockbrd_info(void);
409
410
411 switch (cmd) {
412 case DDI_ATTACH:
413 break;
414
415 case DDI_RESUME:
416 /* XXX see sysctrl:DDI_SUSPEND for special h/w treatment */
417 return (DDI_SUCCESS);
418
419 default:
420 return (DDI_FAILURE);
421 }
422
423 instance = ddi_get_instance(devi);
424
425 if (ddi_soft_state_zalloc(sysctrlp, instance) != DDI_SUCCESS)
426 return (DDI_FAILURE);
427
428 softsp = GETSOFTC(instance);
429
430 /* Set the dip in the soft state */
431 softsp->dip = devi;
432
433 /* Set up the parent dip */
434 softsp->pdip = ddi_get_parent(softsp->dip);
435
436 DPRINTF(SYSCTRL_ATTACH_DEBUG, ("sysctrl: devi= 0x%p\n, softsp=0x%p\n",
437 (void *)devi, (void *)softsp));
438
439 /* First set all of the timeout values */
440 spur_timeout_hz = drv_usectohz(SPUR_TIMEOUT_USEC);
441 spur_long_timeout_hz = drv_usectohz(SPUR_LONG_TIMEOUT_USEC);
442 ac_timeout_hz = drv_usectohz(AC_TIMEOUT_USEC);
443 ps_fail_timeout_hz = drv_usectohz(PS_FAIL_TIMEOUT_USEC);
444 pps_fan_timeout_hz = drv_usectohz(PPS_FAN_TIMEOUT_USEC);
445 bd_insert_delay_hz = drv_usectohz(BRD_INSERT_DELAY_USEC);
446 bd_insert_retry_hz = drv_usectohz(BRD_INSERT_RETRY_USEC);
447 bd_remove_timeout_hz = drv_usectohz(BRD_REMOVE_TIMEOUT_USEC);
448 blink_led_timeout_hz = drv_usectohz(BLINK_LED_TIMEOUT_USEC);
449 overtemp_timeout_hz = drv_usectohz(OVERTEMP_TIMEOUT_SEC * MICROSEC);
450 keyswitch_timeout_hz = drv_usectohz(KEYSWITCH_TIMEOUT_USEC);
451
452 /*
453 * Map in the registers sets that OBP hands us. According
454 * to the sun4u device tree spec., the register sets are as
455 * follows:
456 *
457 * 0 Clock Frequency Registers (contains the bit
458 * for enabling the remote console reset)
459 * 1 Misc (has all the registers that we need
460 * 2 Clock Version Register
461 */
462 if (ddi_map_regs(softsp->dip, 0,
463 (caddr_t *)&softsp->clk_freq1, 0, 0)) {
464 cmn_err(CE_WARN, "sysctrl%d: unable to map clock frequency "
465 "registers", instance);
466 goto bad0;
467 }
468
469 if (ddi_map_regs(softsp->dip, 1,
470 (caddr_t *)&softsp->csr, 0, 0)) {
471 cmn_err(CE_WARN, "sysctrl%d: unable to map internal"
472 "registers", instance);
473 goto bad1;
474 }
475
476 /*
477 * There is a new register for newer vintage clock board nodes,
478 * OBP register set 2 in the clock board node.
479 *
480 */
481 (void) ddi_map_regs(softsp->dip, 2, (caddr_t *)&softsp->clk_ver, 0, 0);
482
483 /*
484 * Fill in the virtual addresses of the registers in the
485 * sysctrl_soft_state structure. We do not want to calculate
486 * them on the fly. This way we waste a little memory, but
487 * avoid bugs down the road.
488 */
489 softsp->clk_freq2 = (uchar_t *)((caddr_t)softsp->clk_freq1 +
490 SYS_OFF_CLK_FREQ2);
491
492 softsp->status1 = (uchar_t *)((caddr_t)softsp->csr +
493 SYS_OFF_STAT1);
494
495 softsp->status2 = (uchar_t *)((caddr_t)softsp->csr +
496 SYS_OFF_STAT2);
497
498 softsp->ps_stat = (uchar_t *)((caddr_t)softsp->csr +
499 SYS_OFF_PSSTAT);
500
501 softsp->ps_pres = (uchar_t *)((caddr_t)softsp->csr +
502 SYS_OFF_PSPRES);
503
504 softsp->pppsr = (uchar_t *)((caddr_t)softsp->csr +
505 SYS_OFF_PPPSR);
506
507 softsp->temp_reg = (uchar_t *)((caddr_t)softsp->csr +
508 SYS_OFF_TEMP);
509
510 set_clockbrd_info();
511
512 /*
513 * Enable the hardware watchdog gate on the clock board if
514 * map_wellknown has detected that watchdog timer is available
515 * and user wants it to be enabled.
516 */
517 if (watchdog_available && watchdog_enable)
518 *(softsp->clk_freq2) |= TOD_RESET_EN;
519 else
520 *(softsp->clk_freq2) &= ~TOD_RESET_EN;
521
522 /* Check for inherited faults from the PROM. */
523 if (*softsp->csr & SYS_LED_MID) {
524 reg_fault(0, FT_PROM, FT_SYSTEM);
525 }
526
527 /*
528 * calculate and cache the number of slots on this system
529 */
530 switch (SYS_TYPE(*softsp->status1)) {
531 case SYS_16_SLOT:
532 softsp->nslots = 16;
533 break;
534
535 case SYS_8_SLOT:
536 softsp->nslots = 8;
537 break;
538
539 case SYS_4_SLOT:
540 /* check the clk_version register - if the ptr is valid */
541 if ((softsp->clk_ver != NULL) &&
542 (SYS_TYPE2(*softsp->clk_ver) == SYS_PLUS_SYSTEM)) {
543 softsp->nslots = 5;
544 } else {
545 softsp->nslots = 4;
546 }
547 break;
548
549 case SYS_TESTBED:
550 default:
551 softsp->nslots = 0;
552 break;
553 }
554
555
556 /* create the fault list kstat */
557 create_ft_kstats(instance);
558
559 /*
560 * Do a priming read on the ADC, and throw away the first value
561 * read. This is a feature of the ADC hardware. After a power cycle
562 * it does not contains valid data until a read occurs.
563 */
564 tmp_reg = *(softsp->temp_reg);
565
566 /* Wait 30 usec for ADC hardware to stabilize. */
567 DELAY(30);
568
569 /* shut off all interrupt sources */
570 *(softsp->csr) &= ~(SYS_PPS_FAN_FAIL_EN | SYS_PS_FAIL_EN |
571 SYS_AC_PWR_FAIL_EN | SYS_SBRD_PRES_EN);
572 tmp_reg = *(softsp->csr);
573 #ifdef lint
574 tmp_reg = tmp_reg;
575 #endif
576
577 /*
578 * Now register our high interrupt with the system.
579 */
580 if (ddi_add_intr(devi, 0, &softsp->iblock,
581 &softsp->idevice, (uint_t (*)(caddr_t))nulldev, NULL) !=
582 DDI_SUCCESS)
583 goto bad2;
584
585 mutex_init(&softsp->csr_mutex, NULL, MUTEX_DRIVER,
586 (void *)softsp->iblock);
587
588 ddi_remove_intr(devi, 0, softsp->iblock);
589
590 if (ddi_add_intr(devi, 0, &softsp->iblock,
591 &softsp->idevice, system_high_handler, (caddr_t)softsp) !=
592 DDI_SUCCESS)
593 goto bad3;
594
595 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_id,
596 &softsp->spur_int_c, NULL, spur_delay, (caddr_t)softsp) !=
597 DDI_SUCCESS)
598 goto bad4;
599
600 mutex_init(&softsp->spur_int_lock, NULL, MUTEX_DRIVER,
601 (void *)softsp->spur_int_c);
602
603
604 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_high_id,
605 NULL, NULL, spur_reenable, (caddr_t)softsp) != DDI_SUCCESS)
606 goto bad5;
607
608 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_long_to_id,
609 NULL, NULL, spur_clear_count, (caddr_t)softsp) != DDI_SUCCESS)
610 goto bad6;
611
612 /*
613 * Now register low-level ac fail handler
614 */
615 if (ddi_add_softintr(devi, DDI_SOFTINT_HIGH, &softsp->ac_fail_id,
616 NULL, NULL, ac_fail_handler, (caddr_t)softsp) != DDI_SUCCESS)
617 goto bad7;
618
619 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->ac_fail_high_id,
620 NULL, NULL, ac_fail_reenable, (caddr_t)softsp) != DDI_SUCCESS)
621 goto bad8;
622
623 /*
624 * Now register low-level ps fail handler
625 */
626
627 if (ddi_add_softintr(devi, DDI_SOFTINT_HIGH, &softsp->ps_fail_int_id,
628 &softsp->ps_fail_c, NULL, ps_fail_int_handler, (caddr_t)softsp) !=
629 DDI_SUCCESS)
630 goto bad9;
631
632 mutex_init(&softsp->ps_fail_lock, NULL, MUTEX_DRIVER,
633 (void *)softsp->ps_fail_c);
634
635 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->ps_fail_poll_id,
636 NULL, NULL, ps_fail_poll_handler, (caddr_t)softsp) !=
637 DDI_SUCCESS)
638 goto bad10;
639
640 /*
641 * Now register low-level pps fan fail handler
642 */
643 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->pps_fan_id,
644 NULL, NULL, pps_fanfail_handler, (caddr_t)softsp) !=
645 DDI_SUCCESS)
646 goto bad11;
647
648 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->pps_fan_high_id,
649 NULL, NULL, pps_fanfail_reenable, (caddr_t)softsp) !=
650 DDI_SUCCESS)
651 goto bad12;
652
653 /*
654 * Based upon a check for a current share backplane, advise
655 * that system does not support hot plug
656 *
657 */
658 if ((*(softsp->pppsr) & SYS_NOT_CURRENT_S) != 0) {
659 cmn_err(CE_NOTE, "Hot Plug not supported in this system");
660 sysctrl_hotplug_disabled = TRUE;
661 }
662
663 /*
664 * If the trigger circuit is busted or the NOT_BRD_PRES line
665 * is stuck then OBP will publish this property stating that
666 * hot plug is not available. If this happens we will complain
667 * to the console and register a system fault. We will also
668 * not enable the board insert interrupt for this session.
669 */
670 if (ddi_prop_op(DDI_DEV_T_ANY, softsp->dip, PROP_LEN_AND_VAL_ALLOC,
671 DDI_PROP_DONTPASS, HOTPLUG_DISABLED_PROPERTY,
672 (caddr_t)&propval, &proplen) == DDI_PROP_SUCCESS) {
673 cmn_err(CE_WARN, "Hot Plug Unavailable [%s]", propval);
674 reg_fault(0, FT_HOT_PLUG, FT_SYSTEM);
675 sysctrl_hotplug_disabled = TRUE;
676 enable_sys_interrupt &= ~SYS_SBRD_PRES_EN;
677 kmem_free(propval, proplen);
678 }
679
680 sysc_board_connect_supported_init();
681
682 fhc_bd_sc_register(sysc_policy_update, softsp);
683
684 sysc_slot_info(softsp->nslots, &start, &limit, &incr);
685
686 /* Prime the board list. */
687 fhc_bdlist_prime(start, limit, incr);
688
689 /*
690 * Set up a board remove timeout call.
691 */
692 (void) fhc_bdlist_lock(-1);
693
694 DPRINTF(SYSCTRL_ATTACH_DEBUG,
695 ("attach: start bd_remove_poll()..."));
696
697 bd_remove_poll(softsp);
698 fhc_bdlist_unlock();
699
700 /*
701 * Now register low-level board insert handler
702 */
703 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->sbrd_pres_id,
704 NULL, NULL, bd_insert_handler, (caddr_t)softsp) != DDI_SUCCESS)
705 goto bad13;
706
707 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->sbrd_gone_id,
708 NULL, NULL, bd_insert_normal, (caddr_t)softsp) != DDI_SUCCESS)
709 goto bad14;
710
711 /*
712 * Now register led blink handler (interrupt level)
713 */
714 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->blink_led_id,
715 &softsp->sys_led_c, NULL, blink_led_handler, (caddr_t)softsp) !=
716 DDI_SUCCESS)
717 goto bad15;
718 mutex_init(&softsp->sys_led_lock, NULL, MUTEX_DRIVER,
719 (void *)softsp->sys_led_c);
720
721 /* initialize the bit field for all pps fans to assumed good */
722 softsp->pps_fan_saved = softsp->pps_fan_external_state =
723 SYS_AC_FAN_OK | SYS_KEYSW_FAN_OK;
724
725 /* prime the power supply state machines */
726 if (enable_sys_interrupt & SYS_PS_FAIL_EN)
727 ddi_trigger_softintr(softsp->ps_fail_poll_id);
728
729
730 /* kick off the OS led blinker */
731 softsp->sys_led = FALSE;
732 ddi_trigger_softintr(softsp->blink_led_id);
733
734 /* Now enable selected interrupt sources */
735 mutex_enter(&softsp->csr_mutex);
736 *(softsp->csr) |= enable_sys_interrupt &
737 (SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
738 SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
739 tmp_reg = *(softsp->csr);
740 #ifdef lint
741 tmp_reg = tmp_reg;
742 #endif
743 mutex_exit(&softsp->csr_mutex);
744
745 /* Initialize the temperature */
746 init_temp_arrays(&softsp->tempstat);
747
748 /*
749 * initialize key switch shadow state
750 */
751 softsp->key_shadow = KEY_BOOT;
752
753 /*
754 * Now add this soft state structure to the front of the linked list
755 * of soft state structures.
756 */
757 if (sys_list == (struct sysctrl_soft_state *)NULL) {
758 mutex_init(&sslist_mutex, NULL, MUTEX_DEFAULT, NULL);
759 }
760 mutex_enter(&sslist_mutex);
761 softsp->next = sys_list;
762 sys_list = softsp;
763 mutex_exit(&sslist_mutex);
764
765 /* Setup the kstats for this device */
766 sysctrl_add_kstats(softsp);
767
768 /* kick off the PPS fan poll routine */
769 pps_fan_poll(softsp);
770
771 if (sysctrl_overtemp_thread_started == 0) {
772 /*
773 * set up the overtemp condition variable before
774 * starting the thread.
775 */
776 cv_init(&overtemp_cv, NULL, CV_DRIVER, NULL);
777
778 /*
779 * start up the overtemp polling thread
780 */
781 (void) thread_create(NULL, 0, (void (*)())sysctrl_overtemp_poll,
782 NULL, 0, &p0, TS_RUN, minclsyspri);
783 sysctrl_overtemp_thread_started++;
784 }
785
786 if (sysctrl_keyswitch_thread_started == 0) {
787 extern void (*abort_seq_handler)();
788
789 /*
790 * interpose sysctrl's abort sequence handler
791 */
792 abort_seq_handler = sysctrl_abort_seq_handler;
793
794 /*
795 * set up the key switch condition variable before
796 * starting the thread
797 */
798 cv_init(&keyswitch_cv, NULL, CV_DRIVER, NULL);
799
800 /*
801 * start up the key switch polling thread
802 */
803 (void) thread_create(NULL, 0,
804 (void (*)())sysctrl_keyswitch_poll, NULL, 0, &p0,
805 TS_RUN, minclsyspri);
806 sysctrl_keyswitch_thread_started++;
807 }
808
809 /*
810 * perform initialization to allow setting of powerfail-time
811 */
812 if ((dip = ddi_find_devinfo("options", -1, 0)) == NULL)
813 softsp->options_nodeid = (pnode_t)0;
814 else
815 softsp->options_nodeid = (pnode_t)ddi_get_nodeid(dip);
816
817 DPRINTF(SYSCTRL_ATTACH_DEBUG,
818 ("sysctrl: Creating devices start:%d, limit:%d, incr:%d\n",
819 start, limit, incr));
820
821 /*
822 * Create minor node for each system attachment points
823 */
824 for (slot_num = start; slot_num < limit; slot_num = slot_num + incr) {
825 char name[30];
826 (void) sprintf(name, "slot%d", slot_num);
827 if (ddi_create_minor_node(devi, name, S_IFCHR,
828 (PUTINSTANCE(instance) | slot_num),
829 DDI_NT_ATTACHMENT_POINT, 0) == DDI_FAILURE) {
830 cmn_err(CE_WARN, "sysctrl%d: \"%s\" "
831 "ddi_create_minor_node failed",
832 instance, name);
833 goto bad16;
834 }
835 }
836
837 ddi_report_dev(devi);
838
839 /*
840 * Remote console is inherited from POST
841 */
842 if ((*(softsp->clk_freq2) & RCONS_UART_EN) == 0) {
843 softsp->enable_rcons_atboot = FALSE;
844 cmn_err(CE_WARN, "Remote console not active");
845 } else
846 softsp->enable_rcons_atboot = TRUE;
847
848 return (DDI_SUCCESS);
849
850 bad16:
851 cv_destroy(&keyswitch_cv);
852 cv_destroy(&overtemp_cv);
853 mutex_destroy(&sslist_mutex);
854 mutex_destroy(&softsp->sys_led_lock);
855 ddi_remove_softintr(softsp->blink_led_id);
856 bad15:
857 ddi_remove_softintr(softsp->sbrd_gone_id);
858 bad14:
859 ddi_remove_softintr(softsp->sbrd_pres_id);
860 bad13:
861 ddi_remove_softintr(softsp->pps_fan_high_id);
862 bad12:
863 ddi_remove_softintr(softsp->pps_fan_id);
864 bad11:
865 ddi_remove_softintr(softsp->ps_fail_poll_id);
866 bad10:
867 mutex_destroy(&softsp->ps_fail_lock);
868 ddi_remove_softintr(softsp->ps_fail_int_id);
869 bad9:
870 ddi_remove_softintr(softsp->ac_fail_high_id);
871 bad8:
872 ddi_remove_softintr(softsp->ac_fail_id);
873 bad7:
874 ddi_remove_softintr(softsp->spur_long_to_id);
875 bad6:
876 ddi_remove_softintr(softsp->spur_high_id);
877 bad5:
878 mutex_destroy(&softsp->spur_int_lock);
879 ddi_remove_softintr(softsp->spur_id);
880 bad4:
881 ddi_remove_intr(devi, 0, softsp->iblock);
882 bad3:
883 mutex_destroy(&softsp->csr_mutex);
884 bad2:
885 ddi_unmap_regs(softsp->dip, 1, (caddr_t *)&softsp->csr, 0, 0);
886 if (softsp->clk_ver != NULL)
887 ddi_unmap_regs(softsp->dip, 2, (caddr_t *)&softsp->clk_ver,
888 0, 0);
889 bad1:
890 ddi_unmap_regs(softsp->dip, 0, (caddr_t *)&softsp->clk_freq1, 0, 0);
891
892 bad0:
893 ddi_soft_state_free(sysctrlp, instance);
894 ddi_remove_minor_node(dip, NULL);
895 cmn_err(CE_WARN,
896 "sysctrl%d: Initialization failure. Some system level events,"
897 " {AC Fail, Fan Failure, PS Failure} not detected", instance);
898 return (DDI_FAILURE);
899 }
900
901 struct sysc_hold {
902 int start;
903 int limit;
904 int incr;
905 int hold;
906 };
907
908 static int
sysctrl_hold_rele_branches(dev_info_t * dip,void * arg)909 sysctrl_hold_rele_branches(dev_info_t *dip, void *arg)
910 {
911 int *rp, len, slot, i;
912 struct sysc_hold *ap = (struct sysc_hold *)arg;
913
914 /*
915 * For Sunfire, top nodes on board are always children of root dip
916 */
917 ASSERT(ddi_get_parent(dip) == ddi_root_node());
918
919 /*
920 * Skip non-PROM and "central" nodes
921 */
922 if (!ndi_dev_is_prom_node(dip) ||
923 strcmp(ddi_node_name(dip), "central") == 0)
924 return (DDI_WALK_PRUNECHILD);
925
926 /*
927 * Extract board # from reg property.
928 */
929 if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
930 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg", (caddr_t)&rp, &len)
931 != DDI_SUCCESS) {
932 DPRINTF(SYSC_DEBUG, ("devinfo node %s(%p) has no reg"
933 " property\n", ddi_node_name(dip), (void *)dip));
934 return (DDI_WALK_PRUNECHILD);
935 }
936
937 slot = (*rp - 0x1c0) >> 2;
938 kmem_free(rp, len);
939
940 ASSERT(ap->start >= 0 && ap->start < ap->limit);
941
942 for (i = ap->start; i < ap->limit; i = i + ap->incr) {
943 if (i == slot)
944 break;
945 }
946
947 if (i >= ap->limit) {
948 DPRINTF(SYSC_DEBUG, ("sysctrl_hold_rele: Invalid board # (%d)"
949 " for node %s(%p)\n", slot, ddi_node_name(dip),
950 (void *)dip));
951 return (DDI_WALK_PRUNECHILD);
952 }
953
954 if (ap->hold) {
955 ASSERT(!e_ddi_branch_held(dip));
956 e_ddi_branch_hold(dip);
957 } else {
958 ASSERT(e_ddi_branch_held(dip));
959 e_ddi_branch_rele(dip);
960 }
961
962 return (DDI_WALK_PRUNECHILD);
963 }
964
965 /* ARGSUSED */
966 static int
sysctrl_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)967 sysctrl_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
968 {
969 #ifdef SYSCTRL_SUPPORTS_DETACH
970 dev_info_t *rdip;
971 struct sysc_hold arg = {0};
972 struct sysctrl_soft_state *softsp;
973 #endif /* SYSCTRL_SUPPORTS_DETACH */
974
975 if (sysctrl_enable_detach_suspend == FALSE)
976 return (DDI_FAILURE);
977
978 switch (cmd) {
979 case DDI_SUSPEND:
980 /*
981 * XXX we don't presently save the state of the remote
982 * console because it is a constant function of POST.
983 * XXX we don't deal with the hardware watchdog here
984 * either. It should be handled in hardclk.
985 */
986 return (DDI_SUCCESS);
987
988 case DDI_DETACH:
989 break;
990 default:
991 return (DDI_FAILURE);
992 }
993
994 #ifdef SYSCTRL_SUPPORTS_DETACH
995
996 /*
997 * XXX If sysctrl ever supports detach, this code should be enabled
998 * This is only the portion of the detach code dealing with
999 * the DDI branch routines. Other parts of detach will need
1000 * to be added.
1001 */
1002
1003 /*
1004 * Walk immediate children of root devinfo node, releasing holds
1005 * on branches acquired in first sysctrl_open().
1006 */
1007
1008 instance = ddi_get_instance(dip);
1009 softsp = GETSOFTC(instance);
1010
1011 if (softsp == NULL) {
1012 cmn_err(CE_WARN, "sysctrl%d device not attached", instance);
1013 return (DDI_FAILURE);
1014 }
1015
1016 sysc_slot_info(softsp->nslots, &arg.start, &arg.limit, &arg.incr);
1017
1018 arg.hold = 0;
1019
1020 rdip = ddi_root_node();
1021
1022 ndi_devi_enter(rdip);
1023 ddi_walk_devs(ddi_get_child(rdip), sysctrl_hold_rele_branches, &arg);
1024 ndi_devi_exit(rdip);
1025
1026 sysctrl_ddi_branch_init = 0;
1027
1028 return (DDI_SUCCESS);
1029 #endif /* SYSCTRL_SUPPORTS_DETACH */
1030
1031 return (DDI_FAILURE);
1032 }
1033
1034 /* ARGSUSED */
1035 static int
sysctrl_open(dev_t * devp,int flag,int otyp,cred_t * credp)1036 sysctrl_open(dev_t *devp, int flag, int otyp, cred_t *credp)
1037 {
1038 int instance;
1039 int slot;
1040 dev_t dev;
1041 dev_info_t *rdip;
1042 struct sysc_hold arg = {0};
1043 struct sysctrl_soft_state *softsp;
1044
1045 dev = *devp;
1046
1047 /*
1048 * We checked against the instance softstate structure since there
1049 * will only be one instance of sysctrl (clock board) in UEXX00
1050 *
1051 * Since we only create minor devices for existing slots on a
1052 * particular system, we don't need to worry about non-exist slot.
1053 */
1054
1055 instance = GETINSTANCE(dev);
1056 slot = GETSLOT(dev);
1057
1058 /* Is the instance attached? */
1059 if ((softsp = GETSOFTC(instance)) == NULL) {
1060 cmn_err(CE_WARN, "sysctrl%d device not attached", instance);
1061 return (ENXIO);
1062 }
1063
1064 /* verify that otyp is appropriate */
1065 if (otyp != OTYP_CHR) {
1066 return (EINVAL);
1067 }
1068
1069 if (!fhc_bd_valid(slot))
1070 return (ENXIO);
1071
1072 /*
1073 * On first open of a sysctrl minor walk immediate children of the
1074 * devinfo root node and hold all branches of interest.
1075 */
1076 mutex_enter(&sysctrl_branch_mutex);
1077 if (!sysctrl_ddi_branch_init) {
1078
1079 sysctrl_ddi_branch_init = 1;
1080
1081 sysc_slot_info(softsp->nslots, &arg.start, &arg.limit,
1082 &arg.incr);
1083 arg.hold = 1;
1084
1085 rdip = ddi_root_node();
1086
1087 ndi_devi_enter(rdip);
1088 ddi_walk_devs(ddi_get_child(rdip), sysctrl_hold_rele_branches,
1089 &arg);
1090 ndi_devi_exit(rdip);
1091 }
1092 mutex_exit(&sysctrl_branch_mutex);
1093
1094 return (DDI_SUCCESS);
1095 }
1096
1097 /* ARGSUSED */
1098 static int
sysctrl_close(dev_t devp,int flag,int otyp,cred_t * credp)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
sysc_enter_transition(int slot)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
sysc_exit_transition(int slot)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
sysc_pkt_init(sysc_cfga_pkt_t * pkt,intptr_t arg,int flag)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
sysc_pkt_fini(sysc_cfga_pkt_t * pkt,intptr_t arg,int flag)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
sysctrl_ioctl(dev_t devt,int cmd,intptr_t arg,int flag,cred_t * cred_p,int * rval_p)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
system_high_handler(caddr_t arg)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
spur_delay(caddr_t arg)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
spur_retry(void * arg)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
spur_reenable(caddr_t arg)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
spur_long_timeout(void * arg)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
spur_clear_count(caddr_t arg)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
ac_fail_handler(caddr_t arg)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
ac_fail_retry(void * arg)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
ac_fail_reenable(caddr_t arg)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
ps_fail_int_handler(caddr_t arg)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
ps_fail_poll_handler(caddr_t arg)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
ps_fail_handler(struct sysctrl_soft_state * softsp,int fromint)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
compute_power_state(struct sysctrl_soft_state * softsp,int plus_load)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
ps_log_pres_change(struct sysctrl_soft_state * softsp,int index,int present)2246 ps_log_pres_change(struct sysctrl_soft_state *softsp, int index, int present)
2247 {
2248 char *trans = present ? "Installed" : "Removed";
2249
2250 switch (index) {
2251 /* the core power supplies (except for 7) */
2252 case 0: case 1: case 2: case 3:
2253 case 4: case 5: case 6:
2254 cmn_err(CE_NOTE, "%s %d %s", ft_str_table[FT_CORE_PS], index,
2255 trans);
2256 if (!present) {
2257 clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2258 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2259 }
2260 break;
2261
2262 /* power supply 7 / pps 1 */
2263 case 7:
2264 if (IS4SLOT(softsp->nslots) || IS5SLOT(softsp->nslots)) {
2265 cmn_err(CE_NOTE, "%s 1 %s", ft_str_table[FT_PPS],
2266 trans);
2267 if (!present) {
2268 clear_fault(1, FT_PPS, FT_SYSTEM);
2269 }
2270 } else {
2271 cmn_err(CE_NOTE, "%s %d %s", ft_str_table[FT_CORE_PS],
2272 index, trans);
2273 if (!present) {
2274 clear_fault(7, FT_CORE_PS, FT_SYSTEM);
2275 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2276 }
2277 }
2278 break;
2279
2280 /* the peripheral power supply 0 */
2281 case SYS_PPS0_INDEX:
2282 cmn_err(CE_NOTE, "%s 0 %s", ft_str_table[FT_PPS], trans);
2283 if (!present) {
2284 clear_fault(0, FT_PPS, FT_SYSTEM);
2285 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2286 }
2287 break;
2288
2289 /* the peripheral rack fan assy */
2290 case SYS_P_FAN_INDEX:
2291 cmn_err(CE_NOTE, "%s %s", ft_str_table[FT_PPS_FAN], trans);
2292 if (!present) {
2293 clear_fault(0, FT_PPS_FAN, FT_SYSTEM);
2294 }
2295 break;
2296
2297 /* we don't mention a change of presence state for any other power */
2298 }
2299 }
2300
2301 /*
2302 * log the change of power supply status
2303 */
2304 static void
ps_log_state_change(struct sysctrl_soft_state * softsp,int index,int ps_ok)2305 ps_log_state_change(struct sysctrl_soft_state *softsp, int index, int ps_ok)
2306 {
2307 int level = ps_ok ? CE_NOTE : CE_WARN;
2308 char *s = ps_ok ? "OK" : "Failing";
2309
2310 switch (index) {
2311 /* the core power supplies (except 7) */
2312 case 0: case 1: case 2: case 3:
2313 case 4: case 5: case 6:
2314 cmn_err(level, "%s %d %s", ft_str_table[FT_CORE_PS], index, s);
2315 if (ps_ok) {
2316 clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2317 } else {
2318 reg_fault(index, FT_CORE_PS, FT_SYSTEM);
2319 }
2320 break;
2321
2322 /* power supply 7 / pps 1 */
2323 case 7:
2324 if (IS4SLOT(softsp->nslots) || IS5SLOT(softsp->nslots)) {
2325 cmn_err(level, "%s 1 %s", ft_str_table[FT_PPS], s);
2326 if (ps_ok) {
2327 clear_fault(1, FT_PPS, FT_SYSTEM);
2328 } else {
2329 reg_fault(1, FT_PPS, FT_SYSTEM);
2330 }
2331 } else {
2332 cmn_err(level, "%s %d %s", ft_str_table[FT_CORE_PS],
2333 index, s);
2334 if (ps_ok) {
2335 clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2336 } else {
2337 reg_fault(index, FT_CORE_PS, FT_SYSTEM);
2338 }
2339 }
2340 break;
2341
2342 /* the peripheral power supply */
2343 case SYS_PPS0_INDEX:
2344 cmn_err(level, "%s %s", ft_str_table[FT_PPS], s);
2345 if (ps_ok) {
2346 clear_fault(0, FT_PPS, FT_SYSTEM);
2347 } else {
2348 reg_fault(0, FT_PPS, FT_SYSTEM);
2349 }
2350 break;
2351
2352 /* shared 3.3v clock power */
2353 case SYS_CLK_33_INDEX:
2354 cmn_err(level, "%s %s", ft_str_table[FT_CLK_33], s);
2355 if (ps_ok) {
2356 clear_fault(0, FT_CLK_33, FT_SYSTEM);
2357 } else {
2358 reg_fault(0, FT_CLK_33, FT_SYSTEM);
2359 }
2360 break;
2361
2362 /* shared 5.0v clock power */
2363 case SYS_CLK_50_INDEX:
2364 cmn_err(level, "%s %s", ft_str_table[FT_CLK_50], s);
2365 if (ps_ok) {
2366 clear_fault(0, FT_CLK_50, FT_SYSTEM);
2367 } else {
2368 reg_fault(0, FT_CLK_50, FT_SYSTEM);
2369 }
2370 break;
2371
2372 /* peripheral 5v */
2373 case SYS_V5_P_INDEX:
2374 cmn_err(level, "%s %s", ft_str_table[FT_V5_P], s);
2375 if (ps_ok) {
2376 clear_fault(0, FT_V5_P, FT_SYSTEM);
2377 } else {
2378 reg_fault(0, FT_V5_P, FT_SYSTEM);
2379 }
2380 break;
2381
2382 /* peripheral 12v */
2383 case SYS_V12_P_INDEX:
2384 cmn_err(level, "%s %s", ft_str_table[FT_V12_P], s);
2385 if (ps_ok) {
2386 clear_fault(0, FT_V12_P, FT_SYSTEM);
2387 } else {
2388 reg_fault(0, FT_V12_P, FT_SYSTEM);
2389 }
2390 break;
2391
2392 /* aux 5v */
2393 case SYS_V5_AUX_INDEX:
2394 cmn_err(level, "%s %s", ft_str_table[FT_V5_AUX], s);
2395 if (ps_ok) {
2396 clear_fault(0, FT_V5_AUX, FT_SYSTEM);
2397 } else {
2398 reg_fault(0, FT_V5_AUX, FT_SYSTEM);
2399 }
2400 break;
2401
2402 /* peripheral 5v precharge */
2403 case SYS_V5_P_PCH_INDEX:
2404 cmn_err(level, "%s %s", ft_str_table[FT_V5_P_PCH], s);
2405 if (ps_ok) {
2406 clear_fault(0, FT_V5_P_PCH, FT_SYSTEM);
2407 } else {
2408 reg_fault(0, FT_V5_P_PCH, FT_SYSTEM);
2409 }
2410 break;
2411
2412 /* peripheral 12v precharge */
2413 case SYS_V12_P_PCH_INDEX:
2414 cmn_err(level, "%s %s", ft_str_table[FT_V12_P_PCH], s);
2415 if (ps_ok) {
2416 clear_fault(0, FT_V12_P_PCH, FT_SYSTEM);
2417 } else {
2418 reg_fault(0, FT_V12_P_PCH, FT_SYSTEM);
2419 }
2420 break;
2421
2422 /* 3.3v precharge */
2423 case SYS_V3_PCH_INDEX:
2424 cmn_err(level, "%s %s", ft_str_table[FT_V3_PCH], s);
2425 if (ps_ok) {
2426 clear_fault(0, FT_V3_PCH, FT_SYSTEM);
2427 } else {
2428 reg_fault(0, FT_V3_PCH, FT_SYSTEM);
2429 }
2430 break;
2431
2432 /* 5v precharge */
2433 case SYS_V5_PCH_INDEX:
2434 cmn_err(level, "%s %s", ft_str_table[FT_V5_PCH], s);
2435 if (ps_ok) {
2436 clear_fault(0, FT_V5_PCH, FT_SYSTEM);
2437 } else {
2438 reg_fault(0, FT_V5_PCH, FT_SYSTEM);
2439 }
2440 break;
2441
2442 /* peripheral power supply fans */
2443 case SYS_P_FAN_INDEX:
2444 cmn_err(level, "%s %s", ft_str_table[FT_PPS_FAN], s);
2445 if (ps_ok) {
2446 clear_fault(0, FT_PPS_FAN, FT_SYSTEM);
2447 } else {
2448 reg_fault(0, FT_PPS_FAN, FT_SYSTEM);
2449 }
2450 break;
2451 }
2452 }
2453
2454 /*
2455 * The timeout from ps_fail_handler() that simply re-triggers a check
2456 * of the ps condition.
2457 */
2458 static void
ps_fail_retry(void * arg)2459 ps_fail_retry(void *arg)
2460 {
2461 struct sysctrl_soft_state *softsp = arg;
2462
2463 ASSERT(softsp);
2464
2465 ddi_trigger_softintr(softsp->ps_fail_poll_id);
2466 }
2467
2468 /*
2469 * pps_fanfail_handler
2470 *
2471 * This routine is called from the high level handler.
2472 */
2473 static uint_t
pps_fanfail_handler(caddr_t arg)2474 pps_fanfail_handler(caddr_t arg)
2475 {
2476 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2477
2478 ASSERT(softsp);
2479
2480 /* always check again in a bit by re-enabling the fan interrupt */
2481 (void) timeout(pps_fanfail_retry, softsp, pps_fan_timeout_hz);
2482
2483 return (DDI_INTR_CLAIMED);
2484 }
2485
2486 /*
2487 * After a bit of waiting, we simply re-enable the interrupt to
2488 * see if we get another one. The softintr triggered routine does
2489 * the dirty work for us since it runs in the interrupt context.
2490 */
2491 static void
pps_fanfail_retry(void * arg)2492 pps_fanfail_retry(void *arg)
2493 {
2494 struct sysctrl_soft_state *softsp = arg;
2495
2496 ASSERT(softsp);
2497
2498 ddi_trigger_softintr(softsp->pps_fan_high_id);
2499 }
2500
2501 /*
2502 * The other half of the retry handler run from the interrupt context
2503 */
2504 static uint_t
pps_fanfail_reenable(caddr_t arg)2505 pps_fanfail_reenable(caddr_t arg)
2506 {
2507 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2508 uchar_t tmp_reg;
2509
2510 ASSERT(softsp);
2511
2512 mutex_enter(&softsp->csr_mutex);
2513
2514 /*
2515 * re-initialize the bit field for all pps fans to assumed good.
2516 * If the fans are still bad, we're going to get an immediate system
2517 * interrupt which will put the correct state back anyway.
2518 *
2519 * NOTE: the polling routines that use this state understand the
2520 * pulse resulting from above...
2521 */
2522 softsp->pps_fan_saved = SYS_AC_FAN_OK | SYS_KEYSW_FAN_OK;
2523
2524 *(softsp->csr) |= SYS_PPS_FAN_FAIL_EN;
2525 tmp_reg = *(softsp->csr);
2526 #ifdef lint
2527 tmp_reg = tmp_reg;
2528 #endif
2529 mutex_exit(&softsp->csr_mutex);
2530
2531 return (DDI_INTR_CLAIMED);
2532 }
2533
2534 /*
2535 *
2536 * Poll the hardware shadow state to determine the pps fan status.
2537 * The shadow state is maintained by the system_high handler and its
2538 * associated pps_* functions (above).
2539 *
2540 * There is a short time interval where the shadow state is pulsed to
2541 * the OK state even when the fans are bad. However, this polling
2542 * routine has some built in hysteresis to filter out those _normal_
2543 * events.
2544 */
2545 static void
pps_fan_poll(void * arg)2546 pps_fan_poll(void *arg)
2547 {
2548 struct sysctrl_soft_state *softsp = arg;
2549 int i;
2550
2551 ASSERT(softsp);
2552
2553 for (i = 0; i < SYS_PPS_FAN_COUNT; i++) {
2554 int fanfail = FALSE;
2555
2556 /* determine fan status */
2557 switch (i) {
2558 case RACK:
2559 fanfail = softsp->pps_fan_saved & SYS_RACK_FANFAIL;
2560 break;
2561
2562 case AC:
2563 /*
2564 * Don't bother polling the AC fan on 4 and 5 slot
2565 * systems.
2566 * Rather, it is handled by the power supply loop.
2567 */
2568 fanfail = !(IS4SLOT(softsp->nslots) ||
2569 IS5SLOT(softsp->nslots)) &&
2570 !(softsp->pps_fan_saved & SYS_AC_FAN_OK);
2571 break;
2572
2573 case KEYSW:
2574 /*
2575 * This signal is not usable if aux5v is missing
2576 * so we will synthesize a failed fan when aux5v
2577 * fails or when pps0 is out.
2578 * The 4 and 5 slot systems behave the same.
2579 */
2580 fanfail = (!(IS4SLOT(softsp->nslots) ||
2581 IS5SLOT(softsp->nslots)) &&
2582 (softsp->ps_stats[SYS_V5_AUX_INDEX].dcshadow !=
2583 PS_OK)) ||
2584 !(softsp->pps_fan_saved & SYS_KEYSW_FAN_OK);
2585 break;
2586
2587 }
2588
2589 /* is the fan bad? */
2590 if (fanfail) {
2591
2592 /* is this condition different than we know? */
2593 if (softsp->pps_fan_state_count[i] == 0) {
2594
2595 /* log the change to failed */
2596 pps_fan_state_change(softsp, i, FALSE);
2597 }
2598
2599 /* always restart the fan OK counter */
2600 softsp->pps_fan_state_count[i] = PPS_FROM_FAIL_TICKS;
2601 } else {
2602
2603 /* do we currently know the fan is bad? */
2604 if (softsp->pps_fan_state_count[i]) {
2605
2606 /* yes, but has it been stable? */
2607 if (--softsp->pps_fan_state_count[i] == 0) {
2608
2609 /* log the change to OK */
2610 pps_fan_state_change(softsp, i, TRUE);
2611 }
2612 }
2613 }
2614 }
2615
2616 /* always check again in a bit by re-enabling the fan interrupt */
2617 (void) timeout(pps_fan_poll, softsp, pps_fan_timeout_hz);
2618 }
2619
2620 /*
2621 * pps_fan_state_change()
2622 *
2623 * Log the changed fan condition and update the external status.
2624 */
2625 static void
pps_fan_state_change(struct sysctrl_soft_state * softsp,int index,int fan_ok)2626 pps_fan_state_change(struct sysctrl_soft_state *softsp, int index, int fan_ok)
2627 {
2628 char *fan_type;
2629 char *state = fan_ok ? "fans OK" : "fan failure detected";
2630
2631 switch (index) {
2632 case RACK:
2633 /* 4 and 5 slot systems behave the same */
2634 fan_type = (IS4SLOT(softsp->nslots) ||
2635 IS5SLOT(softsp->nslots)) ?
2636 "Disk Drive" : "Rack Exhaust";
2637 if (fan_ok) {
2638 softsp->pps_fan_external_state &= ~SYS_RACK_FANFAIL;
2639 clear_fault(0, (IS4SLOT(softsp->nslots) ||
2640 IS5SLOT(softsp->nslots)) ? FT_DSK_FAN :
2641 FT_RACK_EXH, FT_SYSTEM);
2642 } else {
2643 softsp->pps_fan_external_state |= SYS_RACK_FANFAIL;
2644 reg_fault(0, (IS4SLOT(softsp->nslots) ||
2645 IS5SLOT(softsp->nslots)) ? FT_DSK_FAN :
2646 FT_RACK_EXH, FT_SYSTEM);
2647 }
2648 break;
2649
2650 case AC:
2651 fan_type = "AC Box";
2652 if (fan_ok) {
2653 softsp->pps_fan_external_state |= SYS_AC_FAN_OK;
2654 clear_fault(0, FT_AC_FAN, FT_SYSTEM);
2655 } else {
2656 softsp->pps_fan_external_state &= ~SYS_AC_FAN_OK;
2657 reg_fault(0, FT_AC_FAN, FT_SYSTEM);
2658 }
2659 break;
2660
2661 case KEYSW:
2662 fan_type = "Keyswitch";
2663 if (fan_ok) {
2664 softsp->pps_fan_external_state |= SYS_KEYSW_FAN_OK;
2665 clear_fault(0, FT_KEYSW_FAN, FT_SYSTEM);
2666 } else {
2667 softsp->pps_fan_external_state &= ~SYS_KEYSW_FAN_OK;
2668 reg_fault(0, FT_KEYSW_FAN, FT_SYSTEM);
2669 }
2670 break;
2671 default:
2672 fan_type = "[invalid fan id]";
2673 break;
2674 }
2675
2676 /* now log the state change */
2677 cmn_err(fan_ok ? CE_NOTE : CE_WARN, "%s %s", fan_type, state);
2678 }
2679
2680 static uint_t
bd_insert_handler(caddr_t arg)2681 bd_insert_handler(caddr_t arg)
2682 {
2683 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2684
2685 ASSERT(softsp);
2686
2687 DPRINTF(SYSCTRL_ATTACH_DEBUG, ("bd_insert_handler()"));
2688
2689 (void) timeout(bd_insert_timeout, softsp, bd_insert_delay_hz);
2690
2691 return (DDI_INTR_CLAIMED);
2692 }
2693
2694 void
bd_remove_poll(struct sysctrl_soft_state * softsp)2695 bd_remove_poll(struct sysctrl_soft_state *softsp)
2696 {
2697 ASSERT(fhc_bdlist_locked());
2698
2699 if (!bd_remove_to_id) {
2700 bd_remove_to_id = timeout(bd_remove_timeout, softsp,
2701 bd_remove_timeout_hz);
2702 } else {
2703 DPRINTF(SYSCTRL_ATTACH_DEBUG,
2704 ("bd_remove_poll ignoring start request"));
2705 }
2706 }
2707
2708 /*
2709 * bd_insert_timeout()
2710 *
2711 * This routine handles the board insert interrupt. It is called from a
2712 * timeout so that it does not run at interrupt level. The main job
2713 * of this routine is to find hotplugged boards and de-assert the
2714 * board insert interrupt coming from the board. For hotplug phase I,
2715 * the routine also powers down the board.
2716 * JTAG scan is used to find boards which have been inserted.
2717 * All other control of the boards is also done by JTAG scan.
2718 */
2719 static void
bd_insert_timeout(void * arg)2720 bd_insert_timeout(void *arg)
2721 {
2722 struct sysctrl_soft_state *softsp = arg;
2723 int found;
2724
2725 ASSERT(softsp);
2726
2727 if (sysctrl_hotplug_disabled) {
2728 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_HP_DISABLED);
2729 } else {
2730 /*
2731 * Lock the board list mutex. Keep it locked until all work
2732 * is done.
2733 */
2734 (void) fhc_bdlist_lock(-1);
2735
2736 found = fhc_bd_insert_scan();
2737
2738 if (found) {
2739 DPRINTF(SYSCTRL_ATTACH_DEBUG,
2740 ("bd_insert_timeout starting bd_remove_poll()"));
2741 bd_remove_poll(softsp);
2742 }
2743
2744 fhc_bdlist_unlock();
2745 }
2746
2747 /*
2748 * Enable interrupts.
2749 */
2750 ddi_trigger_softintr(softsp->sbrd_gone_id);
2751 }
2752
2753 static void
bd_remove_timeout(void * arg)2754 bd_remove_timeout(void *arg)
2755 {
2756 struct sysctrl_soft_state *softsp = arg;
2757 int keep_polling;
2758
2759 ASSERT(softsp);
2760
2761 /*
2762 * Lock the board list mutex. Keep it locked until all work
2763 * is done.
2764 */
2765 (void) fhc_bdlist_lock(-1);
2766
2767 bd_remove_to_id = 0; /* delete our timeout ID */
2768
2769 keep_polling = fhc_bd_remove_scan();
2770
2771 if (keep_polling) {
2772 bd_remove_poll(softsp);
2773 } else {
2774 DPRINTF(SYSCTRL_ATTACH_DEBUG, ("exiting bd_remove_poll."));
2775 }
2776
2777 fhc_bdlist_unlock();
2778 }
2779
2780 static uint_t
bd_insert_normal(caddr_t arg)2781 bd_insert_normal(caddr_t arg)
2782 {
2783 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2784 uchar_t tmp_reg;
2785
2786 ASSERT(softsp);
2787
2788 /* has the condition been removed? */
2789 /* XXX add deglitch state machine here */
2790 if (!(*(softsp->status1) & SYS_NOT_BRD_PRES)) {
2791 /* check again in a few */
2792 (void) timeout(bd_insert_timeout, softsp, bd_insert_retry_hz);
2793 } else {
2794 /* Turn on the enable bit for this interrupt */
2795 mutex_enter(&softsp->csr_mutex);
2796 *(softsp->csr) |= SYS_SBRD_PRES_EN;
2797 /* flush the hardware store buffer */
2798 tmp_reg = *(softsp->csr);
2799 #ifdef lint
2800 tmp_reg = tmp_reg;
2801 #endif
2802 mutex_exit(&softsp->csr_mutex);
2803 }
2804
2805 return (DDI_INTR_CLAIMED);
2806 }
2807
2808 /*
2809 * blink LED handler.
2810 *
2811 * The actual bit manipulation needs to occur at interrupt level
2812 * because we need access to the CSR with its CSR mutex
2813 */
2814 static uint_t
blink_led_handler(caddr_t arg)2815 blink_led_handler(caddr_t arg)
2816 {
2817 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2818 uchar_t tmp_reg;
2819
2820 ASSERT(softsp);
2821
2822 mutex_enter(&softsp->csr_mutex);
2823
2824 /*
2825 * XXX - The lock for the sys_led is not held here. If more
2826 * complicated tasks are done with the System LED, then
2827 * locking should be done here.
2828 */
2829
2830 /* read the hardware register. */
2831 tmp_reg = *(softsp->csr);
2832
2833 /* Only turn on the OS System LED bit if the softsp state is on. */
2834 if (softsp->sys_led) {
2835 tmp_reg |= SYS_LED_RIGHT;
2836 } else {
2837 tmp_reg &= ~SYS_LED_RIGHT;
2838 }
2839
2840 /* Turn on the yellow LED if system fault status is set. */
2841 if (softsp->sys_fault) {
2842 tmp_reg |= SYS_LED_MID;
2843 } else {
2844 tmp_reg &= ~SYS_LED_MID;
2845 }
2846
2847 /* write to the hardware register */
2848 *(softsp->csr) = tmp_reg;
2849
2850 /* flush the hardware store buffer */
2851 tmp_reg = *(softsp->csr);
2852 #ifdef lint
2853 tmp_reg = tmp_reg;
2854 #endif
2855 mutex_exit(&softsp->csr_mutex);
2856
2857 (void) timeout(blink_led_timeout, softsp, blink_led_timeout_hz);
2858
2859 return (DDI_INTR_CLAIMED);
2860 }
2861
2862 /*
2863 * simply re-trigger the interrupt handler on led timeout
2864 */
2865 static void
blink_led_timeout(void * arg)2866 blink_led_timeout(void *arg)
2867 {
2868 struct sysctrl_soft_state *softsp = arg;
2869 int led_state;
2870
2871 ASSERT(softsp);
2872
2873 /*
2874 * Process the system fault list here. This is where the driver
2875 * must decide what yellow LEDs to turn on if any. The fault
2876 * list is walked and each fhc_list entry is updated with it's
2877 * yellow LED status. This info is used later by the routine
2878 * toggle_board_green_leds().
2879 *
2880 * The variable system_fault is non-zero if any non-
2881 * suppressed faults are found in the system.
2882 */
2883 softsp->sys_fault = process_fault_list();
2884
2885 /* blink the system board OS LED */
2886 mutex_enter(&softsp->sys_led_lock);
2887 softsp->sys_led = !softsp->sys_led;
2888 led_state = softsp->sys_led;
2889 mutex_exit(&softsp->sys_led_lock);
2890
2891 toggle_board_green_leds(led_state);
2892
2893 ddi_trigger_softintr(softsp->blink_led_id);
2894 }
2895
2896 void
toggle_board_green_leds(int led_state)2897 toggle_board_green_leds(int led_state)
2898 {
2899 fhc_bd_t *list;
2900
2901 (void) fhc_bdlist_lock(-1);
2902 for (list = fhc_bd_first(); list; list = fhc_bd_next(list)) {
2903 uint_t value = 0;
2904
2905 if (list->sc.in_transition ||
2906 (list->sc.rstate != SYSC_CFGA_RSTATE_CONNECTED))
2907 continue;
2908
2909 ASSERT(list->sc.type != CLOCK_BOARD);
2910 ASSERT(list->sc.type != DISK_BOARD);
2911 ASSERT(list->softsp);
2912
2913 if ((list->sc.ostate == SYSC_CFGA_OSTATE_CONFIGURED) &&
2914 led_state)
2915 value |= FHC_LED_RIGHT;
2916
2917 if (list->fault)
2918 value |= FHC_LED_MID;
2919 else
2920 value &= ~FHC_LED_MID;
2921
2922 update_board_leds(list, FHC_LED_RIGHT|FHC_LED_MID, value);
2923 }
2924 fhc_bdlist_unlock();
2925 }
2926
2927 /*
2928 * timestamp an AC power failure in nvram
2929 */
2930 static void
nvram_update_powerfail(struct sysctrl_soft_state * softsp)2931 nvram_update_powerfail(struct sysctrl_soft_state *softsp)
2932 {
2933 char buf[80];
2934 int len = 0;
2935
2936 numtos(gethrestime_sec(), buf);
2937
2938 if (softsp->options_nodeid) {
2939 len = prom_setprop(softsp->options_nodeid, "powerfail-time",
2940 buf, strlen(buf)+1);
2941 }
2942
2943 if (len <= 0) {
2944 cmn_err(CE_WARN, "sysctrl%d: failed to set powerfail-time "
2945 "to %s\n", ddi_get_instance(softsp->dip), buf);
2946 }
2947 }
2948
2949 void
sysctrl_add_kstats(struct sysctrl_soft_state * softsp)2950 sysctrl_add_kstats(struct sysctrl_soft_state *softsp)
2951 {
2952 struct kstat *ksp; /* Generic sysctrl kstats */
2953 struct kstat *pksp; /* Power Supply kstat */
2954 struct kstat *tksp; /* Sysctrl temperatrure kstat */
2955 struct kstat *ttsp; /* Sysctrl temperature test kstat */
2956
2957 if ((ksp = kstat_create("unix", ddi_get_instance(softsp->dip),
2958 SYSCTRL_KSTAT_NAME, "misc", KSTAT_TYPE_NAMED,
2959 sizeof (struct sysctrl_kstat) / sizeof (kstat_named_t),
2960 KSTAT_FLAG_PERSISTENT)) == NULL) {
2961 cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
2962 ddi_get_instance(softsp->dip));
2963 } else {
2964 struct sysctrl_kstat *sysksp;
2965
2966 sysksp = (struct sysctrl_kstat *)(ksp->ks_data);
2967
2968 /* now init the named kstats */
2969 kstat_named_init(&sysksp->csr, CSR_KSTAT_NAMED,
2970 KSTAT_DATA_CHAR);
2971
2972 kstat_named_init(&sysksp->status1, STAT1_KSTAT_NAMED,
2973 KSTAT_DATA_CHAR);
2974
2975 kstat_named_init(&sysksp->status2, STAT2_KSTAT_NAMED,
2976 KSTAT_DATA_CHAR);
2977
2978 kstat_named_init(&sysksp->clk_freq2, CLK_FREQ2_KSTAT_NAMED,
2979 KSTAT_DATA_CHAR);
2980
2981 kstat_named_init(&sysksp->fan_status, FAN_KSTAT_NAMED,
2982 KSTAT_DATA_CHAR);
2983
2984 kstat_named_init(&sysksp->key_status, KEY_KSTAT_NAMED,
2985 KSTAT_DATA_CHAR);
2986
2987 kstat_named_init(&sysksp->power_state, POWER_KSTAT_NAMED,
2988 KSTAT_DATA_INT32);
2989
2990 kstat_named_init(&sysksp->clk_ver, CLK_VER_KSTAT_NAME,
2991 KSTAT_DATA_CHAR);
2992
2993 ksp->ks_update = sysctrl_kstat_update;
2994 ksp->ks_private = (void *)softsp;
2995 kstat_install(ksp);
2996 }
2997
2998 if ((tksp = kstat_create("unix", CLOCK_BOARD_INDEX,
2999 OVERTEMP_KSTAT_NAME, "misc", KSTAT_TYPE_RAW,
3000 sizeof (struct temp_stats), KSTAT_FLAG_PERSISTENT)) == NULL) {
3001 cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
3002 ddi_get_instance(softsp->dip));
3003 } else {
3004 tksp->ks_update = overtemp_kstat_update;
3005 tksp->ks_private = (void *)&softsp->tempstat;
3006 kstat_install(tksp);
3007 }
3008
3009 if ((ttsp = kstat_create("unix", CLOCK_BOARD_INDEX,
3010 TEMP_OVERRIDE_KSTAT_NAME, "misc", KSTAT_TYPE_RAW, sizeof (short),
3011 KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) == NULL) {
3012 cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
3013 ddi_get_instance(softsp->dip));
3014 } else {
3015 ttsp->ks_update = temp_override_kstat_update;
3016 ttsp->ks_private = (void *)&softsp->tempstat.override;
3017 kstat_install(ttsp);
3018 }
3019
3020 if ((pksp = kstat_create("unix", ddi_get_instance(softsp->dip),
3021 PSSHAD_KSTAT_NAME, "misc", KSTAT_TYPE_RAW,
3022 SYS_PS_COUNT, KSTAT_FLAG_PERSISTENT)) == NULL) {
3023 cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
3024 ddi_get_instance(softsp->dip));
3025 } else {
3026 pksp->ks_update = psstat_kstat_update;
3027 pksp->ks_private = (void *)softsp;
3028 kstat_install(pksp);
3029 }
3030 }
3031
3032 static int
sysctrl_kstat_update(kstat_t * ksp,int rw)3033 sysctrl_kstat_update(kstat_t *ksp, int rw)
3034 {
3035 struct sysctrl_kstat *sysksp;
3036 struct sysctrl_soft_state *softsp;
3037
3038 sysksp = (struct sysctrl_kstat *)(ksp->ks_data);
3039 softsp = (struct sysctrl_soft_state *)(ksp->ks_private);
3040
3041 /* this is a read-only kstat. Exit on a write */
3042
3043 if (rw == KSTAT_WRITE) {
3044 return (EACCES);
3045 } else {
3046 /*
3047 * copy the current state of the hardware into the
3048 * kstat structure.
3049 */
3050 sysksp->csr.value.c[0] = *(softsp->csr);
3051 sysksp->status1.value.c[0] = *(softsp->status1);
3052 sysksp->status2.value.c[0] = *(softsp->status2);
3053 sysksp->clk_freq2.value.c[0] = *(softsp->clk_freq2);
3054
3055 sysksp->fan_status.value.c[0] = softsp->pps_fan_external_state;
3056 sysksp->key_status.value.c[0] = softsp->key_shadow;
3057 sysksp->power_state.value.i32 = softsp->power_state;
3058
3059 /*
3060 * non-existence of the clock version register returns the
3061 * value 0xff when the hardware register location is read
3062 */
3063 if (softsp->clk_ver != NULL)
3064 sysksp->clk_ver.value.c[0] = *(softsp->clk_ver);
3065 else
3066 sysksp->clk_ver.value.c[0] = (char)0xff;
3067 }
3068 return (0);
3069 }
3070
3071 static int
psstat_kstat_update(kstat_t * ksp,int rw)3072 psstat_kstat_update(kstat_t *ksp, int rw)
3073 {
3074 struct sysctrl_soft_state *softsp;
3075 uchar_t *ptr = (uchar_t *)(ksp->ks_data);
3076 int ps;
3077
3078 softsp = (struct sysctrl_soft_state *)(ksp->ks_private);
3079
3080 if (rw == KSTAT_WRITE) {
3081 return (EACCES);
3082 } else {
3083 for (ps = 0; ps < SYS_PS_COUNT; ps++) {
3084 *ptr++ = softsp->ps_stats[ps].dcshadow;
3085 }
3086 }
3087 return (0);
3088 }
3089
3090 static void
sysctrl_thread_wakeup(void * arg)3091 sysctrl_thread_wakeup(void *arg)
3092 {
3093 int type = (int)(uintptr_t)arg;
3094
3095 /*
3096 * grab mutex to guarantee that our wakeup call
3097 * arrives after we go to sleep -- so we can't sleep forever.
3098 */
3099 mutex_enter(&sslist_mutex);
3100 switch (type) {
3101 case OVERTEMP_POLL:
3102 cv_signal(&overtemp_cv);
3103 break;
3104 case KEYSWITCH_POLL:
3105 cv_signal(&keyswitch_cv);
3106 break;
3107 default:
3108 cmn_err(CE_WARN, "sysctrl: invalid type %d to wakeup\n", type);
3109 break;
3110 }
3111 mutex_exit(&sslist_mutex);
3112 }
3113
3114 static void
sysctrl_overtemp_poll(void)3115 sysctrl_overtemp_poll(void)
3116 {
3117 struct sysctrl_soft_state *list;
3118 callb_cpr_t cprinfo;
3119
3120 CALLB_CPR_INIT(&cprinfo, &sslist_mutex, callb_generic_cpr, "overtemp");
3121
3122 /* The overtemp data structures are protected by a mutex. */
3123 mutex_enter(&sslist_mutex);
3124
3125 while (sysctrl_do_overtemp_thread) {
3126
3127 for (list = sys_list; list != NULL; list = list->next) {
3128 if (list->temp_reg != NULL) {
3129 update_temp(list->pdip, &list->tempstat,
3130 *(list->temp_reg));
3131 }
3132 }
3133
3134 CALLB_CPR_SAFE_BEGIN(&cprinfo);
3135
3136 /* now have this thread sleep for a while */
3137 (void) timeout(sysctrl_thread_wakeup, (void *)OVERTEMP_POLL,
3138 overtemp_timeout_hz);
3139
3140 cv_wait(&overtemp_cv, &sslist_mutex);
3141
3142 CALLB_CPR_SAFE_END(&cprinfo, &sslist_mutex);
3143 }
3144 CALLB_CPR_EXIT(&cprinfo);
3145 thread_exit();
3146 /* NOTREACHED */
3147 }
3148
3149 static void
sysctrl_keyswitch_poll(void)3150 sysctrl_keyswitch_poll(void)
3151 {
3152 struct sysctrl_soft_state *list;
3153 callb_cpr_t cprinfo;
3154
3155 CALLB_CPR_INIT(&cprinfo, &sslist_mutex, callb_generic_cpr, "keyswitch");
3156
3157 /* The keyswitch data strcutures are protected by a mutex. */
3158 mutex_enter(&sslist_mutex);
3159
3160 while (sysctrl_do_keyswitch_thread) {
3161
3162 for (list = sys_list; list != NULL; list = list->next) {
3163 if (list->status1 != NULL)
3164 update_key_state(list);
3165 }
3166
3167 CALLB_CPR_SAFE_BEGIN(&cprinfo);
3168
3169 /* now have this thread sleep for a while */
3170 (void) timeout(sysctrl_thread_wakeup, (void *)KEYSWITCH_POLL,
3171 keyswitch_timeout_hz);
3172
3173 cv_wait(&keyswitch_cv, &sslist_mutex);
3174
3175 CALLB_CPR_SAFE_END(&cprinfo, &sslist_mutex);
3176 }
3177 CALLB_CPR_EXIT(&cprinfo);
3178 thread_exit();
3179 /* NOTREACHED */
3180 }
3181
3182 /*
3183 * check the key switch position for state changes
3184 */
3185 static void
update_key_state(struct sysctrl_soft_state * list)3186 update_key_state(struct sysctrl_soft_state *list)
3187 {
3188 enum keyswitch_state key;
3189
3190 /*
3191 * snapshot current hardware key position
3192 */
3193 if (*(list->status1) & SYS_NOT_SECURE)
3194 key = KEY_NOT_SECURE;
3195 else
3196 key = KEY_SECURE;
3197
3198 /*
3199 * check for state transition
3200 */
3201 if (key != list->key_shadow) {
3202
3203 /*
3204 * handle state transition
3205 */
3206 switch (list->key_shadow) {
3207 case KEY_BOOT:
3208 cmn_err(CE_CONT, "?sysctrl%d: Key switch is%sin the "
3209 "secure position\n", ddi_get_instance(list->dip),
3210 (key == KEY_SECURE) ? " " : " not ");
3211 list->key_shadow = key;
3212 break;
3213 case KEY_SECURE:
3214 case KEY_NOT_SECURE:
3215 cmn_err(CE_NOTE, "sysctrl%d: Key switch has changed"
3216 " to the %s position",
3217 ddi_get_instance(list->dip),
3218 (key == KEY_SECURE) ? "secure" : "not-secure");
3219 list->key_shadow = key;
3220 break;
3221 default:
3222 cmn_err(CE_CONT,
3223 "?sysctrl%d: Key switch is in an unknown position,"
3224 "treated as being in the %s position\n",
3225 ddi_get_instance(list->dip),
3226 (list->key_shadow == KEY_SECURE) ?
3227 "secure" : "not-secure");
3228 break;
3229 }
3230 }
3231 }
3232
3233 /*
3234 * consider key switch position when handling an abort sequence
3235 */
3236 static void
sysctrl_abort_seq_handler(char * msg)3237 sysctrl_abort_seq_handler(char *msg)
3238 {
3239 struct sysctrl_soft_state *list;
3240 uint_t secure = 0;
3241 char buf[64], inst[4];
3242
3243
3244 /*
3245 * if any of the key switch positions are secure,
3246 * then disallow entry to the prom/debugger
3247 */
3248 mutex_enter(&sslist_mutex);
3249 buf[0] = (char)0;
3250 for (list = sys_list; list != NULL; list = list->next) {
3251 if (!(*(list->status1) & SYS_NOT_SECURE)) {
3252 if (secure++)
3253 (void) strcat(buf, ",");
3254 /*
3255 * XXX: later, replace instance number with nodeid
3256 */
3257 (void) sprintf(inst, "%d", ddi_get_instance(list->dip));
3258 (void) strcat(buf, inst);
3259 }
3260 }
3261 mutex_exit(&sslist_mutex);
3262
3263 if (secure) {
3264 cmn_err(CE_CONT,
3265 "!sysctrl(%s): ignoring debug enter sequence\n", buf);
3266 } else {
3267 cmn_err(CE_CONT, "!sysctrl: allowing debug enter\n");
3268 debug_enter(msg);
3269 }
3270 }
3271
3272 #define TABLE_END 0xFF
3273
3274 struct uart_cmd {
3275 uchar_t reg;
3276 uchar_t data;
3277 };
3278
3279 /*
3280 * Time constant defined by this formula:
3281 * ((4915200/32)/(baud) -2)
3282 */
3283
3284 struct uart_cmd uart_table[] = {
3285 { 0x09, 0xc0 }, /* Force hardware reset */
3286 { 0x04, 0x46 }, /* X16 clock mode, 1 stop bit/char, no parity */
3287 { 0x03, 0xc0 }, /* Rx is 8 bits/char */
3288 { 0x05, 0xe2 }, /* DTR, Tx is 8 bits/char, RTS */
3289 { 0x09, 0x02 }, /* No vector returned on interrupt */
3290 { 0x0b, 0x55 }, /* Rx Clock = Tx Clock = BR generator = ~TRxC OUT */
3291 { 0x0c, 0x0e }, /* Time Constant = 0x000e for 9600 baud */
3292 { 0x0d, 0x00 }, /* High byte of time constant */
3293 { 0x0e, 0x02 }, /* BR generator comes from Z-SCC's PCLK input */
3294 { 0x03, 0xc1 }, /* Rx is 8 bits/char, Rx is enabled */
3295 { 0x05, 0xea }, /* DTR, Tx is 8 bits/char, Tx is enabled, RTS */
3296 { 0x0e, 0x03 }, /* BR comes from PCLK, BR generator is enabled */
3297 { 0x00, 0x30 }, /* Error reset */
3298 { 0x00, 0x30 }, /* Error reset */
3299 { 0x00, 0x10 }, /* external status reset */
3300 { 0x03, 0xc1 }, /* Rx is 8 bits/char, Rx is enabled */
3301 { TABLE_END, 0x0 }
3302 };
3303
3304 static void
init_remote_console_uart(struct sysctrl_soft_state * softsp)3305 init_remote_console_uart(struct sysctrl_soft_state *softsp)
3306 {
3307 int i = 0;
3308
3309 /*
3310 * Serial chip expects software to write to the control
3311 * register first with the desired register number. Then
3312 * write to the control register with the desired data.
3313 * So walk thru table writing the register/data pairs to
3314 * the serial port chip.
3315 */
3316 while (uart_table[i].reg != TABLE_END) {
3317 *(softsp->rcons_ctl) = uart_table[i].reg;
3318 *(softsp->rcons_ctl) = uart_table[i].data;
3319 i++;
3320 }
3321 }
3322
3323 /*
3324 * return the slot information of the system
3325 *
3326 * function take a sysctrl_soft_state, so it's ready for sunfire+
3327 * change which requires 2 registers to decide the system type.
3328 */
3329 static void
sysc_slot_info(int nslots,int * start,int * limit,int * incr)3330 sysc_slot_info(int nslots, int *start, int *limit, int *incr)
3331 {
3332 switch (nslots) {
3333 case 8:
3334 *start = 0;
3335 *limit = 8;
3336 *incr = 1;
3337 break;
3338 case 5:
3339 *start = 1;
3340 *limit = 10;
3341 *incr = 2;
3342 break;
3343 case 4:
3344 *start = 1;
3345 *limit = 8;
3346 *incr = 2;
3347 break;
3348 case 0:
3349 case 16:
3350 default:
3351 *start = 0;
3352 *limit = 16;
3353 *incr = 1;
3354 break;
3355 }
3356 }
3357
3358 /*
3359 * reinitialize the Remote Console on the clock board
3360 *
3361 * with V5_AUX power outage the Remote Console ends up in
3362 * unknown state and has to be reinitilized if it was enabled
3363 * initially.
3364 */
3365 static void
rcons_reinit(struct sysctrl_soft_state * softsp)3366 rcons_reinit(struct sysctrl_soft_state *softsp)
3367 {
3368 uchar_t tmp_reg;
3369
3370 if (!(softsp->rcons_ctl))
3371 /*
3372 * There is no OBP register set for the remote console UART,
3373 * so offset from the last register set, the misc register
3374 * set, in order to map in the remote console UART.
3375 */
3376 if (ddi_map_regs(softsp->dip, 1, (caddr_t *)&softsp->rcons_ctl,
3377 RMT_CONS_OFFSET, RMT_CONS_LEN)) {
3378 cmn_err(CE_WARN, "Unable to reinitialize "
3379 "remote console.");
3380 return;
3381 }
3382
3383
3384 /* Disable the remote console reset control bits. */
3385 *(softsp->clk_freq2) &= ~RCONS_UART_EN;
3386
3387 /* flush the hardware buffers */
3388 tmp_reg = *(softsp->csr);
3389
3390 /*
3391 * Program the UART to watch ttya console.
3392 */
3393 init_remote_console_uart(softsp);
3394
3395 /* Now enable the remote console reset control bits. */
3396 *(softsp->clk_freq2) |= RCONS_UART_EN;
3397
3398 /* flush the hardware buffers */
3399 tmp_reg = *(softsp->csr);
3400
3401 /* print some info for user to watch */
3402 cmn_err(CE_NOTE, "Remote console reinitialized");
3403 #ifdef lint
3404 tmp_reg = tmp_reg;
3405 #endif
3406 }
3407