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
display(Sys_tree * tree,Prom_node * root,struct system_kstat_data * kstats,int syserrlog)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
check_platform()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
force_load_drivers()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
explore_slot_occupants()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 *
config_calloc_check(size_t nelem,size_t elsize)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
do_scsb_kstat()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
do_pcf8574_kstat()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
do_pcf8591_kstat()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
gather_diaginfo(int flag)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
netract_disp_prom_version()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
do_promversion(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
mc_promopen(int oflag)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
scsi_disk_status(int disk_number)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
prtdiag_devinfo(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
dump_devs(di_node_t node,void * arg)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
dump_prop_list(char * name,di_node_t node,di_prop_t (* nxtprop)())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
display_mc_prtdiag_info()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
analyze_pcipci_siblings(di_node_t node)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
analyze_nodes(di_node_t l_node,void * arg)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
extract_slot_table_from_obp()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
mc_next(int id)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
mc_walk(int id)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
mc_child(int id)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
mc_dump_node(int id)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
mc_getpropval(struct openpromio * opp)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
alarm_card_occupant()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
scsb_mode(int fd,scsb_op_t sop,uint8_t * new_mode)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
scsb_ioc_reg_read(int fd,uchar_t index,scsb_ioc_rdwr_t * ioc_rd,int num)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(....) */
2452