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