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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Daktari Platform specific functions.
28 *
29 * called when :
30 * machine_type == MTYPE_DAKTARI
31 *
32 */
33
34 #pragma ident "%Z%%M% %I% %E% SMI"
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <kstat.h>
40 #include <string.h>
41 #include <assert.h>
42 #include <libintl.h>
43 #include <note.h>
44
45 #include <sys/openpromio.h>
46 #include <sys/sysmacros.h>
47 #include <sys/daktari.h>
48
49 #include <pdevinfo.h>
50 #include <display.h>
51 #include <pdevinfo_sun4u.h>
52 #include <display_sun4u.h>
53 #include <libprtdiag.h>
54
55 #include <picl.h>
56 #include "workfile.c"
57
58 #if !defined(TEXT_DOMAIN)
59 #define TEXT_DOMAIN "SYS_TEST"
60 #endif
61
62 #define DAK_MAX_SLOTS_PER_IO_BD 9
63 #define DAK_MAX_DISKS 12
64 #define DAK_MAX_FSP_LEDS 2
65 #define DAK_MAX_PS 3
66 #define DAK_MAX_PS_VOLTAGE_SENSORS 4
67 #define DAK_MAX_PS_FAULT_SENSORS 3
68 #define DAK_MAX_FANS 10
69 #ifndef SCHIZO_COMPAT_PROP
70 #define SCHIZO_COMPAT_PROP "pci108e,8001"
71 #endif
72
73 #define MULTIPLE_BITS_SET(x) ((x)&((x)-1))
74
75 extern int print_flag;
76
77 /*
78 * these functions will overlay the symbol table of libprtdiag
79 * at runtime (workgroup server systems only)
80 */
81 void display_cpu_devices(Sys_tree *tree);
82 void display_cpus(Board_node *board);
83 void display_pci(Board_node *board);
84 void display_io_cards(struct io_card *list);
85 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
86 struct system_kstat_data *kstats);
87 void display_ffb(Board_node *board, int table);
88 void display_memoryconf(Sys_tree *tree, struct grp_info *grps);
89
90 /* local functions */
91 static int disp_envc_status(void);
92 static int dak_env_print_temps(picl_nodehdl_t);
93 static int dak_env_print_keyswitch(picl_nodehdl_t);
94 static int dak_env_print_FSP_LEDS(picl_nodehdl_t);
95 static int dak_env_print_disk(picl_nodehdl_t);
96 static int dak_env_print_fans(picl_nodehdl_t);
97 static int dak_env_print_ps(picl_nodehdl_t);
98
99 static void dak_display_hw_revisions(Prom_node *root,
100 Board_node *bnode);
101 static void display_schizo_revisions(Board_node *bdlist);
102
103
104 /*
105 * Defining the error_check function in order to return the
106 * appropriate error code.
107 */
108 /*ARGSUSED0*/
109 int
error_check(Sys_tree * tree,struct system_kstat_data * kstats)110 error_check(Sys_tree *tree, struct system_kstat_data *kstats)
111 {
112 int exit_code = 0; /* init to all OK */
113 /*
114 * silently check for any types of machine errors
115 */
116 print_flag = 0;
117 if (disp_fail_parts(tree)) {
118 /* set exit_code to show failures */
119 exit_code = 1;
120 }
121 print_flag = 1;
122
123 return (exit_code);
124 }
125
126 /*
127 * disp_fail_parts
128 *
129 * Display the failed parts in the system. This function looks for
130 * the status property in all PROM nodes. On systems where
131 * the PROM does not support passing diagnostic information
132 * through the device tree, this routine will be silent.
133 */
134 int
disp_fail_parts(Sys_tree * tree)135 disp_fail_parts(Sys_tree *tree)
136 {
137 int exit_code = 0;
138 int system_failed = 0;
139 Board_node *bnode = tree->bd_list;
140 Prom_node *pnode;
141
142 /* go through all of the boards looking for failed units. */
143 while (bnode != NULL) {
144 /* find failed chips */
145 pnode = find_failed_node(bnode->nodes);
146 if ((pnode != NULL) && !system_failed) {
147 system_failed = 1;
148 exit_code = 1;
149 if (print_flag == 0) {
150 return (exit_code);
151 }
152 log_printf("\n");
153 log_printf(dgettext(TEXT_DOMAIN, "Failed Field "
154 "Replaceable Units (FRU) in System:\n"));
155 log_printf("=========================="
156 "====================\n");
157 }
158 while (pnode != NULL) {
159 void *value;
160 char *name; /* node name string */
161 char *type; /* node type string */
162 char *board_type = NULL;
163
164 value = get_prop_val(find_prop(pnode, "status"));
165 name = get_node_name(pnode);
166
167 /* sanity check of data retrieved from PROM */
168 if ((value == NULL) || (name == NULL)) {
169 pnode = next_failed_node(pnode);
170 continue;
171 }
172
173 /* Find the board type of this board */
174 if (bnode->board_type == CPU_BOARD) {
175 board_type = "CPU";
176 } else {
177 board_type = "IO";
178 }
179
180 log_printf(dgettext(TEXT_DOMAIN, "%s unavailable "
181 "on %s Board #%d\n"), name, board_type,
182 bnode->board_num);
183
184 log_printf(dgettext(TEXT_DOMAIN,
185 "\tPROM fault string: %s\n"), value);
186
187 log_printf(dgettext(TEXT_DOMAIN,
188 "\tFailed Field Replaceable Unit is "));
189
190 /*
191 * Determine whether FRU is CPU module, system
192 * board, or SBus card.
193 */
194 if ((name != NULL) && (strstr(name, "sbus"))) {
195
196 log_printf(dgettext(TEXT_DOMAIN,
197 "SBus Card %d\n"),
198 get_sbus_slot(pnode));
199
200 } else if (((name = get_node_name(pnode->parent)) !=
201 NULL) && (strstr(name, "pci"))) {
202
203 log_printf(dgettext(TEXT_DOMAIN,
204 "PCI Card %d"),
205 get_pci_device(pnode));
206
207 } else if (((type = get_node_type(pnode)) != NULL) &&
208 (strstr(type, "cpu"))) {
209
210 log_printf(dgettext(TEXT_DOMAIN, "UltraSPARC "
211 "module Board %d Module %d\n"), 0,
212 get_id(pnode));
213
214 } else {
215 log_printf(dgettext(TEXT_DOMAIN,
216 "%s board %d\n"), board_type,
217 bnode->board_num);
218 }
219 pnode = next_failed_node(pnode);
220 }
221 bnode = bnode->next;
222 }
223
224 if (!system_failed) {
225 log_printf(dgettext(TEXT_DOMAIN,
226 "No failures found in System\n"));
227 log_printf("===========================\n\n");
228 }
229
230 if (system_failed)
231 return (1);
232 else
233 return (0);
234 }
235
236 /*ARGSUSED*/
237 void
display_hp_fail_fault(Sys_tree * tree,struct system_kstat_data * kstats)238 display_hp_fail_fault(Sys_tree *tree, struct system_kstat_data *kstats)
239 {
240 /* Display failed units */
241 (void) disp_fail_parts(tree);
242 }
243
244 /*ARGSUSED*/
245 void
display_memoryconf(Sys_tree * tree,struct grp_info * grps)246 display_memoryconf(Sys_tree *tree, struct grp_info *grps)
247 {
248 Board_node *bnode = tree->bd_list;
249
250 log_printf(dgettext(TEXT_DOMAIN,
251 "========================= Memory Configuration"
252 " ===============================\n"
253 "\n Logical Logical"
254 " Logical "
255 "\n MC Bank Bank Bank"
256 " DIMM Interleave Interleaved"
257 "\n Brd ID num size "
258 "Status Size "
259 "Factor with"
260 "\n---- --- ---- ------ "
261 "----------- ------ "
262 "---------- -----------"));
263
264 while (bnode != NULL) {
265 if (get_us3_mem_regs(bnode)) {
266 log_printf(dgettext(TEXT_DOMAIN,
267 "\nFailed to get memory information.\n"));
268 return;
269 }
270 bnode = bnode->next;
271 }
272
273 /* Display what we have found */
274 display_us3_banks();
275 }
276
277 void
display_cpu_devices(Sys_tree * tree)278 display_cpu_devices(Sys_tree *tree)
279 {
280 Board_node *bnode;
281
282 /*
283 * Display the table header for CPUs . Then display the CPU
284 * frequency, cache size, and processor revision of all cpus.
285 */
286 log_printf(dgettext(TEXT_DOMAIN,
287 "\n"
288 "========================="
289 " CPUs "
290 "==============================================="
291 "\n"
292 "\n"
293 " Run E$ CPU CPU \n"
294 "Brd CPU MHz MB Impl. Mask \n"
295 "--- ----- ---- ---- ------- ---- \n"));
296
297 /* Now display all of the cpus on each board */
298 bnode = tree->bd_list;
299 if (bnode == NULL) {
300 log_printf(dgettext(TEXT_DOMAIN,
301 "CPU Board list was NULL\n"));
302 }
303 while (bnode != NULL) {
304 display_cpus(bnode);
305 bnode = bnode->next;
306 }
307
308 log_printf("\n");
309 }
310
311 /*
312 * Display the CPUs present on this board.
313 */
314 void
display_cpus(Board_node * board)315 display_cpus(Board_node *board)
316 {
317 Prom_node *cpu;
318 uint_t freq; /* CPU clock frequency */
319 int ecache_size; /* External cache size */
320 int *l3_shares;
321 int *mid;
322 int *impl;
323 int *mask;
324 int *coreid;
325 char fru_prev = 'X'; /* Valid frus are 'A','B','C','D' */
326 int mid_prev;
327 int ecache_size_prev = 0;
328 char fru_name;
329
330 /*
331 * display the CPUs' operating frequency, cache size, impl. field
332 * and mask revision.
333 */
334 for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
335 cpu = dev_next_type(cpu, "cpu")) {
336
337 mid = (int *)get_prop_val(find_prop(cpu, "portid"));
338 if (mid == NULL)
339 mid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
340 freq = DAK_CLK_FREQ_TO_MHZ(get_cpu_freq(cpu));
341 ecache_size = get_ecache_size(cpu);
342 impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
343 mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
344 l3_shares = (int *)get_prop_val(find_prop(cpu,
345 "l3-cache-sharing"));
346
347 /* Do not display a failed CPU node */
348 if ((impl == NULL) || (freq == 0) || (node_failed(cpu)))
349 continue;
350
351 /* Board number */
352 fru_name = (char)('A' + DAK_GETSLOT(*mid));
353
354 if (CPU_IMPL_IS_CMP(*impl)) {
355 coreid = (int *)get_prop_val(find_prop(cpu, "reg"));
356 if (coreid == NULL) {
357 continue;
358 }
359 if ((fru_prev == 'X') ||
360 ((fru_prev != 'X') &&
361 (fru_name != fru_prev))) {
362 fru_prev = fru_name;
363 mid_prev = *mid;
364 ecache_size_prev = ecache_size;
365 continue;
366 } else {
367 /*
368 * Some CMP chips have a split E$,
369 * so the size for both cores is added
370 * together to get the total size for
371 * the chip.
372 *
373 * Still, other CMP chips have E$ (L3)
374 * which is logically shared, so the
375 * total size is equal to the core size.
376 */
377 if ((l3_shares == NULL) ||
378 ((l3_shares != NULL) &&
379 MULTIPLE_BITS_SET(*l3_shares))) {
380 ecache_size += ecache_size_prev;
381 }
382 ecache_size_prev = 0;
383 fru_prev = 'X';
384 }
385 }
386
387 log_printf("%2c", fru_name);
388
389 /* CPU Module ID */
390 if (CPU_IMPL_IS_CMP(*impl)) {
391 log_printf("%3d,%3d", mid_prev, *mid, 0);
392 } else
393 log_printf(" %d ", *mid);
394
395 /* Running frequency */
396 log_printf(" %4u ", freq);
397
398 /* Ecache size */
399 if (ecache_size == 0)
400 log_printf(dgettext(TEXT_DOMAIN, "%3s "),
401 "N/A");
402 else
403 log_printf("%4.1f ",
404 (float)ecache_size / (float)(1<<20));
405
406 /* Implementation */
407 if (impl == NULL) {
408 log_printf(dgettext(TEXT_DOMAIN, "%s "),
409 "N/A");
410 } else {
411 if (IS_CHEETAH(*impl))
412 log_printf("%7s", "US-III ", 0);
413 else if (IS_CHEETAH_PLUS(*impl))
414 log_printf("%7s", "US-III+", 0);
415 else if (IS_JAGUAR(*impl))
416 log_printf("%7s", "US-IV ", 0);
417 else if (IS_PANTHER(*impl))
418 log_printf("%7s", "US-IV+ ", 0);
419 else
420 log_printf("%-7x", *impl, 0);
421 }
422
423 /* CPU Mask */
424 if (mask == NULL) {
425 log_printf(dgettext(TEXT_DOMAIN, " %3s "),
426 "N/A");
427 } else {
428 log_printf(dgettext(TEXT_DOMAIN, " %2d.%d"),
429 (*mask >> 4) & 0xf, *mask & 0xf);
430 }
431
432 log_printf("\n");
433 }
434 }
435
436 /*
437 * display_pci
438 * Display all the PCI IO cards on this board.
439 */
440 void
display_pci(Board_node * board)441 display_pci(Board_node *board)
442 {
443 struct io_card *card_list = NULL;
444 struct io_card card;
445 void *value;
446 Prom_node *pci;
447 Prom_node *card_node;
448 char *slot_name_arr[DAK_MAX_SLOTS_PER_IO_BD] = {NULL};
449 int i;
450 #ifdef DEBUG
451 int slot_name_bits;
452 #endif
453
454 if (board == NULL)
455 return;
456
457 memset(&card, 0, sizeof (struct io_card));
458 /* Initialize all the common information */
459 card.display = TRUE;
460 card.board = board->board_num;
461
462 /*
463 * Search for each pci instance, then find/display all nodes under
464 * each instance node found.
465 */
466 for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP);
467 pci != NULL;
468 pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) {
469 (void) snprintf(card.bus_type, MAXSTRLEN,
470 dgettext(TEXT_DOMAIN, "PCI"));
471 /*
472 * Get slot-name properties from parent node and
473 * store them in an array.
474 */
475 value = (char *)get_prop_val(
476 find_prop(pci, "slot-names"));
477
478 if (value != NULL) {
479 #ifdef DEBUG
480 /* save the 4 byte bitmask */
481 slot_name_bits = *(int *)value;
482 #endif
483
484 /* array starts after first int */
485 slot_name_arr[0] = (char *)value + sizeof (int);
486 for (i = 1; i < DAK_MAX_SLOTS_PER_IO_BD; i++) {
487 slot_name_arr[i] = (char *)slot_name_arr[i - 1]
488 + strlen(slot_name_arr[i - 1]) +1;
489 }
490 }
491 /*
492 * Search for Children of this node ie. Cards.
493 * Note: any of these cards can be a pci-bridge
494 * that itself has children. If we find a
495 * pci-bridge we need to handle it specially.
496 */
497 card_node = pci->child;
498 /* Generate the list of pci cards on pci instance: pci */
499 fill_pci_card_list(pci, card_node, &card, &card_list,
500 slot_name_arr);
501 } /* end-for */
502
503 display_io_cards(card_list);
504 free_io_cards(card_list);
505 log_printf("\n");
506 }
507
508 /*
509 * Print out all the io cards in the list. Also print the column
510 * headers if told to do so.
511 */
512 void
display_io_cards(struct io_card * list)513 display_io_cards(struct io_card *list)
514 {
515 static int banner = 0; /* Have we printed the column headings? */
516 struct io_card *p;
517
518 if (list == NULL)
519 return;
520
521 if (banner == FALSE) {
522 log_printf(dgettext(TEXT_DOMAIN,
523 " Bus Max\n"
524 " IO Port Bus Freq Bus Dev,"
525 "\n"
526 "Brd Type ID Side Slot MHz Freq "
527 "Func State Name "
528 "Model\n"
529 /* ---------Brd IO Port Bus Slot Bus Max Dev Stat */
530 "---- ---- ---- ---- ---- ---- ---- ----"
531 " ----- "
532 "-------------------------------- "
533 "----------------------\n"));
534 banner = TRUE;
535 }
536
537 for (p = list; p != NULL; p = p -> next) {
538 log_printf(dgettext(TEXT_DOMAIN, "I/O "));
539 log_printf("%-4s ", p->bus_type);
540 log_printf("%-3d ", p->schizo_portid);
541 log_printf("%c ", p->pci_bus);
542 log_printf("%-1s ", p->slot_str);
543 log_printf("%-3d ", p->freq);
544 switch (p->pci_bus) {
545 case 'A':
546 log_printf(dgettext(TEXT_DOMAIN, " 66 "));
547 break;
548 case 'B':
549 log_printf(dgettext(TEXT_DOMAIN, " 33 "));
550 break;
551 default:
552 log_printf(dgettext(TEXT_DOMAIN, " - "));
553 break;
554 }
555
556 log_printf("%-1d,%-1d ", p->dev_no, p->func_no);
557 log_printf("%-5s ", p->status);
558 log_printf("%-32.32s", p->name);
559 if (strlen(p->name) > 32)
560 log_printf(dgettext(TEXT_DOMAIN, "+ "));
561 else
562 log_printf(dgettext(TEXT_DOMAIN, " "));
563 log_printf("%-22.22s", p->model);
564 if (strlen(p->model) > 22)
565 log_printf(dgettext(TEXT_DOMAIN, "+"));
566
567 #ifdef DEBUG
568 log_printf(dgettext(TEXT_DOMAIN, "%s "), p->notes);
569 #endif
570 log_printf("\n");
571 }
572 }
573
574 /*
575 * display_ffb
576 *
577 * There are no FFB's on a Daktari, however in the generic library,
578 * the display_ffb() function is implemented so we have to define an
579 * empty function here.
580 */
581 /* ARGSUSED */
582 void
display_ffb(Board_node * board,int table)583 display_ffb(Board_node *board, int table)
584 {}
585
586
587 /*
588 * ----------------------------------------------------------------------------
589 */
590
591 /* ARGSUSED */
592 void
display_diaginfo(int flag,Prom_node * root,Sys_tree * tree,struct system_kstat_data * kstats)593 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
594 struct system_kstat_data *kstats)
595 {
596 /* NOTE(ARGUNUSED(kstats)) */
597 /*
598 * Now display the last powerfail time and the fatal hardware
599 * reset information. We do this under a couple of conditions.
600 * First if the user asks for it. The second is if the user
601 * told us to do logging, and we found a system failure.
602 */
603 if (flag) {
604 /*
605 * display time of latest powerfail. Not all systems
606 * have this capability. For those that do not, this
607 * is just a no-op.
608 */
609 disp_powerfail(root);
610
611 (void) disp_envc_status();
612
613 /* platform_disp_prom_version(tree); */
614 dak_display_hw_revisions(root, tree->bd_list);
615 }
616 }
617
618 /*
619 * local functions
620 */
621
622 /*
623 * disp_envc_status
624 *
625 * This routine displays the environmental status passed up from
626 * device drivers via the envlibobj.so library.
627 * This is a Daktari specific environmental information display routine.
628 */
629 int
disp_envc_status()630 disp_envc_status()
631 {
632 int err;
633 char *system = "SYSTEM";
634 picl_nodehdl_t system_node, root;
635
636 err = picl_initialize();
637 if (err != PICL_SUCCESS) {
638 log_printf(dgettext(TEXT_DOMAIN,
639 "picl_initialize failed\n"
640 "%s\nCannot display environmental status\n"),
641 picl_strerror(err));
642 return (err);
643 }
644 err = picl_get_root(&root);
645 err = find_child_device(root, system, &system_node);
646 if (err != PICL_SUCCESS) {
647 log_printf(dgettext(TEXT_DOMAIN,
648 "picl_get_node_by_path for the SYSTEM node "
649 "failed\n"
650 "%s\nCannot display environmental status\n"),
651 picl_strerror(err));
652 return (err);
653 }
654
655 log_printf(dgettext(TEXT_DOMAIN,
656 "\n"
657 "========================= "
658 "Environmental Status "
659 "========================="
660 "\n"
661 "\n"));
662
663 dak_env_print_temps(system_node);
664 dak_env_print_keyswitch(system_node);
665 dak_env_print_FSP_LEDS(system_node);
666 dak_env_print_disk(system_node);
667 dak_env_print_fans(system_node);
668 dak_env_print_ps(system_node);
669
670 (void) picl_shutdown();
671 return (0);
672 }
673
674 int
dak_env_print_ps(picl_nodehdl_t system_node)675 dak_env_print_ps(picl_nodehdl_t system_node)
676 {
677 int i, r, fail, err = 0;
678 int low_warn_flag = 0;
679 int32_t number;
680 char name[PICL_PROPNAMELEN_MAX];
681 picl_nodehdl_t *ps;
682 picl_nodehdl_t *ps_fail[DAK_MAX_PS_FAULT_SENSORS];
683 picl_nodehdl_t *ps_I_sensor[DAK_MAX_PS_VOLTAGE_SENSORS];
684 int32_t volts[DAK_MAX_PS_VOLTAGE_SENSORS];
685 int32_t lo_warn[DAK_MAX_PS_VOLTAGE_SENSORS];
686 char fault_state
687 [DAK_MAX_PS_FAULT_SENSORS][PICL_PROPNAMELEN_MAX];
688 char ps_state[PICL_PROPNAMELEN_MAX];
689 /* Printing out the Power Supply Heading information */
690 log_printf(dgettext(TEXT_DOMAIN,
691 "Power Supplies:\n"
692 "---------------\n"
693 " "
694 "Current Drain:\n"
695 "Supply Status Fan Fail Temp Fail CS Fail "
696 "3.3V 5V 12V 48V\n"
697 "------ ------------ -------- --------- "
698 "------- ---- -- --- ---\n"));
699
700 err = fill_device_array_from_id(system_node, "PSVC_PS", &number,
701 &ps);
702 if (err != PICL_SUCCESS) {
703 log_printf(dgettext(TEXT_DOMAIN,
704 "failed in fill_device_array_from_id for PS\n"
705 "%s\n"), picl_strerror(err));
706 return (err);
707 }
708 /* Printing out the Power Supply Status information */
709 for (i = 0; i < DAK_MAX_PS; i++) {
710 /*
711 * Re initialize the fail variable so that if
712 * one power supply fails, they don't all do also.
713 */
714 fail = 0;
715
716 err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name,
717 PICL_PROPNAMELEN_MAX);
718 if (err != PICL_SUCCESS) {
719 continue;
720 }
721 err = picl_get_propval_by_name(ps[i], "State", ps_state,
722 PICL_PROPNAMELEN_MAX);
723 if (err != PICL_SUCCESS) {
724 log_printf(dgettext(TEXT_DOMAIN,
725 "Error getting ps[%d]'s state: %s"),
726 i, picl_strerror(err));
727 }
728
729 err = fill_device_array_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR",
730 &number, &ps_fail[i]);
731
732 if (err != PICL_SUCCESS) {
733 log_printf(dgettext(TEXT_DOMAIN,
734 "failed to get present PS fault sensors\n"
735 "%s\n"), picl_strerror(err));
736 return (err);
737 }
738
739 err = fill_device_array_from_id(ps[i], "PSVC_PS_I_SENSOR",
740 &number, &ps_I_sensor[i]);
741
742 if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) {
743 log_printf(dgettext(TEXT_DOMAIN,
744 "failed to get present PS I sensors\n"
745 "%s\n"), picl_strerror(err));
746 }
747
748 log_printf("%s", name);
749
750 /*
751 * If the AC cord is unplugged, then the power supply
752 * sensors will have unreliable values. In this case,
753 * skip to the next power supply.
754 */
755 if (strcmp(ps_state, "HOTPLUGGED") == 0) {
756 log_printf(dgettext(TEXT_DOMAIN,
757 " UNPLUGGED\n"));
758 continue;
759 }
760
761 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) {
762 err = picl_get_propval_by_name(ps_fail[i][r], "State",
763 fault_state[r], PICL_PROPNAMELEN_MAX);
764 if (err == PICL_SUCCESS) {
765 fail =
766 strcmp(fault_state[r], "OFF")
767 + fail;
768 } else {
769 log_printf(dgettext(TEXT_DOMAIN,
770 "picl_get_propval_by_name for ps "
771 "fault state failed\n"
772 "%s\n"), picl_strerror(err));
773 return (err);
774 }
775 }
776 for (r = 0; r < DAK_MAX_PS_VOLTAGE_SENSORS; r++) {
777 err = picl_get_propval_by_name(ps_I_sensor[i][r],
778 "AtoDSensorValue", &volts[r],
779 sizeof (int32_t));
780 if (err != PICL_SUCCESS) {
781 log_printf(dgettext(TEXT_DOMAIN,
782 "failed to get A to D sensor "
783 "value\n%s\n"), picl_strerror(err));
784 return (err);
785 }
786 err = picl_get_propval_by_name(ps_I_sensor[i][r],
787 "LowWarningThreshold", &lo_warn[r],
788 sizeof (int32_t));
789 if (err != PICL_SUCCESS) {
790 log_printf(dgettext(TEXT_DOMAIN,
791 "failed to get low warning threshold "
792 "value\n%s\n"), picl_strerror(err));
793 return (err);
794 }
795 if (volts[r] <= lo_warn[r])
796 low_warn_flag++;
797 }
798
799 if (fail != 0 || low_warn_flag != 0) {
800 log_printf(dgettext(TEXT_DOMAIN,
801 " FAIL "));
802 } else {
803 log_printf(dgettext(TEXT_DOMAIN, " GOOD "));
804 }
805
806 if (fail != 0) {
807 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) {
808 log_printf(dgettext(TEXT_DOMAIN, " %-4s"),
809 fault_state[r]);
810 }
811 } else {
812 for (r = 0; r < DAK_MAX_PS_FAULT_SENSORS; r++) {
813 log_printf(dgettext(TEXT_DOMAIN, " "));
814 }
815 }
816 for (r = 0; r < DAK_MAX_PS_VOLTAGE_SENSORS; r++) {
817 log_printf(dgettext(TEXT_DOMAIN, " %2d"), volts[r]);
818 }
819 log_printf("\n");
820 }
821 log_printf("\n");
822 return (err);
823 }
824
825 int
dak_env_print_fans(picl_nodehdl_t system_node)826 dak_env_print_fans(picl_nodehdl_t system_node)
827 {
828 int i, err = 0;
829 int32_t number, fan_speed;
830 picl_nodehdl_t *fans;
831 char name[PICL_PROPNAMELEN_MAX];
832 char enabled[PICL_PROPNAMELEN_MAX];
833
834 err = fill_device_array_from_id(system_node, "PSVC_FAN", &number,
835 &fans);
836 if (err != PICL_SUCCESS) {
837 log_printf(dgettext(TEXT_DOMAIN,
838 "failed in fill_device_array_from_id "
839 "for FAN\n"
840 "%s\n"), picl_strerror(err));
841 return (err);
842 }
843
844 log_printf("\n");
845 log_printf(dgettext(TEXT_DOMAIN,
846 "=================================\n"));
847 log_printf("\n");
848 log_printf(dgettext(TEXT_DOMAIN, "Fan Bank :\n"));
849 log_printf(dgettext(TEXT_DOMAIN, "----------\n"));
850 log_printf("\n");
851 log_printf(dgettext(TEXT_DOMAIN, "Bank Speed "
852 " Status Fan State\n"));
853 log_printf(dgettext(TEXT_DOMAIN, " ( RPMS )"
854 " \n"));
855 log_printf(dgettext(TEXT_DOMAIN, "---- --------"
856 " --------- ---------\n"));
857
858
859 for (i = 0; i < DAK_MAX_FANS; i++) {
860 char fan_state[PICL_PROPNAMELEN_MAX];
861 fan_speed = 0;
862 err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, name,
863 PICL_PROPNAMELEN_MAX);
864 if (err == PICL_SUCCESS) {
865 log_printf(dgettext(TEXT_DOMAIN, "%16-s"), name);
866 } else {
867 continue;
868 }
869
870 err = picl_get_propval_by_name(fans[i], "Fan-speed",
871 &fan_speed, sizeof (int32_t));
872 if ((err != PICL_SUCCESS) && (err != PICL_INVALIDHANDLE)) {
873 log_printf(dgettext(TEXT_DOMAIN,
874 "failed in picl_get_propval_by_name for "
875 "fan speed\n"
876 "%s\n"), picl_strerror(err));
877 return (err);
878 }
879
880 if ((strcmp(name, "CPU0_PRIM_FAN") != 0) &&
881 (strcmp(name, "CPU1_PRIM_FAN") != 0)) {
882 err = picl_get_propval_by_name(fans[i], "Fan-switch",
883 enabled, PICL_PROPNAMELEN_MAX);
884 if ((err != PICL_SUCCESS) &&
885 (err != PICL_INVALIDHANDLE)) {
886 log_printf(dgettext(TEXT_DOMAIN,
887 "failed in picl_get_propval_by_name for"
888 " fan enabled/disabled\n"
889 "%s\n"), picl_strerror(err));
890 return (err);
891 }
892 /*
893 * Display the fan's speed and whether or not
894 * it's enabled.
895 */
896 if (strcmp(enabled, "ON") == 0) {
897 log_printf(dgettext(TEXT_DOMAIN,
898 "\t %4d [ENABLED]"),
899 fan_speed);
900 } else {
901 log_printf(dgettext(TEXT_DOMAIN,
902 "\t 0 [DISABLED]"));
903 }
904
905 } else {
906 /* Display the fan's speed */
907 log_printf(dgettext(TEXT_DOMAIN, "\t %4d"),
908 fan_speed);
909 log_printf(dgettext(TEXT_DOMAIN,
910 " [ENABLED]"));
911 }
912
913 err = picl_get_propval_by_name(fans[i], "State", fan_state,
914 PICL_PROPNAMELEN_MAX);
915 if (err != PICL_SUCCESS) {
916 log_printf(dgettext(TEXT_DOMAIN,
917 "picl_get_propval_by_name failed: %s"),
918 picl_strerror(err));
919 return (err);
920 }
921 log_printf(dgettext(TEXT_DOMAIN, "\t %s\n"), fan_state);
922 }
923 log_printf("\n");
924 log_printf(dgettext(TEXT_DOMAIN,
925 "=================================\n"));
926 log_printf("\n");
927
928 return (err);
929 }
930
931 int
dak_env_print_disk(picl_nodehdl_t system_node)932 dak_env_print_disk(picl_nodehdl_t system_node)
933 {
934 int i, err;
935 int32_t number;
936 picl_nodehdl_t *disks;
937 picl_nodehdl_t disk_slots[DAK_MAX_DISKS];
938 picl_nodehdl_t disk_fault_leds[DAK_MAX_DISKS];
939 picl_nodehdl_t disk_remove_leds[DAK_MAX_DISKS];
940 char led_state[PICL_PROPNAMELEN_MAX];
941 char name[PICL_PROPNAMELEN_MAX];
942
943 err = fill_device_array_from_id(system_node, "PSVC_DISK", &number,
944 &disks);
945 if (err != PICL_SUCCESS) {
946 log_printf(dgettext(TEXT_DOMAIN,
947 "failed in fill_device_array_from_id for "
948 "DISK\n"
949 "%s\n"), picl_strerror(err));
950 return (err);
951 }
952
953 log_printf(dgettext(TEXT_DOMAIN,
954 "Disk Status:\n"
955 " Presence Fault LED Remove LED\n"));
956
957 for (i = 0; i < DAK_MAX_DISKS; i++) {
958 err = picl_get_propval_by_name(disks[i], PICL_PROP_NAME, name,
959 PICL_PROPNAMELEN_MAX);
960 switch (err) {
961 case PICL_SUCCESS:
962 log_printf(dgettext(TEXT_DOMAIN, "DISK %2d: [%7s]"),
963 i, "PRESENT");
964 break;
965 case PICL_INVALIDHANDLE:
966 log_printf(dgettext(TEXT_DOMAIN, "DISK %2d: [%7s]"),
967 i, "EMPTY");
968 log_printf("\n");
969 continue;
970 default:
971 log_printf(dgettext(TEXT_DOMAIN,
972 "Failed picl_get_propval_by_name for "
973 "disk %d with %s\n"), i, picl_strerror(err));
974 return (err);
975 }
976
977 err = fill_device_from_id(disks[i], "PSVC_PARENT",
978 &(disk_slots[i]));
979 switch (err) {
980 case PICL_SUCCESS:
981 break;
982 case PICL_INVALIDHANDLE:
983 continue;
984 default:
985 log_printf(dgettext(TEXT_DOMAIN,
986 "failed in fill_device_from_id for disk "
987 "slot\n"
988 "%s\n"), picl_strerror(err));
989 return (err);
990 }
991
992 err = fill_device_from_id(disk_slots[i], "PSVC_SLOT_FAULT_LED",
993 &disk_fault_leds[i]);
994 if (err != PICL_SUCCESS) {
995 log_printf(dgettext(TEXT_DOMAIN,
996 "failed in fill_device_from_id for disk slot "
997 "fault led\n"
998 "%s\n"), picl_strerror(err));
999 return (err);
1000 }
1001 err = picl_get_propval_by_name(disk_fault_leds[i],
1002 "State", led_state, PICL_PROPNAMELEN_MAX);
1003 if (err == PICL_SUCCESS) {
1004 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"),
1005 led_state);
1006 } else {
1007 log_printf(dgettext(TEXT_DOMAIN,
1008 "picl_get_propval_by_name for fault led_state"
1009 " failed\n"
1010 "%s\n"), picl_strerror(err));
1011 return (err);
1012 }
1013 err = fill_device_from_id(disk_slots[i], "PSVC_SLOT_REMOVE_LED",
1014 &disk_remove_leds[i]);
1015 if (err != PICL_SUCCESS) {
1016 log_printf(dgettext(TEXT_DOMAIN,
1017 "failed in fill_device_from_id for disk slot "
1018 "remove led\n"
1019 "%s\n"), picl_strerror(err));
1020 return (err);
1021 }
1022
1023 err = picl_get_propval_by_name(disk_remove_leds[i],
1024 "State", led_state, PICL_PROPNAMELEN_MAX);
1025 if (err == PICL_SUCCESS) {
1026 log_printf(dgettext(TEXT_DOMAIN,
1027 " [%3s]"), led_state);
1028 } else {
1029 log_printf(dgettext(TEXT_DOMAIN,
1030 "picl_get_propval_by_name for remove"
1031 " led_state failed\n"
1032 "%s\n"), picl_strerror(err));
1033 return (err);
1034 }
1035 log_printf("\n");
1036 }
1037 return (err);
1038 }
1039
1040 int
dak_env_print_FSP_LEDS(picl_nodehdl_t system_node)1041 dak_env_print_FSP_LEDS(picl_nodehdl_t system_node)
1042 {
1043 int i, err = 0;
1044 int32_t number;
1045 picl_nodehdl_t *fsp_leds;
1046 char led_state[PICL_PROPNAMELEN_MAX];
1047
1048 err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number,
1049 &fsp_leds);
1050 if (err != PICL_SUCCESS) {
1051 log_printf(dgettext(TEXT_DOMAIN,
1052 "failed in fill_device_array_from_id for "
1053 "FSP_LED\n"
1054 "%s\n"), picl_strerror(err));
1055 return (err);
1056 }
1057
1058 log_printf(dgettext(TEXT_DOMAIN,
1059 "System LED Status:\n"
1060 " GEN FAULT REMOVE\n"));
1061 for (i = 0; i < DAK_MAX_FSP_LEDS; i++) {
1062 err = picl_get_propval_by_name(fsp_leds[i], "State",
1063 led_state, PICL_PROPNAMELEN_MAX);
1064 if (err != PICL_SUCCESS) {
1065 log_printf(dgettext(TEXT_DOMAIN,
1066 "picl_get_propval_by_name for led_state"
1067 " failed\n"
1068 "%s\n"), picl_strerror(err));
1069 return (err);
1070 }
1071
1072 log_printf(dgettext(TEXT_DOMAIN,
1073 " [%3s]"), led_state);
1074 }
1075 log_printf("\n\n");
1076 log_printf(dgettext(TEXT_DOMAIN,
1077 " DISK FAULT "));
1078 log_printf(dgettext(TEXT_DOMAIN, "POWER FAULT\n"));
1079 for (i = 2; i < 4; i++) {
1080 err = picl_get_propval_by_name(fsp_leds[i], "State",
1081 led_state, PICL_PROPNAMELEN_MAX);
1082 if (err != PICL_SUCCESS) {
1083 log_printf(dgettext(TEXT_DOMAIN,
1084 "picl_get_propval_by_name for led_state"
1085 " failed\n"
1086 "%s\n"), picl_strerror(err));
1087 return (err);
1088 }
1089 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"),
1090 led_state);
1091 }
1092 log_printf("\n\n");
1093 log_printf(dgettext(TEXT_DOMAIN,
1094 " LEFT THERMAL FAULT "
1095 "RIGHT THERMAL FAULT\n"));
1096 for (i = 4; i < 6; i++) {
1097 err = picl_get_propval_by_name(fsp_leds[i], "State",
1098 led_state, PICL_PROPNAMELEN_MAX);
1099 if (err != PICL_SUCCESS) {
1100 log_printf(dgettext(TEXT_DOMAIN,
1101 "picl_get_propval_by_name for led_state "
1102 "failed\n"
1103 "%s\n"), picl_strerror(err));
1104 return (err);
1105 }
1106 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"),
1107 led_state);
1108 }
1109 log_printf("\n\n");
1110 log_printf(dgettext(TEXT_DOMAIN,
1111 " LEFT DOOR "
1112 "RIGHT DOOR\n"));
1113 for (i = 6; i < 8; i++) {
1114 err = picl_get_propval_by_name(fsp_leds[i], "State",
1115 led_state, PICL_PROPNAMELEN_MAX);
1116 if (err != PICL_SUCCESS) {
1117 log_printf(dgettext(TEXT_DOMAIN,
1118 "picl_get_propval_by_name for led_state"
1119 " failed\n"
1120 "%s\n"), picl_strerror(err));
1121 return (err);
1122 }
1123 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"),
1124 led_state);
1125 }
1126 log_printf("\n\n");
1127 log_printf(dgettext(TEXT_DOMAIN,
1128 "=================================\n"));
1129 log_printf("\n");
1130
1131 return (err);
1132 }
1133
1134 int
dak_env_print_keyswitch(picl_nodehdl_t system_node)1135 dak_env_print_keyswitch(picl_nodehdl_t system_node)
1136 {
1137 int err = 0;
1138 picl_nodehdl_t *keyswitch;
1139 int32_t number;
1140 char ks_pos[PICL_PROPNAMELEN_MAX];
1141
1142 err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number,
1143 &keyswitch);
1144 if (err != PICL_SUCCESS) {
1145 log_printf(dgettext(TEXT_DOMAIN,
1146 "failed in fill_device_array_from_id for "
1147 " PSVC_KEYSWITCH\n"
1148 "%s\n"), picl_strerror(err));
1149 return (err);
1150 }
1151
1152 err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos,
1153 PICL_PROPNAMELEN_MAX);
1154 if (err != PICL_SUCCESS) {
1155 log_printf(dgettext(TEXT_DOMAIN,
1156 "picl_get_propval_by_name for keyswitch state "
1157 "failed\n"
1158 "%s\n"), picl_strerror(err));
1159 return (err);
1160 }
1161
1162 log_printf(dgettext(TEXT_DOMAIN,
1163 "Front Status Panel:\n"
1164 "-------------------\n"
1165 "Keyswitch position: "
1166 "%s\n"), ks_pos);
1167 log_printf("\n");
1168
1169 return (err);
1170 }
1171
1172 int
dak_env_print_temps(picl_nodehdl_t system_node)1173 dak_env_print_temps(picl_nodehdl_t system_node)
1174 {
1175 int i;
1176 int err;
1177 picl_nodehdl_t *system_ts_nodes;
1178 int32_t temp;
1179 int32_t number;
1180 char label[PICL_PROPNAMELEN_MAX];
1181 char state[PICL_PROPNAMELEN_MAX];
1182 char *p;
1183
1184 err = fill_device_array_from_id(system_node, "PSVC_TS", &number,
1185 &system_ts_nodes);
1186 if (err != PICL_SUCCESS) {
1187 return (err);
1188 }
1189
1190 log_printf(dgettext(TEXT_DOMAIN,
1191 "System Temperatures (Celsius):\n"
1192 "-------------------------------\n"
1193 "Device\t\tTemperature\tStatus\n"
1194 "---------------------------------------\n"));
1195
1196 for (i = 0; i < number; i++) {
1197 err = picl_get_propval_by_name(system_ts_nodes[i],
1198 "State", state, sizeof (state));
1199 if (err != PICL_SUCCESS) {
1200 if (err == PICL_INVALIDHANDLE) {
1201 strcpy(state, "n/a");
1202 } else {
1203 log_printf("%s\n", picl_strerror(err));
1204 return (err);
1205 }
1206 }
1207 err = picl_get_propval_by_name(system_ts_nodes[i],
1208 PICL_PROP_NAME, label, PICL_PROPNAMELEN_MAX);
1209 if (err != PICL_SUCCESS) {
1210 if (err == PICL_INVALIDHANDLE)
1211 /* This FRU isn't present. Skip it. */
1212 continue;
1213 log_printf("%s\n", picl_strerror(err));
1214 return (err);
1215 }
1216
1217 /*
1218 * The names in the tree are like "CPU0_DIE_TEMPERATURE_SENSOR".
1219 * All we want to print is up to the first underscore.
1220 */
1221 p = strchr(label, '_');
1222 if (p != NULL)
1223 *p = '\0';
1224
1225 err = picl_get_propval_by_name(system_ts_nodes[i],
1226 "Temperature", &temp, sizeof (temp));
1227 if (err != PICL_SUCCESS) {
1228 log_printf("%s\n", picl_strerror(err));
1229 return (err);
1230 }
1231 log_printf("%s\t\t%3d\t\t%s\n", label, temp, state);
1232 }
1233
1234 log_printf(dgettext(TEXT_DOMAIN,
1235 "\n=================================\n\n"));
1236
1237 return (PICL_SUCCESS);
1238 }
1239
1240 static void
dak_display_hw_revisions(Prom_node * root,Board_node * bdlist)1241 dak_display_hw_revisions(Prom_node *root, Board_node *bdlist)
1242 {
1243 Prom_node *pnode;
1244 char *value;
1245
1246 log_printf(dgettext(TEXT_DOMAIN, "\n"
1247 "========================= HW Revisions "
1248 "=======================================\n\n"));
1249
1250 log_printf(dgettext(TEXT_DOMAIN,
1251 "System PROM revisions:\n"
1252 "----------------------\n"));
1253
1254 pnode = dev_find_node(root, "openprom");
1255 if (pnode != NULL) {
1256 value = (char *)get_prop_val(find_prop(pnode, "version"));
1257 log_printf(value);
1258 }
1259
1260 log_printf(dgettext(TEXT_DOMAIN, "\n\n"
1261 "IO ASIC revisions:\n"
1262 "------------------\n"
1263 " Port\n"
1264 "Model ID Status Version\n"
1265 "-------- ---- ------ -------\n"));
1266
1267 display_schizo_revisions(bdlist);
1268 }
1269
1270 static void
display_schizo_revisions(Board_node * bdlist)1271 display_schizo_revisions(Board_node *bdlist)
1272 {
1273 Prom_node *pnode;
1274 int *int_val;
1275 int portid;
1276 int prev_portid = -1;
1277 char *status_a = NULL;
1278 char *status_b = NULL;
1279 int revision;
1280 #ifdef DEBUG
1281 uint32_t a_notes, b_notes;
1282 #endif
1283 int pci_bus;
1284 Board_node *bnode;
1285 bnode = bdlist;
1286
1287 while (bnode != NULL) {
1288 /*
1289 * search this board node for all Schizos
1290 */
1291 for (pnode = dev_find_node_by_compat(bnode->nodes,
1292 SCHIZO_COMPAT_PROP); pnode != NULL;
1293 pnode = dev_next_node_by_compat(pnode,
1294 SCHIZO_COMPAT_PROP)) {
1295
1296 /*
1297 * get the reg property to determine
1298 * whether we are looking at side A or B
1299 */
1300 int_val = (int *)get_prop_val
1301 (find_prop(pnode, "reg"));
1302 if (int_val != NULL) {
1303 int_val ++; /* second integer in array */
1304 pci_bus = ((*int_val) & 0x7f0000);
1305 }
1306
1307 /* get portid */
1308 int_val = (int *)get_prop_val
1309 (find_prop(pnode, "portid"));
1310 if (int_val == NULL)
1311 continue;
1312
1313 portid = *int_val;
1314
1315 /*
1316 * If this is a new portid and it is PCI bus B,
1317 * we skip onto the PCI bus A.
1318 */
1319 if ((portid != prev_portid) && (pci_bus == 0x700000)) {
1320 prev_portid = portid;
1321 /* status */
1322 status_b = (char *)get_prop_val
1323 (find_prop(pnode, "status"));
1324 #ifdef DEBUG
1325 b_notes = pci_bus;
1326 #endif
1327 continue; /* skip to the next schizo */
1328 }
1329
1330 /*
1331 * This must be side A of the same Schizo.
1332 * Gather all its props and display them.
1333 */
1334 #ifdef DEBUG
1335 a_notes = pci_bus;
1336 #endif
1337
1338 prev_portid = portid;
1339
1340 int_val = (int *)get_prop_val
1341 (find_prop(pnode, "version#"));
1342 if (int_val != NULL)
1343 revision = *int_val;
1344 else
1345 revision = -1;
1346
1347 status_a = (char *)get_prop_val(find_prop
1348 (pnode, "status"));
1349
1350 log_printf(dgettext(TEXT_DOMAIN, "Schizo "));
1351
1352 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0);
1353
1354
1355 log_printf((status_a == NULL && status_b == NULL) ?
1356 dgettext(TEXT_DOMAIN, " ok ") :
1357 dgettext(TEXT_DOMAIN, " fail "));
1358
1359 log_printf(dgettext(TEXT_DOMAIN, " %4d "),
1360 revision);
1361 #ifdef DEBUG
1362 log_printf(" 0x%x 0x%x", a_notes, b_notes);
1363 #endif
1364 log_printf("\n");
1365 }
1366 bnode = bnode->next;
1367 }
1368 }
1369