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