11708Sstevel /*
21708Sstevel * CDDL HEADER START
31708Sstevel *
41708Sstevel * The contents of this file are subject to the terms of the
55019Skd93003 * Common Development and Distribution License (the "License").
65019Skd93003 * You may not use this file except in compliance with the License.
71708Sstevel *
81708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel * or http://www.opensolaris.org/os/licensing.
101708Sstevel * See the License for the specific language governing permissions
111708Sstevel * and limitations under the License.
121708Sstevel *
131708Sstevel * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel *
191708Sstevel * CDDL HEADER END
201708Sstevel */
211708Sstevel /*
22*5889Szk194757 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
231708Sstevel * Use is subject to license terms.
241708Sstevel */
251708Sstevel
261708Sstevel /*
271708Sstevel *
281708Sstevel * Cherrystone platform-specific functions
291708Sstevel *
301708Sstevel */
311708Sstevel
321708Sstevel #pragma ident "%Z%%M% %I% %E% SMI"
331708Sstevel
341708Sstevel #include <stdio.h>
351708Sstevel #include <stdlib.h>
361708Sstevel #include <unistd.h>
371708Sstevel #include <kstat.h>
381708Sstevel #include <string.h>
391708Sstevel #include <assert.h>
401708Sstevel #include <libintl.h>
411708Sstevel #include <note.h>
421708Sstevel #include <syslog.h>
431708Sstevel
441708Sstevel #include <sys/openpromio.h>
451708Sstevel #include <sys/sysmacros.h>
461708Sstevel
471708Sstevel #include <pdevinfo.h>
481708Sstevel #include <display.h>
491708Sstevel #include <pdevinfo_sun4u.h>
501708Sstevel #include <display_sun4u.h>
511708Sstevel
521708Sstevel #include <picl.h>
531708Sstevel
541708Sstevel #include <sys/cheetahregs.h>
551708Sstevel #include <sys/cherrystone.h>
561708Sstevel #include "workfile.c"
571708Sstevel
581708Sstevel #define SCHIZO_COMPAT_PROP "pci108e,8001"
591708Sstevel
601708Sstevel #define MULTIPLE_BITS_SET(x) ((x)&((x)-1))
611708Sstevel
621708Sstevel #define MAX_PS 2
631708Sstevel #define MAX_PS_SENSORS 3
641708Sstevel #define MAX_DISKS 2
651708Sstevel #define MAX_FANS 5
661708Sstevel #define NUM_PCI_SLOTS 5
671708Sstevel
681708Sstevel /*
691708Sstevel * these functions will overlay the symbol table of libprtdiag
701708Sstevel * at runtime (workgroup server systems only)
711708Sstevel */
721708Sstevel void display_cpu_devices(Sys_tree *tree);
731708Sstevel void display_pci(Board_node *board);
741708Sstevel void display_io_cards(struct io_card *list);
751708Sstevel void display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
761708Sstevel struct system_kstat_data *kstats);
771708Sstevel void display_ffb(Board_node *board, int table);
781708Sstevel void display_memoryconf(Sys_tree *tree, struct grp_info *grps);
791708Sstevel
801708Sstevel /* local functions */
811708Sstevel static void disp_envc_status(void);
821708Sstevel static int print_temps(picl_nodehdl_t);
831708Sstevel static int print_keyswitch(picl_nodehdl_t);
841708Sstevel static int print_FSP_LEDS(picl_nodehdl_t);
851708Sstevel static int print_disk(picl_nodehdl_t);
861708Sstevel static int print_fans(picl_nodehdl_t);
871708Sstevel static int print_ps(picl_nodehdl_t);
881708Sstevel
891708Sstevel static void display_hw_revisions(Prom_node *root,
901708Sstevel Board_node *bnode);
911708Sstevel static void display_schizo_revisions(Board_node *bdlist);
921708Sstevel
931708Sstevel
941708Sstevel void
display_cpu_devices(Sys_tree * tree)951708Sstevel display_cpu_devices(Sys_tree *tree)
961708Sstevel {
971708Sstevel Board_node *bnode;
981708Sstevel
991708Sstevel log_printf(dgettext(TEXT_DOMAIN,
1005019Skd93003 "\n========================= CPUs "
1015019Skd93003 "===============================================\n\n"
1025019Skd93003 " Run E$ CPU CPU \n"
1035019Skd93003 "Brd CPU MHz MB Impl. Mask \n"
1045019Skd93003 "--- ----- ---- ---- ------- ---- \n"));
1051708Sstevel
1061708Sstevel bnode = tree->bd_list;
1071708Sstevel while (bnode != NULL) {
1081708Sstevel display_cpus(bnode);
1091708Sstevel bnode = bnode->next;
1101708Sstevel }
1111708Sstevel
1121708Sstevel log_printf("\n");
1131708Sstevel }
1141708Sstevel void
display_cpus(Board_node * board)1151708Sstevel display_cpus(Board_node *board)
1161708Sstevel {
1171708Sstevel Prom_node *cpu;
118*5889Szk194757 uint_t freq;
1191708Sstevel int ecache_size;
1201708Sstevel int *l3_shares;
1211708Sstevel int *mid;
1221708Sstevel int *impl;
1231708Sstevel int *mask;
1241708Sstevel int *coreid;
1251708Sstevel char fru_prev = 'X'; /* Valid frus are 'A','B' */
1261708Sstevel int mid_prev;
1271708Sstevel int ecache_size_prev = 0;
1281708Sstevel char fru_name;
1291708Sstevel
1301708Sstevel /*
1311708Sstevel * display the CPUs' operating frequency, cache size, impl. field
1321708Sstevel * and mask revision.
1331708Sstevel */
1341708Sstevel
1351708Sstevel for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL;
1361708Sstevel cpu = dev_next_type(cpu, "cpu")) {
1371708Sstevel
1381708Sstevel mid = (int *)get_prop_val(find_prop(cpu, "portid"));
1391708Sstevel if (mid == NULL)
1401708Sstevel mid = (int *)get_prop_val(find_prop(cpu, "cpuid"));
1411708Sstevel freq = HZ_TO_MHZ(get_cpu_freq(cpu));
1421708Sstevel ecache_size = get_ecache_size(cpu);
1431708Sstevel impl = (int *)get_prop_val(find_prop(cpu, "implementation#"));
1441708Sstevel mask = (int *)get_prop_val(find_prop(cpu, "mask#"));
1451708Sstevel l3_shares =
1465019Skd93003 (int *)get_prop_val(find_prop(cpu, "l3-cache-sharing"));
1471708Sstevel
1481708Sstevel /* Do not display a failed CPU node */
1491708Sstevel if ((impl == NULL) || (freq == 0) || (node_failed(cpu)))
1501708Sstevel continue;
1511708Sstevel
1521708Sstevel fru_name = CHERRYSTONE_GETSLOT_LABEL(*mid);
1531708Sstevel if (CPU_IMPL_IS_CMP(*impl)) {
1541708Sstevel coreid = (int *)get_prop_val(find_prop(cpu, "reg"));
1551708Sstevel if (coreid == NULL) {
1561708Sstevel continue;
1571708Sstevel }
1581708Sstevel if ((fru_prev == 'X') ||
1595019Skd93003 ((fru_prev != 'X') &&
1605019Skd93003 (fru_name != fru_prev))) {
1611708Sstevel fru_prev = fru_name;
1621708Sstevel mid_prev = *mid;
1631708Sstevel ecache_size_prev = ecache_size;
1641708Sstevel continue;
1651708Sstevel } else {
1661708Sstevel /*
1671708Sstevel * Some CMP chips have a split E$,
1681708Sstevel * so the size for both cores is added
1691708Sstevel * together to get the total size for
1701708Sstevel * the chip.
1711708Sstevel *
1721708Sstevel * Still, other CMP chips have E$ (L3)
1731708Sstevel * which is logically shared, so the
1741708Sstevel * total size is equal to the core size.
1751708Sstevel */
1761708Sstevel if ((l3_shares == NULL) ||
1775019Skd93003 ((l3_shares != NULL) &&
1785019Skd93003 MULTIPLE_BITS_SET(*l3_shares))) {
1791708Sstevel ecache_size += ecache_size_prev;
1801708Sstevel }
1811708Sstevel ecache_size_prev = 0;
1821708Sstevel fru_prev = 'X';
1831708Sstevel }
1841708Sstevel }
1851708Sstevel
1861708Sstevel log_printf(" %c", fru_name);
1871708Sstevel
1881708Sstevel /* CPU Module ID */
1891708Sstevel if (CPU_IMPL_IS_CMP(*impl)) {
1901708Sstevel log_printf("%3d,%3d ", mid_prev, *mid, 0);
1911708Sstevel } else
1921708Sstevel log_printf(" %2d ", *mid);
1931708Sstevel
1941708Sstevel /* Running frequency */
195*5889Szk194757 log_printf("%4u", freq);
1961708Sstevel
1971708Sstevel if (ecache_size == 0)
1981708Sstevel log_printf(" N/A ");
1991708Sstevel else
2001708Sstevel log_printf(" %4.1f ",
2015019Skd93003 (float)ecache_size / (float)(1<<20));
2021708Sstevel /* Implementation */
2031708Sstevel if (impl == NULL) {
2041708Sstevel log_printf(dgettext(TEXT_DOMAIN, " N/A "));
2051708Sstevel } else {
2061708Sstevel if (IS_CHEETAH(*impl))
2071708Sstevel log_printf(dgettext(TEXT_DOMAIN,
2085019Skd93003 "US-III "));
2091708Sstevel else if (IS_CHEETAH_PLUS(*impl))
2101708Sstevel log_printf(dgettext(TEXT_DOMAIN,
2115019Skd93003 "US-III+ "));
2121708Sstevel else if (IS_JAGUAR(*impl))
2131708Sstevel log_printf(dgettext(TEXT_DOMAIN,
2145019Skd93003 "US-IV "));
2151708Sstevel else if (IS_PANTHER(*impl))
2161708Sstevel log_printf(dgettext(TEXT_DOMAIN,
2175019Skd93003 "US-IV+ "));
2181708Sstevel else
2191708Sstevel log_printf("%-6x ", *impl);
2201708Sstevel }
2211708Sstevel
2221708Sstevel /* CPU Mask */
2231708Sstevel if (mask == NULL) {
2241708Sstevel log_printf(dgettext(TEXT_DOMAIN, " N/A\n"));
2251708Sstevel } else {
2261708Sstevel log_printf(dgettext(TEXT_DOMAIN, " %d.%d\n"),
2271708Sstevel (*mask >> 4) & 0xf, *mask & 0xf);
2281708Sstevel }
2291708Sstevel }
2301708Sstevel }
2311708Sstevel
2321708Sstevel /*ARGSUSED0*/
2331708Sstevel void
display_memoryconf(Sys_tree * tree,struct grp_info * grps)2341708Sstevel display_memoryconf(Sys_tree *tree, struct grp_info *grps)
2351708Sstevel {
2361708Sstevel Board_node *bnode = tree->bd_list;
2371708Sstevel
2381708Sstevel log_printf(dgettext(TEXT_DOMAIN,
2391708Sstevel "========================= Memory Configuration"
2401708Sstevel " ===============================\n\n"
2411708Sstevel " Logical Logical Logical\n"
2421708Sstevel " MC Bank Bank Bank DIMM "
2435019Skd93003 "Interleave Interleaved\n"
2441708Sstevel "Brd ID num size Status Size "
2455019Skd93003 "Factor with\n"
2461708Sstevel "--- --- ---- ------ ----------- ------ "
2475019Skd93003 "---------- -----------"));
2481708Sstevel
2491708Sstevel while (bnode != NULL) {
2501708Sstevel if (get_us3_mem_regs(bnode)) {
2511708Sstevel log_printf(dgettext(TEXT_DOMAIN,
2521708Sstevel "\nFailed to get memory information.\n"));
2531708Sstevel return;
2541708Sstevel }
2551708Sstevel bnode = bnode->next;
2561708Sstevel }
2571708Sstevel
2581708Sstevel /* Display what we have found */
2591708Sstevel display_us3_banks();
2601708Sstevel }
2611708Sstevel
2621708Sstevel /*ARGSUSED3*/
2631708Sstevel void
display_diaginfo(int flag,Prom_node * root,Sys_tree * tree,struct system_kstat_data * kstats)2641708Sstevel display_diaginfo(int flag, Prom_node *root, Sys_tree *tree,
2651708Sstevel struct system_kstat_data *kstats)
2661708Sstevel {
2671708Sstevel /*
2681708Sstevel * Now display the last powerfail time and the fatal hardware
2691708Sstevel * reset information. We do this under a couple of conditions.
2701708Sstevel * First if the user asks for it. The second is if the user
2711708Sstevel * told us to do logging, and we found a system failure.
2721708Sstevel */
2731708Sstevel
2741708Sstevel if (flag) {
2751708Sstevel /*
2761708Sstevel * display time of latest powerfail. Not all systems
2771708Sstevel * have this capability. For those that do not, this
2781708Sstevel * is just a no-op.
2791708Sstevel */
2801708Sstevel disp_powerfail(root);
2811708Sstevel
2821708Sstevel disp_envc_status();
2831708Sstevel
2841708Sstevel display_hw_revisions(root, tree->bd_list);
2851708Sstevel }
2861708Sstevel return;
2871708Sstevel
2881708Sstevel }
2891708Sstevel
2901708Sstevel /*
2911708Sstevel * display_pci
2921708Sstevel * Display all the PCI IO cards on this board.
2931708Sstevel */
2941708Sstevel void
display_pci(Board_node * board)2951708Sstevel display_pci(Board_node *board)
2961708Sstevel {
2971708Sstevel struct io_card *card_list = NULL;
2981708Sstevel struct io_card card;
2991708Sstevel void *value;
3001708Sstevel Prom_node *pci;
3011708Sstevel Prom_node *card_node;
3021708Sstevel static int banner = FALSE;
3031708Sstevel
3041708Sstevel char *slot_name_arr[NUM_PCI_SLOTS];
3051708Sstevel int i;
3061708Sstevel
3071708Sstevel if (board == NULL)
3081708Sstevel return;
3091708Sstevel
3105019Skd93003 (void) memset(&card, 0, sizeof (struct io_card));
3111708Sstevel /* Initialize all the common information */
3121708Sstevel card.display = TRUE;
3131708Sstevel card.board = board->board_num;
3141708Sstevel
3151708Sstevel /*
3161708Sstevel * Search for each pci instance, then find/display all nodes under
3171708Sstevel * each instance node found.
3181708Sstevel */
3191708Sstevel for (pci = dev_find_node_by_compat(board->nodes, SCHIZO_COMPAT_PROP);
3205019Skd93003 pci != NULL;
3215019Skd93003 pci = dev_next_node_by_compat(pci, SCHIZO_COMPAT_PROP)) {
3221708Sstevel (void) snprintf(card.bus_type, MAXSTRLEN,
3235019Skd93003 dgettext(TEXT_DOMAIN, "PCI"));
3241708Sstevel /*
3251708Sstevel * Get slot-name properties from parent node and
3261708Sstevel * store them in an array.
3271708Sstevel */
3281708Sstevel value = (char *)get_prop_val(
3295019Skd93003 find_prop(pci, "slot-names"));
3301708Sstevel
3311708Sstevel if (value != NULL) {
3321708Sstevel /* array starts after first int */
3331708Sstevel slot_name_arr[0] = (char *)value + sizeof (int);
3341708Sstevel for (i = 1; i < NUM_PCI_SLOTS; i++) {
3351708Sstevel slot_name_arr[i] = (char *)slot_name_arr[i - 1]
3365019Skd93003 + strlen(slot_name_arr[i - 1]) +1;
3371708Sstevel }
3381708Sstevel }
3391708Sstevel /*
3401708Sstevel * Search for Children of this node ie. Cards.
3411708Sstevel * Note: any of these cards can be a pci-bridge
3421708Sstevel * that itself has children. If we find a
3431708Sstevel * pci-bridge we need to handle it specially.
3441708Sstevel */
3451708Sstevel card_node = pci->child;
3461708Sstevel /* Generate the list of pci cards on pci instance: pci */
3471708Sstevel fill_pci_card_list(pci, card_node, &card, &card_list,
3485019Skd93003 slot_name_arr);
3491708Sstevel } /* end-for */
3501708Sstevel
3511708Sstevel if (!banner && card_list != NULL) {
3521708Sstevel log_printf(dgettext(TEXT_DOMAIN,
3535019Skd93003 " Bus Max\n"
3545019Skd93003 " IO Port Bus Freq Bus Dev,\n"
3555019Skd93003 "Type ID Side Slot MHz Freq Func State "
3565019Skd93003 "Name Model"
3571708Sstevel #ifdef DEBUG
3585019Skd93003 " Notes"
3591708Sstevel #endif
3605019Skd93003 "\n"
3615019Skd93003 "---- ---- ---- ---- ---- ---- ---- ----- "
3625019Skd93003 "-------------------------------- "
3631708Sstevel #ifdef DEBUG
3645019Skd93003 "---------------------- "
3651708Sstevel #endif
3665019Skd93003 "----------------------\n"));
3671708Sstevel banner = TRUE;
3681708Sstevel }
3691708Sstevel
3701708Sstevel display_io_cards(card_list);
3711708Sstevel free_io_cards(card_list);
3721708Sstevel }
3731708Sstevel
3741708Sstevel /*
3751708Sstevel * Print out all the io cards in the list. Also print the column
3761708Sstevel * headers if told to do so.
3771708Sstevel */
3781708Sstevel void
display_io_cards(struct io_card * list)3791708Sstevel display_io_cards(struct io_card *list)
3801708Sstevel {
3811708Sstevel struct io_card *p;
3821708Sstevel
3831708Sstevel for (p = list; p != NULL; p = p -> next) {
3841708Sstevel log_printf(dgettext(TEXT_DOMAIN,
3851708Sstevel "%-4s %-3d %c %-1s %-3d"),
3861708Sstevel p->bus_type, p->schizo_portid, p->pci_bus,
3871708Sstevel p->slot_str, p->freq);
3881708Sstevel
3891708Sstevel switch (p->pci_bus) {
3901708Sstevel case 'A':
3911708Sstevel log_printf(dgettext(TEXT_DOMAIN, " 66 "));
3921708Sstevel break;
3931708Sstevel case 'B':
3941708Sstevel log_printf(dgettext(TEXT_DOMAIN, " 33 "));
3951708Sstevel break;
3961708Sstevel default:
3971708Sstevel assert(0);
3981708Sstevel break;
3991708Sstevel }
4001708Sstevel
4011708Sstevel log_printf(dgettext(TEXT_DOMAIN,
4025019Skd93003 "%-1d,%-1d %-5s %-32.32s"),
4031708Sstevel p->dev_no, p->func_no, p->status, p->name);
4041708Sstevel if (strlen(p->name) > 32)
4051708Sstevel log_printf(dgettext(TEXT_DOMAIN, "+ "));
4061708Sstevel else
4071708Sstevel log_printf(dgettext(TEXT_DOMAIN, " "));
4081708Sstevel log_printf(dgettext(TEXT_DOMAIN, "%-22.22s"), p->model);
4091708Sstevel if (strlen(p->model) > 22)
4101708Sstevel log_printf(dgettext(TEXT_DOMAIN, "+"));
4111708Sstevel #ifdef DEBUG
4121708Sstevel log_printf("%s", p->notes);
4131708Sstevel #endif
4141708Sstevel log_printf("\n");
4151708Sstevel }
4161708Sstevel }
4171708Sstevel
4181708Sstevel /*ARGSUSED*/
4191708Sstevel void
display_ffb(Board_node * board,int table)4201708Sstevel display_ffb(Board_node *board, int table)
4211708Sstevel {
4221708Sstevel /* NOP, since there are no FFB's on this platform. */
4231708Sstevel }
4241708Sstevel
4251708Sstevel
4261708Sstevel /*
4271708Sstevel * local functions
4281708Sstevel */
4291708Sstevel
4301708Sstevel
4311708Sstevel static void
disp_envc_status()4321708Sstevel disp_envc_status()
4331708Sstevel {
4341708Sstevel int err;
4351708Sstevel char *system = "SYSTEM";
4361708Sstevel picl_nodehdl_t system_node, root;
4371708Sstevel
4381708Sstevel log_printf(dgettext(TEXT_DOMAIN,
4395019Skd93003 "\n"
4405019Skd93003 "========================= Environmental Status "
4415019Skd93003 "=========================\n\n"));
4421708Sstevel
4431708Sstevel err = picl_initialize();
4445019Skd93003 if (err != PICL_SUCCESS) {
4455019Skd93003 exit_code = PD_INTERNAL_FAILURE;
4461708Sstevel goto err_out;
4475019Skd93003 }
4481708Sstevel err = picl_get_root(&root);
4495019Skd93003 if (err != PICL_SUCCESS) {
4505019Skd93003 exit_code = PD_INTERNAL_FAILURE;
4511708Sstevel goto err_out;
4525019Skd93003 }
4531708Sstevel err = find_child_device(root, system, &system_node);
4545019Skd93003 if (err != PICL_SUCCESS) {
4555019Skd93003 exit_code = PD_INTERNAL_FAILURE;
4561708Sstevel goto err_out;
4575019Skd93003 }
4581708Sstevel
4591708Sstevel err = print_temps(system_node);
4601708Sstevel err |= print_keyswitch(system_node);
4611708Sstevel err |= print_FSP_LEDS(system_node);
4621708Sstevel err |= print_disk(system_node);
4631708Sstevel err |= print_fans(system_node);
4641708Sstevel err |= print_ps(system_node);
4651708Sstevel
4661708Sstevel if (err != PICL_SUCCESS)
4671708Sstevel goto err_out;
4681708Sstevel
4691708Sstevel return;
4701708Sstevel
4711708Sstevel err_out:
4721708Sstevel log_printf(dgettext(TEXT_DOMAIN,
4735019Skd93003 "\nEnvironmental reporting error: %s\n"),
4745019Skd93003 picl_strerror(err));
4751708Sstevel }
4761708Sstevel
4771708Sstevel static int
print_ps(picl_nodehdl_t system_node)4781708Sstevel print_ps(picl_nodehdl_t system_node)
4791708Sstevel {
4801708Sstevel int i, j, err = 0;
4811708Sstevel int32_t number;
4821708Sstevel picl_nodehdl_t *ps;
4831708Sstevel picl_nodehdl_t *ps_fail_sensor;
4841708Sstevel char name[PICL_PROPNAMELEN_MAX];
4851708Sstevel char fault_state[PICL_PROPNAMELEN_MAX];
4861708Sstevel
4871708Sstevel log_printf(dgettext(TEXT_DOMAIN, "\n\n"
4885019Skd93003 "Power Supplies:\n"
4895019Skd93003 "---------------\n"
4905019Skd93003 "\n"
4915019Skd93003 "Supply Status Fault Fan Fail Temp Fail\n"
4925019Skd93003 "------ ------------ -------- --------- ---------\n"));
4931708Sstevel
4941708Sstevel err = fill_device_array_from_id(system_node, "PSVC_PS", &number, &ps);
4951708Sstevel if (err != PICL_SUCCESS) {
4961708Sstevel return (err);
4971708Sstevel }
4981708Sstevel
4991708Sstevel for (i = 0; i < MAX_PS; i++) {
5001708Sstevel err = picl_get_propval_by_name(ps[i], PICL_PROP_NAME, name,
5011708Sstevel PICL_PROPNAMELEN_MAX);
5021708Sstevel if (err != PICL_SUCCESS)
5031708Sstevel continue;
5041708Sstevel
5051708Sstevel log_printf(dgettext(TEXT_DOMAIN, "%6-s"), name);
5061708Sstevel err = picl_get_propval_by_name(ps[i], "FaultInformation",
5075019Skd93003 fault_state, PICL_PROPNAMELEN_MAX);
5081708Sstevel if (err != PICL_SUCCESS) {
5091708Sstevel free(ps);
5101708Sstevel return (err);
5111708Sstevel }
5121708Sstevel log_printf(dgettext(TEXT_DOMAIN, " [%-12s]"), fault_state);
5131708Sstevel if (strcmp(fault_state, "NO AC POWER") == 0) {
5141708Sstevel log_printf("\n");
5151708Sstevel continue;
5161708Sstevel }
5171708Sstevel
5181708Sstevel err = fill_device_array_from_id(ps[i], "PSVC_DEV_FAULT_SENSOR",
5195019Skd93003 &number, &ps_fail_sensor);
5201708Sstevel
5211708Sstevel if (err != PICL_SUCCESS) {
5221708Sstevel free(ps);
5231708Sstevel return (err);
5241708Sstevel }
5251708Sstevel log_printf(" ");
5261708Sstevel for (j = 0; j < MAX_PS_SENSORS; j++) {
5271708Sstevel err = picl_get_propval_by_name(ps_fail_sensor[j],
5285019Skd93003 "State", fault_state, PICL_PROPNAMELEN_MAX);
5291708Sstevel if (err != PICL_SUCCESS) {
5301708Sstevel if (err == PICL_FAILURE) {
5311708Sstevel break;
5321708Sstevel }
5331708Sstevel free(ps);
5341708Sstevel free(ps_fail_sensor);
5351708Sstevel return (err);
5361708Sstevel }
5371708Sstevel log_printf(dgettext(TEXT_DOMAIN, "%-10s"), fault_state);
5381708Sstevel }
5391708Sstevel log_printf("\n");
5401708Sstevel free(ps_fail_sensor);
5411708Sstevel }
5421708Sstevel
5431708Sstevel log_printf(dgettext(TEXT_DOMAIN,
5445019Skd93003 "\n=================================\n\n"));
5451708Sstevel
5461708Sstevel free(ps);
5471708Sstevel return (PICL_SUCCESS);
5481708Sstevel }
5491708Sstevel
5501708Sstevel static int
print_fans(picl_nodehdl_t system_node)5511708Sstevel print_fans(picl_nodehdl_t system_node)
5521708Sstevel {
5531708Sstevel int i, err;
5541708Sstevel int32_t number;
5551708Sstevel picl_nodehdl_t *fans;
5561708Sstevel picl_nodehdl_t phdl;
5571708Sstevel char prop[PICL_PROPNAMELEN_MAX];
5581708Sstevel char parent[PICL_PROPNAMELEN_MAX];
5591708Sstevel int32_t rpm;
5601708Sstevel
5611708Sstevel err = fill_device_array_from_id(system_node, "PSVC_FAN", &number,
5625019Skd93003 &fans);
5631708Sstevel if (err != PICL_SUCCESS) {
5641708Sstevel return (err);
5651708Sstevel }
5661708Sstevel
5671708Sstevel log_printf(dgettext(TEXT_DOMAIN,
5685019Skd93003 "\n=================================\n\n"
5695019Skd93003 "Fan Status:\n"
5705019Skd93003 "-----------\n\n"
5715019Skd93003 "Fan Tray Fan RPM Status\n"
5725019Skd93003 "----------- ---- ----- ----------\n"));
5731708Sstevel
5741708Sstevel for (i = 0; i < MAX_FANS; i++) {
5751708Sstevel err = picl_get_propval_by_name(fans[i], PICL_PROP_NAME, prop,
5765019Skd93003 PICL_PROPNAMELEN_MAX);
5771708Sstevel if (err != PICL_SUCCESS)
5781708Sstevel continue;
5791708Sstevel
5801708Sstevel err = fill_device_from_id(fans[i], "PSVC_PARENT", &phdl);
5811708Sstevel if (err != PICL_SUCCESS)
5821708Sstevel continue;
5831708Sstevel err = picl_get_propval_by_name(phdl, PICL_PROP_NAME, parent,
5845019Skd93003 PICL_PROPNAMELEN_MAX);
5851708Sstevel if (err != PICL_SUCCESS)
5861708Sstevel continue;
5871708Sstevel
5881708Sstevel log_printf(dgettext(TEXT_DOMAIN, "%-16s"), parent);
5891708Sstevel
5901708Sstevel
5911708Sstevel log_printf(dgettext(TEXT_DOMAIN, "%-16s"), prop);
5921708Sstevel
5931708Sstevel err = picl_get_propval_by_name(fans[i], "Fan-speed",
5941708Sstevel &rpm, sizeof (rpm));
5951708Sstevel if (err != PICL_SUCCESS) {
5961708Sstevel free(fans);
5971708Sstevel return (err);
5981708Sstevel }
5991708Sstevel log_printf(dgettext(TEXT_DOMAIN, "%5d "), rpm);
6001708Sstevel
6011708Sstevel err = picl_get_propval_by_name(fans[i], "FaultInformation",
6021708Sstevel prop, PICL_PROPNAMELEN_MAX);
6031708Sstevel if (err != PICL_SUCCESS) {
6041708Sstevel free(fans);
6051708Sstevel return (err);
6061708Sstevel }
6071708Sstevel log_printf(dgettext(TEXT_DOMAIN, " [%s]\n"), prop);
6081708Sstevel }
6091708Sstevel log_printf(dgettext(TEXT_DOMAIN,
6105019Skd93003 "\n=================================\n\n"));
6111708Sstevel free(fans);
6121708Sstevel return (PICL_SUCCESS);
6131708Sstevel }
6141708Sstevel
6151708Sstevel static int
print_disk(picl_nodehdl_t system_node)6161708Sstevel print_disk(picl_nodehdl_t system_node)
6171708Sstevel {
6181708Sstevel int i, err;
6191708Sstevel int32_t number;
6201708Sstevel picl_nodehdl_t *disks;
6211708Sstevel char state[PICL_PROPNAMELEN_MAX];
6221708Sstevel
6231708Sstevel err = fill_device_array_from_id(system_node, "PSVC_DISK", &number,
6241708Sstevel &disks);
6251708Sstevel if (err != PICL_SUCCESS) {
6261708Sstevel return (err);
6271708Sstevel }
6281708Sstevel
6291708Sstevel log_printf(dgettext(TEXT_DOMAIN,
6305019Skd93003 "Disk Status:\n"
6315019Skd93003 "------------\n"));
6321708Sstevel for (i = 0; i < MAX_DISKS; i++) {
6331708Sstevel err = picl_get_propval_by_name(disks[i], "FaultInformation",
6341708Sstevel state, PICL_PROPNAMELEN_MAX);
6351708Sstevel
6361708Sstevel switch (err) {
6371708Sstevel case PICL_SUCCESS:
6381708Sstevel log_printf(dgettext(TEXT_DOMAIN,
6395019Skd93003 "DISK %d: [%3s]\n"), i, state);
6401708Sstevel break;
6411708Sstevel case PICL_INVALIDHANDLE:
6421708Sstevel log_printf(dgettext(TEXT_DOMAIN,
6435019Skd93003 "DISK %d: [ NOT PRESENT ]\n"), i);
6441708Sstevel break;
6451708Sstevel default:
6461708Sstevel free(disks);
6471708Sstevel return (err);
6481708Sstevel }
6491708Sstevel }
6501708Sstevel free(disks);
6511708Sstevel return (PICL_SUCCESS);
6521708Sstevel }
6531708Sstevel
6541708Sstevel static int
print_FSP_LEDS(picl_nodehdl_t system_node)6551708Sstevel print_FSP_LEDS(picl_nodehdl_t system_node)
6561708Sstevel {
6571708Sstevel int err;
6581708Sstevel int32_t number;
6591708Sstevel picl_nodehdl_t *fsp_led;
6601708Sstevel char fault_state[PICL_PROPNAMELEN_MAX];
6611708Sstevel char locate_state[PICL_PROPNAMELEN_MAX];
6621708Sstevel
6631708Sstevel err = fill_device_array_from_id(system_node, "PSVC_FSP_LED", &number,
6641708Sstevel &fsp_led);
6651708Sstevel if (err != PICL_SUCCESS) {
6661708Sstevel return (err);
6671708Sstevel }
6681708Sstevel
6691708Sstevel assert(number == 2);
6701708Sstevel err = picl_get_propval_by_name(fsp_led[0], "State", &fault_state,
6715019Skd93003 PICL_PROPNAMELEN_MAX);
6721708Sstevel if (err != PICL_SUCCESS) {
6731708Sstevel free(fsp_led);
6741708Sstevel return (err);
6751708Sstevel }
6765019Skd93003
6775019Skd93003 if (strcmp(fault_state, PSVC_LED_ON) == 0)
6785019Skd93003 exit_code = PD_SYSTEM_FAILURE;
6795019Skd93003
6801708Sstevel err = picl_get_propval_by_name(fsp_led[1], "State", &locate_state,
6815019Skd93003 PICL_PROPNAMELEN_MAX);
6821708Sstevel if (err != PICL_SUCCESS) {
6831708Sstevel free(fsp_led);
6841708Sstevel return (err);
6851708Sstevel }
6861708Sstevel
6871708Sstevel log_printf(dgettext(TEXT_DOMAIN,
6885019Skd93003 "System LED Status:\n\n"
6895019Skd93003 " LOCATOR FAULT POWER\n"
6905019Skd93003 " ------- ------- -------\n"
6915019Skd93003 " [%3s] [%3s] [ ON]"),
6925019Skd93003 locate_state, fault_state);
6931708Sstevel
6941708Sstevel log_printf(dgettext(TEXT_DOMAIN,
6955019Skd93003 "\n\n=================================\n\n"));
6961708Sstevel free(fsp_led);
6971708Sstevel return (err);
6981708Sstevel }
6991708Sstevel
7001708Sstevel static int
print_keyswitch(picl_nodehdl_t system_node)7011708Sstevel print_keyswitch(picl_nodehdl_t system_node)
7021708Sstevel {
7031708Sstevel int err;
7041708Sstevel picl_nodehdl_t *keyswitch;
7051708Sstevel int32_t number;
7061708Sstevel char ks_pos[PICL_PROPNAMELEN_MAX];
7071708Sstevel
7081708Sstevel err = fill_device_array_from_id(system_node, "PSVC_KEYSWITCH", &number,
7091708Sstevel &keyswitch);
7101708Sstevel if (err != PICL_SUCCESS) {
7111708Sstevel return (err);
7121708Sstevel }
7131708Sstevel err = picl_get_propval_by_name(keyswitch[0], "State", ks_pos,
7145019Skd93003 PICL_PROPNAMELEN_MAX);
7151708Sstevel if (err != PICL_SUCCESS) {
7161708Sstevel free(keyswitch);
7171708Sstevel return (err);
7181708Sstevel }
7191708Sstevel
7201708Sstevel log_printf(dgettext(TEXT_DOMAIN,
7215019Skd93003 "Front Status Panel:\n"
7225019Skd93003 "-------------------\n"
7235019Skd93003 "Keyswitch position: %s\n\n"), ks_pos);
7241708Sstevel free(keyswitch);
7251708Sstevel return (err);
7261708Sstevel }
7271708Sstevel
7281708Sstevel static int
print_temps(picl_nodehdl_t system_node)7291708Sstevel print_temps(picl_nodehdl_t system_node)
7301708Sstevel {
7311708Sstevel int i;
7321708Sstevel int err;
7331708Sstevel picl_nodehdl_t *system_ts_nodes;
7341708Sstevel int32_t temp;
7351708Sstevel int32_t number;
7361708Sstevel char label[PICL_PROPNAMELEN_MAX];
7371708Sstevel char state[PICL_PROPNAMELEN_MAX];
7381708Sstevel char *p;
7391708Sstevel
7401708Sstevel err = fill_device_array_from_id(system_node, "PSVC_TS", &number,
7411708Sstevel &system_ts_nodes);
7421708Sstevel if (err != PICL_SUCCESS) {
7431708Sstevel return (err);
7441708Sstevel }
7451708Sstevel
7461708Sstevel log_printf(dgettext(TEXT_DOMAIN,
7475019Skd93003 "System Temperatures (Celsius):\n"
7485019Skd93003 "-------------------------------\n"
7495019Skd93003 "Device\t\tTemperature\tStatus\n"
7505019Skd93003 "---------------------------------------\n"));
7511708Sstevel
7521708Sstevel for (i = 0; i < number; i++) {
7531708Sstevel err = picl_get_propval_by_name(system_ts_nodes[i],
7541708Sstevel "State", state, sizeof (state));
7551708Sstevel if (err != PICL_SUCCESS) {
7561708Sstevel if (err == PICL_INVALIDHANDLE) {
7575019Skd93003 (void) strcpy(state, "n/a");
7581708Sstevel } else {
7591708Sstevel free(system_ts_nodes);
7601708Sstevel return (err);
7611708Sstevel }
7621708Sstevel }
7631708Sstevel err = picl_get_propval_by_name(system_ts_nodes[i],
7641708Sstevel PICL_PROP_NAME, label, PICL_PROPNAMELEN_MAX);
7651708Sstevel if (err != PICL_SUCCESS) {
7661708Sstevel if (err == PICL_INVALIDHANDLE)
7671708Sstevel /* This FRU isn't present. Skip it. */
7681708Sstevel continue;
7691708Sstevel free(system_ts_nodes);
7701708Sstevel return (err);
7711708Sstevel }
7721708Sstevel
7731708Sstevel /*
7741708Sstevel * The names in the tree are like "CPU0_DIE_TEMPERATURE_SENSOR".
7751708Sstevel * All we want to print is up to the first underscore.
7761708Sstevel */
7771708Sstevel p = strchr(label, '_');
7781708Sstevel if (p != NULL)
7791708Sstevel *p = '\0';
7801708Sstevel
7811708Sstevel err = picl_get_propval_by_name(system_ts_nodes[i],
7825019Skd93003 "Temperature", &temp, sizeof (temp));
7831708Sstevel if (err != PICL_SUCCESS) {
7841708Sstevel free(system_ts_nodes);
7851708Sstevel return (err);
7861708Sstevel }
7871708Sstevel log_printf("%s\t\t%3d\t\t%s\n", label, temp, state);
7881708Sstevel }
7891708Sstevel
7901708Sstevel log_printf(dgettext(TEXT_DOMAIN,
7915019Skd93003 "\n=================================\n\n"));
7921708Sstevel
7931708Sstevel free(system_ts_nodes);
7941708Sstevel return (PICL_SUCCESS);
7951708Sstevel }
7961708Sstevel
7971708Sstevel static void
display_hw_revisions(Prom_node * root,Board_node * bdlist)7981708Sstevel display_hw_revisions(Prom_node *root, Board_node *bdlist)
7991708Sstevel {
8001708Sstevel Prom_node *pnode;
8011708Sstevel char *value;
8021708Sstevel
8031708Sstevel log_printf(dgettext(TEXT_DOMAIN, "\n"
8045019Skd93003 "========================= HW Revisions "
8055019Skd93003 "=======================================\n\n"));
8061708Sstevel
8071708Sstevel log_printf(dgettext(TEXT_DOMAIN,
8085019Skd93003 "System PROM revisions:\n"
8095019Skd93003 "----------------------\n"));
8101708Sstevel
8111708Sstevel pnode = dev_find_node(root, "openprom");
8121708Sstevel if (pnode != NULL) {
8135019Skd93003 value = (char *)get_prop_val(find_prop(pnode, "version"));
8145019Skd93003 log_printf(value);
8151708Sstevel }
8161708Sstevel
8171708Sstevel log_printf(dgettext(TEXT_DOMAIN, "\n\n"
8185019Skd93003 "IO ASIC revisions:\n"
8195019Skd93003 "------------------\n"
8205019Skd93003 " Port\n"
8215019Skd93003 "Model ID Status Version\n"
8225019Skd93003 "-------- ---- ------ -------\n"));
8231708Sstevel
8241708Sstevel display_schizo_revisions(bdlist);
8251708Sstevel }
8261708Sstevel
8271708Sstevel
8281708Sstevel static void
display_schizo_revisions(Board_node * bdlist)8291708Sstevel display_schizo_revisions(Board_node *bdlist)
8301708Sstevel {
8311708Sstevel Prom_node *pnode;
8321708Sstevel int *int_val;
8331708Sstevel int portid;
8341708Sstevel int prev_portid = -1;
8351708Sstevel char *status_a = NULL;
8361708Sstevel char *status_b = NULL;
8371708Sstevel int revision;
8381708Sstevel #ifdef DEBUG
8391708Sstevel uint32_t a_notes, b_notes;
8401708Sstevel #endif
8411708Sstevel int pci_bus;
8421708Sstevel Board_node *bnode;
8431708Sstevel bnode = bdlist;
8441708Sstevel
8451708Sstevel while (bnode != NULL) {
8461708Sstevel /*
8471708Sstevel * search this board node for all Schizos
8481708Sstevel */
8491708Sstevel
8501708Sstevel for (pnode = dev_find_node_by_compat(bnode->nodes,
8515019Skd93003 SCHIZO_COMPAT_PROP); pnode != NULL;
8525019Skd93003 pnode = dev_next_node_by_compat(pnode,
8535019Skd93003 SCHIZO_COMPAT_PROP)) {
8541708Sstevel
8551708Sstevel /*
8561708Sstevel * get the reg property to determine
8571708Sstevel * whether we are looking at side A or B
8581708Sstevel */
8591708Sstevel
8601708Sstevel int_val = (int *)get_prop_val
8615019Skd93003 (find_prop(pnode, "reg"));
8621708Sstevel if (int_val != NULL) {
8631708Sstevel int_val ++; /* second integer in array */
8641708Sstevel pci_bus = ((*int_val) & 0x7f0000);
8651708Sstevel }
8661708Sstevel
8671708Sstevel /* get portid */
8681708Sstevel int_val = (int *)get_prop_val
8695019Skd93003 (find_prop(pnode, "portid"));
8701708Sstevel if (int_val == NULL)
8711708Sstevel continue;
8721708Sstevel
8731708Sstevel portid = *int_val;
8741708Sstevel
8751708Sstevel /*
8761708Sstevel * If this is a new portid and it is PCI bus B,
8771708Sstevel * we skip onto the PCI bus A.
8781708Sstevel */
8791708Sstevel if ((portid != prev_portid) && (pci_bus == 0x700000)) {
8801708Sstevel prev_portid = portid;
8811708Sstevel /* status */
8821708Sstevel status_b = (char *)get_prop_val
8831708Sstevel (find_prop(pnode, "status"));
8841708Sstevel #ifdef DEBUG
8851708Sstevel b_notes = pci_bus;
8861708Sstevel #endif
8871708Sstevel continue; /* skip to the next schizo */
8881708Sstevel }
8891708Sstevel
8901708Sstevel /*
8911708Sstevel * This must be side A of the same Schizo.
8921708Sstevel * Gather all its props and display them.
8931708Sstevel */
8941708Sstevel #ifdef DEBUG
8951708Sstevel a_notes = pci_bus;
8961708Sstevel #endif
8971708Sstevel
8981708Sstevel prev_portid = portid;
8991708Sstevel
9001708Sstevel int_val = (int *)get_prop_val
9015019Skd93003 (find_prop(pnode, "version#"));
9021708Sstevel if (int_val != NULL)
9031708Sstevel revision = *int_val;
9041708Sstevel else
9051708Sstevel revision = -1;
9061708Sstevel
9071708Sstevel status_a = (char *)get_prop_val(find_prop
9085019Skd93003 (pnode, "status"));
9091708Sstevel
9101708Sstevel log_printf(dgettext(TEXT_DOMAIN, "Schizo "));
9111708Sstevel
9121708Sstevel log_printf(dgettext(TEXT_DOMAIN, "%-3d "), portid, 0);
9131708Sstevel
9141708Sstevel
9151708Sstevel log_printf((status_a == NULL && status_b == NULL) ?
9165019Skd93003 dgettext(TEXT_DOMAIN, " ok ") :
9175019Skd93003 dgettext(TEXT_DOMAIN, " fail "));
9181708Sstevel
9191708Sstevel log_printf(dgettext(TEXT_DOMAIN, " %4d "),
9201708Sstevel revision);
9211708Sstevel #ifdef DEBUG
9221708Sstevel log_printf(" 0x%x 0x%x", a_notes, b_notes);
9231708Sstevel #endif
9241708Sstevel log_printf("\n");
9251708Sstevel }
9261708Sstevel bnode = bnode->next;
9271708Sstevel }
9281708Sstevel }
929