From 5867b512c1592fce1a5bab56e4320efd6598645f Mon Sep 17 00:00:00 2001 From: Adam Muhle Date: Tue, 26 Jul 2011 09:57:45 -0500 Subject: Adding fake PNOR Device Driver Support Change-Id: Ic434159183bc4dd91c8ba588730cda7e0766c6c0 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/223 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell --- src/usr/cxxtest/cxxtestexec.C | 2 + src/usr/pnor/makefile | 2 +- src/usr/pnor/pnordd.C | 301 +++++++++++++++++++++++++++++++++++++++++ src/usr/pnor/pnordd.H | 98 ++++++++++++++ src/usr/pnor/test/makefile | 2 +- src/usr/pnor/test/pnorddtest.H | 130 ++++++++++++++++++ 6 files changed, 533 insertions(+), 2 deletions(-) create mode 100644 src/usr/pnor/pnordd.C create mode 100644 src/usr/pnor/pnordd.H create mode 100644 src/usr/pnor/test/pnorddtest.H (limited to 'src/usr') diff --git a/src/usr/cxxtest/cxxtestexec.C b/src/usr/cxxtest/cxxtestexec.C index 5470b718a..63a12c7ca 100644 --- a/src/usr/cxxtest/cxxtestexec.C +++ b/src/usr/cxxtest/cxxtestexec.C @@ -117,6 +117,8 @@ void _start(void *io_pArgs) tidrc = task_exec( vfsItr->module, NULL ); TRACDCOMP( g_trac_cxxtest, "Launched task: tidrc=%d", tidrc ); + //@fixme-try to alleviate cxxtest deadlock + nanosleep( 1, 0 ); //sleep 1 second } } diff --git a/src/usr/pnor/makefile b/src/usr/pnor/makefile index d52765cd1..0700f7554 100644 --- a/src/usr/pnor/makefile +++ b/src/usr/pnor/makefile @@ -1,7 +1,7 @@ ROOTPATH = ../../.. MODULE = pnor -OBJS = pnorrp.o +OBJS = pnorrp.o pnordd.o SUBDIRS = test.d diff --git a/src/usr/pnor/pnordd.C b/src/usr/pnor/pnordd.C new file mode 100644 index 000000000..fe4699fbe --- /dev/null +++ b/src/usr/pnor/pnordd.C @@ -0,0 +1,301 @@ +/** + * @file pnordd.C + * + * @brief Implementation of the PNOR Device Driver + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pnordd.H" +#include + +#define FAKE_PNOR_START 7*1024*1024 +#define FAKE_PNOR_END 8*1024*1024 + + +extern trace_desc_t* g_trac_pnor; + +namespace PNOR +{ + + + +/** + * @brief Performs an PNOR Read Operation + * This function performs a PNOR Read operation. It follows a pre-defined + * prototype functions in order to be registered with the device-driver + * framework. + * + * @param[in] i_opType Operation type, see DeviceFW::OperationType + * in driverif.H + * @param[in] i_target PNOR target + * @param[in/out] io_buffer Read: Pointer to output data storage + * Write: Pointer to input data storage + * @param[in/out] io_buflen Input: size of io_buffer (in bytes) + * Output: + * Read: Size of output data + * Write: Size of data written + * @param[in] i_accessType DeviceFW::AccessType enum (usrif.H) + * @param[in] i_args This is an argument list for DD framework. + * In this function, there's only one argument, + * containing the PNOR address and chip select + * @return errlHndl_t + */ +errlHndl_t ddRead(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 l_err = NULL; + uint64_t l_addr = va_arg(i_args,uint64_t); + + do{ + l_err = Singleton::instance().read(io_buffer, + io_buflen, + l_addr); + if(l_err) + { + break; + } + + }while(0); + + return l_err; +} + +/** + * @brief Performs an PNOR Write Operation + * This function performs a PNOR Write operation. It follows a pre-defined + * prototype functions in order to be registered with the device-driver + * framework. + * + * @param[in] i_opType Operation type, see DeviceFW::OperationType + * in driverif.H + * @param[in] i_target PNOR target + * @param[in/out] io_buffer Read: Pointer to output data storage + * Write: Pointer to input data storage + * @param[in/out] io_buflen Input: size of io_buffer (in bytes) + * Output: + * Read: Size of output data + * Write: Size of data written + * @param[in] i_accessType DeviceFW::AccessType enum (usrif.H) + * @param[in] i_args This is an argument list for DD framework. + * In this function, there's only one argument, + * containing the PNOR address and chip select + * @return errlHndl_t + */ +errlHndl_t ddWrite(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 l_err = NULL; + uint64_t l_addr = va_arg(i_args,uint64_t); + + do{ + l_err = Singleton::instance().write(io_buffer, + io_buflen, + l_addr); + if(l_err) + { + break; + } + + }while(0); + + return l_err; +} + +// Register PNORDD access functions to DD framework +DEVICE_REGISTER_ROUTE(DeviceFW::READ, + DeviceFW::PNOR, + TARGETING::TYPE_PROC, + ddRead); + +DEVICE_REGISTER_ROUTE(DeviceFW::WRITE, + DeviceFW::PNOR, + TARGETING::TYPE_PROC, + ddWrite); + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +errlHndl_t setLSCAccessMode(lscMode i_mode) +{ + errlHndl_t l_err = NULL; + + do{ + l_err = Singleton::instance().setAccessMode(i_mode); + if(l_err) + { + break; + } + + }while(0); + + return l_err; +} + + +/** + * @brief Read PNOR + */ +errlHndl_t PnorDD::read(void* o_buffer, + size_t& io_buflen, + uint64_t i_address) +{ + TRACDCOMP(g_trac_pnor, "PnorDD::read(i_address=0x%llx)> ", i_address); + errlHndl_t l_err = NULL; + + do{ + //mask off chip select for now, will probably break up fake PNOR into + //multiple fake chips eventually + uint64_t l_address = i_address & 0x00000000FFFFFFFF; + + l_err = verifyAddressRange(l_address, io_buflen); + if(l_err) + { + io_buflen = 0; + break; + } + + //create a pointer to the offset start. + char * srcPtr = (char *)(FAKE_PNOR_START+l_address); + + //@TODO: likely need a mutex around HW access + + //copy data from memory into the buffer. + memcpy(o_buffer, srcPtr, io_buflen); + + + }while(0); + + return l_err; +} + +/** + * @brief Write PNOR + */ +errlHndl_t PnorDD::write(void* i_buffer, + size_t& io_buflen, + uint64_t i_address) +{ + TRACDCOMP(g_trac_pnor, "PnorDD::write(i_address=0x%llx)> ", i_address); + errlHndl_t l_err = NULL; + + do{ + //mask off chip select for now, will probably break up fake PNOR into + //multiple fake chips eventually + uint64_t l_address = i_address & 0x00000000FFFFFFFF; + + + l_err = verifyAddressRange(l_address, io_buflen); + if(l_err) + { + io_buflen = 0; + break; + } + + //create a pointer to the offset start. + char * destPtr = (char *)(FAKE_PNOR_START+l_address); + + //@TODO: likely need a mutex around HW access + + //copy data from memory into the buffer. + memcpy(destPtr, i_buffer, io_buflen); + + + }while(0); + + return l_err; +} + +/** + * @brief Set PNOR to desired mode + */ +errlHndl_t PnorDD::setAccessMode(lscMode i_mode) +{ + errlHndl_t l_err = NULL; + TRACFCOMP(g_trac_pnor, "PnorDD::setAccessMode(0x%llx)> ", i_mode); + + do{ + //@TODO: real impelementation needed + + //Once we have a 'real' implementation, it will likely drive the need for mutexes + //throughout the PnorDD interfaces, to avoid issues with weak consistency or a + //read/write occuring while we're updating the mode, but + //skipping that until it's actually needed. + + //Eventually need to actually change HW state here. + //For now, just record the new mode. + iv_lscMode = i_mode; + + + }while(0); + + return l_err; +} + + +/******************** + Private/Protected Methods + ********************/ + + +/** + * @brief Constructor + */ +PnorDD::PnorDD() +: iv_lscMode(MMRD) +{ + TRACFCOMP(g_trac_pnor, "PnorDD::PnorDD()> "); + +} + +/** + * @brief Destructor + */ +PnorDD::~PnorDD() +{ + + //Nothing todo for now +} + +errlHndl_t PnorDD::verifyAddressRange(uint64_t i_address, + size_t& i_length) +{ + errlHndl_t l_err = NULL; + + do{ + + if((i_address < FAKE_PNOR_START) || + ((i_address+i_length) > FAKE_PNOR_END)) + { + //@TODO create errorlog + break; + } + + + + }while(0); + + return l_err; +} + + + +}; //end PNOR namespace diff --git a/src/usr/pnor/pnordd.H b/src/usr/pnor/pnordd.H new file mode 100644 index 000000000..df953e203 --- /dev/null +++ b/src/usr/pnor/pnordd.H @@ -0,0 +1,98 @@ +#ifndef __PNOR_PNORDD_H +#define __PNOR_PNORDD_H + +/** @file pnordd.H + * @brief Provides the interfaces to the PNOR Device Driver + */ + +namespace PNOR +{ + +//Not sure if this is the right place for these enums, open to suggestions. +/** + * PNOR Modes + */ +enum lscMode +{ + MMRD = 0, /**< Indicates PNOR is in MMRD Mode */ + PMWR, /**< Indicates PNOR is in PMWR Mode */ + + LAST_MODE = PMWR, +}; + + +/** + * @brief Type definition for PNOR address + */ +typedef uint64_t PNORAddress_t; + + +//@TODO: comment args +/** + * @brief External interface for setting LSC mode + */ +errlHndl_t setLSCAccessMode(lscMode i_mode); + + + +class PnorDD +{ + + public: + //@TODO: comment args + /** + * @brief Performs an PNOR Read Operation + */ + errlHndl_t read(void* o_buffer, + size_t& io_buflen, + uint64_t i_address); + + //@TODO: comment args + /** + * @brief Performs an PNOR Write Operation + */ + errlHndl_t write(void* i_buffer, + size_t& io_buflen, + uint64_t i_address); + + //@TODO: comment args + /** + * @brief Set LSC to desired access mode + */ + errlHndl_t setAccessMode(lscMode i_mode); + + + + protected: + /** + * @brief Constructor + */ + PnorDD(); + + + /** + * @brief Destructor + */ + ~PnorDD(); + + //@TODO: comment args + /** + * Verify Request is in appropriate address range + * + */ + errlHndl_t verifyAddressRange(uint64_t i_address, + size_t& i_length); + + + private: + + /** + * PNOR Mode Flag + */ + lscMode iv_lscMode; + +}; + +}; //end PNOR namespace + +#endif diff --git a/src/usr/pnor/test/makefile b/src/usr/pnor/test/makefile index a499d93c4..9e8a10c59 100644 --- a/src/usr/pnor/test/makefile +++ b/src/usr/pnor/test/makefile @@ -1,6 +1,6 @@ ROOTPATH = ../../../.. -MODULE = pnorrptest +MODULE = testpnor TESTS = *.H include ${ROOTPATH}/config.mk diff --git a/src/usr/pnor/test/pnorddtest.H b/src/usr/pnor/test/pnorddtest.H new file mode 100644 index 000000000..a60d53efe --- /dev/null +++ b/src/usr/pnor/test/pnorddtest.H @@ -0,0 +1,130 @@ +#ifndef __PNORDDTEST_H +#define __PNORDDTEST_H + +/** + * @file pnorddtest.H + * + * @brief Test case for PNOR Resource Provider +*/ + +#include +#include +#include +#include +#include +#include +//#include "../pnordd.H" + +extern trace_desc_t* g_trac_pnor; +using namespace TARGETING; + + +class PnorDdTest : public CxxTest::TestSuite +{ + public: + + /** + * @brief PNOR DD test #1 + * Write some data to PNOR and read it back again + */ + void testPnorDD1(void) + { + //@TODO: make this table driven so it can test more values + //@TODO: compare results with expected data. + //@TODO: Add some more interesting tests + + TARGETING::Target* l_testTarget = MASTER_PROCESSOR_CHIP_TARGET_SENTINEL; + size_t l_size = sizeof(uint64_t); + errlHndl_t l_err = NULL; + + do{ + TS_TRACE("testPnorDD1: starting"); + + // Perform PnorDD Write 1 + uint64_t l_address = 0x100; + uint64_t l_writeData = 0x12345678FEEDB0B0; + l_err = deviceWrite(l_testTarget, + &l_writeData, + l_size, + DEVICE_PNOR_ADDRESS(0, l_address)); + if (l_err) + { + TS_FAIL("testPnorDD1: PNORDD write 1: deviceWrite() failed! Error committed."); + break; + } + else + { + TS_TRACE("testPnorDD1: PNORDD write 1, Address 0x%llx, Data %llx", + l_address, + (long long unsigned)l_writeData); + } + + + // Perform PnorDD Write 2 + l_address = 0x108; + l_writeData = 0xFEEDBEEF000ABCDE; + l_err = deviceWrite(l_testTarget, + &l_writeData, + l_size, + DEVICE_PNOR_ADDRESS(0, l_address)); + if (l_err) + { + TS_FAIL("testPnorDD1: PNORDD write 2: deviceWrite() failed! Error committed."); + break; + } + else + { + TS_TRACE("testPnorDD1: PNORDD write 2, Address 0x%llx, Data %llx", + l_address, + (long long unsigned)l_writeData); + } + + // Perform PnorDD read 1 + l_address = 0x100; + uint64_t l_readData = 0; + l_err = deviceRead(l_testTarget, + &l_readData, + l_size, + DEVICE_PNOR_ADDRESS(0, l_address)); + if (l_err) + { + TS_FAIL("testPnorDD1: PNORDD read 1: deviceRead() failed! Error committed."); + break; + } + else + { + TS_TRACE("testPnorDD1: PNORDD read 1, Address 0x%llx, Data %llx", + l_address, + (long long unsigned)l_readData); + } + + // Perform PnorDD read 2 + l_address = 0x108; + l_err = deviceRead(l_testTarget, + &l_readData, + l_size, + DEVICE_PNOR_ADDRESS(0, l_address)); + if (l_err) + { + TS_FAIL("testPnorDD1: PNORDD read 2: deviceRead() failed! Error committed."); + break; + } + else + { + TS_TRACE("testPnorDD1: PNORDD read 2, Address 0x%llx, Data %llx", + l_address, + (long long unsigned)l_readData); + } + + }while(0); + + + //@TODO: Add total fail/pass count trace to know how many passed. + + }; + + +}; + + +#endif -- cgit v1.2.1