diff options
Diffstat (limited to 'util/idcmi.c')
-rw-r--r-- | util/idcmi.c | 976 |
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 */ |