1*29949e86Sstevel /* 2*29949e86Sstevel * CDDL HEADER START 3*29949e86Sstevel * 4*29949e86Sstevel * The contents of this file are subject to the terms of the 5*29949e86Sstevel * Common Development and Distribution License (the "License"). 6*29949e86Sstevel * You may not use this file except in compliance with the License. 7*29949e86Sstevel * 8*29949e86Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*29949e86Sstevel * or http://www.opensolaris.org/os/licensing. 10*29949e86Sstevel * See the License for the specific language governing permissions 11*29949e86Sstevel * and limitations under the License. 12*29949e86Sstevel * 13*29949e86Sstevel * When distributing Covered Code, include this CDDL HEADER in each 14*29949e86Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*29949e86Sstevel * If applicable, add the following below this CDDL HEADER, with the 16*29949e86Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 17*29949e86Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 18*29949e86Sstevel * 19*29949e86Sstevel * CDDL HEADER END 20*29949e86Sstevel */ 21*29949e86Sstevel 22*29949e86Sstevel /* 23*29949e86Sstevel * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*29949e86Sstevel * Use is subject to license terms. 25*29949e86Sstevel */ 26*29949e86Sstevel 27*29949e86Sstevel #pragma ident "%Z%%M% %I% %E% SMI" 28*29949e86Sstevel 29*29949e86Sstevel #include <sys/types.h> 30*29949e86Sstevel #include <sys/conf.h> 31*29949e86Sstevel #include <sys/ddi.h> 32*29949e86Sstevel #include <sys/sunddi.h> 33*29949e86Sstevel #include <sys/sunndi.h> 34*29949e86Sstevel #include <sys/ddi_impldefs.h> 35*29949e86Sstevel #include <sys/ndi_impldefs.h> 36*29949e86Sstevel #include <sys/obpdefs.h> 37*29949e86Sstevel #include <sys/cmn_err.h> 38*29949e86Sstevel #include <sys/errno.h> 39*29949e86Sstevel #include <sys/kmem.h> 40*29949e86Sstevel #include <sys/debug.h> 41*29949e86Sstevel #include <sys/sysmacros.h> 42*29949e86Sstevel #include <sys/ivintr.h> 43*29949e86Sstevel #include <sys/autoconf.h> 44*29949e86Sstevel #include <sys/intreg.h> 45*29949e86Sstevel #include <sys/proc.h> 46*29949e86Sstevel #include <sys/machsystm.h> 47*29949e86Sstevel #include <sys/modctl.h> 48*29949e86Sstevel #include <sys/callb.h> 49*29949e86Sstevel #include <sys/file.h> 50*29949e86Sstevel #include <sys/open.h> 51*29949e86Sstevel #include <sys/stat.h> 52*29949e86Sstevel #include <sys/fhc.h> 53*29949e86Sstevel #include <sys/sysctrl.h> 54*29949e86Sstevel #include <sys/jtag.h> 55*29949e86Sstevel #include <sys/ac.h> 56*29949e86Sstevel #include <sys/simmstat.h> 57*29949e86Sstevel #include <sys/clock.h> 58*29949e86Sstevel #include <sys/promif.h> 59*29949e86Sstevel #include <sys/promimpl.h> 60*29949e86Sstevel #include <sys/cpr.h> 61*29949e86Sstevel #include <sys/cpuvar.h> 62*29949e86Sstevel #include <sys/machcpuvar.h> 63*29949e86Sstevel #include <sys/x_call.h> 64*29949e86Sstevel 65*29949e86Sstevel #ifdef DEBUG 66*29949e86Sstevel struct regs_data { 67*29949e86Sstevel caddr_t msg; 68*29949e86Sstevel u_longlong_t physaddr; 69*29949e86Sstevel uint_t pre_dsct; 70*29949e86Sstevel uint_t post_dsct; 71*29949e86Sstevel uint_t eflag; 72*29949e86Sstevel uint_t oflag; 73*29949e86Sstevel }; 74*29949e86Sstevel 75*29949e86Sstevel static struct regs_data reg_tmpl[] = { 76*29949e86Sstevel "AC Control and Status reg = 0x", AC_BCSR(0), 0, 0, 0, 0, 77*29949e86Sstevel "FHC Control and Status reg = 0x", FHC_CTRL(0), 0, 0, 0, 0, 78*29949e86Sstevel "JTAG Control reg = 0x", FHC_JTAG_CTRL(0), 0, 0, 0, 0, 79*29949e86Sstevel "Interrupt Group Number reg = 0x", FHC_IGN(0), 0, 0, 0, 0, 80*29949e86Sstevel "System Interrupt Mapping reg = 0x", FHC_SIM(0), 0, 0, 0, 0, 81*29949e86Sstevel "System Interrupt State reg = 0x", FHC_SSM(0), 0, 0, 0, 0, 82*29949e86Sstevel "UART Interrupt Mapping reg = 0x", FHC_UIM(0), 0, 0, 0, 0, 83*29949e86Sstevel "UART Interrupt State reg = 0x", FHC_USM(0), 0, 0, 0, 0 84*29949e86Sstevel }; 85*29949e86Sstevel 86*29949e86Sstevel #define NUM_REG (sizeof (reg_tmpl)/sizeof (reg_tmpl[0])) 87*29949e86Sstevel static struct regs_data reg_dt[MAX_BOARDS][NUM_REG]; 88*29949e86Sstevel 89*29949e86Sstevel int sysctrl_enable_regdump = 0; 90*29949e86Sstevel 91*29949e86Sstevel static void precache_regdump(int board); 92*29949e86Sstevel static void display_regdump(void); 93*29949e86Sstevel static void boardstat_regdump(void); 94*29949e86Sstevel 95*29949e86Sstevel #endif /* DEBUG */ 96*29949e86Sstevel 97*29949e86Sstevel extern void bd_remove_poll(struct sysctrl_soft_state *); 98*29949e86Sstevel extern int sysctrl_getsystem_freq(void); 99*29949e86Sstevel extern enum power_state compute_power_state(struct sysctrl_soft_state *, int); 100*29949e86Sstevel extern enum temp_state fhc_env_temp_state(int); 101*29949e86Sstevel extern int sysctrl_hotplug_disabled; 102*29949e86Sstevel /* Let user disable Sunfire Dynamic Reconfiguration */ 103*29949e86Sstevel int enable_dynamic_reconfiguration = 1; 104*29949e86Sstevel 105*29949e86Sstevel int enable_redist = 1; 106*29949e86Sstevel 107*29949e86Sstevel static void sysc_dr_err_decode(sysc_dr_handle_t *, dev_info_t *, int); 108*29949e86Sstevel static uint_t 109*29949e86Sstevel sysc_policy_enough_cooling(struct sysctrl_soft_state *softsp, 110*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t ps_mutex_is_held); 111*29949e86Sstevel static uint_t 112*29949e86Sstevel sysc_policy_enough_precharge(struct sysctrl_soft_state *softsp, 113*29949e86Sstevel sysc_cfga_stat_t *sysc_stat); 114*29949e86Sstevel static uint_t 115*29949e86Sstevel sysc_policy_enough_power(struct sysctrl_soft_state *softsp, 116*29949e86Sstevel int plus_load, uint_t ps_mutex_is_held); 117*29949e86Sstevel static uint_t 118*29949e86Sstevel sysc_policy_hardware_compatible(struct sysctrl_soft_state *softsp, 119*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, sysc_cfga_pkt_t *pkt); 120*29949e86Sstevel static void sysc_policy_empty_condition( 121*29949e86Sstevel struct sysctrl_soft_state *softsp, 122*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t failure, 123*29949e86Sstevel uint_t ps_mutex_is_held); 124*29949e86Sstevel static void sysc_policy_disconnected_condition( 125*29949e86Sstevel struct sysctrl_soft_state *softsp, 126*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t failure, 127*29949e86Sstevel uint_t ps_mutex_is_held); 128*29949e86Sstevel static void sysc_policy_connected_condition(struct sysctrl_soft_state *softsp, 129*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, 130*29949e86Sstevel uint_t ps_mutex_is_held); 131*29949e86Sstevel static void sysc_policy_set_condition(void *sp, sysc_cfga_stat_t *sysc_stat, 132*29949e86Sstevel uint_t ps_mutex_is_held); 133*29949e86Sstevel static void sysc_policy_audit_messages(sysc_audit_evt_t event, 134*29949e86Sstevel sysc_cfga_stat_t *sysc_stat); 135*29949e86Sstevel 136*29949e86Sstevel static void sysctrl_post_config_change(struct sysctrl_soft_state *softsp); 137*29949e86Sstevel static int sysc_bd_connect(int, sysc_cfga_pkt_t *); 138*29949e86Sstevel static int sysc_bd_disconnect(int, sysc_cfga_pkt_t *); 139*29949e86Sstevel static int sysc_bd_configure(int, sysc_cfga_pkt_t *); 140*29949e86Sstevel static int sysc_bd_unconfigure(int, sysc_cfga_pkt_t *); 141*29949e86Sstevel 142*29949e86Sstevel static void sysc_dr_init(sysc_dr_handle_t *handle); 143*29949e86Sstevel static void sysc_dr_uninit(sysc_dr_handle_t *handle); 144*29949e86Sstevel static int sysc_dr_attach(sysc_dr_handle_t *handle, int board); 145*29949e86Sstevel static int sysc_dr_detach(sysc_dr_handle_t *handle, int board); 146*29949e86Sstevel 147*29949e86Sstevel static int sysc_prom_select(pnode_t pnode, void *arg, uint_t flag); 148*29949e86Sstevel static void sysc_branch_callback(dev_info_t *rdip, void *arg, uint_t flags); 149*29949e86Sstevel 150*29949e86Sstevel static int find_and_setup_cpu(int); 151*29949e86Sstevel 152*29949e86Sstevel static int sysc_board_connect_supported(enum board_type); 153*29949e86Sstevel 154*29949e86Sstevel static int find_and_setup_cpu_start(void *cpuid_arg, int has_changed); 155*29949e86Sstevel /* 156*29949e86Sstevel * This function will basically do a prediction on the power state 157*29949e86Sstevel * based on adding one additional load to the equation implemented 158*29949e86Sstevel * by the function compute_power_state. 159*29949e86Sstevel */ 160*29949e86Sstevel /*ARGSUSED*/ 161*29949e86Sstevel static uint_t 162*29949e86Sstevel sysc_policy_enough_power(struct sysctrl_soft_state *softsp, 163*29949e86Sstevel int plus_load, uint_t ps_mutex_is_held) 164*29949e86Sstevel { 165*29949e86Sstevel int retval = 0; 166*29949e86Sstevel 167*29949e86Sstevel ASSERT(softsp); 168*29949e86Sstevel 169*29949e86Sstevel if (!ps_mutex_is_held) { 170*29949e86Sstevel mutex_enter(&softsp->ps_fail_lock); 171*29949e86Sstevel } 172*29949e86Sstevel 173*29949e86Sstevel /* 174*29949e86Sstevel * note that we add one more load 175*29949e86Sstevel * to the equation in compute_power_state 176*29949e86Sstevel * and the answer better be REDUNDANT or 177*29949e86Sstevel * MINIMUM before proceeding. 178*29949e86Sstevel */ 179*29949e86Sstevel switch (compute_power_state(softsp, plus_load)) { 180*29949e86Sstevel case REDUNDANT: 181*29949e86Sstevel case MINIMUM: 182*29949e86Sstevel retval = 1; 183*29949e86Sstevel break; 184*29949e86Sstevel case BELOW_MINIMUM: 185*29949e86Sstevel default: 186*29949e86Sstevel break; 187*29949e86Sstevel } 188*29949e86Sstevel 189*29949e86Sstevel if (!ps_mutex_is_held) { 190*29949e86Sstevel mutex_exit(&softsp->ps_fail_lock); 191*29949e86Sstevel } 192*29949e86Sstevel return (retval); 193*29949e86Sstevel } 194*29949e86Sstevel 195*29949e86Sstevel /* 196*29949e86Sstevel * This function gropes through the shadow registers in the sysctrl soft_state 197*29949e86Sstevel * for the core power supply status, since fan status for them are ORed into 198*29949e86Sstevel * the same status bit, and all other remaining fans. 199*29949e86Sstevel */ 200*29949e86Sstevel static uint_t 201*29949e86Sstevel sysc_policy_enough_cooling(struct sysctrl_soft_state *softsp, 202*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t ps_mutex_is_held) 203*29949e86Sstevel { 204*29949e86Sstevel int retval = 0; 205*29949e86Sstevel 206*29949e86Sstevel if (!ps_mutex_is_held) { 207*29949e86Sstevel mutex_enter(&softsp->ps_fail_lock); 208*29949e86Sstevel } 209*29949e86Sstevel 210*29949e86Sstevel /* 211*29949e86Sstevel * check the power supply in the slot in question 212*29949e86Sstevel * for fans then check all the common fans. 213*29949e86Sstevel */ 214*29949e86Sstevel retval = ((softsp->ps_stats[FHC_BOARD2PS(sysc_stat->board)].pshadow == 215*29949e86Sstevel PRES_IN) && 216*29949e86Sstevel (softsp->ps_stats[FHC_BOARD2PS(sysc_stat->board)].dcshadow == 217*29949e86Sstevel PS_OK)); 218*29949e86Sstevel if (!ps_mutex_is_held) { 219*29949e86Sstevel mutex_exit(&softsp->ps_fail_lock); 220*29949e86Sstevel } 221*29949e86Sstevel return (retval); 222*29949e86Sstevel } 223*29949e86Sstevel 224*29949e86Sstevel /* 225*29949e86Sstevel * This function will check all precharge voltage status. 226*29949e86Sstevel */ 227*29949e86Sstevel /*ARGSUSED*/ 228*29949e86Sstevel static uint_t 229*29949e86Sstevel sysc_policy_enough_precharge(struct sysctrl_soft_state *softsp, 230*29949e86Sstevel sysc_cfga_stat_t *sysc_stat) 231*29949e86Sstevel { 232*29949e86Sstevel int retval = 0; 233*29949e86Sstevel int ppsval = 0; 234*29949e86Sstevel 235*29949e86Sstevel mutex_enter(&softsp->ps_fail_lock); 236*29949e86Sstevel 237*29949e86Sstevel /* 238*29949e86Sstevel * note that we always have to explicitly check 239*29949e86Sstevel * the peripheral power supply for precharge since it 240*29949e86Sstevel * supplies all of the precharge voltages. 241*29949e86Sstevel */ 242*29949e86Sstevel ppsval = (softsp->ps_stats[SYS_PPS0_INDEX].pshadow == PRES_IN) && 243*29949e86Sstevel (softsp->ps_stats[SYS_PPS0_INDEX].dcshadow == PS_OK); 244*29949e86Sstevel 245*29949e86Sstevel /* 246*29949e86Sstevel * check all the precharge status 247*29949e86Sstevel */ 248*29949e86Sstevel retval = ((softsp->ps_stats[SYS_V3_PCH_INDEX].pshadow == PRES_IN) && 249*29949e86Sstevel (softsp->ps_stats[SYS_V3_PCH_INDEX].dcshadow == PS_OK) && 250*29949e86Sstevel (softsp->ps_stats[SYS_V5_PCH_INDEX].pshadow == PRES_IN) && 251*29949e86Sstevel (softsp->ps_stats[SYS_V5_PCH_INDEX].dcshadow == PS_OK)); 252*29949e86Sstevel 253*29949e86Sstevel mutex_exit(&softsp->ps_fail_lock); 254*29949e86Sstevel return (retval&&ppsval); 255*29949e86Sstevel } 256*29949e86Sstevel 257*29949e86Sstevel static int Fsys; 258*29949e86Sstevel 259*29949e86Sstevel /* 260*29949e86Sstevel * This function should only be called once as we may 261*29949e86Sstevel * zero the clock board registers to indicate a configuration change. 262*29949e86Sstevel * The code to calculate the bus frequency has been removed and we 263*29949e86Sstevel * read the eeprom property instead. Another static Fmod (module 264*29949e86Sstevel * frequency may be needed later but so far it is commented out. 265*29949e86Sstevel */ 266*29949e86Sstevel void 267*29949e86Sstevel set_clockbrd_info(void) 268*29949e86Sstevel { 269*29949e86Sstevel uint_t clock_freq = 0; 270*29949e86Sstevel 271*29949e86Sstevel pnode_t root = prom_nextnode((pnode_t)0); 272*29949e86Sstevel (void) prom_getprop(root, "clock-frequency", (caddr_t)&clock_freq); 273*29949e86Sstevel Fsys = clock_freq / 1000000; 274*29949e86Sstevel } 275*29949e86Sstevel 276*29949e86Sstevel #define abs(x) ((x) < 0 ? -(x) : (x)) 277*29949e86Sstevel 278*29949e86Sstevel /*ARGSUSED*/ 279*29949e86Sstevel static uint_t 280*29949e86Sstevel sysc_policy_hardware_compatible(struct sysctrl_soft_state *softsp, 281*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, sysc_cfga_pkt_t *pkt) 282*29949e86Sstevel { 283*29949e86Sstevel int status; 284*29949e86Sstevel 285*29949e86Sstevel ASSERT(Fsys > 0); 286*29949e86Sstevel 287*29949e86Sstevel /* Only allow DR operations on supported hardware */ 288*29949e86Sstevel switch (sysc_stat->type) { 289*29949e86Sstevel case CPU_BOARD: { 290*29949e86Sstevel #ifdef RFE_4174486 291*29949e86Sstevel int i; 292*29949e86Sstevel int cpu_freq; 293*29949e86Sstevel int sram_mode; 294*29949e86Sstevel 295*29949e86Sstevel ASSERT(Fmod > 0); 296*29949e86Sstevel 297*29949e86Sstevel cpu_freq = CPU->cpu_type_info.pi_clock; 298*29949e86Sstevel 299*29949e86Sstevel if (abs(cpu_freq - Fmod) < 8) 300*29949e86Sstevel sram_mode = 1; 301*29949e86Sstevel else 302*29949e86Sstevel sram_mode = 2; 303*29949e86Sstevel 304*29949e86Sstevel status = TRUE; 305*29949e86Sstevel for (i = 0; i < 2; i++) { 306*29949e86Sstevel /* 307*29949e86Sstevel * XXX: Add jtag code which rescans disabled boards. 308*29949e86Sstevel * For the time being disabled boards are not 309*29949e86Sstevel * checked for compatibility when cpu_speed is 0. 310*29949e86Sstevel */ 311*29949e86Sstevel if (sysc_stat->bd.cpu[i].cpu_speed == 0) 312*29949e86Sstevel continue; 313*29949e86Sstevel 314*29949e86Sstevel if (sysc_stat->bd.cpu[i].cpu_speed < cpu_freq) { 315*29949e86Sstevel cmn_err(CE_WARN, "board %d, cpu module %c " 316*29949e86Sstevel "rated at %d Mhz, system freq %d Mhz", 317*29949e86Sstevel sysc_stat->board, (i == 0) ? 'A' : 'B', 318*29949e86Sstevel sysc_stat->bd.cpu[i].cpu_speed, 319*29949e86Sstevel cpu_freq); 320*29949e86Sstevel status = FALSE; 321*29949e86Sstevel } 322*29949e86Sstevel 323*29949e86Sstevel if (sram_mode != sysc_stat->bd.cpu[i].cpu_sram_mode) { 324*29949e86Sstevel cmn_err(CE_WARN, "board %d, cpu module %c " 325*29949e86Sstevel "incompatible sram mode of %dx, " 326*29949e86Sstevel "system is %dx", sysc_stat->board, 327*29949e86Sstevel (i == 0) ? 'A' : 'B', 328*29949e86Sstevel sysc_stat->bd.cpu[i].cpu_sram_mode, 329*29949e86Sstevel sram_mode); 330*29949e86Sstevel status = FALSE; 331*29949e86Sstevel } 332*29949e86Sstevel } 333*29949e86Sstevel break; 334*29949e86Sstevel #endif /* RFE_4174486 */ 335*29949e86Sstevel } 336*29949e86Sstevel 337*29949e86Sstevel case MEM_BOARD: 338*29949e86Sstevel case IO_2SBUS_BOARD: 339*29949e86Sstevel case IO_SBUS_FFB_BOARD: 340*29949e86Sstevel case IO_PCI_BOARD: 341*29949e86Sstevel case IO_2SBUS_SOCPLUS_BOARD: 342*29949e86Sstevel case IO_SBUS_FFB_SOCPLUS_BOARD: 343*29949e86Sstevel status = TRUE; 344*29949e86Sstevel break; 345*29949e86Sstevel 346*29949e86Sstevel case CLOCK_BOARD: 347*29949e86Sstevel case DISK_BOARD: 348*29949e86Sstevel default: 349*29949e86Sstevel status = FALSE; /* default is not supported */ 350*29949e86Sstevel break; 351*29949e86Sstevel } 352*29949e86Sstevel 353*29949e86Sstevel if (status == FALSE) 354*29949e86Sstevel return (status); 355*29949e86Sstevel 356*29949e86Sstevel /* Check for Sunfire boards in a Sunfire+ system */ 357*29949e86Sstevel if (status == TRUE && Fsys > 84 && !fhc_bd_is_plus(sysc_stat->board)) { 358*29949e86Sstevel (void) snprintf(pkt->errbuf, SYSC_OUTPUT_LEN, 359*29949e86Sstevel "not 100 MHz capable "); 360*29949e86Sstevel cmn_err(CE_WARN, "board %d, is not capable of running at " 361*29949e86Sstevel "current system clock (%dMhz)", sysc_stat->board, Fsys); 362*29949e86Sstevel 363*29949e86Sstevel status = FALSE; 364*29949e86Sstevel } 365*29949e86Sstevel 366*29949e86Sstevel return (status); 367*29949e86Sstevel } 368*29949e86Sstevel 369*29949e86Sstevel /* 370*29949e86Sstevel * This function is called to check the policy for a request to transition 371*29949e86Sstevel * to the connected state from the disconnected state. The generic policy 372*29949e86Sstevel * is to do sanity checks again before going live. 373*29949e86Sstevel */ 374*29949e86Sstevel /*ARGSUSED*/ 375*29949e86Sstevel int 376*29949e86Sstevel sysc_policy_connect(struct sysctrl_soft_state *softsp, 377*29949e86Sstevel sysc_cfga_pkt_t *pkt, sysc_cfga_stat_t *sysc_stat) 378*29949e86Sstevel { 379*29949e86Sstevel int retval; 380*29949e86Sstevel 381*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 382*29949e86Sstevel 383*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous RState: %d\n", sysc_stat->rstate)); 384*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous OState: %d\n", sysc_stat->ostate)); 385*29949e86Sstevel 386*29949e86Sstevel switch (sysc_stat->rstate) { 387*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED: 388*29949e86Sstevel /* 389*29949e86Sstevel * Safety policy: only allow connect if board is UNKNOWN cond. 390*29949e86Sstevel * cold start board will be demoted to UNKNOWN cond when 391*29949e86Sstevel * disconnected 392*29949e86Sstevel */ 393*29949e86Sstevel if (sysc_stat->condition != SYSC_CFGA_COND_UNKNOWN) { 394*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_COND); 395*29949e86Sstevel return (EINVAL); 396*29949e86Sstevel } 397*29949e86Sstevel 398*29949e86Sstevel if (!enable_dynamic_reconfiguration) { 399*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NON_DR_PROM); 400*29949e86Sstevel return (ENOTSUP); 401*29949e86Sstevel } 402*29949e86Sstevel 403*29949e86Sstevel if (sysctrl_hotplug_disabled) { 404*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HOTPLUG); 405*29949e86Sstevel return (ENOTSUP); 406*29949e86Sstevel } 407*29949e86Sstevel 408*29949e86Sstevel /* Check PROM support. */ 409*29949e86Sstevel if (!sysc_board_connect_supported(sysc_stat->type)) { 410*29949e86Sstevel cmn_err(CE_WARN, "%s board %d connect" 411*29949e86Sstevel " is not supported by firmware.", 412*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), sysc_stat->board); 413*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT); 414*29949e86Sstevel return (ENOTSUP); 415*29949e86Sstevel } 416*29949e86Sstevel 417*29949e86Sstevel if (!sysc_policy_enough_power(softsp, TRUE, FALSE)) { 418*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_POWER); 419*29949e86Sstevel return (EAGAIN); 420*29949e86Sstevel } 421*29949e86Sstevel 422*29949e86Sstevel if (!sysc_policy_enough_precharge(softsp, sysc_stat)) { 423*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_PRECHARGE); 424*29949e86Sstevel return (EAGAIN); 425*29949e86Sstevel } 426*29949e86Sstevel 427*29949e86Sstevel if (!sysc_policy_enough_cooling(softsp, sysc_stat, FALSE)) { 428*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_COOLING); 429*29949e86Sstevel return (EAGAIN); 430*29949e86Sstevel } 431*29949e86Sstevel 432*29949e86Sstevel if (!sysc_policy_hardware_compatible(softsp, sysc_stat, pkt)) { 433*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT); 434*29949e86Sstevel return (ENOTSUP); 435*29949e86Sstevel } 436*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_RSTATE_CONNECT, 437*29949e86Sstevel sysc_stat); 438*29949e86Sstevel 439*29949e86Sstevel retval = sysc_bd_connect(sysc_stat->board, pkt); 440*29949e86Sstevel if (!retval) { 441*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_CONNECTED; 442*29949e86Sstevel sysc_policy_connected_condition(softsp, 443*29949e86Sstevel sysc_stat, FALSE); 444*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_RSTATE_SUCCEEDED, 445*29949e86Sstevel sysc_stat); 446*29949e86Sstevel } else { 447*29949e86Sstevel uint_t prom_failure; 448*29949e86Sstevel 449*29949e86Sstevel prom_failure = (retval == EIO && 450*29949e86Sstevel pkt->cmd_cfga.errtype == SYSC_ERR_PROM) ? 451*29949e86Sstevel TRUE : FALSE; 452*29949e86Sstevel sysc_policy_disconnected_condition(softsp, 453*29949e86Sstevel sysc_stat, prom_failure, FALSE); 454*29949e86Sstevel sysc_policy_audit_messages( 455*29949e86Sstevel SYSC_AUDIT_RSTATE_CONNECT_FAILED, 456*29949e86Sstevel sysc_stat); 457*29949e86Sstevel } 458*29949e86Sstevel break; 459*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY: 460*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED: 461*29949e86Sstevel default: 462*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_RSTATE); 463*29949e86Sstevel retval = EINVAL; 464*29949e86Sstevel break; 465*29949e86Sstevel } 466*29949e86Sstevel 467*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current RState: %d\n", sysc_stat->rstate)); 468*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current OState: %d\n", sysc_stat->ostate)); 469*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current Condition: %d\n", sysc_stat->condition)); 470*29949e86Sstevel 471*29949e86Sstevel return (retval); 472*29949e86Sstevel } 473*29949e86Sstevel 474*29949e86Sstevel /* 475*29949e86Sstevel * This function is called to check the policy for a request to transition 476*29949e86Sstevel * to the disconnected state from the connected/unconfigured state only. 477*29949e86Sstevel * All other requests are invalid. 478*29949e86Sstevel */ 479*29949e86Sstevel /*ARGSUSED*/ 480*29949e86Sstevel int 481*29949e86Sstevel sysc_policy_disconnect(struct sysctrl_soft_state *softsp, 482*29949e86Sstevel sysc_cfga_pkt_t *pkt, sysc_cfga_stat_t *sysc_stat) 483*29949e86Sstevel { 484*29949e86Sstevel int retval; 485*29949e86Sstevel 486*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 487*29949e86Sstevel 488*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous RState: %d\n", sysc_stat->rstate)); 489*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous OState: %d\n", sysc_stat->ostate)); 490*29949e86Sstevel 491*29949e86Sstevel switch (sysc_stat->rstate) { 492*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED: 493*29949e86Sstevel switch (sysc_stat->ostate) { 494*29949e86Sstevel case SYSC_CFGA_OSTATE_UNCONFIGURED: 495*29949e86Sstevel if (!enable_dynamic_reconfiguration) { 496*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NON_DR_PROM); 497*29949e86Sstevel return (ENOTSUP); 498*29949e86Sstevel } 499*29949e86Sstevel 500*29949e86Sstevel /* Check PROM support. */ 501*29949e86Sstevel if (!sysc_board_connect_supported(sysc_stat->type)) { 502*29949e86Sstevel cmn_err(CE_WARN, "%s board %d disconnect" 503*29949e86Sstevel " is not supported by firmware.", 504*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 505*29949e86Sstevel sysc_stat->board); 506*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT); 507*29949e86Sstevel return (ENOTSUP); 508*29949e86Sstevel } 509*29949e86Sstevel 510*29949e86Sstevel if (!sysc_policy_hardware_compatible(softsp, 511*29949e86Sstevel sysc_stat, pkt)) { 512*29949e86Sstevel cmn_err(CE_WARN, "%s board %d disconnect" 513*29949e86Sstevel " is not yet supported.", 514*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 515*29949e86Sstevel sysc_stat->board); 516*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT); 517*29949e86Sstevel return (ENOTSUP); 518*29949e86Sstevel } 519*29949e86Sstevel 520*29949e86Sstevel if (fhc_bd_is_jtag_master(sysc_stat->board)) { 521*29949e86Sstevel sysc_policy_update(softsp, sysc_stat, 522*29949e86Sstevel SYSC_EVT_BD_CORE_RESOURCE_DISCONNECT); 523*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_CORE_RESOURCE); 524*29949e86Sstevel return (EINVAL); 525*29949e86Sstevel } 526*29949e86Sstevel 527*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_RSTATE_DISCONNECT, 528*29949e86Sstevel sysc_stat); 529*29949e86Sstevel 530*29949e86Sstevel retval = sysc_bd_disconnect(sysc_stat->board, pkt); 531*29949e86Sstevel if (!retval) { 532*29949e86Sstevel sysc_stat->rstate = 533*29949e86Sstevel SYSC_CFGA_RSTATE_DISCONNECTED; 534*29949e86Sstevel DPRINTF(SYSCTRL_ATTACH_DEBUG, 535*29949e86Sstevel ("disconnect starting bd_remove_poll()")); 536*29949e86Sstevel bd_remove_poll(softsp); 537*29949e86Sstevel sysc_policy_disconnected_condition( 538*29949e86Sstevel softsp, 539*29949e86Sstevel sysc_stat, FALSE, FALSE); 540*29949e86Sstevel sysc_policy_audit_messages( 541*29949e86Sstevel SYSC_AUDIT_RSTATE_SUCCEEDED, 542*29949e86Sstevel sysc_stat); 543*29949e86Sstevel cmn_err(CE_NOTE, 544*29949e86Sstevel "board %d is ready to remove", 545*29949e86Sstevel sysc_stat->board); 546*29949e86Sstevel } else { 547*29949e86Sstevel sysc_policy_connected_condition( 548*29949e86Sstevel softsp, sysc_stat, FALSE); 549*29949e86Sstevel sysc_policy_audit_messages( 550*29949e86Sstevel SYSC_AUDIT_RSTATE_DISCONNECT_FAILED, 551*29949e86Sstevel sysc_stat); 552*29949e86Sstevel } 553*29949e86Sstevel break; 554*29949e86Sstevel case SYSC_CFGA_OSTATE_CONFIGURED: 555*29949e86Sstevel default: 556*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_OSTATE); 557*29949e86Sstevel retval = EINVAL; 558*29949e86Sstevel break; 559*29949e86Sstevel } 560*29949e86Sstevel break; 561*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY: 562*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED: 563*29949e86Sstevel default: 564*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_RSTATE); 565*29949e86Sstevel retval = EINVAL; 566*29949e86Sstevel break; 567*29949e86Sstevel } 568*29949e86Sstevel 569*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current RState: %d\n", sysc_stat->rstate)); 570*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current OState: %d\n", sysc_stat->ostate)); 571*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current Condition: %d\n", sysc_stat->condition)); 572*29949e86Sstevel 573*29949e86Sstevel return (retval); 574*29949e86Sstevel } 575*29949e86Sstevel 576*29949e86Sstevel /* 577*29949e86Sstevel * This function is called to check the policy for a request to transition 578*29949e86Sstevel * from the connected/configured state to the connected/unconfigured state only. 579*29949e86Sstevel * All other requests are invalid. 580*29949e86Sstevel */ 581*29949e86Sstevel /*ARGSUSED*/ 582*29949e86Sstevel int 583*29949e86Sstevel sysc_policy_unconfigure(struct sysctrl_soft_state *softsp, 584*29949e86Sstevel sysc_cfga_pkt_t *pkt, sysc_cfga_stat_t *sysc_stat) 585*29949e86Sstevel { 586*29949e86Sstevel int retval; 587*29949e86Sstevel 588*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 589*29949e86Sstevel 590*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous RState: %d\n", sysc_stat->rstate)); 591*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous OState: %d\n", sysc_stat->ostate)); 592*29949e86Sstevel 593*29949e86Sstevel switch (sysc_stat->ostate) { 594*29949e86Sstevel case SYSC_CFGA_OSTATE_CONFIGURED: 595*29949e86Sstevel if (!enable_dynamic_reconfiguration) { 596*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NON_DR_PROM); 597*29949e86Sstevel return (ENOTSUP); 598*29949e86Sstevel } 599*29949e86Sstevel 600*29949e86Sstevel if (!sysc_policy_hardware_compatible(softsp, sysc_stat, pkt)) { 601*29949e86Sstevel cmn_err(CE_WARN, "%s board %d unconfigure" 602*29949e86Sstevel " is not yet supported.", 603*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), sysc_stat->board); 604*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT); 605*29949e86Sstevel return (ENOTSUP); 606*29949e86Sstevel } 607*29949e86Sstevel 608*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_OSTATE_UNCONFIGURE, 609*29949e86Sstevel sysc_stat); 610*29949e86Sstevel 611*29949e86Sstevel retval = sysc_bd_unconfigure(sysc_stat->board, pkt); 612*29949e86Sstevel if (!retval) { 613*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 614*29949e86Sstevel sysc_policy_audit_messages( 615*29949e86Sstevel SYSC_AUDIT_OSTATE_SUCCEEDED, 616*29949e86Sstevel sysc_stat); 617*29949e86Sstevel } else { 618*29949e86Sstevel sysc_policy_audit_messages( 619*29949e86Sstevel SYSC_AUDIT_OSTATE_UNCONFIGURE_FAILED, 620*29949e86Sstevel sysc_stat); 621*29949e86Sstevel } 622*29949e86Sstevel sysc_policy_connected_condition(softsp, sysc_stat, FALSE); 623*29949e86Sstevel break; 624*29949e86Sstevel case SYSC_CFGA_OSTATE_UNCONFIGURED: 625*29949e86Sstevel default: 626*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_OSTATE); 627*29949e86Sstevel retval = EINVAL; 628*29949e86Sstevel break; 629*29949e86Sstevel } 630*29949e86Sstevel 631*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current RState: %d\n", sysc_stat->rstate)); 632*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current OState: %d\n", sysc_stat->ostate)); 633*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current Condition: %d\n", sysc_stat->condition)); 634*29949e86Sstevel 635*29949e86Sstevel return (retval); 636*29949e86Sstevel } 637*29949e86Sstevel 638*29949e86Sstevel /* 639*29949e86Sstevel * This function is called to check the policy for a requested transition 640*29949e86Sstevel * from either the connected/unconfigured state or the connected/configured 641*29949e86Sstevel * state to the connected/configured state. The redundant state transition 642*29949e86Sstevel * is permitted for partially configured set of devices. Basically, we 643*29949e86Sstevel * retry the configure. 644*29949e86Sstevel */ 645*29949e86Sstevel /*ARGSUSED*/ 646*29949e86Sstevel int 647*29949e86Sstevel sysc_policy_configure(struct sysctrl_soft_state *softsp, 648*29949e86Sstevel sysc_cfga_pkt_t *pkt, sysc_cfga_stat_t *sysc_stat) 649*29949e86Sstevel { 650*29949e86Sstevel int retval; 651*29949e86Sstevel 652*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 653*29949e86Sstevel 654*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous RState: %d\n", sysc_stat->rstate)); 655*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous OState: %d\n", sysc_stat->ostate)); 656*29949e86Sstevel 657*29949e86Sstevel switch (sysc_stat->rstate) { 658*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED: 659*29949e86Sstevel switch (sysc_stat->ostate) { 660*29949e86Sstevel case SYSC_CFGA_OSTATE_UNCONFIGURED: 661*29949e86Sstevel if (sysc_stat->condition != SYSC_CFGA_COND_OK) { 662*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_COND); 663*29949e86Sstevel return (EINVAL); 664*29949e86Sstevel } 665*29949e86Sstevel 666*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_OSTATE_CONFIGURE, 667*29949e86Sstevel sysc_stat); 668*29949e86Sstevel retval = sysc_bd_configure(sysc_stat->board, pkt); 669*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_CONFIGURED; 670*29949e86Sstevel sysc_policy_connected_condition(softsp, 671*29949e86Sstevel sysc_stat, FALSE); 672*29949e86Sstevel if (!retval) { 673*29949e86Sstevel sysc_policy_audit_messages( 674*29949e86Sstevel SYSC_AUDIT_OSTATE_SUCCEEDED, 675*29949e86Sstevel sysc_stat); 676*29949e86Sstevel } else { 677*29949e86Sstevel sysc_policy_audit_messages( 678*29949e86Sstevel SYSC_AUDIT_OSTATE_CONFIGURE_FAILED, 679*29949e86Sstevel sysc_stat); 680*29949e86Sstevel } 681*29949e86Sstevel break; 682*29949e86Sstevel case SYSC_CFGA_OSTATE_CONFIGURED: 683*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_OSTATE); 684*29949e86Sstevel retval = ENOTSUP; 685*29949e86Sstevel break; 686*29949e86Sstevel default: 687*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_OSTATE); 688*29949e86Sstevel retval = EINVAL; 689*29949e86Sstevel break; 690*29949e86Sstevel } 691*29949e86Sstevel break; 692*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY: 693*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED: 694*29949e86Sstevel default: 695*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_RSTATE); 696*29949e86Sstevel retval = EINVAL; 697*29949e86Sstevel break; 698*29949e86Sstevel } 699*29949e86Sstevel 700*29949e86Sstevel 701*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current RState: %d\n", sysc_stat->rstate)); 702*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current OState: %d\n", sysc_stat->ostate)); 703*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current Condition: %d\n", sysc_stat->condition)); 704*29949e86Sstevel 705*29949e86Sstevel return (retval); 706*29949e86Sstevel } 707*29949e86Sstevel 708*29949e86Sstevel /*ARGSUSED*/ 709*29949e86Sstevel static void 710*29949e86Sstevel sysc_policy_empty_condition(struct sysctrl_soft_state *softsp, 711*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t failure, 712*29949e86Sstevel uint_t ps_mutex_is_held) 713*29949e86Sstevel { 714*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 715*29949e86Sstevel 716*29949e86Sstevel switch (sysc_stat->condition) { 717*29949e86Sstevel case SYSC_CFGA_COND_UNKNOWN: 718*29949e86Sstevel case SYSC_CFGA_COND_OK: 719*29949e86Sstevel case SYSC_CFGA_COND_FAILING: 720*29949e86Sstevel case SYSC_CFGA_COND_FAILED: 721*29949e86Sstevel /* nothing in the slot so just check power supplies */ 722*29949e86Sstevel case SYSC_CFGA_COND_UNUSABLE: 723*29949e86Sstevel if (sysc_policy_enough_cooling(softsp, sysc_stat, 724*29949e86Sstevel ps_mutex_is_held) && 725*29949e86Sstevel sysc_policy_enough_power(softsp, FALSE, 726*29949e86Sstevel ps_mutex_is_held)) { 727*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN; 728*29949e86Sstevel } else { 729*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNUSABLE; 730*29949e86Sstevel } 731*29949e86Sstevel sysc_stat->last_change = gethrestime_sec(); 732*29949e86Sstevel break; 733*29949e86Sstevel default: 734*29949e86Sstevel ASSERT(FALSE); 735*29949e86Sstevel break; 736*29949e86Sstevel } 737*29949e86Sstevel } 738*29949e86Sstevel /*ARGSUSED*/ 739*29949e86Sstevel static void 740*29949e86Sstevel sysc_policy_disconnected_condition(struct sysctrl_soft_state *softsp, 741*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t failure, 742*29949e86Sstevel uint_t ps_mutex_is_held) 743*29949e86Sstevel { 744*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 745*29949e86Sstevel 746*29949e86Sstevel if (failure) { 747*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_FAILED; 748*29949e86Sstevel sysc_stat->last_change = gethrestime_sec(); 749*29949e86Sstevel return; 750*29949e86Sstevel } 751*29949e86Sstevel switch (sysc_stat->condition) { 752*29949e86Sstevel /* 753*29949e86Sstevel * if unknown, we have come from hotplug case so do a quick 754*29949e86Sstevel * reevaluation. 755*29949e86Sstevel */ 756*29949e86Sstevel case SYSC_CFGA_COND_UNKNOWN: 757*29949e86Sstevel /* 758*29949e86Sstevel * if ok, we have come from connected to disconnected and we stay 759*29949e86Sstevel * ok until removed or reevaluate when reconnect. We might have 760*29949e86Sstevel * experienced a ps fail so reevaluate the condition. 761*29949e86Sstevel */ 762*29949e86Sstevel case SYSC_CFGA_COND_OK: 763*29949e86Sstevel /* 764*29949e86Sstevel * if unsuable, either power supply was missing or 765*29949e86Sstevel * hardware was not compatible. Check to see if 766*29949e86Sstevel * this is still true. 767*29949e86Sstevel */ 768*29949e86Sstevel case SYSC_CFGA_COND_UNUSABLE: 769*29949e86Sstevel /* 770*29949e86Sstevel * failing must transition in the disconnected state 771*29949e86Sstevel * to either unusable or unknown. We may have come here 772*29949e86Sstevel * from cfgadm -f -c disconnect after a power supply failure 773*29949e86Sstevel * in an attempt to protect the board. 774*29949e86Sstevel */ 775*29949e86Sstevel case SYSC_CFGA_COND_FAILING: 776*29949e86Sstevel if (sysc_policy_enough_cooling(softsp, sysc_stat, 777*29949e86Sstevel ps_mutex_is_held) && 778*29949e86Sstevel sysc_policy_enough_power(softsp, FALSE, 779*29949e86Sstevel ps_mutex_is_held)) { 780*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN; 781*29949e86Sstevel } else { 782*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNUSABLE; 783*29949e86Sstevel } 784*29949e86Sstevel sysc_stat->last_change = gethrestime_sec(); 785*29949e86Sstevel break; 786*29949e86Sstevel /* 787*29949e86Sstevel * if failed, we have failed POST and must stay in this 788*29949e86Sstevel * condition until the board has been removed 789*29949e86Sstevel * before ever coming back into another condition 790*29949e86Sstevel */ 791*29949e86Sstevel case SYSC_CFGA_COND_FAILED: 792*29949e86Sstevel break; 793*29949e86Sstevel default: 794*29949e86Sstevel ASSERT(FALSE); 795*29949e86Sstevel break; 796*29949e86Sstevel } 797*29949e86Sstevel } 798*29949e86Sstevel 799*29949e86Sstevel /*ARGSUSED*/ 800*29949e86Sstevel static void 801*29949e86Sstevel sysc_policy_connected_condition(struct sysctrl_soft_state *softsp, 802*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, 803*29949e86Sstevel uint_t ps_mutex_is_held) 804*29949e86Sstevel { 805*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 806*29949e86Sstevel 807*29949e86Sstevel switch (sysc_stat->condition) { 808*29949e86Sstevel case SYSC_CFGA_COND_UNKNOWN: 809*29949e86Sstevel case SYSC_CFGA_COND_OK: 810*29949e86Sstevel case SYSC_CFGA_COND_FAILING: 811*29949e86Sstevel case SYSC_CFGA_COND_UNUSABLE: 812*29949e86Sstevel if (sysc_policy_enough_cooling(softsp, sysc_stat, 813*29949e86Sstevel ps_mutex_is_held) && 814*29949e86Sstevel sysc_policy_enough_power(softsp, FALSE, 815*29949e86Sstevel ps_mutex_is_held) && 816*29949e86Sstevel (fhc_env_temp_state(sysc_stat->board) == TEMP_OK)) { 817*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_OK; 818*29949e86Sstevel } else { 819*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_FAILING; 820*29949e86Sstevel } 821*29949e86Sstevel sysc_stat->last_change = gethrestime_sec(); 822*29949e86Sstevel break; 823*29949e86Sstevel case SYSC_CFGA_COND_FAILED: 824*29949e86Sstevel break; 825*29949e86Sstevel default: 826*29949e86Sstevel ASSERT(FALSE); 827*29949e86Sstevel break; 828*29949e86Sstevel } 829*29949e86Sstevel } 830*29949e86Sstevel 831*29949e86Sstevel static void 832*29949e86Sstevel sysc_policy_set_condition(void *sp, sysc_cfga_stat_t *sysc_stat, 833*29949e86Sstevel uint_t ps_mutex_is_held) 834*29949e86Sstevel { 835*29949e86Sstevel struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)sp; 836*29949e86Sstevel 837*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 838*29949e86Sstevel 839*29949e86Sstevel switch (sysc_stat->rstate) { 840*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY: 841*29949e86Sstevel sysc_policy_empty_condition(softsp, sysc_stat, 842*29949e86Sstevel FALSE, ps_mutex_is_held); 843*29949e86Sstevel break; 844*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED: 845*29949e86Sstevel sysc_policy_disconnected_condition(softsp, sysc_stat, 846*29949e86Sstevel FALSE, ps_mutex_is_held); 847*29949e86Sstevel break; 848*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED: 849*29949e86Sstevel sysc_policy_connected_condition(softsp, sysc_stat, 850*29949e86Sstevel ps_mutex_is_held); 851*29949e86Sstevel break; 852*29949e86Sstevel default: 853*29949e86Sstevel ASSERT(FALSE); 854*29949e86Sstevel break; 855*29949e86Sstevel } 856*29949e86Sstevel } 857*29949e86Sstevel 858*29949e86Sstevel void 859*29949e86Sstevel sysc_policy_update(void *softsp, sysc_cfga_stat_t *sysc_stat, 860*29949e86Sstevel sysc_evt_t event) 861*29949e86Sstevel { 862*29949e86Sstevel fhc_bd_t *list; 863*29949e86Sstevel 864*29949e86Sstevel ASSERT(event == SYSC_EVT_BD_HP_DISABLED || fhc_bdlist_locked()); 865*29949e86Sstevel 866*29949e86Sstevel switch (event) { 867*29949e86Sstevel case SYSC_EVT_BD_EMPTY: 868*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_EMPTY; 869*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 870*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN; 871*29949e86Sstevel sysc_policy_empty_condition(softsp, sysc_stat, FALSE, FALSE); 872*29949e86Sstevel break; 873*29949e86Sstevel case SYSC_EVT_BD_PRESENT: 874*29949e86Sstevel if (sysc_stat->type == DISK_BOARD) { 875*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_DISCONNECTED; 876*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 877*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN; 878*29949e86Sstevel } else { 879*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_CONNECTED; 880*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_CONFIGURED; 881*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_OK; 882*29949e86Sstevel } 883*29949e86Sstevel sysc_stat->last_change = gethrestime_sec(); 884*29949e86Sstevel break; 885*29949e86Sstevel case SYSC_EVT_BD_DISABLED: 886*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_DISCONNECTED; 887*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 888*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN; 889*29949e86Sstevel sysc_policy_disconnected_condition(softsp, 890*29949e86Sstevel sysc_stat, FALSE, FALSE); 891*29949e86Sstevel cmn_err(CE_NOTE, 892*29949e86Sstevel "disabled %s board in slot %d", 893*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 894*29949e86Sstevel sysc_stat->board); 895*29949e86Sstevel break; 896*29949e86Sstevel case SYSC_EVT_BD_FAILED: 897*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_DISCONNECTED; 898*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 899*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNUSABLE; 900*29949e86Sstevel sysc_policy_disconnected_condition(softsp, sysc_stat, 901*29949e86Sstevel TRUE, FALSE); 902*29949e86Sstevel cmn_err(CE_WARN, 903*29949e86Sstevel "failed %s board in slot %d", 904*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 905*29949e86Sstevel sysc_stat->board); 906*29949e86Sstevel break; 907*29949e86Sstevel case SYSC_EVT_BD_OVERTEMP: 908*29949e86Sstevel case SYSC_EVT_BD_TEMP_OK: 909*29949e86Sstevel sysc_policy_set_condition((void *)softsp, sysc_stat, FALSE); 910*29949e86Sstevel break; 911*29949e86Sstevel case SYSC_EVT_BD_PS_CHANGE: 912*29949e86Sstevel for (list = fhc_bd_first(); list; list = fhc_bd_next(list)) { 913*29949e86Sstevel sysc_stat = &(list->sc); 914*29949e86Sstevel sysc_policy_set_condition((void *)softsp, 915*29949e86Sstevel sysc_stat, TRUE); 916*29949e86Sstevel } 917*29949e86Sstevel break; 918*29949e86Sstevel case SYSC_EVT_BD_INS_FAILED: 919*29949e86Sstevel cmn_err(CE_WARN, "powerdown of board %d failed", 920*29949e86Sstevel sysc_stat->board); 921*29949e86Sstevel break; 922*29949e86Sstevel case SYSC_EVT_BD_INSERTED: 923*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_DISCONNECTED; 924*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 925*29949e86Sstevel sysctrl_post_config_change(softsp); 926*29949e86Sstevel sysc_policy_disconnected_condition(softsp, 927*29949e86Sstevel sysc_stat, FALSE, FALSE); 928*29949e86Sstevel cmn_err(CE_NOTE, "%s board has been inserted into slot %d", 929*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), sysc_stat->board); 930*29949e86Sstevel cmn_err(CE_NOTE, 931*29949e86Sstevel "board %d can be removed", sysc_stat->board); 932*29949e86Sstevel break; 933*29949e86Sstevel case SYSC_EVT_BD_REMOVED: 934*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_EMPTY; 935*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 936*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN; 937*29949e86Sstevel 938*29949e86Sstevel /* now it is ok to free the ac pa memory database */ 939*29949e86Sstevel fhc_del_memloc(sysc_stat->board); 940*29949e86Sstevel 941*29949e86Sstevel /* reinitialize sysc_cfga_stat structure */ 942*29949e86Sstevel sysc_stat->type = UNKNOWN_BOARD; 943*29949e86Sstevel sysc_stat->fhc_compid = 0; 944*29949e86Sstevel sysc_stat->ac_compid = 0; 945*29949e86Sstevel (void) bzero(&(sysc_stat->prom_rev), 946*29949e86Sstevel sizeof (sysc_stat->prom_rev)); 947*29949e86Sstevel (void) bzero(&(sysc_stat->bd), 948*29949e86Sstevel sizeof (union bd_un)); 949*29949e86Sstevel sysc_stat->no_detach = sysc_stat->plus_board = 0; 950*29949e86Sstevel sysc_policy_disconnected_condition(softsp, 951*29949e86Sstevel sysc_stat, FALSE, FALSE); 952*29949e86Sstevel cmn_err(CE_NOTE, "board %d has been removed", 953*29949e86Sstevel sysc_stat->board); 954*29949e86Sstevel break; 955*29949e86Sstevel case SYSC_EVT_BD_HP_DISABLED: 956*29949e86Sstevel cmn_err(CE_NOTE, "Hot Plug not supported in this system"); 957*29949e86Sstevel break; 958*29949e86Sstevel case SYSC_EVT_BD_CORE_RESOURCE_DISCONNECT: 959*29949e86Sstevel cmn_err(CE_WARN, "board %d cannot be disconnected because it" 960*29949e86Sstevel " is a core system resource", sysc_stat->board); 961*29949e86Sstevel break; 962*29949e86Sstevel default: 963*29949e86Sstevel ASSERT(FALSE); 964*29949e86Sstevel break; 965*29949e86Sstevel } 966*29949e86Sstevel 967*29949e86Sstevel } 968*29949e86Sstevel 969*29949e86Sstevel /* 970*29949e86Sstevel * signal to POST that the system has been reconfigured and that 971*29949e86Sstevel * the system configuration status information should be invalidated 972*29949e86Sstevel * the next time through POST 973*29949e86Sstevel */ 974*29949e86Sstevel static void 975*29949e86Sstevel sysctrl_post_config_change(struct sysctrl_soft_state *softsp) 976*29949e86Sstevel { 977*29949e86Sstevel /* 978*29949e86Sstevel * We are heading into a configuration change! 979*29949e86Sstevel * Tell post to invalidate its notion of the system configuration. 980*29949e86Sstevel * This is done by clearing the clock registers... 981*29949e86Sstevel */ 982*29949e86Sstevel *softsp->clk_freq1 = 0; 983*29949e86Sstevel *softsp->clk_freq2 &= 984*29949e86Sstevel ~(CLOCK_FREQ_8 | CLOCK_DIV_1 | CLOCK_RANGE | CLOCK_DIV_0); 985*29949e86Sstevel } 986*29949e86Sstevel 987*29949e86Sstevel static int 988*29949e86Sstevel sysc_attach_board(void *arg) 989*29949e86Sstevel { 990*29949e86Sstevel int board = *(int *)arg; 991*29949e86Sstevel 992*29949e86Sstevel return (prom_sunfire_attach_board((uint_t)board)); 993*29949e86Sstevel } 994*29949e86Sstevel 995*29949e86Sstevel static int 996*29949e86Sstevel sysc_bd_connect(int board, sysc_cfga_pkt_t *pkt) 997*29949e86Sstevel { 998*29949e86Sstevel int error = 0; 999*29949e86Sstevel fhc_bd_t *bdp; 1000*29949e86Sstevel sysc_dr_handle_t *sh; 1001*29949e86Sstevel uint64_t mempa; 1002*29949e86Sstevel int del_kstat = 0; 1003*29949e86Sstevel 1004*29949e86Sstevel ASSERT(fhc_bd_busy(board)); 1005*29949e86Sstevel 1006*29949e86Sstevel bdp = fhc_bd(board); 1007*29949e86Sstevel 1008*29949e86Sstevel /* find gap for largest supported simm in advance */ 1009*29949e86Sstevel #define MAX_BANK_SIZE_MB (2 * 1024) 1010*29949e86Sstevel #define BANKS_PER_BOARD 2 1011*29949e86Sstevel mempa = fhc_find_memloc_gap(BANKS_PER_BOARD * MAX_BANK_SIZE_MB); 1012*29949e86Sstevel 1013*29949e86Sstevel fhc_bdlist_unlock(); 1014*29949e86Sstevel 1015*29949e86Sstevel /* TODO: Is mempa vulnerable to re-use here? */ 1016*29949e86Sstevel 1017*29949e86Sstevel sysctrl_suspend_prepare(); 1018*29949e86Sstevel 1019*29949e86Sstevel if ((error = sysctrl_suspend(pkt)) == DDI_SUCCESS) { 1020*29949e86Sstevel /* ASSERT(jtag not held) */ 1021*29949e86Sstevel error = prom_tree_update(sysc_attach_board, &board); 1022*29949e86Sstevel if (error) { 1023*29949e86Sstevel error = EIO; 1024*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_PROM); 1025*29949e86Sstevel } else { 1026*29949e86Sstevel /* attempt to program the memory while frozen */ 1027*29949e86Sstevel fhc_program_memory(board, mempa); 1028*29949e86Sstevel } 1029*29949e86Sstevel sysctrl_resume(pkt); 1030*29949e86Sstevel } 1031*29949e86Sstevel 1032*29949e86Sstevel if (error) { 1033*29949e86Sstevel goto done; 1034*29949e86Sstevel } 1035*29949e86Sstevel 1036*29949e86Sstevel /* 1037*29949e86Sstevel * Must not delete kstat used by prtdiag until the PROM 1038*29949e86Sstevel * has successfully connected to board. 1039*29949e86Sstevel */ 1040*29949e86Sstevel del_kstat = 1; 1041*29949e86Sstevel 1042*29949e86Sstevel sh = &bdp->sh[SYSC_DR_HANDLE_FHC]; 1043*29949e86Sstevel sh->flags |= SYSC_DR_FHC; 1044*29949e86Sstevel sh->errstr = pkt->errbuf; 1045*29949e86Sstevel 1046*29949e86Sstevel sysc_dr_init(sh); 1047*29949e86Sstevel 1048*29949e86Sstevel error = sysc_dr_attach(sh, board); 1049*29949e86Sstevel if (error) 1050*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NDI_ATTACH); 1051*29949e86Sstevel 1052*29949e86Sstevel sysc_dr_uninit(sh); 1053*29949e86Sstevel 1054*29949e86Sstevel if (enable_redist) { 1055*29949e86Sstevel mutex_enter(&cpu_lock); 1056*29949e86Sstevel intr_redist_all_cpus(); 1057*29949e86Sstevel mutex_exit(&cpu_lock); 1058*29949e86Sstevel } 1059*29949e86Sstevel done: 1060*29949e86Sstevel if (del_kstat && bdp->ksp) { 1061*29949e86Sstevel kstat_delete(bdp->ksp); 1062*29949e86Sstevel bdp->ksp = NULL; 1063*29949e86Sstevel } 1064*29949e86Sstevel 1065*29949e86Sstevel (void) fhc_bdlist_lock(-1); 1066*29949e86Sstevel 1067*29949e86Sstevel return (error); 1068*29949e86Sstevel } 1069*29949e86Sstevel 1070*29949e86Sstevel static int 1071*29949e86Sstevel sysc_detach_board(void * arg) 1072*29949e86Sstevel { 1073*29949e86Sstevel int rt; 1074*29949e86Sstevel cpuset_t xcset; 1075*29949e86Sstevel struct jt_mstr *jtm; 1076*29949e86Sstevel int board = *(int *)arg; 1077*29949e86Sstevel 1078*29949e86Sstevel (void) fhc_bdlist_lock(-1); 1079*29949e86Sstevel 1080*29949e86Sstevel #ifdef DEBUG 1081*29949e86Sstevel /* it is important to have fhc_bdlist_lock() earlier */ 1082*29949e86Sstevel if (sysctrl_enable_regdump) 1083*29949e86Sstevel precache_regdump(board); 1084*29949e86Sstevel #endif /* DEBUG */ 1085*29949e86Sstevel 1086*29949e86Sstevel jtm = jtag_master_lock(); 1087*29949e86Sstevel CPUSET_ALL(xcset); 1088*29949e86Sstevel promsafe_xc_attention(xcset); 1089*29949e86Sstevel 1090*29949e86Sstevel #ifdef DEBUG 1091*29949e86Sstevel if (sysctrl_enable_regdump) 1092*29949e86Sstevel boardstat_regdump(); 1093*29949e86Sstevel #endif /* DEBUG */ 1094*29949e86Sstevel 1095*29949e86Sstevel rt = prom_sunfire_detach_board((uint_t)board); 1096*29949e86Sstevel 1097*29949e86Sstevel #ifdef DEBUG 1098*29949e86Sstevel if (sysctrl_enable_regdump) 1099*29949e86Sstevel display_regdump(); 1100*29949e86Sstevel #endif /* DEBUG */ 1101*29949e86Sstevel 1102*29949e86Sstevel xc_dismissed(xcset); 1103*29949e86Sstevel jtag_master_unlock(jtm); 1104*29949e86Sstevel fhc_bdlist_unlock(); 1105*29949e86Sstevel return (rt); 1106*29949e86Sstevel } 1107*29949e86Sstevel 1108*29949e86Sstevel static int 1109*29949e86Sstevel sysc_bd_disconnect(int board, sysc_cfga_pkt_t *pkt) 1110*29949e86Sstevel { 1111*29949e86Sstevel int error; 1112*29949e86Sstevel fhc_bd_t *bdp; 1113*29949e86Sstevel sysc_dr_handle_t *sh; 1114*29949e86Sstevel void fhc_bd_ks_alloc(fhc_bd_t *); 1115*29949e86Sstevel 1116*29949e86Sstevel ASSERT(fhc_bd_busy(board)); 1117*29949e86Sstevel ASSERT(!fhc_bd_is_jtag_master(board)); 1118*29949e86Sstevel 1119*29949e86Sstevel 1120*29949e86Sstevel bdp = fhc_bd(board); 1121*29949e86Sstevel 1122*29949e86Sstevel bdp->flags |= BDF_DETACH; 1123*29949e86Sstevel 1124*29949e86Sstevel fhc_bdlist_unlock(); 1125*29949e86Sstevel 1126*29949e86Sstevel sh = &bdp->sh[SYSC_DR_HANDLE_FHC]; 1127*29949e86Sstevel sh->errstr = pkt->errbuf; 1128*29949e86Sstevel 1129*29949e86Sstevel ASSERT(sh->dip_list == NULL); 1130*29949e86Sstevel 1131*29949e86Sstevel sh->flags |= SYSC_DR_FHC; 1132*29949e86Sstevel sysc_dr_init(sh); 1133*29949e86Sstevel 1134*29949e86Sstevel error = sysc_dr_detach(sh, board); 1135*29949e86Sstevel sh->flags &= ~SYSC_DR_REMOVE; 1136*29949e86Sstevel 1137*29949e86Sstevel sysc_dr_uninit(sh); 1138*29949e86Sstevel if (error) { 1139*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NDI_DETACH); 1140*29949e86Sstevel goto done; 1141*29949e86Sstevel } 1142*29949e86Sstevel error = prom_tree_update(sysc_detach_board, &board); 1143*29949e86Sstevel 1144*29949e86Sstevel if (error) { 1145*29949e86Sstevel error = EIO; 1146*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_PROM); 1147*29949e86Sstevel goto done; 1148*29949e86Sstevel } 1149*29949e86Sstevel 1150*29949e86Sstevel if (enable_redist) { 1151*29949e86Sstevel mutex_enter(&cpu_lock); 1152*29949e86Sstevel intr_redist_all_cpus(); 1153*29949e86Sstevel mutex_exit(&cpu_lock); 1154*29949e86Sstevel } 1155*29949e86Sstevel 1156*29949e86Sstevel fhc_bd_ks_alloc(bdp); 1157*29949e86Sstevel done: 1158*29949e86Sstevel (void) fhc_bdlist_lock(-1); 1159*29949e86Sstevel 1160*29949e86Sstevel return (error); 1161*29949e86Sstevel } 1162*29949e86Sstevel 1163*29949e86Sstevel static int 1164*29949e86Sstevel sysc_bd_configure(int board, sysc_cfga_pkt_t *pkt) 1165*29949e86Sstevel { 1166*29949e86Sstevel int error = 0; 1167*29949e86Sstevel fhc_bd_t *bdp; 1168*29949e86Sstevel sysc_dr_handle_t *sh; 1169*29949e86Sstevel 1170*29949e86Sstevel ASSERT(fhc_bd_busy(board)); 1171*29949e86Sstevel 1172*29949e86Sstevel bdp = fhc_bd(board); 1173*29949e86Sstevel 1174*29949e86Sstevel fhc_bdlist_unlock(); 1175*29949e86Sstevel 1176*29949e86Sstevel 1177*29949e86Sstevel sh = &bdp->sh[SYSC_DR_HANDLE_DEVS]; 1178*29949e86Sstevel sh->errstr = pkt->errbuf; 1179*29949e86Sstevel 1180*29949e86Sstevel ASSERT(sh->dip_list == NULL); 1181*29949e86Sstevel 1182*29949e86Sstevel sysc_dr_init(sh); 1183*29949e86Sstevel 1184*29949e86Sstevel sh->flags |= SYSC_DR_DEVS; 1185*29949e86Sstevel error = sysc_dr_attach(sh, board); 1186*29949e86Sstevel if (error) { 1187*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NDI_ATTACH); 1188*29949e86Sstevel sysc_dr_uninit(sh); 1189*29949e86Sstevel goto done; 1190*29949e86Sstevel } 1191*29949e86Sstevel 1192*29949e86Sstevel sysc_dr_uninit(sh); 1193*29949e86Sstevel 1194*29949e86Sstevel if (enable_redist) { 1195*29949e86Sstevel mutex_enter(&cpu_lock); 1196*29949e86Sstevel intr_redist_all_cpus(); 1197*29949e86Sstevel mutex_exit(&cpu_lock); 1198*29949e86Sstevel } 1199*29949e86Sstevel done: 1200*29949e86Sstevel if (bdp->sc.type == CPU_BOARD) { 1201*29949e86Sstevel /* 1202*29949e86Sstevel * Value of error gets lost for CPU boards. 1203*29949e86Sstevel */ 1204*29949e86Sstevel mutex_enter(&cpu_lock); 1205*29949e86Sstevel 1206*29949e86Sstevel error = find_and_setup_cpu(FHC_BOARD2CPU_A(board)); 1207*29949e86Sstevel if ((error == 0) || (error == ENODEV)) { 1208*29949e86Sstevel int retval_b; 1209*29949e86Sstevel 1210*29949e86Sstevel retval_b = find_and_setup_cpu(FHC_BOARD2CPU_B(board)); 1211*29949e86Sstevel if (retval_b != ENODEV) 1212*29949e86Sstevel error = retval_b; 1213*29949e86Sstevel } 1214*29949e86Sstevel 1215*29949e86Sstevel mutex_exit(&cpu_lock); 1216*29949e86Sstevel } 1217*29949e86Sstevel 1218*29949e86Sstevel (void) fhc_bdlist_lock(-1); 1219*29949e86Sstevel 1220*29949e86Sstevel return (error); 1221*29949e86Sstevel } 1222*29949e86Sstevel 1223*29949e86Sstevel static int 1224*29949e86Sstevel sysc_bd_unconfigure(int board, sysc_cfga_pkt_t *pkt) 1225*29949e86Sstevel { 1226*29949e86Sstevel int error; 1227*29949e86Sstevel fhc_bd_t *bdp; 1228*29949e86Sstevel sysc_dr_handle_t *sh; 1229*29949e86Sstevel 1230*29949e86Sstevel ASSERT(fhc_bdlist_locked()); 1231*29949e86Sstevel ASSERT(fhc_bd_busy(board)); 1232*29949e86Sstevel 1233*29949e86Sstevel bdp = fhc_bd(board); 1234*29949e86Sstevel 1235*29949e86Sstevel if (bdp->sc.type == CPU_BOARD || bdp->sc.type == MEM_BOARD) { 1236*29949e86Sstevel struct ac_soft_state *acsp; 1237*29949e86Sstevel 1238*29949e86Sstevel /* 1239*29949e86Sstevel * Check that any memory on board is not in use. 1240*29949e86Sstevel * This must be done while the board list lock is held 1241*29949e86Sstevel * as memory state can change while fhc_bd_busy() is true 1242*29949e86Sstevel * even though a memory operation cannot be started 1243*29949e86Sstevel * if fhc_bd_busy() is true. 1244*29949e86Sstevel */ 1245*29949e86Sstevel if ((acsp = (struct ac_soft_state *)bdp->ac_softsp) != NULL) { 1246*29949e86Sstevel if (acsp->bank[Bank0].busy != 0 || 1247*29949e86Sstevel acsp->bank[Bank0].ostate == 1248*29949e86Sstevel SYSC_CFGA_OSTATE_CONFIGURED) { 1249*29949e86Sstevel cmn_err(CE_WARN, "memory bank %d in " 1250*29949e86Sstevel "slot %d is in use.", Bank0, board); 1251*29949e86Sstevel (void) snprintf(pkt->errbuf, 1252*29949e86Sstevel SYSC_OUTPUT_LEN, 1253*29949e86Sstevel "memory bank %d in use", 1254*29949e86Sstevel Bank0); 1255*29949e86Sstevel return (EBUSY); 1256*29949e86Sstevel } 1257*29949e86Sstevel 1258*29949e86Sstevel if (acsp->bank[Bank1].busy != 0 || 1259*29949e86Sstevel acsp->bank[Bank1].ostate == 1260*29949e86Sstevel SYSC_CFGA_OSTATE_CONFIGURED) { 1261*29949e86Sstevel cmn_err(CE_WARN, "memory bank %d in " 1262*29949e86Sstevel "slot %d is in use.", Bank1, board); 1263*29949e86Sstevel (void) snprintf(pkt->errbuf, 1264*29949e86Sstevel SYSC_OUTPUT_LEN, 1265*29949e86Sstevel "memory bank %d in use", 1266*29949e86Sstevel Bank1); 1267*29949e86Sstevel return (EBUSY); 1268*29949e86Sstevel } 1269*29949e86Sstevel /* 1270*29949e86Sstevel * Nothing more to do here. The memory interface 1271*29949e86Sstevel * will not make any transitions while 1272*29949e86Sstevel * fhc_bd_busy() is true. Once the ostate 1273*29949e86Sstevel * becomes unconfigured, the memory becomes 1274*29949e86Sstevel * invisible. 1275*29949e86Sstevel */ 1276*29949e86Sstevel } 1277*29949e86Sstevel error = 0; 1278*29949e86Sstevel if (bdp->sc.type == CPU_BOARD) { 1279*29949e86Sstevel struct cpu *cpua, *cpub; 1280*29949e86Sstevel int cpu_flags = 0; 1281*29949e86Sstevel 1282*29949e86Sstevel if (pkt->cmd_cfga.force) 1283*29949e86Sstevel cpu_flags = CPU_FORCED; 1284*29949e86Sstevel 1285*29949e86Sstevel fhc_bdlist_unlock(); 1286*29949e86Sstevel 1287*29949e86Sstevel mutex_enter(&cpu_lock); /* protects CPU states */ 1288*29949e86Sstevel 1289*29949e86Sstevel error = fhc_board_poweroffcpus(board, pkt->errbuf, 1290*29949e86Sstevel cpu_flags); 1291*29949e86Sstevel 1292*29949e86Sstevel cpua = cpu_get(FHC_BOARD2CPU_A(board)); 1293*29949e86Sstevel cpub = cpu_get(FHC_BOARD2CPU_B(board)); 1294*29949e86Sstevel 1295*29949e86Sstevel if ((error == 0) && (cpua != NULL)) { 1296*29949e86Sstevel error = cpu_unconfigure(cpua->cpu_id); 1297*29949e86Sstevel if (error != 0) { 1298*29949e86Sstevel (void) snprintf(pkt->errbuf, 1299*29949e86Sstevel SYSC_OUTPUT_LEN, 1300*29949e86Sstevel "processor %d unconfigure failed", 1301*29949e86Sstevel cpua->cpu_id); 1302*29949e86Sstevel } 1303*29949e86Sstevel } 1304*29949e86Sstevel if ((error == 0) && (cpub != NULL)) { 1305*29949e86Sstevel error = cpu_unconfigure(cpub->cpu_id); 1306*29949e86Sstevel if (error != 0) { 1307*29949e86Sstevel (void) snprintf(pkt->errbuf, 1308*29949e86Sstevel SYSC_OUTPUT_LEN, 1309*29949e86Sstevel "processor %d unconfigure failed", 1310*29949e86Sstevel cpub->cpu_id); 1311*29949e86Sstevel } 1312*29949e86Sstevel } 1313*29949e86Sstevel 1314*29949e86Sstevel mutex_exit(&cpu_lock); 1315*29949e86Sstevel 1316*29949e86Sstevel (void) fhc_bdlist_lock(-1); 1317*29949e86Sstevel } 1318*29949e86Sstevel 1319*29949e86Sstevel if (error != 0) 1320*29949e86Sstevel return (error); 1321*29949e86Sstevel } 1322*29949e86Sstevel 1323*29949e86Sstevel fhc_bdlist_unlock(); 1324*29949e86Sstevel 1325*29949e86Sstevel sh = &bdp->sh[SYSC_DR_HANDLE_DEVS]; 1326*29949e86Sstevel sh->errstr = pkt->errbuf; 1327*29949e86Sstevel 1328*29949e86Sstevel ASSERT(sh->dip_list == NULL); 1329*29949e86Sstevel 1330*29949e86Sstevel sysc_dr_init(sh); 1331*29949e86Sstevel 1332*29949e86Sstevel sh->flags |= SYSC_DR_DEVS; 1333*29949e86Sstevel error = sysc_dr_detach(sh, board); 1334*29949e86Sstevel sh->flags &= ~SYSC_DR_REMOVE; 1335*29949e86Sstevel if (error) { 1336*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NDI_DETACH); 1337*29949e86Sstevel sysc_dr_uninit(sh); 1338*29949e86Sstevel goto done; 1339*29949e86Sstevel } 1340*29949e86Sstevel 1341*29949e86Sstevel sysc_dr_uninit(sh); 1342*29949e86Sstevel 1343*29949e86Sstevel if (enable_redist) { 1344*29949e86Sstevel mutex_enter(&cpu_lock); 1345*29949e86Sstevel intr_redist_all_cpus(); 1346*29949e86Sstevel mutex_exit(&cpu_lock); 1347*29949e86Sstevel } 1348*29949e86Sstevel 1349*29949e86Sstevel done: 1350*29949e86Sstevel (void) fhc_bdlist_lock(-1); 1351*29949e86Sstevel 1352*29949e86Sstevel return (error); 1353*29949e86Sstevel } 1354*29949e86Sstevel 1355*29949e86Sstevel 1356*29949e86Sstevel typedef struct sysc_prom { 1357*29949e86Sstevel sysc_dr_handle_t *handle; /* DR handle */ 1358*29949e86Sstevel int board; /* board id */ 1359*29949e86Sstevel dev_info_t **dipp; /* next slot for storing dip */ 1360*29949e86Sstevel } sysc_prom_t; 1361*29949e86Sstevel 1362*29949e86Sstevel /* 1363*29949e86Sstevel * Attaching devices on a board. 1364*29949e86Sstevel */ 1365*29949e86Sstevel static int 1366*29949e86Sstevel sysc_dr_attach(sysc_dr_handle_t *handle, int board) 1367*29949e86Sstevel { 1368*29949e86Sstevel int i; 1369*29949e86Sstevel int err; 1370*29949e86Sstevel sysc_prom_t arg; 1371*29949e86Sstevel devi_branch_t b = {0}; 1372*29949e86Sstevel 1373*29949e86Sstevel arg.handle = handle; 1374*29949e86Sstevel arg.board = board; 1375*29949e86Sstevel arg.dipp = handle->dip_list; 1376*29949e86Sstevel 1377*29949e86Sstevel b.arg = &arg; 1378*29949e86Sstevel b.type = DEVI_BRANCH_PROM; 1379*29949e86Sstevel b.create.prom_branch_select = sysc_prom_select; 1380*29949e86Sstevel b.devi_branch_callback = sysc_branch_callback; 1381*29949e86Sstevel 1382*29949e86Sstevel handle->error = e_ddi_branch_create(ddi_root_node(), &b, 1383*29949e86Sstevel NULL, DEVI_BRANCH_CHILD); 1384*29949e86Sstevel 1385*29949e86Sstevel if (handle->error) 1386*29949e86Sstevel return (handle->error); 1387*29949e86Sstevel 1388*29949e86Sstevel for (i = 0, arg.dipp = handle->dip_list; 1389*29949e86Sstevel i < handle->dip_list_len; i++, arg.dipp++) { 1390*29949e86Sstevel 1391*29949e86Sstevel err = e_ddi_branch_configure(*arg.dipp, NULL, 0); 1392*29949e86Sstevel /* 1393*29949e86Sstevel * Error only if we fail for fhc dips 1394*29949e86Sstevel */ 1395*29949e86Sstevel if (err && (handle->flags & SYSC_DR_FHC)) { 1396*29949e86Sstevel handle->error = err; 1397*29949e86Sstevel sysc_dr_err_decode(handle, *arg.dipp, TRUE); 1398*29949e86Sstevel return (handle->error); 1399*29949e86Sstevel } 1400*29949e86Sstevel } 1401*29949e86Sstevel 1402*29949e86Sstevel return (0); 1403*29949e86Sstevel } 1404*29949e86Sstevel 1405*29949e86Sstevel /*ARGSUSED*/ 1406*29949e86Sstevel static int 1407*29949e86Sstevel sysc_make_list(void *arg, int has_changed) 1408*29949e86Sstevel { 1409*29949e86Sstevel dev_info_t *rdip; 1410*29949e86Sstevel sysc_prom_t *wp = (sysc_prom_t *)arg; 1411*29949e86Sstevel pnode_t nid = prom_childnode(prom_rootnode()); 1412*29949e86Sstevel 1413*29949e86Sstevel if (wp == NULL) 1414*29949e86Sstevel return (EINVAL); 1415*29949e86Sstevel 1416*29949e86Sstevel for (; nid != OBP_NONODE && nid != OBP_BADNODE; 1417*29949e86Sstevel nid = prom_nextnode(nid)) { 1418*29949e86Sstevel if (sysc_prom_select(nid, arg, 0) != DDI_SUCCESS) 1419*29949e86Sstevel continue; 1420*29949e86Sstevel if (wp->handle->dip_list_len < SYSC_DR_MAX_NODE) { 1421*29949e86Sstevel rdip = wp->handle->dip_list[wp->handle->dip_list_len] = 1422*29949e86Sstevel e_ddi_nodeid_to_dip(nid); 1423*29949e86Sstevel if (rdip != NULL) { 1424*29949e86Sstevel wp->handle->dip_list_len++; 1425*29949e86Sstevel /* 1426*29949e86Sstevel * Branch rooted at dip already held, so 1427*29949e86Sstevel * release hold acquired in e_ddi_nodeid_to_dip 1428*29949e86Sstevel */ 1429*29949e86Sstevel ddi_release_devi(rdip); 1430*29949e86Sstevel ASSERT(e_ddi_branch_held(rdip)); 1431*29949e86Sstevel #ifdef DEBUG 1432*29949e86Sstevel } else { 1433*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("sysc_make_list:" 1434*29949e86Sstevel " e_ddi_nodeid_to_dip() failed for" 1435*29949e86Sstevel " nodeid: %d\n", nid)); 1436*29949e86Sstevel #endif 1437*29949e86Sstevel } 1438*29949e86Sstevel } else { 1439*29949e86Sstevel #ifdef DEBUG 1440*29949e86Sstevel cmn_err(CE_WARN, "sysc_make_list: list overflow\n"); 1441*29949e86Sstevel #endif 1442*29949e86Sstevel return (EFAULT); 1443*29949e86Sstevel } 1444*29949e86Sstevel } 1445*29949e86Sstevel 1446*29949e86Sstevel return (0); 1447*29949e86Sstevel } 1448*29949e86Sstevel 1449*29949e86Sstevel /* 1450*29949e86Sstevel * Detaching devices on a board. 1451*29949e86Sstevel */ 1452*29949e86Sstevel static int 1453*29949e86Sstevel sysc_dr_detach(sysc_dr_handle_t *handle, int board) 1454*29949e86Sstevel { 1455*29949e86Sstevel int i; 1456*29949e86Sstevel uint_t flags; 1457*29949e86Sstevel sysc_prom_t arg; 1458*29949e86Sstevel 1459*29949e86Sstevel ASSERT(handle->dip_list); 1460*29949e86Sstevel ASSERT(handle->dip_list_len == 0); 1461*29949e86Sstevel ASSERT(*handle->dip_list == NULL); 1462*29949e86Sstevel 1463*29949e86Sstevel arg.handle = handle; 1464*29949e86Sstevel arg.board = board; 1465*29949e86Sstevel arg.dipp = NULL; 1466*29949e86Sstevel 1467*29949e86Sstevel handle->error = prom_tree_access(sysc_make_list, &arg, NULL); 1468*29949e86Sstevel if (handle->error) 1469*29949e86Sstevel return (handle->error); 1470*29949e86Sstevel 1471*29949e86Sstevel flags = DEVI_BRANCH_DESTROY | DEVI_BRANCH_EVENT; 1472*29949e86Sstevel 1473*29949e86Sstevel for (i = handle->dip_list_len; i > 0; i--) { 1474*29949e86Sstevel ASSERT(e_ddi_branch_held(handle->dip_list[i - 1])); 1475*29949e86Sstevel handle->error = e_ddi_branch_unconfigure( 1476*29949e86Sstevel handle->dip_list[i - 1], NULL, flags); 1477*29949e86Sstevel if (handle->error) 1478*29949e86Sstevel return (handle->error); 1479*29949e86Sstevel } 1480*29949e86Sstevel 1481*29949e86Sstevel return (0); 1482*29949e86Sstevel } 1483*29949e86Sstevel 1484*29949e86Sstevel static void 1485*29949e86Sstevel sysc_dr_init(sysc_dr_handle_t *handle) 1486*29949e86Sstevel { 1487*29949e86Sstevel handle->dip_list = kmem_zalloc(sizeof (dev_info_t *) * SYSC_DR_MAX_NODE, 1488*29949e86Sstevel KM_SLEEP); 1489*29949e86Sstevel handle->dip_list_len = 0; 1490*29949e86Sstevel } 1491*29949e86Sstevel 1492*29949e86Sstevel /*ARGSUSED2*/ 1493*29949e86Sstevel static int 1494*29949e86Sstevel sysc_prom_select(pnode_t pnode, void *arg, uint_t flag) 1495*29949e86Sstevel { 1496*29949e86Sstevel int bd_id; 1497*29949e86Sstevel char name[OBP_MAXDRVNAME]; 1498*29949e86Sstevel int len; 1499*29949e86Sstevel int *regp; 1500*29949e86Sstevel sysc_prom_t *wp = (sysc_prom_t *)arg; 1501*29949e86Sstevel 1502*29949e86Sstevel bd_id = -1; 1503*29949e86Sstevel len = prom_getproplen(pnode, OBP_REG); 1504*29949e86Sstevel if (len > 0) { 1505*29949e86Sstevel regp = kmem_alloc(len, KM_SLEEP); 1506*29949e86Sstevel (void) prom_getprop(pnode, OBP_REG, (caddr_t)regp); 1507*29949e86Sstevel /* 1508*29949e86Sstevel * Get board id for EXXXX platforms where 1509*29949e86Sstevel * 0x1c0 is EXXXX platform specific data to 1510*29949e86Sstevel * acquire board id. 1511*29949e86Sstevel */ 1512*29949e86Sstevel bd_id = (*regp - 0x1c0) >> 2; 1513*29949e86Sstevel kmem_free(regp, len); 1514*29949e86Sstevel } 1515*29949e86Sstevel 1516*29949e86Sstevel (void) prom_getprop(pnode, OBP_NAME, (caddr_t)name); 1517*29949e86Sstevel if ((bd_id == wp->board) && 1518*29949e86Sstevel ((wp->handle->flags & SYSC_DR_FHC) ? 1519*29949e86Sstevel (strcmp(name, "fhc") == 0): 1520*29949e86Sstevel (strcmp(name, "fhc") != 0)) && 1521*29949e86Sstevel (strcmp(name, "central") != 0)) { 1522*29949e86Sstevel return (DDI_SUCCESS); 1523*29949e86Sstevel } 1524*29949e86Sstevel 1525*29949e86Sstevel return (DDI_FAILURE); 1526*29949e86Sstevel } 1527*29949e86Sstevel 1528*29949e86Sstevel /*ARGSUSED*/ 1529*29949e86Sstevel static void 1530*29949e86Sstevel sysc_branch_callback(dev_info_t *rdip, void *arg, uint_t flags) 1531*29949e86Sstevel { 1532*29949e86Sstevel sysc_prom_t *wp = (sysc_prom_t *)arg; 1533*29949e86Sstevel 1534*29949e86Sstevel ASSERT(wp->dipp != NULL); 1535*29949e86Sstevel ASSERT(*wp->dipp == NULL); 1536*29949e86Sstevel ASSERT((wp->handle->flags & SYSC_DR_REMOVE) == 0); 1537*29949e86Sstevel 1538*29949e86Sstevel if (wp->handle->dip_list_len < SYSC_DR_MAX_NODE) { 1539*29949e86Sstevel *wp->dipp = rdip; 1540*29949e86Sstevel wp->dipp++; 1541*29949e86Sstevel wp->handle->dip_list_len++; 1542*29949e86Sstevel } else { 1543*29949e86Sstevel cmn_err(CE_PANIC, "sysc_branch_callback: list overflow"); 1544*29949e86Sstevel } 1545*29949e86Sstevel } 1546*29949e86Sstevel 1547*29949e86Sstevel /* 1548*29949e86Sstevel * Uninitialize devices for the state of a board. 1549*29949e86Sstevel */ 1550*29949e86Sstevel static void 1551*29949e86Sstevel sysc_dr_uninit(sysc_dr_handle_t *handle) 1552*29949e86Sstevel { 1553*29949e86Sstevel kmem_free(handle->dip_list, 1554*29949e86Sstevel sizeof (dev_info_t *) * SYSC_DR_MAX_NODE); 1555*29949e86Sstevel handle->dip_list = NULL; 1556*29949e86Sstevel handle->dip_list_len = 0; 1557*29949e86Sstevel } 1558*29949e86Sstevel 1559*29949e86Sstevel static void 1560*29949e86Sstevel sysc_dr_err_decode(sysc_dr_handle_t *handle, dev_info_t *dip, int attach) 1561*29949e86Sstevel { 1562*29949e86Sstevel char *p; 1563*29949e86Sstevel 1564*29949e86Sstevel ASSERT(handle->error != 0); 1565*29949e86Sstevel 1566*29949e86Sstevel switch (handle->error) { 1567*29949e86Sstevel case ENOMEM: 1568*29949e86Sstevel break; 1569*29949e86Sstevel case EBUSY: 1570*29949e86Sstevel (void) ddi_pathname(dip, handle->errstr); 1571*29949e86Sstevel break; 1572*29949e86Sstevel default: 1573*29949e86Sstevel handle->error = EFAULT; 1574*29949e86Sstevel if (attach) 1575*29949e86Sstevel (void) ddi_pathname(ddi_get_parent(dip), 1576*29949e86Sstevel handle->errstr); 1577*29949e86Sstevel else 1578*29949e86Sstevel (void) ddi_pathname(dip, handle->errstr); 1579*29949e86Sstevel if (attach) { 1580*29949e86Sstevel p = "/"; 1581*29949e86Sstevel (void) strcat(handle->errstr, p); 1582*29949e86Sstevel (void) strcat(handle->errstr, ddi_node_name(dip)); 1583*29949e86Sstevel } 1584*29949e86Sstevel break; 1585*29949e86Sstevel } 1586*29949e86Sstevel } 1587*29949e86Sstevel 1588*29949e86Sstevel static char * 1589*29949e86Sstevel sysc_rstate_typestr(sysc_cfga_rstate_t rstate, sysc_audit_evt_t event) 1590*29949e86Sstevel { 1591*29949e86Sstevel char *type_str; 1592*29949e86Sstevel 1593*29949e86Sstevel switch (rstate) { 1594*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY: 1595*29949e86Sstevel switch (event) { 1596*29949e86Sstevel case SYSC_AUDIT_RSTATE_EMPTY: 1597*29949e86Sstevel type_str = "emptying"; 1598*29949e86Sstevel break; 1599*29949e86Sstevel case SYSC_AUDIT_RSTATE_SUCCEEDED: 1600*29949e86Sstevel type_str = "emptied"; 1601*29949e86Sstevel break; 1602*29949e86Sstevel case SYSC_AUDIT_RSTATE_EMPTY_FAILED: 1603*29949e86Sstevel type_str = "empty"; 1604*29949e86Sstevel break; 1605*29949e86Sstevel default: 1606*29949e86Sstevel type_str = "empty?"; 1607*29949e86Sstevel break; 1608*29949e86Sstevel } 1609*29949e86Sstevel break; 1610*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED: 1611*29949e86Sstevel switch (event) { 1612*29949e86Sstevel case SYSC_AUDIT_RSTATE_DISCONNECT: 1613*29949e86Sstevel type_str = "disconnecting"; 1614*29949e86Sstevel break; 1615*29949e86Sstevel case SYSC_AUDIT_RSTATE_SUCCEEDED: 1616*29949e86Sstevel type_str = "disconnected"; 1617*29949e86Sstevel break; 1618*29949e86Sstevel case SYSC_AUDIT_RSTATE_DISCONNECT_FAILED: 1619*29949e86Sstevel type_str = "disconnect"; 1620*29949e86Sstevel break; 1621*29949e86Sstevel default: 1622*29949e86Sstevel type_str = "disconnect?"; 1623*29949e86Sstevel break; 1624*29949e86Sstevel } 1625*29949e86Sstevel break; 1626*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED: 1627*29949e86Sstevel switch (event) { 1628*29949e86Sstevel case SYSC_AUDIT_RSTATE_CONNECT: 1629*29949e86Sstevel type_str = "connecting"; 1630*29949e86Sstevel break; 1631*29949e86Sstevel case SYSC_AUDIT_RSTATE_SUCCEEDED: 1632*29949e86Sstevel type_str = "connected"; 1633*29949e86Sstevel break; 1634*29949e86Sstevel case SYSC_AUDIT_RSTATE_CONNECT_FAILED: 1635*29949e86Sstevel type_str = "connect"; 1636*29949e86Sstevel break; 1637*29949e86Sstevel default: 1638*29949e86Sstevel type_str = "connect?"; 1639*29949e86Sstevel break; 1640*29949e86Sstevel } 1641*29949e86Sstevel break; 1642*29949e86Sstevel default: 1643*29949e86Sstevel type_str = "undefined receptacle state"; 1644*29949e86Sstevel break; 1645*29949e86Sstevel } 1646*29949e86Sstevel return (type_str); 1647*29949e86Sstevel } 1648*29949e86Sstevel 1649*29949e86Sstevel static char * 1650*29949e86Sstevel sysc_ostate_typestr(sysc_cfga_ostate_t ostate, sysc_audit_evt_t event) 1651*29949e86Sstevel { 1652*29949e86Sstevel char *type_str; 1653*29949e86Sstevel 1654*29949e86Sstevel switch (ostate) { 1655*29949e86Sstevel case SYSC_CFGA_OSTATE_UNCONFIGURED: 1656*29949e86Sstevel switch (event) { 1657*29949e86Sstevel case SYSC_AUDIT_OSTATE_UNCONFIGURE: 1658*29949e86Sstevel type_str = "unconfiguring"; 1659*29949e86Sstevel break; 1660*29949e86Sstevel case SYSC_AUDIT_OSTATE_SUCCEEDED: 1661*29949e86Sstevel case SYSC_AUDIT_OSTATE_UNCONFIGURE_FAILED: 1662*29949e86Sstevel type_str = "unconfigured"; 1663*29949e86Sstevel break; 1664*29949e86Sstevel default: 1665*29949e86Sstevel type_str = "unconfigure?"; 1666*29949e86Sstevel break; 1667*29949e86Sstevel } 1668*29949e86Sstevel break; 1669*29949e86Sstevel case SYSC_CFGA_OSTATE_CONFIGURED: 1670*29949e86Sstevel switch (event) { 1671*29949e86Sstevel case SYSC_AUDIT_OSTATE_CONFIGURE: 1672*29949e86Sstevel type_str = "configuring"; 1673*29949e86Sstevel break; 1674*29949e86Sstevel case SYSC_AUDIT_OSTATE_SUCCEEDED: 1675*29949e86Sstevel case SYSC_AUDIT_OSTATE_CONFIGURE_FAILED: 1676*29949e86Sstevel type_str = "configured"; 1677*29949e86Sstevel break; 1678*29949e86Sstevel default: 1679*29949e86Sstevel type_str = "configure?"; 1680*29949e86Sstevel break; 1681*29949e86Sstevel } 1682*29949e86Sstevel break; 1683*29949e86Sstevel 1684*29949e86Sstevel default: 1685*29949e86Sstevel type_str = "undefined occupant state"; 1686*29949e86Sstevel break; 1687*29949e86Sstevel } 1688*29949e86Sstevel return (type_str); 1689*29949e86Sstevel } 1690*29949e86Sstevel 1691*29949e86Sstevel static void 1692*29949e86Sstevel sysc_policy_audit_messages(sysc_audit_evt_t event, sysc_cfga_stat_t *sysc_stat) 1693*29949e86Sstevel { 1694*29949e86Sstevel switch (event) { 1695*29949e86Sstevel case SYSC_AUDIT_RSTATE_CONNECT: 1696*29949e86Sstevel cmn_err(CE_NOTE, 1697*29949e86Sstevel "%s %s board in slot %d", 1698*29949e86Sstevel sysc_rstate_typestr(SYSC_CFGA_RSTATE_CONNECTED, 1699*29949e86Sstevel event), 1700*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1701*29949e86Sstevel sysc_stat->board); 1702*29949e86Sstevel break; 1703*29949e86Sstevel case SYSC_AUDIT_RSTATE_DISCONNECT: 1704*29949e86Sstevel cmn_err(CE_NOTE, 1705*29949e86Sstevel "%s %s board in slot %d", 1706*29949e86Sstevel sysc_rstate_typestr( 1707*29949e86Sstevel SYSC_CFGA_RSTATE_DISCONNECTED, 1708*29949e86Sstevel event), 1709*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1710*29949e86Sstevel sysc_stat->board); 1711*29949e86Sstevel break; 1712*29949e86Sstevel case SYSC_AUDIT_RSTATE_SUCCEEDED: 1713*29949e86Sstevel cmn_err(CE_NOTE, 1714*29949e86Sstevel "%s board in slot %d is %s", 1715*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1716*29949e86Sstevel sysc_stat->board, 1717*29949e86Sstevel sysc_rstate_typestr(sysc_stat->rstate, 1718*29949e86Sstevel event)); 1719*29949e86Sstevel break; 1720*29949e86Sstevel case SYSC_AUDIT_RSTATE_CONNECT_FAILED: 1721*29949e86Sstevel cmn_err(CE_NOTE, 1722*29949e86Sstevel "%s board in slot %d failed to %s", 1723*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1724*29949e86Sstevel sysc_stat->board, 1725*29949e86Sstevel sysc_rstate_typestr(SYSC_CFGA_RSTATE_CONNECTED, 1726*29949e86Sstevel event)); 1727*29949e86Sstevel break; 1728*29949e86Sstevel case SYSC_AUDIT_RSTATE_DISCONNECT_FAILED: 1729*29949e86Sstevel cmn_err(CE_NOTE, 1730*29949e86Sstevel "%s board in slot %d failed to %s", 1731*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1732*29949e86Sstevel sysc_stat->board, 1733*29949e86Sstevel sysc_rstate_typestr( 1734*29949e86Sstevel SYSC_CFGA_RSTATE_DISCONNECTED, 1735*29949e86Sstevel event)); 1736*29949e86Sstevel break; 1737*29949e86Sstevel case SYSC_AUDIT_OSTATE_CONFIGURE: 1738*29949e86Sstevel cmn_err(CE_NOTE, 1739*29949e86Sstevel "%s %s board in slot %d", 1740*29949e86Sstevel sysc_ostate_typestr(SYSC_CFGA_OSTATE_CONFIGURED, 1741*29949e86Sstevel event), 1742*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1743*29949e86Sstevel sysc_stat->board); 1744*29949e86Sstevel break; 1745*29949e86Sstevel case SYSC_AUDIT_OSTATE_UNCONFIGURE: 1746*29949e86Sstevel cmn_err(CE_NOTE, 1747*29949e86Sstevel "%s %s board in slot %d", 1748*29949e86Sstevel sysc_ostate_typestr( 1749*29949e86Sstevel SYSC_CFGA_OSTATE_UNCONFIGURED, 1750*29949e86Sstevel event), 1751*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1752*29949e86Sstevel sysc_stat->board); 1753*29949e86Sstevel break; 1754*29949e86Sstevel case SYSC_AUDIT_OSTATE_SUCCEEDED: 1755*29949e86Sstevel cmn_err(CE_NOTE, 1756*29949e86Sstevel "%s board in slot %d is %s", 1757*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1758*29949e86Sstevel sysc_stat->board, 1759*29949e86Sstevel sysc_ostate_typestr(sysc_stat->ostate, 1760*29949e86Sstevel event)); 1761*29949e86Sstevel break; 1762*29949e86Sstevel case SYSC_AUDIT_OSTATE_CONFIGURE_FAILED: 1763*29949e86Sstevel cmn_err(CE_NOTE, 1764*29949e86Sstevel "%s board in slot %d partially %s", 1765*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1766*29949e86Sstevel sysc_stat->board, 1767*29949e86Sstevel sysc_ostate_typestr( 1768*29949e86Sstevel SYSC_CFGA_OSTATE_CONFIGURED, 1769*29949e86Sstevel event)); 1770*29949e86Sstevel break; 1771*29949e86Sstevel case SYSC_AUDIT_OSTATE_UNCONFIGURE_FAILED: 1772*29949e86Sstevel cmn_err(CE_NOTE, 1773*29949e86Sstevel "%s board in slot %d partially %s", 1774*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1775*29949e86Sstevel sysc_stat->board, 1776*29949e86Sstevel sysc_ostate_typestr( 1777*29949e86Sstevel SYSC_CFGA_OSTATE_UNCONFIGURED, 1778*29949e86Sstevel event)); 1779*29949e86Sstevel break; 1780*29949e86Sstevel default: 1781*29949e86Sstevel cmn_err(CE_NOTE, 1782*29949e86Sstevel "unknown audit of a %s %s board in" 1783*29949e86Sstevel " slot %d", 1784*29949e86Sstevel sysc_rstate_typestr(sysc_stat->rstate, 1785*29949e86Sstevel event), 1786*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), 1787*29949e86Sstevel sysc_stat->board); 1788*29949e86Sstevel break; 1789*29949e86Sstevel } 1790*29949e86Sstevel } 1791*29949e86Sstevel 1792*29949e86Sstevel #define MAX_PROP_LEN 33 /* must be > strlen("cpu") */ 1793*29949e86Sstevel 1794*29949e86Sstevel static int 1795*29949e86Sstevel find_and_setup_cpu(int cpuid) 1796*29949e86Sstevel { 1797*29949e86Sstevel return (prom_tree_access(find_and_setup_cpu_start, &cpuid, NULL)); 1798*29949e86Sstevel } 1799*29949e86Sstevel 1800*29949e86Sstevel /* ARGSUSED */ 1801*29949e86Sstevel static int 1802*29949e86Sstevel find_and_setup_cpu_start(void *cpuid_arg, int has_changed) 1803*29949e86Sstevel { 1804*29949e86Sstevel pnode_t nodeid; 1805*29949e86Sstevel int upaid; 1806*29949e86Sstevel char type[MAX_PROP_LEN]; 1807*29949e86Sstevel int cpuid = *(int *)cpuid_arg; 1808*29949e86Sstevel 1809*29949e86Sstevel nodeid = prom_childnode(prom_rootnode()); 1810*29949e86Sstevel while (nodeid != OBP_NONODE) { 1811*29949e86Sstevel if (prom_getproplen(nodeid, "device_type") < MAX_PROP_LEN) 1812*29949e86Sstevel (void) prom_getprop(nodeid, "device_type", 1813*29949e86Sstevel (caddr_t)type); 1814*29949e86Sstevel else 1815*29949e86Sstevel type[0] = '\0'; 1816*29949e86Sstevel (void) prom_getprop(nodeid, "upa-portid", (caddr_t)&upaid); 1817*29949e86Sstevel if ((strcmp(type, "cpu") == 0) && (upaid == cpuid)) { 1818*29949e86Sstevel return (cpu_configure(cpuid)); 1819*29949e86Sstevel } 1820*29949e86Sstevel nodeid = prom_nextnode(nodeid); 1821*29949e86Sstevel } 1822*29949e86Sstevel return (ENODEV); 1823*29949e86Sstevel } 1824*29949e86Sstevel 1825*29949e86Sstevel #define MAX_BOARD_TYPE IO_SBUS_FFB_SOCPLUS_BOARD 1826*29949e86Sstevel 1827*29949e86Sstevel static char sysc_supp_conn[MAX_BOARD_TYPE + 1]; 1828*29949e86Sstevel 1829*29949e86Sstevel static int 1830*29949e86Sstevel sysc_board_connect_supported(enum board_type type) 1831*29949e86Sstevel { 1832*29949e86Sstevel if (type > MAX_BOARD_TYPE) 1833*29949e86Sstevel return (0); 1834*29949e86Sstevel return (sysc_supp_conn[type]); 1835*29949e86Sstevel } 1836*29949e86Sstevel 1837*29949e86Sstevel void 1838*29949e86Sstevel sysc_board_connect_supported_init(void) 1839*29949e86Sstevel { 1840*29949e86Sstevel pnode_t openprom_node; 1841*29949e86Sstevel char sup_list[16]; 1842*29949e86Sstevel int proplen; 1843*29949e86Sstevel int i; 1844*29949e86Sstevel char tstr[3 * 5 + 1]; 1845*29949e86Sstevel 1846*29949e86Sstevel /* Check the firmware for Dynamic Reconfiguration support */ 1847*29949e86Sstevel if (prom_test("SUNW,Ultra-Enterprise,rm-brd") != 0) { 1848*29949e86Sstevel /* The message was printed in platmod:set_platform_defaults */ 1849*29949e86Sstevel enable_dynamic_reconfiguration = 0; 1850*29949e86Sstevel } 1851*29949e86Sstevel 1852*29949e86Sstevel openprom_node = prom_finddevice("/openprom"); 1853*29949e86Sstevel if (openprom_node != OBP_BADNODE) { 1854*29949e86Sstevel proplen = prom_bounded_getprop(openprom_node, 1855*29949e86Sstevel "add-brd-supported-types", 1856*29949e86Sstevel sup_list, sizeof (sup_list) - 1); 1857*29949e86Sstevel } else { 1858*29949e86Sstevel proplen = -1; 1859*29949e86Sstevel } 1860*29949e86Sstevel 1861*29949e86Sstevel if (proplen < 0) { 1862*29949e86Sstevel /* 1863*29949e86Sstevel * This is an old prom which may cause a fatal reset, 1864*29949e86Sstevel * so don't allow any DR operations. 1865*29949e86Sstevel * If enable_dynamic_reconfiguration is 0 1866*29949e86Sstevel * we have already printed a similar message. 1867*29949e86Sstevel */ 1868*29949e86Sstevel if (enable_dynamic_reconfiguration) { 1869*29949e86Sstevel cmn_err(CE_WARN, "Firmware does not support" 1870*29949e86Sstevel " Dynamic Reconfiguration"); 1871*29949e86Sstevel enable_dynamic_reconfiguration = 0; 1872*29949e86Sstevel } 1873*29949e86Sstevel return; 1874*29949e86Sstevel } 1875*29949e86Sstevel for (i = 0; i < proplen; i++) { 1876*29949e86Sstevel switch (sup_list[i]) { 1877*29949e86Sstevel case '0': 1878*29949e86Sstevel sysc_supp_conn[CPU_BOARD] = 1; 1879*29949e86Sstevel sysc_supp_conn[MEM_BOARD] = 1; 1880*29949e86Sstevel break; 1881*29949e86Sstevel case '1': 1882*29949e86Sstevel sysc_supp_conn[IO_2SBUS_BOARD] = 1; 1883*29949e86Sstevel break; 1884*29949e86Sstevel case '2': 1885*29949e86Sstevel sysc_supp_conn[IO_SBUS_FFB_BOARD] = 1; 1886*29949e86Sstevel break; 1887*29949e86Sstevel case '3': 1888*29949e86Sstevel sysc_supp_conn[IO_PCI_BOARD] = 1; 1889*29949e86Sstevel break; 1890*29949e86Sstevel case '4': 1891*29949e86Sstevel sysc_supp_conn[IO_2SBUS_SOCPLUS_BOARD] = 1; 1892*29949e86Sstevel break; 1893*29949e86Sstevel case '5': 1894*29949e86Sstevel sysc_supp_conn[IO_SBUS_FFB_SOCPLUS_BOARD] = 1; 1895*29949e86Sstevel break; 1896*29949e86Sstevel default: 1897*29949e86Sstevel /* Ignore other characters. */ 1898*29949e86Sstevel break; 1899*29949e86Sstevel } 1900*29949e86Sstevel } 1901*29949e86Sstevel if (sysc_supp_conn[CPU_BOARD]) { 1902*29949e86Sstevel cmn_err(CE_NOTE, "!Firmware supports Dynamic Reconfiguration" 1903*29949e86Sstevel " of CPU/Memory boards."); 1904*29949e86Sstevel } else { 1905*29949e86Sstevel cmn_err(CE_NOTE, "Firmware does not support Dynamic" 1906*29949e86Sstevel " Reconfiguration of CPU/Memory boards."); 1907*29949e86Sstevel } 1908*29949e86Sstevel 1909*29949e86Sstevel tstr[0] = '\0'; 1910*29949e86Sstevel if (sysc_supp_conn[IO_2SBUS_BOARD]) 1911*29949e86Sstevel (void) strcat(tstr, ", 1"); 1912*29949e86Sstevel if (sysc_supp_conn[IO_SBUS_FFB_BOARD]) 1913*29949e86Sstevel (void) strcat(tstr, ", 2"); 1914*29949e86Sstevel if (sysc_supp_conn[IO_PCI_BOARD]) 1915*29949e86Sstevel (void) strcat(tstr, ", 3"); 1916*29949e86Sstevel if (sysc_supp_conn[IO_2SBUS_SOCPLUS_BOARD]) 1917*29949e86Sstevel (void) strcat(tstr, ", 4"); 1918*29949e86Sstevel if (sysc_supp_conn[IO_SBUS_FFB_SOCPLUS_BOARD]) 1919*29949e86Sstevel (void) strcat(tstr, ", 5"); 1920*29949e86Sstevel if (tstr[0] != '\0') { 1921*29949e86Sstevel /* Skip leading ", " using &tstr[2]. */ 1922*29949e86Sstevel cmn_err(CE_NOTE, "!Firmware supports Dynamic Reconfiguration" 1923*29949e86Sstevel " of I/O board types %s.", &tstr[2]); 1924*29949e86Sstevel } else { 1925*29949e86Sstevel cmn_err(CE_NOTE, "Firmware does not support Dynamic" 1926*29949e86Sstevel " Reconfiguration of I/O boards."); 1927*29949e86Sstevel } 1928*29949e86Sstevel } 1929*29949e86Sstevel 1930*29949e86Sstevel #ifdef DEBUG 1931*29949e86Sstevel 1932*29949e86Sstevel static void 1933*29949e86Sstevel precache_regdump(int board) 1934*29949e86Sstevel { 1935*29949e86Sstevel fhc_bd_t *curr_bdp; 1936*29949e86Sstevel int bd_idx; 1937*29949e86Sstevel int reg_idx; 1938*29949e86Sstevel 1939*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) { 1940*29949e86Sstevel bcopy((void *) reg_tmpl, (void *) ®_dt[bd_idx][0], 1941*29949e86Sstevel (sizeof (struct regs_data))*NUM_REG); 1942*29949e86Sstevel curr_bdp = fhc_bd(bd_idx); 1943*29949e86Sstevel if (curr_bdp->sc.rstate == SYSC_CFGA_RSTATE_CONNECTED) { 1944*29949e86Sstevel for (reg_idx = 0; reg_idx < NUM_REG; reg_idx++) { 1945*29949e86Sstevel reg_dt[bd_idx][reg_idx].eflag = TRUE; 1946*29949e86Sstevel if (bd_idx != board) 1947*29949e86Sstevel reg_dt[bd_idx][reg_idx].oflag = TRUE; 1948*29949e86Sstevel reg_dt[bd_idx][reg_idx].physaddr += 1949*29949e86Sstevel (FHC_BOARD_SPAN*2*bd_idx); 1950*29949e86Sstevel reg_dt[bd_idx][reg_idx].pre_dsct = 1951*29949e86Sstevel ldphysio(reg_dt[bd_idx][reg_idx].physaddr); 1952*29949e86Sstevel } 1953*29949e86Sstevel } 1954*29949e86Sstevel } 1955*29949e86Sstevel 1956*29949e86Sstevel 1957*29949e86Sstevel } 1958*29949e86Sstevel 1959*29949e86Sstevel static void 1960*29949e86Sstevel boardstat_regdump(void) 1961*29949e86Sstevel { 1962*29949e86Sstevel int bd_idx; 1963*29949e86Sstevel 1964*29949e86Sstevel prom_printf("\nBoard status before disconnect.\n"); 1965*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) { 1966*29949e86Sstevel if (reg_dt[bd_idx][0].eflag == 0) { 1967*29949e86Sstevel prom_printf("Board #%d is idle.\n", bd_idx); 1968*29949e86Sstevel } else { 1969*29949e86Sstevel prom_printf("Board #%d is on.\n", bd_idx); 1970*29949e86Sstevel } 1971*29949e86Sstevel } 1972*29949e86Sstevel 1973*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) { 1974*29949e86Sstevel if (reg_dt[bd_idx][0].eflag) { 1975*29949e86Sstevel prom_printf("\nRegisters for Board #%d", bd_idx); 1976*29949e86Sstevel prom_printf(" (before disconnect).\n"); 1977*29949e86Sstevel prom_printf("AC_BCSR FHC_CTRL JTAG IGN SIM" 1978*29949e86Sstevel " SISM UIM USM\n"); 1979*29949e86Sstevel prom_printf("%08x %08x %08x %04x" 1980*29949e86Sstevel " %08x %04x %08x %04x\n", 1981*29949e86Sstevel reg_dt[bd_idx][0].pre_dsct, 1982*29949e86Sstevel reg_dt[bd_idx][1].pre_dsct, 1983*29949e86Sstevel reg_dt[bd_idx][2].pre_dsct, 1984*29949e86Sstevel reg_dt[bd_idx][3].pre_dsct, 1985*29949e86Sstevel reg_dt[bd_idx][4].pre_dsct, 1986*29949e86Sstevel reg_dt[bd_idx][5].pre_dsct, 1987*29949e86Sstevel reg_dt[bd_idx][6].pre_dsct, 1988*29949e86Sstevel reg_dt[bd_idx][7].pre_dsct); 1989*29949e86Sstevel } 1990*29949e86Sstevel } 1991*29949e86Sstevel 1992*29949e86Sstevel } 1993*29949e86Sstevel 1994*29949e86Sstevel static void 1995*29949e86Sstevel display_regdump(void) 1996*29949e86Sstevel { 1997*29949e86Sstevel int bd_idx; 1998*29949e86Sstevel int reg_idx; 1999*29949e86Sstevel 2000*29949e86Sstevel prom_printf("Board status after disconnect.\n"); 2001*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) { 2002*29949e86Sstevel if (reg_dt[bd_idx][0].oflag == 0) { 2003*29949e86Sstevel prom_printf("Board #%d is idle.\n", bd_idx); 2004*29949e86Sstevel } else { 2005*29949e86Sstevel prom_printf("Board #%d is on.\n", bd_idx); 2006*29949e86Sstevel for (reg_idx = 0; reg_idx < NUM_REG; reg_idx++) 2007*29949e86Sstevel reg_dt[bd_idx][reg_idx].post_dsct = 2008*29949e86Sstevel ldphysio(reg_dt[bd_idx][reg_idx].physaddr); 2009*29949e86Sstevel } 2010*29949e86Sstevel } 2011*29949e86Sstevel 2012*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) { 2013*29949e86Sstevel if (reg_dt[bd_idx][0].eflag) { 2014*29949e86Sstevel prom_printf("\nRegisters for Board #%d", bd_idx); 2015*29949e86Sstevel prom_printf(" (before and after disconnect).\n"); 2016*29949e86Sstevel prom_printf("AC_BCSR FHC_CTRL JTAG IGN SIM" 2017*29949e86Sstevel " SISM UIM USM\n"); 2018*29949e86Sstevel prom_printf("%08x %08x %08x %04x" 2019*29949e86Sstevel " %08x %04x %08x %04x\n", 2020*29949e86Sstevel reg_dt[bd_idx][0].pre_dsct, 2021*29949e86Sstevel reg_dt[bd_idx][1].pre_dsct, 2022*29949e86Sstevel reg_dt[bd_idx][2].pre_dsct, 2023*29949e86Sstevel reg_dt[bd_idx][3].pre_dsct, 2024*29949e86Sstevel reg_dt[bd_idx][4].pre_dsct, 2025*29949e86Sstevel reg_dt[bd_idx][5].pre_dsct, 2026*29949e86Sstevel reg_dt[bd_idx][6].pre_dsct, 2027*29949e86Sstevel reg_dt[bd_idx][7].pre_dsct); 2028*29949e86Sstevel if (reg_dt[bd_idx][0].oflag) { 2029*29949e86Sstevel prom_printf("%08x %08x %08x %04x" 2030*29949e86Sstevel " %08x %04x %08x %04x\n", 2031*29949e86Sstevel reg_dt[bd_idx][0].post_dsct, 2032*29949e86Sstevel reg_dt[bd_idx][1].post_dsct, 2033*29949e86Sstevel reg_dt[bd_idx][2].post_dsct, 2034*29949e86Sstevel reg_dt[bd_idx][3].post_dsct, 2035*29949e86Sstevel reg_dt[bd_idx][4].post_dsct, 2036*29949e86Sstevel reg_dt[bd_idx][5].post_dsct, 2037*29949e86Sstevel reg_dt[bd_idx][6].post_dsct, 2038*29949e86Sstevel reg_dt[bd_idx][7].post_dsct); 2039*29949e86Sstevel } else { 2040*29949e86Sstevel prom_printf("no data (board got" 2041*29949e86Sstevel " disconnected)-------------------" 2042*29949e86Sstevel "---------------\n"); 2043*29949e86Sstevel } 2044*29949e86Sstevel } 2045*29949e86Sstevel 2046*29949e86Sstevel } 2047*29949e86Sstevel 2048*29949e86Sstevel } 2049*29949e86Sstevel 2050*29949e86Sstevel #endif /* DEBUG */ 2051