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 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 23 * 24 * Netract Platform specific functions. 25 * 26 * called when : 27 * machine_type == MTYPE_MONTECARLO 28 */ 29 30 /* includes */ 31 #include <assert.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <stddef.h> 35 #include <unistd.h> 36 #include <ctype.h> 37 #include <string.h> 38 #include <strings.h> 39 #include <stropts.h> 40 #include <fcntl.h> 41 #include <kvm.h> 42 #include <kstat.h> 43 #include <sys/types.h> 44 #include <sys/utsname.h> 45 #include <sys/openpromio.h> 46 #include <sys/sunddi.h> 47 #include <sys/ddi_impldefs.h> 48 #include <sys/devinfo_impl.h> 49 #include <sys/ioccom.h> 50 #include <sys/systeminfo.h> 51 #include <libintl.h> 52 #include <config_admin.h> 53 #include "pdevinfo.h" 54 #include "display.h" 55 #include "pdevinfo_sun4u.h" 56 #include "display_sun4u.h" 57 #include "libprtdiag.h" 58 #include "libdevinfo.h" 59 60 /* MC specific header, might just include from MC space */ 61 #include "mct_topology.h" 62 #include "envctrl_gen.h" 63 #include "pcf8574_nct.h" 64 #include "netract_gen.h" 65 #include "hscimpl.h" 66 #include "scsbioctl.h" 67 68 #if !defined(TEXT_DOMAIN) 69 #define TEXT_DOMAIN "SYS_TEST" 70 #endif 71 72 /* globals */ 73 #define MAXNAMESZ 128 74 #define MAX_NODE_NAME_SZ 32 75 76 /* this values equates to Max Tree depth for now */ 77 #define MAXIMUM_DEVS 64 78 79 typedef char device_info_t[MAX_NODE_NAME_SZ]; 80 81 typedef struct { 82 cfga_list_data_t *ldatap; 83 int req; /* If set, this list_data was requested by user */ 84 } ap_out_t; 85 86 87 typedef struct { 88 uint_t slot_addr; 89 uint_t slot_stat; 90 uint_t slot_cond; 91 device_info_t devs_info[MAXIMUM_DEVS]; 92 uint_t number_devs; 93 } mc_slot_info_t; 94 95 typedef struct { 96 mc_slot_info_t mc_slot_info[MC_MAX_SLOTS]; 97 } slot_data_t; 98 99 100 extern char *progname; 101 extern int print_flag; 102 103 /* These are used to store all force loads of the drivers */ 104 static int ps_fd[MC_MAX_PS]; 105 static int oprom_fd; 106 static int slot_index = 0; 107 static int idx_minuscpu = 0; 108 static int num_devs = 0; 109 static int sd_instances[MC_MAX_SLOTS*15]; 110 static int gpio_instances[MC_MAX_PS+MC_MAX_FAN]; 111 static int sd_count = 0; 112 static int st_instance; 113 static int gpio_count = 0; 114 static int slot_table_not_found = 0; 115 116 /* default not present */ 117 static int alarm_card_present = 0; 118 static int cpu_ftm_present = 0; 119 120 /* 121 * We will store all kstat in globals so that 122 * we can browse thru them later 123 */ 124 static int fail_syssoft_prop = 0; 125 static int fail_drv_prop = 0; 126 di_node_t rootnode; /* root nexus */ 127 slot_data_t mc_slots_data; 128 129 /* scsb driver kstats */ 130 scsb_ks_leddata_t scsb_ks_leddata; 131 scsb_ks_state_t scsb_ks_state; 132 mct_topology_t scsb_ks_topo; 133 134 /* pcf8574(gpio) driver kstats */ 135 envctrl_cpuvoltage_t pcf8574_ks_cpuv; 136 envctrl_pwrsupp_t pcf8574_ks_ps1; 137 envctrl_fantray_t pcf8574_ks_fant1; 138 envctrl_pwrsupp_t pcf8574_ks_ps2; 139 envctrl_fantray_t pcf8574_ks_fant2; 140 141 /* pcf8591(adc-dac) driver kstats */ 142 envctrl_temp_t pcf8591_ks_temp; 143 144 hsc_slot_table_t hotswap_slot_table[MC_MAX_SLOTS]; 145 hsc_prom_slot_table_t prom_slot_table[MC_MAX_SLOTS]; 146 147 static char *hotswap_mode = NULL; 148 static char *slot_auto_config[MC_MAX_SLOTS]; 149 static int slot_table_size; 150 151 /* 152 * use this to ascertain what's the system, 153 * default is tonga, we can add more for future variations 154 * 0=tonga, 1=montecarlo 155 * we need also to figure out what the system version is 156 * 0 = 1.5, 1 = 1.0, 0.6 etc. 157 */ 158 int montecarlo = 0; 159 int version_p15_and_p20 = 0; 160 161 #define MAX_PRTDIAG_INFO_LENGTH 1024 162 #define MAX_PRTDIAG_FRUS 22 163 #define BIT_TEST(X, N) ((X) & (1 << (N))) 164 #define SLOT1_OK_BIT 0 165 #define SLOT2_OK_BIT 1 166 #define SLOT3_OK_BIT 2 167 #define SLOT4_OK_BIT 3 168 #define SLOT5_OK_BIT 4 169 #define SLOT6_OK_BIT 5 170 #define SLOT7_OK_BIT 6 171 #define SLOT8_OK_BIT 7 172 #define PDU1_OK_BIT SLOT2_OK_BIT 173 #define PDU2_OK_BIT SLOT4_OK_BIT 174 #define FTM_OK_BIT SLOT5_OK_BIT 175 #define SCB_OK_BIT SLOT6_OK_BIT 176 #define FAN1_OK_BIT SLOT1_OK_BIT 177 #define FAN2_OK_BIT SLOT2_OK_BIT 178 #define DISK1_OK_BIT SLOT4_OK_BIT 179 #define DISK2_OK_BIT SLOT5_OK_BIT 180 #define DISK3_OK_BIT SLOT6_OK_BIT 181 #define PS1_OK_BIT SLOT7_OK_BIT 182 #define PS2_OK_BIT SLOT8_OK_BIT 183 #define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0) 184 #define ENVC_DEBUG_MODE 0x03 185 #define OPENPROMDEV "/dev/openprom" 186 #define I2C_PCF8591_NAME "adc-dac" 187 #define I2C_KSTAT_CPUTEMP "adc_temp" 188 #define SCSB_DEV "scsb" 189 #define SDERR "sderr" 190 #define STERR "sterr" 191 #define OK "ok" 192 #define NOK "Not ok" 193 #define ON "on" 194 #define OFF "off" 195 #define BLINK "blink" 196 #define NA "Not Available" 197 #define UK "Unknown " 198 #define YES "Yes" 199 #define NO "No " 200 #define LO "low" 201 #define HI "high" 202 #define BLANK " " 203 #define SYSSOFT_PROP "System software" 204 #define DRV_PROP "Driver" 205 #define HSC_PROP_NAME "hsc-slot-map" 206 #define HSC_MODE "hotswap-mode" 207 #define PCI_ROOT_AP "pci" 208 #define PROPS "Properties:" 209 #define BOARDTYPE "Board Type:" 210 #define DEVS "Devices:" 211 #define CPCI_IO "CompactPCI IO Slot" 212 #define AC_CARD "Alarm Card" 213 #define CPU_FTM "Front Transition Module" 214 #define SCTRL_PROM_P06 0x00 215 #define SCTRL_PROM_P10 0x01 216 #define SCTRL_PROM_P15 0x02 217 #define SCTRL_PROM_P20 0x03 218 219 #define RMM_NUMBER 3 220 221 #define MONTECARLO_PLATFORM "SUNW,UltraSPARC-IIi-Netract" 222 #define MAKAHA_PLATFORM "SUNW,UltraSPARC-IIe-NetraCT-40" 223 224 /* 225 * The follow table is indexed with the enum's defined by mct_slot_occupant_t 226 * OC_UNKN OC_CPU OC_AC OC_BHS OC_FHS OC_HAHS 227 * OC_QFE OC_FRCH OC_COMBO OC_PMC OC_ATM 228 * 229 * But "scsb" can currently identify only CPU and Alarm Cards by known 230 * slot numbers. 231 */ 232 char *slot_occupants[] = { 233 CPCI_IO, 234 "CPU board ", 235 CPCI_IO, 236 "Basic HotSwap Board", 237 "Full HotSwap Board", 238 "HA Board", 239 "QFE Board", 240 "Fresh Choice Board", 241 "SUN Combo Board", 242 "PMC Board", 243 "ATM Board" 244 }; 245 246 static char *prtdiag_fru_types[] = { 247 "I/O ", /* 0 */ 248 "CPU ", 249 "PSU ", 250 "HDD ", 251 "FAN ", 252 "Alarm Card ", 253 "SCB ", 254 "SSB ", 255 "CFTM ", 256 "CRTM ", 257 "PRTM ", 258 "Midplane " /* 11 */ 259 }; 260 261 char prtdiag_fru_info[MAX_PRTDIAG_FRUS][MAX_PRTDIAG_INFO_LENGTH]; 262 263 #define SCB_REG_READ 1 264 #define SCB_REG_WRITE 2 265 266 /* Standard Device nodes - hardwired for now */ 267 /* will include fan tray later, cpu voltage not impl */ 268 static char *scsb_node = NULL; 269 static char **ps_node = NULL; 270 static char *temp_node = NULL; 271 272 static char *mc_scsb_node = 273 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/sysctrl@0,80:scsb"; 274 275 static char *ot_scsb_node = 276 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/sysctrl@0,80:scsb"; 277 278 static char *mc_ps_node[] = { 279 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7c:pwrsuppply", 280 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7e:pwrsuppply" 281 }; 282 283 static char *ot_ps_node[] = { 284 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7c:pwrsuppply", 285 "/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7e:pwrsuppply" 286 }; 287 288 static char *mc_temp_node = 289 "/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/adc-dac@0,9e:cputemp"; 290 291 /* 292 * these functions will overlay the symbol table of libprtdiag 293 * at runtime (netract systems only) 294 * display functions 295 */ 296 int display(Sys_tree *, Prom_node *, struct system_kstat_data *, int); 297 /* local functions */ 298 /* 299 * prom function 300 */ 301 static void gather_diaginfo(int flag); 302 static int extract_slot_table_from_obp(); 303 static int mc_next(int id); 304 static void mc_walk(int id); 305 static int mc_child(int id); 306 static void mc_dump_node(int id); 307 static int mc_getpropval(struct openpromio *opp); 308 309 #ifdef REDUNDANT_INFO 310 static int mc_get_cpu_freq(Prom_node *node); 311 static int mc_get_ecache_size(Prom_node *node); 312 static void mc_display_cpus(Board_node *board); 313 static void mc_display_cpu_devices(Sys_tree *tree); 314 #endif /* REDUNDANT_INFO */ 315 316 static void netract_disp_prom_version(); 317 318 /* 319 * Since we do not have a system wide kstat for MC/Tg 320 * here we have to do specific kstats to drivers that 321 * post this information - MC/Tg specific drivers 322 * that post kstat here are : scsb, pcf8574(gpio) and pcf8591 323 */ 324 static int analyze_nodes(di_node_t, void*); 325 static void analyze_pcipci_siblings(di_node_t); 326 static void display_mc_prtdiag_info(); 327 static int dump_devs(di_node_t, void *); 328 static void prtdiag_devinfo(void); 329 static void force_load_drivers(); 330 static int dump_prop_list(char *name, 331 di_node_t node, di_prop_t (*nxtprop)()); 332 static void *config_calloc_check(size_t nelem, size_t elsize); 333 static void explore_slot_occupants(); 334 static void do_scsb_kstat(); 335 static void do_pcf8574_kstat(); 336 static void do_pcf8591_kstat(); 337 static void do_promversion(); 338 static int mc_promopen(int oflag); 339 static int scsi_disk_status(int disk_number); 340 static void alarm_card_occupant(); 341 static int scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode); 342 static int scsb_ioc_reg_read(int fd, uchar_t index, 343 scsb_ioc_rdwr_t *ioc_rd, int num); 344 345 static int check_platform(); 346 347 int 348 display(Sys_tree *tree, 349 Prom_node *root, 350 struct system_kstat_data *kstats, 351 int syserrlog) 352 { 353 int exit_code = 0; /* init to all OK */ 354 void *value; /* used for opaque PROM data */ 355 struct mem_total memory_total; /* Total memory in system */ 356 struct grp_info grps; /* Info on all groups in system */ 357 #ifdef lint 358 syserrlog = syserrlog; 359 #endif 360 sys_clk = -1; /* System clock freq. (in MHz) */ 361 /* 362 * Now display the machine's configuration. We do this if we 363 * are not logging or exit_code is set (machine is broke). 364 */ 365 if (!logging || exit_code) { 366 struct utsname uts_buf; 367 368 /* 369 * Display system banner 370 */ 371 (void) uname(&uts_buf); 372 373 log_printf(dgettext(TEXT_DOMAIN, 374 "System Configuration: Oracle Corporation" 375 " %s %s\n"), uts_buf.machine, 376 get_prop_val(find_prop(root, "banner-name")), 0); 377 378 /* display system clock frequency */ 379 value = get_prop_val(find_prop(root, "clock-frequency")); 380 if (value != NULL) { 381 sys_clk = ((*((int *)value)) + 500000) / 1000000; 382 log_printf(dgettext(TEXT_DOMAIN, 383 "System clock frequency: " 384 "%d MHz\n"), sys_clk, 0); 385 } 386 387 /* Display the Memory Size */ 388 display_memorysize(tree, kstats, &grps, &memory_total); 389 /* Lets make sure we have all the needed drivers loaded */ 390 /* display Montecarlo/Tonga FRU information */ 391 if (!extract_slot_table_from_obp()) 392 log_printf(dgettext(TEXT_DOMAIN, 393 "\r\nslot-table not available\r\n"), 0); 394 do_scsb_kstat(); 395 force_load_drivers(); 396 gather_diaginfo(print_flag && !logging); 397 /* figure out if ac is present */ 398 alarm_card_occupant(); 399 /* platform specific display mod */ 400 display_mc_prtdiag_info(); 401 di_fini(rootnode); 402 netract_disp_prom_version(); 403 } /* if (!logging || exit_code) */ 404 405 return (exit_code); 406 407 } /* display(....) */ 408 409 static int 410 check_platform() 411 { 412 char si_platform[SYS_NMLN]; 413 414 /* 415 * Check for the platform: Montecarlo or Makaha/CP2040 based 416 */ 417 if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) { 418 return (-1); 419 } 420 421 if ((strncmp(si_platform, MONTECARLO_PLATFORM, 422 strlen(MONTECARLO_PLATFORM))) == 0) { 423 scsb_node = mc_scsb_node; 424 ps_node = mc_ps_node; 425 temp_node = mc_temp_node; 426 } else if ((strncmp(si_platform, MAKAHA_PLATFORM, 427 strlen(MAKAHA_PLATFORM))) == 0) { 428 scsb_node = ot_scsb_node; 429 ps_node = ot_ps_node; 430 temp_node = NULL; 431 } else { 432 return (-1); 433 } 434 435 return (0); 436 } 437 438 void 439 force_load_drivers() 440 { 441 int i; 442 443 if (NULL == scsb_node || NULL == ps_node) { 444 if (check_platform() == -1) { 445 return; 446 } 447 } 448 449 /* check scb/ssb presence */ 450 if (scsb_ks_state.scb_present || scsb_ks_state.ssb_present) { 451 if (open(scsb_node, O_RDONLY) < 0) 452 log_printf(dgettext(TEXT_DOMAIN, 453 "\nscsb open FAILED!"), 0); 454 } 455 456 /* check the num of PS we have */ 457 for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) { 458 if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) { 459 if ((ps_fd[i] = open(ps_node[i], O_RDONLY)) < 0) 460 log_printf(dgettext(TEXT_DOMAIN, 461 "\npowersupply%d open failed"), 462 i, 0); 463 } 464 } /* for */ 465 466 /* open the cpu temp driver */ 467 if (temp_node) { 468 if (open(temp_node, O_RDONLY) < 0) 469 log_printf(dgettext(TEXT_DOMAIN, 470 "\ncputemp open FAILED!"), 0); 471 } 472 } 473 474 475 void 476 explore_slot_occupants() 477 { 478 char *cp = NULL; 479 int index; 480 int ret = CFGA_ERROR; 481 char *estrp = NULL; 482 cfga_list_data_t *list_array = NULL; 483 ap_out_t *out_array = NULL; 484 int nlist = 0; 485 char *prefilt_optp = NULL; 486 int dyn_exp = 1; 487 char *plat_opts = NULL; 488 489 ret = config_list_ext(0, NULL, &list_array, 490 &nlist, plat_opts, prefilt_optp, &estrp, 491 dyn_exp ? CFGA_FLAG_LIST_ALL : 0); 492 if (ret != CFGA_OK) { 493 log_printf(dgettext(TEXT_DOMAIN, 494 "\ncannot explore configuration"), 0); 495 return; 496 } 497 assert(nlist != 0); 498 out_array = config_calloc_check(nlist, sizeof (*out_array)); 499 if (out_array == NULL) { 500 ret = CFGA_LIB_ERROR; 501 goto bail; 502 } 503 /* create a list of output stat data */ 504 for (index = 0; index < nlist; index++) { 505 out_array[index].ldatap = &list_array[index]; 506 out_array[index].req = 0; 507 } 508 509 for (index = 0; index < nlist; index++) { 510 if ((cp = strstr(out_array[index].ldatap->ap_phys_id, 511 "cpci_slot")) != NULL) { 512 mc_slots_data.mc_slot_info[idx_minuscpu].slot_stat 513 = out_array[index].ldatap->ap_o_state; 514 mc_slots_data.mc_slot_info[idx_minuscpu].slot_cond 515 = out_array[index].ldatap->ap_cond; 516 idx_minuscpu++; 517 } 518 } 519 bail: 520 S_FREE(list_array); 521 S_FREE(out_array); 522 } 523 524 525 /* 526 * config_calloc_check - perform allocation, check result and 527 * set error indicator 528 */ 529 void * 530 config_calloc_check( 531 size_t nelem, 532 size_t elsize) 533 { 534 void *p; 535 static char alloc_fail[] = 536 "%s: memory allocation failed (%d*%d bytes)\n"; 537 538 p = calloc(nelem, elsize); 539 if (p == NULL) { 540 log_printf(dgettext(TEXT_DOMAIN, alloc_fail), nelem, elsize, 0); 541 } 542 return (p); 543 } 544 545 546 void 547 do_scsb_kstat() 548 { 549 kstat_ctl_t *kc; 550 kstat_t *ksp_leddata; 551 kstat_t *ksp_state; 552 kstat_t *ksp_topo; 553 scsb_ks_leddata_t *pks_leddata; 554 scsb_ks_state_t *pks_state; 555 mct_topology_t *pks_topo; 556 int i; 557 558 #ifdef DEBUG_TEMP1 559 int index; 560 #endif 561 if (!(kc = kstat_open())) { 562 #ifdef DEBUG_TEMP 563 log_printf("\nkstat_open failed", 0); 564 #endif 565 return; 566 } 567 #ifdef lint 568 kc = kc; 569 #endif 570 /* get kstat on scsb led data */ 571 if ((ksp_leddata = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_LEDDATA)) 572 == NULL) { 573 #ifdef DEBUG_TEMP 574 log_printf("\nkstat_lookup for scsb_leddata failed", 0); 575 #endif 576 return; 577 } 578 if (kstat_read(kc, ksp_leddata, NULL) == -1) { 579 #ifdef DEBUG_TEMP 580 log_printf("\nkstat_read for scsb_leddata failed", 0); 581 #endif 582 return; 583 } 584 pks_leddata = (scsb_ks_leddata_t *)ksp_leddata->ks_data; 585 scsb_ks_leddata = *pks_leddata; /* set the globals for future */ 586 #ifdef DEBUG_LEDS 587 /* dump the kstat leddata */ 588 printf("\nDumping LED regs: "); 589 for (i = 0; i < SCSB_LEDDATA_REGISTERS; ++i) { 590 log_printf("0x%x ", pks_leddata->scb_led_regs[i] & 0xff, 0); 591 } 592 log_printf("\n", 0); 593 #endif 594 /* get kstat on scsb states */ 595 if ((ksp_state = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_STATE)) 596 == NULL) { 597 #ifdef DEBUG_TEMP 598 log_printf("\nkstat_lookup for scsb_state failed", 0); 599 #endif 600 return; 601 } 602 if (kstat_read(kc, ksp_state, NULL) == -1) { 603 #ifdef DEBUG_TEMP 604 log_printf("\nkstat_read for scsb_state failed", 0); 605 #endif 606 return; 607 } 608 pks_state = (scsb_ks_state_t *)ksp_state->ks_data; 609 scsb_ks_state = *pks_state; /* set the global for future */ 610 #ifdef DEBUG_TEMP1 611 /* dump the kstat state */ 612 log_printf("\tSCB is%spresent\n", 613 pks_state->scb_present ? " " : " not ", 0); 614 log_printf("\tSSB is%spresent\n", 615 pks_state->ssb_present ? " " : " not ", 0); 616 log_printf("\tscsb is%sfrozen\n", 617 pks_state->scsb_frozen ? " " : " not ", 0); 618 log_printf("\tscsb mode: ", 0); 619 switch (pks_state->scsb_mode) { 620 case ENVC_DEBUG_MODE: 621 log_printf("DEBUG MODE\n", 0); 622 break; 623 case ENVCTRL_DIAG_MODE: 624 log_printf("DIAGNOSTIC MODE\n", 0); 625 break; 626 case ENVCTRL_NORMAL_MODE: 627 log_printf("NORMAL MODE\n", 0); 628 break; 629 } 630 log_printf("\tscsb event code: 0x%x\n", pks_state->event_code, 0); 631 #endif /* DEBUG_TEMP1 */ 632 633 if ((ksp_topo = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_TOPOLOGY)) 634 == NULL) { 635 #ifdef DEBUG_TEMP 636 log_printf("\nkstat_lookup for scsb_topo failed", 0); 637 #endif 638 return; 639 } 640 if (kstat_read(kc, ksp_topo, NULL) == -1) { 641 #ifdef DEBUG_TEMP 642 log_printf("\nkstat_read for scsb_topo failed", 0); 643 #endif 644 return; 645 } 646 pks_topo = (mct_topology_t *)ksp_topo->ks_data; 647 scsb_ks_topo = *pks_topo; /* set the global for future */ 648 /* 649 * we need to set this so that we can get status info 650 * for the 2 powersupplies in MC as we need to get 651 * kstat from both driver instances for environment 652 */ 653 if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF) 654 montecarlo = 1; /* Monte Carlo */ 655 /* 656 * HW version 0.6 and 1.0 had different led maps 657 * its assumed that HW 2.0 would not change this 658 * need to modify if it does 659 */ 660 if ((pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P15) || 661 (pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P20)) { 662 version_p15_and_p20 = 1; 663 } 664 665 /* set flag to note that CFTM is present */ 666 for (i = 0; i < pks_topo->max_units[CFTM]; ++i) { 667 if (pks_topo->mct_cftm[i].fru_status == FRU_PRESENT) 668 cpu_ftm_present = 1; 669 } 670 671 #ifdef DEBUG_TEMP1 672 /* 673 * Midplane 674 */ 675 log_printf("Midplane type: ", 0); 676 if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF) 677 log_printf("Netra ct800 server\n", 0); 678 else 679 log_printf("Netra ct400 server%s\n", 680 pks_topo->mid_plane.fru_id == 681 SCTRL_MPID_QUARTER_NODSK ? ", no disk" : " with disk", 0); 682 log_printf("Midplane version: %d\n", 683 pks_topo->mid_plane.fru_version, 0); 684 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 685 pks_topo->mct_scb[0].fru_type, 686 pks_topo->mct_scb[0].fru_unit, 687 pks_topo->mct_scb[0].fru_id, 688 pks_topo->mct_scb[0].fru_version, 0); 689 /* 690 * Slots 691 */ 692 log_printf("Slots present out of maximum %d\n", 693 pks_topo->max_units[SLOT], 0); 694 for (i = 0; i < pks_topo->max_units[SLOT]; ++i) { 695 if (pks_topo->mct_slots[i].fru_status != FRU_PRESENT) 696 continue; 697 index = (int)pks_topo->mct_slots[i].fru_type; 698 log_printf("\tSlot %d occupant: %s;", 699 pks_topo->mct_slots[i].fru_unit, slot_occupants[index], 0); 700 log_printf(" ID 0x%x; VER 0x%x ; ", 701 pks_topo->mct_slots[i].fru_id, 702 pks_topo->mct_slots[i].fru_version, 0); 703 log_printf(" Slot health %d\n", 704 pks_topo->mct_slots[i].fru_health, 0); 705 /* pks_topo->mct_slots[i].fru_health */ 706 } 707 708 /* 709 * PDU 710 */ 711 log_printf("PDUs present out of maximum %d\n", 712 pks_topo->max_units[PDU], 0); 713 for (i = 0; i < pks_topo->max_units[PDU]; ++i) { 714 if (pks_topo->mct_pdu[i].fru_status != FRU_PRESENT) 715 continue; 716 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 717 pks_topo->mct_pdu[i].fru_type, 718 pks_topo->mct_pdu[i].fru_unit, 719 pks_topo->mct_pdu[i].fru_id, 720 pks_topo->mct_pdu[i].fru_version, 0); 721 /* pks_topo->mct_pdu[i].fru_health */ 722 } 723 724 /* 725 * Power Supplies 726 */ 727 log_printf("Power Supplies present out of maximum %d\n", 728 pks_topo->max_units[PS], 0); 729 for (i = 0; i < pks_topo->max_units[PS]; ++i) { 730 if (pks_topo->mct_ps[i].fru_status != FRU_PRESENT) 731 continue; 732 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 733 pks_topo->mct_ps[i].fru_type, 734 pks_topo->mct_ps[i].fru_unit, 735 pks_topo->mct_ps[i].fru_id, 736 pks_topo->mct_ps[i].fru_version, 0); 737 } 738 739 /* 740 * Disks 741 */ 742 log_printf("Disks present out of maximum %d\n", 743 pks_topo->max_units[DISK], 0); 744 for (i = 0; i < pks_topo->max_units[DISK]; ++i) { 745 if (pks_topo->mct_disk[i].fru_status != FRU_PRESENT) 746 continue; 747 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 748 pks_topo->mct_disk[i].fru_type, 749 pks_topo->mct_disk[i].fru_unit, 750 pks_topo->mct_disk[i].fru_id, 751 pks_topo->mct_disk[i].fru_version, 0); 752 } 753 754 /* 755 * Fans 756 */ 757 log_printf("Fans present out of maximum %d\n", 758 pks_topo->max_units[FAN], 0); 759 for (i = 0; i < pks_topo->max_units[FAN]; ++i) { 760 if (pks_topo->mct_fan[i].fru_status != FRU_PRESENT) 761 continue; 762 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 763 pks_topo->mct_fan[i].fru_type, 764 pks_topo->mct_fan[i].fru_unit, 765 pks_topo->mct_fan[i].fru_id, 766 pks_topo->mct_fan[i].fru_version, 0); 767 } 768 769 /* 770 * SCBs 771 */ 772 log_printf("SCBs present out of maximum %d\n", 773 pks_topo->max_units[SCB], 0); 774 for (i = 0; i < pks_topo->max_units[SCB]; ++i) { 775 if (pks_topo->mct_scb[i].fru_status != FRU_PRESENT) 776 continue; 777 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 778 pks_topo->mct_scb[i].fru_type, 779 pks_topo->mct_scb[i].fru_unit, 780 pks_topo->mct_scb[i].fru_id, 781 pks_topo->mct_scb[i].fru_version, 0); 782 } 783 784 /* 785 * SSBs 786 */ 787 log_printf("SSBs present out of maximum %d\n", 788 pks_topo->max_units[SSB], 0); 789 for (i = 0; i < pks_topo->max_units[SSB]; ++i) { 790 if (pks_topo->mct_ssb[i].fru_status != FRU_PRESENT) 791 continue; 792 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 793 pks_topo->mct_ssb[i].fru_type, 794 pks_topo->mct_ssb[i].fru_unit, 795 pks_topo->mct_ssb[i].fru_id, 796 pks_topo->mct_ssb[i].fru_version, 0); 797 } 798 799 /* 800 * Alarms Cards 801 */ 802 log_printf("Alarm Cards present out of maximum %d\n", 803 pks_topo->max_units[ALARM], 0); 804 for (i = 0; i < pks_topo->max_units[ALARM]; ++i) { 805 if (pks_topo->mct_alarm[i].fru_status != FRU_PRESENT) 806 continue; 807 log_printf("\ttype %d; unit %d; id 0x%x; VER 0x%x\n", 808 pks_topo->mct_alarm[i].fru_type, 809 pks_topo->mct_alarm[i].fru_unit, 810 pks_topo->mct_alarm[i].fru_id, 811 pks_topo->mct_alarm[i].fru_version, 0); 812 } 813 814 /* 815 * CFTMs 816 */ 817 log_printf("CFTMs present out of maximum %d\n", 818 pks_topo->max_units[CFTM], 0); 819 for (i = 0; i < pks_topo->max_units[CFTM]; ++i) { 820 if (pks_topo->mct_cftm[i].fru_status != FRU_PRESENT) 821 continue; 822 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 823 pks_topo->mct_cftm[i].fru_type, 824 pks_topo->mct_cftm[i].fru_unit, 825 pks_topo->mct_cftm[i].fru_id, 826 pks_topo->mct_cftm[i].fru_version, 0); 827 } 828 829 /* 830 * CRTMs 831 */ 832 log_printf("CRTMs present out of maximum %d\n", 833 pks_topo->max_units[CRTM], 0); 834 for (i = 0; i < pks_topo->max_units[CRTM]; ++i) { 835 if (pks_topo->mct_crtm[i].fru_status != FRU_PRESENT) 836 continue; 837 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 838 pks_topo->mct_crtm[i].fru_type, 839 pks_topo->mct_crtm[i].fru_unit, 840 pks_topo->mct_crtm[i].fru_id, 841 pks_topo->mct_crtm[i].fru_version, 0); 842 } 843 844 /* 845 * PRTMs 846 */ 847 log_printf("PRTMs present out of maximum %d\n", 848 pks_topo->max_units[PRTM], 0); 849 for (i = 0; i < pks_topo->max_units[PRTM]; ++i) { 850 if (pks_topo->mct_prtm[i].fru_status != FRU_PRESENT) 851 continue; 852 log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n", 853 pks_topo->mct_prtm[i].fru_type, 854 pks_topo->mct_prtm[i].fru_unit, 855 pks_topo->mct_prtm[i].fru_id, 856 pks_topo->mct_prtm[i].fru_version, 0); 857 } 858 #endif /* DEBUG_TEMP1 */ 859 860 } /* do_scsb_kstat(...) */ 861 862 863 void 864 do_pcf8574_kstat() 865 { 866 kstat_ctl_t *kc; 867 kstat_t *ksp_ps; 868 kstat_t *ksp_fan; 869 envctrl_pwrsupp_t *pks_ps; 870 envctrl_fantray_t *pks_fan; 871 int i; 872 char *kstat_name = NULL; 873 874 if (!(kc = kstat_open())) { 875 #ifdef DEBUG_TEMP 876 log_printf("\nkstat_open for pcf8574 failed", 0); 877 #endif 878 return; 879 } 880 881 #ifdef lint 882 kc = kc; 883 #endif 884 /* get kstat on gpio powersupply and fan states */ 885 for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) { 886 if (i == 1) { 887 kstat_name = I2C_KSTAT_PWRSUPPLY; 888 strncat(kstat_name, "1", 1); 889 } else { 890 kstat_name = I2C_KSTAT_PWRSUPPLY; 891 strncat(kstat_name, "2", 1); 892 } 893 if ((ksp_ps = kstat_lookup(kc, I2C_PCF8574_NAME, 0, kstat_name)) 894 == NULL) { 895 #ifdef DEBUG_TEMP 896 log_printf("\nks lookup for pwrsupply%d failed", 897 i+1, 0); 898 #endif 899 return; 900 } 901 if (kstat_read(kc, ksp_ps, NULL) == -1) { 902 #ifdef DEBUG_TEMP 903 log_printf("\nks read for pwrsupply%d failed", i+1, 0); 904 #endif 905 return; 906 } 907 pks_ps = (envctrl_pwrsupp_t *)ksp_ps->ks_data; 908 if (i == 1) 909 pcf8574_ks_ps1 = *pks_ps; /* ps 1 */ 910 else 911 pcf8574_ks_ps2 = *pks_ps; /* ps 2 */ 912 } /* for */ 913 for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) { 914 if (i == 1) { 915 kstat_name = I2C_KSTAT_FANTRAY; 916 strncat(kstat_name, "1", 1); 917 } else { 918 kstat_name = I2C_KSTAT_FANTRAY; 919 strncat(kstat_name, "2", 1); 920 } 921 if ((ksp_fan = kstat_lookup(kc, I2C_PCF8574_NAME, 922 0, kstat_name)) == NULL) { 923 #ifdef DEBUG_TEMP 924 log_printf("\nks lookup for fantray%d failed", 925 i+1, 0); 926 #endif 927 return; 928 } 929 if (kstat_read(kc, ksp_fan, NULL) == -1) { 930 #ifdef DEBUG_TEMP 931 log_printf("\nks read for fantray%d failed", i+1, 0); 932 #endif 933 return; 934 } 935 pks_fan = (envctrl_fantray_t *)ksp_fan->ks_data; 936 if (i == 1) 937 pcf8574_ks_fant1 = *pks_fan; /* fan 1 */ 938 else 939 pcf8574_ks_fant2 = *pks_fan; /* fan 2 */ 940 } /* for */ 941 kstat_close(kc); 942 943 } /* do_pcf8574_kstat(...) */ 944 945 void 946 do_pcf8591_kstat() 947 { 948 kstat_ctl_t *kc; 949 kstat_t *ksp_temp; 950 951 envctrl_temp_t *pks_temp; 952 953 if (!(kc = kstat_open())) { 954 #ifdef DEBUG_TEMP 955 log_printf("ks open for pcf8591 failed", 0); 956 #endif 957 return; 958 } 959 #ifdef lint 960 kc = kc; 961 #endif 962 /* get kstat on adc driver's CPU temperature data */ 963 if ((ksp_temp = kstat_lookup(kc, I2C_PCF8591_NAME, 964 -1, I2C_KSTAT_CPUTEMP)) 965 == NULL) { 966 #ifdef DEBUG_TEMP 967 log_printf("ks lookup for adc_temp failed", 0); 968 #endif 969 return; 970 } 971 if (kstat_read(kc, ksp_temp, NULL) == -1) { 972 #ifdef DEBUG_TEMP 973 log_printf("ks read for adc_temp failed", 0); 974 #endif 975 return; 976 } 977 pks_temp = (envctrl_temp_t *)ksp_temp->ks_data; 978 pcf8591_ks_temp = *pks_temp; 979 kstat_close(kc); 980 } /* do_pcf8591_kstat(.) */ 981 982 983 void 984 gather_diaginfo(int flag) 985 { 986 if (flag) { 987 /* gather system environmental conditions. */ 988 /* obtain kstat info from gpio & temp. driver */ 989 do_pcf8574_kstat(); 990 do_pcf8591_kstat(); 991 explore_slot_occupants(); /* fill in some occupant info */ 992 prtdiag_devinfo(); 993 analyze_pcipci_siblings(rootnode); 994 } 995 996 } /* display_diaginfo(...) */ 997 998 void 999 netract_disp_prom_version() 1000 { 1001 /* Display Prom revision header */ 1002 log_printf(dgettext(TEXT_DOMAIN, "System Board PROM revision:\n"), 0); 1003 log_printf("---------------------------\n", 0); 1004 do_promversion(); 1005 1006 } /* netract_disp_prom_version(.) */ 1007 1008 1009 /* 1010 * Get and print the PROM version. 1011 */ 1012 void 1013 do_promversion(void) 1014 { 1015 Oppbuf oppbuf; 1016 struct openpromio *opp = &(oppbuf.opp); 1017 1018 if (mc_promopen(O_RDONLY)) { 1019 log_printf(dgettext(TEXT_DOMAIN, 1020 "\nCannot open openprom device"), 0); 1021 return; 1022 } 1023 1024 opp->oprom_size = MAXVALSIZE; 1025 if (ioctl(oprom_fd, OPROMGETVERSION, opp) < 0) { 1026 perror("\nOPROMGETVERSION ioctl failed"); 1027 return; 1028 } 1029 log_printf("%s\n", opp->oprom_array, 0); 1030 1031 if (close(oprom_fd) < 0) { 1032 log_printf(dgettext(TEXT_DOMAIN, 1033 "\nclose error on %s"), OPENPROMDEV, 0); 1034 return; 1035 } 1036 } /* do_promversion() */ 1037 1038 int 1039 mc_promopen(int oflag) 1040 { 1041 for (;;) { 1042 if ((oprom_fd = open(OPENPROMDEV, oflag)) < 0) { 1043 if (errno == EAGAIN) { 1044 (void) sleep(5); 1045 continue; 1046 } 1047 if (errno == ENXIO) 1048 return (-1); 1049 log_printf(dgettext(TEXT_DOMAIN, 1050 "\ncannot open %s"), OPENPROMDEV, 0); 1051 return (1); 1052 } else 1053 return (0); 1054 } 1055 } 1056 1057 1058 /* 1059 * This will return -1 for status unknown, 0 for OK, and 1 for failed (scsi 1060 * hard errors) 1061 * swiped from envmon policies 1062 */ 1063 int 1064 scsi_disk_status(int disk_number) 1065 { 1066 kstat_ctl_t *kc; 1067 kstat_t *ksp_disk; 1068 kstat_named_t *disk_data; 1069 1070 int i; 1071 int nlist = 0; 1072 cfga_list_data_t *list_array = NULL; 1073 char *ap_ids[] = {"c0"}; 1074 1075 if ((kc = kstat_open()) == NULL) { 1076 log_printf(dgettext(TEXT_DOMAIN, "\nks open failed"), 0); 1077 return (-1); 1078 } 1079 1080 if (disk_number == RMM_NUMBER) { /* RMM */ 1081 if (config_list_ext(1, ap_ids, &list_array, &nlist, 1082 NULL, NULL, NULL, CFGA_FLAG_LIST_ALL) != CFGA_OK) { 1083 kstat_close(kc); 1084 return (-1); 1085 } 1086 for (i = 0; i < nlist; i++) { 1087 if (strstr(list_array[i].ap_phys_id, "rmt/0") != NULL) { 1088 /* Tape drive */ 1089 if (list_array[i].ap_o_state == 1090 CFGA_STAT_UNCONFIGURED) { 1091 kstat_close(kc); 1092 return (-1); 1093 } 1094 if ((ksp_disk = kstat_lookup(kc, STERR, 1095 st_instance, NULL)) == NULL) { 1096 kstat_close(kc); 1097 return (-1); 1098 } 1099 break; 1100 } else if (strstr(list_array[i].ap_phys_id, 1101 "dsk/c0t6d0") != NULL) { 1102 /* CD_ROM */ 1103 if (list_array[i].ap_o_state == 1104 CFGA_STAT_UNCONFIGURED) { 1105 kstat_close(kc); 1106 return (-1); 1107 } 1108 if ((ksp_disk = kstat_lookup(kc, SDERR, 1109 sd_instances[disk_number-1], NULL)) == 1110 NULL) { 1111 kstat_close(kc); 1112 return (-1); 1113 } 1114 break; 1115 } 1116 } 1117 } else { /* Hard disk */ 1118 if ((ksp_disk = kstat_lookup(kc, SDERR, 1119 sd_instances[disk_number-1], NULL)) == NULL) { 1120 kstat_close(kc); 1121 return (-1); 1122 } 1123 } 1124 1125 if (kstat_read(kc, ksp_disk, NULL) == -1) { 1126 log_printf(dgettext(TEXT_DOMAIN, 1127 "\nks read error for disk%d, drv inst%d"), 1128 disk_number, sd_instances[disk_number-1], 0); 1129 kstat_close(kc); 1130 return (-1); 1131 } 1132 disk_data = KSTAT_NAMED_PTR(ksp_disk); 1133 /* 1134 * if disk_data[].value is >0, we have a problem 1135 */ 1136 if (disk_data[1].value.ui32 == 0) { 1137 kstat_close(kc); 1138 return (0); 1139 } else { 1140 kstat_close(kc); 1141 return (1); 1142 } 1143 } 1144 1145 1146 void 1147 prtdiag_devinfo(void) 1148 { 1149 uint_t flag; 1150 /* lets get everything we can from kernel */ 1151 flag = DINFOSUBTREE|DINFOPROP; 1152 rootnode = di_init("/", flag); 1153 if (rootnode == DI_NODE_NIL) { 1154 log_printf(dgettext(TEXT_DOMAIN, 1155 "\nprtdiag_devinfo: di_init() failed"), 0); 1156 return; 1157 } 1158 (void) di_walk_node(rootnode, DI_WALK_CLDFIRST, NULL, 1159 dump_devs); 1160 } 1161 1162 1163 /* 1164 * gather information about this node, returns appropriate code. 1165 * specific information we seek are driver names, instances 1166 * we will initialize some globals depending on what we find 1167 * from the kernel device tree info and may be private data 1168 * if required 1169 */ 1170 /*ARGSUSED1*/ 1171 int 1172 dump_devs(di_node_t node, void *arg) 1173 { 1174 char *driver_name; 1175 1176 driver_name = di_driver_name(node); 1177 /* we will initialize our globals here */ 1178 if ((di_instance(node) >= 0) && 1179 (driver_name != NULL) && 1180 (!(di_state(node) & DI_DRIVER_DETACHED))) { 1181 if (strcmp(driver_name, "pcf8574") == 0) { 1182 gpio_instances[gpio_count] = di_instance(node); 1183 gpio_count++; 1184 } else if (strcmp(driver_name, "sd") == 0) { 1185 sd_instances[sd_count] = di_instance(node); 1186 sd_count++; 1187 } else if (strcmp(driver_name, "st") == 0) { 1188 st_instance = di_instance(node); 1189 } 1190 } 1191 1192 if (strcmp(di_node_name(node), "pseudo") == 0) 1193 return (DI_WALK_PRUNECHILD); 1194 else 1195 return (DI_WALK_CONTINUE); 1196 } 1197 1198 1199 1200 /* 1201 * Returns 0 if error , 1 otherwise 1202 */ 1203 int 1204 dump_prop_list(char *name, di_node_t node, di_prop_t (*nxtprop)()) 1205 { 1206 int prop_len, i, k, max_slots_minus_cpu, n; 1207 uchar_t *prop_data; 1208 char *p; 1209 char *temp_s; 1210 di_prop_t prop, next; 1211 int ret_value = 0; 1212 1213 max_slots_minus_cpu = scsb_ks_topo.max_units[SLOT]-1; 1214 1215 if ((next = nxtprop(node, DI_PROP_NIL)) == DI_PROP_NIL) 1216 return (0); 1217 while (next != DI_PROP_NIL) { 1218 int maybe_str = 1, npossible_strs = 0; 1219 prop = next; 1220 next = nxtprop(node, prop); 1221 /* 1222 * get prop length and value: 1223 * private interface--always success 1224 */ 1225 prop_len = di_prop_rawdata(prop, &prop_data); 1226 if (di_prop_type(prop) == DDI_PROP_UNDEF_IT) { 1227 continue; 1228 } 1229 1230 if (prop_len == 0) { 1231 continue; 1232 } 1233 if (prop_data[prop_len - 1] != '\0') { 1234 maybe_str = 0; 1235 } else { 1236 /* 1237 * Every character must be a string character or a \0, 1238 * and there must not be two \0's in a row. 1239 */ 1240 for (i = 0; i < prop_len; i++) { 1241 if (prop_data[i] == '\0') { 1242 npossible_strs++; 1243 } else if (!isascii(prop_data[i]) || 1244 iscntrl(prop_data[i])) { 1245 maybe_str = 0; 1246 break; 1247 } 1248 1249 if ((i > 0) && (prop_data[i] == '\0') && 1250 (prop_data[i - 1] == '\0')) { 1251 maybe_str = 0; 1252 break; 1253 } 1254 } 1255 } 1256 1257 if (maybe_str) { 1258 p = (char *)prop_data; 1259 for (i = 0; i < npossible_strs - 1; i++) { 1260 if ((strcmp(name, SYSSOFT_PROP) == 0) && 1261 (strcmp(di_prop_name(prop), 1262 HSC_PROP_NAME) == 0)) { 1263 temp_s = p; 1264 temp_s += strlen(temp_s) + 1; 1265 } 1266 p += strlen(p) + 1; 1267 } 1268 1269 if ((strcmp(name, SYSSOFT_PROP) == 0) && 1270 (strcmp(di_prop_name(prop), HSC_PROP_NAME) == 0)) { 1271 temp_s = temp_s - prop_len+2; 1272 for (k = 0, n = 0; k < prop_len; k++) { 1273 if (temp_s[k] == 0) { 1274 n++; 1275 } 1276 } 1277 if (n % 4) { 1278 log_printf(dgettext(TEXT_DOMAIN, 1279 "\nbad slot-table(%d)\n"), n); 1280 slot_table_not_found = 0; 1281 return (ret_value); 1282 } 1283 slot_table_size = n / 4; 1284 /* 1285 * NOTE : We save slot table info in order 1286 */ 1287 for (k = 0; k < slot_table_size; k++) { 1288 char *nexus, *pcidev, *phys_slotname; 1289 char *ga; 1290 /* 1291 * Pick off pointer to nexus 1292 * path or PROM handle 1293 */ 1294 nexus = temp_s; 1295 while (*temp_s != NULL) 1296 temp_s++; 1297 temp_s++; 1298 1299 /* 1300 * Pick off pointer to the 1301 * pci device number 1302 */ 1303 pcidev = temp_s; 1304 while (*temp_s != NULL) 1305 temp_s++; 1306 temp_s++; 1307 1308 /* Pick off physical slot no */ 1309 phys_slotname = temp_s; 1310 while (*temp_s != NULL) 1311 temp_s++; 1312 temp_s++; 1313 1314 /* 1315 * Pick off GA bits which 1316 * we dont use for now. 1317 */ 1318 ga = temp_s; 1319 while (*temp_s != NULL) 1320 temp_s++; 1321 temp_s++; 1322 1323 hotswap_slot_table[k].pslotnum 1324 = atoi(phys_slotname); 1325 hotswap_slot_table[k].ga = atoi(ga); 1326 hotswap_slot_table[k].pci_devno 1327 = atoi(pcidev); 1328 strcpy(hotswap_slot_table[k].nexus, 1329 nexus); 1330 } /* for (k = 0; k < slot_table_size; k++) */ 1331 1332 ret_value = 1; 1333 } else /* (strcmp(name, SYSSOFT_PROP) */ 1334 slot_table_not_found = 1; 1335 1336 /* 1337 * now we want to save off the info 1338 * we would use later 1339 */ 1340 if ((strcmp(name, DRV_PROP) == 0) && 1341 (strcmp(di_prop_name(prop), HSC_MODE) == 0)) { 1342 hotswap_mode = p; 1343 ret_value = 1; 1344 } else if ((strcmp(name, DRV_PROP) == 0) && 1345 (strcmp(di_prop_name(prop), HSC_MODE) != 0)) { 1346 /* save it in order in the right index */ 1347 slot_auto_config[max_slots_minus_cpu] = p; 1348 max_slots_minus_cpu--; 1349 ret_value = 1; 1350 } 1351 1352 } else { 1353 for (i = 0; i < prop_len; ++i) { 1354 #if 0 1355 unsigned char byte; 1356 byte = (unsigned char)prop_data[i]; 1357 log_printf("%2.2x", byte, 0); 1358 #endif 1359 } 1360 } 1361 } 1362 return (ret_value); 1363 } 1364 1365 1366 void 1367 display_mc_prtdiag_info() 1368 { 1369 int i, index; 1370 int s_index, i1; 1371 int tg_cpu_index = 0; 1372 char *mcfru_type, *status, *mc_ok_led, *mc_nok_led; 1373 char *misc_info, *health, *board_type; 1374 1375 log_printf("===============================", 0); 1376 log_printf(dgettext(TEXT_DOMAIN, 1377 " FRU Information ================================\n"), 0); 1378 log_printf(dgettext(TEXT_DOMAIN, 1379 "FRU FRU FRU Green Amber"), 0); 1380 log_printf(dgettext(TEXT_DOMAIN, " Miscellaneous\n"), 0); 1381 log_printf(dgettext(TEXT_DOMAIN, 1382 "Type Unit# Present LED LED"), 0); 1383 log_printf(dgettext(TEXT_DOMAIN, " Information\n"), 0); 1384 1385 log_printf("---------- ----- ------- ----- -----", 0); 1386 log_printf(" ----------------------------------\n", 0); 1387 1388 if (scsb_ks_topo.mid_plane.fru_id == SCTRL_MPID_HALF) 1389 misc_info = "Netra ct800"; 1390 else { 1391 misc_info = "Netra ct400"; 1392 } 1393 mcfru_type = prtdiag_fru_types[MIDPLANE]; 1394 switch (scsb_ks_topo.mid_plane.fru_status) { 1395 case FRU_PRESENT: 1396 status = YES; 1397 break; 1398 case FRU_NOT_PRESENT: 1399 status = NO; 1400 break; 1401 case FRU_NOT_AVAILABLE: 1402 status = NA; break; 1403 default: 1404 status = NA; break; 1405 } 1406 mc_ok_led = " "; 1407 mc_nok_led = " "; 1408 1409 log_printf(dgettext(TEXT_DOMAIN, 1410 "%10s %-5d %-7s %-5s %-5s %s\n"), 1411 mcfru_type, scsb_ks_topo.mid_plane.fru_unit, 1412 status, mc_ok_led, mc_nok_led, 1413 misc_info, 0); 1414 log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0); 1415 log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK, 1416 scsb_ks_topo.mid_plane.fru_version, 0); 1417 log_printf(dgettext(TEXT_DOMAIN, "%49sMaximum Slots=%d\n"), BLANK, 1418 scsb_ks_topo.max_units[SLOT], 0); 1419 1420 /* SCB & SSB */ 1421 mcfru_type = prtdiag_fru_types[SCB]; 1422 for (i = 0; i < scsb_ks_topo.max_units[SCB]; ++i) { 1423 misc_info = "System Controller Board"; 1424 if (version_p15_and_p20) { 1425 mc_ok_led = 1426 BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1] 1427 & 0xff), SCB_OK_BIT) ? BLINK : 1428 (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1] 1429 & 0xff), SCB_OK_BIT) ? ON:OFF); 1430 mc_nok_led = 1431 BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1] 1432 & 0xff), SCB_OK_BIT) ? ON:OFF; 1433 } else { 1434 /* 1435 * support for 1.0 systems - 1436 * Hack! - should use tables ? 1437 */ 1438 mc_ok_led = 1439 (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2] 1440 & 0xff), 0) ? ON:OFF); 1441 mc_nok_led = 1442 BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2] 1443 & 0xff), 0) ? ON:OFF; 1444 } 1445 switch (scsb_ks_topo.mct_scb[i].fru_status) { 1446 case FRU_PRESENT: 1447 status = YES; 1448 break; 1449 case FRU_NOT_PRESENT: 1450 status = NO; 1451 break; 1452 case FRU_NOT_AVAILABLE: 1453 status = NA; 1454 break; 1455 default: 1456 status = NA; 1457 break; 1458 } 1459 log_printf(dgettext(TEXT_DOMAIN, 1460 "%10s %-5d %-7s %-5s %-5s %s\n"), 1461 mcfru_type, scsb_ks_topo.mct_scb[i].fru_unit, 1462 status, mc_ok_led, mc_nok_led, misc_info, 0); 1463 log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0); 1464 log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK, 1465 scsb_ks_topo.mct_scb[0].fru_version, 0); 1466 if (fail_drv_prop == 1) 1467 log_printf(dgettext(TEXT_DOMAIN, 1468 "%49s%s=%s\n"), BLANK, HSC_MODE, 1469 hotswap_mode, 0); 1470 } /* for */ 1471 1472 mcfru_type = prtdiag_fru_types[SSB]; 1473 for (i = 0; i < scsb_ks_topo.max_units[SSB]; ++i) { 1474 misc_info = "System Status Panel"; 1475 switch (scsb_ks_topo.mct_ssb[i].fru_status) { 1476 case FRU_PRESENT: 1477 status = YES; 1478 break; 1479 case FRU_NOT_PRESENT: 1480 status = NO; 1481 break; 1482 case FRU_NOT_AVAILABLE: 1483 status = NA; 1484 break; 1485 default: 1486 status = NA; 1487 break; 1488 } 1489 log_printf(dgettext(TEXT_DOMAIN, 1490 "%10s %-5d %-7s %-5s %-5s %s\n"), 1491 mcfru_type, scsb_ks_topo.mct_ssb[i].fru_unit, 1492 status, BLANK, BLANK, misc_info, 0); 1493 } /* for */ 1494 1495 /* Slots */ 1496 for (i = 0; i < scsb_ks_topo.max_units[SLOT]; ++i) { 1497 if (montecarlo) { 1498 if (scsb_ks_topo.mct_slots[i].fru_unit == 1) 1499 mcfru_type = prtdiag_fru_types[1]; 1500 else 1501 mcfru_type = prtdiag_fru_types[SLOT]; 1502 /* 1503 * Another way this could have been done is, 1504 * to read the sub system id 1505 * it is 0x6722 for Alarm Card 1506 * but this id is only valid for the new ACs 1507 * older ACs still have the same susbsystem 1508 * id as most other Sun PCI cards 1509 * We cannot completely rely on this. 1510 * Also,it turns out that Sun OpenBoot does not 1511 * always follow IEEE 1275 std, hence in a few 1512 * systems, the "subsystem-id" published by the 1513 * PROM could not be found 1514 * We know the AC slot# if present on both MC&Tg 1515 * Hence we check on both - now we are sure 1516 * that we have found an AC 1517 */ 1518 if ((scsb_ks_topo.mct_slots[i].fru_unit == 8) && 1519 (alarm_card_present == 1)) 1520 board_type = AC_CARD; 1521 else 1522 board_type = UK; 1523 } else { 1524 if (scsb_ks_topo.mct_slots[i].fru_unit == 3) 1525 mcfru_type = prtdiag_fru_types[1]; 1526 else 1527 mcfru_type = prtdiag_fru_types[SLOT]; 1528 /* 1529 * Another way this could have been done is, 1530 * to read the sub system id 1531 * it is 0x6722 for Alarm Card 1532 * but this id is only valid for the new ACs 1533 * older ACs still have the same susbsystem 1534 * id as most other Sun PCI cards 1535 * We cannot completely rely on this. 1536 * Also,it turns out that Sun OpenBoot does not 1537 * always follow IEEE 1275 std, hence in a few 1538 * systems, the "subsystem-id" published by the 1539 * PROM could not be found 1540 * We know the AC slot# if present on both MC&Tg 1541 * Hence we check on both - now we are sure 1542 * that we have found an AC 1543 */ 1544 if ((scsb_ks_topo.mct_slots[i].fru_unit == 1) && 1545 (alarm_card_present == 1)) 1546 board_type = AC_CARD; 1547 else 1548 board_type = UK; 1549 } 1550 if (version_p15_and_p20) { 1551 mc_ok_led = 1552 BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[0] 1553 & 0xff), i) ? BLINK : 1554 (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[0] 1555 & 0xff), i) ? ON:OFF); 1556 mc_nok_led = 1557 BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[0] 1558 & 0xff), i) ? ON:OFF; 1559 } else { 1560 /* 1561 * support for 1.0 systems - 1562 * Hack! - should use tables ? 1563 */ 1564 if (scsb_ks_topo.mct_slots[i].fru_unit == 7) { 1565 mc_ok_led = 1566 BIT_TEST( 1567 (scsb_ks_leddata.leds.p10.blink_leds[1] 1568 & 0xff), 0) ? BLINK : 1569 (BIT_TEST( 1570 (scsb_ks_leddata.leds.p10.ok_leds[1] 1571 & 0xff), 0) ? ON:OFF); 1572 mc_nok_led = 1573 BIT_TEST( 1574 (scsb_ks_leddata.leds.p10.nok_leds[1] 1575 & 0xff), 0) ? ON:OFF; 1576 } else if (scsb_ks_topo.mct_slots[i].fru_unit == 8) { 1577 mc_ok_led = 1578 BIT_TEST( 1579 (scsb_ks_leddata.leds.p10.blink_leds[1] 1580 & 0xff), 1) ? BLINK : 1581 (BIT_TEST( 1582 (scsb_ks_leddata.leds.p10.ok_leds[1] 1583 & 0xff), 1) ? ON:OFF); 1584 mc_nok_led = 1585 BIT_TEST( 1586 (scsb_ks_leddata.leds.p10.nok_leds[1] 1587 & 0xff), 1) ? ON:OFF; 1588 } else { 1589 /* 1590 * for all other slots offset, 1591 * index are the same 1592 */ 1593 mc_ok_led = 1594 BIT_TEST( 1595 (scsb_ks_leddata.leds.p10.blink_leds[0] 1596 & 0xff), i) ? BLINK : 1597 (BIT_TEST( 1598 (scsb_ks_leddata.leds.p10.ok_leds[0] 1599 & 0xff), i) ? ON:OFF); 1600 mc_nok_led = 1601 BIT_TEST( 1602 (scsb_ks_leddata.leds.p10.nok_leds[0] 1603 & 0xff), i) ? ON:OFF; 1604 } 1605 1606 } /* else if (!version_p15_and_p20) */ 1607 1608 switch (scsb_ks_topo.mct_slots[i].fru_status) { 1609 case FRU_PRESENT: 1610 status = YES; 1611 break; 1612 case FRU_NOT_PRESENT: 1613 status = NO; 1614 break; 1615 case FRU_NOT_AVAILABLE: 1616 status = NA; 1617 break; 1618 default: 1619 status = NA; 1620 break; 1621 } 1622 1623 index = (int)scsb_ks_topo.mct_slots[i].fru_type; 1624 if (montecarlo) { 1625 if (scsb_ks_topo.mct_slots[i].fru_unit == 1) { 1626 /* cpu slot */ 1627 log_printf(dgettext(TEXT_DOMAIN, 1628 "%10s %-5d %-7s %-5s "), 1629 mcfru_type, 1630 scsb_ks_topo.mct_slots[i].fru_unit, 1631 status, mc_ok_led, mc_nok_led, 0); 1632 log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), 1633 mc_nok_led, 1634 slot_occupants[index], 0); 1635 log_printf(dgettext(TEXT_DOMAIN, 1636 "%49stemperature(celsius):%d\n"), 1637 BLANK, 1638 pcf8591_ks_temp.value, 0); 1639 #ifdef NEVER 1640 log_printf(dgettext(TEXT_DOMAIN, 1641 "%49sminimum temperature:%d\n"), 1642 BLANK, 1643 pcf8591_ks_temp.min, 0); 1644 log_printf(dgettext(TEXT_DOMAIN, 1645 "%49swarning temp. threshold:%d\n"), 1646 BLANK, 1647 pcf8591_ks_temp.warning_threshold, 0); 1648 log_printf(dgettext(TEXT_DOMAIN, 1649 "%49sshutdown temp.threshold:%d\n"), 1650 BLANK, 1651 pcf8591_ks_temp.shutdown_threshold, 0); 1652 #endif /* NEVER */ 1653 } else if ((scsb_ks_topo.mct_slots[i].fru_unit == 2) && 1654 (cpu_ftm_present == 1)) { 1655 /* CFTM slot */ 1656 /* 1657 * The CFTM can only be present in Slot 2 1658 * for Netract-800, for Netract-400 the FTM 1659 * is not sitted in a Slot. Hence, this is 1660 * another special case and we need to handle 1661 * this differently than other slots 1662 */ 1663 log_printf(dgettext(TEXT_DOMAIN, 1664 "%10s %-5d %-7s %-5s "), 1665 mcfru_type, 1666 scsb_ks_topo.mct_slots[i].fru_unit, 1667 status, mc_ok_led, mc_nok_led, 0); 1668 log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), 1669 mc_nok_led, 1670 CPU_FTM, 0); 1671 } else { 1672 if (fail_drv_prop == 1) { 1673 log_printf(dgettext(TEXT_DOMAIN, 1674 "%10s %-5d %-7s %-5s "), 1675 mcfru_type, 1676 scsb_ks_topo.mct_slots[i].fru_unit, 1677 status, mc_ok_led, 0); 1678 log_printf(dgettext(TEXT_DOMAIN, 1679 "%-5s %s\n"), 1680 mc_nok_led, 1681 slot_occupants[index], 0); 1682 log_printf(dgettext(TEXT_DOMAIN, 1683 "%46s%s\n"), BLANK, 1684 PROPS, 0); 1685 log_printf(dgettext(TEXT_DOMAIN, 1686 "%49sauto-config=%s\n"), 1687 BLANK, 1688 slot_auto_config[i], 0); 1689 } else { 1690 log_printf(dgettext(TEXT_DOMAIN, 1691 "%10s %-5d %-7s %-5s "), 1692 mcfru_type, 1693 scsb_ks_topo.mct_slots[i].fru_unit, 1694 status, mc_ok_led, 0); 1695 log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), 1696 mc_nok_led, 1697 slot_occupants[index], 0); 1698 } 1699 } 1700 } else { /* tonga */ 1701 if (scsb_ks_topo.mct_slots[i].fru_unit == 3) { 1702 /* cpu slot */ 1703 log_printf(dgettext(TEXT_DOMAIN, 1704 "%10s %-5d %-7s %-5s "), 1705 mcfru_type, 1706 scsb_ks_topo.mct_slots[i].fru_unit, 1707 status, mc_ok_led, 0); 1708 log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), 1709 mc_nok_led, 1710 slot_occupants[index], 0); 1711 log_printf(dgettext(TEXT_DOMAIN, 1712 "%49stemperature(celsius):%d\n"), 1713 BLANK, 1714 pcf8591_ks_temp.value, 0); 1715 #ifdef NEVER 1716 1717 log_printf(dgettext(TEXT_DOMAIN, 1718 "%49sminimum temperature:%d\n"), 1719 BLANK, 1720 pcf8591_ks_temp.min, 0); 1721 log_printf(dgettext(TEXT_DOMAIN, 1722 "%49swarning temp. threshold:%d\n"), 1723 BLANK, 1724 pcf8591_ks_temp.warning_threshold, 0); 1725 log_printf(dgettext(TEXT_DOMAIN, 1726 "%49sshutdown temp. threshold:%d\n"), 1727 BLANK, 1728 pcf8591_ks_temp.shutdown_threshold, 0); 1729 #endif /* NEVER */ 1730 } else { 1731 if (fail_drv_prop == 1) { 1732 log_printf(dgettext(TEXT_DOMAIN, 1733 "%10s %-5d %-7s %-5s "), 1734 mcfru_type, 1735 scsb_ks_topo.mct_slots[i].fru_unit, 1736 status, mc_ok_led, 0); 1737 log_printf(dgettext(TEXT_DOMAIN, 1738 "%-5s %s\n"), 1739 mc_nok_led, 1740 slot_occupants[index], 0); 1741 1742 log_printf(dgettext(TEXT_DOMAIN, 1743 "%46s%s\n"), BLANK, PROPS, 0); 1744 log_printf(dgettext(TEXT_DOMAIN, 1745 "%49sauto-config=%s\n"), 1746 BLANK, 1747 slot_auto_config[tg_cpu_index+1], 1748 0); 1749 if (scsb_ks_topo.mct_slots[i].fru_unit 1750 != 3) 1751 tg_cpu_index++; 1752 } else { 1753 log_printf(dgettext(TEXT_DOMAIN, 1754 "%10s %-5d %-7s %-5s "), 1755 mcfru_type, 1756 scsb_ks_topo.mct_slots[i].fru_unit, 1757 status, mc_ok_led, 0); 1758 log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"), 1759 mc_nok_led, 1760 slot_occupants[index], 0); 1761 } 1762 } 1763 } 1764 /* we first match the correct slot numbers */ 1765 for (s_index = 0; s_index < slot_table_size; s_index++) { 1766 if (slot_table_not_found == 1) { 1767 /* use prom table */ 1768 if (scsb_ks_topo.mct_slots[i].fru_unit == 1769 prom_slot_table[s_index].pslotnum) { 1770 /* 1771 * search for the addr/pci num 1772 * in all slot info structs 1773 */ 1774 for (i1 = 0; i1 < slot_index; 1775 i1++) { 1776 if (prom_slot_table[s_index].pci_devno == 1777 mc_slots_data.mc_slot_info[i1].slot_addr) { 1778 int nd; 1779 log_printf(dgettext(TEXT_DOMAIN, 1780 "%46s%s%s\n"), BLANK, 1781 BOARDTYPE, board_type, 0); 1782 log_printf(dgettext(TEXT_DOMAIN, 1783 "%46s%s\n"), BLANK, DEVS, 0); 1784 log_printf(dgettext(TEXT_DOMAIN, 1785 "%49s%s\n"), BLANK, 1786 PCI_ROOT_AP, 0); 1787 for (nd = 0; 1788 nd < mc_slots_data.mc_slot_info[i1].number_devs; 1789 nd++) { 1790 log_printf(dgettext(TEXT_DOMAIN, "%52s%s\n"), BLANK, 1791 mc_slots_data.mc_slot_info[i1].devs_info[nd], 1792 0); 1793 } /* for */ 1794 1795 } /* if */ 1796 1797 } /* for(i1) */ 1798 1799 } /* if */ 1800 1801 } else { 1802 /* use solaris lot table */ 1803 if (fail_syssoft_prop == 1) { 1804 if (scsb_ks_topo.mct_slots[i].fru_unit == 1805 hotswap_slot_table[s_index].pslotnum) { 1806 /* 1807 * search for the addr/pci 1808 * num in all slot info structs 1809 */ 1810 for (i1 = 0; i1 < slot_index; i1++) { 1811 if (hotswap_slot_table[s_index].pci_devno == 1812 mc_slots_data.mc_slot_info[i1].slot_addr) { 1813 int nd; 1814 for (nd = 0; 1815 nd < mc_slots_data.mc_slot_info[i1].number_devs; 1816 nd++) { 1817 log_printf(dgettext(TEXT_DOMAIN, "%49s%s\n"), BLANK, 1818 mc_slots_data.mc_slot_info[i1].devs_info[nd], 1819 0); 1820 } 1821 } /* if */ 1822 1823 } /* for(i1) */ 1824 1825 } /* if */ 1826 1827 } /* (fail_syssoft_prop == 1) */ 1828 1829 } /* (slot_table_not_found == 1) */ 1830 1831 } /* for(s_index) */ 1832 1833 } /* for */ 1834 mcfru_type = "PDU"; 1835 misc_info = "Power Distribution Unit"; 1836 for (i = 0; i < scsb_ks_topo.max_units[PDU]; ++i) { 1837 if (version_p15_and_p20) { 1838 mc_ok_led = 1839 BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1] 1840 & 0xff), PDU1_OK_BIT+i*2) ? BLINK : 1841 (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1] 1842 & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF); 1843 mc_nok_led = 1844 BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1] 1845 & 0xff), PDU1_OK_BIT+i*2) ? ON:OFF; 1846 } 1847 switch (scsb_ks_topo.mct_pdu[i].fru_status) { 1848 case FRU_PRESENT: 1849 status = YES; 1850 break; 1851 case FRU_NOT_PRESENT: 1852 status = NO; 1853 break; 1854 case FRU_NOT_AVAILABLE: 1855 status = NA; 1856 break; 1857 default: 1858 status = NA; 1859 break; 1860 } 1861 if (version_p15_and_p20) { 1862 log_printf(dgettext(TEXT_DOMAIN, 1863 "%-10s %-5d %-7s %-5s %-5s %s\n"), 1864 mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit, 1865 status, mc_ok_led, mc_nok_led, misc_info, 0); 1866 } else { 1867 log_printf(dgettext(TEXT_DOMAIN, 1868 "%-10s %-5d %-7s%18s%s\n"), 1869 mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit, 1870 status, BLANK, misc_info, 0); 1871 } 1872 } /* for */ 1873 1874 /* PS */ 1875 mcfru_type = prtdiag_fru_types[PS]; 1876 misc_info = "Power Supply Unit"; 1877 for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) { 1878 if (version_p15_and_p20) { 1879 mc_ok_led = 1880 BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2] 1881 & 0xff), PS1_OK_BIT+i) ? BLINK : 1882 (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2] 1883 & 0xff), PS1_OK_BIT+i) ? ON:OFF); 1884 mc_nok_led = 1885 BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2] 1886 & 0xff), PS1_OK_BIT+i) ? ON:OFF; 1887 } else { 1888 /* 1889 * support for 1.0 systems - 1890 * Hack! - should use tables ? 1891 */ 1892 mc_ok_led = 1893 (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2] 1894 & 0xff), 1+i) ? ON:OFF); 1895 mc_nok_led = 1896 BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2] 1897 & 0xff), 1+i) ? ON:OFF; 1898 } 1899 switch (scsb_ks_topo.mct_ps[i].fru_status) { 1900 case FRU_PRESENT: 1901 status = YES; 1902 break; 1903 case FRU_NOT_PRESENT: 1904 status = NO; 1905 break; 1906 case FRU_NOT_AVAILABLE: 1907 status = NA; 1908 break; 1909 default: 1910 status = NA; 1911 break; 1912 } 1913 log_printf(dgettext(TEXT_DOMAIN, 1914 "%10s %-5d %-7s %-5s %-5s %s\n"), 1915 mcfru_type, scsb_ks_topo.mct_ps[i].fru_unit, 1916 status, mc_ok_led, mc_nok_led, 1917 misc_info, 0); 1918 if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) { 1919 if (scsb_ks_topo.mct_ps[i].fru_unit == 1) { 1920 log_printf(dgettext(TEXT_DOMAIN, 1921 "%49scondition:%s\n"), BLANK, 1922 ((pcf8574_ks_ps1.ps_ok)? NOK:OK), 0); 1923 log_printf(dgettext(TEXT_DOMAIN, 1924 "%49stemperature:%s\n"), BLANK, 1925 ((pcf8574_ks_ps1.temp_ok)? NOK:OK), 0); 1926 log_printf(dgettext(TEXT_DOMAIN, 1927 "%49sps fan:%s\n"), BLANK, 1928 ((pcf8574_ks_ps1.psfan_ok)? NOK:OK), 0); 1929 log_printf(dgettext(TEXT_DOMAIN, 1930 "%49ssupply:%s\n"), BLANK, 1931 ((pcf8574_ks_ps1.on_state)? OFF:ON), 0); 1932 } else { 1933 log_printf(dgettext(TEXT_DOMAIN, 1934 "%49scondition:%s\n"), BLANK, 1935 ((pcf8574_ks_ps2.ps_ok)? NOK:OK), 0); 1936 log_printf(dgettext(TEXT_DOMAIN, 1937 "%49stemperature:%s\n"), BLANK, 1938 ((pcf8574_ks_ps2.temp_ok)? NOK:OK), 0); 1939 log_printf(dgettext(TEXT_DOMAIN, 1940 "%49sps fan:%s\n"), BLANK, 1941 ((pcf8574_ks_ps2.psfan_ok)? NOK:OK), 0); 1942 log_printf(dgettext(TEXT_DOMAIN, 1943 "%49ssupply:%s\n"), BLANK, 1944 ((pcf8574_ks_ps2.on_state)? OFF:ON), 0); 1945 } /* if */ 1946 } 1947 1948 } /* for */ 1949 1950 /* Fan tray */ 1951 mcfru_type = prtdiag_fru_types[FAN]; 1952 misc_info = "Fan Tray"; 1953 for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) { 1954 if (version_p15_and_p20) { 1955 mc_ok_led = 1956 BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2] 1957 & 0xff), FAN1_OK_BIT+i) ? BLINK : 1958 (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2] 1959 & 0xff), FAN1_OK_BIT+i) ? ON:OFF); 1960 mc_nok_led = 1961 BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2] 1962 & 0xff), FAN1_OK_BIT+i) ? ON:OFF; 1963 } else { 1964 /* 1965 * support for 1.0 systems - 1966 * Hack! - should use tables ? 1967 */ 1968 mc_ok_led = 1969 (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[3] 1970 & 0xff), 3+i) ? ON:OFF); 1971 mc_nok_led = 1972 BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[3] 1973 & 0xff), 3+i) ? ON:OFF; 1974 } 1975 switch (scsb_ks_topo.mct_fan[i].fru_status) { 1976 case FRU_PRESENT: 1977 status = YES; 1978 break; 1979 case FRU_NOT_PRESENT: 1980 status = NO; 1981 break; 1982 case FRU_NOT_AVAILABLE: 1983 status = NA; 1984 break; 1985 default: 1986 status = NA; 1987 break; 1988 } 1989 log_printf(dgettext(TEXT_DOMAIN, 1990 "%10s %-5d %-7s %-5s %-5s %s\n"), 1991 mcfru_type, scsb_ks_topo.mct_fan[i].fru_unit, 1992 status, mc_ok_led, mc_nok_led, 1993 misc_info, 0); 1994 if (scsb_ks_topo.mct_fan[i].fru_status == FRU_PRESENT) { 1995 if (scsb_ks_topo.mct_fan[i].fru_unit == 1) { 1996 log_printf(dgettext(TEXT_DOMAIN, 1997 "%49scondition:%s\n"), BLANK, 1998 ((pcf8574_ks_fant1.fan_ok)? OK:NOK), 0); 1999 log_printf(dgettext(TEXT_DOMAIN, 2000 "%49sfan speed:%s\n"), BLANK, 2001 ((pcf8574_ks_fant1.fanspeed)? HI:LO), 0); 2002 } else { 2003 log_printf(dgettext(TEXT_DOMAIN, 2004 "%49scondition:%s\n"), BLANK, 2005 ((pcf8574_ks_fant2.fan_ok)? OK:NOK), 0); 2006 log_printf(dgettext(TEXT_DOMAIN, 2007 "%49sfan speed:%s\n"), BLANK, 2008 ((pcf8574_ks_fant2.fanspeed)? HI:LO), 0); 2009 } 2010 } 2011 2012 } /* for */ 2013 2014 /* DISKS */ 2015 for (i = 0; i < scsb_ks_topo.max_units[DISK]; ++i) { 2016 if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER) 2017 mcfru_type = prtdiag_fru_types[DISK]; 2018 else 2019 mcfru_type = "RMM "; 2020 switch (scsb_ks_topo.mct_disk[i].fru_status) { 2021 case FRU_PRESENT: 2022 status = YES; 2023 break; 2024 case FRU_NOT_PRESENT: 2025 status = NO; 2026 break; 2027 case FRU_NOT_AVAILABLE: 2028 status = NA; 2029 break; 2030 default: 2031 status = NA; 2032 break; 2033 } 2034 if (version_p15_and_p20) { 2035 mc_ok_led = 2036 BIT_TEST((scsb_ks_leddata.scb_led_regs[8] 2037 & 0xff), DISK1_OK_BIT+i) ? BLINK : 2038 (BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2] 2039 & 0xff), DISK1_OK_BIT+i) ? ON:OFF); 2040 mc_nok_led = 2041 BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2] 2042 & 0xff), DISK1_OK_BIT+i) ? ON:OFF; 2043 } else { 2044 /* 2045 * support for 1.0 systems - 2046 * Hack! - should use tables ? 2047 */ 2048 mc_ok_led = 2049 (BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2] 2050 & 0xff), DISK1_OK_BIT+i) ? ON:OFF); 2051 mc_nok_led = 2052 BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2] 2053 & 0xff), DISK1_OK_BIT+i) ? ON:OFF; 2054 } 2055 /* print everything except condition */ 2056 if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER) { 2057 misc_info = "Hard Disk Drive"; 2058 log_printf(dgettext(TEXT_DOMAIN, 2059 "%10s %-5d %-7s %-5s %-5s %s\n"), 2060 mcfru_type, scsb_ks_topo.mct_disk[i].fru_unit-1, 2061 status, mc_ok_led, mc_nok_led, misc_info, 0); 2062 } else { 2063 misc_info = "Removable Media Module"; 2064 log_printf(dgettext(TEXT_DOMAIN, 2065 "%10s %5s %-7s %-5s %-5s %s\n"), 2066 mcfru_type, BLANK, 2067 status, mc_ok_led, mc_nok_led, misc_info, 0); 2068 } 2069 2070 /* find out fru health from the SCSI drivers */ 2071 if (scsb_ks_topo.mct_disk[i].fru_status == FRU_PRESENT) { 2072 switch ( 2073 scsi_disk_status( 2074 scsb_ks_topo.mct_disk[i].fru_unit)) { 2075 case 0: 2076 health = OK; 2077 break; 2078 case 1: 2079 health = NOK; 2080 break; 2081 case -1: 2082 health = UK; 2083 break; 2084 default: 2085 health = NA; 2086 break; 2087 } 2088 log_printf(dgettext(TEXT_DOMAIN, 2089 "%49scondition:%s\n"), BLANK, health, 0); 2090 } 2091 2092 } /* for */ 2093 2094 log_printf(dgettext(TEXT_DOMAIN, "\n"), 0); 2095 2096 } /* display_mc_prtdiag_info() */ 2097 2098 2099 void 2100 analyze_pcipci_siblings(di_node_t node) 2101 { 2102 di_node_t lc_node; 2103 /* we will find all the dev info for slots first */ 2104 lc_node = di_drv_first_node("pci_pci", node); 2105 lc_node = di_child_node(lc_node); 2106 /* we are at "pci" node now */ 2107 do { 2108 if (di_walk_node(lc_node, DI_WALK_CLDFIRST, 2109 NULL, analyze_nodes) != 0) { 2110 return; 2111 } 2112 } while ((lc_node = di_sibling_node(lc_node)) != DI_NODE_NIL); 2113 2114 /* now we wll gather info on sysctrl */ 2115 lc_node = di_drv_first_node(SCSB_DEV, node); 2116 if (lc_node != DI_NODE_NIL) 2117 analyze_nodes(lc_node, "sysctrl"); 2118 } /* analyze_pcipci_siblings(.) */ 2119 2120 2121 int 2122 analyze_nodes(di_node_t l_node, void *arg) 2123 { 2124 char *temp; 2125 char *name, *pname; 2126 di_node_t parent; 2127 /* 2128 * we will figure out whether the parent node is "pci" type 2129 * we will save info only in this case as we only want to 2130 * print out the nodes under AP and not others 2131 */ 2132 parent = di_parent_node(l_node); 2133 pname = di_node_name(parent); 2134 name = di_node_name(l_node); 2135 /* 2136 * if this is PCI bridge, we know that this is the AP for slots 2137 * hence, we will save off the address(to convert to slot mapping) 2138 * later, and also we will start saving off slot info struct for 2139 * reporting later 2140 * we will save the immediate childs of this bridge only 2141 */ 2142 if (strcmp(name, "pci") == 0) { 2143 num_devs = 0; 2144 if ((temp = di_bus_addr(l_node)) != NULL) { 2145 mc_slots_data.mc_slot_info[slot_index].slot_addr 2146 = (int)strtol(temp, (char **)NULL, 16); 2147 } 2148 slot_index++; 2149 } else { 2150 if (strcmp(pname, "pci") == 0) { 2151 if ((mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs]) 2152 != NULL) { 2153 (void) strcat( 2154 mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs], 2155 name); 2156 } else { 2157 (void) strcpy( 2158 mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs], 2159 name); 2160 } /* if ((mc_slots_data.mc_slot_inf */ 2161 2162 num_devs++; 2163 mc_slots_data.mc_slot_info[slot_index-1].number_devs 2164 = num_devs; 2165 } /* if parent is pci */ 2166 2167 } /* if node is pci */ 2168 if (arg != NULL) { 2169 if (strcmp((char *)arg, "sysctrl") == 0) { 2170 if (dump_prop_list("System", l_node, 2171 di_prop_sys_next)) { 2172 (void) dump_prop_list(NULL, l_node, 2173 di_prop_global_next); 2174 } else { 2175 fail_syssoft_prop = 2176 dump_prop_list(SYSSOFT_PROP, 2177 l_node, di_prop_global_next); 2178 } 2179 2180 fail_drv_prop = 2181 dump_prop_list(DRV_PROP, l_node, 2182 di_prop_drv_next); 2183 /* 2184 * (void) dump_prop_list("Hardware", 2185 * l_node, di_prop_hw_next); 2186 */ 2187 /* dump_priv_data(l_node); */ 2188 } 2189 } 2190 2191 return (0); 2192 2193 } /* analyze_nodes(..) */ 2194 2195 2196 2197 /* 2198 * To get the slot information, 2199 * The OBP defines the 'slot-table' property. But the OS 2200 * can override it with 'hsc-slot-map' property 2201 * through the .conf file. 2202 * Since the formats are different, 2 different property names 2203 * are chosen. 2204 * The OBP property format is 2205 * <phandle>,<pci-devno>,<phys-slotno>,<ga-bits> 2206 * The OS property format is (ga-bits is not used however) 2207 * <busnexus-path>,<pci-devno>,<phys-slotno>,<ga-bits> 2208 * returns 0 on error, 1 otherwise 2209 */ 2210 int 2211 extract_slot_table_from_obp() 2212 { 2213 if (mc_promopen(O_RDONLY)) { 2214 log_printf(dgettext(TEXT_DOMAIN, 2215 "\ncannot open openprom device"), 0); 2216 return (0); 2217 } 2218 2219 if (mc_next(0) == 0) 2220 return (0); 2221 mc_walk(mc_next(0)); 2222 2223 if (close(oprom_fd) < 0) { 2224 log_printf(dgettext(TEXT_DOMAIN, 2225 "\nclose error on %s"), OPENPROMDEV, 0); 2226 return (0); 2227 } 2228 2229 return (1); 2230 2231 } /* extract_slot_table_from_obp() */ 2232 2233 2234 int 2235 mc_next(int id) 2236 { 2237 Oppbuf oppbuf; 2238 struct openpromio *opp = &(oppbuf.opp); 2239 2240 bzero(oppbuf.buf, BUFSIZE); 2241 opp->oprom_size = MAXVALSIZE; 2242 opp->oprom_node = id; 2243 if (ioctl(oprom_fd, OPROMNEXT, opp) < 0) { 2244 log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMNEXT"), 0); 2245 return (0); 2246 } 2247 return (opp->oprom_node); 2248 2249 } /* mc_next(.) */ 2250 2251 2252 void 2253 mc_walk(int id) 2254 { 2255 int curnode; 2256 mc_dump_node(id); 2257 if (curnode = mc_child(id)) 2258 mc_walk(curnode); 2259 if (curnode = mc_next(id)) 2260 mc_walk(curnode); 2261 } /* mc_walk(.) */ 2262 2263 int 2264 mc_child(int id) 2265 { 2266 Oppbuf oppbuf; 2267 struct openpromio *opp = &(oppbuf.opp); 2268 2269 bzero(oppbuf.buf, BUFSIZE); 2270 opp->oprom_size = MAXVALSIZE; 2271 opp->oprom_node = id; 2272 if (ioctl(oprom_fd, OPROMCHILD, opp) < 0) { 2273 perror("\nOPROMCHILD"); 2274 exit(0); 2275 } 2276 return (opp->oprom_node); 2277 2278 } /* mc_child(.) */ 2279 2280 2281 /* 2282 * Print all properties and values 2283 */ 2284 void 2285 mc_dump_node(int id) 2286 { 2287 int k; 2288 Oppbuf oppbuf; 2289 hsc_prom_slot_table_t *hpstp; 2290 struct openpromio *opp = &(oppbuf.opp); 2291 2292 /* get first prop by asking for null string */ 2293 bzero(oppbuf.buf, BUFSIZE); 2294 for (;;) { 2295 /* 2296 * get next property name 2297 */ 2298 opp->oprom_size = MAXNAMESZ; 2299 2300 if (ioctl(oprom_fd, OPROMNXTPROP, opp) < 0) { 2301 perror("\nOPROMNXTPROP"); 2302 return; 2303 } 2304 if (opp->oprom_size == 0) 2305 break; 2306 if (strcmp(opp->oprom_array, "slot-table") == 0) { 2307 if (mc_getpropval(opp) || opp->oprom_size 2308 == (uint_t)-1) { 2309 log_printf(dgettext(TEXT_DOMAIN, 2310 "\ndata not available"), 0); 2311 return; 2312 } else { 2313 slot_table_size = 2314 opp->oprom_size / 2315 sizeof (hsc_prom_slot_table_t); 2316 hpstp = 2317 (hsc_prom_slot_table_t *)opp->oprom_array; 2318 for (k = 0; k < slot_table_size; k++, hpstp++) { 2319 prom_slot_table[k].pslotnum = 2320 hpstp->pslotnum; 2321 prom_slot_table[k].ga = 2322 hpstp->ga; 2323 prom_slot_table[k].pci_devno = 2324 hpstp->pci_devno; 2325 prom_slot_table[k].phandle = 2326 hpstp->phandle; 2327 } /* for (k = 0; k < slot_table_size; k++) */ 2328 2329 } 2330 } 2331 } 2332 2333 } /* mc_dump_node(.) */ 2334 2335 2336 int 2337 mc_getpropval(struct openpromio *opp) 2338 { 2339 opp->oprom_size = MAXVALSIZE; 2340 if (ioctl(oprom_fd, OPROMGETPROP, opp) < 0) { 2341 log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMGETPROP"), 0); 2342 return (1); 2343 } 2344 return (0); 2345 2346 } /* mc_getpropval(.) */ 2347 2348 2349 2350 /* 2351 * This function returns nothing. 2352 */ 2353 void 2354 alarm_card_occupant() 2355 { 2356 int scsb_fd; 2357 scsb_ioc_rdwr_t ioc_read; 2358 uint8_t new_mode = 0; 2359 uint8_t old_mode = 0; 2360 uchar_t reg_index; 2361 2362 if (NULL == scsb_node) { 2363 if (check_platform() == -1) { 2364 return; 2365 } 2366 } 2367 2368 if (version_p15_and_p20 == 1) 2369 reg_index = 0xe9; /* config status reg offset on SCB */ 2370 else 2371 reg_index = 0xd7; /* config status reg offset on SCB */ 2372 2373 if ((scsb_fd = open(scsb_node, O_RDONLY)) < 0) { 2374 log_printf(dgettext(TEXT_DOMAIN, 2375 "\n%s open failed"), scsb_node, 0); 2376 return; 2377 } 2378 2379 /* save off the old mode */ 2380 if (scsb_mode(scsb_fd, GET, &old_mode) == 0) 2381 return; 2382 /* we put scsb in diag mode to read this specific ioctl */ 2383 new_mode = ENVCTRL_DIAG_MODE; 2384 if (scsb_mode(scsb_fd, SET, &new_mode) == 0) 2385 return; 2386 /* now lets read the config register */ 2387 if (scsb_ioc_reg_read(scsb_fd, reg_index, &ioc_read, 1) == 0) 2388 return; 2389 /* restore the original mode */ 2390 if (scsb_mode(scsb_fd, SET, &old_mode) == 0) 2391 return; 2392 alarm_card_present = (BIT_TEST(ioc_read.ioc_rbuf[0]&0xff, 0) ? 1:0); 2393 2394 } /* alarm_card_occupant() */ 2395 2396 2397 /* 2398 * This function changes the SCSB mode to the desired one 2399 * 1 on sucess, 0 otherwise 2400 */ 2401 int 2402 scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode) 2403 { 2404 struct strioctl sioc; 2405 2406 if (sop == GET) 2407 sioc.ic_cmd = ENVC_IOC_GETMODE; 2408 else 2409 sioc.ic_cmd = ENVC_IOC_SETMODE; 2410 2411 sioc.ic_timout = 0; 2412 sioc.ic_len = sizeof (uint8_t); 2413 sioc.ic_dp = (char *)new_mode; 2414 2415 2416 if (ioctl(fd, I_STR, &sioc) == -1) { 2417 log_printf(dgettext(TEXT_DOMAIN, 2418 "\nscsb_mode():scsb ioctl() failed"), 0); 2419 return (0); 2420 } 2421 return (1); 2422 2423 } /* scsb_mode(...) */ 2424 2425 2426 /* 2427 * 1 on success, 0 otherwise 2428 */ 2429 int 2430 scsb_ioc_reg_read(int fd, uchar_t index, scsb_ioc_rdwr_t *ioc_rd, int num) 2431 { 2432 struct strioctl sioc; 2433 scsb_ioc_rdwr_t *rdwrp; 2434 2435 rdwrp = ioc_rd; 2436 sioc.ic_timout = 0; 2437 sioc.ic_len = sizeof (scsb_ioc_rdwr_t); 2438 sioc.ic_dp = (char *)rdwrp; 2439 /* setup read command before ioctl */ 2440 sioc.ic_cmd = SCSBIOC_REG_READ; 2441 rdwrp->ioc_wlen = 0; 2442 rdwrp->ioc_rlen = num; 2443 rdwrp->ioc_regindex = index; 2444 if (ioctl(fd, I_STR, &sioc) == -1) { 2445 log_printf(dgettext(TEXT_DOMAIN, 2446 "scsb_ioc_reg_read(): scsb ioctl() failed\n"), 0); 2447 return (0); 2448 } 2449 return (1); 2450 2451 } /* scsb_ioc_reg_read(....) */