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