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 * Littleneck Platform specific functions.
26 *
27 * called when :
28 * machine_type == MTYPE_LITTLENECK
29 *
30 */
31
32 #pragma ident "%Z%%M% %I% %E% SMI"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <kstat.h>
38 #include <string.h>
39 #include <assert.h>
40 #include <libintl.h>
41 #include <note.h>
42 #include <syslog.h>
43
44 #include <sys/openpromio.h>
45 #include <sys/sysmacros.h>
46
47 #include <pdevinfo.h>
48 #include <display.h>
49 #include <pdevinfo_sun4u.h>
50 #include <display_sun4u.h>
51 #include <libprtdiag.h>
52
53 #include <picl.h>
54 #include "workfile.c"
55
56 #define LNECK_MAX_PS 2
57 #define LNECK_MAX_DISKS 2
58 #define LNECK_MAX_FANS 1
59
60 #ifndef SCHIZO_COMPAT_PROP
61 #define SCHIZO_COMPAT_PROP "pci108e,8001"
62 #endif
63
64 /* Count of failed PSU's found */
65 int ps_failure = 0;
66
67 /*
68 * Ignore first entry into disp_envc_status()
69 * from libprtdiag/common/display_sun4u.c
70 */
71 int print_flag = 0;
72
73 /*
74 * these functions will overlay the symbol table of libprtdiag
75 * at runtime (workgroup server systems only)
76 */
77 int error_check(Sys_tree *tree, struct system_kstat_data *kstats);
78 void display_cpu_devices(Sys_tree *tree);
79 void display_pci(Board_node *board);
80 void display_io_cards(struct io_card *list);
81 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
82 struct system_kstat_data *kstats);
83 void display_ffb(Board_node *board, int table);
84 void display_memoryconf(Sys_tree *tree, struct grp_info *grps);
85
86 /* local functions */
87 static int disp_envc_status(void);
88 static int lneck_env_print_temps(picl_nodehdl_t);
89 static int lneck_env_print_keyswitch(picl_nodehdl_t);
90 static int lneck_env_print_FSP_LEDS(picl_nodehdl_t);
91 static int lneck_env_print_disk(picl_nodehdl_t);
92 static int lneck_env_print_fans(picl_nodehdl_t);
93 static int lneck_env_print_ps(picl_nodehdl_t);
94
95 static void lneck_display_hw_revisions(Prom_node *root,
96 Board_node *bnode);
97 static void display_schizo_revisions(Board_node *bdlist);
98
99 /*
100 * Defining the error_check function in order to return the
101 * appropriate error code.
102 */
103 /*ARGSUSED0*/
104 int
error_check(Sys_tree * tree,struct system_kstat_data * kstats)105 error_check(Sys_tree *tree, struct system_kstat_data *kstats)
106 {
107 int exit_code = 0; /* init to all OK */
108 /* silently check for any types of machine errors */
109 print_flag = 0;
110 if (disp_fail_parts(tree) || disp_envc_status())
111 /* set exit_code to show failures */
112 exit_code = 1;
113
114 print_flag = 1;
115
116 return (exit_code);
117 }
118
119 void
display_cpu_devices(Sys_tree * tree)120 display_cpu_devices(Sys_tree *tree)
121 {
122 Board_node *bnode;
123
124 /*
125 * Display the table header for CPUs . Then display the CPU
126 * frequency, cache size, and processor revision of all cpus.
127 */
128 log_printf(dgettext(TEXT_DOMAIN,
129 "\n"
130 "========================= CPUs "
131 "==============================================="
132 "\n"
133 "\n"
134 " Run E$ CPU CPU \n"
135 "Brd CPU MHz MB Impl. Mask \n"
136 "--- --- ---- ---- ------- ---- \n"));
137
138 /* Now display all of the cpus on each board */
139 bnode = tree->bd_list;
140 while (bnode != NULL) {
141 display_cpus(bnode);
142 bnode = bnode->next;
143 }
144
145 log_printf("\n");
146 }
147
148
149 /*
150 * Display the CPUs present on this board.
151 */
152 void
display_cpus(Board_node * board)153 display_cpus(Board_node *board)
154 {
155 Prom_node *cpu;
156 char cpu_name[] = "cpu";
157
158 /*
159 * display the CPUs' operating frequency, cache size, impl. field
160 * and mask revision.
161 */
162
163 for (cpu = dev_find_type(board->nodes, cpu_name); cpu != NULL;
164 cpu = dev_next_type(cpu, cpu_name)) {
165 uint_t freq; /* CPU clock frequency */
166 int ecache_size; /* External cache size */
167 int *mid;
168 int *impl;
169 int *mask;
170
171 mid = (int *)get_prop_val(find_prop(cpu, "portid"));
172 freq = LNECK_CLK_FREQ_TO_MHZ(get_cpu_freq(cpu));
173 ecache_size = get_ecache_size(cpu);
174 impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
175 mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
176
177 /* Do not display a failed CPU node */
178 if ((freq != 0) && (node_failed(cpu) == 0)) {
179 /* Board number */
180 switch (*mid) {
181 case 1:
182 log_printf(dgettext(TEXT_DOMAIN,
183 " B "));
184 break;
185 case 0:
186 log_printf(dgettext(TEXT_DOMAIN,
187 " A "));
188 break;
189 default:
190 log_printf(dgettext(TEXT_DOMAIN, "X "));
191 }
192
193 /* CPU MID */
194 log_printf("%2d ", *mid);
195
196 /* Module number */
197
198 /* Running frequency */
199 log_printf("%4u ", freq);
200
201 /* Ecache size */
202 if (ecache_size == 0)
203 log_printf("N/A ");
204 else
205 log_printf("%4.1f ",
206 (float)ecache_size / (float)(1<<20));
207
208 /* Implementation */
209 if (impl == NULL) {
210 log_printf(dgettext(TEXT_DOMAIN, "%6s "),
211 " N/A");
212 } else {
213 if (IS_CHEETAH(*impl))
214 log_printf("%-7s ", "US-III", 0);
215 else if (IS_CHEETAH_PLUS(*impl))
216 log_printf("%-7s ", "US-III+", 0);
217 else
218 log_printf("%-7x ", *impl, 0);
219 }
220
221 /* CPU Mask */
222 if (mask == NULL) {
223 log_printf(dgettext(TEXT_DOMAIN, " N/A "));
224 } else {
225 log_printf(dgettext(TEXT_DOMAIN, " %d.%d "),
226 (*mask >> 4) & 0xf, *mask & 0xf);
227 }
228
229 log_printf("\n");
230 }
231 }
232 }
233
234 /*ARGSUSED0*/
235 void
display_memoryconf(Sys_tree * tree,struct grp_info * grps)236 display_memoryconf(Sys_tree *tree, struct grp_info *grps)
237 {
238 Board_node *bnode = tree->bd_list;
239
240 log_printf(dgettext(TEXT_DOMAIN,
241 "========================= Memory Configuration"
242 " ===============================\n"
243 "\n Logical Logical Logical "
244 "\n MC Bank Bank Bank DIMM "
245 "Interleave Interleaved"
246 "\n Brd ID num size Status Size "
247 "Factor with"
248 "\n---- --- ---- ------ ----------- ------ "
249 "---------- -----------"));
250
251 while (bnode != NULL) {
252 if (get_us3_mem_regs(bnode)) {
253 log_printf(dgettext(TEXT_DOMAIN,
254 "\nFailed to get memory information.\n"));
255 return;
256 }
257 bnode = bnode->next;
258 }
259
260 /* Display what we have found */
261 display_us3_banks();
262 }
263
264 /*ARGSUSED2*/
265 void
display_diaginfo(int flag,Prom_node * root,Sys_tree * tree,struct system_kstat_data * kstats)266 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
267 struct system_kstat_data *kstats)
268 {
269 /*
270 * Now display the last powerfail time and the fatal hardware
271 * reset information. We do this under a couple of conditions.
272 * First if the user asks for it. The second is iof the user
273 * told us to do logging, and we found a system failure.
274 */
275
276 if (flag) {
277 /*
278 * display time of latest powerfail. Not all systems
279 * have this capability. For those that do not, this
280 * is just a no-op.
281 */
282 disp_powerfail(root);
283
284 (void) disp_envc_status();
285
286 /* Hardware revision function calls */
287 lneck_display_hw_revisions(root, tree->bd_list);
288 log_printf("\n");
289 }
290 return;
291
292 }
293
294 /*
295 * display_pci
296 * Display all the PCI IO cards on this board.
297 */
298 void
display_pci(Board_node * board)299 display_pci(Board_node *board)
300 {
301 struct io_card *card_list = NULL;
302 struct io_card card;
303 void *value;
304 Prom_node *pci;
305 Prom_node *card_node;
306
307 char *slot_name_arr[LNECK_MAX_SLOTS_PER_IO_BD] = {NULL};
308 int i;
309
310 if (board == NULL)
311 return;
312
313 memset(&card, 0, sizeof (struct io_card));
314 /* Initialize all the common information */
315 card.display = TRUE;
316 card.board = board->board_num;
317
318 /*
319 * Search for each pci instance, then find/display all nodes under
320 * each instance node found.
321 */
322 for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP);
323 pci != NULL;
324 pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) {
325 (void) snprintf(card.bus_type, MAXSTRLEN,
326 dgettext(TEXT_DOMAIN, "PCI"));
327 /*
328 * Get slot-name properties from parent node and
329 * store them in an array.
330 */
331 value = (char *)get_prop_val(
332 find_prop(pci, "slot-names"));
333
334 if (value != NULL) {
335 /* array starts after first int */
336 slot_name_arr[0] = (char *)value + sizeof (int);
337 for (i = 1; i < LNECK_MAX_SLOTS_PER_IO_BD; i++) {
338 slot_name_arr[i] = (char *)slot_name_arr[i - 1]
339 + strlen(slot_name_arr[i - 1]) +1;
340 }
341 }
342 /*
343 * Search for Children of this node ie. Cards.
344 * Note: any of these cards can be a pci-bridge
345 * that itself has children. If we find a
346 * pci-bridge we need to handle it specially.
347 */
348 card_node = pci->child;
349 /* Generate the list of pci cards on pci instance: pci */
350 fill_pci_card_list(pci, card_node, &card, &card_list,
351 slot_name_arr);
352 } /* end-for */
353
354 display_io_cards(card_list);
355 free_io_cards(card_list);
356 log_printf("\n");
357 }
358
359 /*
360 * Print out all the io cards in the list. Also print the column
361 * headers if told to do so.
362 */
363 void
display_io_cards(struct io_card * list)364 display_io_cards(struct io_card *list)
365 {
366 static int banner = 0; /* Have we printed the column headings? */
367 struct io_card *p;
368
369 if (list == NULL) {
370 return;
371 }
372
373 if (banner == FALSE) {
374 log_printf(dgettext(TEXT_DOMAIN,
375 " Bus Max\n"
376 " IO Port Bus Freq Bus Dev,\n"
377 "Brd Type ID Side Slot MHz Freq Func State "
378 "Name "));
379 #ifdef DEBUG
380 log_printf(dgettext(TEXT_DOMAIN,
381 "Model Notes\n"));
382 #else
383 log_printf(dgettext(TEXT_DOMAIN, "Model\n"));
384 #endif
385 /* ---------Node Brd IO Port Bus Slot Bus Max Dev Stat */
386 log_printf(dgettext(TEXT_DOMAIN,
387 "---- ---- ---- ---- ---- ---- ---- ---- ----- "
388 "-------------------------------- "
389 #ifdef DEBUG
390 "---------------------- "
391 #endif
392 "----------------------\n"));
393 banner = TRUE;
394 }
395
396 for (p = list; p != NULL; p = p -> next) {
397 log_printf(dgettext(TEXT_DOMAIN, "I/O "));
398 log_printf(dgettext(TEXT_DOMAIN, "%-4s "), p->bus_type);
399 log_printf(dgettext(TEXT_DOMAIN, "%-3d "),
400 p->schizo_portid);
401 log_printf(dgettext(TEXT_DOMAIN, "%c "), p->pci_bus);
402 log_printf(dgettext(TEXT_DOMAIN, "%-1s "), p->slot_str);
403 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), p->freq);
404 switch (p->pci_bus) {
405 case 'A':
406 log_printf(dgettext(TEXT_DOMAIN, " 66 "));
407 break;
408 case 'B':
409 log_printf(dgettext(TEXT_DOMAIN, " 33 "));
410 break;
411 default:
412 log_printf(dgettext(TEXT_DOMAIN, " - "));
413 break;
414 }
415
416 log_printf(dgettext(TEXT_DOMAIN, "%-1d,%-1d "),
417 p->dev_no, p->func_no);
418 log_printf(dgettext(TEXT_DOMAIN, "%-5s "), p->status);
419 log_printf(dgettext(TEXT_DOMAIN, "%-32.32s"), p->name);
420 if (strlen(p->name) > 32)
421 log_printf(dgettext(TEXT_DOMAIN, "+ "));
422 else
423 log_printf(dgettext(TEXT_DOMAIN, " "));
424 log_printf(dgettext(TEXT_DOMAIN, "%-22.22s"), p->model);
425 if (strlen(p->model) > 22)
426 log_printf(dgettext(TEXT_DOMAIN, "+"));
427 #ifdef DEBUG
428 log_printf("%s ", p->notes);
429 #endif
430 log_printf("\n");
431 }
432 }
433
434 /*
435 * display_ffb
436 *
437 * There are no FFB's on a Littleneck, however in the generic library,
438 * the display_ffb() function is implemented so we have to define an
439 * empty function here.
440 */
441 /*ARGSUSED0*/
442 void
display_ffb(Board_node * board,int table)443 display_ffb(Board_node *board, int table)
444 {}
445
446
447 /*
448 * local functions
449 */
450
451 /*
452 * disp_fail_parts
453 *
454 * Display the failed parts in the system. This function looks for
455 * the status property in all PROM nodes. On systems where
456 * the PROM does not support passing diagnostic information
457 * through the device tree, this routine will be silent.
458 */
459 int
disp_fail_parts(Sys_tree * tree)460 disp_fail_parts(Sys_tree *tree)
461 {
462 int exit_code = 0;
463 int system_failed = 0;
464 Board_node *bnode = tree->bd_list;
465 Prom_node *pnode;
466
467 /* go through all of the boards looking for failed units. */
468 while (bnode != NULL) {
469 /* find failed chips */
470 pnode = find_failed_node(bnode->nodes);
471 if ((pnode != NULL) && !system_failed) {
472 system_failed = 1;
473 exit_code = 1;
474 if (print_flag == 0) {
475 return (exit_code);
476 }
477 log_printf("\n");
478 log_printf(dgettext(TEXT_DOMAIN, "Failed Field "
479 "Replaceable Units (FRU) in System:\n"));
480 log_printf("=========================="
481 "====================\n");
482 }
483 while (pnode != NULL) {
484 void *value;
485 char *name; /* node name string */
486 char *type; /* node type string */
487 char *board_type = NULL;
488
489 value = get_prop_val(find_prop(pnode, "status"));
490 name = get_node_name(pnode);
491
492 /* sanity check of data retrieved from PROM */
493 if ((value == NULL) || (name == NULL)) {
494 pnode = next_failed_node(pnode);
495 continue;
496 }
497
498 /* Find the board type of this board */
499 if (bnode->board_type == CPU_BOARD) {
500 board_type = "CPU";
501 } else {
502 board_type = "IO";
503 }
504
505 log_printf(dgettext(TEXT_DOMAIN, "%s unavailable "
506 "on %s Board #%d\n"), name, board_type,
507 bnode->board_num);
508
509 log_printf(dgettext(TEXT_DOMAIN,
510 "\tPROM fault string: %s\n"), value);
511
512 log_printf(dgettext(TEXT_DOMAIN,
513 "\tFailed Field Replaceable Unit is "));
514
515 /*
516 * Determine whether FRU is CPU module, system
517 * board, or SBus card.
518 */
519 if ((name != NULL) && (strstr(name, "sbus"))) {
520
521 log_printf(dgettext(TEXT_DOMAIN,
522 "SBus Card %d\n"),
523 get_sbus_slot(pnode));
524
525 } else if (((name = get_node_name(pnode->parent)) !=
526 NULL) && (strstr(name, "pci"))) {
527
528 log_printf(dgettext(TEXT_DOMAIN,
529 "PCI Card %d"),
530 get_pci_device(pnode));
531
532 } else if (((type = get_node_type(pnode)) != NULL) &&
533 (strstr(type, "cpu"))) {
534
535 log_printf(dgettext(TEXT_DOMAIN, "UltraSPARC "
536 "module Board %d Module %d\n"), 0,
537 get_id(pnode));
538
539 } else {
540 log_printf(dgettext(TEXT_DOMAIN,
541 "%s board %d\n"), board_type,
542 bnode->board_num);
543 }
544 pnode = next_failed_node(pnode);
545 }
546 bnode = bnode->next;
547 }
548
549 if (!system_failed) {
550 log_printf(dgettext(TEXT_DOMAIN,
551 "No failures found in System\n"));
552 log_printf("===========================\n\n");
553 return (0);
554 } else {
555 return (1);
556 }
557 }
558
559
560 /*
561 * disp_envc_status
562 *
563 * This routine displays the environmental status passed up from
564 * device drivers via the envlibobj.so library.
565 * This is a Littleneck specific environmental information display routine.
566 */
567 static int
disp_envc_status(void)568 disp_envc_status(void)
569 {
570 int err;
571 char *system = "SYSTEM";
572 picl_nodehdl_t system_node, root;
573
574 log_printf("\n");
575 log_printf(dgettext(TEXT_DOMAIN, "========================="
576 " Environmental Status =========================\n\n"));
577
578 err = picl_initialize();
579 if (err != PICL_SUCCESS) {
580 log_printf(dgettext(TEXT_DOMAIN,
581 "Cannot print environmental information\n"
582 "picl_initialize failed\n"
583 "%s\n"), picl_strerror(err));
584 }
585
586 if (err == PICL_SUCCESS) {
587 err = picl_get_root(&root);
588 err = find_child_device(root, system, &system_node);
589 if (err != PICL_SUCCESS) {
590 log_printf(dgettext(TEXT_DOMAIN,
591 "Cannot print environmental information\n"
592 "find_child_device for the SYSTEM node "
593 "failed\n"
594 "%s\n"), picl_strerror(err));
595 }
596
597 if ((err = lneck_env_print_temps(system_node)) !=
598 PICL_SUCCESS) {
599 log_printf(dgettext(TEXT_DOMAIN,
600 "Temperature Checking failed: %s\n"),
601 picl_strerror(err));
602 }
603 if ((err = lneck_env_print_keyswitch(system_node)) !=
604 PICL_SUCCESS) {
605 log_printf(dgettext(TEXT_DOMAIN,
606 "Keyswitch information checking failed: %s\n"),
607 picl_strerror(err));
608 }
609 if ((err = lneck_env_print_FSP_LEDS(system_node)) !=
610 PICL_SUCCESS) {
611 log_printf(dgettext(TEXT_DOMAIN,
612 "FSP LED information checking failed: %s\n"),
613 picl_strerror(err));
614 }
615 if ((err = lneck_env_print_disk(system_node)) !=
616 PICL_SUCCESS) {
617 log_printf(dgettext(TEXT_DOMAIN,
618 "Disk information checking failed: %s\n"),
619 picl_strerror(err));
620 }
621 if ((err = lneck_env_print_fans(system_node)) !=
622 PICL_SUCCESS) {
623 log_printf(dgettext(TEXT_DOMAIN,
624 "Fan information checking failed: %s\n"),
625 picl_strerror(err));
626 }
627 if ((err = lneck_env_print_ps(system_node)) !=
628 PICL_SUCCESS) {
629 log_printf(dgettext(TEXT_DOMAIN,
630 "Power Supply information checking failed: "
631 "%s\n"), picl_strerror(err));
632 } else if (ps_failure != 0)
633 err = PICL_FAILURE;
634 }
635 return (err);
636 }
637
638 int
lneck_env_print_ps(picl_nodehdl_t system_node)639 lneck_env_print_ps(picl_nodehdl_t system_node)
640 {
641 int i, err = 0;
642 int32_t number;
643 picl_nodehdl_t *ps;
644 picl_nodehdl_t ps_fail[2], ps_type[2];
645 char name[PICL_PROPNAMELEN_MAX];
646 boolean_t type;
647 char fault_state[PICL_PROPNAMELEN_MAX];
648
649 log_printf(dgettext(TEXT_DOMAIN,
650 "Power Supplies:\n"
651 "---------------\n"
652 "Supply Status PS Type\n"
653 "------ ------ ---------------\n"));
654 err = fill_device_array_from_id(system_node, "PSVC_PS", &number,
655 &ps);
656 if (err != PICL_SUCCESS) {
657 return (err);
658 }
659
660 for (i = 0; i < LNECK_MAX_PS; i++) {
661 err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name,
662 PICL_PROPNAMELEN_MAX);
663 if (err == PICL_SUCCESS) {
664 log_printf(dgettext(TEXT_DOMAIN, "%6-s"), name);
665 } else continue;
666
667 err = picl_get_propval_by_name(ps[i], "FaultInformation",
668 fault_state, PICL_PROPNAMELEN_MAX);
669 if (err == PICL_SUCCESS) {
670 if ((strlen(fault_state) == 0) ||
671 (strcmp(fault_state, "NO_FAULT") == 0)) {
672 strcpy(fault_state, "OK");
673 } else
674 /*
675 * Bump up count if fault_state !OK
676 */
677 ps_failure++;
678
679 log_printf(dgettext(TEXT_DOMAIN, " [%-6s] "),
680 fault_state);
681 } else {
682 return (err);
683 }
684
685 err = fill_device_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR",
686 &ps_fail[i]);
687 if (err != PICL_SUCCESS) {
688 return (err);
689 }
690
691 err = fill_device_from_id(ps[i], "PSVC_DEV_TYPE_SENSOR",
692 &ps_type[i]);
693 if (err != PICL_SUCCESS) {
694 return (err);
695 }
696 err = picl_get_propval_by_name(ps_type[i], "Gpio-value", &type,
697 sizeof (boolean_t));
698 if (err == PICL_SUCCESS) {
699 log_printf(dgettext(TEXT_DOMAIN, " [%13s]"),
700 type == 0 ? "Quahog/Razor" : "Sun-Fire-280R");
701 if (type == 0) {
702 log_printf(dgettext(TEXT_DOMAIN,
703 "WARNING: PS is of the wrong type\n"));
704 } else log_printf("\n");
705 } else {
706 return (err);
707 }
708
709 }
710
711 log_printf(dgettext(TEXT_DOMAIN,
712 "\n"
713 "================================="
714 "\n"
715 "\n"));
716
717 /*
718 * Do not display an error message just because PS1 is
719 * not present.
720 */
721 if (err == PICL_INVALIDHANDLE) {
722 err = PICL_SUCCESS;
723 }
724
725 return (err);
726 }
727
728 int
lneck_env_print_fans(picl_nodehdl_t system_node)729 lneck_env_print_fans(picl_nodehdl_t system_node) {
730 int i, err = 0;
731 int32_t number;
732 picl_nodehdl_t *fans;
733 picl_nodehdl_t fan_fault[1];
734 char fault_state[PICL_PROPNAMELEN_MAX];
735 char name[PICL_PROPNAMELEN_MAX];
736
737 err = fill_device_array_from_id(system_node, "PSVC_FAN", &number,
738 &fans);
739 if (err != PICL_SUCCESS) {
740 return (err);
741 }
742
743 log_printf(dgettext(TEXT_DOMAIN,
744 "\n"
745 "=================================\n"
746 "\n"
747 "Fan Bank :\n"
748 "----------\n"
749 "\n"
750 "Bank Status\n"
751 "---- -------\n"));
752
753 for (i = 0; i < LNECK_MAX_FANS; i++) {
754 err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, name,
755 PICL_PROPNAMELEN_MAX);
756 if (err == PICL_SUCCESS) {
757 log_printf(dgettext(TEXT_DOMAIN, "%16-s"), name);
758 } else continue;
759
760 err = fill_device_from_id(fans[i], "PSVC_DEV_FAULT_SENSOR",
761 &fan_fault[i]);
762 if (err != PICL_SUCCESS) {
763 return (err);
764 }
765
766 err = picl_get_propval_by_name(fans[i], "FaultInformation",
767 &fault_state, PICL_PROPNAMELEN_MAX);
768
769 if (err == PICL_SUCCESS) {
770 log_printf(dgettext(TEXT_DOMAIN, " [%3s]\n"),
771 fault_state);
772 } else {
773 return (err);
774 }
775 }
776 log_printf(dgettext(TEXT_DOMAIN,
777 "\n"
778 "================================="
779 "\n"
780 "\n"));
781
782 return (err);
783 }
784
785 int
lneck_env_print_disk(picl_nodehdl_t system_node)786 lneck_env_print_disk(picl_nodehdl_t system_node) {
787 int i, err = 0;
788 int32_t number;
789 picl_nodehdl_t *disks;
790 char fault_state[PICL_PROPNAMELEN_MAX];
791 char name[PICL_PROPNAMELEN_MAX];
792
793 err = fill_device_array_from_id(system_node, "PSVC_DISK", &number,
794 &disks);
795 if (err != PICL_SUCCESS) {
796 return (err);
797 }
798
799 log_printf(dgettext(TEXT_DOMAIN,
800 "Disk Status:\n"
801 " Presence Fault Value\n"
802 " -------- -----------\n"));
803
804 for (i = 0; i < LNECK_MAX_DISKS; i++) {
805 err = picl_get_propval_by_name(disks[i], PICL_PROP_NAME, name,
806 PICL_PROPNAMELEN_MAX);
807 switch (err) {
808 case PICL_SUCCESS:
809 log_printf(dgettext(TEXT_DOMAIN,
810 "DISK %2d: [PRESENT]"), i);
811 break;
812 case PICL_INVALIDHANDLE:
813 log_printf(dgettext(TEXT_DOMAIN,
814 "DISK %2d: [EMPTY ]\n"), i);
815 continue;
816 default:
817 return (err);
818 }
819 err = picl_get_propval_by_name(disks[i], "FaultInformation",
820 &fault_state, PICL_PROPNAMELEN_MAX);
821 if (err == PICL_SUCCESS) {
822 log_printf(dgettext(TEXT_DOMAIN, " [%3s]"),
823 fault_state);
824 } else {
825 if (err != PICL_INVALIDHANDLE)
826 return (err);
827 }
828 log_printf("\n");
829 }
830
831 if (err == PICL_INVALIDHANDLE) {
832 err = PICL_SUCCESS;
833 }
834
835 return (err);
836 }
837
838 int
lneck_env_print_FSP_LEDS(picl_nodehdl_t system_node)839 lneck_env_print_FSP_LEDS(picl_nodehdl_t system_node) {
840 int err;
841 int32_t number;
842 picl_nodehdl_t *fsp_led;
843 char fault_state[PICL_PROPNAMELEN_MAX];
844
845 err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number,
846 &fsp_led);
847 if (err != PICL_SUCCESS) {
848 return (err);
849 }
850
851 log_printf(dgettext(TEXT_DOMAIN,
852 "System LED Status: POWER GEN FAULT\n"
853 " [ ON]"));
854 err = picl_get_propval_by_name(fsp_led[0], "State", &fault_state,
855 PICL_PROPNAMELEN_MAX);
856 if (err == PICL_SUCCESS) {
857 log_printf(" [%3s]", fault_state);
858 } else {
859 return (err);
860 }
861
862 log_printf(dgettext(TEXT_DOMAIN,
863 "\n"
864 "\n"
865 "================================="
866 "\n"
867 "\n"));
868
869 return (err);
870 }
871
872 int
lneck_env_print_keyswitch(picl_nodehdl_t system_node)873 lneck_env_print_keyswitch(picl_nodehdl_t system_node) {
874 int err = 0;
875 picl_nodehdl_t *keyswitch;
876 int32_t number;
877 char ks_pos[PICL_PROPNAMELEN_MAX];
878
879 err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number,
880 &keyswitch);
881 if (err != PICL_SUCCESS) {
882 return (err);
883 }
884 err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos,
885 PICL_PROPNAMELEN_MAX);
886 if (err != PICL_SUCCESS) {
887 return (err);
888 }
889
890 log_printf(dgettext(TEXT_DOMAIN,
891 "Front Status Panel:\n"
892 "-------------------\n"
893 "Keyswitch position: %s\n"), ks_pos);
894 log_printf("\n");
895
896 return (err);
897 }
898
899 int
lneck_env_print_temps(picl_nodehdl_t system_node)900 lneck_env_print_temps(picl_nodehdl_t system_node) {
901 int i, err = 0;
902 picl_nodehdl_t *system_ts_nodes;
903 int32_t temp, number;
904
905 err = fill_device_array_from_id(system_node, "PSVC_TS", &number,
906 &system_ts_nodes);
907 if (err != PICL_SUCCESS) {
908 return (err);
909 }
910
911
912 log_printf(dgettext(TEXT_DOMAIN,
913 "System Temperatures (Celsius):\n"
914 "------------------------------\n"
915 "cpu0 1 \n"
916 "---------\n"));
917
918 for (i = 0; i < 2; i++) {
919 err = picl_get_propval_by_name(system_ts_nodes[i],
920 "Temperature", &temp, sizeof (temp));
921 if (err == PICL_SUCCESS) {
922 log_printf(dgettext(TEXT_DOMAIN, " %02d"), temp);
923 } else {
924 if (err == PICL_INVALIDHANDLE) {
925 err = PICL_SUCCESS;
926 log_printf(dgettext(TEXT_DOMAIN, " xx"));
927 } else {
928 return (err);
929 }
930 }
931 }
932
933 log_printf("\n");
934 log_printf("\n");
935 log_printf(dgettext(TEXT_DOMAIN,
936 "=================================\n"));
937 log_printf("\n");
938
939 return (err);
940 }
941
942 static void
lneck_display_hw_revisions(Prom_node * root,Board_node * bdlist)943 lneck_display_hw_revisions(Prom_node *root, Board_node *bdlist)
944 {
945 Prom_node *pnode;
946 char *value;
947
948 log_printf(dgettext(TEXT_DOMAIN, "\n"
949 "========================= HW Revisions "
950 "=======================================\n\n"));
951
952 log_printf(dgettext(TEXT_DOMAIN,
953 "System PROM revisions:\n"
954 "----------------------\n"));
955
956 pnode = dev_find_node(root, "openprom");
957 if (pnode != NULL) {
958 value = (char *)get_prop_val(find_prop(pnode, "version"));
959 log_printf(value);
960 }
961
962 log_printf(dgettext(TEXT_DOMAIN, "\n\n"
963 "IO ASIC revisions:\n"
964 "------------------\n"
965 " Port\n"
966 "Model ID Status Version\n"
967 "-------- ---- ------ -------\n"));
968
969 display_schizo_revisions(bdlist);
970 }
971
972 static void
display_schizo_revisions(Board_node * bdlist)973 display_schizo_revisions(Board_node *bdlist)
974 {
975 Prom_node *pnode;
976 int *int_val;
977 int portid;
978 int prev_portid = -1;
979 char *status_a = NULL;
980 char *status_b = NULL;
981 int revision;
982 #ifdef DEBUG
983 uint32_t a_notes, b_notes;
984 #endif
985 int pci_bus;
986 Board_node *bnode;
987 bnode = bdlist;
988
989 while (bnode != NULL) {
990 /*
991 * search this board node for all Schizos
992 */
993
994 for (pnode = dev_find_node_by_compat(bnode->nodes,
995 SCHIZO_COMPAT_PROP); pnode != NULL;
996 pnode = dev_next_node_by_compat(pnode,
997 SCHIZO_COMPAT_PROP)) {
998
999 /*
1000 * get the reg property to determine
1001 * whether we are looking at side A or B
1002 */
1003
1004 int_val = (int *)get_prop_val
1005 (find_prop(pnode, "reg"));
1006 if (int_val != NULL) {
1007 int_val ++; /* second integer in array */
1008 pci_bus = ((*int_val) & 0x7f0000);
1009 }
1010
1011 /* get portid */
1012 int_val = (int *)get_prop_val
1013 (find_prop(pnode, "portid"));
1014 if (int_val == NULL)
1015 continue;
1016
1017 portid = *int_val;
1018
1019 /*
1020 * If this is a new portid and it is PCI bus B,
1021 * we skip onto the PCI bus A.
1022 */
1023 if ((portid != prev_portid) && (pci_bus == 0x700000)) {
1024 prev_portid = portid;
1025 /* status */
1026 status_b = (char *)get_prop_val
1027 (find_prop(pnode, "status"));
1028 #ifdef DEBUG
1029 b_notes = pci_bus;
1030 #endif
1031 continue; /* skip to the next schizo */
1032 }
1033
1034 /*
1035 * This must be side A of the same Schizo.
1036 * Gather all its props and display them.
1037 */
1038 #ifdef DEBUG
1039 a_notes = pci_bus;
1040 #endif
1041
1042 prev_portid = portid;
1043
1044 int_val = (int *)get_prop_val
1045 (find_prop(pnode, "version#"));
1046 if (int_val != NULL)
1047 revision = *int_val;
1048 else
1049 revision = -1;
1050
1051 status_a = (char *)get_prop_val(find_prop
1052 (pnode, "status"));
1053
1054 log_printf(dgettext(TEXT_DOMAIN, "Schizo "));
1055
1056 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0);
1057
1058
1059 log_printf((status_a == NULL && status_b == NULL) ?
1060 dgettext(TEXT_DOMAIN, " ok ") :
1061 dgettext(TEXT_DOMAIN, " fail "));
1062
1063 log_printf(dgettext(TEXT_DOMAIN, " %4d "),
1064 revision);
1065 #ifdef DEBUG
1066 log_printf(" 0x%x 0x%x", a_notes, b_notes);
1067 #endif
1068 log_printf("\n");
1069 }
1070 bnode = bnode->next;
1071 }
1072 }
1073