/**************************************************************************** Copyright (c) 2006, Dell 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: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 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. - Neither the name of Dell Inc 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. *****************************************************************************/ /* Includes this file is dependent on */ #include #include #include #include #include /**************************************************************************** Global Variables ****************************************************************************/ extern char g_FanReduntant[]; extern char g_PSReduntant[]; /**************************************************************************** Local Variables ****************************************************************************/ char* pCssdBldStr = CSSD_BUILD_STR; /* Code Begins */ /**************************************************************************** CSSLongDiv ****************************************************************************/ longdiv_t CSSLongDiv(long numerator, long denominator) { int n_sign; int d_sign; unsigned long n; unsigned long d; unsigned long t; longdiv_t value; n_sign = 1; d_sign = 1; n = (unsigned long)(numerator); d = (unsigned long)(denominator); if (numerator < 0) { n = -numerator; n_sign = -1; } if (denominator < 0) { d = -denominator; d_sign = -1; } value.quot = (n / d) * (n_sign * d_sign); if (value.quot < 0) { t = -value.quot; } else { t = value.quot; } value.rem = (n * n_sign) - (value.quot * d * d_sign); return(value); } /**************************************************************************** CSSlongToAscii This routine converts a value to a ASCII string. value ****************************************************************************/ unsigned char CSSlongToAscii(long value, char* buff, int radix) { char* p; /* pointer to traverse string */ char* firstDigit; /* pointer to first digit */ char temp; /* temp char */ longdiv_t digit; unsigned char total_characters; p = buff; /* save pointer to first digit */ firstDigit = p; total_characters = 0; if (value < 0) { /* negative, so output '-' and negate */ *p++ = '-'; value = (unsigned long)(-(long)value); } /* divide the given value until is is less than Zero */ do { /* get remainder. Note: do not use the % opertor due to some 16 complers do not support sign 32 bit values */ digit = CSSLongDiv(value, (long)radix); /* get next digit */ value = digit.quot; /* convert to ascii and store */ if (digit.rem > 9) { *p++ = (char)(digit.rem - 10 + 'a'); /* a letter */ } else { *p++ = (char)(digit.rem + '0'); /* a digit */ } total_characters++; }while (value > 0); /* We now have the digit of the number in the buffer, but in reverse order. Thus we reverse them now. */ /* terminate string; p points to last digit */ *p-- = '\0'; do { temp = *p; *p = *firstDigit; /* swap *p and *first digit */ *firstDigit = temp; --p; /* advance to next two digits */ ++firstDigit; } while (firstDigit < p); /* repeat until halfway */ return total_characters; } /**************************************************************************** CSSAsciiToLong This function is here to support 16 bit compliers ****************************************************************************/ long CSSAsciiToLong( _IN const char *nptr) { char c; /* current char */ unsigned long total; /* current total */ char sign; /* if '-', then negative, otherwise positive */ char *ptr = (char*)nptr; /* skip whitespace */ while ( *ptr == ' ' ) { ++ptr; } c = *ptr++; sign = c; /* save sign indication */ if ((c == '-') || (c == '+')) { c = *ptr++; /* skip sign */ } total = 0; while ((c >= '0') && (c <= '9')) { total = 10 * total + (c - '0'); /* accumulate digit */ c = *ptr++; /* get next char */ } if (sign == '-') return -(long)total; else return (long)total; /* return result, negated if necessary */ } /**************************************************************************** CSSFindEntitySDRRecord Searches SDRs to find the Entity for the given SDR record if one exist ****************************************************************************/ SDRType *CSSFindEntitySDRRecord( _IN const GETFIRSTSDRFN GetFirstSDR, _IN const GETNEXTSDRFN GetNextSDR, _IN const OEM2IPMISDRFN Oem2IPMISDR, _IN const void* pIPMISDR, _IN void* puserParameter) { unsigned char entityID; unsigned char entityInst; unsigned char fruID; unsigned char fruInst; unsigned char recordType; SDRType* pSdrHandle = NULL; if ((NULL != GetFirstSDR) && (NULL != GetNextSDR)) { entityID = CSSSDRGetAttribute(pIPMISDR,SDR_ATTRIBUTE_ENTITY_ID, Oem2IPMISDR); entityInst = CSSSDRGetAttribute(pIPMISDR,SDR_ATTRIBUTE_ENTITY_INST, Oem2IPMISDR); pSdrHandle = GetFirstSDR(puserParameter); while ( pSdrHandle != NULL) { recordType = CSSSDRGetAttribute(pSdrHandle,SDR_ATTRIBUTE_RECORD_TYPE, Oem2IPMISDR); if (recordType == SDR_FRU_DEV_LOCATOR) { fruID = CSSSDRGetAttribute(pSdrHandle,SDR_ATTRIBUTE_ENTITY_ID,Oem2IPMISDR); fruInst = CSSSDRGetAttribute(pSdrHandle,SDR_ATTRIBUTE_ENTITY_INST,Oem2IPMISDR); /* Find the SDR that matches the given entity */ if ((fruID == entityID) && (fruInst == entityInst)) { /* found the record break */ break; } } pSdrHandle = GetNextSDR(pSdrHandle, puserParameter); } } return pSdrHandle; } /**************************************************************************** CSSGetProbeName This routine copies the text for a sensor from its SDR record to the destination probe name ****************************************************************************/ int CSSGetProbeName( IPMISDR* pSdr, unsigned char instance, char* probeName, unsigned short size, const OEM2IPMISDRFN Oem2IPMISDR) { unsigned short length; char numStr[16]; IPMISDR* pRecord; IPMISDR theRecord; int status = COMMON_STATUS_BAD_PARAMETER; if( Oem2IPMISDR != NULL ) { Oem2IPMISDR(pSdr, &theRecord); pRecord = &theRecord; } else { pRecord = (IPMISDR*)pSdr; } if (NULL != pSdr && NULL != probeName) { probeName[0] = '\0'; switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: length = (unsigned short)(pRecord->type.type1.typeLengthCode & 0x1F); if (length < size) { memcpy(probeName, pRecord->type.type1.sensorName, length); probeName[length] = '\0'; } break; case SDR_COMPACT_SENSOR: /* NOTE: Type 2 SDRs can be shared by multiple sensors with consecutive sensor numbers */ length = (unsigned short)(pRecord->type.type2.typeLengthCode & 0x1F); memcpy(probeName, pRecord->type.type2.sensorName, length); probeName[length] = '\0'; if((pRecord->type.type2.recordSharing1 & 0x0F) > 1) { CSSlongToAscii((long)instance, numStr, 10); strcat(probeName, " "); strcat(probeName, numStr); } break; case SDR_FRU_DEV_LOCATOR: length = (unsigned short)(pRecord->type.type11.devIdStrTypeLen & 0x1F); if (length < size) { memcpy(probeName, pRecord->type.type11.devString, length); probeName[length] = '\0'; } break; case SDR_MGMT_CTRL_DEV_LOCATOR: length = (unsigned short)(pRecord->type.type12.devIdStrTypeLen & 0x1F); if (length < size) { memcpy(probeName, pRecord->type.type12.devString, length); probeName[length] = '\0'; } break; case SDR_OEM_RECORD: /* do this processing only if OEM flag is set i.e. when we know this is our box */ length = (unsigned short) (pRecord->header.recordLength - 3); if (length < size) { memcpy(probeName, pRecord->type.typeC0.OemType.dellOem.oemString, length); probeName[length] = '\0'; } break; } status = COMMON_STATUS_SUCCESS; } return status; } /**************************************************************************** CSSGetSensorTypeStr This function gets a string that describes the IPMI defined sensor type ****************************************************************************/ char *CSSGetSensorTypeStr(_IN unsigned char sensorType, _IN unsigned char readingType) { char *sensorTypeStr = g_SensorTypesTable[0]; if ((sensorType > 0) && (sensorType < MAX_SENSOR_TYPE_NAMES)) { sensorTypeStr = g_SensorTypesTable[sensorType]; /* special case */ if (readingType == IPMI_READING_TYPE_REDUNDANCY) { switch(sensorType) { case IPMI_SENSOR_FAN: sensorTypeStr = g_FanReduntant; break; case IPMI_SENSOR_PS: sensorTypeStr = g_PSReduntant; break; } } } else if (sensorType == IPMI_SENSOR_SYS_DEGRADE_STATUS) { sensorTypeStr = "Performance status"; } return sensorTypeStr; } /**************************************************************************** CSSSDRGetAttribute This function obtains data elements from an SDR ****************************************************************************/ unsigned char CSSSDRGetAttribute( _IN const void* pSDRRec, _IN unsigned char param, _IN const OEM2IPMISDRFN Oem2IPMISDR) { unsigned char retVal = 0; IPMISDR* pRecord; IPMISDR theRecord; if( Oem2IPMISDR != NULL ) { Oem2IPMISDR ( pSDRRec, &theRecord ); pRecord = &theRecord; } else { pRecord = (IPMISDR*)pSDRRec; } switch(param) { case SDR_ATTRIBUTE_TOLERANCE: retVal = pRecord->type.type1.tolerance; break; case SDR_ATTRIBUTE_ACCURACY: retVal = pRecord->type.type1.accuracy; break; case SDR_ATTRIBUTE_OFFSET: retVal = pRecord->type.type1.b; break; case SDR_ATTRIBUTE_MULTIPLIER: retVal = pRecord->type.type1.m; break; case SDR_ATTRIBUTE_EXPONENT: retVal = pRecord->type.type1.rbExp; break; case SDR_ATTRIBUTE_RECORD_TYPE: retVal = pRecord->header.recordType; break; case SDR_ATTRIBUTE_ENTITY_ID: switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal= pRecord->type.type1.entityID; break; case SDR_COMPACT_SENSOR: retVal = pRecord->type.type2.entityID; break; case SDR_ENTITY_ASSOC: retVal = pRecord->type.type8.containerEntityID; break; case SDR_FRU_DEV_LOCATOR: retVal = pRecord->type.type11.fruEntityId; break; default: break; } break; case SDR_ATTRIBUTE_ENTITY_INST: /* check the record type and return the sensortype from appropriate sdr structure */ switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal = pRecord->type.type1.entityInstance; break; case SDR_COMPACT_SENSOR: retVal = pRecord->type.type2.entityInstance; break; case SDR_ENTITY_ASSOC: retVal = pRecord->type.type8.containerEntityInstance; break; case SDR_FRU_DEV_LOCATOR: retVal = pRecord->type.type11.fruEntityInst; break; default: break; } break; case SDR_ATTRIBUTE_READING_TYPE: switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal = pRecord->type.type1.readingType; break; case SDR_COMPACT_SENSOR: retVal = pRecord->type.type2.readingType; break; default: break; } break; case SDR_ATTRIBUTE_SENSOR_TYPE: /* check the record type and return the sensortype from appropriate sdr structure */ switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal = pRecord->type.type1.sensorType; break; case SDR_COMPACT_SENSOR: retVal = pRecord->type.type2.sensorType; break; default: break; } break; case SDR_ATTRIBUTE_SHARE_COUNT: switch(pRecord->header.recordType) { case SDR_COMPACT_SENSOR: retVal = (unsigned char) (pRecord->type.type2.recordSharing1 & 0x0F); break; default: retVal = 1; break; } break; case SDR_ATTRIBUTE_SENSOR_NUMBER: switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal = pRecord->type.type1.sensorNum; break; case SDR_COMPACT_SENSOR: retVal = pRecord->type.type2.sensorNum; break; } break; case SDR_ATTRIBUTE_SENSOR_OWNER_ID: switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal = pRecord->type.type1.ownerID; break; case SDR_COMPACT_SENSOR: retVal = pRecord->type.type2.ownerID; break; } break; case SDR_ATTRIBUTE_THRES_READ_MASK: /* check the record type and return the appropriate thr mask */ switch(((IPMISDR *)pSDRRec)->header.recordType) { case SDR_FULL_SENSOR: retVal = (unsigned char)(pRecord->type.type1.readingMask & 0x00ff); break; case SDR_COMPACT_SENSOR: retVal = (unsigned char)(pRecord->type.type2.readingMask & 0x00ff); break; } break; case SDR_ATTRIBUTE_THRES_SET_MASK: /* check the record type and return the appropriate thr mask */ switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal = (unsigned char)((pRecord->type.type1.readingMask >> 8) & 0x00ff); break; case SDR_COMPACT_SENSOR: retVal = (unsigned char)((pRecord->type.type2.readingMask >> 8) & 0x00ff); break; } break; case SDR_ATTRIBUTE_OEM_BYTE: /* check the record type and return the sensortype from appropriate sdr structure */ switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal = (unsigned char)pRecord->type.type1.OEM; break; case SDR_COMPACT_SENSOR: retVal = (unsigned char)pRecord->type.type2.OEM; break; } break; case SDR_ATTRIBUTE_SENSOR_UNITS: switch(pRecord->header.recordType) { case SDR_FULL_SENSOR: retVal = (unsigned char)pRecord->type.type1.units2; break; case SDR_COMPACT_SENSOR: retVal = (unsigned char)pRecord->type.type2.units2; break; } break; } return retVal; } /* Code Ends */