diff options
Diffstat (limited to 'src/usr/pnor/pnorrp.C')
-rw-r--r-- | src/usr/pnor/pnorrp.C | 446 |
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; +} |