summaryrefslogtreecommitdiffstats
path: root/src/usr/pnor/pnorrp.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/pnor/pnorrp.C')
-rw-r--r--src/usr/pnor/pnorrp.C446
1 files changed, 360 insertions, 86 deletions
diff --git a/src/usr/pnor/pnorrp.C b/src/usr/pnor/pnorrp.C
index 73edaacdb..7a9992c15 100644
--- a/src/usr/pnor/pnorrp.C
+++ b/src/usr/pnor/pnorrp.C
@@ -3,33 +3,39 @@
#include <pnor/pnor_reasoncodes.H>
#include <initservice/taskargs.H>
#include <sys/msg.h>
-#include <kernel/block.H>
#include <trace/interface.H>
-#include <errl/errlentry.H>
#include <errl/errlmanager.H>
#include <targeting/targetservice.H>
#include <devicefw/userif.H>
#include <limits.h>
#include <string.h>
+#include <kernel/console.H>
// Trace definition
trace_desc_t* g_trac_pnor = NULL;
-TRAC_INIT(&g_trac_pnor, "PNOR", 4096);
+TRAC_INIT(&g_trac_pnor, "PNOR", 4096); //4K
+// Easy macro replace for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
+/**
+ * Eyecatcher strings for PNOR TOC entries
+ */
const char* cv_EYECATCHER[] = {
- "TOC", /**< PNOR_TOC : Table of Contents */
- "GLOBAL", /**< PNOR_GLOBAL_DATA : Global Data */
- "SBE", /**< PNOR_SBE_IPL : Self-Boot Enginer IPL image */
- "HBB", /**< PNOR_HB_BASE_CODE : Hostboot Base Image */
- "HBD", /**< PNOR_HB_DATA : Hostboot Data */
- "XXX", /**< PNOR_HB_ERRLOGS : Hostboot Error log Repository */
- "HBI", /**< PNOR_HB_EXT_CODE : Hostboot Extended Image */
- "HBR", /**< PNOR_HB_RUNTIME : Hostboot Runtime Image */
- "OPAL", /**< PNOR_PAYLOAD : HAL/OPAL */
- "PFWL", /**< PNOR_PFW_LITE_CODE : PFW-lite */
- "OCC", /**< PNOR_OCC_CODE : OCC Code Image */
- "PART", /**< PNOR_KVM_PART_INFO : KVM Partition Information */
- "XXX", /**< PNOR_CODE_UPDATE : Code Update Overhead */
+ "TOC", /**< PNOR::TOC : Table of Contents */
+ "GLOBAL", /**< PNOR::GLOBAL_DATA : Global Data */
+ "SBE", /**< PNOR::SBE_IPL : Self-Boot Enginer IPL image */
+ "HBB", /**< PNOR::HB_BASE_CODE : Hostboot Base Image */
+ "HBD", /**< PNOR::HB_DATA : Hostboot Data */
+ "XXX", /**< PNOR::HB_ERRLOGS : Hostboot Error log Repository */
+ "HBI", /**< PNOR::HB_EXT_CODE : Hostboot Extended Image */
+ "HBR", /**< PNOR::HB_RUNTIME : Hostboot Runtime Image */
+ "OPAL", /**< PNOR::PAYLOAD : HAL/OPAL */
+ "PFWL", /**< PNOR::PFW_LITE_CODE : PFW-lite */
+ "OCC", /**< PNOR::OCC_CODE : OCC Code Image */
+ "PART", /**< PNOR::KVM_PART_INFO : KVM Partition Information */
+ "XXX", /**< PNOR::CODE_UPDATE : Code Update Overhead */
"XXX", /**< NUM_SECTIONS : Used as invalid entry */
};
@@ -47,11 +53,11 @@ TASK_ENTRY_MACRO( PnorRP::init );
/**
* @brief Return the size and address of a given section of PNOR data
*/
-void PNOR::getSectionInfo( PNOR::SectionId i_section,
- PNOR::SideSelect i_side,
- PNOR::SectionInfo_t& o_info )
+errlHndl_t PNOR::getSectionInfo( PNOR::SectionId i_section,
+ PNOR::SideSelect i_side,
+ PNOR::SectionInfo_t& o_info )
{
- Singleton<PnorRP>::instance().getSectionInfo(i_section,i_side,o_info);
+ return Singleton<PnorRP>::instance().getSectionInfo(i_section,i_side,o_info);
}
@@ -61,7 +67,7 @@ void PNOR::getSectionInfo( PNOR::SectionId i_section,
*/
void PnorRP::init( void* i_taskArgs )
{
- TRACFCOMP(g_trac_pnor, "PnorRP::init> " );
+ TRACUCOMP(g_trac_pnor, "PnorRP::init> " );
INITSERVICE::TaskArgs::TaskArgs* args = (INITSERVICE::TaskArgs::TaskArgs*)i_taskArgs;
uint64_t rc = 0;
if( Singleton<PnorRP>::instance().didStartupFail(rc) )
@@ -80,6 +86,7 @@ void PnorRP::init( void* i_taskArgs )
*/
void wait_for_message( void* unused )
{
+ TRACUCOMP(g_trac_pnor, "wait_for_message> " );
Singleton<PnorRP>::instance().waitForMessage();
}
@@ -93,10 +100,14 @@ void wait_for_message( void* unused )
*/
PnorRP::PnorRP()
: iv_msgQ(NULL)
-,iv_block(NULL)
+,iv_startupRC(0)
{
+ TRACFCOMP(g_trac_pnor, "PnorRP::PnorRP> " );
+
// setup everything in a separate function
initDaemon();
+
+ TRACFCOMP(g_trac_pnor, "< PnorRP::PnorRP " );
}
/**
@@ -104,11 +115,12 @@ PnorRP::PnorRP()
*/
PnorRP::~PnorRP()
{
+ TRACFCOMP(g_trac_pnor, "PnorRP::~PnorRP> " );
+
// delete the message queue we created
msg_q_destroy( iv_msgQ );
- //@fixme - do we need to delete the Block we allocated?
- //delete iv_block;
+ TRACFCOMP(g_trac_pnor, "< PnorRP::~PnorRP" );
}
/**
@@ -116,6 +128,8 @@ PnorRP::~PnorRP()
*/
void PnorRP::initDaemon()
{
+ TRACUCOMP(g_trac_pnor, "PnorRP::initDaemon> " );
+
// read the TOC in the PNOR to compute the sections
readTOC();
@@ -123,25 +137,61 @@ void PnorRP::initDaemon()
iv_msgQ = msg_q_create();
// create a Block, passing in the message queue
- //@fixme iv_block = new Block( 0, 0 );
+ //@todo iv_block = new Block( 0, 0 );
// start task to wait on the queue
task_create( wait_for_message, NULL );
+
+ TRACUCOMP(g_trac_pnor, "< PnorRP::initDaemon" );
}
/**
* @brief Return the size and address of a given section of PNOR data
*/
-void PnorRP::getSectionInfo( PNOR::SectionId i_section,
- PNOR::SideSelect i_side,
- PNOR::SectionInfo_t& o_info )
+errlHndl_t PnorRP::getSectionInfo( PNOR::SectionId i_section,
+ PNOR::SideSelect i_side,
+ PNOR::SectionInfo_t& o_info )
{
- // cheat for now
+ //TRACDCOMP(g_trac_pnor, "PnorRP::getSectionInfo> i_section=%d, i_side=%X", i_section, i_side );
+ errlHndl_t errhdl = NULL;
+
+ PNOR::SectionId id = i_section;
+ // Zero-length means the section is invalid
+ if( 0 == iv_TOC[i_side][id].size )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRP::getSectionInfo> Invalid Section Requested : i_section=%d, i_side=%d", i_section, i_side );
+ TRACFCOMP(g_trac_pnor, "o_info={ id=%d, size=%d }", iv_TOC[i_side][i_section].id, iv_TOC[i_side][i_section].size );
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORRP_GETSECTIONINFO
+ * @reasoncode PNOR::RC_INVALID_SECTION
+ * @userdata1 Requested Section
+ * @userdata2 Requested Side
+ * @devdesc PnorRP::waitForMessage> Invalid Address for read/write
+ */
+ errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_GETSECTIONINFO,
+ PNOR::RC_INVALID_SECTION,
+ TO_UINT64(i_section),
+ TO_UINT64(i_side));
+
+ // set the return valid to our invalid data
+ id = PNOR::INVALID_SECTION;
+ }
- //@todo - when we get a real PNOR image
-
+ TRACFCOMP( g_trac_pnor, "i_section=%d, i_side=%d : id=%d", i_section, i_side, iv_TOC[i_side][i_section].id );
+
+ // copy my data into the external format
+ o_info.id = iv_TOC[i_side][i_section].id;
+ o_info.side = iv_TOC[i_side][i_section].side;
+ o_info.name = cv_EYECATCHER[i_section];
+ o_info.vaddr = iv_TOC[i_side][i_section].virtAddr;
+ o_info.size = iv_TOC[i_side][i_section].size;
+ o_info.eccProtected = iv_TOC[i_side][i_section].eccProtected;
+
+ return errhdl;
}
@@ -151,28 +201,60 @@ void PnorRP::getSectionInfo( PNOR::SectionId i_section,
*/
void PnorRP::readTOC()
{
+ TRACUCOMP(g_trac_pnor, "PnorRP::readTOC>" );
+
// Zero out my table
- for( PNOR::SectionId id = PNOR::FIRST_SECTION;
- id < PNOR::NUM_SECTIONS;
- id = (PNOR::SectionId) (id + 1) )
+ for( uint64_t side = 0; side < NUM_SIDES; side++ )
{
- iv_TOC[id].id = id;
- iv_TOC[id].name = cv_EYECATCHER[PNOR::INVALID_SECTION];
- iv_TOC[id].vaddr = 0;
- iv_TOC[id].size = 0;
- iv_TOC[id].eccProtected = false;
+ for( PNOR::SectionId id = PNOR::FIRST_SECTION;
+ id <= PNOR::NUM_SECTIONS; //include extra entry for error paths
+ id = (PNOR::SectionId) (id + 1) )
+ {
+ iv_TOC[side][id].id = id;
+ iv_TOC[side][id].side = (PNOR::SideSelect)side;
+ iv_TOC[side][id].chip = 0;
+ iv_TOC[side][id].mmrdAddr = 0;
+ iv_TOC[side][id].pmrwAddr = 0;
+ iv_TOC[side][id].virtAddr = 0;
+ iv_TOC[side][id].size = 0;
+ iv_TOC[side][id].eccProtected = false;
+ }
}
- // Add a special entry for error paths
- iv_TOC[PNOR::INVALID_SECTION].id = PNOR::INVALID_SECTION;
- iv_TOC[PNOR::INVALID_SECTION].name = cv_EYECATCHER[PNOR::INVALID_SECTION];
- iv_TOC[PNOR::INVALID_SECTION].vaddr = 0;
- iv_TOC[PNOR::INVALID_SECTION].size = 0;
- iv_TOC[PNOR::INVALID_SECTION].eccProtected = false;
-
- //@todo - load flash layout
-
- //@todo - read TOC if we haven't yet
+ //@todo - Add in some dummy values for now
+
+ // assume 1 chip with only 1 side for now, no sideless
+ // TOC starts at offset zero in MMRD mode
+
+ // put some random sizes in here
+ iv_TOC[PNOR::SIDE_A][PNOR::TOC].size = 8 + 8 + PNOR::NUM_SECTIONS*sizeof(TOCEntry_t);
+ iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].size = 500*1024; //500K
+ iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].size = PAGESIZE; //4K
+ iv_TOC[PNOR::SIDE_A][PNOR::HB_DATA].size = 2*PAGESIZE; //8K
+
+ // fake PNOR will look like this: TOC::HB_EXT_CODE:GLOBAL_DATA:HB_DATA
+ // virtual addresses
+ iv_TOC[PNOR::SIDE_A][PNOR::TOC].virtAddr = BASE_VADDR + 0;
+ iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].virtAddr = iv_TOC[PNOR::SIDE_A][PNOR::TOC].virtAddr + iv_TOC[PNOR::SIDE_A][PNOR::TOC].size;
+ iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].virtAddr = iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].virtAddr + iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].size;
+ iv_TOC[PNOR::SIDE_A][PNOR::HB_DATA].virtAddr = iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].virtAddr + iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].size;
+ // MMRD offsets
+ iv_TOC[PNOR::SIDE_A][PNOR::TOC].mmrdAddr = 0;
+ iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].mmrdAddr = iv_TOC[PNOR::SIDE_A][PNOR::TOC].mmrdAddr + iv_TOC[PNOR::SIDE_A][PNOR::TOC].size;
+ iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].mmrdAddr = iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].mmrdAddr + iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].size;
+ iv_TOC[PNOR::SIDE_A][PNOR::HB_DATA].mmrdAddr = iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].mmrdAddr + iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].size;
+ // PMRW offsets - no ECC support yet so just equal to MMRD
+ iv_TOC[PNOR::SIDE_A][PNOR::TOC].pmrwAddr = BASE_VADDR + 0;
+ iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].pmrwAddr = iv_TOC[PNOR::SIDE_A][PNOR::TOC].virtAddr + iv_TOC[PNOR::SIDE_A][PNOR::TOC].size;
+ iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].pmrwAddr = iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].virtAddr + iv_TOC[PNOR::SIDE_A][PNOR::HB_EXT_CODE].size;
+ iv_TOC[PNOR::SIDE_A][PNOR::HB_DATA].pmrwAddr = iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].virtAddr + iv_TOC[PNOR::SIDE_A][PNOR::GLOBAL_DATA].size;
+
+ //@todo - end fake data
+
+ //@todo - load flash layout (how many chips)
+ //@todo - read TOC on each chip/bank/whatever
+
+ TRACUCOMP(g_trac_pnor, "< PnorRP::readTOC" );
}
@@ -182,6 +264,9 @@ void PnorRP::readTOC()
*/
void PnorRP::waitForMessage()
{
+ TRACFCOMP(g_trac_pnor, "PnorRP::waitForMessage>" );
+
+ errlHndl_t l_err = NULL;
msg_t* message = NULL;
uint8_t* user_addr = NULL;
uint8_t* eff_addr = NULL;
@@ -191,43 +276,68 @@ void PnorRP::waitForMessage()
while(1)
{
+ TRACUCOMP(g_trac_pnor, "PnorRP::waitForMessage> waiting for message" );
message = msg_wait( iv_msgQ );
if( message )
{
user_addr = (uint8_t*)message->data[0];
eff_addr = (uint8_t*)message->data[1];
- computeDeviceAddr( eff_addr, dev_offset, chip_select );
- needs_ecc = iv_TOC[sectionFromAddr(eff_addr)].eccProtected;
+ l_err = computeDeviceAddr( eff_addr, MMRD_MODE, dev_offset, chip_select, needs_ecc );
+ //@todo - assuming MMRD mode for now
+ if( l_err )
+ {
+ errlCommit(l_err);
+ //@todo - kill calling task?, commit log
+
+ if( !msg_is_async(message) )
+ {
+ TRACUCOMP( g_trac_pnor, "sending response...\n" );
+ msg_respond( iv_msgQ, message ); //@todo - what goes in response message?
+ }
+ continue; // go wait for another message
+ }
+
+ //@todo - handle MMRD/PMRW mode
+ // if MMRD then needs_ecc = false
switch(message->type)
{
case( RP::READ_PAGE ):
- readFromDevice( dev_offset, chip_select, user_addr );
+ readFromDevice( dev_offset, chip_select, needs_ecc, user_addr );
break;
case( RP::WRITE_PAGE ):
- writeToDevice( dev_offset, chip_select, true, user_addr );
+ writeToDevice( dev_offset, chip_select, needs_ecc, user_addr );
break;
default:
- TRACFCOMP( g_trac_pnor, "PnorRP::waitForMessage> Unrecognized message type user_addr=%p, eff_addr=%p, msgtype=%d", user_addr, eff_addr, message->type );
+ TRACFCOMP( g_trac_pnor, "PnorRP::waitForMessage> Unrecognized message type : user_addr=%p, eff_addr=%p, msgtype=%d", user_addr, eff_addr, message->type );
/*@
* @errortype
- * @moduleid PNOR::PNORRP_WAITFORMESSAGE
- * @reasoncode PNOR::INVALID_MESSAGE
+ * @moduleid PNOR::MOD_PNORRP_WAITFORMESSAGE
+ * @reasoncode PNOR::RC_INVALID_MESSAGE
* @userdata1 Message type
* @userdata2 User memory address
* @devdesc PnorRP::waitForMessage> Unrecognized message type
*/
- errlHndl_t l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- PNOR::PNORRP_WAITFORMESSAGE,
- PNOR::INVALID_MESSAGE,
- (uint64_t)message->type,
- (uint64_t)user_addr);
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_WAITFORMESSAGE,
+ PNOR::RC_INVALID_MESSAGE,
+ TO_UINT64(message->type),
+ (uint64_t)user_addr);
errlCommit(l_err);
- //@fixme - kill calling task?, commit log
+ //@todo - kill calling task?, commit log
+ continue; // go wait for another message
+ }
+
+ if( !msg_is_async(message) )
+ {
+ TRACUCOMP( g_trac_pnor, "sending response...\n" );
+ msg_respond( iv_msgQ, message ); //@todo - what goes in response message?
}
}
}
+
+ TRACFCOMP(g_trac_pnor, "< PnorRP::waitForMessage" );
}
@@ -236,18 +346,43 @@ void PnorRP::waitForMessage()
*/
void PnorRP::readFromDevice( uint64_t i_offset,
uint64_t i_chip,
+ bool i_ecc,
void* o_dest )
{
- TARGETING::Target* pnor_target = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL; //@fixme
+ TRACUCOMP(g_trac_pnor, "PnorRP::readFromDevice> i_offset=0x%X, i_chip=%d", i_offset, i_chip );
+ TARGETING::Target* pnor_target = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL; //@todo
+
+ void* data_to_read = o_dest;
+ uint8_t* ecc_buffer = NULL;
size_t read_size = PAGESIZE;
+ if( i_ecc )
+ {
+ ecc_buffer = new uint8_t[PAGESIZE_PLUS_ECC];
+ data_to_read = ecc_buffer;
+ read_size = PAGESIZE_PLUS_ECC;
+ }
+
errlHndl_t l_err = DeviceFW::deviceRead(pnor_target,
- o_dest,
+ data_to_read,
read_size,
- DEVICE_PNOR_ADDRESS(i_offset,i_chip) );
- errlCommit(l_err);
- //@fixme - commit log
+ DEVICE_PNOR_ADDRESS(i_chip,i_offset) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRP::readFromDevice> Error from device : RC=%X", l_err->reasonCode() );
+ errlCommit(l_err);
+ //@todo - anything else?
+ }
+
+ // remove the ECC data
+ if( i_ecc )
+ {
+ l_err = stripECC( data_to_read, o_dest );
+ //@todo - handle ECC error
+ delete[] ecc_buffer;
+ }
+ TRACUCOMP(g_trac_pnor, "< PnorRP::readFromDevice" );
}
/**
@@ -258,60 +393,199 @@ void PnorRP::writeToDevice( uint64_t i_offset,
bool i_ecc,
void* i_src )
{
- TARGETING::Target* pnor_target = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL; //@fixme
+ TRACUCOMP(g_trac_pnor, "PnorRP::writeToDevice> i_offset=%X, i_chip=%d", i_offset, i_chip );
+
+ TARGETING::Target* pnor_target = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL; //@todo
// apply ECC to data if needed
void* data_to_write = i_src;
- void* ecc_buffer = NULL;
+ uint8_t* ecc_buffer = NULL;
if( i_ecc )
{
- ecc_buffer = (void*)new uint8_t[PAGESIZE];
+ ecc_buffer = new uint8_t[PAGESIZE];
applyECC( i_src, ecc_buffer );
- data_to_write = ecc_buffer;
+ data_to_write = (void*)ecc_buffer;
}
size_t write_size = PAGESIZE;
errlHndl_t l_err = DeviceFW::deviceWrite(pnor_target,
data_to_write,
write_size,
- DEVICE_PNOR_ADDRESS(i_offset,i_chip) );
- errlCommit(l_err);
+ DEVICE_PNOR_ADDRESS(i_chip,i_offset) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRP::readFromDevice> Error from device : RC=%X", l_err->reasonCode() );
+ errlCommit(l_err);
+ //@todo - anything else?
+ }
+ if( ecc_buffer )
+ {
+ delete[] ecc_buffer;
+ }
+
+ TRACUCOMP(g_trac_pnor, "< PnorRP::writeToDevice" );
}
/**
* @brief Convert a virtual address into the PNOR device address
*/
-void PnorRP::computeDeviceAddr( void* i_vaddr,
- uint64_t& o_offset,
- uint64_t& o_chip )
+errlHndl_t PnorRP::computeDeviceAddr( void* i_vaddr,
+ ControllerMode i_mode,
+ uint64_t& o_offset,
+ uint64_t& o_chip,
+ bool& o_ecc )
{
- //@fixme
- o_offset = ((uint64_t)i_vaddr) - iv_block->getBaseAddress();
- o_chip = 0;
+ errlHndl_t l_err = NULL;
+ o_offset = 0;
+ o_chip = 99;
+ uint64_t l_vaddr = (uint64_t)i_vaddr;
+
+ // make sure this is one of our addresses
+ if( !((l_vaddr >= BASE_VADDR)
+ && (l_vaddr < LAST_VADDR)) )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRP::computeDeviceAddr> Virtual Address outside known PNOR range : i_vaddr=%p", i_vaddr );
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORRP_WAITFORMESSAGE
+ * @reasoncode PNOR::RC_INVALID_MESSAGE
+ * @userdata1 Virtual Address
+ * @userdata2 Base PNOR Address
+ * @devdesc PnorRP::computeDeviceAddr> Virtual Address outside
+ * known PNOR range
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_COMPUTEDEVICEADDR,
+ PNOR::RC_INVALID_ADDRESS,
+ l_vaddr,
+ BASE_VADDR);
+ return l_err;
+ }
+
+ // find the matching section
+ PNOR::SideSelect side = PNOR::SIDE_A;
+ PNOR::SectionId id = PNOR::INVALID_SECTION;
+ l_err = computeSection( l_vaddr, side, id );
+ if( l_err )
+ {
+ return l_err;
+ }
+
+ // pull out the information we need to return from our global copy
+ o_chip = iv_TOC[side][id].chip;
+ o_ecc = iv_TOC[side][id].eccProtected;
+ o_offset = l_vaddr - iv_TOC[side][id].virtAddr; //offset into pnor
+ if( MMRD_MODE == i_mode )
+ {
+ o_offset += iv_TOC[side][id].mmrdAddr;
+ }
+ else
+ {
+ o_offset += iv_TOC[side][id].pmrwAddr;
+ }
+
+ TRACUCOMP( g_trac_pnor, "< PnorRP::computeDeviceAddr: o_offset=0x%X, o_chip=%d", o_offset, o_chip );
+ return l_err;
}
/**
* @brief Apply ECC algorithm to data, assumes size of 1 page
- *
- * @param[in] i_orig Original data to write
- * @param[in] o_ecc Data after applying ECC
*/
void PnorRP::applyECC( void* i_orig,
void* o_ecc )
{
+ TRACFCOMP(g_trac_pnor, "> PnorRP::applyECC" );
+
//@todo - fill this in
memcpy( o_ecc, i_orig, PAGESIZE );
+
+ TRACFCOMP(g_trac_pnor, "< PnorRP::applyECC" );
+}
+
+/**
+ * @brief Apply ECC algorithm to data, assumes logical size of 1 page
+ */
+errlHndl_t PnorRP::stripECC( void* i_orig,
+ void* o_data )
+{
+ TRACFCOMP(g_trac_pnor, "> PnorRP::stripECC" );
+
+ //@todo - fill this in
+ memcpy( o_data, i_orig, PAGESIZE );
+
+ TRACFCOMP(g_trac_pnor, "< PnorRP::stripECC" );
+ return NULL;
}
/**
- * @brief Retrieve the section Id based on the virtual address
+ * @brief Static instance function for testcase only
*/
-PNOR::SectionId PnorRP::sectionFromAddr( void* i_addr )
+PnorRP& PnorRP::getInstance()
{
- //@fixme - how do I do this?
- return PNOR::INVALID_SECTION;
+ return Singleton<PnorRP>::instance();
}
+/**
+ * @brief Figure out which section a VA belongs to
+ */
+errlHndl_t PnorRP::computeSection( uint64_t i_vaddr,
+ PNOR::SideSelect& o_side,
+ PNOR::SectionId& o_id )
+{
+ errlHndl_t errhdl = NULL;
+
+ o_id = PNOR::INVALID_SECTION;
+
+ // first figure out which side it is on (slight performance boost)
+ if( (i_vaddr >= SIDEA_VADDR)
+ && (i_vaddr < (SIDEA_VADDR + SIDE_SIZE)) )
+ {
+ o_side = PNOR::SIDE_A;
+ }
+ else if( (i_vaddr >= SIDEB_VADDR)
+ && (i_vaddr < (SIDEB_VADDR + SIDE_SIZE)) )
+ {
+ o_side = PNOR::SIDE_B;
+ }
+ else if( (i_vaddr >= SIDELESS_VADDR)
+ && (i_vaddr < (SIDELESS_VADDR + SIDE_SIZE)) )
+ {
+ o_side = PNOR::SIDELESS;
+ }
+ else
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRP::computeSection> Invalid virtual address : i_vaddr=%X", i_vaddr );
+ /*@
+ * @errortype
+ * @moduleid PNOR::MOD_PNORRP_COMPUTESECTION
+ * @reasoncode PNOR::RC_INVALID_ADDRESS
+ * @userdata1 Requested Virtual Address
+ * @userdata2 <unused>
+ * @devdesc PnorRP::computeSection> Invalid Address
+ */
+ errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ PNOR::MOD_PNORRP_COMPUTESECTION,
+ PNOR::RC_INVALID_ADDRESS,
+ i_vaddr,
+ 0);
+ return errhdl;
+ }
+
+ // loop through all sections to find a matching id
+ for( PNOR::SectionId id = PNOR::FIRST_SECTION;
+ id < PNOR::NUM_SECTIONS;
+ id = (PNOR::SectionId) (id + 1) )
+ {
+ if( (i_vaddr >= iv_TOC[o_side][id].virtAddr)
+ && (i_vaddr < (iv_TOC[o_side][id].virtAddr + iv_TOC[o_side][id].size)) )
+ {
+ o_id = iv_TOC[o_side][id].id;
+ break;
+ }
+ }
+
+ return errhdl;
+}
OpenPOWER on IntegriCloud