summaryrefslogtreecommitdiff
path: root/util/isensor.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2014-07-06 18:04:32 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2014-07-06 18:04:32 +0200
commita7f89980e5b3f4b9a74c70dbc5ffe8aabd28be28 (patch)
tree41c4deec1fdfbafd7821b4ca7a9772ac0abd92f5 /util/isensor.c
Imported Upstream version 2.9.3upstream/2.9.3
Diffstat (limited to 'util/isensor.c')
-rw-r--r--util/isensor.c3680
1 files changed, 3680 insertions, 0 deletions
diff --git a/util/isensor.c b/util/isensor.c
new file mode 100644
index 0000000..ac93411
--- /dev/null
+++ b/util/isensor.c
@@ -0,0 +1,3680 @@
+/*
+ * isensor.c
+ *
+ * This tool reads the SDR records to return sensor information.
+ * It can use either the Intel /dev/imb driver or VALinux /dev/ipmikcs.
+ *
+ * Author: arcress at users.sourceforge.net
+ * Copyright (c) 2002-2006 Intel Corporation.
+ * Copyright (c) 2009 Kontron America, Inc.
+ *
+ * 07/25/02 Andy Cress created
+ * 10/09/02 Andy Cress v1.1 added decodeValue(RawToFloat) routine
+ * 10/11/02 Andy Cress v1.2 added expon routine
+ * 10/30/02 Andy Cress v1.3 added SDR types 08 & 14
+ * 12/04/02 Andy Cress v1.4 changed dstatus descriptions
+ * 01/29/03 Andy Cress v1.5 added MV OpenIPMI driver support
+ * Hannes Schulz <schulz@schwaar.com>
+ * 1) correct raw readings to floatval
+ * 2) allow extra SDR bytes returned from HP netserver 1000r
+ * Guo Min <guo.min@intel.com>
+ * add -l option for simpler list display
+ * 02/25/03 Andy Cress v1.6 misc cleanup
+ * 05/02/03 Andy Cress v1.7 add PowerOnHours
+ * 07/28/03 Andy Cress v1.8 added -t option for threshold values,
+ * added sample Discovery routine (unfinished),
+ * added ipmi_getdeviceid for completeness.
+ * 09/05/03 Andy Cress v1.9 show SDR OEM subtypes,
+ * fix GetSDR multi-part get for OEM SDRs
+ * stop if SDR Repository is empty
+ * 09/23/03 Andy Cress v1.10 Add options to set thresholds
+ * 10/14/03 Andy Cress v1.11 Fixed sdr offset for ShowThreshold values
+ * 01/15/04 Andy Cress v1.12 Fixed SetThreshold to set hysteresis,
+ * Fixed sens_cap testing in ShowThresh(Full)
+ * 01/30/04 Andy Cress v1.13 Changed field display order, added header,
+ * check for sdr sz below min, added WIN32.
+ * 02/19/04 Andy Cress v1.14 Added SDR type 3 parsing for mBMC
+ * 02/27/04 Andy Cress v1.15 Added check for superuser, more mBMC logic
+ * 03/11/04 Andy Cress v1.16 Added & removed private mBMC code for set
+ * thresholds due to licensing issues
+ * 04/13/04 Andy Cress v1.17 Added -r to show raw SDRs also
+ * 05/05/04 Andy Cress v1.18 call ipmi_close before exit,
+ * fix sresp in GetSDR for WIN32.
+ * 07/07/04 Andy Cress v1.19 Added -a to reArm sensor,
+ * show debug raw reading values only in hex
+ * 08/18/04 Andy Cress v1.20 Added decoding for DIMM status
+ * 11/01/04 Andy Cress v1.21 add -N / -R for remote nodes,
+ * added -U for remote username
+ * 11/19/04 Andy Cress v1.22 added more decoding for compact reading types,
+ * added -w option to wrap thresholds
+ * 11/24/04 ARCress v1.23 added sens_type to display output
+ * 12/10/04 ARCress v1.24 added support for device sdrs also,
+ * fixed sens_cap byte,
+ * 01/10/05 ARCress v1.25 change ShowThresh order, highest to lowest,
+ * change signed exponent type in RawToFloat
+ * 01/13/05 ARCress v1.26 added time display if fwrap
+ * 01/28/05 ARCress v1.27 mod for Power Redundancy SDR status
+ * 02/15/05 ARCress v1.28 added FloatToRaw for -h/-l threshold set funcs,
+ * always take -n sensor_num as hex (like displayed)
+ * 03/07/05 ARCress v1.29 added "LAN Leash Lost" decoding in decode_comp_
+ * added -v to show max/min & hysteresis.
+ * 03/22/05 ARCress v1.30 added OEM subtype 0x60 for BMC TAM
+ * 03/26/05 ARCress v1.31 added battery type to decode_comp_reading
+ * 04/21/05 ARCress v1.32 added error message if -n sensor_num not found,
+ * added more decoding for Power Redund sensor
+ * 06/20/05 ARCress v1.33 if GetSDRRepository cc=0xc1 switch fdevsdrs mode,
+ * also detect fdevsdrs better for ATCA.
+ * 07/28/05 ARCress v1.34 check for Reading init state,
+ * add extra byte to decode_comp_reading()
+ * 09/12/05 ARCress v1.35 don't check superuser for fipmi_lan
+ * 01/26/06 ARCress v1.36 added -i option to only show one sensor index
+ * 03/14/06 ARCress v1.37 added -p option to save persistent thresholds
+ * 04/06/06 ARCress v1.38 show auto/manual rearm
+ * 07/17/06 ARCress v1.39 add -V, add -L, handle RepInfo rc=0xc1
+ * 11/28/06 ARCress v1.46 added -c -m for ATCA child MCs
+ * 08/15/07 ARCress v1.58 filter display if -n sensor_num
+ * 08/29/07 ARCress v1.59 fixed Battery sensor interpretation
+ * 10/31/07 ARCress v2.3 retry GetSDR if cc=0xC5 (lost reservationID)
+ * 01/14/08 ARCress v2.6 add -u param for setting unique thresholds,
+ * always show float when setting thresholds,
+ * fixup in decoding Proc,PS Comp readings
+ * 01/25/08 ARCress v2.7 allow float input with -u thresholds,
+ * add -p persist logic for -u thresholds.
+ */
+/*M*
+Copyright (c) 2002-2006 Intel Corporation.
+Copyright (c) 2009 Kontron America, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ a.. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ b.. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ c.. Neither the name of Intel nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *M*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h> // for: double pow(double x, double y);
+#include <string.h>
+#include <time.h>
+#ifdef WIN32
+#include <windows.h>
+#include "getopt.h"
+#elif defined(DOS)
+#include <dos.h>
+#include "getopt.h"
+#else
+#include <sys/stat.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#else
+#include <getopt.h>
+#endif
+#endif
+#if defined(LINUX)
+#include <unistd.h>
+#include <sys/types.h>
+#endif
+#include "ipmicmd.h"
+#include "isensor.h"
+
+#define PICMG_CHILD 1 /* show child MCs if -b */
+#define MIN_SDR_SZ 8
+#define SZCHUNK 16 /* SDR chunksize was 8, now 16 */
+#define INIT_SNUM 0xff
+#define N_SGRP 16
+#define THR_EMPTY 999
+
+extern int get_LastError( void ); /* ipmilan.c */
+extern int use_devsdrs(int picmg); /* ipmicmd.c */
+extern int get_MemDesc(int array, int dimm, char *desc, int *psz); /*mem_if.c*/
+extern char *get_sensor_type_desc(uchar stype); /*ievents.c*/
+#ifdef METACOMMAND
+#include "oem_intel.h"
+/* void show_oemsdr_intel(uchar *sdr); in oem_intel.h */
+/* int decode_sensor_intel(); in oem_intel.h */
+/* int is_romley(int vend, int prod); in oem_intel.h */
+extern int decode_sensor_kontron(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_kontron.c*/
+extern int decode_sensor_fujitsu(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_fujitsu.c*/
+extern int decode_sensor_sun(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_sun.c*/
+extern int decode_sensor_supermicro(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_supermicro.c*/
+extern int decode_sensor_quanta(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_quanta.c*/
+extern int decode_sensor_hp(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_hp.c*/
+extern int decode_sensor_dell(uchar *sdr,uchar *reading,char *pstring,
+ int slen); /*see oem_dell.c*/
+extern void show_oemsdr_hp(uchar *sdr);
+#else
+int is_romley(int vend, int prod) {
+ if ((vend == VENDOR_INTEL) && ((prod >= 0x0048) && (prod <= 0x005e)))
+ return(1);
+ return(0);
+}
+int is_thurley(int vend, int prod) {
+ if ((vend == VENDOR_INTEL) && ((prod >= 0x003A) && (prod <= 0x0040)))
+ return(1);
+ return(0);
+}
+#endif
+#ifdef ALONE
+#define NENTID 53
+static char *entity_id_str[NENTID] = {
+/* 00 */ "unspecified",
+/* 01 */ "other",
+/* 02 */ "unknown",
+/* 03 */ "processor",
+/* 04 */ "disk",
+/* 05 */ "peripheral bay",
+/* 06 */ "management module",
+/* 07 */ "system board",
+/* 08 */ "memory module",
+/* 09 */ "processor module",
+/* 10 */ "power supply",
+/* 11 */ "add-in card",
+/* 12 */ "front panel bd",
+/* 13 */ "back panel board",
+/* 14 */ "power system bd",
+/* 15 */ "drive backplane",
+/* 16 */ "expansion board",
+/* 17 */ "Other system board",
+/* 18 */ "processor board",
+/* 19 */ "power unit",
+/* 20 */ "power module",
+/* 21 */ "power distr board",
+/* 22 */ "chassis back panel bd",
+/* 23 */ "system chassis",
+/* 24 */ "sub-chassis",
+/* 25 */ "Other chassis board",
+/* 26 */ "Disk Drive Bay",
+/* 27 */ "Peripheral Bay",
+/* 28 */ "Device Bay",
+/* 29 */ "fan",
+/* 30 */ "cooling unit",
+/* 31 */ "cable/interconnect",
+/* 32 */ "memory device ",
+/* 33 */ "System Mgt Software",
+/* 34 */ "BIOS",
+/* 35 */ "Operating System",
+/* 36 */ "system bus",
+/* 37 */ "Group",
+/* 38 */ "Remote Mgt Comm Device",
+/* 39 */ "External Environment",
+/* 40 */ "battery",
+/* 41 */ "Processing blade",
+/* 43 */ "Processor/memory module",
+/* 44 */ "I/O module",
+/* 45 */ "Processor/IO module",
+/* 46 */ "Mgt Controller Firmware",
+/* 47 */ "IPMI Channel",
+/* 48 */ "PCI Bus",
+/* 49 */ "PCI Express Bus",
+/* 50 */ "SCSI Bus",
+/* 51 */ "SATA/SAS bus",
+/* 52 */ "Processor FSB"
+};
+char *decode_entity_id(int id) {
+ if (id < NENTID) return ("");
+ else return(entity_id_str[id]); }
+#else
+/* char *decode_entity_id(int id); *isensor.h, from ievents.c*/
+#endif
+/************************
+ * Global Data
+ ************************/
+static char *progname = "isensor";
+static char *progver = "2.93";
+#ifdef WIN32
+static char savefile[] = "%ipmiutildir%\\thresholds.cmd";
+#else
+static char savefile[] = "/var/lib/ipmiutil/thresholds.sh";
+// static char savefile[] = "/usr/share/ipmiutil/thresholds.sh";
+#endif
+extern char fdebug; /*from ipmicmd.c*/
+int sens_verbose = 0; /* =1 show max/min & hysteresis also */
+static int fdevsdrs = 0;
+static int fReserveOK = 1;
+static int fDoReserve = 1;
+static int fsimple = 0; /*=1 simple, canonical output*/
+static int fshowthr = 0; /* =1 show thresholds, =2 show thr in ::: fmt */
+static int fwrap = 0;
+static int frawsdr = 0;
+static int frearm = 0;
+static int fshowidx = 0; /* only show a specific SDR index/range */
+static int fshowgrp = 0; /* =1 show group of sensors by sensor type */
+static int fdoloop = 0; /* =1 if user specified number of loops */
+static int fpicmg = 0;
+static int fchild = 0; /* =1 show child SDRs */
+static int fset_mc = 0; /* =1 -m to set_mc */
+static int fdump = 0;
+static int frestore = 0;
+static int fjumpstart = 0;
+static int fgetmem = 0;
+static int fprivset = 0;
+static char fremote = 0;
+static int nloops = 1; /* num times to show repeated sensor readings */
+static char bdelim = BDELIM; /* delimiter for canonical output */
+static char tmpstr[20]; /* temp string */
+static char *binfile = NULL;
+static int fsetthresh = 0;
+static int fsavethresh = 0;
+static uchar sensor_grps[N_SGRP] = {0, 0}; /*sensor type groups*/
+static ushort sensor_idx1 = 0xffff;
+static ushort sensor_idxN = 0xffff;
+static uchar sensor_num = INIT_SNUM;
+static uchar sensor_hi = 0xff;
+static uchar sensor_lo = 0xff;
+static uchar sensor_thr[6] = {0,0,0,0,0,0};
+static double sensor_thrf[6] = {0,0,0,0,0,0};
+static double sensor_hi_f = 0;
+static double sensor_lo_f = 0;
+static int fmBMC = 0;
+static int fRomley = 0;
+static char chEol = '\n'; /* newline by default, space if option -w */
+static uchar resid[2] = {0,0};
+static uchar g_bus = PUBLIC_BUS;
+static uchar g_sa = 0;
+static uchar g_lun = BMC_LUN;
+static uchar g_addrtype = ADDR_SMI;
+static int vend_id = 0;
+static int prod_id;
+
+/* sensor_dstatus
+ * This is used to decode the sensor reading types and meanings.
+ * Use IPMI Table 36-1 and 36-2 for this.
+ */
+#define N_DSTATUS 82
+#define STR_CUSTOM 58
+#define STR_OEM 71
+#define STR_AC_LOST 76
+#define STR_PS_FAIL 77
+#define STR_PS_CONFIG 78
+#define STR_HSC_OFF 79
+#define STR_REBUILDING 80
+#define STR_OTHER 81
+static char oem_string[50] = "OEM";
+static char *sensor_dstatus[N_DSTATUS] = {
+/* 0 00h */ "OK ",
+/* Threshold event states */
+/* 1 01h */ "Warn-lo", // "Warning-lo",
+/* 2 02h */ "Crit-lo", // "Critical-lo",
+/* 3 04h */ "BelowCrit", // "BelowCrit-lo",
+/* 4 08h */ "Warn-hi", // "Warning-hi",
+/* 5 10h */ "Crit-hi", // "Critical-hi",
+/* 6 20h */ "AboveCrit", // "AboveCrit-hi",
+/* 7 40h */ "Init ", /*in init state, no reading*/
+/* 8 80h */ "OK* ",
+/* Hotswap Controller event states, also Availability */
+/* 9 HSC */ "Present", /*present,inserted*/
+/*10 HSC */ "Absent", /*absent,removed,empty,missing*/
+/*11 HSC */ "Ready",
+/*12 HSC */ "Faulty",
+/* Digital/Discrete event states */
+/*13 D-D */ "Asserted",
+/*14 D-D */ "Deassert",
+/*15 D-D */ "Predict ",
+/* Availability event states */
+/*16 Avl */ "Disabled",
+/*17 Avl */ "Enabled ",
+/*18 Avl */ "Redundant",
+/*19 Avl */ "RedunLost",
+/*20 Avl */ "RedunDegr",
+/* ACPI Device Power States */
+/*21 ACPI*/ "Off ",
+/*22 ACPI*/ "Working",
+/*23 ACPI*/ "Sleeping", /*D2/S2*/
+/*24 ACPI*/ "On",
+/* Critical Interrupt event states */
+/*25 CrI */ "FP_NMI ",
+/*26 CrI */ "Bus_TimOut",
+/*27 CrI */ "IOch_NMI",
+/*28 CrI */ "SW_NMI ",
+/*29 CrI */ "PCI_PERR",
+/*30 CrI */ "PCI_SERR",
+/*31 CrI */ "EISA_TimOut",
+/*32 CrI */ "Bus_Warn ", /*Correctable*/
+/*33 CrI */ "Bus_Error", /*Uncorrectable*/
+/*34 CrI */ "Fatal_NMI",
+/*35 CrI */ "Bus_Fatal", /*0x0A*/
+/*36 CrI */ "Bus_Degraded", /*0x0B*/
+/* Physical Security event states */
+/*37 Phys*/ "LanLeashLost",
+/*38 Phys*/ "ChassisIntrus",
+/* Memory states */
+/*39 Mem */ "ECCerror",
+/*40 Mem */ "ParityErr",
+/* Discrete sensor invalid readings (error or init state) */
+/*41 D-D */ "Unknown",
+/*42 D-D */ "NotAvailable",
+/* Discrete sensor OEM reading states */
+/*43 OEM */ "Enabled ",
+/*44 OEM */ "Disabled",
+/* Session Audit states */
+/*45 OEM */ "Activated ",
+/*46 OEM */ "Deactivated",
+/*47 HSC */ "Unused ",
+/* Processor event states */
+/*48 Proc*/ "IERR",
+/*49 Proc*/ "ThermalTrip",
+/*50 Proc*/ "FRB1Failure",
+/*51 Proc*/ "FRB2Failure",
+/*52 Proc*/ "FRB3Failure",
+/*53 Proc*/ "ConfigError",
+/*54 Proc*/ "SMBIOSError",
+/*55 Proc*/ "ProcPresent",
+/*56 Proc*/ "ProcDisabled",
+/*57 Proc*/ "TermPresent",
+/* Custom data string, 15 bytes */
+/*58 Custom*/ "CustomData12345",
+/* Event Log */
+/*59 EvLog*/ "MemLogDisab",
+/*60 EvLog*/ "TypLogDisab",
+/*61 EvLog*/ "LogCleared",
+/*62 EvLog*/ "AllLogDisab",
+/*63 EvLog*/ "SelFull",
+/*64 EvLog*/ "SelNearFull",
+/* more Digital Discrete */
+/*65 D-D */ "Exceeded",
+/*66 Alert*/ "AlertPage",
+/*67 Alert*/ "AlertLAN",
+/*68 Alert*/ "AlertPET",
+/*69 Alert*/ "AlertSNMP",
+/*70 Alert*/ "None",
+/*71 OEM str*/ &oem_string[0],
+/* Version Change */
+/*72 Change*/ "HW Changed",
+/*73 Change*/ "SW Changed",
+/*74 Change*/ "HW incompatibility",
+/*75 Change*/ "Change Error",
+/* Power Supply event states */
+/*76 PS */ "AC_Lost ",
+/*77 PS */ "PS_Failed",
+/* Power Supply event states */
+/*78 PS */ "Config_Err",
+/*79 HSC */ "Offline",
+/*80 HSC */ "Rebuilding",
+/*81 other*/ " _ "
+};
+
+static char *raid_states[9] = { /*for sensor type 0x0d drive status */
+ "Faulty",
+ "Rebuilding",
+ "InFailedArray",
+ "InCriticalArray",
+ "ParityCheck",
+ "PredictedFault",
+ "Un-configured",
+ "HotSpare",
+ "NoRaid" };
+
+#define NSENSTYPES 0x2a
+#ifdef OLD
+/* see ievents.c */
+static const char *sensor_types[NSENSTYPES] = { /*IPMI 2.0 Table 42-3*/
+/* 00h */ "reserved",
+/* 01h */ "Temperature",
+/* 02h */ "Voltage",
+/* 03h */ "Current",
+/* 04h */ "Fan",
+/* 05h */ "Platform Chassis Intrusion",
+/* 06h */ "Platform Security Violation",
+/* 07h */ "Processor",
+/* 08h */ "Power Supply",
+/* 09h */ "Power Unit",
+/* 0Ah */ "Cooling Device",
+/* 0Bh */ "FRU Sensor",
+/* 0Ch */ "Memory",
+/* 0Dh */ "Drive Slot",
+/* 0Eh */ "POST Memory Resize",
+/* 0Fh */ "System Firmware",
+/* 10h */ "SEL Disabled",
+/* 11h */ "Watchdog 1",
+/* 12h */ "System Event", /* offset 0,1,2 */
+/* 13h */ "Critical Interrupt", /* offset 0,1,2 */
+/* 14h */ "Button", /* offset 0,1,2 */
+/* 15h */ "Board",
+/* 16h */ "Microcontroller",
+/* 17h */ "Add-in Card",
+/* 18h */ "Chassis",
+/* 19h */ "Chip Set",
+/* 1Ah */ "Other FRU",
+/* 1Bh */ "Cable / Interconnect",
+/* 1Ch */ "Terminator",
+/* 1Dh */ "System Boot Initiated",
+/* 1Eh */ "Boot Error",
+/* 1Fh */ "OS Boot",
+/* 20h */ "OS Critical Stop",
+/* 21h */ "Slot / Connector",
+/* 22h */ "ACPI Power State",
+/* 23h */ "Watchdog 2",
+/* 24h */ "Platform Alert",
+/* 25h */ "Entity Presence",
+/* 26h */ "Monitor ASIC",
+/* 27h */ "LAN",
+/* 28h */ "Management Subsystem Health",
+/* 29h */ "Battery",
+};
+#endif
+
+#define NUNITS 30
+static char *unit_types[] = {
+/* 00 */ "unspecified",
+/* 01 */ "degrees C",
+/* 02 */ "degrees F",
+/* 03 */ "degrees K",
+/* 04 */ "Volts",
+/* 05 */ "Amps",
+/* 06 */ "Watts",
+/* 07 */ "Joules",
+/* 08 */ "Coulombs",
+/* 09 */ "VA",
+/* 10 */ "Nits",
+/* 11 */ "lumen",
+/* 12 */ "lux",
+/* 13 */ "Candela",
+/* 14 */ "kPa",
+/* 15 */ "PSI",
+/* 16 */ "Newton",
+/* 17 */ "CFM",
+/* 18 */ "RPM",
+/* 19 */ "Hz",
+/* 20 */ "microseconds",
+/* 21 */ "milliseconds",
+/* 22 */ "seconds",
+/* 23 */ "minutes",
+/* 24 */ "hours",
+/* 25 */ "days",
+/* 26 */ "weeks",
+/* 27 */ "mil",
+/* 28 */ "inches",
+/* 29 */ "feet",
+/* 42 */ "cycles"
+};
+/* 68 * "megabit", */
+/* 72 * "megabyte", */
+/* 90 * "uncorrectable error" (last defined)*/
+static char *unit_types_short[] = {
+/* 00 */ "?", /*unknown, not specified*/
+/* 01 */ "C",
+/* 02 */ "F",
+/* 03 */ "K",
+/* 04 */ "V",
+/* 05 */ "A",
+/* 06 */ "W",
+/* 07 */ "J",
+/* 08 */ "Coul",
+/* 09 */ "VA",
+/* 10 */ "Nits",
+/* 11 */ "lumen",
+/* 12 */ "lux",
+/* 13 */ "Cand",
+/* 14 */ "kPa",
+/* 15 */ "PSI",
+/* 16 */ "Newton",
+/* 17 */ "CFM",
+/* 18 */ "RPM",
+/* 19 */ "Hz",
+/* 20 */ "usec",
+/* 21 */ "msec",
+/* 22 */ "sec",
+/* 23 */ "min",
+/* 24 */ "hrs",
+/* 25 */ "days",
+/* 26 */ "wks",
+/* 27 */ "mil",
+/* 28 */ "in",
+/* 29 */ "ft",
+/* 42 */ "cyc"
+};
+
+ushort parse_idx(char *str)
+{
+ int i, n;
+ char istr[5];
+ if (strncmp(str,"0x",2) == 0) str += 2;
+ n = strlen_(str);
+ if (n == 4) {
+ i = (htoi(str) << 8) + htoi(&str[2]);
+ } else if (n == 3) {
+ istr[0] = '0';
+ memcpy(&istr[1],str,3);
+ i = (htoi(istr) << 8) + htoi(&istr[2]);
+ } else i = htoi(str); /*was atoi()*/
+ printf("idx = 0x%x\n",i);
+ return((ushort)i);
+}
+
+int get_idx_range(char *str)
+{
+ // int i = 0;
+ char *p;
+ p = strchr(str,'-');
+ if (p == NULL) p = strchr(str,',');
+ if (p != NULL) {
+ *p = 0;
+ p++;
+ sensor_idx1 = parse_idx(str);
+ sensor_idxN = parse_idx(p);
+ } else {
+ sensor_idx1 = parse_idx(str);
+ sensor_idxN = sensor_idx1;
+ }
+ return(0);
+}
+
+char *get_unit_type(int iunits, int ibase, int imod, int fshort)
+{
+ char *pstr = NULL;
+ char **punittypes;
+ static char unitstr[32];
+ int jbase, jmod;
+ uchar umod;
+
+ punittypes = unit_types;
+ if (fshort) punittypes = unit_types_short;
+ if (fdebug) printf("get_unit_type(%x,%d,%d,%d)\n",iunits,ibase,imod,fshort);
+ umod = (iunits & 0x06) >> 1;
+ if (ibase < NUNITS) jbase = ibase;
+ else {
+ if (fdebug) printf("units base %02x > %d\n",ibase,NUNITS);
+ if (ibase == 42) jbase = NUNITS; /*"cycles"*/
+ else jbase = 0;
+ }
+ if (imod < NUNITS) jmod = imod;
+ else {
+ if (fdebug) printf("units mod %02x > %d\n",imod,NUNITS);
+ jmod = 0;
+ }
+ switch (umod) {
+ case 2:
+ snprintf(unitstr,sizeof(unitstr),"%s * %s",
+ punittypes[jbase],punittypes[jmod]);
+ pstr = unitstr;
+ break;
+ case 1:
+ snprintf(unitstr,sizeof(unitstr),"%s/%s",
+ punittypes[jbase],punittypes[jmod]);
+ pstr = unitstr;
+ break;
+ case 0:
+ default:
+ pstr = punittypes[jbase];
+ break;
+ }
+ if ((umod == 0) && (iunits > 0)) {
+ /* special cases for other SensorUnits1 bits */
+ if ((iunits & 0x01) != 0) { /*percentage*/
+ if (fshort) pstr = "%";
+ else pstr = "percent";
+ } else if (iunits == 0xC0) { /*no analog reading*/
+ pstr = "na";
+ } else if (iunits == 0x18) {
+ /* For Tyan fans: base=42, units=24.(0x18) -> cycles/hour */
+ snprintf(unitstr,sizeof(unitstr),"%s/hour",punittypes[jbase]);
+ pstr = unitstr;
+ }
+ }
+ return(pstr);
+}
+
+char *decode_capab(uchar c)
+{
+ static char cstr[50];
+ char *arm;
+ char *thr;
+ char *evt;
+ // char *hys;
+ uchar b;
+ /* decode sens_capab bits */
+ if ((c & 0x40) == 0) arm = "man"; /*manual rearm*/
+ else arm = "auto"; /*automatic rearm*/
+ /* skip hysteresis bits (0x30) */
+ b = ((c & 0x0c) >> 2);
+ switch(b) {
+ case 0x00: thr = "none"; break; /*no thresholds*/
+ case 0x01: thr = "read"; break;
+ case 0x02: thr = "write"; break; /*read & write*/
+ case 0x03:
+ default: thr = "fixed"; break;
+ }
+ b = (c & 0x03) ;
+ switch(b) {
+ case 0x00: evt = "state"; break; /*threshold or discrete state*/
+ case 0x01: evt = "entire"; break; /*entire sensor only*/
+ case 0x02: evt = "disab"; break; /*global disable only*/
+ case 0x03:
+ default: evt = "none"; break; /*no events*/
+ }
+ sprintf(cstr,"arm=%s thr=%s evts=%s",arm,thr,evt);
+ return(cstr);
+}
+
+
+int get_group_id(char *pstr)
+{
+ int i, j, n, sz, len;
+ char *p;
+ int rv = -1;
+
+ sz = strlen_(pstr);
+ p = &pstr[0];
+ n = 0;
+ for (i = 0; i <= sz; i++) {
+ if (n >= N_SGRP) break;
+ switch(pstr[i]) {
+ case ',': /*delimiter*/
+ case '\n':
+ case '\0':
+ pstr[i] = 0; /*stringify this word*/
+ len = strlen_(p);
+ for (j = 0; j < NSENSTYPES; j++) {
+ if (strncasecmp(get_sensor_type_desc(j),p,len) == 0) {
+ sensor_grps[n++] = (uchar)j;
+ rv = 0;
+ break;
+ }
+ } /*endfor(j)*/
+ if (i+1 < sz) p = &pstr[i+1]; /*set p for next word*/
+ if (j >= NSENSTYPES) { /* sensor type not found */
+ rv = -1;
+ i = sz; /*exit loop*/
+ }
+ break;
+ default:
+ break;
+ } /*end switch*/
+ } /*end for(i)*/
+ if (rv == 0) rv = n;
+ else rv = -1;
+ return(rv);
+}
+
+static int validate_thresholds(void *pthrs, char flag, uchar *sdr)
+{
+ double *thrf;
+ uchar *thr;
+ int rv = 0;
+ uchar bits;
+
+ if (sdr == NULL) bits = 0xff; /*assume all are used*/
+ else bits = sdr[18]; /*18=indicates which are readable/used */
+
+ if (bits == 0) {
+ printf("No threshold values can be set for this sensor.\n");
+ return(3);
+ }
+ if (flag == 1) { /*float*/
+ thrf = (double *)pthrs;
+ if (fdebug)
+ printf("validate_thresh: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n",
+ bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]);
+ if ((bits & 0x02) != 0) { /*thrf[1] lo-crit is valid*/
+ if ((thrf[1] > thrf[0]) && ((bits & 0x01) != 0)) rv = 1;
+ if ((thrf[2] > thrf[1]) && ((bits & 0x04) != 0)) rv = 1; /*lo is wrong*/
+ }
+ if ((bits & 0x10) != 0) { /*thrf[4] hi-crit is valid*/
+ if ((thrf[4] < thrf[3]) && ((bits & 0x08) != 0)) rv = 2;
+ if ((thrf[5] < thrf[4]) && ((bits & 0x20) != 0)) rv = 2; /*hi is wrong*/
+ }
+ if (rv != 0) {
+ printf("Threshold values: %f>=%f>=%f, %f<=%f<=%f\n",
+ thrf[0], thrf[1], thrf[2], thrf[3], thrf[4], thrf[5]);
+ printf("Invalid threshold order in %s range.\n",
+ ((rv == 1)? "lo": "hi"));
+ }
+ } else {
+ thr = (uchar *)pthrs;
+ if ((bits & 0x02) != 0) { /*thr[1] lo-crit is valid*/
+ if ((thr[1] > thr[0]) && ((bits & 0x01) != 0)) rv = 1;
+ if ((thr[2] > thr[1]) && ((bits & 0x04) != 0)) rv = 1; /*lo is wrong*/
+ }
+ if ((bits & 0x10) != 0) { /*thr[4] hi-crit is valid*/
+ if ((thr[4] < thr[3]) && ((bits & 0x08) != 0)) rv = 2;
+ if ((thr[5] < thr[4]) && ((bits & 0x20) != 0)) rv = 2; /*hi is wrong*/
+ }
+ if (rv != 0) {
+ printf("Threshold values: %02x>=%02x>=%02x %02x<=%02x<=%02x\n",
+ thr[0], thr[1], thr[2], thr[3], thr[4], thr[5]);
+ printf("Invalid threshold order within -u (%s)\n",
+ ((rv == 1)? "lo": "hi"));
+ }
+ }
+ return(rv);
+}
+
+int
+GetSDRRepositoryInfo(int *nret, int *fdev)
+{
+ uchar resp[MAX_BUFFER_SIZE];
+ int sresp = MAX_BUFFER_SIZE;
+ int rc;
+ int nSDR;
+ int freespace;
+ ushort cmd;
+ uchar cc = 0;
+ int i;
+
+ memset(resp,0,6); /* init first part of buffer */
+ if (nret != NULL) *nret = 0;
+ if (fdev != NULL) fdevsdrs = *fdev;
+ if (fdevsdrs) cmd = GET_DEVSDR_INFO;
+ else cmd = GET_SDR_REPINFO;
+ rc = ipmi_cmd_mc(cmd, NULL, 0, resp,&sresp, &cc, fdebug);
+ if (fdebug) printf("ipmi_cmd[%04x] repinf(%d) status=%d cc=%x\n",
+ cmd, fdevsdrs,rc,cc);
+ /* some drivers return cc in rc */
+ if ((rc == 0xc1) || (rc == 0xd4)) cc = rc;
+ else if (rc != 0) return(rc);
+ if (cc != 0) {
+ if ((cc == 0xc1) || /*0xC1 (193.) means unsupported command */
+ (cc == 0xd4)) /*0xD4 means insufficient privilege (Sun/HP)*/
+ {
+ /* Must be reporting wrong bit for fdevsdrs,
+ * so switch & retry */
+ if (fdevsdrs) {
+ fdevsdrs = 0;
+ cmd = GET_SDR_REPINFO;
+ } else {
+ fdevsdrs = 1;
+ cmd = GET_DEVSDR_INFO;
+ }
+ sresp = MAX_BUFFER_SIZE;
+ rc = ipmi_cmd_mc(cmd, NULL, 0, resp,&sresp, &cc, fdebug);
+ if (fdebug)
+ printf("ipmi_cmd[%04x] repinf status=%d cc=%x\n",cmd,rc,cc);
+ if (rc != ACCESS_OK) return(rc);
+ if (cc != 0) return(cc);
+ } else return(cc);
+ }
+
+ if (fdevsdrs) {
+ nSDR = resp[0];
+ freespace = 1;
+ fReserveOK = 1;
+ } else {
+ nSDR = resp[1] + (resp[2] << 8);
+ freespace = resp[3] + (resp[4] << 8);
+ if ((resp[13] & 0x02) == 0) fReserveOK = 0;
+ else fReserveOK = 1;
+ }
+ if (nret != NULL) *nret = nSDR;
+ if (fdev != NULL) *fdev = fdevsdrs;
+ if (fdebug) {
+ //successful, show data
+ printf("SDR Repository (len=%d): ",sresp);
+ for (i = 0; i < sresp; i++) printf("%02x ",resp[i]);
+ printf("\n");
+ printf("SDR Info: fdevsdrs=%d nSDRs=%d free space = %x ReserveOK=%d\n",
+ fdevsdrs,nSDR,freespace,fReserveOK);
+ }
+
+ return(0);
+} /*end GetSDRRepositoryInfo()*/
+
+
+int
+GetSensorThresholds(uchar sens_num, uchar *thr_data)
+{
+ uchar resp[MAX_BUFFER_SIZE];
+ int sresp = MAX_BUFFER_SIZE;
+ uchar inputData[6];
+ int rc;
+ uchar cc = 0;
+
+ inputData[0] = sens_num;
+ rc = ipmi_cmd_mc(GET_SENSOR_THRESHOLD, inputData,1, resp,&sresp, &cc,fdebug);
+ if (fdebug)
+ printf("GetSensorThreshold[%02x] rc = %d, resp(%d) %02x %02x %02x %02x %02x %02x %02x\n",
+ sens_num,rc, sresp,resp[0],resp[1],resp[2],resp[3],
+ resp[4],resp[5],resp[6]);
+ if (rc != ACCESS_OK) return(rc);
+ if (cc != 0) return(cc);
+ if (sresp == 0) return(-2);
+ memcpy(thr_data,resp,sresp);
+ return(0);
+}
+
+int
+RearmSensor(uchar sens_num)
+{
+ uchar resp[MAX_BUFFER_SIZE];
+ int sresp = MAX_BUFFER_SIZE;
+ uchar inputData[8];
+ int rc;
+ uchar cc = 0;
+
+ memset(inputData,0,6);
+ memset(resp,0,6);
+ inputData[0] = sens_num;
+ rc = ipmi_cmd_mc(GET_SEVT_ENABLE, inputData, 1, resp,&sresp, &cc, fdebug);
+ if (rc == 0 && cc != 0) rc = cc;
+ if (rc != 0 || fdebug)
+ printf("GetSensorEventEnable(%02x) rc = %d, cc = %x %02x %02x %02x\n",
+ sens_num,rc,cc,resp[0],resp[1],resp[3]);
+ if (rc == 0 && resp[0] != 0xc0) {
+ printf("EventEnable(%02x) = %02x, is not 0xc0\n",
+ sens_num,resp[0]);
+ memset(inputData,0,6);
+ inputData[0] = sens_num;
+ inputData[1] = resp[0] | 0xc0;
+ inputData[2] = resp[1];
+ inputData[3] = resp[2];
+ inputData[4] = resp[3];
+ inputData[5] = resp[4];
+ rc = ipmi_cmd_mc(SET_SEVT_ENABLE, inputData, 6, resp,&sresp,
+ &cc, fdebug);
+ if (rc == 0 && cc != 0) rc = cc;
+ if (rc != 0 || fdebug)
+ printf("SetSensorEventEnable(%02x) rc = %d, cc = %x\n",
+ sens_num,rc,cc);
+ }
+
+ memset(inputData,0,6);
+ inputData[0] = sens_num;
+ inputData[1] = 0; /* rearm all events for this sensor */
+ rc = ipmi_cmd_mc(REARM_SENSOR, inputData, 6, resp,&sresp, &cc, fdebug);
+ if (fdebug)
+ printf("RearmSensor(%02x) rc = %d, cc = %x %02x %02x\n",
+ sens_num,rc,cc,resp[0],resp[1]);
+ if (rc == 0 && cc != 0) rc = cc;
+
+ /* Could also do a global rearm via SetEventReceiver. */
+
+ return(rc);
+} /*end RearmSensor*/
+
+int
+SetSensorThresholds(uchar sens_num, uchar hi, uchar lo,
+ uchar *thr_data, uchar *thr_set)
+{
+ uchar resp[MAX_BUFFER_SIZE];
+ int sresp = MAX_BUFFER_SIZE;
+ uchar inputData[8];
+ int rc;
+ uchar cc = 0;
+ uchar sets = 0;
+ int i;
+
+ /*
+ * Set the sensor Hysteresis before setting the threshold.
+ */
+ memset(inputData,0,8);
+ inputData[0] = sens_num;
+ inputData[1] = 0xff;
+ rc = ipmi_cmd_mc(GET_SENSOR_HYSTERESIS,inputData,2, resp,&sresp, &cc,fdebug);
+ if (fdebug)
+ printf("GetSensorHysteresis(%02x) rc = %d, cc = %x %02x %02x\n",
+ sens_num,rc,cc,resp[0],resp[1]);
+ if (rc != ACCESS_OK) return(rc);
+ inputData[0] = sens_num;
+ inputData[1] = 0xff;
+ inputData[2] = resp[0];
+ inputData[3] = resp[1];
+ rc = ipmi_cmd_mc(SET_SENSOR_HYSTERESIS,inputData,4, resp,&sresp, &cc,fdebug);
+ if (fdebug)
+ printf("SetSensorHysteresis(%02x) rc = %d, cc = %x\n",
+ sens_num,rc,cc);
+ if (rc != ACCESS_OK) return(rc);
+
+ /*
+ * The application should validate that values are ordered,
+ * e.g. upper critical should be greater than upper
+ * non-critical.
+ * Due to the limited command line parameter interface,
+ * use the hi & lo values to set each of the thresholds.
+ * For a full implemenation, these thresholds should be set
+ * individually.
+ */
+ memset(inputData,0,8);
+ inputData[0] = sens_num;
+ sets = thr_data[0];
+ if (thr_set != NULL) { /* use specific thr_set values */
+ memcpy(&inputData[2],thr_set,6);
+ } else { /*default, use hi/lo params */
+ if (lo == 0xff) sets &= 0x38; /* don't set lowers */
+ else {
+ inputData[2] = lo; /* lower non-crit (& 0x01) */
+ inputData[3] = lo - 1; /* lower critical (& 0x02) */
+ inputData[4] = lo - 2; /* lower non-recov (& 0x04) */
+ }
+ if (hi == 0xff) sets &= 0x07; /* don't set uppers */
+ else {
+ inputData[5] = hi; /* upper non-crit (& 0x08) */
+ inputData[6] = hi + 1; /* upper critical (& 0x10) */
+ inputData[7] = hi + 2; /* upper non-recov (& 0x20) */
+ }
+ }
+ inputData[1] = sets; /* which ones to set */
+ { /* show from/to changes */
+ printf("GetThreshold[%02x]: %02x ",sens_num,sens_num);
+ for (i = 0; i < 7; i++) printf("%02x ",thr_data[i]);
+ printf("\n");
+ printf("SetThreshold[%02x]: ",sens_num);
+ for (i = 0; i < 8; i++) printf("%02x ",inputData[i]);
+ printf("\n");
+ }
+ rc = ipmi_cmd_mc(SET_SENSOR_THRESHOLD, inputData, 8, resp,&sresp, &cc, fdebug);
+ if (fdebug)
+ printf("SetSensorThreshold(%02x) rc = %d, cc = %x\n",
+ sens_num,rc,cc);
+ if (rc == 0 && cc != 0) rc = cc;
+ /* mBMC gets cc = 0xD5 (213.) here, setting thresholds disabled. */
+ return(rc);
+}
+
+int
+GetSensorReading(uchar sens_num, void *psdr, uchar *sens_data)
+{
+ uchar resp[MAX_BUFFER_SIZE];
+ int sresp = MAX_BUFFER_SIZE;
+ uchar inputData[6];
+ SDR02REC *sdr = NULL;
+ int mc;
+ int rc;
+ uchar cc = 0;
+ uchar lun = 0;
+ uchar chan = 0;
+
+ if (psdr != NULL) {
+ sdr = (SDR02REC *)psdr;
+ mc = sdr->sens_ownid;
+ if (mc != BMC_SA) { /* not BMC, e.g. HSC or ME sensor */
+ uchar a = ADDR_IPMB;
+ if (mc == HSC_SA) a = ADDR_SMI;
+ chan = (sdr->sens_ownlun & 0xf0) >> 4;
+ lun = (sdr->sens_ownlun & 0x03);
+ ipmi_set_mc(chan,(uchar)mc, lun,a);
+ }
+ } else mc = BMC_SA;
+ inputData[0] = sens_num;
+ rc = ipmi_cmd_mc(GET_SENSOR_READING,inputData,1, resp,&sresp,&cc,fdebug);
+ if (fdebug)
+ printf("GetSensorReading mc=%x,%x,%x status=%d cc=%x sz=%d resp: %02x %02x %02x %02x\n",
+ chan,mc,lun,rc,cc,sresp,resp[0],resp[1],resp[2],resp[3]);
+ if (mc != BMC_SA) ipmi_restore_mc();
+ if ((rc == 0) && (cc != 0)) {
+ if (fdebug) printf("GetSensorReading error %x %s\n",cc,
+ decode_cc((ushort)0,(uchar)cc));
+ rc = cc;
+ }
+ if (rc != 0) return(rc);
+
+ if (resp[1] & 0x20) { /* init state, reading invalid */
+ if (fdebug)
+ printf("sensor[%x] in init state, no reading\n", sens_num);
+ sens_data[1] = resp[1];
+ sens_data[2] = 0x40; /*set bit num for init state*/
+ } else { /*valid reading, copy it*/
+ /* only returns 4 bytes, no matter what type */
+ memcpy(sens_data,resp,4);
+ }
+ return(0);
+} /*end GetSensorReading()*/
+
+int
+GetSensorReadingFactors(uchar snum, uchar raw, int *m, int *b, int * b_exp,
+ int *r, int *a)
+{
+ uchar resp[MAX_BUFFER_SIZE];
+ int sresp = MAX_BUFFER_SIZE;
+ uchar inputData[6];
+ int rc;
+ uchar cc = 0;
+ int toler, a_exp;
+
+ inputData[0] = snum;
+ inputData[1] = raw;
+ rc = ipmi_cmd_mc(GET_SENSOR_READING_FACTORS, inputData, 2,
+ resp,&sresp, &cc, fdebug);
+ if (fdebug) printf("GetSensorReadingFactors status = %d\n",rc);
+ if (rc != ACCESS_OK) return(rc);
+ if (cc != 0) return(cc);
+
+ /* successful, copy values */
+ *m = resp[1] + ((resp[2] & 0xc0) << 2);
+ toler = resp[2] & 0x3f;
+ *b = resp[3] + ((resp[4] & 0xc0) << 2);
+ *a = (resp[4] & 0x3f) + ((resp[5] & 0xf0) << 4);
+ a_exp = (resp[5] & 0xc0) >> 2;
+ *r = (resp[6] &0xf0) >> 4;
+ *b_exp = resp[6] & 0x0f;
+ if (fdebug) {
+ printf("factors: next=%x m=%d b=%d b_exp=%d a=%d a_exp=%d r=%d\n",
+ resp[0],*m,*b,*b_exp,*a,a_exp,*r);
+ }
+ return(0);
+}
+
+int GetSensorType(uchar snum, uchar *stype, uchar *rtype)
+{
+ uchar resp[MAX_BUFFER_SIZE];
+ int sresp = MAX_BUFFER_SIZE;
+ uchar inputData[6];
+ int rc;
+ uchar cc = 0;
+
+ inputData[0] = snum;
+ rc = ipmi_cmd_mc(GET_SENSOR_TYPE, inputData, 1,
+ resp,&sresp, &cc, fdebug);
+ if (fdebug) printf("GetSensorType: ipmi_cmd rv = %d, cc = %x\n",rc,cc);
+ if (rc != ACCESS_OK) return(rc);
+ if (cc != 0) return(cc);
+ /* successful, copy values */
+ if (stype != NULL) *stype = resp[0];
+ if (rtype != NULL) *rtype = resp[1] & 0x7f;
+ return(rc);
+}
+
+void set_reserve(int val)
+{
+ fDoReserve = val;
+}
+
+int sdr_get_reservation(uchar *res_id, int fdev)
+{
+ int sresp;
+ uchar resp[MAX_BUFFER_SIZE];
+ uchar cc = 0;
+ ushort cmd;
+ int rc = -1;
+
+ if (fDoReserve == 1) {
+ fDoReserve = 0; /* only reserve SDR the first time */
+ sresp = sizeof(resp);;
+ if (fdev) cmd = RESERVE_DEVSDR_REP;
+ else cmd = RESERVE_SDR_REP;
+ rc = ipmi_cmd_mc(cmd, NULL, 0, resp, &sresp, &cc, fdebug);
+ if (rc == 0 && cc != 0) rc = cc;
+ if (rc == 0) { /* ok, so set the reservation id */
+ resid[0] = resp[0];
+ resid[1] = resp[1];
+ }
+ /* A reservation is cancelled by the next reserve request. */
+ if (fdebug)
+ printf("ipmi_cmd RESERVE status=%d cc=%x id=%02x%02x\n",
+ rc,cc,resid[0],resid[1]);
+ } else rc = 0;
+ /* if not first time, or if error, return existing resid. */
+ res_id[0] = resid[0];
+ res_id[1] = resid[1];
+ return(rc);
+} /*end sdr_get_reservation*/
+
+int sdr_clear_repo(int fdev)
+{
+ int sresp;
+ uchar resp[MAX_BUFFER_SIZE];
+ uchar inputData[6];
+ uchar cc = 0;
+ int rc = -1;
+ ushort cmd;
+ uchar resv[2] = {0,0};
+
+ if (fReserveOK)
+ rc = sdr_get_reservation(resv,fdev);
+
+ cmd = 0x27 + (NETFN_STOR << 8); /*Clear SDR Repository*/
+ inputData[0] = resv[0]; /*res id LSB*/
+ inputData[1] = resv[1]; /*res id MSB*/
+ inputData[2] = 'C';
+ inputData[3] = 'L';
+ inputData[4] = 'R';
+ inputData[5] = 0xAA;
+ sresp = sizeof(resp);;
+ rc = ipmi_cmd_mc(cmd, inputData, 6, resp, &sresp,&cc, fdebug);
+ if (fdebug) printf("sdr_clear_repo: rc = %d, cc = %x, sz=%d\n",rc,cc,sresp);
+ if (rc == 0 && cc != 0) rc = cc;
+
+ if (rc == 0 && (resp[0] & 1) != 1) {
+ if (fdebug) printf("Wait for sdr_clear_repo to complete\n");
+ os_usleep(1,0);
+ }
+ return(rc);
+}
+
+int sdr_add_record(uchar *sdr, int fdev)
+{
+ int sresp;
+ uchar resp[MAX_BUFFER_SIZE];
+ uchar inputData[6+SZCHUNK];
+ uchar cc = 0;
+ int rc = -1;
+ ushort cmd;
+ uchar resv[2] = {0,0};
+ int reclen, len, i;
+ int recid, chunksz;
+ uchar prog;
+
+ reclen = sdr[4] + 5;
+ recid = sdr[0] + (sdr[1] << 8);
+ /* OEM SDRs can be min 8 bytes, less is an error. */
+ if (reclen < 8) return(LAN_ERR_BADLENGTH);
+ if (fReserveOK)
+ rc = sdr_get_reservation(resv,fdev);
+ if (fdebug) printf("sdr_add_record[%x]: reclen = %d, reserve rc = %d\n",
+ recid,reclen,rc);
+
+ cmd = 0x25 + (NETFN_STOR << 8); /*PartialAddSdr*/
+ recid = 0; /*first chunk must be added as 0000*/
+ chunksz = SZCHUNK;
+ for (i = 0; i < reclen; )
+ {
+ prog = 0;
+ len = chunksz;
+ if ((i+chunksz) >= reclen) { /*last record*/
+ len = reclen - i;
+ prog = 1;
+ }
+ inputData[0] = resv[0]; /*res id LSB*/
+ inputData[1] = resv[1]; /*res id MSB*/
+ inputData[2] = recid & 0x00ff; /*record id LSB*/
+ inputData[3] = (recid >> 8) & 0x00ff; /*record id MSB*/
+ inputData[4] = (uchar)i; /*offset */
+ inputData[5] = prog; /*progress: 1=last record*/
+ memcpy(&inputData[6],&sdr[i],len);
+ sresp = sizeof(resp);
+ rc = ipmi_cmd_mc(cmd, inputData, 6+len, resp, &sresp,&cc, fdebug);
+ if (fdebug)
+ printf("sdr_add_record[%x,%x]: rc = %d, cc = %x, sz=%d\n",
+ recid,i,rc,cc,sresp);
+ if (rc == 0 && cc != 0) rc = cc;
+ if (rc != 0) break;
+ if (recid == 0 && rc == 0) /*first time, so set recid*/
+ recid = resp[0] + (resp[1] << 8);
+ i += len;
+ }
+ return(rc);
+}
+
+int GetSDR(int r_id, int *r_next, uchar *recdata, int srecdata, int *rlen)
+{
+ int sresp;
+ uchar resp[MAX_BUFFER_SIZE+SZCHUNK];
+ uchar respchunk[SZCHUNK+10];
+ uchar inputData[6];
+ uchar cc = 0;
+ int rc = -1;
+ int i, chunksz, thislen, off;
+ int reclen;
+ ushort cmd;
+ uchar resv[2] = {0,0};
+
+ chunksz = SZCHUNK;
+ reclen = srecdata; /*max size of SDR record*/
+ off = 0;
+ *rlen = 0;
+ *r_next = 0xffff; /*default*/
+ if (fReserveOK)
+ rc = sdr_get_reservation(resv,fdevsdrs);
+ if (fdevsdrs) cmd = GET_DEVICE_SDR;
+ else cmd = GET_SDR;
+ if (reclen == 0xFFFF) { /* get it all in one call */
+ inputData[0] = resv[0]; /*res id LSB*/
+ inputData[1] = resv[1]; /*res id MSB*/
+ inputData[2] = r_id & 0x00ff; /*record id LSB*/
+ inputData[3] = (r_id & 0xff00) >> 8; /*record id MSB*/
+ inputData[4] = 0; /*offset */
+ inputData[5] = 0xFF; /*bytes to read, ff=all*/
+ sresp = sizeof(resp);;
+ if (fdebug) printf("ipmi_cmd SDR id=%d read_all, len=%d\n",
+ r_id,sresp);
+ rc = ipmi_cmd_mc(cmd, inputData, 6, recdata, &sresp,&cc, fdebug);
+ /* This will usually return cc = 0xCA (invalid length). */
+ if (fdebug) printf("ipmi_cmd SDR data status = %d, cc = %x, sz=%d\n",
+ rc,cc,sresp);
+ reclen = sresp;
+ *r_next = recdata[0] + (recdata[1] << 8);
+ } else /* if (reclen > chunksz) do multi-part chunks */
+ for (off = 0; off < reclen; )
+ {
+ thislen = chunksz;
+ if ((off+chunksz) > reclen) thislen = reclen - off;
+ inputData[0] = resv[0]; /*res id LSB*/
+ inputData[1] = resv[1]; /*res id MSB*/
+ inputData[2] = r_id & 0x00ff; /*record id LSB*/
+ inputData[3] = (r_id & 0xff00) >> 8; /*record id MSB*/
+ inputData[4] = (uchar)off; /*offset */
+ inputData[5] = (uchar)thislen; /*bytes to read, ff=all*/
+ sresp = sizeof(respchunk);
+ rc = ipmi_cmd_mc(cmd, inputData, 6, respchunk, &sresp,&cc, fdebug);
+ if (fdebug)
+ printf("ipmi_cmd SDR[%x] off=%d ilen=%d status=%d cc=%x sz=%d\n",
+ r_id,off,thislen,rc,cc,sresp);
+ if (off == 0 && cc == 0xCA && thislen == SZCHUNK) {
+ /* maybe shorter than SZCHUNK, try again */
+ chunksz = 0x06;
+ if (fdebug) printf("sdr[%x] try again with chunksz=%d\n",
+ r_id,chunksz);
+ continue;
+ }
+ if (off > chunksz) {
+ /* already have first part of the SDR, ok to truncate */
+ if (rc == -3) { /* if LAN_ERR_RECV_FAIL */
+ if (fdebug) printf("sdr[%x] error rc=%d len=%d truncated\n",
+ r_id,rc,sresp);
+ sresp = 0;
+ rc = 0;
+ }
+ if (cc == 0xC8 || cc == 0xCA) { /* length errors */
+ /* handle certain MCs that report wrong length,
+ * at least use what we already have (sresp==0) */
+ if (fdebug) printf("sdr[%x] error cc=%02x len=%d truncated\n",
+ r_id,cc,sresp);
+ cc = 0;
+ }
+ }
+ if (rc != ACCESS_OK) return(rc);
+ if (cc != 0) return(cc);
+ /* if here, successful, chunk was read */
+ if (sresp < (thislen+2)) {
+ /* There are some SDRs that may report the wrong length, and
+ * return less bytes than they reported, so just truncate. */
+ if (fdebug) printf("sdr[%x] off=%d, expected %d, got %d\n",
+ r_id,off,thislen+2,sresp);
+ if (sresp >= 2) thislen = sresp - 2;
+ else thislen = 0;
+ reclen = off + thislen; /* truncate, stop reading */
+ }
+ /* successful */
+ memcpy(&resp[off],&respchunk[2],thislen);
+ if (off == 0 && sresp >= 5) {
+ *r_next = respchunk[0] + (respchunk[1] << 8);
+ reclen = respchunk[6] + 5; /*get actual record size*/
+ if (reclen > srecdata) {
+ if (fdebug) printf("sdr[%x] chunk0, reclen=%d srecdata=%d\n",
+ r_id, reclen, srecdata);
+ reclen = srecdata; /*truncate*/
+ }
+ }
+ off += thislen;
+ *rlen = off;
+ }
+ if (fdebug) {
+ printf("GetSDR[%04x] next=%x (len=%d): ",r_id,*r_next,reclen);
+ for (i = 0; i < reclen; i++) printf("%02x ",resp[i]);
+ printf("\n");
+ }
+ memcpy(recdata,&resp[0],reclen);
+ *rlen = reclen;
+ return(rc);
+} /*end GetSDR*/
+
+static int nsdrs = 0; /*number of sdrs*/
+static int sz_sdrs = 0; /*actual size used with sdrs*/
+static uchar *psdrcache = NULL;
+
+void free_sdr_cache(uchar *ptr)
+{
+ if (ptr != NULL) free(ptr);
+ if ((ptr != psdrcache) && (psdrcache != NULL))
+ free(psdrcache);
+ psdrcache = NULL;
+}
+
+int get_sdr_file(char *sdrfile, uchar **sdrlist)
+{
+ int rv = -1;
+ FILE *fp = NULL;
+ int i, n, num, nsdr, isdr, len;
+ uchar *sdrbuf;
+ uchar buff[255];
+ uchar hbuf[85];
+ char fvalid;
+
+ fp = fopen(sdrfile,"r");
+ if (fp == NULL) {
+ printf("Cannot open file %s\n",sdrfile);
+ return(ERR_FILE_OPEN);
+ }
+ /* determine number of SDRs by number of lines in the file */
+ num = 0;
+ while (fgets(buff, 255, fp)) { num++; }
+ if (fdebug) printf("Reading %d SDRs from file %s\n",num,sdrfile);
+ sdrbuf = malloc(num * SDR_SZ);
+ if (sdrbuf == NULL) {
+ fclose(fp);
+ return(rv);
+ }
+ fseek(fp, 0L, SEEK_SET);
+ *sdrlist = sdrbuf;
+ psdrcache = sdrbuf;
+ nsdrs = num;
+ isdr = 0;
+ nsdr = 0;
+ while (fgets(buff, 255, fp)) {
+ len = strlen_(buff);
+ fvalid = 0;
+ if (buff[0] >= '0' && (buff[0] <= '9')) fvalid = 1;
+ else if (buff[0] >= 'a' && (buff[0] <= 'f')) fvalid = 1;
+ else if (buff[0] >= 'A' && (buff[0] <= 'F')) fvalid = 1;
+ if (fvalid == 0) continue;
+ i = 0;
+ for (n = 0; n < len; ) {
+ if (buff[n] < 0x20) break; /* '\n', etc. */
+ hbuf[i++] = htoi(&buff[n]);
+ n += 3;
+ }
+ memcpy(&sdrbuf[isdr],hbuf,i);
+ isdr += i;
+ nsdr++;
+ } /*end while*/
+ if (fdebug) printf("Read %d SDRs, %d bytes\n",nsdr,isdr);
+ fclose(fp);
+ rv = 0;
+ return(rv);
+}
+
+int get_sdr_cache(uchar **pret)
+{
+ int rv = -1;
+ int i, n, sz, len, asz;
+ int recid, recnext;
+ uchar *pcache;
+ uchar *psdr;
+
+ if (pret == NULL) return(rv);
+ fdevsdrs = use_devsdrs(fpicmg);
+
+ if ((psdrcache != NULL) && (nsdrs > 0)) { /*already have sdrcache*/
+ *pret = psdrcache;
+ if (fdebug) printf("get_sdr_cache: already have cache (%p)\n",*pret);
+ return(0);
+ }
+
+ rv = GetSDRRepositoryInfo(&n,&fdevsdrs);
+ if (rv != 0) return(rv);
+ if (n == 0) {
+ /* this is an error, probably because fdevsdrs is wrong.*/
+ if (fdebug) printf("get_sdr_cache: nsdrs=0, retrying\n");
+ fdevsdrs = (fdevsdrs ^ 1);
+ n = 150; /*try some default num SDRs*/
+ }
+
+ sz = n * SDR_SZ; /*estimate max size for n sdrs*/
+ pcache = malloc(sz);
+ if (pcache == NULL) return(rv);
+ psdrcache = pcache;
+ *pret = pcache;
+ memset(pcache,0,sz);
+ recid = 0;
+ asz = 0;
+ for (i = 0; i <= n; i++)
+ {
+ if (recid == 0xffff) break;
+ // psdr = &pcache[i * SDR_SZ];
+ psdr = &pcache[asz];
+ rv = GetSDR(recid,&recnext,psdr,SDR_SZ,&len);
+ if (fdebug)
+ printf("GetSDR[%x] rv = %d len=%d next=%x\n",recid,rv,len,recnext);
+ if (rv != 0) {
+ if (rv == 0xC5) { set_reserve(1); i--; } /*retry*/
+ else break;
+ } else { /*success*/
+ asz += len;
+ if (recnext == recid) recid = 0xffff;
+ else recid = recnext;
+ }
+ }
+ nsdrs = n;
+ sz_sdrs = asz; /* save the size for later*/
+ if (fdebug) {
+ printf("get_sdr_cache, n=%d sz=%d asz=%d\n",n,sz,asz);
+ if (i < n) printf("get_sdr_cache error, i=%d < n=%d, rv=%d\n",i,n,rv);
+ }
+ return(rv);
+}
+
+int find_nsdrs(uchar *pcache)
+{
+ int num = 0;
+ int asz = 0;
+ int i, len;
+ uchar *sdr;
+ ushort recid;
+
+ if (pcache == NULL) return(num);
+ for (i = 0; asz < sz_sdrs; i++)
+ {
+ sdr = &pcache[asz];
+ len = sdr[4] + 5;
+ recid = sdr[0] + (sdr[1] << 8);
+ asz += len;
+ if (fdebug) printf("SDR[%x] len=%d i=%d\n", recid,len,i);
+ }
+ num = i;
+ return(num);
+}
+
+int find_sdr_by_snum(uchar *psdr, uchar *pcache, uchar snum, uchar sa)
+{
+ int rv = -1;
+ uchar *sdr;
+ int i, k, len;
+ int asz = 0;
+ if (psdr == NULL) return(rv);
+ if (pcache == NULL) return(rv);
+ for (i = 0; i <= nsdrs; i++)
+ {
+ // sdr = &pcache[i * SDR_SZ];
+ sdr = &pcache[asz];
+ len = sdr[4] + 5;
+ asz += len;
+ switch(sdr[3]) {
+ case 0x01: k = 7; break; /*full sensor*/
+ case 0x02: k = 7; break; /*compact sensor*/
+ case 0x03: k = 7; break;/*compact sensor*/
+ default: k = 0; break;
+ }
+ if (k == 0) continue;
+ else {
+ if ((sdr[5] == sa) && (sdr[k] == snum)) {
+ memcpy(psdr,sdr,len);
+ return(0);
+ }
+ }
+ }
+ return(rv);
+}
+
+int find_sdr_by_tag(uchar *psdr, uchar *pcache, char *tag, uchar dbg)
+{
+ int rv = -1;
+ uchar *sdr;
+ int i, k, n, len;
+ int asz = 0;
+ if (psdr == NULL) return(rv);
+ if (pcache == NULL) return(rv);
+ if (tag == NULL) return(rv);
+ if (dbg) fdebug = 1;
+ n = strlen_(tag);
+ if (fdebug) printf("find_sdr_by_tag(%s) nsdrs=%d\n",tag,nsdrs);
+ for (i = 0; i <= nsdrs; i++)
+ {
+ // sdr = &pcache[i * SDR_SZ];
+ sdr = &pcache[asz];
+ len = sdr[4] + 5;
+ asz += len;
+ switch(sdr[3]) { /* set tag offset by SDR type */
+ case 0x01: k = 48; break; /*full SDR*/
+ case 0x02: k = 32; break; /*compact SDR*/
+ case 0x03: k = 17; break; /*event-only SDR*/
+ case 0x10: k = 16; break; /*device locator SDR*/
+ case 0x11: k = 16; break; /*FRU device locator SDR*/
+ case 0x12: k = 16; break; /*IPMB device locator SDR*/
+ default: k = 0; break; /*else do not have an ID string/tag*/
+ }
+ if (k == 0) {
+ if (fdebug) printf("sdr[%d] idx=%02x%02x num=%x type=%x skip\n",
+ i,sdr[1],sdr[0],sdr[7],sdr[3]);
+ continue;
+ } else {
+ if (len > SDR_SZ) len = SDR_SZ;
+ if (fdebug) {
+ char tmp[17];
+ memset(tmp,0,sizeof(tmp));
+ memcpy(tmp,&sdr[k],(len - k));
+ tmp[16] = 0; /*force stringify*/
+ printf("sdr[%d] idx=%02x%02x num=%x tag: %s\n",i,sdr[1],sdr[0],
+ sdr[7],tmp);
+ }
+ if (strncmp(tag,&sdr[k],n) == 0) {
+ memcpy(psdr,sdr,len);
+ return(0);
+ }
+ }
+ }
+ return(rv);
+}
+
+
+int find_sdr_next(uchar *psdr, uchar *pcache, ushort id)
+{
+ int rv = -1;
+ uchar *sdr;
+ int i, imatch, len;
+ ushort recid;
+ int asz = 0;
+ if (psdr == NULL) return(rv);
+ if (pcache == NULL) return(rv);
+ imatch = nsdrs;
+ for (i = 0; i < nsdrs; i++)
+ {
+ // sdr = &pcache[i * SDR_SZ];
+ sdr = &pcache[asz];
+ len = sdr[4] + 5;
+ recid = sdr[0] + (sdr[1] << 8);
+ asz += len;
+ // if (fdebug) printf("SDR[%x] len=%d id=%x i=%d imatch=%d\n",
+ // recid,len,id,i,imatch);
+ if (recid == id) imatch = i + 1; /*matches prev, return next one*/
+ if (id == 0) { rv = 0; break; }
+ if (i == imatch) { rv = 0; break; }
+ }
+ if (rv == 0) memcpy(psdr,sdr,len);
+ return(rv);
+}
+
+int find_sdr_by_id(uchar *psdr, uchar *pcache, ushort id)
+{
+ int rv = -1;
+ uchar *sdr;
+ int i, imatch, len;
+ ushort recid;
+ int asz = 0;
+ if (psdr == NULL) return(rv);
+ if (pcache == NULL) return(rv);
+ imatch = nsdrs;
+ for (i = 0; i < nsdrs; i++)
+ {
+ sdr = &pcache[asz];
+ len = sdr[4] + 5;
+ recid = sdr[0] + (sdr[1] << 8);
+ asz += len;
+ if (recid == id) { rv = 0; break; }
+ }
+ if (rv == 0) memcpy(psdr,sdr,len);
+ return(rv);
+}
+
+uchar
+bitnum(ushort value)
+{
+ uchar ret = 0;
+ int i;
+ /* returns the highest bit number number set in this word. */
+ /* Bit numbers are 1-based in this routine, 0 means no bits set. */
+ /* scan 15 bits (0x7FFF). */
+ for (i = 0; i < 15; i++) {
+ if (value & 0x01) ret = i+1; /*was ret++;*/
+ value = (value >> 1);
+ }
+ return(ret);
+}
+
+static double
+expon(int x, int y)
+{
+ double res;
+ int i;
+ /* compute exponent: x to the power y */
+ res = 1;
+ if (y > 0) {
+ for (i = 0; i < y; i++) res = res * x;
+ } else if (y < 0) {
+ for (i = 0; i > y; i--) res = res / x;
+ } /* else if if (y == 0) do nothing, res=1 */
+ return(res);
+}
+
+double
+RawToFloat(uchar raw, uchar *psdr)
+{
+ double floatval;
+ int m, b, a;
+ uchar ax;
+ int rx, b_exp;
+ SDR01REC *sdr;
+ int signval;
+
+ sdr = (SDR01REC *)psdr;
+ floatval = (double)raw; /*default*/
+
+ // if (raw == 0xff) floatval = 0; else
+ if (sdr->rectype == 0x01) { /* SDR rectype == full */
+ if (fdebug)
+ printf("units=%x base=%d mod=%d (raw=%x, nom_rd=%x)\n",
+ sdr->sens_units,sdr->sens_base,sdr->sens_mod,
+ raw, sdr->nom_reading);
+ m = sdr->m + ((sdr->m_t & 0xc0) << 2);
+ b = sdr->b + ((sdr->b_a & 0xc0) << 2);
+ if (b & 0x0200) b = (b - 0x0400); /*negative*/
+ if (m & 0x0200) m = (m - 0x0400); /*negative*/
+ rx = (sdr->rx_bx & 0xf0) >> 4;
+ if (rx & 0x08) rx = (rx - 0x10); /*negative, fix sign w ARM compilers*/
+ a = (sdr->b_a & 0x3f) + ((sdr->a_ax & 0xf0) << 2);
+ ax = (sdr->a_ax & 0x0c) >> 2;
+ b_exp = (sdr->rx_bx & 0x0f);
+ if (b_exp & 0x08) b_exp = (b_exp - 0x10); /*negative*/
+ //b_exp |= 0xf0; /* negative 8-bit */
+ if ((sdr->sens_units & 0xc0) == 0) { /*unsigned*/
+ floatval = (double)raw;
+ } else { /*signed*/
+ if (raw & 0x80) signval = (raw - 0x100);
+ else signval = raw;
+ floatval = (double)signval;
+ }
+ floatval *= (double) m;
+#ifdef MATH_OK
+ floatval += (b * pow (10,b_exp));
+ floatval *= pow (10,rx);
+#else
+ floatval += (b * expon (10,b_exp));
+ floatval *= expon (10,rx);
+#endif
+ if (fdebug)
+ printf("decode1: m=%d b=%d b_exp=%x rx=%d, a=%d ax=%d l=%x, floatval=%f\n",
+ m,b,b_exp,rx,a,ax,sdr->linear,floatval);
+ switch(sdr->linear) {
+ case 0: /*linear*/
+ break;
+ case 7: /*invert 1/x*/
+ /* skip if zero to avoid dividing by zero */
+ if (raw != 0) floatval = 1 / floatval;
+ break;
+ case 1: /*ln*/
+ case 2: /*log10, log2, e, exp10, exp2, */
+ case 3: /*log2*/
+ case 4: /*e*/
+ case 5: /*exp10*/
+ case 6: /*exp2*/
+ case 8: /*sqr(x)*/
+ case 9: /*cube(x)*/
+ case 10: /*sqrt(x)*/
+ case 11: /*cube-1(x)*/
+ default:
+ if (fdebug) printf("linear mode %x not implemented\n",sdr->linear);
+ break;
+ } /*end-switch linear*/
+ }
+
+#ifdef NOT_LINEAR
+ /* else if (sdr->linear != 7) */
+ {
+ double be, re;
+ rc = GetSensorType(sdr->sens_num,&stype,&rtype);
+ if (fdebug)
+ printf("decode: rc=%x, stype=%x, rtype=%x\n",rc,stype,rtype);
+ if (rc != 0) return(floatval);
+
+ /* GetSensorReadingFactors */
+ rc = GetSensorReadingFactors(sdr->sens_num,raw,&m,&b,&b_exp,&r,&a);
+ if (rc == 0) {
+ // floatval = ((m * raw) + (b * be)) * re;
+ }
+ if (fdebug) printf("decode: rc=%x, floatval=%f\n",rc,floatval);
+ }
+#endif
+
+ return(floatval);
+}
+
+#define IpmiAnalogDataFormatUnsigned 0
+#define IpmiAnalogDataFormat1Compl 1
+#define IpmiAnalogDataFormat2Compl 2
+
+uchar
+FloatToRaw(double val, uchar *psdr, int rounding)
+{
+ double cval;
+ int lowraw, highraw, raw, maxraw, minraw, next_raw;
+ int analog_dfmt;
+
+ analog_dfmt = (psdr[20] >> 6) & 0x03;
+ switch( analog_dfmt )
+ {
+ case IpmiAnalogDataFormat1Compl:
+ lowraw = -127;
+ highraw = 127;
+ minraw = -127;
+ maxraw = 127;
+ next_raw = 0;
+ break;
+ case IpmiAnalogDataFormat2Compl:
+ lowraw = -128;
+ highraw = 127;
+ minraw = -128;
+ maxraw = 127;
+ next_raw = 0;
+ break;
+ case IpmiAnalogDataFormatUnsigned:
+ default:
+ lowraw = 0;
+ highraw = 255;
+ minraw = 0;
+ maxraw = 255;
+ next_raw = 128;
+ break;
+ }
+
+ /* do a binary search for the right nth root value */
+ do {
+ raw = next_raw;
+ cval = RawToFloat( (uchar)raw, psdr );
+ if ( cval < val ) {
+ next_raw = ((highraw - raw) / 2) + raw;
+ lowraw = raw;
+ } else {
+ next_raw = ((raw - lowraw) / 2) + lowraw;
+ highraw = raw;
+ }
+ } while ( raw != next_raw );
+
+ /* Do rounding to get the final value */
+ switch( rounding ) {
+ case 0: /* Round Normal = Round to nearest value */
+ if ( val > cval ) {
+ if ( raw < maxraw ) {
+ double nval;
+ nval = RawToFloat((uchar)(raw+1),psdr);
+ nval = cval + ((nval - cval) / 2.0);
+ if ( val >= nval ) raw++;
+ }
+ } else {
+ if ( raw > minraw ) {
+ double pval;
+ pval = RawToFloat((uchar)(raw-1),psdr);
+ pval = pval + ((cval - pval) / 2.0);
+ if ( val < pval ) raw--;
+ }
+ }
+ break;
+ case 1: /*Round Down*/
+ if ((val < cval) && (raw > minraw )) raw--;
+ break;
+ case 2: /*Round Up*/
+ if ((val > cval) && (raw < maxraw)) raw++;
+ break;
+ }
+ if ( analog_dfmt == IpmiAnalogDataFormat1Compl )
+ if ( raw < 0 ) raw -= 1;
+ return((uchar)raw);
+} /*end FloatToRaw()*/
+
+static int fill_thresholds(double *thrf, uchar *sdr)
+{
+ int rv = 0;
+ uchar *vals;
+ uchar bits;
+
+ // snum = sdr[7];
+ bits = sdr[19]; /*which are settable*/
+ vals = &sdr[36];
+ if (fdebug)
+ printf("fill_thresholds: bits=%02x, values: %f>=%f>=%f, %f<=%f<=%f\n",
+ bits, thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]);
+ if (thrf[0] == THR_EMPTY) {
+ if ((bits & 0x01) != 0) { /*lo-noncrit*/
+ thrf[0] = RawToFloat(vals[5],sdr);
+ rv++;
+ } else thrf[0] = 0;
+ }
+ if (thrf[1] == THR_EMPTY) {
+ if ((bits & 0x02) != 0) { /*lo-crit*/
+ thrf[1] = RawToFloat(vals[4],sdr);
+ rv++;
+ } else thrf[1] = 0;
+ }
+ if (thrf[2] == THR_EMPTY) {
+ if ((bits & 0x04) != 0) { /*lo-unrec*/
+ thrf[2] = RawToFloat(vals[3],sdr);
+ rv++;
+ } else thrf[2] = 0;
+ }
+ if (thrf[3] == THR_EMPTY) {
+ if ((bits & 0x08) != 0) { /*hi-noncrit*/
+ thrf[3] = RawToFloat(vals[2],sdr);
+ rv++;
+ } else thrf[3] = 0;
+ }
+ if (thrf[4] == THR_EMPTY) {
+ if ((bits & 0x10) != 0) { /*hi-crit*/
+ thrf[4] = RawToFloat(vals[1],sdr);
+ rv++;
+ } else thrf[4] = 0;
+ }
+ if (thrf[5] == THR_EMPTY) {
+ if ((bits & 0x20) != 0) { /*hi-unrec*/
+ thrf[5] = RawToFloat(vals[0],sdr);
+ rv++;
+ } else thrf[5] = 0;
+ }
+ if (fdebug)
+ printf("fill_thresholds: after rv=%d values: %f>=%f>=%f, %f<=%f<=%f\n",
+ rv,thrf[0],thrf[1],thrf[2], thrf[3],thrf[4],thrf[5]);
+ return(rv);
+}
+
+char *
+decode_itype(uchar itype)
+{
+ char *retstr;
+ int i;
+ /* Decode the Interrupt Type from Entity Assoc records */
+
+ retstr = tmpstr;
+ if (itype <= 0x0f) sprintf(retstr,"IRQ_%d",itype);
+ else if (itype <= 0x13) {
+ strcpy(retstr,"PCI-A");
+ for (i=0x10;i<itype;i++) retstr[4]++;
+ }
+ else if (itype == 0x14) strcpy(retstr,"SMI");
+ else if (itype == 0x15) strcpy(retstr,"SCI");
+ else if (itype >= 0x20 && itype <= 0x5f)
+ sprintf(retstr,"SysInt_%d",itype-0x20);
+ else if (itype == 0x60) strcpy(retstr,"ACPI/PnP");
+ else if (itype == 0xFF) strcpy(retstr,"NoInt");
+ else strcpy(retstr,"Invalid");
+ return(retstr);
+}
+
+int decode_oem_sensor(uchar *sdr,uchar *reading,char *pstring,int slen)
+{
+ int rv = -1;
+#ifdef METACOMMAND
+ switch(vend_id) {
+ case VENDOR_INTEL:
+ rv = decode_sensor_intel(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_KONTRON:
+ rv = decode_sensor_kontron(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_FUJITSU:
+ rv = decode_sensor_fujitsu(sdr,reading,pstring,slen);
+ break;
+ case VENDOR_SUN:
+ rv = decode_sensor_sun(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_MAGNUM:
+ case VENDOR_SUPERMICRO:
+ case VENDOR_SUPERMICROX:
+ rv = decode_sensor_supermicro(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_QUANTA:
+ rv = decode_sensor_quanta(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_HP:
+ rv = decode_sensor_hp(sdr, reading, pstring, slen);
+ break;
+ case VENDOR_DELL:
+ rv = decode_sensor_dell(sdr, reading, pstring, slen);
+ break;
+ default:
+ break;
+ } /*end-switch vend_id*/
+ if (fdebug && rv == 0)
+ printf("decode_oem_sensor rv=%d vend=%x string=%s\n",rv,vend_id,pstring);
+#endif
+ return (rv);
+}
+
+int show_oemsdr(int vend, uchar *sdr)
+{
+ int rv = -1;
+ int i, len;
+
+#ifdef METACOMMAND
+ if (vend == VENDOR_INTEL) {
+ show_oemsdr_intel(sdr); /*show subtypes for Intel BMC_TAM*/
+ rv = 0;
+ } else if (vend == 4156) { /*special HP/NewAccess OEM SDR*/
+ show_oemsdr_hp(sdr);
+ rv = 0;
+ } else if (vend == VENDOR_QUANTA) {
+ printf("Quanta: ");
+ show_oemsdr_nm(sdr);
+ rv = 0;
+ }
+#endif
+ if (rv != 0) {
+ len = sdr[4] + 5;
+ if (vend == VENDOR_FUJITSU) printf("Fujitsu: ");
+ else if (vend == VENDOR_INTEL) printf("Intel: ");
+ else printf("manuf=%d: ",vend);
+ for (i = 8; i < len; i++) printf("%02x ",sdr[i]);
+ printf("\n");
+ }
+ return(rv);
+}
+
+void
+ShowThresh(int flg, uchar bits, uchar *vals, uchar *sdr)
+{
+ char str[128] = "";
+ char part[24]; /* ~15 bytes used */
+ double ival;
+ char sep[4];
+ char *tag;
+ tag = "";
+ if (fsimple) {
+ sprintf(sep,"%c ",bdelim);
+ tag = "Thresholds";
+ } else sep[0] = 0; /*null string*/
+ if (fshowthr == 2) {
+ double i0, i1, i2, i3, i4, i5;
+ i0 = RawToFloat(vals[0],sdr);
+ i1 = RawToFloat(vals[1],sdr);
+ i2 = RawToFloat(vals[2],sdr);
+ i3 = RawToFloat(vals[3],sdr);
+ i4 = RawToFloat(vals[4],sdr);
+ i5 = RawToFloat(vals[5],sdr);
+ sprintf(str,"%.2f:%.2f:%.2f:%.2f:%.2f:%.2f",i0,i1,i2,i3,i4,i5);
+ printf("\t%s%s%s%c",sep,"Thresh ",str,chEol);
+ } else if (flg != 0) { /* Compact, did GetThresholds, reverse order */
+ if (bits & 0x20) {
+ ival = RawToFloat(vals[5],sdr);
+ sprintf(part,"%shi-unrec %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x10) {
+ ival = RawToFloat(vals[4],sdr);
+ sprintf(part,"%shi-crit %.2f ", sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x08) {
+ ival = RawToFloat(vals[3],sdr);
+ sprintf(part,"%shi-noncr %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x01) {
+ ival = RawToFloat(vals[0],sdr);
+ sprintf(part,"%slo-noncr %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x02) {
+ ival = RawToFloat(vals[1],sdr);
+ sprintf(part,"%slo-crit %.2f ", sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x04) {
+ ival = RawToFloat(vals[2],sdr);
+ sprintf(part,"%slo-unrec %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (flg == 2) {
+ if (sens_verbose) tag = "Volatile ";
+ printf("\t%s%s%s%c",sep,tag,str,chEol);
+ } else
+ printf("\t%s%s%s%c",sep,tag,str,chEol);
+ } else { /*Full SDR*/
+ if (fdebug) printf("ShowThresh[%x]: bits=%02x, sdr18=%02x %02x\n",
+ sdr[7],bits,sdr[18],sdr[19]);
+ if (bits & 0x20) {
+ ival = RawToFloat(vals[0],sdr);
+ sprintf(part,"%shi-unrec %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x10) {
+ ival = RawToFloat(vals[1],sdr);
+ sprintf(part,"%shi-crit %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x08) {
+ ival = RawToFloat(vals[2],sdr);
+ sprintf(part,"%shi-noncr %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x01) {
+ ival = RawToFloat(vals[5],sdr);
+ sprintf(part,"%slo-noncr %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x02) {
+ ival = RawToFloat(vals[4],sdr);
+ sprintf(part,"%slo-crit %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (bits & 0x04) {
+ ival = RawToFloat(vals[3],sdr);
+ sprintf(part,"%slo-unrec %.2f ",sep,ival);
+ strcat(str,part);
+ }
+ if (sens_verbose) tag = "SdrThres ";
+ printf("\t%s%s%s%c",sep,tag,str,chEol);
+ if (sens_verbose)
+ { /* show max/min & hysteresis from full sdr */
+ str[0] = 0;
+ ival = RawToFloat(sdr[31],sdr);
+ sprintf(part,"%snom %.2f ",sep,ival);
+ strcat(str,part);
+ ival = RawToFloat(sdr[32],sdr);
+ sprintf(part,"%snmax %.2f ",sep,ival);
+ strcat(str,part);
+ ival = RawToFloat(sdr[33],sdr);
+ sprintf(part,"%snmin %.2f ",sep,ival);
+ strcat(str,part);
+
+ ival = RawToFloat(sdr[34],sdr);
+ sprintf(part,"%ssmax %.2f ",sep,ival);
+ strcat(str,part);
+
+ ival = RawToFloat(sdr[35],sdr);
+ sprintf(part,"%ssmin %.2f ",sep,ival);
+ strcat(str,part);
+
+#ifdef OLD
+ ival = RawToFloat(sdr[42],sdr);
+ sprintf(part,"%s+hyst %.2f ",sep,ival);
+ strcat(str,part);
+
+ ival = RawToFloat(sdr[43],sdr);
+ sprintf(part,"%s-hyst %.2f ",sep,ival);
+ strcat(str,part);
+#endif
+
+ printf("\t%s%c",str,chEol);
+ }
+ } /*endif full sdr*/
+}
+
+/*
+ * decode_comp_reading
+ *
+ * Decodes the readings from compact SDR sensors.
+ * Use sensor_dstatus array for sensor reading types and meaning strings.
+ * Refer to IPMI Table 36-1 and 36-2 for this.
+ *
+ * Note that decoding should be based on sensor type and ev_type only,
+ * except for end cases.
+ *
+ * Note reading1 = sens_reading[2], reading2 = sens_reading[3]
+ */
+int
+decode_comp_reading(uchar type, uchar evtype, uchar num,
+ uchar reading1, uchar reading2)
+{
+ int istr = 0; /*string index into sensor_dstatus[] */
+ uchar b;
+ ushort reading;
+ static char customstr[35];
+
+ /* usually reading2 has h.o. bit set (0x80). */
+ reading = reading1 | ((reading2 & 0x7f) << 8);
+
+ switch(type)
+ {
+ case 0x01: /*Discrete Thermal, Temperature*/
+ if (fdebug)
+ printf("Discrete Thermal snum %x evtype=%x reading=%x\n",
+ num,evtype,reading);
+ if (evtype == 0x07) {
+ b = bitnum(reading);
+ if (b == 0) istr = 8; /*no bits set, "OK*"*/
+ else if (b < 3) istr = 0; /*bits 1,2 "OK"*/
+ else istr = 65; /*transition to error, Limit Exceeded*/
+ } else if (evtype == 0x05) {
+ /* see CPU1 VRD Temp on S5000, snum 0xc0 thru 0xcf */
+ if (reading & 0x01) istr = 65; /* Limit Exceeded*/
+ else istr = 0; /* "OK" LimitNotExceeded*/
+ } else if (evtype == 0x03) {
+ if (reading & 0x01) istr = 13; /* Asserted */
+ else istr = 0; /* "OK" Deasserted */
+ } else { /* evtype == other 0x05 */
+ if (reading & 0x01) istr = 0; /* 8="OK*", 0="OK" */
+ else istr = 5; /*state asserted, Crit-hi */
+ }
+ break;
+ case 0x02: /*Discrete Voltage*/
+ { /* evtype == 0x05 for VBat, 0x03 for VR Watchdog */
+ if (reading & 0x01) istr = 65; /*LimitExceeded, was Crit-hi*/
+ else istr = 0; /* "OK" LimitNotExceeded*/
+ }
+ break;
+ case 0x04: /*Fan*/
+ if (evtype == 0x0b) { /*redundancy*/
+ b = reading & 0x3f;
+ if (b == 0x00) istr = 16; /*sensor disabled*/
+ else if (b == 0x01) istr = 18; /*fully redundant*/
+ else if (b == 0x02) istr = 19; /*redundancy lost*/
+ else if (b == 0x0b) istr = STR_AC_LOST; /*ac lost*/
+ else istr = 20; /*redundancy degraded*/
+ } else if (evtype == 0x08) { /*presence*/
+ if (reading & 0x02) istr = 9; /*Present/Inserted*/
+ else if (reading & 0x01) istr = 10; /*Absent/Removed*/
+ else /*reading==00*/ istr = 47; /*Unused*/
+ } else if (evtype == 0x03) { /*PS Fan Fail*/
+ if (reading == 0) istr = 0; /*OK*/
+ else istr = 12; /*faulty*/
+ } else { /*other evtype*/
+ b = reading & 0x0f;
+ if (b == 0) istr = 12; /*faulty*/
+ else if (b & 0x01) istr = 11; /*ready*/
+ else istr = 41; /*Unknown*/
+ }
+ break;
+ case 0x05: /*Physical Security, Chassis */
+ if (reading == 0) istr = 0; /*OK*/
+ else if (reading & 0x01) istr = 38; /*chassis intrusion*/
+ /* 0x02 Drive bay intrusion */
+ /* 0x04 IO area intrusion */
+ /* 0x08 Processor area intrusion */
+ else if (reading & 0x10) istr = 37; /*lan leash lost*/
+ /* 0x20 Dock/Undock */
+ /* 0x40 Fan area intrusion */
+ else istr = 41; /* Unknown, was bitnum(reading); */
+ break;
+ case 0x07: /*Processor Status - 0x80 is OK/Present */
+ b = bitnum(reading);
+ if (evtype == 0x03) {
+ if (b <= 1) istr = 0; /*bit1 Deasserted, OK* */
+ else istr = 13; /*bit2 Asserted*/
+ } else { /*usu 0x6f*/
+ if (b > 10) istr = 41; /*Unknown*/
+ else if (b == 0) istr = 0; /*OK*/
+ else istr = 47 + b; /*Proc strings 48 thru 57*/
+ }
+ break;
+ case 0x08: /*Power Supply*/
+ b = reading & 0x7f;
+ if (b == 0) istr = 10; /*absent*/
+ else if (b & 0x40) istr = STR_PS_CONFIG; /*Config Err*/
+ else if (b & 0x08) istr = STR_AC_LOST; /*AC Lost*/
+ else if (b & 0x04) istr = 15; /*Predictive Fail*/
+ else if (b & 0x02) istr = STR_PS_FAIL; /*PS Fail*/
+ else if (b & 0x01) istr = 9; /*present*/
+ break;
+ case 0x09: /*Power Unit*/
+ b = reading & 0x3f;
+ if (evtype == 0x0b) { /*Power Redundancy*/
+ if (b == 0x00) istr = 16; /*sensor disabled*/
+ else if (b == 0x01) istr = 18; /*fully redundant*/
+ else if (b == 0x02) istr = 19; /*redundancy lost*/
+ else if (b == 0x0b) istr = STR_AC_LOST; /*ac lost*/
+ else istr = 20; /*redundancy degraded*/
+ } else { /* Power Unit (evtype==0x6f or 0xef) */
+ if (b == 0) istr = 17; /*enabled*/
+ else if ((b & 0x01) == 1) istr = 16; /*disabled*/
+ }
+ break;
+ case 0x0C: /* Memory */
+ b = reading & 0x3f;
+ if (b == 0) istr = 0; /*OK*/
+ else if (b & 0x01) istr = 8; /*Correctable ECC (OK*)*/
+ else if ((b & 0x02) || (b & 0x20)) istr = 39; /*ECC Error*/
+ else if (b & 0x04) istr = 40; /*Parity Error*/
+ else istr = bitnum(b); /* ECC or other error */
+ break;
+ case 0x0D: /* drive slot - usually HSC sens_ownid == 0xc0 */
+ if (fRomley) { /* evtype==0x6f, has both status and presence */
+ if (reading & 0x02) istr = 12; /*Faulty*/
+ else if (reading & 0x80) istr = STR_REBUILDING; /*Rebuilding*/
+ else if (reading & 0x01) istr = 9; /*Present (OK)*/
+ else istr = 10; /*Absent*/
+ } else {
+ if (evtype == 8) { /* HSC slot presence sensors (num > 8)*/
+ if (reading1 & 0x02) istr = 9; /*Present/Inserted*/
+ else if (reading1 & 0x01) istr = 10; /*Absent/Removed*/
+ else /*reading1==00*/ istr = 47; /*Unused*/
+ } else { /* HSC slot status sensors (evtype==0x6f) */
+ /* usually reading2 == 0x82 or 0x8E if healthy */
+ if (reading2 & 0x01) istr = 12; /*state8=Rebuild stopped*/
+ else if (reading2 & 0x02) istr = 11; /*state9=Inserted/Ready */
+ else if (reading2 & 0x04) istr = 11; /*state10=Safe_to_Remove*/
+ else if (reading2 & 0x08) istr = 11; /*state11=Ready */
+ else if (reading2 == 0x80) istr = 47; /*no states, Unused*/
+ else istr = 12; /*faulty*/
+ b = 8; /*if no bits set, no raid state */
+ if (reading1 & 0x01) { b = 0; } /*state0=Faulty*/
+ else if (reading1 & 0x02) b = 1; /*state1=Rebuilding*/
+ else if (reading1 & 0x04) b = 2; /*state2=InFailedArray*/
+ else if (reading1 & 0x08) b = 3; /*state3=InCriticalArray*/
+ else if (reading1 & 0x10) b = 4; /*state4=ParityCheck*/
+ else if (reading1 & 0x20) b = 5; /*state5=PredictedFault*/
+ else if (reading1 & 0x40) b = 6; /*state6=Un-configured*/
+ else if (reading1 & 0x80) b = 7; /*state7=HotSpare*/
+ if (b < 8) {
+ /* also include a raid_state, via custom string */
+ sprintf(customstr,"%s %s",
+ sensor_dstatus[istr], raid_states[b]);
+ istr = STR_CUSTOM;
+ sensor_dstatus[istr] = customstr;
+ if (fdebug) printf("dstatus=%s\n",sensor_dstatus[istr]);
+ }
+ } /*end-else HSC slot status*/
+ }
+ break;
+ case 0x10: /*Event Logging*/
+ /* usu evtype==0x6f*/
+ b = bitnum(reading & 0x3f);
+ switch (b) {
+ case 0x00: istr = 0; break; /*OK*/
+ case 0x01: istr = 59; break; /*MemLogDisabled*/
+ case 0x02: istr = 60; break; /*TypLogDisabled*/
+ case 0x03: istr = 61; break; /*LogCleared*/
+ case 0x04: istr = 62; break; /*AllLogDisabled*/
+ case 0x05: istr = 63; break; /*SelFull*/
+ case 0x06: istr = 64; break; /*SelNearFull*/
+ default: istr = 41; break; /*Unknown*/
+ }
+ break;
+ case 0x12: /*System Event*/
+ if (reading == 0) istr = 0;
+ else istr = 13; /*Asserted*/
+ break;
+ case 0x13: /*Critical Interrupt*/
+ /* valid bits: 0x03FF */
+ if (reading == 0) istr = 0; /*OK*/
+ else {
+ b = bitnum(reading); /* ECC or other error */
+ if (b > 10) b = 10;
+ istr = 24 + b;
+ }
+ break;
+ case 0x14: /*Button*/
+ if (reading == 0) istr = 0; /*OK*/
+ else istr = 13; /*Asserted*/
+ break;
+ case 0x15: /*Module/ Board */
+ if (evtype == 0x08) { /*presence*/
+ if (reading & 0x02) istr = 9; /*Present/Inserted*/
+ else if (reading & 0x01) istr = 10; /*Absent/Removed*/
+ else /*reading==00*/ istr = 47; /*Unused*/
+ }
+ break;
+ case 0x16: /* HSBP Status (esp. Romley) */
+ if (reading & 0x010) istr = STR_HSC_OFF; /*Offline*/
+ else istr = 0; /*OK*/
+ break;
+ case 0x17: /* ATCA CDM, Air Filter, Filter Tray */
+ if (reading == 0) istr = 0; /*OK*/
+ else if (reading & 0x01) istr = 10; /*Absent*/
+ else istr = bitnum(reading); /* other error, TODO: fix this */
+ break;
+ case 0x1C: /*Terminator (usu SCSI)*/
+ if (reading & 0x01) istr = 9; /*present*/
+ else istr = 10; /*missing,absent*/
+ break;
+ case 0x21: /*DIMM memory slot*/
+ if ((reading & 0x04) != 0) istr = 9; /*present*/
+ else istr = 10; /*absent*/
+ sprintf(customstr,"%s", sensor_dstatus[istr]);
+ if ((reading & 0x01) != 0) strcat(customstr,",Fault");
+ if ((reading & 0x0100) != 0) strcat(customstr,",Disabled");
+ istr = 58; /*use a custom string*/
+ sensor_dstatus[istr] = customstr;
+ if (fdebug) printf("dstatus=%s\n",sensor_dstatus[istr]);
+ break;
+ case 0x22: /*ACPI Power State*/
+ b = bitnum(reading);
+ switch(b) {
+ case 0: istr = 0; break; /*OK*/
+ case 1: istr = 22; break; /*Working*/
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ case 10: istr = 23; break; /*Sleeping*/
+ case 6:
+ case 7:
+ case 8:
+ case 11:
+ case 13: istr = 21; break; /*Off*/
+ case 12: istr = 24; break; /*On*/
+ default: istr = 41; /*unknown*/
+ }
+ break;
+ case 0x23: /*Watchdog*/
+ if (reading == 0) istr = 0;
+ else istr = 13; /*Asserted*/
+ break;
+ case 0x24: /*Platform Alert*/
+ b = bitnum(reading);
+ switch(b) {
+ case 0: istr = 0; break; /*OK, no bits set*/
+ case 1: istr = 66; break; /*Page, bit 0 set*/
+ case 2: istr = 67; break; /*LAN, bit 1 set*/
+ case 3: istr = 68; break; /*PET*/
+ case 4: istr = 69; break; /*SNMP OEM*/
+ default: istr = 70; /*None*/
+ }
+ break;
+ case 0x25: /* Entity Presence */
+ if (reading & 0x01) istr = 8; /*Present*/
+ else if (reading & 0x02) istr = 9; /*Absent*/
+ else if (reading & 0x04) istr = 16; /*Disabled*/
+ else istr = 42; /* NotAvailable */
+ break;
+ case 0x28: /* BMC FW Health */
+ if (reading == 0) istr = 0; /*OK*/
+ else istr = 12; /*Faulty*/
+ break;
+ case 0x29: /* Battery */
+ switch(reading & 0x7f) {
+ case 0x00: istr = 0; break; /*OK*/
+ case 0x01: istr = 15; break; /*Predict Fail*/
+ case 0x04: istr = 9; break; /*Present*/
+ case 0x02:
+ default: istr = 12; break; /*Failed/Faulty*/
+ }
+ break;
+ case 0x2A: /* Session Audit (IPMI 2.0) */
+ if (reading == 0x00) istr = 45; /*Activated*/
+ else istr = 46; /*Deactivated*/
+ break;
+ case 0x2B: /* Version Change */
+ b = bitnum(reading1);
+ switch(b) {
+ case 0: istr = 0; break; /*OK, no bits set*/
+ case 1: istr = 72; break; /*HW Changed, bit 0 set*/
+ case 2: istr = 73; break; /*SW Changed, bit 1 set*/
+ case 3: istr = 74; break; /*HW incompatibility*/
+ default: istr = 75; break; /*Change error*/
+ }
+ break;
+ case 0x60: /* SCSI 1 Term Flt */
+ case 0x61: /* SCSI 2 Term Flt */
+ break;
+ /* sensor types 0xC0 - 0xFF are OEM RESERVED */
+ case 0xF1: /* ATCA IPMB-0 Sensor */
+ if ((reading & 0x7fff) == 0x0008) istr = 0; /*OK*/
+ else istr = bitnum(reading1); /* other error, TODO: refine this */
+ break;
+ case 0xC0: /* SMI State, NMI State */
+ case 0xD8: /* BIST */
+ case 0xF0: /* ATCA FRU HotSwap, TODO: refine this */
+ case 0xF2: /* ATCA Module HotSwap, TODO: refine this */
+ case 0xF3: /* SMI Timeout, etc. */
+ if (reading & 0x01) istr = 13; /* Asserted */
+ else istr = 0; /* "OK", Deasserted */
+ break;
+ default:
+ if (fdebug)
+ printf("sensor[%x] type %02x not decoded, reading = %04x\n",
+ num,type,reading);
+ istr = STR_OTHER; /* other " - " */
+ }
+ return(istr);
+} /* end decode_comp_reading */
+
+#define STYPSZ 15
+static char *get_stype_str(uchar stype)
+{ /*return sensor type string, with fixed length */
+ static char stype_str[STYPSZ+1];
+ char *tmpstr;
+ int i, n;
+ tmpstr = get_sensor_type_desc(stype);
+ n = strlen_(tmpstr);
+ if (n > STYPSZ) n = STYPSZ;
+ strncpy(stype_str,tmpstr,n);
+ for (i = n; i < STYPSZ; i++) stype_str[i] = ' ';
+ stype_str[i] = 0;
+ tmpstr = stype_str;
+ return(tmpstr);
+}
+
+void
+ShowSDR(char *tag, uchar *sdr)
+{
+ SDR01REC *sdr01;
+ SDR02REC *sdr02;
+ SDR08REC *sdr08;
+ SDR11REC *sdr11;
+ SDR12REC *sdr12;
+ SDR14REC *sdr14;
+ SDRc0REC *sdrc0;
+ char idstr[32];
+ char *typestr = NULL;
+ int vend;
+ int len, ilen, i, j;
+ int ioff;
+ uchar sens[4];
+ uchar sens_cap;
+ uchar shar_cnt;
+ int rc;
+ double val;
+ char brearm;
+ uchar sep[4];
+ char rdgstr[50];
+
+ len = sdr[4] + 5;
+ sens_cap = 0x80; /*ignore*/
+ if (fdebug) printf("ShowSDR: len=%d, type=%x\n",len,sdr[3]);
+ memset(sens,0,4);
+ if (frawsdr || fdebug) {
+ printf("raw SDR: ");
+ for (i = 0; i < len; i++)
+ printf("%02x ",sdr[i]);
+ printf("\n");
+ }
+ switch(sdr[3])
+ {
+ case 0x01: /* Full sensor record */
+ sdr01 = (SDR01REC *)sdr;
+ ioff = 48;
+ if (ioff > len) {
+ if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n",
+ sdr[3],len,ioff);
+ printf("Bad SDR Length, please apply the correct FRU/SDR diskette\n");
+ return;
+ }
+ sens_cap = sdr[11]; /*sdr01->sens_capab*/
+ ilen = len - ioff;
+ if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1;
+ memcpy(idstr,&sdr[ioff],ilen);
+ for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; }
+ idstr[ilen] = 0; /* stringify */
+ if ((sdr01->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/
+ else brearm = 'a'; /*automatic rearm*/
+ if (fdebug) printf("entity %d.%d, idlen=%d sizeof=%d idstr0=%c s0=%x\n",
+ sdr01->entity_id, sdr01->entity_inst,
+ ilen,sizeof(SDR01REC),idstr[0],sdr[ioff]);
+ rc = GetSensorReading(sdr01->sens_num,sdr01,sens);
+ if (rc != 0) { /* if rc != 0, leave sens values zero */
+ i = 41; /* Unknown */
+ val = 0;
+ if (rc == 0xCB) { /*sensor not present*/
+ i = 10; /* Absent */
+ typestr = "na";
+ } else typestr = decode_rv(rc);
+ } else {
+ j = (sens[2] & 0x3f); /*sensor reading state*/
+ i = bitnum((ushort)j); /*sensor_dstatus index*/
+ if (fdebug)
+ printf("bitnum(%02x)=%d raw=%02x init=%x base/units=%x/%x\n",
+ sens[2],i,sens[0],sens[1],sdr01->sens_base,
+ sdr01->sens_units);
+ if ((sens[1] & 0x20) != 0) { i = 7; val = 0; } /* Init state */
+ else val = RawToFloat(sens[0],sdr);
+ typestr = get_unit_type(sdr01->sens_units, sdr01->sens_base,
+ sdr01->sens_mod, fsimple);
+#ifdef WRONG
+ if (is_romley(vend_id,prod_id) &&
+ (sdr01->sens_type == 0x0C) && (sdr01->sens_units & 0x01))
+ { /* Intel Memory Thermal Throttling %, raw 0x01 == 0.5 % */
+ val = (val / 2); /* handle MTT SDR errata */
+ } /*correct solution is to fix the SDR m-value instead */
+#endif
+ }
+ rc = decode_oem_sensor(sdr,sens,oem_string,sizeof(oem_string));
+ if (rc == 0) {
+ strncpy(rdgstr,oem_string,sizeof(rdgstr));
+ } else {
+ if (fsimple)
+ snprintf(rdgstr,sizeof(rdgstr),"%s %c %.2f %s",
+ sensor_dstatus[i],bdelim,val,typestr);
+ else
+ snprintf(rdgstr,sizeof(rdgstr),"%02x %s %.2f %s",
+ sens[0], sensor_dstatus[i],val,typestr);
+ }
+ sep[0] = 0; /*null string*/
+ printf("%s", tag);
+ if (fsimple) {
+ sprintf(sep,"%c ",bdelim);
+ printf("%04x %c Full %c %s %c %02x %c %s %c %s%c",
+ sdr01->recid, bdelim, bdelim,
+ get_stype_str(sdr01->sens_type),
+ bdelim, sdr01->sens_num,bdelim, idstr,
+ bdelim,rdgstr,chEol);
+ } else
+ printf("%04x SDR Full %02x %02x %02x %c %02x snum %02x %s = %s%c",
+ sdr01->recid, sdr01->rectype, sdr01->ev_type,
+ sdr01->sens_ownid, brearm, sdr01->sens_type, sdr01->sens_num,
+ idstr, rdgstr, chEol);
+ if (fdebug && fshowthr)
+ printf("cap=%02x settable=%02x, readable=%02x\n",
+ sens_cap,sdr[19],sdr[18]);
+ if (sens_verbose) /* if -v, also show Entity ID */
+ printf("\t%sEntity ID %d.%d (%s), Capab: %s%c",
+ sep, sdr01->entity_id, sdr01->entity_inst,
+ decode_entity_id(sdr01->entity_id), // sens_cap,
+ decode_capab(sens_cap),chEol);
+ if (fshowthr && (sens_cap & 0x0f) != 0x03) {
+ uchar thresh[7];
+ /* Thresholds, so show them */
+ /* Use settable bits to show thresholds, since the
+ * readable values will be off for Full SDRs.
+ * If cant set any thresholds, only show SDR thresholds */
+ if (sdr[19] == 0) rc = 1;
+ else {
+ /* Show volatile thresholds. */
+ rc = GetSensorThresholds(sdr01->sens_num,&thresh[0]);
+ if (rc == 0) ShowThresh(2,thresh[0],&thresh[1],sdr);
+ }
+ /* Show SDR non-volatile thresholds. */
+ if (sens_verbose || rc !=0) ShowThresh(0,sdr[18],&sdr[36],sdr);
+ // ShowThresh(0,0x3f,&sdr[36],sdr); /* to show all %%%% */
+ }
+ if (fwrap) { /* (chEol != '\n') include time */
+ time_t ltime;
+ time(&ltime);
+ if (fsimple)
+ printf("%c %s",bdelim,ctime(&ltime)); /*ctime has '\n' */
+ else
+ printf("at %s",ctime(&ltime)); /*ctime has '\n' */
+ }
+ break;
+ case 0x02: /* Compact sensor record */
+ sdr02 = (SDR02REC *)sdr;
+ ioff = 32;
+ if (ioff > len) {
+ if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n",
+ sdr[3],len,ioff);
+ printf("Bad SDR Length, please apply the correct FRU/SDR diskette\n");
+ return;
+ }
+ sens_cap = sdr[11]; /*sdr02->sens_capab*/
+ shar_cnt = sdr02->shar_cnt & 0x0f; /*sdr[23]*/
+ ilen = len - ioff;
+ if ((ilen+1) >= sizeof(idstr)) ilen = sizeof(idstr) - 2;
+ memcpy(idstr,&sdr[ioff],ilen);
+ if ((shar_cnt > 1) && (sdr02->shar_off & 0x80) != 0) { /*do shared SDR*/
+ j = (sdr02->shar_off & 0x7f); /*sdr[24] = modifier offset*/
+ if (fdebug) printf("share count = %d, mod_offset = %d\n",shar_cnt,j);
+ if ((sdr02->shar_cnt & 0x10) != 0) { /*alpha*/
+ idstr[ilen++] = 0x40 + j; /* j=1 -> 'A' */
+ idstr[ilen] = 0; /* stringify */
+ } else { /*numeric*/
+ sprintf(&idstr[ilen],"%d",j);
+ ilen = strlen_(idstr);
+ }
+ } /* else normal idstr */
+ for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; }
+ idstr[ilen] = 0; /* stringify */
+ if ((sdr02->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/
+ else brearm = 'a'; /*automatic rearm*/
+ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%d, s0=%x\n",
+ ilen,idstr[0],sizeof(SDR02REC),sdr[ioff]);
+ memset(sens,0,sizeof(sens));
+ rc = GetSensorReading(sdr02->sens_num,sdr02,sens);
+ if (rc != 0) { /* if rc != 0, leave sens values zero */
+ i = 41; /* Unknown */
+ val = 0;
+ if (rc == 0xCB) { /*sensor not present*/
+ i = 10; /* Absent */
+ typestr = "na";
+ } else typestr = decode_rv(rc);
+ } else {
+ if ((sens[1] & 0x20) != 0) i = 42; /*init state, NotAvailable*/
+ else {
+ rc = decode_oem_sensor(sdr,sens,oem_string,sizeof(oem_string));
+ if (rc == 0) i = STR_OEM;
+ else i = decode_comp_reading(sdr02->sens_type,sdr02->ev_type,
+ sdr02->sens_num,sens[2],sens[3]);
+ }
+ }
+ if (fdebug)
+ printf("snum %x type %x evt %x reading %02x%02x i=%d rc=%d %s\n",
+ sdr02->sens_num,sdr02->sens_type,sdr02->ev_type,
+ sens[3],sens[2],i,rc, decode_rv(rc));
+ j = sens[2] | ((sens[3] & 0x7f) << 8); /*full reading, less h.o. bit*/
+ sep[0] = 0; /*null string*/
+ printf("%s", tag);
+ if (fsimple) {
+ sprintf(sep,"%c ",bdelim);
+ printf("%04x %c Compact %c %s %c %02x %c %s %c %s %c%c",
+ sdr02->recid, bdelim, bdelim,
+ get_stype_str(sdr02->sens_type),
+ bdelim, sdr02->sens_num, bdelim, idstr,
+ bdelim, sensor_dstatus[i],bdelim,chEol);
+ } else if (i == STR_OEM) {
+ // idstr[ilen] = 0; /*cut out padding in idstr*/
+ printf("%04x SDR Comp %02x %02x %02x %c %02x snum %02x %s = %04x %s%c",
+ sdr02->recid, sdr02->rectype, sdr02->ev_type,
+ sdr02->sens_ownid, brearm, sdr02->sens_type, sdr02->sens_num,
+ idstr, j, sensor_dstatus[i],chEol);
+ // sensor_dstatus[i] == oem_string
+ } else {
+ printf("%04x SDR Comp %02x %02x %02x %c %02x snum %02x %s = %04x %s%c",
+ sdr02->recid, sdr02->rectype, sdr02->ev_type,
+ sdr02->sens_ownid, brearm, sdr02->sens_type, sdr02->sens_num,
+ idstr, j, sensor_dstatus[i],chEol);
+ /* idstr, sens[0], sens[1], sens[2], sens[3], */
+ }
+ if (fdebug && fshowthr)
+ printf("cap=%02x settable=%02x, readable=%02x\n",
+ sens_cap,sdr[19],sdr[18]);
+ if (fshowthr) /*also show Entity ID */
+ printf("\t%sEntity ID %d.%d (%s), Capab: %s%c",
+ sep, sdr02->entity_id, sdr02->entity_inst,
+ decode_entity_id(sdr02->entity_id), // sens_cap,
+ decode_capab(sens_cap),chEol);
+ if (fshowthr &&
+ ((sens_cap & 0x80) == 0) && (sens_cap & 0x0C) != 0) {
+ uchar thresh[7];
+ /* Thresholds, show them */
+ /* Use readable bits to get & show thresholds */
+ if (sdr[20] != 0) {
+ rc = GetSensorThresholds(sdr02->sens_num,&thresh[0]);
+ if (rc == 0) ShowThresh(1,thresh[0],&thresh[1],sdr);
+ }
+ }
+ if (fwrap) { /*include time and \n */
+ time_t ltime;
+ time(&ltime);
+ if (fsimple)
+ printf("%c %s",bdelim,ctime(&ltime)); /*ctime has '\n' */
+ else
+ printf("at %s",ctime(&ltime)); /*ctime has '\n' */
+ }
+ break;
+ case 0x03: /* Event-only sensor record, treat like Compact SDR */
+ sdr02 = (SDR02REC *)sdr;
+ ioff = 17;
+ if (ioff > len) {
+ printf("Bad SDR %x Length %d. Please apply the correct FRU/SDR diskette\n",
+ sdr02->recid, len);
+ return;
+ }
+ if (!fsimple)
+ {
+ ilen = len - ioff;
+ if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1;
+ memcpy(idstr,&sdr[ioff],ilen);
+ for (i=ilen; i<16; i++) { idstr[i] = ' '; ilen++; }
+ idstr[ilen] = 0; /* stringify */
+ sens_cap = sdr[11];
+ memset(sens,0,sizeof(sens));
+ if ((sdr02->sens_capab & 0x40) == 0) brearm = 'm'; /*manual rearm*/
+ else brearm = 'a'; /*automatic rearm*/
+ // rc = GetSensorReading(sdr02->sens_num,sdr02,sens);
+ /* EvtOnly SDRs do not support readings.
+ * GetSensorReading would return ccode=0xCB (not present),
+ * but this skips error msg */
+ rc = 0xCB;
+ i = bitnum((ushort)sens[2]);
+ j = sens[2] | ((sens[3] & 0x7f) << 8);
+ printf("%s",tag);
+ printf("%04x SDR EvtO %02x %02x %02x %c %02x snum %02x %s = %04x %s\n",
+ sdr02->recid, sdr02->rectype, sdr02->reclen,
+ sdr02->sens_ownid, 'a', sdr[10], sdr02->sens_num,
+ idstr, j, sensor_dstatus[i]);
+ // sens[0], sens[1], sens[2], sens[3], sensor_dstatus[i]
+ }
+ break;
+ case 0x08: /* Entity Association record */
+ sdr08 = (SDR08REC *)sdr;
+ if (!fsimple)
+ {
+ printf("%s",tag);
+ printf("%04x SDR EntA %02x %02x %02x %02x %02x: ",
+ sdr08->recid, sdr08->rectype, sdr08->reclen,
+ sdr08->contid, sdr08->continst, sdr08->flags);
+ for (i = 0; i < 8; i++) printf("%02x ",sdr08->edata[i]);
+ printf("\n");
+ }
+ break;
+ case 0x09: /* Device-relative Entity Association record */
+ sdr08 = (SDR08REC *)sdr; /*but SDR09 is 26 bytes*/
+ if (!fsimple)
+ {
+ printf("%s",tag);
+ printf("%04x SDR DEnt %02x %02x %02x %02x %02x %02x %02x: ",
+ sdr08->recid, sdr08->rectype, sdr08->reclen,
+ sdr08->contid, sdr08->continst, sdr08->flags,
+ sdr08->edata[0], sdr08->edata[1]);
+ /*display 2 of 4 contained entity devices edata[2-10] */
+ for (i = 2; i < 8; i++) printf("%02x ",sdr08->edata[i]);
+ printf("\n");
+ }
+ break;
+ case 0x10: /* Generic Device Locator record */
+ sdr11 = (SDR11REC *)sdr;
+ ioff = 16;
+ if (ioff > len) {
+ if (fdebug) printf("SDR %x bad length: type=%x, len=%d, ioff=%d\n",
+ sdr11->recid, sdr[3],len,ioff);
+ return;
+ }
+ if (!fsimple)
+ {
+ ilen = len - ioff;
+ if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1;
+ memcpy(idstr,&sdr[ioff],ilen);
+ idstr[ilen] = 0; /* stringify */
+ printf("%s", tag);
+ if (fsimple)
+ printf("DevLocator record[%x]%c device %02x %c %s\n",
+ sdr11->recid, bdelim,sdr11->dev_slave_adr,bdelim,idstr);
+ else
+ printf("%04x SDR DLoc %02x %02x dev: %02x %02x %02x %02x %02x %02x %s\n",
+ sdr11->recid, sdr11->rectype, sdr11->reclen,
+ sdr11->dev_access_adr, sdr11->dev_slave_adr,
+ sdr11->access_lun, sdr[8], sdr[10], sdr[11],
+ idstr);
+ }
+ break;
+ case 0x11: /* FRU record */
+ sdr11 = (SDR11REC *)sdr;
+ ioff = 16;
+ if (ioff > len) {
+ if (fdebug) printf("SDR %x bad length: type=%x len=%d ioff=%d\n",
+ sdr11->recid, sdr[3],len,ioff);
+ printf("Please apply the correct FRU/SDR diskette\n");
+ return;
+ }
+ if (!fsimple)
+ {
+ ilen = len - ioff;
+ if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1;
+ memcpy(idstr,&sdr[ioff],ilen);
+ idstr[ilen] = 0; /* stringify */
+ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%d, s0=%x\n",
+ ilen,idstr[0],sizeof(SDR11REC),sdr[ioff]);
+ printf("%s", tag);
+ if (fsimple)
+ printf("FRU record[%x]: device %02x : %s\n",
+ sdr11->recid, sdr11->dev_slave_adr,idstr);
+ else
+ printf("%04x SDR FRU %02x %02x dev: %02x %02x %02x %02x %02x %02x %s\n",
+ sdr11->recid, sdr11->rectype, sdr11->reclen,
+ sdr11->dev_access_adr, sdr11->dev_slave_adr /*fru_id*/,
+ sdr11->access_lun, sdr11->chan_num,
+ sdr11->entity_id, sdr11->entity_inst,
+ idstr);
+ }
+ break;
+ case 0x12: /* IPMB record */
+ sdr12 = (SDR12REC *)sdr;
+ ioff = 16;
+ if (ioff > len) {
+ if (fdebug) printf("bad length: type=%x, len=%d, ioff=%d\n",
+ sdr[3],len,ioff);
+ printf("Please apply the correct FRU/SDR diskette\n");
+ return;
+ }
+ if (!fsimple)
+ {
+ ilen = len - ioff;
+ if (ilen >= sizeof(idstr)) ilen = sizeof(idstr) - 1;
+ memcpy(idstr,&sdr[ioff],ilen);
+ idstr[ilen] = 0; /* stringify */
+ if (fdebug) printf("ilen=%d, istr0=%c, sizeof=%d, s0=%x\n",
+ ilen,idstr[0],sizeof(SDR12REC),sdr[ioff]);
+ printf("%s", tag);
+ if (fsimple)
+ printf("IPMB record[%x]%c addr %02x %02x %c %s\n",
+ sdr12->recid, bdelim,sdr12->dev_slave_adr,
+ sdr12->chan_num,bdelim,idstr);
+ else
+ printf("%04x SDR IPMB %02x %02x dev: %02x %02x %02x %02x %02x %s\n",
+ sdr12->recid, sdr12->rectype, sdr12->reclen,
+ sdr12->dev_slave_adr, sdr12->chan_num, sdr12->dev_capab,
+ sdr12->entity_id, sdr12->entity_inst,
+ idstr);
+ }
+ break;
+ case 0x14: /* BMC Message Channel Info record */
+ sdr14 = (SDR14REC *)sdr;
+ if(!fsimple){
+ printf("%s", tag);
+ printf("%04x SDR BMsg %02x %02x: ",
+ sdr14->recid, sdr14->rectype, sdr14->reclen );
+ for (i = 0; i < 8; i++) printf("%02x ",sdr14->mdata[i]);
+ printf("%s %s %02x\n",decode_itype(sdr14->mint),
+ decode_itype(sdr14->eint), sdr14->rsvd);
+ }
+ break;
+ case 0xc0: /* OEM SDR record (manuf_id 343. = Intel) */
+ sdrc0 = (SDRc0REC *)sdr;
+ if(!fsimple)
+ {
+ vend = sdrc0->manuf_id[0] + (sdrc0->manuf_id[1] << 8)
+ + (sdrc0->manuf_id[2] << 16);
+ printf("%s",tag);
+ printf("%04x SDR OEM %02x %02x ",
+ sdrc0->recid, sdrc0->rectype, sdrc0->reclen);
+ show_oemsdr(vend,sdr);
+ }
+ break;
+ default:
+ sdrc0 = (SDRc0REC *)sdr;
+ /* also saw type = 0x08 & 0x14 on STL2s */
+ if (!fsimple){
+ printf("%s", tag);
+ printf("%04x SDR type=%02x ", sdrc0->recid, sdr[3]);
+ for (i = 0; i < len; i++) printf("%02x ",sdr[i]);
+ printf("\n");
+ }
+ }
+ return;
+}
+
+static int
+ShowPowerOnHours(void)
+{
+ uchar resp[MAX_BUFFER_SIZE];
+ int sresp = MAX_BUFFER_SIZE;
+ uchar cc;
+ int rc = -1;
+ int i;
+ unsigned int hrs;
+
+ if (fmBMC) return(0);
+ if (fsimple) return(0);
+ sresp = MAX_BUFFER_SIZE;
+ memset(resp,0,6); /* default response size is 5 */
+ rc = ipmi_cmd_mc(GET_POWERON_HOURS, NULL, 0, resp, &sresp, &cc, fdebug);
+ if (rc == 0 && cc == 0) {
+ /* show the hours (32-bits) */
+ hrs = resp[1] | (resp[2] << 8) | (resp[3] << 16) | (resp[4] << 24);
+ if (resp[0] == 0) /*avoid div-by-zero*/ i = 1;
+ else if (resp[0] == 60) /*normal*/ i = 1;
+ else {
+ i = 60 / resp[0];
+ hrs = hrs / i;
+ }
+ printf(" SDR IPMI sensor: Power On Hours \t = %d hours\n",
+ hrs);
+ }
+ if (fdebug) {
+ printf("PowerOnHours (rc=%d cc=%x len=%d): ",rc,cc,sresp);
+ if (rc == 0)
+ for (i = 0; i < sresp; i++) printf("%02x ",resp[i]);
+ printf("\n");
+ }
+ return(rc);
+}
+
+int SaveThreshold(int id, int sensor_num, int sensor_lo, int sensor_hi,
+ uchar *thr_set)
+{
+ int rv = 0;
+ char lostr[20];
+ char histr[20];
+ FILE *fd;
+
+ /* persist the thresholds by re-applying with ipmiutil sensor commands.*/
+ if (thr_set != NULL) {
+ sprintf(lostr,"-u 0x%02x%02x%02x%02x%02x%02x",
+ sensor_thr[0], sensor_thr[1], sensor_thr[2],
+ sensor_thr[3], sensor_thr[4], sensor_thr[5]);
+ histr[0] = 0; /*empty string*/
+ } else {
+ if (sensor_lo != 0xff) {
+ sprintf(lostr,"-l 0x%02x",sensor_lo);
+ } else lostr[0] = 0;
+ if (sensor_hi != 0xff) {
+ sprintf(histr,"-h 0x%02x",sensor_hi);
+ } else histr[0] = 0;
+ }
+ fd = fopen(savefile,"a+");
+ if (fd == NULL) return(-1);
+ fprintf(fd, "ipmiutil sensor -i 0x%04x -n 0x%02x %s %s\n", id, sensor_num,
+ lostr,histr);
+ fclose(fd);
+ return(rv);
+}
+
+#ifdef NOT_USED
+#define PICMG_GET_ADDR_INFO 0x01
+static int get_picmg_addrinfo(uchar a1, uchar a2, uchar *addrdata)
+{
+ uchar idata[5];
+ uchar rdata[16];
+ int rlen;
+ ushort icmd;
+ uchar ilen, cc;
+ int rv;
+
+ idata[0] = 0x00;
+ idata[1] = 0x00;
+ idata[2] = 0x03;
+ idata[3] = a1; /* 01 thru 0f */
+ idata[4] = a2; /* 00, 01 thru 09 */
+ ilen = 5;
+ rlen = sizeof(rdata);
+ icmd = PICMG_GET_ADDR_INFO | (NETFN_PICMG << 8);
+ rv = ipmi_cmd_mc(icmd, idata, ilen, rdata, &rlen, &cc, fdebug);
+ if (rv == 0 && cc != 0) rv = cc;
+ if (rv == 0) {
+ if (fdebug) {
+ printf("picmg_addr(%02x,%02x)",a1,a2);
+ dump_buf("picmg_addr",rdata,rlen,0);
+ }
+ memcpy(addrdata,rdata,rlen);
+ }
+ return(rv);
+}
+#endif
+
+#ifdef WIN32
+static int get_filesize(char *fileName, ulong *psize)
+{
+ int rv;
+ WIN32_FILE_ATTRIBUTE_DATA fileInfo;
+
+ if (fileName == NULL) return -1;
+ if (psize == NULL) return -1;
+ rv = GetFileAttributesEx(fileName, GetFileExInfoStandard, (void*)&fileInfo);
+ if (!rv) return -1;
+ *psize = (long)fileInfo.nFileSizeLow;
+ return 0;
+}
+#endif
+
+int read_sdr_binfile(char *binfile, uchar **pbufret, int *buflen)
+{
+ uchar *pbuf = NULL;
+ FILE *fp;
+ int len;
+ int ret;
+#ifdef WIN32
+ {
+ ulong flen;
+ ret = get_filesize(binfile, &flen);
+ if (ret == 0) len = flen;
+ else {
+ ret = get_LastError();
+ printf("Cannot get file size for %s, error %d\n",binfile,ret);
+ return(ret);
+ }
+ }
+#endif
+ fp = fopen(binfile,"r");
+ if (fp == NULL) {
+ ret = get_LastError();
+ printf("Cannot open file %s, error %d\n",binfile,ret);
+ return(ret);
+ }
+#ifndef WIN32
+ {
+ struct stat st;
+ /* use fstat to get file size and allocate buffer */
+ ret = fstat(fileno(fp), &st);
+ len = st.st_size; /*file size in bytes*/
+ if (ret != 0) {
+ ret = get_LastError();
+ printf("Cannot stat file %s, error %d\n",binfile,ret);
+ return(ret);
+ }
+ }
+#endif
+ // len = nsdrs * SDR_SZ; /*estimate max size for n sdrs*/
+ sz_sdrs = len;
+ pbuf = malloc(len);
+ if (fdebug) printf("restore: malloc(%d) pbuf=%p\n",len,pbuf);
+ if (pbuf == NULL) {
+ ret = -1;
+ fclose(fp);
+ return(ret);
+ }
+ /*ok, so proceed with restore*/
+ ret = 0;
+ len = (int)fread(pbuf, 1, sz_sdrs, fp);
+ if (len <= 0) {
+ ret = get_LastError();
+ printf("Error %d reading file %s\n",ret,binfile);
+ sz_sdrs = 0; /*for safety*/
+ }
+ fclose(fp);
+ if (fdebug) {
+ printf("SDR buffer from file (len=%d,sz=%d)\n",len,sz_sdrs);
+ dump_buf("SDR buffer",pbuf,len,1);
+ }
+ *pbufret = pbuf;
+ *buflen = len;
+ return(ret);
+}
+
+#ifdef ALONE
+#ifdef WIN32
+int __cdecl
+#else
+int
+#endif
+main(int argc, char **argv)
+#else
+/* METACOMMAND or libipmiutil */
+int i_sensor(int argc, char **argv)
+#endif
+{
+ int ret, rv;
+ int c;
+ int recid, recnext;
+ uchar sdrdata[MAX_BUFFER_SIZE];
+ uchar devrec[16];
+ int sz, i, j;
+ int fsetfound = 0;
+ int iloop;
+ int ipass, npass;
+ uchar *pset;
+ char *p;
+ char *s1;
+
+ printf("%s: version %s\n",progname,progver);
+
+ while ( (c = getopt( argc, argv,"a:bcd:ef:g:h:i:j:l:m:n:opqrstu:vwxT:V:J:L:EYF:P:N:R:U:Z:?")) != EOF )
+ switch(c) {
+ case 'a': /* reArm sensor number N */
+ if (strncmp(optarg,"0x",2) == 0) frearm = htoi(&optarg[2]);
+ else frearm = htoi(optarg); /*was atoi()*/
+ break;
+ case 'c': fsimple = 1; break; /* Canonical/simple output*/
+ case 'd': fdump = 1; /* Dump SDRs to a file*/
+ binfile = optarg; break;
+ case 'b': fchild = 1; break; /* Bladed, so get child SDRs */
+ case 'e': fchild = 1; break; /* Extra bladed child SDRs */
+ case 'f': frestore = 1; /* Restore SDRs from a file*/
+ binfile = optarg; break;
+ case 's': fsimple = 1; break; /* Simple/canonical output */
+ /*fcanonical==fsimple*/
+ case 'g':
+ rv = get_group_id(optarg);
+ if (rv < 0) {
+ printf("Unrecognized sensor type group (%s)\n",optarg);
+ ret = ERR_BAD_PARAM;
+ goto do_exit;
+ } else fshowgrp = rv;
+ if (fdebug) printf("num sensor type groups = %d\n",fshowgrp);
+ break;
+ case 'i':
+ fshowidx = 1;
+ get_idx_range(optarg);
+ break;
+ case 'j': fjumpstart = 1; /* Load SDR cache from a file*/
+ binfile = optarg; break;
+ case 't': fshowthr = 1; break;
+ case 'v': fshowthr = 1; sens_verbose = 1; break;
+ case 'p': fsavethresh = 1; break;
+ case 'q': fshowthr = 2; fwrap = 1; break;
+ case 'r': frawsdr = 1; break;
+ case 'm': /* specific MC, 3-byte address, e.g. "409600" */
+ g_bus = htoi(&optarg[0]); /*bus/channel*/
+ g_sa = htoi(&optarg[2]); /*device slave address*/
+ g_lun = htoi(&optarg[4]); /*LUN*/
+ if (optarg[6] == 's') {
+ g_addrtype = ADDR_SMI; s1 = "SMI";
+ } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; }
+ fset_mc = 1;
+ printf("set MC at %s bus=%x sa=%x lun=%x\n",
+ s1,g_bus,g_sa,g_lun);
+ break;
+ case 'o':
+ fgetmem = 1;
+ break;
+ case 'n':
+ if (strncmp(optarg,"0x",2) == 0) i = htoi(&optarg[2]);
+ else i = htoi(optarg); /*was atoi()*/
+ sensor_num = (uchar)i;
+ printf("sensor_num = 0x%x\n",sensor_num);
+ break;
+ case 'h': /* highest threshold */
+ if (strncmp(optarg,"0x",2) == 0) {
+ i = htoi(&optarg[2]);
+ sensor_hi = (uchar)i;
+ fsetthresh = 1;
+ } else {
+ sensor_hi_f = atof(optarg);
+ fsetthresh = 2; /*indicates float conversion*/
+ }
+ break;
+ case 'l': /* lowest threshold */
+ if (strncmp(optarg,"0x",2) == 0) {
+ i = htoi(&optarg[2]);
+ sensor_lo = (uchar)i;
+ fsetthresh = 1;
+ } else {
+ sensor_lo_f = atof(optarg);
+ fsetthresh = 2; /*indicates float conversion*/
+ }
+ break;
+ case 'u': /* specify unique thresholds in hex or float */
+ /* raw hex format: 0xLNLCLUHNHCHU, all 6 required */
+ if (strncmp(optarg,"0x",2) == 0) { /*raw hex thresholds*/
+ sensor_thr[0] = htoi(&optarg[2]); /*lo noncrit*/
+ sensor_thr[1] = htoi(&optarg[4]); /*lo crit*/
+ sensor_thr[2] = htoi(&optarg[6]); /*lo unrec*/
+ sensor_thr[3] = htoi(&optarg[8]); /*hi noncrit*/
+ sensor_thr[4] = htoi(&optarg[10]); /*hi crit*/
+ sensor_thr[5] = htoi(&optarg[12]); /*hi unrec*/
+ /* validate sensor threshold ordering */
+ rv = validate_thresholds(&sensor_thr[0],0,NULL);
+ if (rv == 0) {
+ sensor_lo = sensor_thr[0];
+ sensor_hi = sensor_thr[3];
+ fsetthresh = 3; /*indicates unique raw thresholds */
+ } else {
+ ret = ERR_BAD_PARAM;
+ goto do_exit;
+ }
+ } else {
+ /* assume float input thresholds, with ':' separator*/
+ /* format LN:LC:LU:HN:HC:HU */
+ sz = strlen_(optarg);
+ p = &optarg[0];
+ for (i = 0; i < 6; i++) sensor_thrf[i] = THR_EMPTY;
+ j = 0;
+ for (i = 0; i <= sz; i++) {
+ if (j >= 6) break;
+ switch(optarg[i]) {
+ case ':':
+ case '\n':
+ case '\0':
+ optarg[i] = 0;
+ if (p[0] == 0) sensor_thrf[j] = THR_EMPTY;
+ else sensor_thrf[j] = atof(p);
+ if (i+1 < sz) p = &optarg[i+1];
+ j++;
+ break;
+ default:
+ break;
+ }
+ }
+ /* validate sensor threshold ordering later */
+ // rv = validate_thresholds(&sensor_thrf[0],1,NULL);
+ // if (rv == 0) {
+ sensor_lo_f = sensor_thrf[0];
+ sensor_hi_f = sensor_thrf[3];
+ fsetthresh = 4; /*indicates unique float thresholds */
+ // } else {
+ // ret = ERR_BAD_PARAM;
+ // goto do_exit;
+ // }
+ } /*end-else -u float thresholds*/
+ break;
+ case 'w': fwrap = 1; break;
+ case 'x': fdebug = 1; break;
+ case 'L': /* Loop */
+ nloops = atoi(optarg);
+ fdoloop = 1;
+ break;
+ case 'V': /* priv level */
+ fprivset = 1;
+ case 'N': /* nodename */
+ case 'U': /* remote username */
+ case 'P': /* remote password */
+ case 'R': /* remote password */
+ case 'E': /* get password from IPMI_PASSWORD environment var */
+ case 'F': /* force driver type */
+ case 'T': /* auth type */
+ case 'J': /* cipher suite */
+ case 'Y': /* prompt for remote password */
+ case 'Z': /* set local MC address */
+ parse_lan_options(c,optarg,fdebug);
+ break;
+ default: /*usage*/
+ printf("Usage: %s [-abcdefghijlmnprstuvwxL -NUPREFTVY]\n",progname);
+ printf("where -x shows eXtra debug messages\n");
+ printf(" -a snum reArms the sensor (snum) for events\n");
+ printf(" -b show Bladed child MCs for PICMG (same as -e)\n");
+ printf(" -c displays a simpler, Canonical output fmt\n");
+ printf(" -d file Dump SDRs to a binary file\n");
+ printf(" -e show Every bladed child MC for PICMG\n");
+ // printf(" -f file Restore SDRs from a binary dump file\n");
+ printf(" -g fan show only this sensor type group\n");
+ printf(" -h tval specifies the Highest threshold to set\n");
+ printf(" -i id only show these sensor ids\n");
+ printf(" -j file Jump-start SDR cache from a binary file\n");
+ printf(" -l tval specifies the Lowest threshold to set\n");
+ printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n");
+ printf(" -n snum specifies the sensor Number to set hi/lo\n");
+ printf(" -o output memory DIMM information\n");
+ printf(" -p persist the threshold being set\n");
+ printf(" -q shows threshold values in d:d:d format\n");
+ printf(" -r show Raw SDR bytes\n");
+ printf(" -s displays a Simpler output format\n");
+ printf(" -t shows Threshold values in text format\n");
+ printf(" -u thr set Unique threshold values (e.g. 3:2:1:48:49:50)\n");
+ printf(" -v Verbose: thresholds, max/min, hysteresis\n");
+ printf(" -w Wrap thresholds on sensor line\n");
+ printf(" -L n Loop n times\n");
+ print_lan_opt_usage();
+ ret = ERR_USAGE;
+ goto do_exit;
+ }
+ if (fjumpstart && fchild) {
+ printf("Cannot use -j jumpstart cache with -c child SDRs\n");
+ ret = ERR_BAD_PARAM;
+ goto do_exit;
+ }
+ fremote = is_remote();
+#ifndef WIN32
+ if (fremote == 0) {
+ /* only run this as superuser for accessing IPMI devices. */
+ i = geteuid();
+ if (i > 1) {
+ printf("Not superuser (%d)\n", i);
+ ret = ERR_NOT_ALLOWED;
+ goto do_exit;
+ }
+ }
+#endif
+ if (fremote) {
+ if (!fprivset) {
+ /* on many systems, getting the SDR Reservation ID requires admin */
+ /* if ((fsetthresh != 0) || (frearm != 0)) also require admin */
+ parse_lan_options('V',"4",0);
+ }
+ }
+
+ ret = ipmi_getdeviceid(devrec,sizeof(devrec),fdebug);
+ if (ret == 0) {
+ uchar ipmi_maj;
+ uchar ipmi_min;
+ char *pstr;
+ ipmi_maj = devrec[4] & 0x0f;
+ ipmi_min = devrec[4] >> 4;
+ if ((devrec[1] & 0x80) == 0x80) fdevsdrs = 1;
+ vend_id = devrec[6] + (devrec[7] << 8) + (devrec[8] << 16);
+ prod_id = devrec[9] + (devrec[10] << 8);
+ if (vend_id == VENDOR_NSC) { /*NSC mBMC*/
+ pstr = "mBMC";
+ fmBMC = 1;
+ fdevsdrs = 0;
+ } else if (vend_id == VENDOR_INTEL) { /*Intel BMC*/
+ /*Intel Sahalee BMC */
+ pstr = "BMC";
+ fmBMC = 0;
+ if (is_romley(vend_id,prod_id)) fRomley = 1;
+ if (prod_id == 0x003E || fRomley) /*Urbanna NSN2U,CG2100*/
+ set_max_kcs_loops(URNLOOPS); /*longer KCS timeout*/
+ } else { /* Other products */
+ pstr = "BMC";
+ fmBMC = 0;
+ if (vend_id == VENDOR_NEC) fdevsdrs = 0;
+ }
+ show_devid( devrec[2], devrec[3], ipmi_maj, ipmi_min);
+ // "-- %s version %x.%x, IPMI version %d.%d \n", pstr,
+ } else {
+ goto do_exit;
+ }
+
+ ret = ipmi_getpicmg( devrec, sizeof(devrec),fdebug);
+ if (ret == 0) fpicmg = 1;
+ /*if not PICMG, some vendors override to SDR Rep*/
+ fdevsdrs = use_devsdrs(fpicmg);
+ if (fdevsdrs) printf("supports device sdrs\n");
+ npass = 1;
+ if (g_sa != 0) {
+ /* target a specific MC via IPMB (usu a picmg blade) */
+ ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype);
+ fchild = 0; /* no children, only the specified address */
+ } else {
+#ifdef PICMG_CHILD
+ /* fchild set above if -b is specified to get Blade child SDRs */
+ /* npass = 2 will get both SdrRep & DevSdr passes on CMM */
+ if (fpicmg && fdevsdrs) {
+ npass = 2;
+ g_addrtype = ADDR_IPMB;
+ }
+#endif
+ g_sa = BMC_SA;
+ }
+
+ if (fgetmem) {
+ if (fremote) printf("Cannot get memory DIMM information remotely.\n");
+ else {
+ int msz;
+ char desc[80];
+ char szstr[25];
+ ret = -1;
+ for (j = 0; j < 1; j++) {
+ for (i = 0; i < 16; i++) {
+ rv = get_MemDesc(j, i, desc,&msz);
+ if (rv == 0) {
+ if (msz == 0) strcpy(szstr,"not present");
+ else if (msz & 0x8000)
+ sprintf(szstr,"size=%dKB",(msz & 0x7FFF));
+ else sprintf(szstr,"size=%dMB",msz);
+ printf("Memory Device (%d,%d): %s : %s\n",
+ j,i,desc,szstr);
+ ret = 0;
+ }
+ }
+ }
+ } /*end-else*/
+ goto do_exit;
+ }
+
+ if (fdump) {
+ uchar *pbuf = NULL;
+ FILE *fp;
+ int len;
+ ret = get_sdr_cache(&pbuf);
+ if (ret == 0) {
+ fp = fopen(binfile,"w");
+ if (fp == NULL) {
+ ret = get_LastError();
+ printf("Cannot open file %s, error %d\n",binfile,ret);
+ } else {
+ printf("Writing SDR size %d to %s ...\n",sz_sdrs,binfile);
+ len = (int)fwrite(pbuf, 1, sz_sdrs, fp);
+ fclose(fp);
+ if (len <= 0) {
+ ret = get_LastError();
+ printf("Error %d writing file %s\n",ret,binfile);
+ } else ret = 0;
+ }
+ free_sdr_cache(pbuf);
+ }
+ goto do_exit;
+ } /*endif fdump*/
+
+ if (frestore) {
+ uchar sdr[MAX_BUFFER_SIZE];
+ ushort id;
+ int slen;
+ uchar *pbuf = NULL;
+
+ ret = read_sdr_binfile(binfile,&pbuf,&slen);
+ if (ret == 0) { /*successful, so write SDRs */
+ nsdrs = find_nsdrs(pbuf);
+ printf("Ready to restore %d SDRs\n",nsdrs);
+ set_reserve(1);
+ ret = sdr_clear_repo(fdevsdrs);
+ if (ret != 0) {
+ printf("SDR Clear Repository error %d\n",ret);
+ goto do_exit;
+ }
+ id = 0;
+ while(find_sdr_next(sdr,pbuf,id) == 0) {
+ id = sdr[0] + (sdr[1] << 8);
+ if (fdebug) printf("adding SDR[%x]\n",id);
+ set_reserve(1);
+ ret = sdr_add_record(sdr,fdevsdrs);
+ if (ret != 0) {
+ printf("SDR[%x] add error %d\n",id,ret);
+ break;
+ }
+ } /*end while sdr*/
+ }
+ if (ret == 0) printf("Restored %d SDRs successfully.\n",nsdrs);
+ free_sdr_cache(pbuf); /* does nothing if (pbuf == NULL) */
+ goto do_exit;
+ } /*endif frestore*/
+
+ if (fjumpstart) {
+ uchar *pbuf = NULL;
+ int slen;
+ ret = read_sdr_binfile(binfile,&pbuf,&slen);
+ if (ret != 0) fjumpstart = 0; /* use normal method if error*/
+ else { /* set this as the SDR cache */
+ psdrcache = pbuf;
+ sz_sdrs = slen;
+ nsdrs = find_nsdrs(pbuf);
+ if (fdebug) printf("jumpstart cache: nsdrs=%d size=%d\n",nsdrs,slen);
+ }
+ } /*endif fjumpstart*/
+
+ for (ipass = 0; ipass < npass; ipass++)
+ {
+ if (fjumpstart) ; /*already got this above*/
+ else {
+ ret = GetSDRRepositoryInfo(&j,&fdevsdrs);
+ if (fdebug) printf("GetSDRRepositoryInfo: ret=%x nSDRs=%d\n",ret,j);
+ if (ret == 0 && j == 0) {
+ printf("SDR Repository is empty\n");
+ goto do_exit;
+ }
+ nsdrs = j;
+ }
+
+ /* show header for SDR records */
+ if (fsimple)
+ printf(" ID | SDRType | Type |SNum| Name |Status| Reading\n");
+ else
+ printf("_ID_ SDR_Type_xx ET Own Typ S_Num Sens_Description Hex & Interp Reading\n");
+
+ if (fwrap) chEol = ' ';
+ if (!fdoloop) nloops = 1;
+ for (iloop = 0; iloop < nloops; iloop++)
+ {
+ if (fshowidx) recid = sensor_idx1;
+ else recid = 0;
+ while (recid != 0xffff)
+ {
+ if (fjumpstart) {
+ ret = find_sdr_next(sdrdata,psdrcache,recid);
+ if (ret != 0) { ret = 0; break; } /*end of sdrs*/
+ recnext = sdrdata[0] + (sdrdata[1] << 8); /*same as recid*/
+ sz = sdrdata[4] + 5;
+ } else {
+ ret = GetSDR(recid,&recnext,sdrdata,sizeof(sdrdata),&sz);
+ if (fdebug)
+ printf("GetSDR[%04x]: ret = %x, next=%x\n",recid,ret,recnext);
+ if (ret != 0) {
+ if (ret > 0) { /* ret is a completion code error */
+ printf("%04x GetSDR error 0x%02x %s, rlen=%d\n",recid,ret,
+ decode_cc((ushort)0,(uchar)ret),sz);
+ if (ret == 0xC5) { /* lost Reservation ID, retry */
+ /* This means that some other IPMI software has
+ * requested a Reservation before we finished, so
+ * we need to refresh the Reservation ID * retry. */
+ fDoReserve = 1; /* get a new SDR Reservation ID */
+ ret = GetSDR(recid,&recnext,sdrdata,sizeof(sdrdata),&sz);
+ if (fdebug)
+ printf("GetSDR[%04x]: ret = %x, next=%x\n",recid,ret,
+ recnext);
+ }
+ } else printf("%04x GetSDR error %d, rlen = %d\n", recid,ret,sz);
+ if (sz < MIN_SDR_SZ) { /* don't have recnext, so abort */
+ break;
+ } /* else fall through & continue */
+ }
+ } /*end-else*/
+ if (ret == 0) { /* (ret == 0) OK, got full SDR */
+ if (fdebug) {
+ dump_buf("got SDR",sdrdata,sz,0);
+ }
+ if (sz < MIN_SDR_SZ) goto NextSdr;
+ /* if recid == 0, get real record id */
+ if (recid == 0) recid = sdrdata[0] + (sdrdata[1] << 8);
+ if (fshowgrp > 0) {
+ for (i = 0; i < fshowgrp; i++) {
+ uchar styp;
+ if (sdrdata[3] == 0x03) styp = sdrdata[10]; /*EvtOnly*/
+ else styp = sdrdata[12];
+ if (fdebug) printf("sdrt=%02x styp=%02x sgrp[%d]=%02x\n",
+ sdrdata[3],styp,i,sensor_grps[i]);
+ if (sdrdata[3] == 0xc0) continue; /*skip OEM SDRs*/
+ if (styp == sensor_grps[i]) break;
+ }
+ if (i >= fshowgrp) goto NextSdr;
+ }
+
+ if ((sensor_num == INIT_SNUM) || (sdrdata[7] == sensor_num)
+ || fsetthresh) {
+ /* if -n not set or if -n matches, parse and show the SDR */
+ ShowSDR("",sdrdata);
+ } /* else filter SDRs if not matching -n sensor_num */
+
+#ifdef PICMG_CHILD
+ /*
+ * Special logic for blade child MCs in PICMG ATCA systems
+ * if fchild, try all child MCs within the chassis.
+ * SDR type 12 capabilities bits (sdrdata[8]):
+ * 80 = Chassis Device
+ * 40 = Bridge
+ * 20 = IPMB Event Generator
+ * 10 = IPMB Event Receiver
+ * 08 = FRU Device
+ * 04 = SEL Device
+ * 02 = SDR Repository Device
+ * 01 = Sensor Device
+ * But all child MCs use Device SDRs anyway.
+ */
+ if (fpicmg && fchild && (sdrdata[3] == 0x12)) { /* PICMG MC DLR */
+ int _recid, _recnext, _sz;
+ uchar _sdrdata[MAX_SDR_SIZE];
+ int devsdrs_save;
+ uchar cc;
+
+ /* save the BMC globals, use IPMB MC */
+ devsdrs_save = fdevsdrs;
+ fdevsdrs = 1; /* use Device SDRs for the children*/
+ if (fdebug)
+ printf(" --- IPMB MC (sa=%02x cap=%02x id=%02x devsdrs=%d):\n",
+ sdrdata[5],sdrdata[8],sdrdata[12],fdevsdrs);
+ fDoReserve = 1; /* get a new SDR Reservation ID */
+ ipmi_set_mc(PICMG_SLAVE_BUS,sdrdata[5],sdrdata[6],g_addrtype);
+
+ _sz = 16;
+ ret = ipmi_cmd_mc(GET_DEVICE_ID,NULL,0,_sdrdata,&_sz,&cc,fdebug);
+ if (ret == 0 && cc == 0) {
+ /* Get the SDRs from the IPMB MC */
+ _recid = 0;
+ while (_recid != 0xffff)
+ {
+ ret = GetSDR(_recid,&_recnext,_sdrdata,sizeof(_sdrdata),&_sz);
+ if (ret != 0) {
+ printf("%04x GetSDR error %d, rlen = %d\n",_recid,ret,_sz);
+ break;
+ }
+ else if (_sz >= MIN_SDR_SZ)
+ ShowSDR(" ",_sdrdata);
+
+ if (_recnext == _recid) _recid = 0xffff;
+ else _recid = _recnext;
+ } /*end while*/
+ } /*endif ret==0*/
+
+ /* restore BMC globals */
+ fdevsdrs = devsdrs_save;
+ ipmi_restore_mc();
+ fDoReserve = 1; /* get a new SDR Reservation ID */
+ } /*endif fpicmg && fchild*/
+#endif
+
+ if (fdebug) printf("fsetthresh=%d snum=%02x(%02x) sa=%02x(%02x)\n",
+ fsetthresh,sdrdata[7],sensor_num,sdrdata[5],g_sa);
+ if (fsetthresh && (sdrdata[7] == sensor_num)
+ && (sdrdata[5] == g_sa)) /*g_sa usu is BMC_SA*/
+ {
+ /* setting threshold, compute threshold raw values */
+ if (fsetthresh == 2) { /*set from float*/
+ if (fdebug)
+ printf("lof=%.2f hif=%.2f\n", sensor_lo_f,sensor_hi_f);
+ if (sensor_lo_f != 0)
+ sensor_lo = FloatToRaw(sensor_lo_f,sdrdata,0);
+ if (sensor_hi_f != 0)
+ sensor_hi = FloatToRaw(sensor_hi_f,sdrdata,0);
+ } else if (fsetthresh == 1) { /*raw thresholds*/
+ if (sensor_hi != 0xff)
+ sensor_hi_f = RawToFloat(sensor_hi,sdrdata);
+ if (sensor_lo != 0xff)
+ sensor_lo_f = RawToFloat(sensor_lo,sdrdata);
+ } else if (fsetthresh == 3) { /*unique raw thresholds*/
+ if (sensor_hi != 0xff)
+ sensor_hi_f = RawToFloat(sensor_hi,sdrdata);
+ if (sensor_lo != 0xff)
+ sensor_lo_f = RawToFloat(sensor_lo,sdrdata);
+ } else if (fsetthresh == 4) { /*set unique from float*/
+ i = fill_thresholds(&sensor_thrf[0], sdrdata);
+ /* if (i > 0) ; * filled in some thresholds */
+ { /* always set lo/hi if any are non-zero */
+ for (j = 0; j < 3; j++) {
+ if (sensor_thrf[j] != 0) {
+ sensor_lo_f = sensor_thrf[j]; break; }
+ }
+ for (j = 3; j < 6; j++) {
+ if (sensor_thrf[j] != 0) {
+ sensor_hi_f = sensor_thrf[j]; break; }
+ }
+ }
+ if (fdebug)
+ printf("lof=%.2f hif=%.2f\n", sensor_lo_f,sensor_hi_f);
+ /* convert thrf (float) to thr (raw) */
+ if (sensor_lo_f != 0) {
+ sensor_lo = FloatToRaw(sensor_lo_f,sdrdata,0);
+ sensor_thr[0] = FloatToRaw(sensor_thrf[0],sdrdata,0);
+ sensor_thr[1] = FloatToRaw(sensor_thrf[1],sdrdata,0);
+ sensor_thr[2] = FloatToRaw(sensor_thrf[2],sdrdata,0);
+ }
+ if (sensor_hi_f != 0) {
+ sensor_hi = FloatToRaw(sensor_hi_f,sdrdata,0);
+ sensor_thr[3] = FloatToRaw(sensor_thrf[3],sdrdata,0);
+ sensor_thr[4] = FloatToRaw(sensor_thrf[4],sdrdata,0);
+ sensor_thr[5] = FloatToRaw(sensor_thrf[5],sdrdata,0);
+ }
+ /* validate threshold ordering */
+ if (validate_thresholds(sensor_thrf,1,sdrdata) != 0) {
+ ret = ERR_BAD_PARAM;
+ goto do_exit;
+ }
+ }
+ {
+ printf("\tSetting SDR %04x sensor %02x to lo=%02x hi=%02x\n",
+ recid,sensor_num,sensor_lo,sensor_hi);
+ if (recid == 0) fsetfound = 1;
+ else fsetfound = recid;
+ }
+ } /*endif fsetthresh */
+ } /*endif ok, got full SDR */
+
+NextSdr:
+ if (fshowidx) {
+ /* if we have already read the last in the range, done. */
+ if (recid >= sensor_idxN) break; // recnext = 0xffff; // break;
+ }
+ if (fjumpstart) recid = recnext;
+ else {
+ if (recnext == recid) recid = 0xffff; /*break;*/
+ else recid = recnext;
+ }
+ } /*end while recid*/
+ if (fdoloop && (nloops > 1)) {
+ printf("\n"); /* output an empty separator line */
+ os_usleep(1,0); /*delay 1 sec between loops*/
+ }
+ } /*end for nloops*/
+
+ if (npass > 1) { /* npass==2 for PICMG */
+ /* Switch fdevsdrs from Device to Repository */
+ if (fdevsdrs == 0) fdevsdrs = 1;
+ else fdevsdrs = 0;
+ fDoReserve = 1; /* get a new SDR Reservation ID */
+ }
+ } /*end for npass*/
+
+ if ((fshowidx == 0) && (fshowgrp == 0)) {
+ /* use local rv, errors are ignored for POH */
+ rv = ShowPowerOnHours();
+ }
+
+ if (frearm != 0) {
+ ret = RearmSensor((uchar)frearm);
+ printf("RearmSensor(0x%02x) ret = %d\n",frearm,ret);
+ }
+
+ if (fsetthresh != 0) {
+ uchar tdata[7];
+ if (fsetfound == 0) {
+ printf("Did not find sensor number %02x.\nPlease enter the sensor number parameter in hex, as it is displayed above.\n",sensor_num);
+ }
+ ret = GetSensorThresholds(sensor_num,tdata);
+ if (ret != 0) goto do_exit;
+#ifdef TEST
+ printf("thresh(%02x): %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ sensor_num, sensor_num, tdata[0], tdata[1], tdata[2],
+ tdata[3], tdata[4], tdata[5], tdata[6]);
+ printf(" set(%02x): %02x %02x \n",
+ sensor_num,sensor_lo,sensor_hi);
+#endif
+ if (fsetthresh == 3 || fsetthresh == 4) {
+ /* apply unique sensor thresholds */
+ pset = &sensor_thr[0];
+ } else pset = NULL; /* use just hi/lo */
+ ret = SetSensorThresholds(sensor_num,sensor_hi,sensor_lo,tdata,pset);
+ printf("SetSensorThreshold[%02x] to lo=%02x(%4.3f) hi=%02x(%4.3f), ret = %d\n",
+ sensor_num,sensor_lo,sensor_lo_f,sensor_hi,sensor_hi_f,ret);
+ if (fsavethresh && ret == 0) {
+ recid = fsetfound;
+ rv = SaveThreshold(recid,sensor_num,sensor_lo,sensor_hi,pset);
+ if (rv == 0)
+ printf("Saved thresholds for sensor %02x\n",sensor_num);
+ }
+ fsetthresh = 0; /*only set threshold once*/
+ }
+
+do_exit:
+ if (fjumpstart) free_sdr_cache(psdrcache); /* does nothing if ==NULL*/
+ /* show_outcome(progname,ret); *handled in ipmiutil.c*/
+ ipmi_close_();
+ return(ret);
+}
+
+/* end isensor.c */