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