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