summaryrefslogtreecommitdiff
path: root/util/idcmi.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/idcmi.c
Imported Upstream version 2.9.3upstream/2.9.3
Diffstat (limited to 'util/idcmi.c')
-rw-r--r--util/idcmi.c976
1 files changed, 976 insertions, 0 deletions
diff --git a/util/idcmi.c b/util/idcmi.c
new file mode 100644
index 0000000..1e53ae8
--- /dev/null
+++ b/util/idcmi.c
@@ -0,0 +1,976 @@
+/*
+ * idcmi.c
+ * Data Center Manageability Interface (DCMI) command support
+ *
+ * Change history:
+ * 11/17/2011 ARCress - created
+ *
+ *---------------------------------------------------------------------
+ */
+/*M*
+Copyright (c) 2011 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 Kontron 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*/
+
+#ifdef WIN32
+#include <windows.h>
+#include <stdlib.h>
+#include "getopt.h"
+#else
+#include <sys/types.h>
+#if defined(HPUX)
+/* getopt is defined in stdio.h */
+#elif defined(MACOS)
+/* getopt is defined in unistd.h */
+#include <unistd.h>
+#include <sys/time.h>
+#else
+#include <stdlib.h>
+#include <getopt.h>
+#endif
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include "ipmicmd.h"
+#include "isensor.h"
+#include "idcmi.h"
+
+static char * progname = "idcmi";
+static char * progver = "2.93";
+extern char fdebug; /*from ipmicmd.c*/
+static uchar g_bus = PUBLIC_BUS;
+static uchar g_sa = BMC_SA;
+static uchar g_lun = BMC_LUN;
+static uchar g_addrtype = ADDR_SMI;
+static uchar dcmi_ver = 0x00; /* 0x10, 0x11, or 0x15 */
+static uchar fpwm = 0; /* =1 if Power Management supported */
+static uchar do_sensors = 0;
+static uchar set_asset = 0;
+static uchar set_mcid = 0;
+static char *asset_new = NULL;
+static char *mcid_new = NULL;
+static int asset_len = 0;
+static int mcid_len = 0;
+static char mc_id[64];
+static char asset[64];
+
+#ifdef NOT
+/* see idcmi.h */
+#define NETFN_DCMI 0x2C
+#define CMD_DCMI_GET_CAPAB 0x01
+#define CMD_DCMI_GET_POWREAD 0x02
+#define CMD_DCMI_GET_POWLIMIT 0x03
+#define CMD_DCMI_SET_POWLIMIT 0x04
+#define CMD_DCMI_ACT_POWLIMIT 0x05
+#define CMD_DCMI_GET_ASSETTAG 0x06
+#define CMD_DCMI_GET_SENSORINF 0x07
+#define CMD_DCMI_SET_ASSETTAG 0x08
+#define CMD_DCMI_GET_MCIDSTR 0x09
+#define CMD_DCMI_SET_MCIDSTR 0x0A
+/* for DCMI 1.5 only */
+#define CMD_DCMI_SET_THERMLIM 0x0B
+#define CMD_DCMI_GET_THERMLIM 0x0C
+#define CMD_DCMI_GET_TEMPRDNGS 0x10
+#define CMD_DCMI_SET_CONFIG 0x12
+#define CMD_DCMI_GET_CONFIG 0x13
+#endif
+
+static int dcmi_usage(void)
+{
+ printf("Usage: %s [-admsx -NUPREFTVY] <function>\n", progname);
+ printf(" -a Set DCMI Asset Tag to this string\n");
+ printf(" -d Set DCMI MC ID to this string\n");
+ printf(" -m002000 specific MC (bus 00,sa 20,lun 00)\n");
+ printf(" -s Get DCMI sensor info\n");
+ printf(" -x Display extra debug messages\n");
+ print_lan_opt_usage();
+ printf("where <function> is one of:\n");
+ printf(" info Get DCMI Capabilities, MC ID, asset tag (default)\n");
+ printf(" power [get] Get Power reading & limit\n");
+ printf(" power set_limit <power> Set Power limit\n");
+ printf(" power set_action <action> Set Power limit exception action\n");
+ printf(" (action = no_action | power_off | log_sel)\n");
+ printf(" power set_correction <ms> Set Power limit correction time (in ms)\n");
+ printf(" power set_sample <sec> Set Power limit sampling period (in sec)\n");
+ printf(" power activate Activate Power limit\n");
+ printf(" power deactivate Deactivate Power limit\n");
+ printf(" thermal Get/Set DCMI Thermal parameters\n");
+ printf(" config Get/Set DCMI Configuration parameters\n");
+ printf(" help Show this help message\n");
+ return(ERR_USAGE);
+}
+
+static int dcmi_get_capab(int param, uchar *pdata, int sdata)
+{
+ uchar idata[4];
+ uchar rdata[32];
+ int rlen;
+ uchar cc;
+ int rv, i;
+
+ if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM);
+ idata[0] = 0xDC;
+ idata[1] = (uchar)param;
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_GET_CAPAB, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,2, rdata, &rlen, &cc, fdebug);
+ if ((rv != 0) || (cc != 0)) {
+ if (fdebug)
+ printf("dcmi_get_capab(%d): rv = %d, ccode %02x\n",param,rv,cc);
+ if (rv == 0) rv = cc;
+ return(rv);
+ }
+ /* if here, success */
+ if (fdebug) { /*show raw response*/
+ printf("dcmi_get_capab(%d): rlen = %d\n",param,rlen);
+ for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]);
+ printf("\n");
+ }
+ if (rlen > sdata) {
+ if (fdebug)
+ printf("dcmi_get_capab(%d): data truncated from %d to %d\n",
+ param,rlen,sdata);
+ rlen = sdata;
+ }
+ memcpy(pdata,rdata,rlen);
+ return(rv);
+}
+
+static int dcmi_get_power_read(int param, uchar *pdata, int sdata)
+{
+ uchar idata[5];
+ uchar rdata[32];
+ int rlen;
+ uchar cc;
+ int rv, i;
+
+ if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM);
+ idata[0] = 0xDC;
+ idata[1] = (uchar)param; /*mode 1 or 2*/
+ idata[2] = 0x00;
+ idata[3] = 0x00;
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_GET_POWREAD, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,4, rdata, &rlen, &cc, fdebug);
+ if (rv == 0) rv = cc;
+ if (fdebug) { /*show raw response*/
+ printf("dcmi_get_power_read(%d): rv = %d rlen = %d\n",param,rv,rlen);
+ for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]);
+ printf("\n");
+ }
+ if (rv == 0) { /* if here, success */
+ if (rlen > sdata) {
+ if (fdebug)
+ printf("dcmi_get_power_read(%d): data truncated from %d to %d\n",
+ param,rlen,sdata);
+ rlen = sdata;
+ }
+ memcpy(pdata,rdata,rlen);
+ }
+ return(rv);
+}
+
+static int dcmi_get_power_limit( uchar *pdata, int sdata)
+{
+ uchar idata[5];
+ uchar rdata[32];
+ int rlen;
+ uchar cc;
+ int rv, i;
+
+ if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM);
+ idata[0] = 0xDC;
+ idata[1] = 0x00;
+ idata[2] = 0x00;
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_GET_POWLIMIT, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,3, rdata, &rlen, &cc, fdebug);
+ if (rv == 0) rv = cc;
+ if (fdebug) { /*show raw response*/
+ printf("dcmi_get_power_limit: rv = %d rlen = %d\n",rv,rlen);
+ for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]);
+ printf("\n");
+ }
+ if (rv == 0) { /* if here, success */
+ if (rlen > sdata) {
+ if (fdebug)
+ printf("dcmi_get_power_limit: data truncated from %d to %d\n",
+ rlen,sdata);
+ rlen = sdata;
+ }
+ memcpy(pdata,rdata,rlen);
+ }
+ return(rv);
+}
+
+static int dcmi_set_power_limit(int param,int value, uchar *pow, int spow)
+{
+ int rv = 0;
+ uchar idata[32];
+ uchar rdata[32];
+ int rlen;
+ uchar cc;
+
+ if (spow > 15) spow = 15;
+ memcpy(idata,pow,spow);
+ switch(param)
+ {
+ case CORRECTION_TIME:
+ idata[10]=(uchar)((value >> 24) & 0xff);
+ idata[9] =(uchar)((value >> 16) & 0xff);
+ idata[8] =(uchar)((value >> 8) & 0xff);
+ idata[7] =(uchar)((value) & 0xff);
+ break;
+ case EXCEPTION_ACTION:
+ idata[4] = (uchar)(value & 0xff);
+ break;
+ case POWER_LIMIT:
+ idata[5] = (uchar)(value & 0xff);
+ idata[6] = (uchar)((value >> 8) & 0xff);
+ break;
+ case SAMPLE_PERIOD:
+ idata[14] = (uchar)((value >> 8) & 0xff);
+ idata[13] = (uchar)(value & 0xff);
+ break;
+ default:
+ return ERR_BAD_PARAM;
+ break;
+ }
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_SET_POWLIMIT, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,15, rdata, &rlen,&cc, fdebug);
+ if (fdebug)
+ printf("dcmi_set_power_limit(%d,%d): rv = %d cc = %x\n",
+ param,value,rv,cc);
+ if (rv == 0) rv = cc;
+ return (rv);
+}
+
+
+static int dcmi_power_limit_activate ( int yes)
+{
+ int rv;
+ uchar idata[5];
+ uchar rdata[32];
+ int rlen;
+ uchar cc;
+ if (yes < 0) return (ERR_BAD_PARAM);
+ if (yes > 1) return (ERR_BAD_PARAM);
+
+ idata[0] = 0xDC;
+ idata[1] = yes;
+ idata[2] = 0x00;
+ idata[3] = 0x00;
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_ACT_POWLIMIT, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,4, rdata, &rlen, &cc, fdebug);
+ if (fdebug)
+ printf("dcmi_power_limit_activate(%d): rv = %d cc = %x\n",yes,rv,cc);
+ if (rv == 0) rv = cc;
+ return(rv);
+}
+
+void dcmi_show_power_read(int parm, uchar *cdata, int sdata)
+{
+ int i;
+ ulong sample_period;
+ time_t t = 0;
+ uchar state;
+
+ if (fdebug) { /*++++*/
+ printf("dcmi_show_power_read(%d,%p,%d) called\n",parm,cdata,sdata);
+ for (i = 0; i < sdata; i++) printf("%02x ",cdata[i]);
+ printf("\n");
+ }
+ if (sdata < 18) {
+ printf("power_read data length %d is too short\n",sdata);
+ return;
+ }
+ if (cdata[0] != 0xDC) {
+ printf("power_read: invalid first data byte (0x%02x)\n",cdata[0]);
+ return;
+ }
+ memcpy(&t,&cdata[9],4);
+ sample_period = cdata[13];
+ sample_period += (cdata[14] << 8);
+ sample_period += (cdata[15] << 16);
+ sample_period += (cdata[16] << 24);
+ state = cdata[17];
+ switch(parm) {
+ case 1: /* Mode 1 - System Power Statistics */
+ printf(" Current Power: %d Watts\n",cdata[1]+(cdata[2]<<8));
+ printf(" Min Power over sample duration: %d Watts\n",cdata[3]+(cdata[4]<<8));
+ printf(" Max Power over sample duration: %d Watts\n",cdata[5]+(cdata[6]<<8));
+ printf(" Avg Power over sample duration: %d Watts\n",cdata[7]+(cdata[8]<<8));
+ printf(" Timestamp: %s\n",ctime(&t));
+ printf(" Sampling period: %d ms\n",sample_period);
+ printf(" Power reading state is: %s\n",(state&0x40)? "active":"not active");
+ break;
+ case 2: /* Mode 2 - Enhanced System Power Statistics */
+ printf("Enhanced Power Mode 2 decoding not yet implemented\n");
+ /* TODO */
+ // break;
+ default:
+ for (i = 0; i < sdata; i++) printf("%02x ",cdata[i]);
+ printf("\n");
+ break;
+ }
+}
+
+void dcmi_show_power_limit(uchar *cdata, int sdata, int rv)
+{
+ ulong correction_time;
+ char *pstr;
+
+ correction_time = cdata[6];
+ correction_time += (cdata[7] << 8);
+ correction_time += (cdata[8] << 16);
+ correction_time += (cdata[9] << 24);
+
+ if (rv == 0) pstr = "(active)";
+ else if (rv == 0x80) pstr = "(inactive)";
+ else pstr = "(error)";
+ printf(" Exception Action: ");
+ if (cdata[3] & 0x01)
+ printf("Hard Power off\n");
+ else if ((cdata[3] & 0x11) == 0x11)
+ printf("SEL logging\n");
+ else
+ printf("OEM defined\n");
+ printf(" Power Limit: %d Watts %s\n",cdata[4]+(cdata[5]<<8), pstr);
+ printf(" Correction Time: %d ms\n", correction_time);
+ printf(" Sampling period: %d sec\n", cdata[12]+(cdata[13]<<8));
+}
+
+static int dcmi_get_sensorinf(uchar styp, uchar snum, uchar offset,
+ uchar *pdata, int sdata)
+{
+ uchar idata[5];
+ uchar rdata[32];
+ int rlen;
+ uchar cc;
+ int rv, i;
+
+ if (pdata == NULL || sdata == 0) return(ERR_BAD_PARAM);
+ idata[0] = 0xDC;
+ idata[1] = styp; /*sensor type, 0x01 = Temperature*/
+ idata[2] = snum; /*sensor number */
+ idata[3] = 0x00; /*Entity Instance, 0 = all instances*/
+ idata[4] = offset; /*Entity Instance start/offset */
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_GET_SENSORINF, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,5, rdata, &rlen, &cc, fdebug);
+ if (rv == 0) rv = cc;
+ if (fdebug) { /*show raw response*/
+ printf("dcmi_get_sensorinf(%d): rlen = %d\n",snum,rlen);
+ for (i = 0; i < rlen; i++) printf("%02x ",rdata[i]);
+ printf("\n");
+ }
+ if (rv == 0) { /* if here, success */
+ if (rlen > sdata) {
+ if (fdebug)
+ printf("dcmi_get_sensorinf(%d): data truncated from %d to %d\n",
+ snum,rlen,sdata);
+ rlen = sdata;
+ }
+ memcpy(pdata,rdata,rlen);
+ }
+ return(rv);
+}
+
+static char *entstr(int i)
+{
+ char *pstr = NULL;
+ switch(i) {
+ case 0: pstr = "Inlet"; break;
+ case 1: pstr = "CPU"; break;
+ case 2:
+ default:
+ pstr = "Baseboard"; break;
+ }
+ return(pstr);
+}
+
+static int dcmi_get_sensors(int styp)
+{
+ int i, j, n, r, recs;
+ uchar offset, id;
+ uchar dbuf[20];
+ uchar s1;
+ int rv;
+ uchar *sdrs = NULL;
+ uchar sdr[128];
+
+ offset = 0;
+ r = 1; n = 8;
+ s1 = 0x40; /*0x40,0x41,0x42*/
+ rv = get_sdr_cache(&sdrs);
+
+ printf("---Sensors---\n");
+ for (i = 0; i < 3; i++)
+ {
+ rv = dcmi_get_sensorinf(styp,s1+i,offset,dbuf,sizeof(dbuf));
+ if (rv != 0) break;
+ n = dbuf[1];
+ recs = dbuf[2];
+ printf(" %d %s temp sensors: \tn_returned=%d\n",n,entstr(i),recs);
+ for (r = 0; r < n; r += recs)
+ {
+ recs = dbuf[2];
+ if (recs == 0) break;
+ for (j = 0; j < r; j++) {
+ id = (dbuf[4 + (2*j)] << 8) + dbuf[3 + (2*j)];
+ if (fdebug) printf("j=%d id=%x \n",j,id);
+ /* get the sensor info for each record id */
+ rv = find_sdr_next(sdr,sdrs,(id-1));
+ ShowSDR("",sdr);
+ }
+ offset += recs;
+ rv = dcmi_get_sensorinf(1,s1+i,offset,dbuf,sizeof(dbuf));
+ if (rv != 0) break;
+ }
+ }
+ if (rv != 0) printf("dcmi_get_sensors(%d,%d) error %d\n",styp,i,rv);
+ free_sdr_cache(sdrs);
+ return(rv);
+}
+
+static int dcmi_get_asset_tag(char *pdata, int sdata, int *dlen)
+{
+ uchar idata[4];
+ uchar rdata[32];
+ int rlen;
+ uchar cc;
+ int n, rv = -1;
+ int sz_chunk = 16;
+ int sz_all;
+
+ if (pdata == NULL || sdata < 16) return(ERR_BAD_PARAM);
+ memset(pdata,0,sdata);
+ sz_all = sdata;
+ for (n = 0; (n < sdata && n < sz_all); n += sz_chunk) {
+ idata[0] = 0xDC;
+ idata[1] = n; /*offset*/
+ idata[2] = sz_chunk; /*bytes to read*/
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_GET_ASSETTAG, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,3, rdata, &rlen, &cc, fdebug);
+ if (fdebug)
+ printf("dcmi_get_asset(%d): rv=%d ccode=%02x rlen=%d\n",
+ n,rv,cc,rlen);
+ if (rv == 0) rv = cc;
+ if (rv == 0) { /* if here, success */
+ if (n == 0) sz_all = rdata[1];
+ if ((n + sz_chunk) > sdata) {
+ if (fdebug)
+ printf("dcmi_get_asset(%d): data truncated from %d to %d\n",
+ n,(n+sz_chunk),sdata);
+ sz_chunk = (sdata - n);
+ }
+ memcpy(&pdata[n],&rdata[2],sz_chunk);
+ } else break;
+ } /*end-for loop*/
+ pdata[n] = 0; /*stringify*/
+ if (dlen != NULL) *dlen = n;
+ return(rv);
+}
+
+static int dcmi_get_mc_id(char *pdata, int sdata, int *dlen)
+{
+ uchar idata[4];
+ uchar rdata[32];
+ int rlen;
+ uchar cc;
+ int n, rv = -1;
+ int sz_chunk = 16;
+ int sz_all;
+
+ if (pdata == NULL || sdata < 16) return(ERR_BAD_PARAM);
+ memset(pdata,0,sdata);
+ sz_all = sdata;
+ for (n = 0; (n < sdata && n < sz_all); n += sz_chunk) {
+ idata[0] = 0xDC;
+ idata[1] = n; /*offset*/
+ idata[2] = sz_chunk; /*bytes to read*/
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_GET_MCIDSTR, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,3, rdata, &rlen, &cc, fdebug);
+ if (fdebug)
+ printf("dcmi_get_mc_id(%d): rv=%d ccode=%02x rlen=%d\n",
+ n,rv,cc,rlen);
+ if (rv == 0) rv = cc;
+ if (rv == 0) { /* if here, success */
+ if (n == 0) sz_all = rdata[1];
+ if ((n + sz_chunk) > sdata) {
+ if (fdebug)
+ printf("dcmi_get_mc_id(%d): data truncated from %d to %d\n",
+ n,(n+sz_chunk),sdata);
+ sz_chunk = (sdata - n);
+ }
+ memcpy(&pdata[n],&rdata[2],sz_chunk);
+ } else break;
+ } /*end-for loop*/
+ pdata[n] = 0; /*stringify*/
+ if (dlen != NULL) *dlen = n;
+ return(rv);
+}
+
+static int dcmi_set_asset_tag(char *pdata, int sdata)
+{
+ int rv = -1;
+ uchar idata[32];
+ uchar rdata[8];
+ uchar cc;
+ int ilen, rlen, n;
+ int sz_chunk = 16;
+
+ if (pdata == NULL || sdata < 2) return(ERR_BAD_PARAM);
+ for (n = 0; (n < sdata); n += sz_chunk) {
+ idata[0] = 0xDC;
+ idata[1] = n; /*offset*/
+ idata[2] = sz_chunk; /*bytes to read*/
+ memset(&idata[3],0x20,sz_chunk);
+ ilen = 3 + sz_chunk;
+ if ((n + sz_chunk) > sdata) sz_chunk = sdata - n;
+ memcpy(&idata[3],&pdata[n],sz_chunk);
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_SET_ASSETTAG, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,ilen, rdata, &rlen, &cc, fdebug);
+ if (rv == 0) {
+ if (fdebug)
+ printf("dcmi_set_asset_tag(%d,%d,%d) cc=%x resp: %02x %02x %02x\n",
+ sdata,n,sz_chunk,cc,rdata[0],rdata[1],rdata[2]);
+ rv = cc;
+ }
+ if (rv != 0) break;
+ }
+ return(rv);
+}
+
+static int dcmi_set_mc_id(char *pdata, int sdata)
+{
+ int rv = -1;
+ uchar idata[32];
+ uchar rdata[8];
+ uchar cc;
+ int ilen, rlen, n;
+ int sz_chunk = 16;
+
+ if (pdata == NULL || sdata < 2) return(ERR_BAD_PARAM);
+ for (n = 0; (n < sdata); n += sz_chunk) {
+ if ((n + sz_chunk) > sdata) sz_chunk = sdata - n;
+ idata[0] = 0xDC;
+ idata[1] = n; /*offset*/
+ idata[2] = sz_chunk; /*bytes to read*/
+ memset(&idata[3],0x20,sz_chunk);
+ ilen = 3 + sz_chunk;
+ if ((n + sz_chunk) > sdata) sz_chunk = sdata - n;
+ memcpy(&idata[3],&pdata[n],sz_chunk);
+ rlen = sizeof(rdata);
+ rv = ipmi_cmdraw( CMD_DCMI_SET_MCIDSTR, NETFN_DCMI,
+ g_sa, g_bus, g_lun,
+ idata,ilen, rdata, &rlen, &cc, fdebug);
+ if (rv == 0) {
+ if (fdebug) printf("dcmi_set_mc_id(%d,%d,%d) resp: %02x %02x %02x\n",
+ sdata,n,sz_chunk,rdata[0], rdata[1], rdata[2]);
+ rv = cc;
+ }
+ if (rv != 0) break;
+ }
+ return(rv);
+}
+
+static int dcmi_show_asset_tag(void)
+{
+ int rv = -1;
+ rv = dcmi_get_asset_tag(asset,sizeof(asset),&asset_len);
+ if (rv == 0) printf("DCMI Asset Tag: \t%s\n",asset);
+ return(rv);
+}
+
+static int dcmi_show_mc_id(void)
+{
+ int rv = -1;
+ rv = dcmi_get_mc_id(mc_id,sizeof(mc_id),&mcid_len);
+ if (rv == 0) printf("DCMI Mgt Controller ID: \t%s\n",mc_id);
+ return(rv);
+}
+
+static char *supported[2] = { "Unsupported", "Supported" };
+
+void dcmi_show_capab(int parm, uchar *cdata, int sdata)
+{
+ char mystr[64] = "";
+ int i, j, k, n, f;
+ switch(parm)
+ {
+ case 1:
+ printf("DCMI Version: \t%d.%d\n",cdata[1],cdata[2]);
+ dcmi_ver = ((cdata[1] & 0x0f) << 4) + (cdata[2] & 0x0f);
+ if (cdata[5] & 0x01) { fpwm = 1; }
+ else { fpwm = 0; }
+ printf("DCMI Power Management: \t%s\n",supported[fpwm]);
+ if (cdata[6] & 0x01) f = 1;
+ else f = 0;
+ printf("DCMI System Interface Access:\t%s\n",supported[f]);
+ if (cdata[6] & 0x02) f = 1;
+ else f = 0;
+ printf("DCMI Serial TMode Access:\t%s\n",supported[f]);
+ if (cdata[6] & 0x02) f = 1;
+ else f = 0;
+ printf("DCMI Secondary LAN Channel:\t%s\n",supported[f]);
+ break;
+ case 2:
+ mystr[0] = 0;
+ if (cdata[5] & 0x80) strcat(mystr,"Overwrite ");
+ else strcat(mystr,"NoOverwrite ");
+ if (cdata[5] & 0x40) strcat(mystr,"FlushAll ");
+ if (cdata[5] & 0x20) strcat(mystr,"FlushRec");
+ printf("DCMI SEL Management: \t%s\n",mystr);
+ n = ((cdata[5] & 0x0F) << 8) + cdata[4];
+ printf("DCMI SEL num entries: \t%d\n",n);
+ i = cdata[8];
+ printf("DCMI Temperature Polling: \t%d sec\n",i);
+ break;
+ case 3:
+ n = ((cdata[4] & 0xFE) >> 1);
+ printf("DCMI PWM Slave_Address: \t%02x\n",n);
+ n = ((cdata[5] & 0xF0) >> 4);
+ printf("DCMI PWM Channel: \t%02x\n",n);
+ printf("DCMI PWM Dev_Rev: \t%02x\n",(cdata[5] & 0x0F));
+ break;
+ case 4:
+ printf("DCMI LanPlus primary chan:\t%02x\n",cdata[4]);
+ printf("DCMI LanPlus secondary chan:\t%02x\n",cdata[5]);
+ printf("DCMI Serial channel: \t%02x\n",cdata[6]);
+ break;
+ case 5:
+ n = cdata[4];
+ if (n > (5 + sdata)) n = sdata - 5; /*truncate*/
+ for (i = 0; i < n; i++) {
+ j = (cdata[5+i] & 0x0f);
+ k = ((cdata[5+i] & 0xf0) >> 4);
+ switch(k) {
+ case 3: strcpy(mystr,"days"); break;
+ case 2: strcpy(mystr,"hrs"); break;
+ case 1: strcpy(mystr,"min"); break;
+ case 0:
+ default: strcpy(mystr,"sec"); break;
+ }
+ printf("DCMI Power Stats Duration(%d):\t%d %s\n",i,j,mystr);
+ }
+ break;
+ default:
+ printf("DCMI(%d) data: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ parm,cdata[1],cdata[2],cdata[3],cdata[4],
+ cdata[5], cdata[6], cdata[7], cdata[8]);
+ break;
+ }
+}
+
+static int dcmi_show_all_capab(void)
+{
+ int rv = -1;
+ int i;
+ uchar cdata[32];
+
+ for (i = 1; i <= 5; i++)
+ {
+ /* only read power stats(5) when power management is supported */
+ if (i == 5 && fpwm == 0) continue;
+ rv = dcmi_get_capab(i, cdata, sizeof(cdata));
+ if (rv != 0) {
+ if (i == 1 && rv == CC_DCMI_INVALID_COMMAND) { /*0xC1 on first*/
+ printf("DCMI not supported on this platform\n");
+ break;
+ } else if (i == 5 && rv == CC_DCMI_RECORD_NOT_PRESENT) /*0xCB*/
+ rv = 0; /*optional, ignore this error*/
+ /*else just dont show the param*/
+ } else dcmi_show_capab(i,cdata,sizeof(cdata));
+
+ } /*end-for dcmi_capab loop */
+ return(rv);
+}
+
+#ifdef METACOMMAND
+int i_dcmi(int argc, char **argv)
+#else
+#ifdef WIN32
+int __cdecl
+#else
+int
+#endif
+main(int argc, char **argv)
+#endif
+{
+ int rv = 0;
+ int c, i;
+ char *s1;
+ uchar cdata[32];
+ uchar powdata[32];
+
+ printf("%s ver %s\n", progname,progver);
+ parse_lan_options('V',"4",0); /*default to admin priv*/
+
+ while ( (c = getopt( argc, argv,"a:d:m:sT:V:J:EYF:P:N:R:U:Z:x?")) != EOF )
+ switch (c) {
+ case 'a': set_asset = 1; asset_new = optarg; break;
+ case 'd': set_mcid = 1; mcid_new = optarg; break;
+ case 'm': /* specific IPMB 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*/
+ g_addrtype = ADDR_IPMB;
+ if (optarg[6] == 's') {
+ g_addrtype = ADDR_SMI; s1 = "SMI";
+ } else { g_addrtype = ADDR_IPMB; s1 = "IPMB"; }
+ ipmi_set_mc(g_bus,g_sa,g_lun,g_addrtype);
+ printf("Use MC at %s bus=%x sa=%x lun=%x\n",
+ s1,g_bus,g_sa,g_lun);
+ break;
+ case 's': do_sensors = 1; break;
+ case 'x': fdebug = 1; break; /* debug messages */
+ 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 'V': /* priv level */
+ case 'Y': /* prompt for remote password */
+ case 'Z': /* set local MC address */
+ parse_lan_options(c,optarg,fdebug);
+ break;
+ case '?':
+ return(dcmi_usage());
+ break;
+ }
+ for (i = 0; i < optind; i++) { argv++; argc--; }
+
+ if ((argc > 0) && strcmp(argv[0], "help") == 0) {
+ return(dcmi_usage());
+ }
+
+ rv = ipmi_getdeviceid( cdata, sizeof(cdata),fdebug);
+ if (rv == 0) {
+ uchar ipmi_maj, ipmi_min;
+ ipmi_maj = cdata[4] & 0x0f;
+ ipmi_min = cdata[4] >> 4;
+ show_devid( cdata[2], cdata[3], ipmi_maj, ipmi_min);
+ } else goto do_exit;
+
+ if (set_asset) {
+ rv = dcmi_get_asset_tag(asset,sizeof(asset),&asset_len);
+ memset(asset,' ',asset_len); /*fill with spaces*/
+ asset_len = strlen_(asset_new);
+ if (asset_len >= sizeof(asset)) asset_len = sizeof(asset) - 1;
+ memcpy(asset,asset_new,asset_len);
+ asset[asset_len] = 0;
+ rv = dcmi_set_asset_tag(asset, asset_len);
+ printf("Set DCMI Asset Tag to %s, ret = %d\n",asset_new,rv);
+ }
+ if (set_mcid) {
+ rv = dcmi_get_mc_id(mc_id,sizeof(mc_id),&mcid_len);
+ memset(mc_id,' ',mcid_len); /*fill with spaces*/
+ mcid_len = strlen_(mcid_new);
+ if (mcid_len >= sizeof(mc_id)) mcid_len = sizeof(mc_id) - 1;
+ memcpy(mc_id,mcid_new,mcid_len);
+ mc_id[mcid_len] = 0;
+ rv = dcmi_set_mc_id(mcid_new, mcid_len);
+ printf("Set DCMI MC ID to %s, ret = %d\n",mcid_new,rv);
+ }
+
+ if ( (argc == 0) || (strcmp(argv[0], "info") == 0) ) {
+ rv = dcmi_show_all_capab();
+ if (rv == 0) {
+ rv = dcmi_show_mc_id();
+ rv = dcmi_show_asset_tag();
+ if (do_sensors) rv = dcmi_get_sensors(1); /*temp sensors*/
+ rv = 0; /*ignore errors for optional features*/
+ }
+ } else
+ {
+ rv = dcmi_get_capab(1, cdata, sizeof(cdata));
+ if (rv == 0) dcmi_show_capab(1,cdata,sizeof(cdata));
+ else if (rv == CC_DCMI_INVALID_COMMAND) /*0xC1 on first*/
+ printf("DCMI not supported on this platform\n");
+
+ if (strncmp(argv[0], "power",5) == 0) {
+ if (fpwm == 0) { /*not supported in capab */
+ printf("DCMI Power functions not supported on this platform.\n");
+ rv = LAN_ERR_NOTSUPPORT;
+ } else {
+ rv = dcmi_get_power_read(1, cdata, sizeof(cdata));
+ if (rv == 0) {
+ dcmi_show_power_read(1,cdata,sizeof(cdata));
+ rv = dcmi_get_power_limit(powdata, sizeof(powdata));
+ if (rv == 0)
+ dcmi_show_power_limit(powdata,sizeof(powdata),rv);
+ else if (rv == 0x80) {
+ dcmi_show_power_limit(powdata,sizeof(powdata),rv);
+ rv = 0;
+ }
+ }
+ if (argc < 2) ; /*just get, done above*/
+ else if (strncmp(argv[1],"get",3) == 0) ; /*done above*/
+ else if (strncmp(argv[1],"set_limit",9) == 0) {
+ if (argc < 3) return(dcmi_usage());
+ i = atoi(argv[2]);
+ { /*let range checking be done by DCMI*/
+ rv = dcmi_set_power_limit (POWER_LIMIT, i, powdata,16);
+ switch(rv) {
+ case 0:
+ printf("DCMI Power limit applied successfully.\n");
+ break;
+ case 0x84: printf("Power limit out of range\n"); break;
+ case 0x85: printf("Correction time out of range\n");
+ break;
+ case 0x89:
+ printf("Statistics reporting period out of range\n");
+ break;
+ default:
+ printf("DCMI Power Limit Set error %d\n",rv); break;
+ }
+ if (rv == 0) {
+ rv = dcmi_power_limit_activate(1);
+ printf ("DCMI Power Limit Activate returned %d\n",rv);
+ }
+ }
+ }
+ else if (strncmp(argv[1],"activate",8) == 0) {
+ rv = dcmi_power_limit_activate(1);
+ if (rv == 0)
+ printf ("DCMI Power Limit Activated.\n");
+ else printf("DCMI Power Limit Activate error %d\n",rv);
+ }
+ else if (strncmp(argv[1],"deactivate",10) == 0) {
+ rv = dcmi_power_limit_activate(0);
+ if (rv == 0)
+ printf("DCMI Power Limit Deactivated.\n");
+ else printf("DCMI Power Limit Deactivate error %d\n",rv);
+ }
+ else if (strcmp(argv[1],"set_action")==0) {
+ if (argc < 3) return(dcmi_usage());
+ else if (strcmp(argv[2],"no_action") == 0)
+ rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x00,
+ powdata,16);
+ else if (strcmp(argv[2],"log_sel") == 0)
+ rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x11,
+ powdata,16);
+ else if (strcmp(argv[2],"power_off") == 0)
+ rv = dcmi_set_power_limit(EXCEPTION_ACTION,0x01,
+ powdata,16);
+ else return(dcmi_usage());
+ if (rv == 0)
+ printf("exception action set successfully.\n");
+ else printf("set_exception action error %d\n",rv);
+ }
+ else if (strcmp(argv[1],"set_sample")==0) {
+ if (argc < 3) return(dcmi_usage());
+ i = atoi(argv[2]);
+ if (i != 0) {
+ rv = dcmi_set_power_limit (SAMPLE_PERIOD,i,powdata,16);
+ if (rv == 0x00)
+ printf("sample period set successfully\n");
+ else if (rv == 0x89)
+ printf("sample period %d out of range\n",i);
+ else printf("set_sample period error %d\n",rv);
+ }
+ else { printf("invalid sample period %d\n",i);
+ rv = ERR_USAGE; }
+ }
+ else if (strcmp(argv[1],"set_correction")==0) {
+ if (argc < 3) return(dcmi_usage());
+ i = atoi(argv[2]);
+ if (i != 0) {
+ rv = dcmi_set_power_limit(CORRECTION_TIME,i,powdata,16);
+ if (rv == 0x00)
+ printf("correction time set successfully\n");
+ else if (rv == 0x85)
+ printf("correction time %d out of range\n",i);
+ else {
+ dcmi_usage();
+ rv = ERR_USAGE;
+ }
+ }
+ else { printf("correction time %d invalid\n",i);
+ rv = ERR_USAGE; }
+ }
+ else {
+ printf("invalid subfunction %s\n",argv[1]);
+ rv = ERR_USAGE;
+ }
+ } /* endif power functions supported */
+
+ } else if (strcmp(argv[0], "thermal") == 0) {
+ if (dcmi_ver < 0x15) { /*not supported in DCMI < 1.5 */
+ printf("DCMI 1.5 Thermal functions not supported on this platform.\n");
+ rv = LAN_ERR_NOTSUPPORT;
+ } else {
+ rv = dcmi_get_sensors(1); /*temp sensors*/
+/* These are DCMI 1.5 commands */
+// #define CMD_DCMI_SET_THERMLIM 0x0B
+// #define CMD_DCMI_GET_THERMLIM 0x0C
+// #define CMD_DCMI_GET_TEMPRDNGS 0x10
+/* TODO: implement these 3 DCMI thermal commands */
+ printf("DCMI 1.5 Thermal functions not yet implemented\n");
+ rv = ERR_USAGE;
+ }
+ } else if (strcmp(argv[0], "config") == 0) {
+ if (dcmi_ver < 0x15) { /*not supported in DCMI < 1.5 */
+ printf("DCMI 1.5 Config functions not supported on this platform.\n");
+ rv = LAN_ERR_NOTSUPPORT;
+ } else { /* These are DCMI 1.5 commands */
+// #define CMD_DCMI_SET_CONFIG 0x12
+// #define CMD_DCMI_GET_CONFIG 0x13
+/* TODO: implement these 2 DCMI config commands */
+ printf("DCMI 1.5 Config get/set functions not yet implemented\n");
+ rv = ERR_USAGE;
+ }
+ } else {
+ return(dcmi_usage());
+ }
+ } /*else not info command*/
+
+do_exit:
+ ipmi_close_();
+ return rv;
+}
+/* end idcmi.c */