montecarlo.c revision 03831d35f7499c87d51205817c93e9a8d42c4bae
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2000-2001 by Sun Microsystems, Inc.
* All rights reserved.
*
* Netract Platform specific functions.
*
* called when :
* machine_type == MTYPE_MONTECARLO
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* includes */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <stropts.h>
#include <fcntl.h>
#include <kvm.h>
#include <kstat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/openpromio.h>
#include <sys/sunddi.h>
#include <sys/ddi_impldefs.h>
#include <sys/devinfo_impl.h>
#include <sys/ioccom.h>
#include <sys/systeminfo.h>
#include <libintl.h>
#include <config_admin.h>
#include "pdevinfo.h"
#include "display.h"
#include "pdevinfo_sun4u.h"
#include "display_sun4u.h"
#include "libprtdiag.h"
#include "libdevinfo.h"
/* MC specific header, might just include from MC space */
#include "mct_topology.h"
#include "envctrl_gen.h"
#include "pcf8574_nct.h"
#include "netract_gen.h"
#include "hscimpl.h"
#include "scsbioctl.h"
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
/* globals */
#define MAXNAMESZ 128
#define MAX_NODE_NAME_SZ 32
/* this values equates to Max Tree depth for now */
#define MAXIMUM_DEVS 64
typedef char device_info_t[MAX_NODE_NAME_SZ];
typedef struct {
cfga_list_data_t *ldatap;
int req; /* If set, this list_data was requested by user */
} ap_out_t;
typedef struct {
uint_t slot_addr;
uint_t slot_stat;
uint_t slot_cond;
device_info_t devs_info[MAXIMUM_DEVS];
uint_t number_devs;
} mc_slot_info_t;
typedef struct {
mc_slot_info_t mc_slot_info[MC_MAX_SLOTS];
} slot_data_t;
extern char *progname;
extern int print_flag;
/* These are used to store all force loads of the drivers */
static int ps_fd[MC_MAX_PS];
static int oprom_fd;
static int slot_index = 0;
static int idx_minuscpu = 0;
static int num_devs = 0;
static int sd_instances[MC_MAX_SLOTS*15];
static int gpio_instances[MC_MAX_PS+MC_MAX_FAN];
static int sd_count = 0;
static int st_instance;
static int gpio_count = 0;
static int slot_table_not_found = 0;
/* default not present */
static int alarm_card_present = 0;
static int cpu_ftm_present = 0;
/*
* We will store all kstat in globals so that
* we can browse thru them later
*/
static int fail_syssoft_prop = 0;
static int fail_drv_prop = 0;
di_node_t rootnode; /* root nexus */
slot_data_t mc_slots_data;
/* scsb driver kstats */
scsb_ks_leddata_t scsb_ks_leddata;
scsb_ks_state_t scsb_ks_state;
mct_topology_t scsb_ks_topo;
/* pcf8574(gpio) driver kstats */
envctrl_cpuvoltage_t pcf8574_ks_cpuv;
envctrl_pwrsupp_t pcf8574_ks_ps1;
envctrl_fantray_t pcf8574_ks_fant1;
envctrl_pwrsupp_t pcf8574_ks_ps2;
envctrl_fantray_t pcf8574_ks_fant2;
/* pcf8591(adc-dac) driver kstats */
envctrl_temp_t pcf8591_ks_temp;
hsc_slot_table_t hotswap_slot_table[MC_MAX_SLOTS];
hsc_prom_slot_table_t prom_slot_table[MC_MAX_SLOTS];
static char *hotswap_mode = NULL;
static char *slot_auto_config[MC_MAX_SLOTS];
static int slot_table_size;
/*
* use this to ascertain what's the system,
* default is tonga, we can add more for future variations
* 0=tonga, 1=montecarlo
* we need also to figure out what the system version is
* 0 = 1.5, 1 = 1.0, 0.6 etc.
*/
int montecarlo = 0;
int version_p15_and_p20 = 0;
#define MAX_PRTDIAG_INFO_LENGTH 1024
#define MAX_PRTDIAG_FRUS 22
#define BIT_TEST(X, N) ((X) & (1 << (N)))
#define SLOT1_OK_BIT 0
#define SLOT2_OK_BIT 1
#define SLOT3_OK_BIT 2
#define SLOT4_OK_BIT 3
#define SLOT5_OK_BIT 4
#define SLOT6_OK_BIT 5
#define SLOT7_OK_BIT 6
#define SLOT8_OK_BIT 7
#define PDU1_OK_BIT SLOT2_OK_BIT
#define PDU2_OK_BIT SLOT4_OK_BIT
#define FTM_OK_BIT SLOT5_OK_BIT
#define SCB_OK_BIT SLOT6_OK_BIT
#define FAN1_OK_BIT SLOT1_OK_BIT
#define FAN2_OK_BIT SLOT2_OK_BIT
#define DISK1_OK_BIT SLOT4_OK_BIT
#define DISK2_OK_BIT SLOT5_OK_BIT
#define DISK3_OK_BIT SLOT6_OK_BIT
#define PS1_OK_BIT SLOT7_OK_BIT
#define PS2_OK_BIT SLOT8_OK_BIT
#define S_FREE(x) (((x) != NULL) ? (free(x), (x) = NULL) : (void *)0)
#define ENVC_DEBUG_MODE 0x03
#define OPENPROMDEV "/dev/openprom"
#define I2C_PCF8591_NAME "adc-dac"
#define I2C_KSTAT_CPUTEMP "adc_temp"
#define SCSB_DEV "scsb"
#define SDERR "sderr"
#define STERR "sterr"
#define OK "ok"
#define NOK "Not ok"
#define ON "on"
#define OFF "off"
#define BLINK "blink"
#define NA "Not Available"
#define UK "Unknown "
#define YES "Yes"
#define NO "No "
#define LO "low"
#define HI "high"
#define BLANK " "
#define SYSSOFT_PROP "System software"
#define DRV_PROP "Driver"
#define HSC_PROP_NAME "hsc-slot-map"
#define HSC_MODE "hotswap-mode"
#define PCI_ROOT_AP "pci"
#define PROPS "Properties:"
#define BOARDTYPE "Board Type:"
#define DEVS "Devices:"
#define CPCI_IO "CompactPCI IO Slot"
#define AC_CARD "Alarm Card"
#define CPU_FTM "Front Transition Module"
#define SCTRL_PROM_P06 0x00
#define SCTRL_PROM_P10 0x01
#define SCTRL_PROM_P15 0x02
#define SCTRL_PROM_P20 0x03
#define RMM_NUMBER 3
#define MONTECARLO_PLATFORM "SUNW,UltraSPARC-IIi-Netract"
#define MAKAHA_PLATFORM "SUNW,UltraSPARC-IIe-NetraCT-40"
/*
* The follow table is indexed with the enum's defined by mct_slot_occupant_t
* OC_UNKN OC_CPU OC_AC OC_BHS OC_FHS OC_HAHS
* OC_QFE OC_FRCH OC_COMBO OC_PMC OC_ATM
*
* But "scsb" can currently identify only CPU and Alarm Cards by known
* slot numbers.
*/
char *slot_occupants[] = {
CPCI_IO,
"CPU board ",
CPCI_IO,
"Basic HotSwap Board",
"Full HotSwap Board",
"HA Board",
"QFE Board",
"Fresh Choice Board",
"SUN Combo Board",
"PMC Board",
"ATM Board"
};
static char *prtdiag_fru_types[] = {
"I/O ", /* 0 */
"CPU ",
"PSU ",
"HDD ",
"FAN ",
"Alarm Card ",
"SCB ",
"SSB ",
"CFTM ",
"CRTM ",
"PRTM ",
"Midplane " /* 11 */
};
char prtdiag_fru_info[MAX_PRTDIAG_FRUS][MAX_PRTDIAG_INFO_LENGTH];
#define SCB_REG_READ 1
#define SCB_REG_WRITE 2
/* Standard Device nodes - hardwired for now */
/* will include fan tray later, cpu voltage not impl */
static char *scsb_node = NULL;
static char **ps_node = NULL;
static char *temp_node = NULL;
static char *mc_scsb_node =
"/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/sysctrl@0,80:scsb";
static char *ot_scsb_node =
"/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/sysctrl@0,80:scsb";
static char *mc_ps_node[] = {
"/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7c:pwrsuppply",
"/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/gpio@0,7e:pwrsuppply"
};
static char *ot_ps_node[] = {
"/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7c:pwrsuppply",
"/devices/pci@1f,0/pci@1,1/ebus@3/sysmgmt@14,600000/gpio@0,7e:pwrsuppply"
};
static char *mc_temp_node =
"/devices/pci@1f,0/pci@1,1/ebus@1/i2c@14,600000/adc-dac@0,9e:cputemp";
/*
* these functions will overlay the symbol table of libprtdiag
* at runtime (netract systems only)
* display functions
*/
int display(Sys_tree *, Prom_node *, struct system_kstat_data *, int);
/* local functions */
/*
* prom function
*/
static void gather_diaginfo(int flag);
static int extract_slot_table_from_obp();
static int mc_next(int id);
static void mc_walk(int id);
static int mc_child(int id);
static void mc_dump_node(int id);
static int mc_getpropval(struct openpromio *opp);
#ifdef REDUNDANT_INFO
static int mc_get_cpu_freq(Prom_node *node);
static int mc_get_ecache_size(Prom_node *node);
static void mc_display_cpus(Board_node *board);
static void mc_display_cpu_devices(Sys_tree *tree);
#endif /* REDUNDANT_INFO */
static void netract_disp_prom_version();
/*
* Since we do not have a system wide kstat for MC/Tg
* here we have to do specific kstats to drivers that
* post this information - MC/Tg specific drivers
* that post kstat here are : scsb, pcf8574(gpio) and pcf8591
*/
static int analyze_nodes(di_node_t, void*);
static void analyze_pcipci_siblings(di_node_t);
static void display_mc_prtdiag_info();
static int dump_devs(di_node_t, void *);
static void prtdiag_devinfo(void);
static void force_load_drivers();
static int dump_prop_list(char *name,
di_node_t node, di_prop_t (*nxtprop)());
static void *config_calloc_check(size_t nelem, size_t elsize);
static void explore_slot_occupants();
static void do_scsb_kstat();
static void do_pcf8574_kstat();
static void do_pcf8591_kstat();
static void do_promversion();
static int mc_promopen(int oflag);
static int scsi_disk_status(int disk_number);
static void alarm_card_occupant();
static int scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode);
static int scsb_ioc_reg_read(int fd, uchar_t index,
scsb_ioc_rdwr_t *ioc_rd, int num);
static int check_platform();
int
display(Sys_tree *tree,
Prom_node *root,
struct system_kstat_data *kstats,
int syserrlog)
{
int exit_code = 0; /* init to all OK */
void *value; /* used for opaque PROM data */
struct mem_total memory_total; /* Total memory in system */
struct grp_info grps; /* Info on all groups in system */
#ifdef lint
syserrlog = syserrlog;
#endif
sys_clk = -1; /* System clock freq. (in MHz) */
/*
* Now display the machine's configuration. We do this if we
* are not logging or exit_code is set (machine is broke).
*/
if (!logging || exit_code) {
struct utsname uts_buf;
/*
* Display system banner
*/
(void) uname(&uts_buf);
log_printf(dgettext(TEXT_DOMAIN,
"System Configuration: Sun Microsystems"
" %s %s\n"), uts_buf.machine,
get_prop_val(find_prop(root, "banner-name")), 0);
/* display system clock frequency */
value = get_prop_val(find_prop(root, "clock-frequency"));
if (value != NULL) {
sys_clk = ((*((int *)value)) + 500000) / 1000000;
log_printf(dgettext(TEXT_DOMAIN,
"System clock frequency: "
"%d MHz\n"), sys_clk, 0);
}
/* Display the Memory Size */
display_memorysize(tree, kstats, &grps, &memory_total);
/* Lets make sure we have all the needed drivers loaded */
/* display Montecarlo/Tonga FRU information */
if (!extract_slot_table_from_obp())
log_printf(dgettext(TEXT_DOMAIN,
"\r\nslot-table not available\r\n"), 0);
do_scsb_kstat();
force_load_drivers();
gather_diaginfo(print_flag && !logging);
/* figure out if ac is present */
alarm_card_occupant();
/* platform specific display mod */
display_mc_prtdiag_info();
di_fini(rootnode);
netract_disp_prom_version();
} /* if (!logging || exit_code) */
return (exit_code);
} /* display(....) */
static int
check_platform()
{
char si_platform[SYS_NMLN];
/*
* Check for the platform: Montecarlo or Makaha/CP2040 based
*/
if (sysinfo(SI_PLATFORM, si_platform, sizeof (si_platform)) == -1) {
return (-1);
}
if ((strncmp(si_platform, MONTECARLO_PLATFORM,
strlen(MONTECARLO_PLATFORM))) == 0) {
scsb_node = mc_scsb_node;
ps_node = mc_ps_node;
temp_node = mc_temp_node;
} else if ((strncmp(si_platform, MAKAHA_PLATFORM,
strlen(MAKAHA_PLATFORM))) == 0) {
scsb_node = ot_scsb_node;
ps_node = ot_ps_node;
temp_node = NULL;
} else {
return (-1);
}
return (0);
}
void
force_load_drivers()
{
int i;
if (NULL == scsb_node || NULL == ps_node) {
if (check_platform() == -1) {
return;
}
}
/* check scb/ssb presence */
if (scsb_ks_state.scb_present || scsb_ks_state.ssb_present) {
if (open(scsb_node, O_RDONLY) < 0)
log_printf(dgettext(TEXT_DOMAIN,
"\nscsb open FAILED!"), 0);
}
/* check the num of PS we have */
for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) {
if ((ps_fd[i] = open(ps_node[i], O_RDONLY)) < 0)
log_printf(dgettext(TEXT_DOMAIN,
"\npowersupply%d open failed"),
i, 0);
}
} /* for */
/* open the cpu temp driver */
if (temp_node) {
if (open(temp_node, O_RDONLY) < 0)
log_printf(dgettext(TEXT_DOMAIN,
"\ncputemp open FAILED!"), 0);
}
}
void
explore_slot_occupants()
{
char *cp = NULL;
int index;
int ret = CFGA_ERROR;
char *estrp = NULL;
cfga_list_data_t *list_array = NULL;
ap_out_t *out_array = NULL;
int nlist = 0;
char *prefilt_optp = NULL;
int dyn_exp = 1;
char *plat_opts = NULL;
ret = config_list_ext(0, NULL, &list_array,
&nlist, plat_opts, prefilt_optp, &estrp,
dyn_exp ? CFGA_FLAG_LIST_ALL : 0);
if (ret != CFGA_OK) {
log_printf(dgettext(TEXT_DOMAIN,
"\ncannot explore configuration"), 0);
return;
}
assert(nlist != 0);
out_array = config_calloc_check(nlist, sizeof (*out_array));
if (out_array == NULL) {
ret = CFGA_LIB_ERROR;
goto bail;
}
/* create a list of output stat data */
for (index = 0; index < nlist; index++) {
out_array[index].ldatap = &list_array[index];
out_array[index].req = 0;
}
for (index = 0; index < nlist; index++) {
if ((cp = strstr(out_array[index].ldatap->ap_phys_id,
"cpci_slot")) != NULL) {
mc_slots_data.mc_slot_info[idx_minuscpu].slot_stat
= out_array[index].ldatap->ap_o_state;
mc_slots_data.mc_slot_info[idx_minuscpu].slot_cond
= out_array[index].ldatap->ap_cond;
idx_minuscpu++;
}
}
bail:
S_FREE(list_array);
S_FREE(out_array);
}
/*
* config_calloc_check - perform allocation, check result and
* set error indicator
*/
void *
config_calloc_check(
size_t nelem,
size_t elsize)
{
void *p;
static char alloc_fail[] =
"%s: memory allocation failed (%d*%d bytes)\n";
p = calloc(nelem, elsize);
if (p == NULL) {
log_printf(dgettext(TEXT_DOMAIN, alloc_fail), nelem, elsize, 0);
}
return (p);
}
void
do_scsb_kstat()
{
kstat_ctl_t *kc;
kstat_t *ksp_leddata;
kstat_t *ksp_state;
kstat_t *ksp_topo;
scsb_ks_leddata_t *pks_leddata;
scsb_ks_state_t *pks_state;
mct_topology_t *pks_topo;
int i;
#ifdef DEBUG_TEMP1
int index;
#endif
if (!(kc = kstat_open())) {
#ifdef DEBUG_TEMP
log_printf("\nkstat_open failed", 0);
#endif
return;
}
#ifdef lint
kc = kc;
#endif
/* get kstat on scsb led data */
if ((ksp_leddata = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_LEDDATA))
== NULL) {
#ifdef DEBUG_TEMP
log_printf("\nkstat_lookup for scsb_leddata failed", 0);
#endif
return;
}
if (kstat_read(kc, ksp_leddata, NULL) == -1) {
#ifdef DEBUG_TEMP
log_printf("\nkstat_read for scsb_leddata failed", 0);
#endif
return;
}
pks_leddata = (scsb_ks_leddata_t *)ksp_leddata->ks_data;
scsb_ks_leddata = *pks_leddata; /* set the globals for future */
#ifdef DEBUG_LEDS
/* dump the kstat leddata */
printf("\nDumping LED regs: ");
for (i = 0; i < SCSB_LEDDATA_REGISTERS; ++i) {
log_printf("0x%x ", pks_leddata->scb_led_regs[i] & 0xff, 0);
}
log_printf("\n", 0);
#endif
/* get kstat on scsb states */
if ((ksp_state = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_STATE))
== NULL) {
#ifdef DEBUG_TEMP
log_printf("\nkstat_lookup for scsb_state failed", 0);
#endif
return;
}
if (kstat_read(kc, ksp_state, NULL) == -1) {
#ifdef DEBUG_TEMP
log_printf("\nkstat_read for scsb_state failed", 0);
#endif
return;
}
pks_state = (scsb_ks_state_t *)ksp_state->ks_data;
scsb_ks_state = *pks_state; /* set the global for future */
#ifdef DEBUG_TEMP1
/* dump the kstat state */
log_printf("\tSCB is%spresent\n",
pks_state->scb_present ? " " : " not ", 0);
log_printf("\tSSB is%spresent\n",
pks_state->ssb_present ? " " : " not ", 0);
log_printf("\tscsb is%sfrozen\n",
pks_state->scsb_frozen ? " " : " not ", 0);
log_printf("\tscsb mode: ", 0);
switch (pks_state->scsb_mode) {
case ENVC_DEBUG_MODE:
log_printf("DEBUG MODE\n", 0);
break;
case ENVCTRL_DIAG_MODE:
log_printf("DIAGNOSTIC MODE\n", 0);
break;
case ENVCTRL_NORMAL_MODE:
log_printf("NORMAL MODE\n", 0);
break;
}
log_printf("\tscsb event code: 0x%x\n", pks_state->event_code, 0);
#endif /* DEBUG_TEMP1 */
if ((ksp_topo = kstat_lookup(kc, SCSB_DEV, 0, SCSB_KS_TOPOLOGY))
== NULL) {
#ifdef DEBUG_TEMP
log_printf("\nkstat_lookup for scsb_topo failed", 0);
#endif
return;
}
if (kstat_read(kc, ksp_topo, NULL) == -1) {
#ifdef DEBUG_TEMP
log_printf("\nkstat_read for scsb_topo failed", 0);
#endif
return;
}
pks_topo = (mct_topology_t *)ksp_topo->ks_data;
scsb_ks_topo = *pks_topo; /* set the global for future */
/*
* we need to set this so that we can get status info
* for the 2 powersupplies in MC as we need to get
* kstat from both driver instances for environment
*/
if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF)
montecarlo = 1; /* Monte Carlo */
/*
* HW version 0.6 and 1.0 had different led maps
* its assumed that HW 2.0 would not change this
* need to modify if it does
*/
if ((pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P15) ||
(pks_topo->mct_scb[0].fru_version == SCTRL_PROM_P20)) {
version_p15_and_p20 = 1;
}
/* set flag to note that CFTM is present */
for (i = 0; i < pks_topo->max_units[CFTM]; ++i) {
if (pks_topo->mct_cftm[i].fru_status == FRU_PRESENT)
cpu_ftm_present = 1;
}
#ifdef DEBUG_TEMP1
/*
* Midplane
*/
log_printf("Midplane type: ", 0);
if (pks_topo->mid_plane.fru_id == SCTRL_MPID_HALF)
log_printf("Netra ct800 server\n", 0);
else
log_printf("Netra ct400 server%s\n",
pks_topo->mid_plane.fru_id ==
SCTRL_MPID_QUARTER_NODSK ? ", no disk" : " with disk", 0);
log_printf("Midplane version: %d\n",
pks_topo->mid_plane.fru_version, 0);
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_scb[0].fru_type,
pks_topo->mct_scb[0].fru_unit,
pks_topo->mct_scb[0].fru_id,
pks_topo->mct_scb[0].fru_version, 0);
/*
* Slots
*/
log_printf("Slots present out of maximum %d\n",
pks_topo->max_units[SLOT], 0);
for (i = 0; i < pks_topo->max_units[SLOT]; ++i) {
if (pks_topo->mct_slots[i].fru_status != FRU_PRESENT)
continue;
index = (int)pks_topo->mct_slots[i].fru_type;
log_printf("\tSlot %d occupant: %s;",
pks_topo->mct_slots[i].fru_unit, slot_occupants[index], 0);
log_printf(" ID 0x%x; VER 0x%x ; ",
pks_topo->mct_slots[i].fru_id,
pks_topo->mct_slots[i].fru_version, 0);
log_printf(" Slot health %d\n",
pks_topo->mct_slots[i].fru_health, 0);
/* pks_topo->mct_slots[i].fru_health */
}
/*
* PDU
*/
log_printf("PDUs present out of maximum %d\n",
pks_topo->max_units[PDU], 0);
for (i = 0; i < pks_topo->max_units[PDU]; ++i) {
if (pks_topo->mct_pdu[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_pdu[i].fru_type,
pks_topo->mct_pdu[i].fru_unit,
pks_topo->mct_pdu[i].fru_id,
pks_topo->mct_pdu[i].fru_version, 0);
/* pks_topo->mct_pdu[i].fru_health */
}
/*
* Power Supplies
*/
log_printf("Power Supplies present out of maximum %d\n",
pks_topo->max_units[PS], 0);
for (i = 0; i < pks_topo->max_units[PS]; ++i) {
if (pks_topo->mct_ps[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_ps[i].fru_type,
pks_topo->mct_ps[i].fru_unit,
pks_topo->mct_ps[i].fru_id,
pks_topo->mct_ps[i].fru_version, 0);
}
/*
* Disks
*/
log_printf("Disks present out of maximum %d\n",
pks_topo->max_units[DISK], 0);
for (i = 0; i < pks_topo->max_units[DISK]; ++i) {
if (pks_topo->mct_disk[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_disk[i].fru_type,
pks_topo->mct_disk[i].fru_unit,
pks_topo->mct_disk[i].fru_id,
pks_topo->mct_disk[i].fru_version, 0);
}
/*
* Fans
*/
log_printf("Fans present out of maximum %d\n",
pks_topo->max_units[FAN], 0);
for (i = 0; i < pks_topo->max_units[FAN]; ++i) {
if (pks_topo->mct_fan[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_fan[i].fru_type,
pks_topo->mct_fan[i].fru_unit,
pks_topo->mct_fan[i].fru_id,
pks_topo->mct_fan[i].fru_version, 0);
}
/*
* SCBs
*/
log_printf("SCBs present out of maximum %d\n",
pks_topo->max_units[SCB], 0);
for (i = 0; i < pks_topo->max_units[SCB]; ++i) {
if (pks_topo->mct_scb[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_scb[i].fru_type,
pks_topo->mct_scb[i].fru_unit,
pks_topo->mct_scb[i].fru_id,
pks_topo->mct_scb[i].fru_version, 0);
}
/*
* SSBs
*/
log_printf("SSBs present out of maximum %d\n",
pks_topo->max_units[SSB], 0);
for (i = 0; i < pks_topo->max_units[SSB]; ++i) {
if (pks_topo->mct_ssb[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_ssb[i].fru_type,
pks_topo->mct_ssb[i].fru_unit,
pks_topo->mct_ssb[i].fru_id,
pks_topo->mct_ssb[i].fru_version, 0);
}
/*
* Alarms Cards
*/
log_printf("Alarm Cards present out of maximum %d\n",
pks_topo->max_units[ALARM], 0);
for (i = 0; i < pks_topo->max_units[ALARM]; ++i) {
if (pks_topo->mct_alarm[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d; unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_alarm[i].fru_type,
pks_topo->mct_alarm[i].fru_unit,
pks_topo->mct_alarm[i].fru_id,
pks_topo->mct_alarm[i].fru_version, 0);
}
/*
* CFTMs
*/
log_printf("CFTMs present out of maximum %d\n",
pks_topo->max_units[CFTM], 0);
for (i = 0; i < pks_topo->max_units[CFTM]; ++i) {
if (pks_topo->mct_cftm[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_cftm[i].fru_type,
pks_topo->mct_cftm[i].fru_unit,
pks_topo->mct_cftm[i].fru_id,
pks_topo->mct_cftm[i].fru_version, 0);
}
/*
* CRTMs
*/
log_printf("CRTMs present out of maximum %d\n",
pks_topo->max_units[CRTM], 0);
for (i = 0; i < pks_topo->max_units[CRTM]; ++i) {
if (pks_topo->mct_crtm[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_crtm[i].fru_type,
pks_topo->mct_crtm[i].fru_unit,
pks_topo->mct_crtm[i].fru_id,
pks_topo->mct_crtm[i].fru_version, 0);
}
/*
* PRTMs
*/
log_printf("PRTMs present out of maximum %d\n",
pks_topo->max_units[PRTM], 0);
for (i = 0; i < pks_topo->max_units[PRTM]; ++i) {
if (pks_topo->mct_prtm[i].fru_status != FRU_PRESENT)
continue;
log_printf("\ttype %d unit %d; id 0x%x; VER 0x%x\n",
pks_topo->mct_prtm[i].fru_type,
pks_topo->mct_prtm[i].fru_unit,
pks_topo->mct_prtm[i].fru_id,
pks_topo->mct_prtm[i].fru_version, 0);
}
#endif /* DEBUG_TEMP1 */
} /* do_scsb_kstat(...) */
void
do_pcf8574_kstat()
{
kstat_ctl_t *kc;
kstat_t *ksp_ps;
kstat_t *ksp_fan;
envctrl_pwrsupp_t *pks_ps;
envctrl_fantray_t *pks_fan;
int i;
char *kstat_name = NULL;
if (!(kc = kstat_open())) {
#ifdef DEBUG_TEMP
log_printf("\nkstat_open for pcf8574 failed", 0);
#endif
return;
}
#ifdef lint
kc = kc;
#endif
/* get kstat on gpio powersupply and fan states */
for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
if (i == 1) {
kstat_name = I2C_KSTAT_PWRSUPPLY;
strncat(kstat_name, "1", 1);
} else {
kstat_name = I2C_KSTAT_PWRSUPPLY;
strncat(kstat_name, "2", 1);
}
if ((ksp_ps = kstat_lookup(kc, I2C_PCF8574_NAME, 0, kstat_name))
== NULL) {
#ifdef DEBUG_TEMP
log_printf("\nks lookup for pwrsupply%d failed",
i+1, 0);
#endif
return;
}
if (kstat_read(kc, ksp_ps, NULL) == -1) {
#ifdef DEBUG_TEMP
log_printf("\nks read for pwrsupply%d failed", i+1, 0);
#endif
return;
}
pks_ps = (envctrl_pwrsupp_t *)ksp_ps->ks_data;
if (i == 1)
pcf8574_ks_ps1 = *pks_ps; /* ps 1 */
else
pcf8574_ks_ps2 = *pks_ps; /* ps 2 */
} /* for */
for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) {
if (i == 1) {
kstat_name = I2C_KSTAT_FANTRAY;
strncat(kstat_name, "1", 1);
} else {
kstat_name = I2C_KSTAT_FANTRAY;
strncat(kstat_name, "2", 1);
}
if ((ksp_fan = kstat_lookup(kc, I2C_PCF8574_NAME,
0, kstat_name)) == NULL) {
#ifdef DEBUG_TEMP
log_printf("\nks lookup for fantray%d failed",
i+1, 0);
#endif
return;
}
if (kstat_read(kc, ksp_fan, NULL) == -1) {
#ifdef DEBUG_TEMP
log_printf("\nks read for fantray%d failed", i+1, 0);
#endif
return;
}
pks_fan = (envctrl_fantray_t *)ksp_fan->ks_data;
if (i == 1)
pcf8574_ks_fant1 = *pks_fan; /* fan 1 */
else
pcf8574_ks_fant2 = *pks_fan; /* fan 2 */
} /* for */
kstat_close(kc);
} /* do_pcf8574_kstat(...) */
void
do_pcf8591_kstat()
{
kstat_ctl_t *kc;
kstat_t *ksp_temp;
envctrl_temp_t *pks_temp;
if (!(kc = kstat_open())) {
#ifdef DEBUG_TEMP
log_printf("ks open for pcf8591 failed", 0);
#endif
return;
}
#ifdef lint
kc = kc;
#endif
/* get kstat on adc driver's CPU temperature data */
if ((ksp_temp = kstat_lookup(kc, I2C_PCF8591_NAME,
-1, I2C_KSTAT_CPUTEMP))
== NULL) {
#ifdef DEBUG_TEMP
log_printf("ks lookup for adc_temp failed", 0);
#endif
return;
}
if (kstat_read(kc, ksp_temp, NULL) == -1) {
#ifdef DEBUG_TEMP
log_printf("ks read for adc_temp failed", 0);
#endif
return;
}
pks_temp = (envctrl_temp_t *)ksp_temp->ks_data;
pcf8591_ks_temp = *pks_temp;
kstat_close(kc);
} /* do_pcf8591_kstat(.) */
void
gather_diaginfo(int flag)
{
if (flag) {
/* gather system environmental conditions. */
/* obtain kstat info from gpio & temp. driver */
do_pcf8574_kstat();
do_pcf8591_kstat();
explore_slot_occupants(); /* fill in some occupant info */
prtdiag_devinfo();
analyze_pcipci_siblings(rootnode);
}
} /* display_diaginfo(...) */
void
netract_disp_prom_version()
{
/* Display Prom revision header */
log_printf(dgettext(TEXT_DOMAIN, "System Board PROM revision:\n"), 0);
log_printf("---------------------------\n", 0);
do_promversion();
} /* netract_disp_prom_version(.) */
/*
* Get and print the PROM version.
*/
void
do_promversion(void)
{
Oppbuf oppbuf;
struct openpromio *opp = &(oppbuf.opp);
if (mc_promopen(O_RDONLY)) {
log_printf(dgettext(TEXT_DOMAIN,
"\nCannot open openprom device"), 0);
return;
}
opp->oprom_size = MAXVALSIZE;
if (ioctl(oprom_fd, OPROMGETVERSION, opp) < 0) {
perror("\nOPROMGETVERSION ioctl failed");
return;
}
log_printf("%s\n", opp->oprom_array, 0);
if (close(oprom_fd) < 0) {
log_printf(dgettext(TEXT_DOMAIN,
"\nclose error on %s"), OPENPROMDEV, 0);
return;
}
} /* do_promversion() */
int
mc_promopen(int oflag)
{
for (;;) {
if ((oprom_fd = open(OPENPROMDEV, oflag)) < 0) {
if (errno == EAGAIN) {
(void) sleep(5);
continue;
}
if (errno == ENXIO)
return (-1);
log_printf(dgettext(TEXT_DOMAIN,
"\ncannot open %s"), OPENPROMDEV, 0);
return (1);
} else
return (0);
}
}
/*
* This will return -1 for status unknown, 0 for OK, and 1 for failed (scsi
* hard errors)
* swiped from envmon policies
*/
int
scsi_disk_status(int disk_number)
{
kstat_ctl_t *kc;
kstat_t *ksp_disk;
kstat_named_t *disk_data;
int i;
int nlist = 0;
cfga_list_data_t *list_array = NULL;
char *ap_ids[] = {"c0"};
if ((kc = kstat_open()) == NULL) {
log_printf(dgettext(TEXT_DOMAIN, "\nks open failed"), 0);
return (-1);
}
if (disk_number == RMM_NUMBER) { /* RMM */
if (config_list_ext(1, ap_ids, &list_array, &nlist,
NULL, NULL, NULL, CFGA_FLAG_LIST_ALL) != CFGA_OK) {
kstat_close(kc);
return (-1);
}
for (i = 0; i < nlist; i++) {
if (strstr(list_array[i].ap_phys_id, "rmt/0") != NULL) {
/* Tape drive */
if (list_array[i].ap_o_state ==
CFGA_STAT_UNCONFIGURED) {
kstat_close(kc);
return (-1);
}
if ((ksp_disk = kstat_lookup(kc, STERR,
st_instance, NULL)) == NULL) {
kstat_close(kc);
return (-1);
}
break;
} else if (strstr(list_array[i].ap_phys_id,
"dsk/c0t6d0") != NULL) {
/* CD_ROM */
if (list_array[i].ap_o_state ==
CFGA_STAT_UNCONFIGURED) {
kstat_close(kc);
return (-1);
}
if ((ksp_disk = kstat_lookup(kc, SDERR,
sd_instances[disk_number-1], NULL)) ==
NULL) {
kstat_close(kc);
return (-1);
}
break;
}
}
} else { /* Hard disk */
if ((ksp_disk = kstat_lookup(kc, SDERR,
sd_instances[disk_number-1], NULL)) == NULL) {
kstat_close(kc);
return (-1);
}
}
if (kstat_read(kc, ksp_disk, NULL) == -1) {
log_printf(dgettext(TEXT_DOMAIN,
"\nks read error for disk%d, drv inst%d"),
disk_number, sd_instances[disk_number-1], 0);
kstat_close(kc);
return (-1);
}
disk_data = KSTAT_NAMED_PTR(ksp_disk);
/*
* if disk_data[].value is >0, we have a problem
*/
if (disk_data[1].value.ui32 == 0) {
kstat_close(kc);
return (0);
} else {
kstat_close(kc);
return (1);
}
}
void
prtdiag_devinfo(void)
{
uint_t flag;
/* lets get everything we can from kernel */
flag = DINFOSUBTREE|DINFOPROP;
rootnode = di_init("/", flag);
if (rootnode == DI_NODE_NIL) {
log_printf(dgettext(TEXT_DOMAIN,
"\nprtdiag_devinfo: di_init() failed"), 0);
return;
}
(void) di_walk_node(rootnode, DI_WALK_CLDFIRST, NULL,
dump_devs);
}
/*
* gather information about this node, returns appropriate code.
* specific information we seek are driver names, instances
* we will initialize some globals depending on what we find
* from the kernel device tree info and may be private data
* if required
*/
/*ARGSUSED1*/
int
dump_devs(di_node_t node, void *arg)
{
char *driver_name;
driver_name = di_driver_name(node);
/* we will initialize our globals here */
if ((di_instance(node) >= 0) &&
(driver_name != NULL) &&
(!(di_state(node) & DI_DRIVER_DETACHED))) {
if (strcmp(driver_name, "pcf8574") == 0) {
gpio_instances[gpio_count] = di_instance(node);
gpio_count++;
} else if (strcmp(driver_name, "sd") == 0) {
sd_instances[sd_count] = di_instance(node);
sd_count++;
} else if (strcmp(driver_name, "st") == 0) {
st_instance = di_instance(node);
}
}
if (strcmp(di_node_name(node), "pseudo") == 0)
return (DI_WALK_PRUNECHILD);
else
return (DI_WALK_CONTINUE);
}
/*
* Returns 0 if error , 1 otherwise
*/
int
dump_prop_list(char *name, di_node_t node, di_prop_t (*nxtprop)())
{
int prop_len, i, k, max_slots_minus_cpu, n;
uchar_t *prop_data;
char *p;
char *temp_s;
di_prop_t prop, next;
int ret_value = 0;
max_slots_minus_cpu = scsb_ks_topo.max_units[SLOT]-1;
if ((next = nxtprop(node, DI_PROP_NIL)) == DI_PROP_NIL)
return (0);
while (next != DI_PROP_NIL) {
int maybe_str = 1, npossible_strs = 0;
prop = next;
next = nxtprop(node, prop);
/*
* get prop length and value:
* private interface--always success
*/
prop_len = di_prop_rawdata(prop, &prop_data);
if (di_prop_type(prop) == DDI_PROP_UNDEF_IT) {
continue;
}
if (prop_len == 0) {
continue;
}
if (prop_data[prop_len - 1] != '\0') {
maybe_str = 0;
} else {
/*
* Every character must be a string character or a \0,
* and there must not be two \0's in a row.
*/
for (i = 0; i < prop_len; i++) {
if (prop_data[i] == '\0') {
npossible_strs++;
} else if (!isascii(prop_data[i]) ||
iscntrl(prop_data[i])) {
maybe_str = 0;
break;
}
if ((i > 0) && (prop_data[i] == '\0') &&
(prop_data[i - 1] == '\0')) {
maybe_str = 0;
break;
}
}
}
if (maybe_str) {
p = (char *)prop_data;
for (i = 0; i < npossible_strs - 1; i++) {
if ((strcmp(name, SYSSOFT_PROP) == 0) &&
(strcmp(di_prop_name(prop),
HSC_PROP_NAME) == 0)) {
temp_s = p;
temp_s += strlen(temp_s) + 1;
}
p += strlen(p) + 1;
}
if ((strcmp(name, SYSSOFT_PROP) == 0) &&
(strcmp(di_prop_name(prop), HSC_PROP_NAME) == 0)) {
temp_s = temp_s - prop_len+2;
for (k = 0, n = 0; k < prop_len; k++) {
if (temp_s[k] == 0) {
n++;
}
}
if (n % 4) {
log_printf(dgettext(TEXT_DOMAIN,
"\nbad slot-table(%d)\n"), n);
slot_table_not_found = 0;
return (ret_value);
}
slot_table_size = n / 4;
/*
* NOTE : We save slot table info in order
*/
for (k = 0; k < slot_table_size; k++) {
char *nexus, *pcidev, *phys_slotname;
char *ga;
/*
* Pick off pointer to nexus
* path or PROM handle
*/
nexus = temp_s;
while (*temp_s != NULL)
temp_s++;
temp_s++;
/*
* Pick off pointer to the
* pci device number
*/
pcidev = temp_s;
while (*temp_s != NULL)
temp_s++;
temp_s++;
/* Pick off physical slot no */
phys_slotname = temp_s;
while (*temp_s != NULL)
temp_s++;
temp_s++;
/*
* Pick off GA bits which
* we dont use for now.
*/
ga = temp_s;
while (*temp_s != NULL)
temp_s++;
temp_s++;
hotswap_slot_table[k].pslotnum
= atoi(phys_slotname);
hotswap_slot_table[k].ga = atoi(ga);
hotswap_slot_table[k].pci_devno
= atoi(pcidev);
strcpy(hotswap_slot_table[k].nexus,
nexus);
} /* for (k = 0; k < slot_table_size; k++) */
ret_value = 1;
} else /* (strcmp(name, SYSSOFT_PROP) */
slot_table_not_found = 1;
/*
* now we want to save off the info
* we would use later
*/
if ((strcmp(name, DRV_PROP) == 0) &&
(strcmp(di_prop_name(prop), HSC_MODE) == 0)) {
hotswap_mode = p;
ret_value = 1;
} else if ((strcmp(name, DRV_PROP) == 0) &&
(strcmp(di_prop_name(prop), HSC_MODE) != 0)) {
/* save it in order in the right index */
slot_auto_config[max_slots_minus_cpu] = p;
max_slots_minus_cpu--;
ret_value = 1;
}
} else {
for (i = 0; i < prop_len; ++i) {
#if 0
unsigned char byte;
byte = (unsigned char)prop_data[i];
log_printf("%2.2x", byte, 0);
#endif
}
}
}
return (ret_value);
}
void
display_mc_prtdiag_info()
{
int i, index;
int s_index, i1;
int tg_cpu_index = 0;
char *mcfru_type, *status, *mc_ok_led, *mc_nok_led;
char *misc_info, *health, *board_type;
log_printf("===============================", 0);
log_printf(dgettext(TEXT_DOMAIN,
" FRU Information ================================\n"), 0);
log_printf(dgettext(TEXT_DOMAIN,
"FRU FRU FRU Green Amber"), 0);
log_printf(dgettext(TEXT_DOMAIN, " Miscellaneous\n"), 0);
log_printf(dgettext(TEXT_DOMAIN,
"Type Unit# Present LED LED"), 0);
log_printf(dgettext(TEXT_DOMAIN, " Information\n"), 0);
log_printf("---------- ----- ------- ----- -----", 0);
log_printf(" ----------------------------------\n", 0);
if (scsb_ks_topo.mid_plane.fru_id == SCTRL_MPID_HALF)
misc_info = "Netra ct800";
else {
misc_info = "Netra ct400";
}
mcfru_type = prtdiag_fru_types[MIDPLANE];
switch (scsb_ks_topo.mid_plane.fru_status) {
case FRU_PRESENT:
status = YES;
break;
case FRU_NOT_PRESENT:
status = NO;
break;
case FRU_NOT_AVAILABLE:
status = NA; break;
default:
status = NA; break;
}
mc_ok_led = " ";
mc_nok_led = " ";
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s %-5s %s\n"),
mcfru_type, scsb_ks_topo.mid_plane.fru_unit,
status, mc_ok_led, mc_nok_led,
misc_info, 0);
log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0);
log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK,
scsb_ks_topo.mid_plane.fru_version, 0);
log_printf(dgettext(TEXT_DOMAIN, "%49sMaximum Slots=%d\n"), BLANK,
scsb_ks_topo.max_units[SLOT], 0);
/* SCB & SSB */
mcfru_type = prtdiag_fru_types[SCB];
for (i = 0; i < scsb_ks_topo.max_units[SCB]; ++i) {
misc_info = "System Controller Board";
if (version_p15_and_p20) {
mc_ok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1]
& 0xff), SCB_OK_BIT) ? BLINK :
(BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1]
& 0xff), SCB_OK_BIT) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1]
& 0xff), SCB_OK_BIT) ? ON:OFF;
} else {
/*
* support for 1.0 systems -
* Hack! - should use tables ?
*/
mc_ok_led =
(BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
& 0xff), 0) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
& 0xff), 0) ? ON:OFF;
}
switch (scsb_ks_topo.mct_scb[i].fru_status) {
case FRU_PRESENT:
status = YES;
break;
case FRU_NOT_PRESENT:
status = NO;
break;
case FRU_NOT_AVAILABLE:
status = NA;
break;
default:
status = NA;
break;
}
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s %-5s %s\n"),
mcfru_type, scsb_ks_topo.mct_scb[i].fru_unit,
status, mc_ok_led, mc_nok_led, misc_info, 0);
log_printf(dgettext(TEXT_DOMAIN, "%46s%s\n"), BLANK, PROPS, 0);
log_printf(dgettext(TEXT_DOMAIN, "%49sVersion=%d\n"), BLANK,
scsb_ks_topo.mct_scb[0].fru_version, 0);
if (fail_drv_prop == 1)
log_printf(dgettext(TEXT_DOMAIN,
"%49s%s=%s\n"), BLANK, HSC_MODE,
hotswap_mode, 0);
} /* for */
mcfru_type = prtdiag_fru_types[SSB];
for (i = 0; i < scsb_ks_topo.max_units[SSB]; ++i) {
misc_info = "System Status Panel";
switch (scsb_ks_topo.mct_ssb[i].fru_status) {
case FRU_PRESENT:
status = YES;
break;
case FRU_NOT_PRESENT:
status = NO;
break;
case FRU_NOT_AVAILABLE:
status = NA;
break;
default:
status = NA;
break;
}
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s %-5s %s\n"),
mcfru_type, scsb_ks_topo.mct_ssb[i].fru_unit,
status, BLANK, BLANK, misc_info, 0);
} /* for */
/* Slots */
for (i = 0; i < scsb_ks_topo.max_units[SLOT]; ++i) {
if (montecarlo) {
if (scsb_ks_topo.mct_slots[i].fru_unit == 1)
mcfru_type = prtdiag_fru_types[1];
else
mcfru_type = prtdiag_fru_types[SLOT];
/*
* Another way this could have been done is,
* to read the sub system id
* it is 0x6722 for Alarm Card
* but this id is only valid for the new ACs
* older ACs still have the same susbsystem
* id as most other Sun PCI cards
* We cannot completely rely on this.
* Also,it turns out that Sun OpenBoot does not
* always follow IEEE 1275 std, hence in a few
* systems, the "subsystem-id" published by the
* PROM could not be found
* We know the AC slot# if present on both MC&Tg
* Hence we check on both - now we are sure
* that we have found an AC
*/
if ((scsb_ks_topo.mct_slots[i].fru_unit == 8) &&
(alarm_card_present == 1))
board_type = AC_CARD;
else
board_type = UK;
} else {
if (scsb_ks_topo.mct_slots[i].fru_unit == 3)
mcfru_type = prtdiag_fru_types[1];
else
mcfru_type = prtdiag_fru_types[SLOT];
/*
* Another way this could have been done is,
* to read the sub system id
* it is 0x6722 for Alarm Card
* but this id is only valid for the new ACs
* older ACs still have the same susbsystem
* id as most other Sun PCI cards
* We cannot completely rely on this.
* Also,it turns out that Sun OpenBoot does not
* always follow IEEE 1275 std, hence in a few
* systems, the "subsystem-id" published by the
* PROM could not be found
* We know the AC slot# if present on both MC&Tg
* Hence we check on both - now we are sure
* that we have found an AC
*/
if ((scsb_ks_topo.mct_slots[i].fru_unit == 1) &&
(alarm_card_present == 1))
board_type = AC_CARD;
else
board_type = UK;
}
if (version_p15_and_p20) {
mc_ok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[0]
& 0xff), i) ? BLINK :
(BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[0]
& 0xff), i) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[0]
& 0xff), i) ? ON:OFF;
} else {
/*
* support for 1.0 systems -
* Hack! - should use tables ?
*/
if (scsb_ks_topo.mct_slots[i].fru_unit == 7) {
mc_ok_led =
BIT_TEST(
(scsb_ks_leddata.leds.p10.blink_leds[1]
& 0xff), 0) ? BLINK :
(BIT_TEST(
(scsb_ks_leddata.leds.p10.ok_leds[1]
& 0xff), 0) ? ON:OFF);
mc_nok_led =
BIT_TEST(
(scsb_ks_leddata.leds.p10.nok_leds[1]
& 0xff), 0) ? ON:OFF;
} else if (scsb_ks_topo.mct_slots[i].fru_unit == 8) {
mc_ok_led =
BIT_TEST(
(scsb_ks_leddata.leds.p10.blink_leds[1]
& 0xff), 1) ? BLINK :
(BIT_TEST(
(scsb_ks_leddata.leds.p10.ok_leds[1]
& 0xff), 1) ? ON:OFF);
mc_nok_led =
BIT_TEST(
(scsb_ks_leddata.leds.p10.nok_leds[1]
& 0xff), 1) ? ON:OFF;
} else {
/*
* for all other slots offset,
* index are the same
*/
mc_ok_led =
BIT_TEST(
(scsb_ks_leddata.leds.p10.blink_leds[0]
& 0xff), i) ? BLINK :
(BIT_TEST(
(scsb_ks_leddata.leds.p10.ok_leds[0]
& 0xff), i) ? ON:OFF);
mc_nok_led =
BIT_TEST(
(scsb_ks_leddata.leds.p10.nok_leds[0]
& 0xff), i) ? ON:OFF;
}
} /* else if (!version_p15_and_p20) */
switch (scsb_ks_topo.mct_slots[i].fru_status) {
case FRU_PRESENT:
status = YES;
break;
case FRU_NOT_PRESENT:
status = NO;
break;
case FRU_NOT_AVAILABLE:
status = NA;
break;
default:
status = NA;
break;
}
index = (int)scsb_ks_topo.mct_slots[i].fru_type;
if (montecarlo) {
if (scsb_ks_topo.mct_slots[i].fru_unit == 1) {
/* cpu slot */
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s "),
mcfru_type,
scsb_ks_topo.mct_slots[i].fru_unit,
status, mc_ok_led, mc_nok_led, 0);
log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"),
mc_nok_led,
slot_occupants[index], 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49stemperature(celsius):%d\n"),
BLANK,
pcf8591_ks_temp.value, 0);
#ifdef NEVER
log_printf(dgettext(TEXT_DOMAIN,
"%49sminimum temperature:%d\n"),
BLANK,
pcf8591_ks_temp.min, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49swarning temp. threshold:%d\n"),
BLANK,
pcf8591_ks_temp.warning_threshold, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49sshutdown temp.threshold:%d\n"),
BLANK,
pcf8591_ks_temp.shutdown_threshold, 0);
#endif /* NEVER */
} else if ((scsb_ks_topo.mct_slots[i].fru_unit == 2) &&
(cpu_ftm_present == 1)) {
/* CFTM slot */
/*
* The CFTM can only be present in Slot 2
* for Netract-800, for Netract-400 the FTM
* is not sitted in a Slot. Hence, this is
* another special case and we need to handle
* this differently than other slots
*/
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s "),
mcfru_type,
scsb_ks_topo.mct_slots[i].fru_unit,
status, mc_ok_led, mc_nok_led, 0);
log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"),
mc_nok_led,
CPU_FTM, 0);
} else {
if (fail_drv_prop == 1) {
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s "),
mcfru_type,
scsb_ks_topo.mct_slots[i].fru_unit,
status, mc_ok_led, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%-5s %s\n"),
mc_nok_led,
slot_occupants[index], 0);
log_printf(dgettext(TEXT_DOMAIN,
"%46s%s\n"), BLANK,
PROPS, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49sauto-config=%s\n"),
BLANK,
slot_auto_config[i], 0);
} else {
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s "),
mcfru_type,
scsb_ks_topo.mct_slots[i].fru_unit,
status, mc_ok_led, 0);
log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"),
mc_nok_led,
slot_occupants[index], 0);
}
}
} else { /* tonga */
if (scsb_ks_topo.mct_slots[i].fru_unit == 3) {
/* cpu slot */
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s "),
mcfru_type,
scsb_ks_topo.mct_slots[i].fru_unit,
status, mc_ok_led, 0);
log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"),
mc_nok_led,
slot_occupants[index], 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49stemperature(celsius):%d\n"),
BLANK,
pcf8591_ks_temp.value, 0);
#ifdef NEVER
log_printf(dgettext(TEXT_DOMAIN,
"%49sminimum temperature:%d\n"),
BLANK,
pcf8591_ks_temp.min, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49swarning temp. threshold:%d\n"),
BLANK,
pcf8591_ks_temp.warning_threshold, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49sshutdown temp. threshold:%d\n"),
BLANK,
pcf8591_ks_temp.shutdown_threshold, 0);
#endif /* NEVER */
} else {
if (fail_drv_prop == 1) {
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s "),
mcfru_type,
scsb_ks_topo.mct_slots[i].fru_unit,
status, mc_ok_led, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%-5s %s\n"),
mc_nok_led,
slot_occupants[index], 0);
log_printf(dgettext(TEXT_DOMAIN,
"%46s%s\n"), BLANK, PROPS, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49sauto-config=%s\n"),
BLANK,
slot_auto_config[tg_cpu_index+1],
0);
if (scsb_ks_topo.mct_slots[i].fru_unit
!= 3)
tg_cpu_index++;
} else {
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s "),
mcfru_type,
scsb_ks_topo.mct_slots[i].fru_unit,
status, mc_ok_led, 0);
log_printf(dgettext(TEXT_DOMAIN, "%-5s %s\n"),
mc_nok_led,
slot_occupants[index], 0);
}
}
}
/* we first match the correct slot numbers */
for (s_index = 0; s_index < slot_table_size; s_index++) {
if (slot_table_not_found == 1) {
/* use prom table */
if (scsb_ks_topo.mct_slots[i].fru_unit ==
prom_slot_table[s_index].pslotnum) {
/*
* search for the addr/pci num
* in all slot info structs
*/
for (i1 = 0; i1 < slot_index;
i1++) {
if (prom_slot_table[s_index].pci_devno ==
mc_slots_data.mc_slot_info[i1].slot_addr) {
int nd;
log_printf(dgettext(TEXT_DOMAIN,
"%46s%s%s\n"), BLANK,
BOARDTYPE, board_type, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%46s%s\n"), BLANK, DEVS, 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49s%s\n"), BLANK,
PCI_ROOT_AP, 0);
for (nd = 0;
nd < mc_slots_data.mc_slot_info[i1].number_devs;
nd++) {
log_printf(dgettext(TEXT_DOMAIN, "%52s%s\n"), BLANK,
mc_slots_data.mc_slot_info[i1].devs_info[nd],
0);
} /* for */
} /* if */
} /* for(i1) */
} /* if */
} else {
/* use solaris lot table */
if (fail_syssoft_prop == 1) {
if (scsb_ks_topo.mct_slots[i].fru_unit ==
hotswap_slot_table[s_index].pslotnum) {
/*
* search for the addr/pci
* num in all slot info structs
*/
for (i1 = 0; i1 < slot_index; i1++) {
if (hotswap_slot_table[s_index].pci_devno ==
mc_slots_data.mc_slot_info[i1].slot_addr) {
int nd;
for (nd = 0;
nd < mc_slots_data.mc_slot_info[i1].number_devs;
nd++) {
log_printf(dgettext(TEXT_DOMAIN, "%49s%s\n"), BLANK,
mc_slots_data.mc_slot_info[i1].devs_info[nd],
0);
}
} /* if */
} /* for(i1) */
} /* if */
} /* (fail_syssoft_prop == 1) */
} /* (slot_table_not_found == 1) */
} /* for(s_index) */
} /* for */
mcfru_type = "PDU";
misc_info = "Power Distribution Unit";
for (i = 0; i < scsb_ks_topo.max_units[PDU]; ++i) {
if (version_p15_and_p20) {
mc_ok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[1]
& 0xff), PDU1_OK_BIT+i*2) ? BLINK :
(BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[1]
& 0xff), PDU1_OK_BIT+i*2) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[1]
& 0xff), PDU1_OK_BIT+i*2) ? ON:OFF;
}
switch (scsb_ks_topo.mct_pdu[i].fru_status) {
case FRU_PRESENT:
status = YES;
break;
case FRU_NOT_PRESENT:
status = NO;
break;
case FRU_NOT_AVAILABLE:
status = NA;
break;
default:
status = NA;
break;
}
if (version_p15_and_p20) {
log_printf(dgettext(TEXT_DOMAIN,
"%-10s %-5d %-7s %-5s %-5s %s\n"),
mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit,
status, mc_ok_led, mc_nok_led, misc_info, 0);
} else {
log_printf(dgettext(TEXT_DOMAIN,
"%-10s %-5d %-7s%18s%s\n"),
mcfru_type, scsb_ks_topo.mct_pdu[i].fru_unit,
status, BLANK, misc_info, 0);
}
} /* for */
/* PS */
mcfru_type = prtdiag_fru_types[PS];
misc_info = "Power Supply Unit";
for (i = 0; i < scsb_ks_topo.max_units[PS]; ++i) {
if (version_p15_and_p20) {
mc_ok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2]
& 0xff), PS1_OK_BIT+i) ? BLINK :
(BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
& 0xff), PS1_OK_BIT+i) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
& 0xff), PS1_OK_BIT+i) ? ON:OFF;
} else {
/*
* support for 1.0 systems -
* Hack! - should use tables ?
*/
mc_ok_led =
(BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
& 0xff), 1+i) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
& 0xff), 1+i) ? ON:OFF;
}
switch (scsb_ks_topo.mct_ps[i].fru_status) {
case FRU_PRESENT:
status = YES;
break;
case FRU_NOT_PRESENT:
status = NO;
break;
case FRU_NOT_AVAILABLE:
status = NA;
break;
default:
status = NA;
break;
}
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s %-5s %s\n"),
mcfru_type, scsb_ks_topo.mct_ps[i].fru_unit,
status, mc_ok_led, mc_nok_led,
misc_info, 0);
if (scsb_ks_topo.mct_ps[i].fru_status == FRU_PRESENT) {
if (scsb_ks_topo.mct_ps[i].fru_unit == 1) {
log_printf(dgettext(TEXT_DOMAIN,
"%49scondition:%s\n"), BLANK,
((pcf8574_ks_ps1.ps_ok)? NOK:OK), 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49stemperature:%s\n"), BLANK,
((pcf8574_ks_ps1.temp_ok)? NOK:OK), 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49sps fan:%s\n"), BLANK,
((pcf8574_ks_ps1.psfan_ok)? NOK:OK), 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49ssupply:%s\n"), BLANK,
((pcf8574_ks_ps1.on_state)? OFF:ON), 0);
} else {
log_printf(dgettext(TEXT_DOMAIN,
"%49scondition:%s\n"), BLANK,
((pcf8574_ks_ps2.ps_ok)? NOK:OK), 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49stemperature:%s\n"), BLANK,
((pcf8574_ks_ps2.temp_ok)? NOK:OK), 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49sps fan:%s\n"), BLANK,
((pcf8574_ks_ps2.psfan_ok)? NOK:OK), 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49ssupply:%s\n"), BLANK,
((pcf8574_ks_ps2.on_state)? OFF:ON), 0);
} /* if */
}
} /* for */
/* Fan tray */
mcfru_type = prtdiag_fru_types[FAN];
misc_info = "Fan Tray";
for (i = 0; i < scsb_ks_topo.max_units[FAN]; ++i) {
if (version_p15_and_p20) {
mc_ok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.blink_leds[2]
& 0xff), FAN1_OK_BIT+i) ? BLINK :
(BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
& 0xff), FAN1_OK_BIT+i) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
& 0xff), FAN1_OK_BIT+i) ? ON:OFF;
} else {
/*
* support for 1.0 systems -
* Hack! - should use tables ?
*/
mc_ok_led =
(BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[3]
& 0xff), 3+i) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[3]
& 0xff), 3+i) ? ON:OFF;
}
switch (scsb_ks_topo.mct_fan[i].fru_status) {
case FRU_PRESENT:
status = YES;
break;
case FRU_NOT_PRESENT:
status = NO;
break;
case FRU_NOT_AVAILABLE:
status = NA;
break;
default:
status = NA;
break;
}
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s %-5s %s\n"),
mcfru_type, scsb_ks_topo.mct_fan[i].fru_unit,
status, mc_ok_led, mc_nok_led,
misc_info, 0);
if (scsb_ks_topo.mct_fan[i].fru_status == FRU_PRESENT) {
if (scsb_ks_topo.mct_fan[i].fru_unit == 1) {
log_printf(dgettext(TEXT_DOMAIN,
"%49scondition:%s\n"), BLANK,
((pcf8574_ks_fant1.fan_ok)? OK:NOK), 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49sfan speed:%s\n"), BLANK,
((pcf8574_ks_fant1.fanspeed)? HI:LO), 0);
} else {
log_printf(dgettext(TEXT_DOMAIN,
"%49scondition:%s\n"), BLANK,
((pcf8574_ks_fant2.fan_ok)? OK:NOK), 0);
log_printf(dgettext(TEXT_DOMAIN,
"%49sfan speed:%s\n"), BLANK,
((pcf8574_ks_fant2.fanspeed)? HI:LO), 0);
}
}
} /* for */
/* DISKS */
for (i = 0; i < scsb_ks_topo.max_units[DISK]; ++i) {
if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER)
mcfru_type = prtdiag_fru_types[DISK];
else
mcfru_type = "RMM ";
switch (scsb_ks_topo.mct_disk[i].fru_status) {
case FRU_PRESENT:
status = YES;
break;
case FRU_NOT_PRESENT:
status = NO;
break;
case FRU_NOT_AVAILABLE:
status = NA;
break;
default:
status = NA;
break;
}
if (version_p15_and_p20) {
mc_ok_led =
BIT_TEST((scsb_ks_leddata.scb_led_regs[8]
& 0xff), DISK1_OK_BIT+i) ? BLINK :
(BIT_TEST((scsb_ks_leddata.leds.p15.ok_leds[2]
& 0xff), DISK1_OK_BIT+i) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p15.nok_leds[2]
& 0xff), DISK1_OK_BIT+i) ? ON:OFF;
} else {
/*
* support for 1.0 systems -
* Hack! - should use tables ?
*/
mc_ok_led =
(BIT_TEST((scsb_ks_leddata.leds.p10.ok_leds[2]
& 0xff), DISK1_OK_BIT+i) ? ON:OFF);
mc_nok_led =
BIT_TEST((scsb_ks_leddata.leds.p10.nok_leds[2]
& 0xff), DISK1_OK_BIT+i) ? ON:OFF;
}
/* print everything except condition */
if (scsb_ks_topo.mct_disk[i].fru_unit != RMM_NUMBER) {
misc_info = "Hard Disk Drive";
log_printf(dgettext(TEXT_DOMAIN,
"%10s %-5d %-7s %-5s %-5s %s\n"),
mcfru_type, scsb_ks_topo.mct_disk[i].fru_unit-1,
status, mc_ok_led, mc_nok_led, misc_info, 0);
} else {
misc_info = "Removable Media Module";
log_printf(dgettext(TEXT_DOMAIN,
"%10s %5s %-7s %-5s %-5s %s\n"),
mcfru_type, BLANK,
status, mc_ok_led, mc_nok_led, misc_info, 0);
}
/* find out fru health from the SCSI drivers */
if (scsb_ks_topo.mct_disk[i].fru_status == FRU_PRESENT) {
switch (
scsi_disk_status(
scsb_ks_topo.mct_disk[i].fru_unit)) {
case 0:
health = OK;
break;
case 1:
health = NOK;
break;
case -1:
health = UK;
break;
default:
health = NA;
break;
}
log_printf(dgettext(TEXT_DOMAIN,
"%49scondition:%s\n"), BLANK, health, 0);
}
} /* for */
log_printf(dgettext(TEXT_DOMAIN, "\n"), 0);
} /* display_mc_prtdiag_info() */
void
analyze_pcipci_siblings(di_node_t node)
{
di_node_t lc_node;
/* we will find all the dev info for slots first */
lc_node = di_drv_first_node("pci_pci", node);
lc_node = di_child_node(lc_node);
/* we are at "pci" node now */
do {
if (di_walk_node(lc_node, DI_WALK_CLDFIRST,
NULL, analyze_nodes) != 0) {
return;
}
} while ((lc_node = di_sibling_node(lc_node)) != DI_NODE_NIL);
/* now we wll gather info on sysctrl */
lc_node = di_drv_first_node(SCSB_DEV, node);
if (lc_node != DI_NODE_NIL)
analyze_nodes(lc_node, "sysctrl");
} /* analyze_pcipci_siblings(.) */
int
analyze_nodes(di_node_t l_node, void *arg)
{
char *temp;
char *name, *pname;
di_node_t parent;
/*
* we will figure out whether the parent node is "pci" type
* we will save info only in this case as we only want to
* print out the nodes under AP and not others
*/
parent = di_parent_node(l_node);
pname = di_node_name(parent);
name = di_node_name(l_node);
/*
* if this is PCI bridge, we know that this is the AP for slots
* hence, we will save off the address(to convert to slot mapping)
* later, and also we will start saving off slot info struct for
* reporting later
* we will save the immediate childs of this bridge only
*/
if (strcmp(name, "pci") == 0) {
num_devs = 0;
if ((temp = di_bus_addr(l_node)) != NULL) {
mc_slots_data.mc_slot_info[slot_index].slot_addr
= (int)strtol(temp, (char **)NULL, 16);
}
slot_index++;
} else {
if (strcmp(pname, "pci") == 0) {
if ((mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs])
!= NULL) {
(void) strcat(
mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs],
name);
} else {
(void) strcpy(
mc_slots_data.mc_slot_info[slot_index-1].devs_info[num_devs],
name);
} /* if ((mc_slots_data.mc_slot_inf */
num_devs++;
mc_slots_data.mc_slot_info[slot_index-1].number_devs
= num_devs;
} /* if parent is pci */
} /* if node is pci */
if (arg != NULL) {
if (strcmp((char *)arg, "sysctrl") == 0) {
if (dump_prop_list("System", l_node,
di_prop_sys_next)) {
(void) dump_prop_list(NULL, l_node,
di_prop_global_next);
} else {
fail_syssoft_prop =
dump_prop_list(SYSSOFT_PROP,
l_node, di_prop_global_next);
}
fail_drv_prop =
dump_prop_list(DRV_PROP, l_node,
di_prop_drv_next);
/*
* (void) dump_prop_list("Hardware",
* l_node, di_prop_hw_next);
*/
/* dump_priv_data(l_node); */
}
}
return (0);
} /* analyze_nodes(..) */
/*
* To get the slot information,
* The OBP defines the 'slot-table' property. But the OS
* can override it with 'hsc-slot-map' property
* through the .conf file.
* Since the formats are different, 2 different property names
* are chosen.
* The OBP property format is
* <phandle>,<pci-devno>,<phys-slotno>,<ga-bits>
* The OS property format is (ga-bits is not used however)
* <busnexus-path>,<pci-devno>,<phys-slotno>,<ga-bits>
* returns 0 on error, 1 otherwise
*/
int
extract_slot_table_from_obp()
{
if (mc_promopen(O_RDONLY)) {
log_printf(dgettext(TEXT_DOMAIN,
"\ncannot open openprom device"), 0);
return (0);
}
if (mc_next(0) == 0)
return (0);
mc_walk(mc_next(0));
if (close(oprom_fd) < 0) {
log_printf(dgettext(TEXT_DOMAIN,
"\nclose error on %s"), OPENPROMDEV, 0);
return (0);
}
return (1);
} /* extract_slot_table_from_obp() */
int
mc_next(int id)
{
Oppbuf oppbuf;
struct openpromio *opp = &(oppbuf.opp);
bzero(oppbuf.buf, BUFSIZE);
opp->oprom_size = MAXVALSIZE;
opp->oprom_node = id;
if (ioctl(oprom_fd, OPROMNEXT, opp) < 0) {
log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMNEXT"), 0);
return (0);
}
return (opp->oprom_node);
} /* mc_next(.) */
void
mc_walk(int id)
{
int curnode;
mc_dump_node(id);
if (curnode = mc_child(id))
mc_walk(curnode);
if (curnode = mc_next(id))
mc_walk(curnode);
} /* mc_walk(.) */
int
mc_child(int id)
{
Oppbuf oppbuf;
struct openpromio *opp = &(oppbuf.opp);
bzero(oppbuf.buf, BUFSIZE);
opp->oprom_size = MAXVALSIZE;
opp->oprom_node = id;
if (ioctl(oprom_fd, OPROMCHILD, opp) < 0) {
perror("\nOPROMCHILD");
exit(0);
}
return (opp->oprom_node);
} /* mc_child(.) */
/*
* Print all properties and values
*/
void
mc_dump_node(int id)
{
int k;
Oppbuf oppbuf;
hsc_prom_slot_table_t *hpstp;
struct openpromio *opp = &(oppbuf.opp);
/* get first prop by asking for null string */
bzero(oppbuf.buf, BUFSIZE);
for (;;) {
/*
* get next property name
*/
opp->oprom_size = MAXNAMESZ;
if (ioctl(oprom_fd, OPROMNXTPROP, opp) < 0) {
perror("\nOPROMNXTPROP");
return;
}
if (opp->oprom_size == 0)
break;
if (strcmp(opp->oprom_array, "slot-table") == 0) {
if (mc_getpropval(opp) || opp->oprom_size
== (uint_t)-1) {
log_printf(dgettext(TEXT_DOMAIN,
"\ndata not available"), 0);
return;
} else {
slot_table_size =
opp->oprom_size /
sizeof (hsc_prom_slot_table_t);
hpstp =
(hsc_prom_slot_table_t *)opp->oprom_array;
for (k = 0; k < slot_table_size; k++, hpstp++) {
prom_slot_table[k].pslotnum =
hpstp->pslotnum;
prom_slot_table[k].ga =
hpstp->ga;
prom_slot_table[k].pci_devno =
hpstp->pci_devno;
prom_slot_table[k].phandle =
hpstp->phandle;
} /* for (k = 0; k < slot_table_size; k++) */
}
}
}
} /* mc_dump_node(.) */
int
mc_getpropval(struct openpromio *opp)
{
opp->oprom_size = MAXVALSIZE;
if (ioctl(oprom_fd, OPROMGETPROP, opp) < 0) {
log_printf(dgettext(TEXT_DOMAIN, "\nError OPROMGETPROP"), 0);
return (1);
}
return (0);
} /* mc_getpropval(.) */
/*
* This function returns nothing.
*/
void
alarm_card_occupant()
{
int scsb_fd;
scsb_ioc_rdwr_t ioc_read;
uint8_t new_mode = 0;
uint8_t old_mode = 0;
uchar_t reg_index;
if (NULL == scsb_node) {
if (check_platform() == -1) {
return;
}
}
if (version_p15_and_p20 == 1)
reg_index = 0xe9; /* config status reg offset on SCB */
else
reg_index = 0xd7; /* config status reg offset on SCB */
if ((scsb_fd = open(scsb_node, O_RDONLY)) < 0) {
log_printf(dgettext(TEXT_DOMAIN,
"\n%s open failed"), scsb_node, 0);
return;
}
/* save off the old mode */
if (scsb_mode(scsb_fd, GET, &old_mode) == 0)
return;
/* we put scsb in diag mode to read this specific ioctl */
new_mode = ENVCTRL_DIAG_MODE;
if (scsb_mode(scsb_fd, SET, &new_mode) == 0)
return;
/* now lets read the config register */
if (scsb_ioc_reg_read(scsb_fd, reg_index, &ioc_read, 1) == 0)
return;
/* restore the original mode */
if (scsb_mode(scsb_fd, SET, &old_mode) == 0)
return;
alarm_card_present = (BIT_TEST(ioc_read.ioc_rbuf[0]&0xff, 0) ? 1:0);
} /* alarm_card_occupant() */
/*
* This function changes the SCSB mode to the desired one
* 1 on sucess, 0 otherwise
*/
int
scsb_mode(int fd, scsb_op_t sop, uint8_t *new_mode)
{
struct strioctl sioc;
if (sop == GET)
sioc.ic_cmd = ENVC_IOC_GETMODE;
else
sioc.ic_cmd = ENVC_IOC_SETMODE;
sioc.ic_timout = 0;
sioc.ic_len = sizeof (uint8_t);
sioc.ic_dp = (char *)new_mode;
if (ioctl(fd, I_STR, &sioc) == -1) {
log_printf(dgettext(TEXT_DOMAIN,
"\nscsb_mode():scsb ioctl() failed"), 0);
return (0);
}
return (1);
} /* scsb_mode(...) */
/*
* 1 on success, 0 otherwise
*/
int
scsb_ioc_reg_read(int fd, uchar_t index, scsb_ioc_rdwr_t *ioc_rd, int num)
{
struct strioctl sioc;
scsb_ioc_rdwr_t *rdwrp;
rdwrp = ioc_rd;
sioc.ic_timout = 0;
sioc.ic_len = sizeof (scsb_ioc_rdwr_t);
sioc.ic_dp = (char *)rdwrp;
/* setup read command before ioctl */
sioc.ic_cmd = SCSBIOC_REG_READ;
rdwrp->ioc_wlen = 0;
rdwrp->ioc_rlen = num;
rdwrp->ioc_regindex = index;
if (ioctl(fd, I_STR, &sioc) == -1) {
log_printf(dgettext(TEXT_DOMAIN,
"scsb_ioc_reg_read(): scsb ioctl() failed\n"), 0);
return (0);
}
return (1);
} /* scsb_ioc_reg_read(....) */