summaryrefslogtreecommitdiffstats
path: root/src/usr/pnor/pnorrp.H
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/pnor/pnorrp.H')
-rw-r--r--src/usr/pnor/pnorrp.H119
1 files changed, 97 insertions, 22 deletions
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();
};
OpenPOWER on IntegriCloud