diff options
author | Terry J. Opie <opiet@us.ibm.com> | 2012-01-03 15:06:17 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-01-31 13:06:56 -0600 |
commit | e5908dd4c110595e7c11d46009b07aa068dc19cd (patch) | |
tree | e0b7647123fbc87f4f459f909bb4f2be0da8f0dd /src/usr/spd/spd.C | |
parent | 39b01da0087097401dea4d9a9f4e483734e751d8 (diff) | |
download | talos-hostboot-e5908dd4c110595e7c11d46009b07aa068dc19cd.tar.gz talos-hostboot-e5908dd4c110595e7c11d46009b07aa068dc19cd.zip |
SPD Device Driver
- JEDEC format for DDR3
- Testcases
Change-Id: I8a9bf87335914d5cb824adb92f11546c37e5b423
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/610
Tested-by: Jenkins Server
Reviewed-by: Van H. Lee <vanlee@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/spd/spd.C')
-rwxr-xr-x | src/usr/spd/spd.C | 901 |
1 files changed, 901 insertions, 0 deletions
diff --git a/src/usr/spd/spd.C b/src/usr/spd/spd.C new file mode 100755 index 000000000..0a1dc5bae --- /dev/null +++ b/src/usr/spd/spd.C @@ -0,0 +1,901 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/spd/spd.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2012 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file spd.C + * + * @brief Implementation of the SPD device driver + * + */ + +// ---------------------------------------------- +// Includes +// ---------------------------------------------- +//#include <string.h> +//#include <sys/time.h> + +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <targeting/targetservice.H> +#include <devicefw/driverif.H> +#include <vfs/vfs.H> +#include <spd/spdreasoncodes.H> +#include <spd/spdenums.H> + +#include "spd.H" +#include "spdDDR3.H" + +// ---------------------------------------------- +// Globals +// ---------------------------------------------- +bool g_loadModule = true; +mutex_t g_spdMutex = MUTEX_INITIALIZER; + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +trace_desc_t* g_trac_spd = NULL; +TRAC_INIT( & g_trac_spd, "SPD", 4096 ); + +// ------------------------ +// Macros for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) +//#define TRACSSCOMP(args...) TRACFCOMP(args) +#define TRACSSCOMP(args...) + + +// ---------------------------------------------- +// Defines +// ---------------------------------------------- + +namespace SPD +{ + +// Register the perform Op with the routing code for DIMMs. +DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, + DeviceFW::SPD, + TARGETING::TYPE_DIMM, + spdAccess ); + +// ------------------------------------------------------------------ +// spdRead +// ------------------------------------------------------------------ +errlHndl_t spdAccess( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, + void * io_buffer, + size_t & io_buflen, + int64_t i_accessType, + va_list i_args ) +{ + errlHndl_t err = NULL; + uint64_t keyword = va_arg( i_args, uint64_t ); + + if( DeviceFW::READ == i_opType ) + { + // Read the SPD keyword + err = spdGetKeywordValue( keyword, + io_buffer, + io_buflen, + i_target ); + } + else + { + // Write the SPD keyword + err = spdWriteKeywordValue( keyword, + io_buffer, + io_buflen, + i_target ); + } + + return err; +} // end spdRead + + +// ------------------------------------------------------------------ +// spdGetKeywordValue +// ------------------------------------------------------------------ +errlHndl_t spdGetKeywordValue ( uint64_t i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target ) +{ + errlHndl_t err = NULL; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdGetKeywordValue(), io_buflen: %d, keyword: 0x%04x", + io_buflen, i_keyword ); + + do + { + // Read the Basic Memory Type + uint8_t memType = 0x0; + err = spdFetchData( MEM_TYPE_ADDR, + MEM_TYPE_ADDR_SZ, + &memType, + i_target ); + + if( err ) + { + break; + } + + TRACDCOMP( g_trac_spd, + INFO_MRK"Mem Type: %04x", + memType ); + + // If the user wanted the Basic Memory Type, return this now + if( BASIC_MEMORY_TYPE == i_keyword ) + { + io_buflen = MEM_TYPE_ADDR_SZ; + memcpy( io_buffer, &memType, io_buflen ); + break; + } + + // Check the Basic Memory Type to be sure its valid before + // continuing. + if( SPD_DDR3 == memType ) + { + // Read the keyword value + err = spdGetValue( i_keyword, + io_buffer, + io_buflen, + i_target, + memType ); + + if( err ) + { + break; + } + } + else + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Invalid Basic Memory Type (0x%04x)", + memType ); + + /*@ + * @errortype + * @reasoncode SPD_INVALID_BASIC_MEMORY_TYPE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_GET_KEYWORD_VALUE + * @userdata1 Basic Memory Type (Byte 2) + * @userdata2 Keyword Requested + * @devdesc Invalid Basic Memory Type + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_GET_KEYWORD_VALUE, + SPD_INVALID_BASIC_MEMORY_TYPE, + memType, + i_keyword ); + } + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdGetKeywordValue()" ); + + return err; +} + + +// ------------------------------------------------------------------ +// spdWriteKeywordValue +// ------------------------------------------------------------------ +errlHndl_t spdWriteKeywordValue ( uint64_t i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target ) +{ + errlHndl_t err = NULL; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdWriteKeywordValue()" ); + + do + { + // TODO - This will be implemented with story 4659 + TRACFCOMP( g_trac_spd, + ERR_MRK"SPD writes are not supported yet!" ); + + /*@ + * @errortype + * @reasoncode SPD_NOT_SUPPORTED + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_WRITE_KEYWORD_VALUE + * @userdata1 i_keyword + * @userdata2 <UNUSED> + * @devdesc SPD Writes are not supported yet. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_WRITE_KEYWORD_VALUE, + SPD_NOT_SUPPORTED, + i_keyword, + 0x0 ); + break; + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdWriteKeywordValue()" ); + + return err; +} + + +// ------------------------------------------------------------------ +// spdFetchData +// ------------------------------------------------------------------ +errlHndl_t spdFetchData ( uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data, + TARGETING::Target * i_target ) +{ + errlHndl_t err = NULL; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdFetchData()" ); + + do + { + // --------------------------------------------------------------- + // TODO - For now, we will use a generic name of dimmspd.dat, and + // access the file via vfs for all SPD content for ALL DIMMs. + // + // Unfortunately Fsp will not be able to write into our file + // space in PNOR because the files/names will need to be signed. + // This means that eventually there will be block of data in PNOR + // where each DIMMs, and potential DIMM, information will be at + // a given offset. + // --------------------------------------------------------------- + + err = spdReadBinaryFile( i_byteAddr, + i_numBytes, + o_data ); + + if( err ) + { + break; + } + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdFetchData()" ); + + return err; +} + + +// ------------------------------------------------------------------ +// spdGetValue +// ------------------------------------------------------------------ +errlHndl_t spdGetValue ( uint64_t i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target, + uint64_t i_DDRRev ) +{ + errlHndl_t err = NULL; + uint8_t * tmpBuffer = static_cast<uint8_t *>(io_buffer); + KeywordData * kwdData; + uint32_t arraySize = 0x0; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdGetValue()" ); + + do + { + if( SPD_DDR3 == i_DDRRev ) + { + kwdData = ddr3Data; + arraySize = (sizeof(ddr3Data)/sizeof(ddr3Data[0])); + + } + else + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Unsupported DDRx Revision (0x%04x)", + i_DDRRev ); + + /*@ + * @errortype + * @reasoncode SPD_INVALID_BASIC_MEMORY_TYPE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_GET_VALUE + * @userdata1 SPD Keyword + * @userdata2 The DDR Revision + * @devdesc Invalid DDR Revision + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_GET_VALUE, + SPD_INVALID_BASIC_MEMORY_TYPE, + i_keyword, + i_DDRRev ); + + break; + } + + // TODO - A binary_search algorithm will be implemented with + // Story 4709. + // Loop through the lookup table. + bool keywordFound = false; + for( uint32_t i = 0; i < arraySize; i++ ) + { + if( kwdData[i].keyword == i_keyword ) + { + keywordFound = true; + + if( kwdData[i].isSpecialCase ) + { + // Handle special cases where data isn't sequential + // or is in reverse order from what would be read. + err = spdSpecialCases( i_keyword, + io_buffer, + io_buflen, + i_target, + i, + i_DDRRev ); + + break; + } + + // Check io_buflen versus size in table + err = spdCheckSize( io_buflen, + kwdData[i].length, + i_keyword ); + + if( err ) + { + break; + } + + // Read length requested + err = spdFetchData( kwdData[i].offset, + kwdData[i].length, + tmpBuffer, + i_target ); + + if( err ) + { + break; + } + + // if useBitmask set, mask and then shift data + if( kwdData[i].useBitMask ) + { + // Any bit mask/shifting will always be on a <1 Byte value + // thus, we touch only byte 0. + tmpBuffer[0] = tmpBuffer[0] & kwdData[i].bitMask; + tmpBuffer[0] = tmpBuffer[0] >> kwdData[i].shift; + } + + // Set length read + io_buflen = kwdData[i].length; + break; + } + } + + if( err ) + { + break; + } + + if( !keywordFound ) + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Could not find keyword (0x%04x) in lookup table!", + i_keyword ); + + /*@ + * @errortype + * @reasoncode SPD_KEYWORD_NOT_FOUND + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_GET_VALUE + * @userdata1 SPD Keyword + * @userdata2 <UNUSED> + * @devdesc Invalid SPD Keyword + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_GET_VALUE, + SPD_KEYWORD_NOT_FOUND, + i_keyword, + 0x0 ); + break; + } + } while( 0 ); + + if( err ) + { + // Signal the caller that there was an error getting + // data and that there is no valid data. + io_buflen = 0; + } + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdGetValue()" ); + + return err; +} + + +// ------------------------------------------------------------------ +// spdSpecialCases +// ------------------------------------------------------------------ +errlHndl_t spdSpecialCases ( uint64_t i_keyword, + void * io_buffer, + size_t & io_buflen, + TARGETING::Target * i_target, + uint64_t i_entry, + uint64_t i_DDRRev ) +{ + errlHndl_t err = NULL; + uint8_t * tmpBuffer = static_cast<uint8_t *>(io_buffer); + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdSpecialCases()" ); + + do + { + // Handle each of the special cases here + if( SPD_DDR3 == i_DDRRev ) + { + switch( i_keyword ) + { + case CAS_LATENCIES_SUPPORTED: + // Length 2 bytes + // Byte 0x0e [7:0] + // Byte 0x0f [6:0] - MSB + + // Check Size of buffer + err = spdCheckSize( io_buflen, + 2, + i_keyword ); + + if( err ) break; + + // Get MSB + err = spdFetchData( ddr3Data[i_entry].offset, + 1, /* Read 1 byte at a time */ + &tmpBuffer[0], + i_target ); + + if( err ) break; + + // Mask and shift if needed + if( ddr3Data[i_entry].useBitMask ) + { + tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask; + tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift; + } + + // Get LSB + err = spdFetchData( 0x0e, + 1, /* Read 1 byte at a time */ + &tmpBuffer[1], + i_target ); + + if( err ) break; + + // Set number of bytes read + io_buflen = 2; + break; + + case TRC_MIN: + // Length 2 bytes + // Byte 0x15 [7:4] - MSB + // Byte 0x17 [7:0] + + // Check Size of buffer + err = spdCheckSize( io_buflen, + 2, + i_keyword ); + + if( err ) break; + + // Get MSB + err = spdFetchData( ddr3Data[i_entry].offset, + 1, /* Read 1 byte at a time */ + &tmpBuffer[0], + i_target ); + + if( err ) break; + + // Mask and shift if needed + if( ddr3Data[i_entry].useBitMask ) + { + tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask; + tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift; + } + + // Get LSB + err = spdFetchData( 0x17, + 1, /* Read 1 byte at a time */ + &tmpBuffer[1], + i_target ); + + if( err ) break; + + // Set number of bytes read + io_buflen = 2; + break; + + case TRAS_MIN: + // Length 2 bytes + // Byte 0x15 [3:0] - MSB + // Byte 0x16 [7:0] + + // Check size of buffer + err = spdCheckSize( io_buflen, + 2, + i_keyword ); + + if( err ) break; + + // Get MSB + err = spdFetchData( ddr3Data[i_entry].offset, + 1, /* Read 1 byte at a time */ + &tmpBuffer[0], + i_target ); + + if( err ) break; + + // Mask and shift if needed + if( ddr3Data[i_entry].useBitMask ) + { + tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask; + tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift; + } + + // Get LSB + err = spdFetchData( 0x16, + 1, /* Read 1 byte at a time */ + &tmpBuffer[1], + i_target ); + + if( err ) break; + + // Set number of bytes read + io_buflen = 2; + break; + + case TRFC_MIN: + // Length 2 bytes + // Byte 0x18 [7:0] + // Byte 0x19 [7:0] - MSB + + // Check size of buffer + err = spdCheckSize( io_buflen, + 2, + i_keyword ); + + if( err ) break; + + // Get MSB + err = spdFetchData( ddr3Data[i_entry].offset, + 1, /* Read 1 byte at a time */ + &tmpBuffer[0], + i_target ); + + if( err ) break; + + // Mask and shift if needed + if( ddr3Data[i_entry].useBitMask ) + { + tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask; + tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift; + } + + // Get LSB + err = spdFetchData( 0x18, + 1, /* Read 1 byte at a time */ + &tmpBuffer[1], + i_target ); + + if( err ) break; + + // Set number of bytes read + io_buflen = 2; + break; + + case TFAW_MIN: + // Length 2 bytes + // Byte 0x1c [3:0] - MSB + // byte 0x1d [7:0] + + // Check size of buffer + err = spdCheckSize( io_buflen, + 2, + i_keyword ); + + if( err ) break; + + // Get MSB + err = spdFetchData( ddr3Data[i_entry].offset, + 1, /* Read 1 byte at a time */ + &tmpBuffer[0], + i_target ); + + if( err ) break; + + // Mask and shift if needed + if( ddr3Data[i_entry].useBitMask ) + { + tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask; + tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift; + } + + // Get LSB + err = spdFetchData( 0x1d, + 1, /* Read 1 byte at a time */ + &tmpBuffer[1], + i_target ); + + if( err ) break; + + // Set number of bytes read + io_buflen = 2; + break; + + case MODULE_MANUFACTURER_ID: + // Length 2 bytes + // Byte 0x75 [7:0] + // Byte 0x76 [7:0] - MSB + + + // Check size of buffer + err = spdCheckSize( io_buflen, + 2, + i_keyword ); + + if( err ) break; + + // Get MSB + err = spdFetchData( ddr3Data[i_entry].offset, + 1, /* Read 1 byte at a time */ + &tmpBuffer[0], + i_target ); + + if( err ) break; + + // Mask and shift if needed + if( ddr3Data[i_entry].useBitMask ) + { + tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask; + tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift; + } + + // Get LSB + err = spdFetchData( 0x75, + 1, /* Read 1 byte at a time */ + &tmpBuffer[1], + i_target ); + + if( err ) break; + + // Set number of bytes read + io_buflen = 2; + break; + + default: + TRACFCOMP( g_trac_spd, + ERR_MRK"Unknown keyword (0x%04x) for DDR3 special cases!", + i_keyword ); + + /*@ + * @errortype + * @reasoncode SPD_INVALID_SPD_KEYWORD + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_SPECIAL_CASES + * @userdata1 SPD Keyword + * @userdata2 Table Entry + * @devdesc Keyword is not a special case keyword. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_SPECIAL_CASES, + SPD_INVALID_SPD_KEYWORD, + i_keyword, + i_entry ); + break; + }; + } + else + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Unsupported DDRx Revision (0x%04x)", + i_DDRRev ); + + /*@ + * @errortype + * @reasoncode SPD_INVALID_BASIC_MEMORY_TYPE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_SPECIAL_CASES + * @userdata1 SPD Keyword + * @userdata2[0:31] SPD Table entry + * @userdata2[32:63] DIMM DDR Revision + * @devdesc Invalid DDR Revision + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_SPECIAL_CASES, + SPD_INVALID_BASIC_MEMORY_TYPE, + i_keyword, + TWO_UINT32_TO_UINT64( i_entry, i_DDRRev) ); + + break; + } + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdSpecialCases()" ); + + return err; +} + + +// ------------------------------------------------------------------ +// spdCheckSize +// ------------------------------------------------------------------ +errlHndl_t spdCheckSize ( size_t i_bufferSz, + size_t i_expBufferSz, + uint64_t i_keyword ) +{ + errlHndl_t err = NULL; + + // Check that the buffer is greater than or equal to the size + // we need to get all the keyword data requested. + if( i_bufferSz < i_expBufferSz ) + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Buffer Size (%d) for keyword (0x%04x) wasn't greater than " + "or equal to expected size (%d)", + i_bufferSz, i_keyword, i_expBufferSz ); + + /*@ + * @errortype + * @reasoncode SPD_INSUFFICIENT_BUFFER_SIZE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_CHECK_SIZE + * @userdata1 Keyword + * @userdata2[0:31] Needed Buffer Size + * @userdata2[32:63] Expected Buffer Size + * @devdesc Buffer Size provided was not big enough for + * the keyword requested. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_CHECK_SIZE, + SPD_INSUFFICIENT_BUFFER_SIZE, + i_keyword, + TWO_UINT32_TO_UINT64( i_bufferSz, i_expBufferSz ) ); + } + + return err; +} + + +// ------------------------------------------------------------------ +// spdReadBinaryFile +// ------------------------------------------------------------------ +errlHndl_t spdReadBinaryFile ( uint64_t i_byteAddr, + size_t i_numBytes, + void * o_data ) +{ + errlHndl_t err = NULL; + const char * fileName = "dimmspd.dat"; + const char * startAddr = NULL; + size_t fileSize; + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdReadBinaryFile()" ); + + do + { + if( g_loadModule ) + { + mutex_lock( &g_spdMutex ); + + if( g_loadModule ) + { + // Load the file + TRACUCOMP( g_trac_spd, + "Load file" ); + err = VFS::module_load( fileName ); + + if( err ) + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Error opening binary SPD file: %s", + fileName ); + mutex_unlock( &g_spdMutex ); + + break; + } + + g_loadModule = false; + } + mutex_unlock( &g_spdMutex ); + } + + // Get the starting address of the file/module + TRACUCOMP( g_trac_spd, + "Get starting address/size" ); + err = VFS::module_address( fileName, + startAddr, + fileSize ); + + if( err ) + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Error getting starting address of binary SPD file: %s", + fileName ); + + break; + } + + // Check that we can read the amount of data we need to from the + // file we just loaded + TRACUCOMP( g_trac_spd, + "Check Size vs file size" ); + if( (i_byteAddr + i_numBytes) > fileSize ) + { + TRACFCOMP( g_trac_spd, + ERR_MRK"Unable to read %d bytes from %s at offset 0x%08x " + "because file size is only %d bytes!", + i_numBytes, + fileName, + i_byteAddr, + fileSize ); + uint64_t tmpData = (i_byteAddr + i_numBytes); + tmpData = tmpData << 16; + tmpData = tmpData & (fileSize & 0xFFFF); + + /*@ + * @errortype + * @reasoncode SPD_INSUFFICIENT_FILE_SIZE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_READ_BINARY_FILE + * @userdata1 File Size + * @userdata2[0:48] Starting offset into file + * @userdata2[49:63] Number of bytes to read + * @devdesc File is not sufficiently large to read number of + * bytes at offset given without overrunning file. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_READ_BINARY_FILE, + SPD_INSUFFICIENT_FILE_SIZE, + fileSize, + tmpData ); + + break; + } + + // Retrieve the data requested + TRACUCOMP( g_trac_spd, + "Copy data out of file" ); + memcpy( o_data, (startAddr + i_byteAddr), i_numBytes ); + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdReadBinaryFile()" ); + + return err; +} + + +} // end namespace SPD |