summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDan Crowell <dcrowell@us.ibm.com>2011-07-29 13:22:18 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2011-08-08 08:03:58 -0500
commitdf4b0117660700e195864b761dfe92dd3467c686 (patch)
tree8542d84e764200031416e89a5defa166a616e0d0 /src
parentb6041015e48c8987813b2220f59da4bf6c54383e (diff)
downloadtalos-hostboot-df4b0117660700e195864b761dfe92dd3467c686.tar.gz
talos-hostboot-df4b0117660700e195864b761dfe92dd3467c686.zip
More PNOR RP work - Task 3440 (Story 3330)
Also includes testcase work for Task 3388 Change-Id: Ib4ff920f351554fe457c171f601a38809ca6ac6f Functional PNOR RP code that works with the PNOR DD. Still missing the complete path but should be ready for use by the next level up. Task 3440 Change-Id: Id32a919f88da636c341116444e557387beaccdb2 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/230 Tested-by: Jenkins Server Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com> Reviewed-by: ADAM R. MUHLE <armuhle@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/devicefw/devfwreasoncodes.H2
-rw-r--r--src/include/usr/devicefw/userif.H10
-rw-r--r--src/include/usr/pnor/pnor_reasoncodes.H9
-rw-r--r--src/include/usr/pnor/pnorif.H32
-rw-r--r--src/kernel/syscall.C38
-rw-r--r--src/usr/devicefw/associator.C2
-rw-r--r--src/usr/errl/errlentry.C1
-rw-r--r--src/usr/errl/errlmanager.C7
-rw-r--r--src/usr/pnor/pnorrp.C446
-rw-r--r--src/usr/pnor/pnorrp.H119
-rw-r--r--src/usr/pnor/test/pnorrptest.H282
11 files changed, 792 insertions, 156 deletions
diff --git a/src/include/usr/devicefw/devfwreasoncodes.H b/src/include/usr/devicefw/devfwreasoncodes.H
index 0f55f063d..16493ca5b 100644
--- a/src/include/usr/devicefw/devfwreasoncodes.H
+++ b/src/include/usr/devicefw/devfwreasoncodes.H
@@ -7,7 +7,7 @@ namespace DeviceFW
{
enum DevFwModuleId
{
- DEVFW_MOD_ASSOCIATOR = 0x00,
+ DEVFW_MOD_ASSOCIATOR = 0x01,
};
enum DevFwReasonCode
diff --git a/src/include/usr/devicefw/userif.H b/src/include/usr/devicefw/userif.H
index c1bbd864b..6c261caab 100644
--- a/src/include/usr/devicefw/userif.H
+++ b/src/include/usr/devicefw/userif.H
@@ -42,13 +42,13 @@ namespace DeviceFW
/**
* Construct a PNOR DD address
* address = 0000_0000_0000_000c_aaaa_aaaa_aaaa_aaaa
- * c=side, a=address
- * @param[in] chip Chip Select
- * @param[in] addr Offset (from zero) into selected flash chip
+ * c=chip, a=address
+ * @param[in] i_chip Chip Select
+ * @param[in] i_addr Offset (from zero) into selected flash chip
* @return 64-bit address to pass into PNOR device commands
*/
- #define DEVICE_PNOR_ADDRESS( chip, addr ) \
- DeviceFW::PNOR, ((static_cast<uint64_t>(chip)<<32)|static_cast<uint64_t>(addr))
+ #define DEVICE_PNOR_ADDRESS( i_chip, i_addr ) \
+ DeviceFW::PNOR, ((static_cast<uint64_t>(i_chip)<<32)|static_cast<uint64_t>(i_addr))
/**
diff --git a/src/include/usr/pnor/pnor_reasoncodes.H b/src/include/usr/pnor/pnor_reasoncodes.H
index 48ba21c00..0e7f002e4 100644
--- a/src/include/usr/pnor/pnor_reasoncodes.H
+++ b/src/include/usr/pnor/pnor_reasoncodes.H
@@ -7,12 +7,17 @@ namespace PNOR
{
enum PNORModuleId
{
- PNORRP_WAITFORMESSAGE = 0x01,
+ MOD_PNORRP_WAITFORMESSAGE = 0x01, /**< pnorrp.C : PnorRP::waitForMessage */
+ MOD_PNORRP_COMPUTEDEVICEADDR = 0x02, /**< pnorrp.C : PnorRP::computeDeviceAddr */
+ MOD_PNORRP_GETSECTIONINFO = 0x03, /**< pnorrp.C : PnorRP::getSectionInfo */
+ MOD_PNORRP_COMPUTESECTION = 0x04, /**< pnorrp.C : PnorRP::computeSection */
};
enum PNORReasonCode
{
- INVALID_MESSAGE = PNOR_COMP_ID | 0x01,
+ RC_INVALID_MESSAGE = PNOR_COMP_ID | 0x01,
+ RC_INVALID_ADDRESS = PNOR_COMP_ID | 0x02,
+ RC_INVALID_SECTION = PNOR_COMP_ID | 0x03,
};
};
diff --git a/src/include/usr/pnor/pnorif.H b/src/include/usr/pnor/pnorif.H
index 1b551d8ee..49f4e7879 100644
--- a/src/include/usr/pnor/pnorif.H
+++ b/src/include/usr/pnor/pnorif.H
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <builtins.h>
+#include <errl/errlentry.H>
namespace PNOR
{
@@ -14,7 +15,7 @@ enum SectionId
{
TOC, /**< Table of Contents */
GLOBAL_DATA, /**< Global Data */
- SBE_IPL, /**< Self-Boot Enginer IPL image */
+ SBE_IPL, /**< Self-Boot Engine IPL image */
HB_BASE_CODE, /**< Hostboot Base Image */
HB_DATA, /**< Hostboot Data */
HB_ERRLOGS, /**< Hostboot Error log Repository */
@@ -33,26 +34,29 @@ enum SectionId
};
/**
+ * Select a side of flash to access
+ */
+enum SideSelect
+{
+ SIDE_A, /**< A-side of flash */
+ SIDE_B, /**< B-side of flash */
+ SIDELESS, /**< Sideless data */
+};
+
+/**
* Information about a section of PNOR
*/
struct SectionInfo_t
{
SectionId id; /**< Identifier for this section */
+ SideSelect side; /**< Identifier for the side of flash */
const char* name; /**< Name of the section */
+
uint64_t vaddr; /**< Virtual address for the start of the section */
uint64_t size; /**< Actual size of content in bytes */
bool eccProtected; /**< Section is ECC protected */
};
-/**
- * Select a side of flash to access
- */
-enum SideSelect
-{
- SIDE_A = 0xA, /**< A-side of flash */
- SIDE_B = 0xB, /**< B-side of flash */
- SIDELESS = 0xF, /**< Sideless data */
-};
@@ -63,11 +67,11 @@ enum SideSelect
* @param[in] i_side Side select
* @param[out] o_info Location and size information
*
- * @return size_t Offset of section in bytes
+ * @return errlHndl_t Error log if request was invalid
*/
-void getSectionInfo( SectionId i_section,
- SideSelect i_side,
- SectionInfo_t& o_info );
+errlHndl_t getSectionInfo( SectionId i_section,
+ SideSelect i_side,
+ SectionInfo_t& o_info );
}
diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C
index 5f80e0c19..6242c4bcb 100644
--- a/src/kernel/syscall.C
+++ b/src/kernel/syscall.C
@@ -66,32 +66,32 @@ namespace Systemcalls
syscall syscalls[] =
{
- &TaskYield,
- &TaskStart,
- &TaskEnd,
+ &TaskYield, // TASK_YIELD
+ &TaskStart, // TASK_START
+ &TaskEnd, // TASK_END
- &MsgQCreate,
- &MsgQDestroy,
- &MsgQRegisterRoot,
- &MsgQResolveRoot,
+ &MsgQCreate, // MSGQ_CREATE
+ &MsgQDestroy, // MSGQ_DESTROY
+ &MsgQRegisterRoot, // MSGQ_REGISTER_ROOT
+ &MsgQResolveRoot, // MSGQ_RESOLVE_ROOT
- &MsgSend,
- &MsgSendRecv,
- &MsgRespond,
- &MsgWait,
+ &MsgSend, // MSG_SEND
+ &MsgSendRecv, // MSG_SENDRECV
+ &MsgRespond, // MSG_RESPOND
+ &MsgWait, // MSG_WAIT
- &MmioMap,
- &MmioUnmap,
+ &MmioMap, // MMIO_MAP
+ &MmioUnmap, // MMIO_UNMAP
- &TimeNanosleep,
+ &TimeNanosleep, // TIME_NANOSLEEP
- &FutexWait,
- &FutexWake,
+ &FutexWait, // FUTEX_WAIT
+ &FutexWake, // FUTEX_WAKE
- &Shutdown,
+ &Shutdown, // MISC_SHUTDOWN
- &CpuCoreType,
- &CpuDDLevel,
+ &CpuCoreType, // MISC_CPUCORETYPE
+ &CpuDDLevel, // MISC_CPUDDLEVEL
};
};
diff --git a/src/usr/devicefw/associator.C b/src/usr/devicefw/associator.C
index 80ca6d9b6..8919e0a07 100644
--- a/src/usr/devicefw/associator.C
+++ b/src/usr/devicefw/associator.C
@@ -76,6 +76,7 @@ namespace DeviceFW
if(((targets.flag) && (i_targetType != WILDCARD)) ||
((!targets.flag) && (i_targetType == WILDCARD)))
{
+ TRACFCOMP(g_traceBuffer, "Invalid registration type was given to register a device : i_opType=%d, i_accType=%d, i_targetType=%d", i_opType, i_accType, i_targetType );
/*@
* @errortype
* @moduleid DEVFW_MOD_ASSOCIATOR
@@ -211,6 +212,7 @@ namespace DeviceFW
// Call function if one was found, create error otherwise.
if (NULL == l_devRoute)
{
+ TRACFCOMP(g_traceBuffer, "A device driver operation was attempted for which no driver has been registered : i_opType=%d, i_accessType=%d, l_devType=%d", i_opType, i_accessType, l_devType );
/*@
* @errortype
* @moduleid DEVFW_MOD_ASSOCIATOR
diff --git a/src/usr/errl/errlentry.C b/src/usr/errl/errlentry.C
index fcff1c204..40138051c 100644
--- a/src/usr/errl/errlentry.C
+++ b/src/usr/errl/errlentry.C
@@ -42,6 +42,7 @@ iv_user2(i_user2),
iv_sections(NULL)
{
iv_logId = theErrlManager::instance().getUniqueErrId();
+ TRACFCOMP(ERRORLOG::g_trac_errl, "Error %d created : modid=%X, rc=%X", iv_logId, iv_modId, iv_reasonCode);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C
index 9a7a848f2..10eccbc66 100644
--- a/src/usr/errl/errlmanager.C
+++ b/src/usr/errl/errlmanager.C
@@ -51,9 +51,12 @@ void ErrlManager::commitErrLog(errlHndl_t& io_err)
}
else
{
+ TRACFCOMP( g_trac_errl, "commitErrLog()> Reasoncode=%X, Id=%d", io_err->reasonCode(), io_err->logId() );
+
+ //@fixme - an id is already assigned in the constructor, which one do we want?
// Assign a unique error ID to the committed log
- uint32_t l_errId = getUniqueErrId();
- io_err->setLogId(l_errId);
+ //uint32_t l_errId = getUniqueErrId();
+ //io_err->setLogId(l_errId);
// @todo:
// - Flatten error into PNOR
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;
+}
diff --git a/src/usr/pnor/pnorrp.H b/src/usr/pnor/pnorrp.H
index 013e37c37..dccce8cd5 100644
--- a/src/usr/pnor/pnorrp.H
+++ b/src/usr/pnor/pnorrp.H
@@ -5,7 +5,8 @@
#include <sys/msg.h>
#include <stdint.h>
#include <builtins.h>
-class Block;
+#include <errl/errlentry.H>
+#include <limits.h>
/**
* PNOR Resource Provider
@@ -27,11 +28,11 @@ class PnorRP
* @param[in] i_side Side select
* @param[out] o_info Location and size information
*
- * @return size_t Offset of section in bytes
+ * @return errlHndl_t Error log if request was invalid
*/
- void getSectionInfo( PNOR::SectionId i_section,
- PNOR::SideSelect i_side,
- PNOR::SectionInfo_t& o_info );
+ errlHndl_t getSectionInfo( PNOR::SectionId i_section,
+ PNOR::SideSelect i_side,
+ PNOR::SectionInfo_t& o_info );
protected:
/**
@@ -48,21 +49,68 @@ class PnorRP
private:
/**
+ * PNOR Constants
+ */
+ enum
+ {
+ BASE_VADDR = 0x80000000, /**< 2GB */
+
+ NUM_SIDES = 3, /**< A, B, Sideless */
+
+ SIDE_SIZE = 0x2000000, /**< Allocate 32 MB of VA per side */
+
+ SIDEA_VADDR = BASE_VADDR, /**< Base address of Side A */
+ SIDEB_VADDR = SIDEA_VADDR + SIDE_SIZE, /**< Base address of Side B */
+ SIDELESS_VADDR = SIDEA_VADDR + SIDE_SIZE*2, /**< Base address of Sideless data */
+
+ LAST_VADDR = BASE_VADDR + SIDE_SIZE*NUM_SIDES, /**< End of our VA range */
+
+ /** Real number of bytes required to read 1 logical page */
+ PAGESIZE_PLUS_ECC = PAGESIZE * (9/8), // 8 bytes of data + 1 byte of ECC
+ };
+
+ /**
* Table of Contents entry
+ * This matches the PNOR binary layout @todo this will change
*/
struct TOCEntry_t
{
char name[8]; /**< Null terminated ascii string */
- uint64_t offset; /**< Offset to region from zero */
- uint64_t size; /**< Size of region in bytes */
+ uint64_t offset; /**< Offset to region from zero (relative to chip) */
+ uint64_t size; /**< Size of region in bytes (with or without ECC?) */
uint64_t size_act; /**< Actual size of content in bytes */
char fuse_tbd[96]; /**< Remainder is TBD depending on FUSE requirements */
+ //@todo - need a chip select here I think?
+ };
+
+ /**
+ * Mode that PNOR controller is using
+ */
+ enum ControllerMode
+ {
+ MMRD_MODE, /**< MMRD - Read-Only, ECC is hidden by hardware */
+ PMRW_MODE, /**< PMRW - Write-able mode, ECC must be handled on reads/writes */
+ };
+
+ /**
+ * Internal information to deal with the sections of PNOR
+ */
+ struct SectionData_t {
+ PNOR::SectionId id; /**< Identifier for this section */
+ PNOR::SideSelect side; /** Side Select */
+
+ uint64_t chip; /**< Chip Select */
+ uint64_t mmrdAddr; /**< Address in MMRD mode (no ECC) */
+ uint64_t pmrwAddr; /**< Address in PMRW mode (with ECC) */
+ uint64_t virtAddr; /**< Virtual address for the start of the section */
+ uint64_t size; /**< Actual size of content in bytes (not including ECC) */
+ bool eccProtected; /**< Section is ECC protected */
};
/**
* Cached copy of section data
*/
- PNOR::SectionInfo_t iv_TOC[PNOR::NUM_SECTIONS+1];
+ SectionData_t iv_TOC[NUM_SIDES][PNOR::NUM_SECTIONS+1];
/**
* Pointer to the message queue where we receive messages
@@ -75,11 +123,6 @@ class PnorRP
uint64_t iv_startupRC;
/**
- * Memory Block associated with my PNOR memory space
- */
- Block* iv_block;
-
- /**
* @brief Initialize the daemon, called by constructor
*/
void initDaemon();
@@ -95,18 +138,20 @@ class PnorRP
void waitForMessage();
/**
- * @brief Retrieve 1 page of data from the PNOR device
+ * @brief Retrieve 1 logical page of data from the PNOR device
*
* @param[in] i_offset Offset into PNOR chip
* @param[in] i_chip Which PNOR chip
+ * @param[in] i_ecc true=apply ECC after reading
* @param[out] o_dest Buffer to copy data into
*/
void readFromDevice( uint64_t i_offset,
uint64_t i_chip,
+ bool i_ecc,
void* o_dest );
/**
- * @brief Write 1 page of data to the PNOR device
+ * @brief Write 1 logical page of data to the PNOR device
*
* @param[in] i_offset Offset into PNOR chip
* @param[in] i_chip Which PNOR chip
@@ -122,12 +167,31 @@ class PnorRP
* @brief Convert a virtual address into the PNOR device address
*
* @param[in] i_vaddr Virtual address of page
+ * @param[in] i_mode PNOR Controller mode
* @param[out] o_offset Offset into PNOR chip
* @param[out] o_chip Which PNOR chip
+ * @param[out] o_ecc true=data is ECC-protected
+ *
+ * @return Error if VA is bad
*/
- void computeDeviceAddr( void* i_vaddr,
- uint64_t& o_offset,
- uint64_t& o_chip );
+ errlHndl_t computeDeviceAddr( void* i_vaddr,
+ ControllerMode i_mode,
+ uint64_t& o_offset,
+ uint64_t& o_chip,
+ bool& o_ecc );
+
+ /**
+ * @brief Figure out which section a VA belongs to
+ *
+ * @param[in] i_vaddr Virtual address of page
+ * @param[out] o_side Which side of the flash
+ * @param[out] o_id Which section of PNOR
+ *
+ * @return Error if VA is bad
+ */
+ errlHndl_t computeSection( uint64_t i_vaddr,
+ PNOR::SideSelect& o_side,
+ PNOR::SectionId& o_id );
/**
* @brief Apply ECC algorithm to data
@@ -139,13 +203,15 @@ class PnorRP
void* o_ecc );
/**
- * @brief Retrieve the section Id based on the virtual address
+ * @brief Apply ECC algorithm to data, assumes size of 1 page
*
- * @param[in] i_addr Virtual address of page within section
+ * @param[in] i_orig Original data that was read
+ * @param[in] o_data Data after removing ECC
*
- * @return SectionId Id of matching section, =INVALID_SECTION if no match
+ * @return Error if ECC is incorrect
*/
- PNOR::SectionId sectionFromAddr( void* i_addr );
+ errlHndl_t stripECC( void* i_orig,
+ void* o_data );
/**
* @brief Returns true if the initial startup failed for some reason
@@ -156,6 +222,7 @@ class PnorRP
{
if( iv_startupRC )
{
+ //@patrick : Weak consistency bug? Will need some sort of lwsync / isync coordinating reading / setting of iv_startupRC if the daemonized task could be setting this.
o_rc = iv_startupRC;
return true;
}
@@ -165,6 +232,14 @@ class PnorRP
// allow local helper function to call private methods
friend void wait_for_message( void* unused );
+
+ // allow testcase to see inside
+ friend class PnorRpTest;
+
+ /**
+ * @brief Static instance function for testcase only
+ */
+ static PnorRP& getInstance();
};
diff --git a/src/usr/pnor/test/pnorrptest.H b/src/usr/pnor/test/pnorrptest.H
index e9375d3c2..c2c5cccd9 100644
--- a/src/usr/pnor/test/pnorrptest.H
+++ b/src/usr/pnor/test/pnorrptest.H
@@ -12,6 +12,10 @@
#include <errl/errlentry.H>
#include <errl/errltypes.H>
#include <pnor/pnorif.H>
+#include <sys/rp.h>
+#include <sys/msg.h>
+#include <limits.h>
+#include "../pnorrp.H"
extern trace_desc_t* g_trac_pnor;
@@ -21,16 +25,284 @@ class PnorRpTest : public CxxTest::TestSuite
public:
/**
- * @brief PNOR RP test #1
- * Description
+ * @brief PNOR RP test - Section Info
+ * Look for mismatches in section information from expected
*/
- void testXX(void)
+ void test_getSectionInfo(void)
{
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_getSectionInfo> Start" );
+ uint64_t fails = 0;
+ uint64_t total = 0;
+ PNOR::SectionInfo_t info;
+ errlHndl_t errhdl = NULL;
+
+ struct ExpVals_t {
+ uint64_t size;
+ uint64_t vaddr;
+ };
+ const ExpVals_t exp_data[] = {
+ /* TOC */ { 0x690, 0x80000000 },
+ /* GLOBAL_DATA */ { PAGESIZE, 0x8007D690 },
+ /* SBE_IPL */ { 0, 0 },
+ /* HB_BASE_CODE */ { 0, 0 },
+ /* HB_DATA */ { 2*PAGESIZE, 0x8007E690 },
+ /* HB_ERRLOGS */ { 0, 0 },
+ /* HB_EXT_CODE */ { 0x7D000, 0x80000690 },
+ /* HB_RUNTIME */ { 0, 0 },
+ /* PAYLOAD */ { 0, 0 },
+ /* PFW_LITE_CODE */ { 0, 0 },
+ /* OCC_CODE */ { 0, 0 },
+ /* KVM_PART_INFO */ { 0, 0 },
+ /* CODE_UPDATE */ { 0, 0 },
+ };
+
+ for( PNOR::SectionId id = PNOR::FIRST_SECTION;
+ id < PNOR::NUM_SECTIONS;
+ id = (PNOR::SectionId) (id + 1) )
+ {
+ total++;
+ errhdl = PNOR::getSectionInfo( id, PNOR::SIDE_A, info );
+ if( errhdl )
+ {
+ if( exp_data[id].size != 0 )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_getSectionInfo> ERROR : getSectionInfo returned error for %d : RC=%X", id, errhdl->reasonCode() );
+ TS_FAIL( "PnorRpTest::test_getSectionInfo> ERROR : Unexpected error log" );
+ fails++;
+ errlCommit(errhdl);
+ }
+ else
+ {
+ delete errhdl;
+ }
+ }
+
+ // Look for expected size
+ total++;
+ if( info.size != exp_data[id].size )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_getSectionInfo> ERROR : Mismatched size for section %d : id=%d, exp=%d, actual=%d", id, info.id, exp_data[id].size, info.size );
+ TS_FAIL( "PnorRpTest::test_getSectionInfo> ERROR : Mismatched Size" );
+ fails++;
+ }
+
+ // Look for expected vaddr
+ total++;
+ if( info.vaddr != exp_data[id].vaddr )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_getSectionInfo> ERROR : Mismatched vaddr for section %d : id=%d, exp=%d, actual=%d", id, info.id, exp_data[id].vaddr, info.vaddr );
+ TS_FAIL( "PnorRpTest::test_getSectionInfo> ERROR : Mismatched vaddr" );
+ fails++;
+ }
+ }
+
+
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_getSectionInfo> %d/%d fails", fails, total );
+ };
+
+ /**
+ * @brief PNOR RP test - Read/Write Page
+ * Use message interface to read and write individual pages
+ */
+ void test_messageReadWrite(void)
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> Start" );
+ uint64_t fails = 0;
+ uint64_t total = 0;
+ int rc = 0;
+
+ msg_q_t mq = PnorRP::getInstance().iv_msgQ;
+
+
+ // allocate some space to play with
+ uint64_t data1_r[PAGESIZE/sizeof(uint64_t)];
+ uint64_t data2_r[PAGESIZE/sizeof(uint64_t)];
+ uint64_t data_tmp[PAGESIZE/sizeof(uint64_t)];
+
+ // use the HB_DATA as scratch space
+ PNOR::SectionInfo_t info;
+ PNOR::getSectionInfo( PNOR::HB_DATA, PNOR::SIDE_A, info );
+
+ msg_t* msg = msg_allocate();
+
+ // read the first page
+ total++;
+ msg->type = RP::READ_PAGE;
+ msg->data[0] = (uint64_t)data1_r; //data[0] = address to copy into (user buffer)
+ msg->data[1] = info.vaddr; //data[1] = address to copy from (effective address)
+ rc = msg_sendrecv( mq, msg );
+ if( rc )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ_PAGE):1" );
+ TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ_PAGE):1, rc=%d", rc );
+ fails++;
+ }
+
+ // read the second page
+ total++;
+ msg->type = RP::READ_PAGE;
+ msg->data[0] = (uint64_t)data2_r; //data[0] = address to copy into (user buffer)
+ msg->data[1] = info.vaddr + PAGESIZE; //data[1] = address to copy from (effective address)
+ rc = msg_sendrecv( mq, msg );
+ if( rc )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ_PAGE):2" );
+ TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ_PAGE):2, rc=%d", rc );
+ fails++;
+ }
+
+ // put some data into the first page
+ for( uint64_t x = 0; x < (PAGESIZE/sizeof(uint64_t)); x++ )
+ {
+ data_tmp[x] = x;
+ }
+
+ // write the changed page back out
+ total++;
+ msg->type = RP::WRITE_PAGE;
+ msg->data[0] = (uint64_t)data_tmp; //data[0] = address to copy from (user buffer)
+ msg->data[1] = info.vaddr; //data[1] = address to copy into (effective address)
+ rc = msg_sendrecv( mq, msg );
+ if( rc )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(WRITE_PAGE):1" );
+ TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(WRITE_PAGE):1, rc=%d", rc );
+ fails++;
+ }
+
+ // read the first page again
+ total++;
+ msg->type = RP::READ_PAGE;
+ msg->data[0] = (uint64_t)data1_r; //data[0] = address to copy into (user buffer)
+ msg->data[1] = info.vaddr; //data[1] = address to copy from (effective address)
+ rc = msg_sendrecv( mq, msg );
+ if( rc )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ_PAGE):3" );
+ TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ_PAGE):3, rc=%d", rc );
+ fails++;
+ }
+
+ // compare to what we wrote
+ total++;
+ if( memcmp( data_tmp, data1_r, PAGESIZE ) )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : Data mismatch in page0" );
+ TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : Data mismatch in page0" );
+ fails++;
+ uint64_t* act_data = data1_r;
+ for( uint64_t x = 0; x < 4; x++ )
+ {
+ TRACFCOMP( g_trac_pnor, "ACT:%2d : %.16X %.16X %.16X %.16X", x, act_data[x*4], act_data[x*4+1], act_data[x*4+2], act_data[x*4+3] );
+ TRACFCOMP( g_trac_pnor, "EXP:%2d : %.16X %.16X %.16X %.16X", x, act_data[x*4], act_data[x*4+1], act_data[x*4+2], act_data[x*4+3] );
+ }
+ }
+
+ // read the second page again
+ total++;
+ msg->type = RP::READ_PAGE;
+ msg->data[0] = (uint64_t)data_tmp; //data[0] = address to copy into (user buffer)
+ msg->data[1] = info.vaddr + PAGESIZE; //data[1] = address to copy from (effective address)
+ rc = msg_sendrecv( mq, msg );
+ if( rc )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ_PAGE):4" );
+ TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ_PAGE):4, rc=%d", rc );
+ fails++;
+ }
+
+ // compare to what we read the first time
+ total++;
+ if( memcmp( data_tmp, data2_r, PAGESIZE ) )
+ {
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : Data mismatch in page1" );
+ TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : Data mismatch in page1" );
+ fails++;
+ uint64_t* act_data = data_tmp;
+ for( uint64_t x = 0; x < 4; x++ )
+ {
+ TRACFCOMP( g_trac_pnor, "ACT:%2d : %.16X %.16X %.16X %.16X", x, act_data[x*4], act_data[x*4+1], act_data[x*4+2], act_data[x*4+3] );
+ TRACFCOMP( g_trac_pnor, "EXP:%2d : %.16X %.16X %.16X %.16X", x, act_data[x*4], act_data[x*4+1], act_data[x*4+2], act_data[x*4+3] );
+ }
+ }
+
+ msg_free(msg);
+
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> %d/%d fails", fails, total );
+ };
+
+ /**
+ * @brief PNOR RP test - Read/Write Addresses
+ * do read/modify/write/read to different virtual addresses
+ */
+ void test_AddrReadWrite(void)
+ {
+ return; //@todo - enable this after Task 3445
+ TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> Start" );
+ uint64_t fails = 0;
+ uint64_t total = 0;
+ uint64_t* ptr = NULL;
+
+ // read a bunch of addresses
+ ptr = new uint64_t[16];
+ for( uint64_t addr = 0;
+ addr < 20;
+ addr += 2048 ) // loop at 2K (half-page) intervals
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> addr=%X", addr );
+ total++;
+ memcpy( ptr, (void*)(0x80000000+addr), 16*sizeof(uint64_t) );
+ }
+ delete[] ptr;
+
+ // setup a bunch of interesting addresses to read/write from
+ uint64_t test_addrs[] = {
+ 0x8007E690, // chip0-HB_DATA
+ 0x8207E690, // chip1-HB_DATA
+ 0x8007E790, // chip0-HB_DATA+0x100
+ 0x8207E890, // chip1-HB_DATA+0x200
+ };
+ uint64_t test_vals[] = {
+ 0x1111222233334444,
+ 0xA5A5A5A5A5A5A5A5,
+ 0x5566778899AABBCC,
+ 0xBEEFBEEFBEEFBEEF,
+ };
+
+ // loop around and do alternating writes and reads
+ for( uint64_t x = 0; x < (sizeof(test_addrs)/sizeof(test_addrs[0])); x++ )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> x1=%d", x );
+ total++;
+ ptr = (uint64_t*) test_addrs[x];
+ *ptr = test_vals[x];
+ // verify we can write data
+ if( *ptr != test_vals[x] )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> ERROR : Data mismatch in first write of address 0x%p : exp=0x%X, act=0x%X", ptr, test_vals[x], *ptr );
+ TS_FAIL( "PnorRpTest::test_AddrReadWrite> ERROR : Data mismatch in first write" );
+ fails++;
+ }
+ }
+ for( uint64_t x = 0; x < (sizeof(test_addrs)/sizeof(test_addrs[0])); x++ )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> x2=%d", x );
+ total++;
+ ptr = (uint64_t*) test_addrs[x];
+ // make sure we don't write on top of each other
+ if( *ptr != test_vals[x] )
+ {
+ TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> ERROR : Data mismatch in second read of address 0x%p : exp=0x%X, act=0x%X", ptr, test_vals[x], *ptr );
+ TS_FAIL( "PnorRpTest::test_AddrReadWrite> ERROR : Data mismatch in second read" );
+ fails++;
+ }
+ }
+
+ TRACFCOMP(g_trac_pnor, "PnorRpTest::test_AddrReadWrite> %d/%d fails", fails, total );
};
//@todo - import config data from build and compare to section info
- //@todo - do read/modify/write/read to different virtual addresses
- //@todo - send messages to do read/write of individual pages
+
};
OpenPOWER on IntegriCloud