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 *
28 * Cherrystone platform-specific functions
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
52 #include <picl.h>
53
54 #include <sys/cheetahregs.h>
55 #include <sys/cherrystone.h>
56 #include "workfile.c"
57
58 #define SCHIZO_COMPAT_PROP "pci108e,8001"
59
60 #define MULTIPLE_BITS_SET(x) ((x)&((x)-1))
61
62 #define MAX_PS 2
63 #define MAX_PS_SENSORS 3
64 #define MAX_DISKS 2
65 #define MAX_FANS 5
66 #define NUM_PCI_SLOTS 5
67
68 /*
69 * these functions will overlay the symbol table of libprtdiag
70 * at runtime (workgroup server systems only)
71 */
72 void display_cpu_devices(Sys_tree *tree);
73 void display_pci(Board_node *board);
74 void display_io_cards(struct io_card *list);
75 void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
76 struct system_kstat_data *kstats);
77 void display_ffb(Board_node *board, int table);
78 void display_memoryconf(Sys_tree *tree, struct grp_info *grps);
79
80 /* local functions */
81 static void disp_envc_status(void);
82 static int print_temps(picl_nodehdl_t);
83 static int print_keyswitch(picl_nodehdl_t);
84 static int print_FSP_LEDS(picl_nodehdl_t);
85 static int print_disk(picl_nodehdl_t);
86 static int print_fans(picl_nodehdl_t);
87 static int print_ps(picl_nodehdl_t);
88
89 static void display_hw_revisions(Prom_node *root,
90 Board_node *bnode);
91 static void display_schizo_revisions(Board_node *bdlist);
92
93
94 void
display_cpu_devices(Sys_tree * tree)95 display_cpu_devices(Sys_tree *tree)
96 {
97 Board_node *bnode;
98
99 log_printf(dgettext(TEXT_DOMAIN,
100 "\n========================= CPUs "
101 "===============================================\n\n"
102 " Run E$ CPU CPU \n"
103 "Brd CPU MHz MB Impl. Mask \n"
104 "--- ----- ---- ---- ------- ---- \n"));
105
106 bnode = tree->bd_list;
107 while (bnode != NULL) {
108 display_cpus(bnode);
109 bnode = bnode->next;
110 }
111
112 log_printf("\n");
113 }
114 void
display_cpus(Board_node * board)115 display_cpus(Board_node *board)
116 {
117 Prom_node *cpu;
118 uint_t freq;
119 int ecache_size;
120 int *l3_shares;
121 int *mid;
122 int *impl;
123 int *mask;
124 int *coreid;
125 char fru_prev = 'X'; /* Valid frus are 'A','B' */
126 int mid_prev;
127 int ecache_size_prev = 0;
128 char fru_name;
129
130 /*
131 * display the CPUs' operating frequency, cache size, impl. field
132 * and mask revision.
133 */
134
135 for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
136 cpu = dev_next_type(cpu, "cpu")) {
137
138 mid = (int *)get_prop_val(find_prop(cpu, "portid"));
139 if (mid == NULL)
140 mid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
141 freq = HZ_TO_MHZ(get_cpu_freq(cpu));
142 ecache_size = get_ecache_size(cpu);
143 impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
144 mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
145 l3_shares =
146 (int *)get_prop_val(find_prop(cpu, "l3-cache-sharing"));
147
148 /* Do not display a failed CPU node */
149 if ((impl == NULL) || (freq == 0) || (node_failed(cpu)))
150 continue;
151
152 fru_name = CHERRYSTONE_GETSLOT_LABEL(*mid);
153 if (CPU_IMPL_IS_CMP(*impl)) {
154 coreid = (int *)get_prop_val(find_prop(cpu, "reg"));
155 if (coreid == NULL) {
156 continue;
157 }
158 if ((fru_prev == 'X') ||
159 ((fru_prev != 'X') &&
160 (fru_name != fru_prev))) {
161 fru_prev = fru_name;
162 mid_prev = *mid;
163 ecache_size_prev = ecache_size;
164 continue;
165 } else {
166 /*
167 * Some CMP chips have a split E$,
168 * so the size for both cores is added
169 * together to get the total size for
170 * the chip.
171 *
172 * Still, other CMP chips have E$ (L3)
173 * which is logically shared, so the
174 * total size is equal to the core size.
175 */
176 if ((l3_shares == NULL) ||
177 ((l3_shares != NULL) &&
178 MULTIPLE_BITS_SET(*l3_shares))) {
179 ecache_size += ecache_size_prev;
180 }
181 ecache_size_prev = 0;
182 fru_prev = 'X';
183 }
184 }
185
186 log_printf(" %c", fru_name);
187
188 /* CPU Module ID */
189 if (CPU_IMPL_IS_CMP(*impl)) {
190 log_printf("%3d,%3d ", mid_prev, *mid, 0);
191 } else
192 log_printf(" %2d ", *mid);
193
194 /* Running frequency */
195 log_printf("%4u", freq);
196
197 if (ecache_size == 0)
198 log_printf(" N/A ");
199 else
200 log_printf(" %4.1f ",
201 (float)ecache_size / (float)(1<<20));
202 /* Implementation */
203 if (impl == NULL) {
204 log_printf(dgettext(TEXT_DOMAIN, " N/A "));
205 } else {
206 if (IS_CHEETAH(*impl))
207 log_printf(dgettext(TEXT_DOMAIN,
208 "US-III "));
209 else if (IS_CHEETAH_PLUS(*impl))
210 log_printf(dgettext(TEXT_DOMAIN,
211 "US-III+ "));
212 else if (IS_JAGUAR(*impl))
213 log_printf(dgettext(TEXT_DOMAIN,
214 "US-IV "));
215 else if (IS_PANTHER(*impl))
216 log_printf(dgettext(TEXT_DOMAIN,
217 "US-IV+ "));
218 else
219 log_printf("%-6x ", *impl);
220 }
221
222 /* CPU Mask */
223 if (mask == NULL) {
224 log_printf(dgettext(TEXT_DOMAIN, " N/A\n"));
225 } else {
226 log_printf(dgettext(TEXT_DOMAIN, " %d.%d\n"),
227 (*mask >> 4) & 0xf, *mask & 0xf);
228 }
229 }
230 }
231
232 /*ARGSUSED0*/
233 void
display_memoryconf(Sys_tree * tree,struct grp_info * grps)234 display_memoryconf(Sys_tree *tree, struct grp_info *grps)
235 {
236 Board_node *bnode = tree->bd_list;
237
238 log_printf(dgettext(TEXT_DOMAIN,
239 "========================= Memory Configuration"
240 " ===============================\n\n"
241 " Logical Logical Logical\n"
242 " MC Bank Bank Bank DIMM "
243 "Interleave Interleaved\n"
244 "Brd ID num size Status Size "
245 "Factor with\n"
246 "--- --- ---- ------ ----------- ------ "
247 "---------- -----------"));
248
249 while (bnode != NULL) {
250 if (get_us3_mem_regs(bnode)) {
251 log_printf(dgettext(TEXT_DOMAIN,
252 "\nFailed to get memory information.\n"));
253 return;
254 }
255 bnode = bnode->next;
256 }
257
258 /* Display what we have found */
259 display_us3_banks();
260 }
261
262 /*ARGSUSED3*/
263 void
display_diaginfo(int flag,Prom_node * root,Sys_tree * tree,struct system_kstat_data * kstats)264 display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
265 struct system_kstat_data *kstats)
266 {
267 /*
268 * Now display the last powerfail time and the fatal hardware
269 * reset information. We do this under a couple of conditions.
270 * First if the user asks for it. The second is if the user
271 * told us to do logging, and we found a system failure.
272 */
273
274 if (flag) {
275 /*
276 * display time of latest powerfail. Not all systems
277 * have this capability. For those that do not, this
278 * is just a no-op.
279 */
280 disp_powerfail(root);
281
282 disp_envc_status();
283
284 display_hw_revisions(root, tree->bd_list);
285 }
286 return;
287
288 }
289
290 /*
291 * display_pci
292 * Display all the PCI IO cards on this board.
293 */
294 void
display_pci(Board_node * board)295 display_pci(Board_node *board)
296 {
297 struct io_card *card_list = NULL;
298 struct io_card card;
299 void *value;
300 Prom_node *pci;
301 Prom_node *card_node;
302 static int banner = FALSE;
303
304 char *slot_name_arr[NUM_PCI_SLOTS];
305 int i;
306
307 if (board == NULL)
308 return;
309
310 (void) memset(&card, 0, sizeof (struct io_card));
311 /* Initialize all the common information */
312 card.display = TRUE;
313 card.board = board->board_num;
314
315 /*
316 * Search for each pci instance, then find/display all nodes under
317 * each instance node found.
318 */
319 for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP);
320 pci != NULL;
321 pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) {
322 (void) snprintf(card.bus_type, MAXSTRLEN,
323 dgettext(TEXT_DOMAIN, "PCI"));
324 /*
325 * Get slot-name properties from parent node and
326 * store them in an array.
327 */
328 value = (char *)get_prop_val(
329 find_prop(pci, "slot-names"));
330
331 if (value != NULL) {
332 /* array starts after first int */
333 slot_name_arr[0] = (char *)value + sizeof (int);
334 for (i = 1; i < NUM_PCI_SLOTS; i++) {
335 slot_name_arr[i] = (char *)slot_name_arr[i - 1]
336 + strlen(slot_name_arr[i - 1]) +1;
337 }
338 }
339 /*
340 * Search for Children of this node ie. Cards.
341 * Note: any of these cards can be a pci-bridge
342 * that itself has children. If we find a
343 * pci-bridge we need to handle it specially.
344 */
345 card_node = pci->child;
346 /* Generate the list of pci cards on pci instance: pci */
347 fill_pci_card_list(pci, card_node, &card, &card_list,
348 slot_name_arr);
349 } /* end-for */
350
351 if (!banner && card_list != NULL) {
352 log_printf(dgettext(TEXT_DOMAIN,
353 " Bus Max\n"
354 " IO Port Bus Freq Bus Dev,\n"
355 "Type ID Side Slot MHz Freq Func State "
356 "Name Model"
357 #ifdef DEBUG
358 " Notes"
359 #endif
360 "\n"
361 "---- ---- ---- ---- ---- ---- ---- ----- "
362 "-------------------------------- "
363 #ifdef DEBUG
364 "---------------------- "
365 #endif
366 "----------------------\n"));
367 banner = TRUE;
368 }
369
370 display_io_cards(card_list);
371 free_io_cards(card_list);
372 }
373
374 /*
375 * Print out all the io cards in the list. Also print the column
376 * headers if told to do so.
377 */
378 void
display_io_cards(struct io_card * list)379 display_io_cards(struct io_card *list)
380 {
381 struct io_card *p;
382
383 for (p = list; p != NULL; p = p -> next) {
384 log_printf(dgettext(TEXT_DOMAIN,
385 "%-4s %-3d %c %-1s %-3d"),
386 p->bus_type, p->schizo_portid, p->pci_bus,
387 p->slot_str, p->freq);
388
389 switch (p->pci_bus) {
390 case 'A':
391 log_printf(dgettext(TEXT_DOMAIN, " 66 "));
392 break;
393 case 'B':
394 log_printf(dgettext(TEXT_DOMAIN, " 33 "));
395 break;
396 default:
397 assert(0);
398 break;
399 }
400
401 log_printf(dgettext(TEXT_DOMAIN,
402 "%-1d,%-1d %-5s %-32.32s"),
403 p->dev_no, p->func_no, p->status, p->name);
404 if (strlen(p->name) > 32)
405 log_printf(dgettext(TEXT_DOMAIN, "+ "));
406 else
407 log_printf(dgettext(TEXT_DOMAIN, " "));
408 log_printf(dgettext(TEXT_DOMAIN, "%-22.22s"), p->model);
409 if (strlen(p->model) > 22)
410 log_printf(dgettext(TEXT_DOMAIN, "+"));
411 #ifdef DEBUG
412 log_printf("%s", p->notes);
413 #endif
414 log_printf("\n");
415 }
416 }
417
418 /*ARGSUSED*/
419 void
display_ffb(Board_node * board,int table)420 display_ffb(Board_node *board, int table)
421 {
422 /* NOP, since there are no FFB's on this platform. */
423 }
424
425
426 /*
427 * local functions
428 */
429
430
431 static void
disp_envc_status()432 disp_envc_status()
433 {
434 int err;
435 char *system = "SYSTEM";
436 picl_nodehdl_t system_node, root;
437
438 log_printf(dgettext(TEXT_DOMAIN,
439 "\n"
440 "========================= Environmental Status "
441 "=========================\n\n"));
442
443 err = picl_initialize();
444 if (err != PICL_SUCCESS) {
445 exit_code = PD_INTERNAL_FAILURE;
446 goto err_out;
447 }
448 err = picl_get_root(&root);
449 if (err != PICL_SUCCESS) {
450 exit_code = PD_INTERNAL_FAILURE;
451 goto err_out;
452 }
453 err = find_child_device(root, system, &system_node);
454 if (err != PICL_SUCCESS) {
455 exit_code = PD_INTERNAL_FAILURE;
456 goto err_out;
457 }
458
459 err = print_temps(system_node);
460 err |= print_keyswitch(system_node);
461 err |= print_FSP_LEDS(system_node);
462 err |= print_disk(system_node);
463 err |= print_fans(system_node);
464 err |= print_ps(system_node);
465
466 if (err != PICL_SUCCESS)
467 goto err_out;
468
469 return;
470
471 err_out:
472 log_printf(dgettext(TEXT_DOMAIN,
473 "\nEnvironmental reporting error: %s\n"),
474 picl_strerror(err));
475 }
476
477 static int
print_ps(picl_nodehdl_t system_node)478 print_ps(picl_nodehdl_t system_node)
479 {
480 int i, j, err = 0;
481 int32_t number;
482 picl_nodehdl_t *ps;
483 picl_nodehdl_t *ps_fail_sensor;
484 char name[PICL_PROPNAMELEN_MAX];
485 char fault_state[PICL_PROPNAMELEN_MAX];
486
487 log_printf(dgettext(TEXT_DOMAIN, "\n\n"
488 "Power Supplies:\n"
489 "---------------\n"
490 "\n"
491 "Supply Status Fault Fan Fail Temp Fail\n"
492 "------ ------------ -------- --------- ---------\n"));
493
494 err = fill_device_array_from_id(system_node, "PSVC_PS", &number, &ps);
495 if (err != PICL_SUCCESS) {
496 return (err);
497 }
498
499 for (i = 0; i < MAX_PS; i++) {
500 err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name,
501 PICL_PROPNAMELEN_MAX);
502 if (err != PICL_SUCCESS)
503 continue;
504
505 log_printf(dgettext(TEXT_DOMAIN, "%6-s"), name);
506 err = picl_get_propval_by_name(ps[i], "FaultInformation",
507 fault_state, PICL_PROPNAMELEN_MAX);
508 if (err != PICL_SUCCESS) {
509 free(ps);
510 return (err);
511 }
512 log_printf(dgettext(TEXT_DOMAIN, " [%-12s]"), fault_state);
513 if (strcmp(fault_state, "NO AC POWER") == 0) {
514 log_printf("\n");
515 continue;
516 }
517
518 err = fill_device_array_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR",
519 &number, &ps_fail_sensor);
520
521 if (err != PICL_SUCCESS) {
522 free(ps);
523 return (err);
524 }
525 log_printf(" ");
526 for (j = 0; j < MAX_PS_SENSORS; j++) {
527 err = picl_get_propval_by_name(ps_fail_sensor[j],
528 "State", fault_state, PICL_PROPNAMELEN_MAX);
529 if (err != PICL_SUCCESS) {
530 if (err == PICL_FAILURE) {
531 break;
532 }
533 free(ps);
534 free(ps_fail_sensor);
535 return (err);
536 }
537 log_printf(dgettext(TEXT_DOMAIN, "%-10s"), fault_state);
538 }
539 log_printf("\n");
540 free(ps_fail_sensor);
541 }
542
543 log_printf(dgettext(TEXT_DOMAIN,
544 "\n=================================\n\n"));
545
546 free(ps);
547 return (PICL_SUCCESS);
548 }
549
550 static int
print_fans(picl_nodehdl_t system_node)551 print_fans(picl_nodehdl_t system_node)
552 {
553 int i, err;
554 int32_t number;
555 picl_nodehdl_t *fans;
556 picl_nodehdl_t phdl;
557 char prop[PICL_PROPNAMELEN_MAX];
558 char parent[PICL_PROPNAMELEN_MAX];
559 int32_t rpm;
560
561 err = fill_device_array_from_id(system_node, "PSVC_FAN", &number,
562 &fans);
563 if (err != PICL_SUCCESS) {
564 return (err);
565 }
566
567 log_printf(dgettext(TEXT_DOMAIN,
568 "\n=================================\n\n"
569 "Fan Status:\n"
570 "-----------\n\n"
571 "Fan Tray Fan RPM Status\n"
572 "----------- ---- ----- ----------\n"));
573
574 for (i = 0; i < MAX_FANS; i++) {
575 err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, prop,
576 PICL_PROPNAMELEN_MAX);
577 if (err != PICL_SUCCESS)
578 continue;
579
580 err = fill_device_from_id(fans[i], "PSVC_PARENT", &phdl);
581 if (err != PICL_SUCCESS)
582 continue;
583 err = picl_get_propval_by_name(phdl, PICL_PROP_NAME, parent,
584 PICL_PROPNAMELEN_MAX);
585 if (err != PICL_SUCCESS)
586 continue;
587
588 log_printf(dgettext(TEXT_DOMAIN, "%-16s"), parent);
589
590
591 log_printf(dgettext(TEXT_DOMAIN, "%-16s"), prop);
592
593 err = picl_get_propval_by_name(fans[i], "Fan-speed",
594 &rpm, sizeof (rpm));
595 if (err != PICL_SUCCESS) {
596 free(fans);
597 return (err);
598 }
599 log_printf(dgettext(TEXT_DOMAIN, "%5d "), rpm);
600
601 err = picl_get_propval_by_name(fans[i], "FaultInformation",
602 prop, PICL_PROPNAMELEN_MAX);
603 if (err != PICL_SUCCESS) {
604 free(fans);
605 return (err);
606 }
607 log_printf(dgettext(TEXT_DOMAIN, " [%s]\n"), prop);
608 }
609 log_printf(dgettext(TEXT_DOMAIN,
610 "\n=================================\n\n"));
611 free(fans);
612 return (PICL_SUCCESS);
613 }
614
615 static int
print_disk(picl_nodehdl_t system_node)616 print_disk(picl_nodehdl_t system_node)
617 {
618 int i, err;
619 int32_t number;
620 picl_nodehdl_t *disks;
621 char state[PICL_PROPNAMELEN_MAX];
622
623 err = fill_device_array_from_id(system_node, "PSVC_DISK", &number,
624 &disks);
625 if (err != PICL_SUCCESS) {
626 return (err);
627 }
628
629 log_printf(dgettext(TEXT_DOMAIN,
630 "Disk Status:\n"
631 "------------\n"));
632 for (i = 0; i < MAX_DISKS; i++) {
633 err = picl_get_propval_by_name(disks[i], "FaultInformation",
634 state, PICL_PROPNAMELEN_MAX);
635
636 switch (err) {
637 case PICL_SUCCESS:
638 log_printf(dgettext(TEXT_DOMAIN,
639 "DISK %d: [%3s]\n"), i, state);
640 break;
641 case PICL_INVALIDHANDLE:
642 log_printf(dgettext(TEXT_DOMAIN,
643 "DISK %d: [ NOT PRESENT ]\n"), i);
644 break;
645 default:
646 free(disks);
647 return (err);
648 }
649 }
650 free(disks);
651 return (PICL_SUCCESS);
652 }
653
654 static int
print_FSP_LEDS(picl_nodehdl_t system_node)655 print_FSP_LEDS(picl_nodehdl_t system_node)
656 {
657 int err;
658 int32_t number;
659 picl_nodehdl_t *fsp_led;
660 char fault_state[PICL_PROPNAMELEN_MAX];
661 char locate_state[PICL_PROPNAMELEN_MAX];
662
663 err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number,
664 &fsp_led);
665 if (err != PICL_SUCCESS) {
666 return (err);
667 }
668
669 assert(number == 2);
670 err = picl_get_propval_by_name(fsp_led[0], "State", &fault_state,
671 PICL_PROPNAMELEN_MAX);
672 if (err != PICL_SUCCESS) {
673 free(fsp_led);
674 return (err);
675 }
676
677 if (strcmp(fault_state, PSVC_LED_ON) == 0)
678 exit_code = PD_SYSTEM_FAILURE;
679
680 err = picl_get_propval_by_name(fsp_led[1], "State", &locate_state,
681 PICL_PROPNAMELEN_MAX);
682 if (err != PICL_SUCCESS) {
683 free(fsp_led);
684 return (err);
685 }
686
687 log_printf(dgettext(TEXT_DOMAIN,
688 "System LED Status:\n\n"
689 " LOCATOR FAULT POWER\n"
690 " ------- ------- -------\n"
691 " [%3s] [%3s] [ ON]"),
692 locate_state, fault_state);
693
694 log_printf(dgettext(TEXT_DOMAIN,
695 "\n\n=================================\n\n"));
696 free(fsp_led);
697 return (err);
698 }
699
700 static int
print_keyswitch(picl_nodehdl_t system_node)701 print_keyswitch(picl_nodehdl_t system_node)
702 {
703 int err;
704 picl_nodehdl_t *keyswitch;
705 int32_t number;
706 char ks_pos[PICL_PROPNAMELEN_MAX];
707
708 err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number,
709 &keyswitch);
710 if (err != PICL_SUCCESS) {
711 return (err);
712 }
713 err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos,
714 PICL_PROPNAMELEN_MAX);
715 if (err != PICL_SUCCESS) {
716 free(keyswitch);
717 return (err);
718 }
719
720 log_printf(dgettext(TEXT_DOMAIN,
721 "Front Status Panel:\n"
722 "-------------------\n"
723 "Keyswitch position: %s\n\n"), ks_pos);
724 free(keyswitch);
725 return (err);
726 }
727
728 static int
print_temps(picl_nodehdl_t system_node)729 print_temps(picl_nodehdl_t system_node)
730 {
731 int i;
732 int err;
733 picl_nodehdl_t *system_ts_nodes;
734 int32_t temp;
735 int32_t number;
736 char label[PICL_PROPNAMELEN_MAX];
737 char state[PICL_PROPNAMELEN_MAX];
738 char *p;
739
740 err = fill_device_array_from_id(system_node, "PSVC_TS", &number,
741 &system_ts_nodes);
742 if (err != PICL_SUCCESS) {
743 return (err);
744 }
745
746 log_printf(dgettext(TEXT_DOMAIN,
747 "System Temperatures (Celsius):\n"
748 "-------------------------------\n"
749 "Device\t\tTemperature\tStatus\n"
750 "---------------------------------------\n"));
751
752 for (i = 0; i < number; i++) {
753 err = picl_get_propval_by_name(system_ts_nodes[i],
754 "State", state, sizeof (state));
755 if (err != PICL_SUCCESS) {
756 if (err == PICL_INVALIDHANDLE) {
757 (void) strcpy(state, "n/a");
758 } else {
759 free(system_ts_nodes);
760 return (err);
761 }
762 }
763 err = picl_get_propval_by_name(system_ts_nodes[i],
764 PICL_PROP_NAME, label, PICL_PROPNAMELEN_MAX);
765 if (err != PICL_SUCCESS) {
766 if (err == PICL_INVALIDHANDLE)
767 /* This FRU isn't present. Skip it. */
768 continue;
769 free(system_ts_nodes);
770 return (err);
771 }
772
773 /*
774 * The names in the tree are like "CPU0_DIE_TEMPERATURE_SENSOR".
775 * All we want to print is up to the first underscore.
776 */
777 p = strchr(label, '_');
778 if (p != NULL)
779 *p = '\0';
780
781 err = picl_get_propval_by_name(system_ts_nodes[i],
782 "Temperature", &temp, sizeof (temp));
783 if (err != PICL_SUCCESS) {
784 free(system_ts_nodes);
785 return (err);
786 }
787 log_printf("%s\t\t%3d\t\t%s\n", label, temp, state);
788 }
789
790 log_printf(dgettext(TEXT_DOMAIN,
791 "\n=================================\n\n"));
792
793 free(system_ts_nodes);
794 return (PICL_SUCCESS);
795 }
796
797 static void
display_hw_revisions(Prom_node * root,Board_node * bdlist)798 display_hw_revisions(Prom_node *root, Board_node *bdlist)
799 {
800 Prom_node *pnode;
801 char *value;
802
803 log_printf(dgettext(TEXT_DOMAIN, "\n"
804 "========================= HW Revisions "
805 "=======================================\n\n"));
806
807 log_printf(dgettext(TEXT_DOMAIN,
808 "System PROM revisions:\n"
809 "----------------------\n"));
810
811 pnode = dev_find_node(root, "openprom");
812 if (pnode != NULL) {
813 value = (char *)get_prop_val(find_prop(pnode, "version"));
814 log_printf(value);
815 }
816
817 log_printf(dgettext(TEXT_DOMAIN, "\n\n"
818 "IO ASIC revisions:\n"
819 "------------------\n"
820 " Port\n"
821 "Model ID Status Version\n"
822 "-------- ---- ------ -------\n"));
823
824 display_schizo_revisions(bdlist);
825 }
826
827
828 static void
display_schizo_revisions(Board_node * bdlist)829 display_schizo_revisions(Board_node *bdlist)
830 {
831 Prom_node *pnode;
832 int *int_val;
833 int portid;
834 int prev_portid = -1;
835 char *status_a = NULL;
836 char *status_b = NULL;
837 int revision;
838 #ifdef DEBUG
839 uint32_t a_notes, b_notes;
840 #endif
841 int pci_bus;
842 Board_node *bnode;
843 bnode = bdlist;
844
845 while (bnode != NULL) {
846 /*
847 * search this board node for all Schizos
848 */
849
850 for (pnode = dev_find_node_by_compat(bnode->nodes,
851 SCHIZO_COMPAT_PROP); pnode != NULL;
852 pnode = dev_next_node_by_compat(pnode,
853 SCHIZO_COMPAT_PROP)) {
854
855 /*
856 * get the reg property to determine
857 * whether we are looking at side A or B
858 */
859
860 int_val = (int *)get_prop_val
861 (find_prop(pnode, "reg"));
862 if (int_val != NULL) {
863 int_val ++; /* second integer in array */
864 pci_bus = ((*int_val) & 0x7f0000);
865 }
866
867 /* get portid */
868 int_val = (int *)get_prop_val
869 (find_prop(pnode, "portid"));
870 if (int_val == NULL)
871 continue;
872
873 portid = *int_val;
874
875 /*
876 * If this is a new portid and it is PCI bus B,
877 * we skip onto the PCI bus A.
878 */
879 if ((portid != prev_portid) && (pci_bus == 0x700000)) {
880 prev_portid = portid;
881 /* status */
882 status_b = (char *)get_prop_val
883 (find_prop(pnode, "status"));
884 #ifdef DEBUG
885 b_notes = pci_bus;
886 #endif
887 continue; /* skip to the next schizo */
888 }
889
890 /*
891 * This must be side A of the same Schizo.
892 * Gather all its props and display them.
893 */
894 #ifdef DEBUG
895 a_notes = pci_bus;
896 #endif
897
898 prev_portid = portid;
899
900 int_val = (int *)get_prop_val
901 (find_prop(pnode, "version#"));
902 if (int_val != NULL)
903 revision = *int_val;
904 else
905 revision = -1;
906
907 status_a = (char *)get_prop_val(find_prop
908 (pnode, "status"));
909
910 log_printf(dgettext(TEXT_DOMAIN, "Schizo "));
911
912 log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0);
913
914
915 log_printf((status_a == NULL && status_b == NULL) ?
916 dgettext(TEXT_DOMAIN, " ok ") :
917 dgettext(TEXT_DOMAIN, " fail "));
918
919 log_printf(dgettext(TEXT_DOMAIN, " %4d "),
920 revision);
921 #ifdef DEBUG
922 log_printf(" 0x%x 0x%x", a_notes, b_notes);
923 #endif
924 log_printf("\n");
925 }
926 bnode = bnode->next;
927 }
928 }
929