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