summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/devicefw/userif.H13
-rw-r--r--src/include/usr/hbotcompid.H9
-rw-r--r--src/include/usr/mbox/mbox_reasoncodes.H46
-rw-r--r--src/include/usr/mbox/mboxif.H41
-rw-r--r--src/makefile4
-rw-r--r--src/usr/makefile2
-rw-r--r--src/usr/mbox/makefile30
-rw-r--r--src/usr/mbox/mboxdd.C541
-rw-r--r--src/usr/mbox/mboxdd.H121
-rw-r--r--src/usr/mbox/test/makefile28
-rw-r--r--src/usr/mbox/test/mboxddtest.H123
11 files changed, 947 insertions, 11 deletions
diff --git a/src/include/usr/devicefw/userif.H b/src/include/usr/devicefw/userif.H
index 336bce720..8d95db3a9 100644
--- a/src/include/usr/devicefw/userif.H
+++ b/src/include/usr/devicefw/userif.H
@@ -63,12 +63,6 @@ namespace DeviceFW
#define DEVICE_PRESENT_ADDRESS() \
DeviceFW::PRESENT
- /** Construct the device addressing parameters for FSI device ops.
- * @param[in] i_address - FSI address to operate on.
- */
- #define DEVICE_FSI_ADDRESS(i_address) \
- DeviceFW::FSI, static_cast<uint64_t>((i_address))
-
/**
* Construct a PNOR DD address
* address = 0000_0000_0000_000c_aaaa_aaaa_aaaa_aaaa
@@ -94,6 +88,13 @@ namespace DeviceFW
#define DEVICE_SPD_ADDRESS( i_keyword )\
DeviceFW::SPD, static_cast<uint64_t>(( i_keyword ))
+ /**
+ * Construct the device addressing parameters for the MAILBOX device.
+ * @param[out] o_status - Set with all available status bits
+ * from MBOX::MboxReadStatus
+ */
+ #define DEVICE_MBOX_ADDRESS(o_status) \
+ DeviceFW::MAILBOX, static_cast<uint64_t*>((o_status))
/**
* @brief Perform a hardware read operation.
diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H
index 0c36827a3..6e812ea5b 100644
--- a/src/include/usr/hbotcompid.H
+++ b/src/include/usr/hbotcompid.H
@@ -170,7 +170,6 @@ const compId_t INTR_COMP_ID = 0x0F00;
const char INTR_COMP_NAME[] = "intr";
//@}
-
/** @name SPD
* EEPROM device driver component
*/
@@ -179,6 +178,13 @@ const compId_t SPD_COMP_ID = 0x1000;
const char SPD_COMP_NAME[] = "spd";
//@}
+/** @name MBOX
+ * MBOX component
+ */
+//@{
+const compId_t MBOX_COMP_ID = 0x1100;
+const char MBOX_COMP_NAME[] = "mbox";
+//@}
/** @name RESERVED
* Reserved component ID. x3100 is the component ID
@@ -189,7 +195,6 @@ const char SPD_COMP_NAME[] = "spd";
//@{
const compId_t RESERVED_COMP_ID = 0x3100;
const char RESERVED_COMP_NAME[] = "reserved";
-//@}
// ----------------------------------------------------------
// CXXTEST Unit Test, reserve compid near the end...
diff --git a/src/include/usr/mbox/mbox_reasoncodes.H b/src/include/usr/mbox/mbox_reasoncodes.H
new file mode 100644
index 000000000..126eb2f75
--- /dev/null
+++ b/src/include/usr/mbox/mbox_reasoncodes.H
@@ -0,0 +1,46 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/usr/mbox/mbox_reasoncodes.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __MBOX_REASONCODES_H
+#define __MBOX_REASONCODES_H
+
+#include <hbotcompid.H>
+
+namespace MBOX
+{
+ enum MBOXModuleId
+ {
+ MOD_MBOXDD_INVALID = 0x00, /**< Zero is an invalid module id */
+ MOD_MBOXDD_READ = 0x01,
+ MOD_MBOXDD_WRITE = 0x02,
+ };
+
+ enum MBOXReasonCode
+ {
+ RC_INVALID_LENGTH = MBOX_COMP_ID | 0x01,
+ RC_INVALID_MESSAGE_TYPE = MBOX_COMP_ID | 0x02,
+ RC_NO_PERM_TO_SEND = MBOX_COMP_ID | 0x03,
+ RC_MSG_PENDING = MBOX_COMP_ID | 0x04,
+ };
+};
+
+#endif
diff --git a/src/include/usr/mbox/mboxif.H b/src/include/usr/mbox/mboxif.H
new file mode 100644
index 000000000..214f73c37
--- /dev/null
+++ b/src/include/usr/mbox/mboxif.H
@@ -0,0 +1,41 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/usr/mbox/mboxif.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __MBOX_MBOXIF_H
+#define __MBOX_MBOXIF_H
+
+namespace MBOX
+{
+ static const uint32_t MBOX_MAX_DATA_BYTES = 64; //16 32-bit Data Registers
+
+ enum MboxReadStatus {
+ MBOX_ABORT_LAST_MSG = 0x00000040, /* Cancel Timed Out Operation */
+ MBOX_DOORBELL_ERROR = 0x00000010, /* Error Set In Error Register */
+ MBOX_XDN_ACK = 0x00000004, /* LBUS Data Acknowledgment */
+ MBOX_DATA_PENDING = 0x00000001, /* PIB Data Pending */
+ MBOX_ILLEGAL_OP = 0x08000000, /* Illegal Operation Attempted */
+ MBOX_DATA_WRITE_ERR = 0x04000000, /* Write Full LBUS Mailbox Error */
+ MBOX_DATA_READ_ERR = 0x02000000, /* Read Empty LBUS Mailbox Error */
+ MBOX_PARITY_ERR = 0x01000000, /* LBUS RAM Parity Error Detected */
+ };
+};
+#endif
diff --git a/src/makefile b/src/makefile
index 0f97b6b8e..f6738efad 100644
--- a/src/makefile
+++ b/src/makefile
@@ -49,7 +49,7 @@ DIRECT_BOOT_OBJECTS = start.o kernel.o taskmgr.o cpumgr.o syscall.o \
RUNTIME_OBJECTS =
BASE_MODULES = trace errl devicefw scom xscom initservice taskargs \
- pnor vfs
+ pnor vfs mbox
EXTENDED_MODULES = targeting ecmddatabuffer fapi hwp plat \
extinitsvc istepdisp hwas fsi fsiscom i2c intr \
@@ -63,7 +63,7 @@ TESTCASE_MODULES = cxxtest testerrl testdevicefw testsyslib \
testscom testxscom testtargeting testinitservice testkernel \
testhwpf testecmddatabuffer initsvctasktest2 testcxxtest \
testpnor testi2c testfsi testvfs testhwas testintr testspd \
- testpore testutil
+ testpore testutil testmbox
RELOCATABLE_IMAGE_LDFLAGS = -pie --export-dynamic
diff --git a/src/usr/makefile b/src/usr/makefile
index 579a2159a..4737ffd6e 100644
--- a/src/usr/makefile
+++ b/src/usr/makefile
@@ -27,6 +27,6 @@ OBJS = module_init.o
SUBDIRS = example.d trace.d cxxtest.d testcore.d errl.d devicefw.d \
scom.d xscom.d targeting.d initservice.d hwpf.d \
ecmddatabuffer.d pnor.d i2c.d vfs.d fsi.d hwas.d fsiscom.d \
- intr.d spd.d pore.d util.d
+ intr.d spd.d pore.d util.d mbox.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/mbox/makefile b/src/usr/mbox/makefile
new file mode 100644
index 000000000..816d6dd37
--- /dev/null
+++ b/src/usr/mbox/makefile
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/mbox/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2012
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+ROOTPATH = ../../..
+MODULE = mbox
+
+OBJS = mboxdd.o
+
+SUBDIRS = test.d
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/mbox/mboxdd.C b/src/usr/mbox/mboxdd.C
new file mode 100644
index 000000000..441925fd1
--- /dev/null
+++ b/src/usr/mbox/mboxdd.C
@@ -0,0 +1,541 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mbox/mboxdd.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#include "mboxdd.H"
+#include <mbox/mboxif.H>
+#include <mbox/mbox_reasoncodes.H>
+#include <devicefw/driverif.H>
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <targeting/targetservice.H>
+
+trace_desc_t* g_trac_mbox = NULL;
+TRAC_INIT(&g_trac_mbox, "MBOX", 4096); //4K
+
+//TODO - May or may not be necessary for MBOX error logs
+uint64_t target_to_uint64(const TARGETING::Target* i_target)
+{
+ uint64_t id = 0;
+ if( i_target == NULL )
+ {
+ id = 0x0;
+ }
+ else if( i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL )
+ {
+ id = 0xFFFFFFFFFFFFFFFF;
+ }
+ else
+ {
+ // physical path, 3 nibbles per type/instance pair
+ // TIITIITII... etc.
+ TARGETING::EntityPath epath;
+ i_target->tryGetAttr<TARGETING::ATTR_PHYS_PATH>(epath);
+ for( uint32_t x = 0; x < epath.size(); x++ )
+ {
+ id = id << 12;
+ id |= (uint64_t)((epath[x].type << 8) & 0xF00);
+ id |= (uint64_t)(epath[x].instance & 0x0FF);
+ }
+ }
+ return id;
+}
+
+namespace MBOX
+{
+
+/**
+ * @brief Performs an MBOX Read Operation
+ * This function performs a MBOX 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 MBOX 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 (userif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ *
+ * @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* o_status = va_arg(i_args,uint64_t*);
+
+ do
+ {
+ l_err = Singleton<MboxDD>::instance().read(i_target,io_buffer,
+ io_buflen,o_status);
+ if (l_err)
+ {
+ break;
+ }
+ } while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Performs an MBOX Write Operation
+ * This function performs a MBOX 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 MBOX 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 (userif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ *
+ * @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;
+
+ do
+ {
+ l_err = Singleton<MboxDD>::instance().write(i_target,io_buffer,
+ io_buflen);
+ if(l_err)
+ {
+ break;
+ }
+ } while(0);
+
+ return l_err;
+}
+
+// Register MBOXDD access functions to DD framework
+DEVICE_REGISTER_ROUTE(DeviceFW::READ,
+ DeviceFW::MAILBOX,
+ TARGETING::TYPE_PROC,
+ ddRead);
+
+DEVICE_REGISTER_ROUTE(DeviceFW::WRITE,
+ DeviceFW::MAILBOX,
+ TARGETING::TYPE_PROC,
+ ddWrite);
+
+}; //end MBOX namespace
+
+/**
+ * @brief Performs a mailbox read operation
+ */
+errlHndl_t MboxDD::read(TARGETING::Target* i_target,void *o_buffer,
+ size_t &io_buflen,uint64_t* o_status)
+{
+ uint64_t l_stat = 0;
+ errlHndl_t l_err = NULL;
+ uint32_t l_64bitBuf[2] = {0};
+ uint32_t l_IntReg[2] = {0};
+ size_t l_64bitSize = sizeof(uint64_t);
+
+ do
+ {
+ if (MBOX::MBOX_MAX_DATA_BYTES < io_buflen)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::read> Invalid data length : io_buflen=%d", io_buflen);
+ /*@
+ * @errortype
+ * @moduleid MBOX::MOD_MBOXDD_READ
+ * @reasoncode MBOX::RC_INVALID_LENGTH
+ * @userdata1 Target ID String...
+ * @userdata2 Data Length
+ * @devdesc MboxDD::read> Invalid data length (< msg_t size)
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MBOX::MOD_MBOXDD_READ,
+ MBOX::RC_INVALID_LENGTH,
+ target_to_uint64(i_target),
+ TO_UINT64(io_buflen));
+ l_err->collectTrace("MBOX",1024);
+ break;
+ }
+
+ l_err = deviceOp(DeviceFW::READ,i_target,
+ l_IntReg,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DB_INT_REG_PIB));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::read> Unable to read PIB Interrupt Register");
+ break;
+ }
+ if ((l_IntReg[0] & MBOX::MBOX_DOORBELL_ERROR) ==
+ MBOX::MBOX_DOORBELL_ERROR)
+ {
+ TRACFCOMP(g_trac_mbox, INFO_MRK "MBOX::read> Found interrupt on error status register");
+ l_err = getErrStat(i_target,l_stat);
+ if (l_err)
+ {
+ break;
+ }
+ }
+
+ l_err = deviceOp(DeviceFW::READ,i_target,
+ l_64bitBuf,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::read> Unable to read Doorbell Status/Control Register");
+ break;
+ }
+ /*
+ * DB_STATUS_1A_REG: doorbell status and control 1a
+ * Bit31(MSB) : Permission to Send Doorbell 1
+ * Bit30 : Abort Doorbell 1
+ * Bit29 : PIB Slave B Pending Doorbell 1
+ * Bit28 : LBUS Slave A Pending Doorbell 1
+ * Bit27 : Reserved
+ * Bit26 : Xdn Doorbell 1
+ * Bit25 : Xup Doorbell 1
+ * Bit24 : Reserved
+ * Bit23-20 : Header Count LBUS Slave A Doorbell 1
+ * Bit19-12 : Data Count LBUS Slave A Doorbell 1
+ * Bit11-8 : Header Count PIB Slave B Doorbell 1
+ * Bit7-0 : Data Count PIB Slave B Doorbell 1
+ */
+ //Check for Abort
+ if ((l_IntReg[0] & MBOX::MBOX_ABORT_LAST_MSG) ==
+ MBOX::MBOX_ABORT_LAST_MSG &&
+ (l_64bitBuf[0] & 0x40000000) == 0x40000000)
+ {
+ l_stat |= MBOX::MBOX_ABORT_LAST_MSG;
+ }
+ //Check for Xdn
+ if ((l_IntReg[0] & MBOX::MBOX_XDN_ACK) ==
+ MBOX::MBOX_XDN_ACK &&
+ (l_64bitBuf[0] & 0x04000000) == 0x04000000)
+ {
+ l_stat |= MBOX::MBOX_XDN_ACK;
+ }
+ //Check for PIB Pending
+ if ((l_IntReg[0] & MBOX::MBOX_DATA_PENDING) ==
+ MBOX::MBOX_DATA_PENDING &&
+ (l_64bitBuf[0] & 0x20000000) == 0x20000000)
+ {
+ l_stat |= MBOX::MBOX_DATA_PENDING;
+ //Read how many bytes are significant
+ if (io_buflen < ((l_64bitBuf[0] & 0x000FF000) >> 12))
+ {
+ TRACFCOMP(g_trac_mbox, INFO_MRK "MBOX::read> Data truncated, input buffer length less than number of significant bytes");
+ }
+ uint32_t i = 0;
+ uint32_t l_data[2];
+ uint8_t l_numRegs = (io_buflen*sizeof(uint8_t))/sizeof(uint32_t);
+ if ((io_buflen*sizeof(uint8_t))%sizeof(uint32_t) != 0) l_numRegs++;
+ uint8_t *l_buf = static_cast<uint8_t *>(o_buffer);
+ //Extract Data
+ while (i < l_numRegs)
+ {
+ l_err = deviceOp(DeviceFW::READ,i_target,
+ l_data,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DATA_LBUS_START+i));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::read> Unable to read Data Area Register 0x%X",MBOX_DATA_LBUS_START+i);
+ break;
+ }
+ //TODO Use memcpy() since byte aligned?
+ for (uint8_t byteNum = 0;byteNum<sizeof(uint32_t);++byteNum)
+ {
+ *(l_buf+(byteNum+i*sizeof(uint32_t))) =
+ (l_data[0]>>(sizeof(uint32_t)*8-(byteNum+1)*8) & 0x000000FF);
+ }
+ i++;
+ }
+ if (l_err)
+ {
+ break;
+ }
+
+ //Write-to-Clear PIB Pending,Xup,and bits 23-12
+ l_64bitBuf[0] = 0x22FFF000;
+ l_err = deviceOp(DeviceFW::WRITE,i_target,
+ l_64bitBuf,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::read> Unable to clear Doorbell Status/Control Register");
+ break;
+ }
+ }
+
+ //Write-to-Clear 'on' bits of interrupt reg
+ l_err = deviceOp(DeviceFW::WRITE,i_target,
+ l_IntReg,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DB_INT_REG_PIB));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::read> Unable to clear PIB Interrupt Register");
+ break;
+ }
+ (*o_status) = l_stat;
+
+ } while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Performs a mailbox write operation
+ */
+errlHndl_t MboxDD::write(TARGETING::Target* i_target,void* i_buffer,
+ size_t& i_buflen)
+{
+ errlHndl_t l_err = NULL;
+ uint32_t l_64bitBuf[2] = {0};
+ size_t l_64bitSize = sizeof(uint64_t);
+
+ do
+ {
+ //Expect size in bytes
+ if (i_buflen > MBOX::MBOX_MAX_DATA_BYTES)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::write> Invalid data length : i_buflen=%d", i_buflen);
+ /*@
+ * @errortype
+ * @moduleid MBOX::MOD_MBOXDD_WRITE
+ * @reasoncode MBOX::RC_INVALID_LENGTH
+ * @userdata1 Target ID String...
+ * @userdata2 Data Length
+ * @devdesc MboxDD::write> Invalid data length (> msg_t size)
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MBOX::MOD_MBOXDD_WRITE,
+ MBOX::RC_INVALID_LENGTH,
+ target_to_uint64(i_target),
+ TO_UINT64(i_buflen));
+ l_err->collectTrace("MBOX",1024);
+ break;
+ }
+
+ l_err = deviceOp(DeviceFW::READ,i_target,
+ l_64bitBuf,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::write> Unable to read Doorbell Status/Control Register");
+ break;
+ }
+
+ /*
+ * DB_STATUS_1A_REG: doorbell status and control 1a
+ * Bit31(MSB) : Permission to Send Doorbell 1
+ * Bit30 : Abort Doorbell 1
+ * Bit29 : PIB Slave B Pending Doorbell 1
+ * Bit28 : LBUS Slave A Pending Doorbell 1
+ * Bit27 : Reserved
+ * Bit26 : Xdn Doorbell 1
+ * Bit25 : Xup Doorbell 1
+ * Bit24 : Reserved
+ * Bit23-20 : Header Count LBUS Slave A Doorbell 1
+ * Bit19-12 : Data Count LBUS Slave A Doorbell 1
+ * Bit11-8 : Header Count PIB Slave B Doorbell 1
+ * Bit7-0 : Data Count PIB Slave B Doorbell 1
+ */
+ //Verify Permission-to-Send
+ if ((l_64bitBuf[0] & 0x80000000) == 0x80000000)
+ {
+ //Verify LBUS Pending,
+ if ((l_64bitBuf[0] & 0x10000FFF) == 0)
+ {
+ uint32_t i = 0;
+ uint32_t l_data[2] = {0};
+ uint8_t l_numRegs = (i_buflen*sizeof(uint8_t))/sizeof(uint32_t);
+ if ((i_buflen*sizeof(uint8_t))%sizeof(uint32_t) != 0) l_numRegs++;
+ uint32_t *l_buf = static_cast<uint32_t *>(i_buffer);
+ //Write Data registers
+ while (i < l_numRegs)
+ {
+ l_data[0] = *(l_buf+i);
+ l_err = deviceOp(DeviceFW::WRITE,i_target,
+ l_data,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DATA_PIB_START+i));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::write> Unable to write Data Area Register 0x%X",MBOX_DATA_PIB_START+i);
+ break;
+ }
+ i++;
+ }
+ if (l_err)
+ {
+ break;
+ }
+
+ //Write LBUS Pending(28) and Data Count bits(11-0)
+ l_64bitBuf[0] = 0x10000000 | i_buflen;
+ l_err = deviceOp(DeviceFW::WRITE,i_target,
+ l_64bitBuf,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::write> Unable to set Doorbell Status/Control Register");
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::write> Message still pending : MBOX_DB_STAT_CNTRL_1=%X", l_64bitBuf[0]);
+ /*@
+ * @errortype
+ * @moduleid MBOX::MOD_MBOXDD_WRITE
+ * @reasoncode MBOX::RC_MSG_PENDING
+ * @userdata1 Target ID String...
+ * @userdata2 Status/Control Register
+ * @devdesc MboxDD::write> Message still pending
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MBOX::MOD_MBOXDD_WRITE,
+ MBOX::RC_MSG_PENDING,
+ target_to_uint64(i_target),
+ reinterpret_cast<uint64_t>(l_64bitBuf));
+ l_err->collectTrace("MBOX",1024);
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::write> Permission-to-Send bit not set : MBOX_DB_STAT_CNTRL_1=%X", l_64bitBuf[0]);
+ /*@
+ * @errortype
+ * @moduleid MBOX::MOD_MBOXDD_WRITE
+ * @reasoncode MBOX::RC_NO_PERM_TO_SEND
+ * @userdata1 Target ID String...
+ * @userdata2 Status/Control Register
+ * @devdesc MboxDD::write> Permission-to-Send not set
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MBOX::MOD_MBOXDD_WRITE,
+ MBOX::RC_NO_PERM_TO_SEND,
+ target_to_uint64(i_target),
+ reinterpret_cast<uint64_t>(l_64bitBuf));
+ l_err->collectTrace("MBOX",1024);
+ break;
+ }
+
+ } while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Reads the mailbox PIB error status register
+ */
+errlHndl_t MboxDD::getErrStat(TARGETING::Target* i_target,uint64_t &o_status)
+{
+ errlHndl_t l_err = NULL;
+ uint32_t l_64bitBuf[2] = {0};
+ size_t l_64bitSize = sizeof(uint64_t);
+
+ do
+ {
+ l_err = deviceOp(DeviceFW::READ,i_target,
+ l_64bitBuf,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DB_ERR_STAT_PIB));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::getErrStat> Unable to read PIB Error Status");
+ break;
+ }
+ else
+ {
+ //Check for Illegal Op
+ if ((l_64bitBuf[0] & MBOX::MBOX_ILLEGAL_OP) ==
+ MBOX::MBOX_ILLEGAL_OP)
+ {
+ o_status |= MBOX::MBOX_ILLEGAL_OP;
+ }
+ //Check for Write Full
+ if ((l_64bitBuf[0] & MBOX::MBOX_DATA_WRITE_ERR) ==
+ MBOX::MBOX_DATA_WRITE_ERR)
+ {
+ o_status |= MBOX::MBOX_DATA_WRITE_ERR;
+ }
+ //Check for Read Empty
+ if ((l_64bitBuf[0] & MBOX::MBOX_DATA_READ_ERR) ==
+ MBOX::MBOX_DATA_READ_ERR)
+ {
+ o_status |= MBOX::MBOX_DATA_READ_ERR;
+ }
+ //Check for Parity Error & add address of parity error
+ if ((l_64bitBuf[0] & MBOX::MBOX_PARITY_ERR) ==
+ MBOX::MBOX_PARITY_ERR)
+ {
+ o_status |= MBOX::MBOX_PARITY_ERR;
+ uint64_t l_temp = (l_64bitBuf[0] & 0x00FF0000);
+ o_status |= (l_temp << 40);
+ }
+ }
+ //Write '1' to Clear Status(16)
+ l_64bitBuf[0] = 0x00010000;
+ l_err = deviceOp(DeviceFW::WRITE,i_target,
+ l_64bitBuf,l_64bitSize,
+ DEVICE_XSCOM_ADDRESS(MBOX_DB_ERR_STAT_PIB));
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MBOX::getErrStat> Unable to clear PIB Error Status");
+ break;
+ }
+
+ } while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Constructor
+ */
+MboxDD::MboxDD()
+{
+ TRACFCOMP(g_trac_mbox, "MboxDD::MboxDD()> ");
+}
+
+/**
+ * @brief Destructor
+ */
+MboxDD::~MboxDD()
+{
+}
diff --git a/src/usr/mbox/mboxdd.H b/src/usr/mbox/mboxdd.H
new file mode 100644
index 000000000..46df5db30
--- /dev/null
+++ b/src/usr/mbox/mboxdd.H
@@ -0,0 +1,121 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mbox/mboxdd.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __MBOX_MBOXDD_H
+#define __MBOX_MBOXDD_H
+
+#include <errl/errlentry.H>
+#include <usr/devicefw/driverif.H>
+
+/** @file mboxdd.H
+ * @brief Provides the interfaces to the MBOX Device Driver
+ */
+class MboxDD
+{
+
+ public:
+
+ /**
+ * @brief Performs a mailbox read operation
+ *
+ * @param[in] i_target - Chip target of MBOX operation
+ * @param[out] o_buffer - Destination buffer for data
+ * @param[in/out] io_buflen - Size of buffer
+ * @param[out] o_status - Contains any error status bits
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t read(TARGETING::Target* i_target,
+ void* o_buffer,
+ size_t& io_buflen,
+ uint64_t* o_status);
+
+ /**
+ * @brief Performs a mailbox write operation
+ *
+ * @param[in] i_target - Chip target of MBOX operation
+ * @param[in] i_buffer - Location of data to be written
+ * @param[in] i_buflen - Size of data
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t write(TARGETING::Target* i_target,
+ void* i_buffer,
+ size_t& i_buflen);
+
+ /**
+ * @brief Reads the mailbox PIB error status register
+ *
+ * @param[in] i_target - Chip target of MBOX operation
+ * @param[out] o_status - Bits set to errors found
+ */
+ errlHndl_t getErrStat(TARGETING::Target* i_target,
+ uint64_t &o_status);
+
+ protected:
+
+ /**
+ * @brief Constructor
+ */
+ MboxDD();
+
+ /**
+ * @brief Destructor
+ */
+ ~MboxDD();
+
+ private:
+
+ //Mailbox 1 Status & Interrupt register addresses
+ enum MboxRegs {
+ MBOX_DB_STAT_CNTRL_1 = 0x00050024, //LBUS(rw),PIB(rw) Stat/Cntrl 1
+ MBOX_DB_ERR_STAT_PIB = 0x00050030, //LBUS(ro),PIB(rw) Err Stat B
+ MBOX_DB_ERR_STAT_LBUS = 0x00050031, //LBUS(rw),PIB(ro) Err Stat A
+ MBOX_DB_INT_REG_LBUS = 0x00050032, //LBUS(rw),PIB(ro) Int Reg A
+ MBOX_DB_INT_MASK_LBUS_RS = 0x00050033, //LBUS(r/set),PIB(ro) Int Mask A
+ MBOX_DB_INT_MASK_LBUS_RC = 0x00050034, //LBUS(r/clear),PIB(ro/zero)
+ MBOX_DB_INT_REG_PIB = 0x00050035, //LBUS(ro),PIB(rw) Int Reg B
+ MBOX_DB_INT_MASK_PIB_RS = 0x00050036, //LBUS(ro),PIB(r/set) Int Mask B
+ MBOX_DB_INT_MASK_PIB_RC = 0x00050037, //LBUS(ro/zero,PIB(r/clear)
+ };
+
+ //Mailbox 1 Header/Command register addresses
+ enum MboxHeadCmdRegs {
+ MBOX_HEAD_CMD_LBUS0 = 0x00050021, //LBUS(rw),PIB(ro) H/C 0A
+ MBOX_HEAD_CMD_LBUS1 = 0x00050022, //LBUS(rw),PIB(ro) H/C 1A
+ MBOX_HEAD_CMD_LBUS2 = 0x00050023, //LBUS(rw),PIB(ro) H/C 2A
+ MBOX_HEAD_CMD_PIB0 = 0x00050025, //LBUS(ro),PIB(rw) H/C 0B
+ MBOX_HEAD_CMD_PIB1 = 0x00050026, //LBUS(ro),PIB(rw) H/C 1B
+ MBOX_HEAD_CMD_PIB2 = 0x00050027, //LBUS(ro),PIB(rw) H/C 2B
+ };
+
+ //Mailbox 1 Data register address boundaries
+ enum MboxDataRegs {
+ MBOX_DATA_LBUS_START = 0x00050040, //LBUS(rw),PIB(ro) First address
+ MBOX_DATA_LBUS_END = 0x0005004F, //LBUS(rw),PIB(ro) Last address
+ MBOX_DATA_PIB_START = 0x00050080, //LBUS(ro),PIB(rw) First address
+ MBOX_DATA_PIB_END = 0x0005008F, //LBUS(ro),PIB(rw) Last address
+ };
+
+};
+
+#endif
diff --git a/src/usr/mbox/test/makefile b/src/usr/mbox/test/makefile
new file mode 100644
index 000000000..1c9c09f95
--- /dev/null
+++ b/src/usr/mbox/test/makefile
@@ -0,0 +1,28 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/mbox/test/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2012
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+ROOTPATH = ../../../..
+
+MODULE = testmbox
+TESTS = *.H
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/mbox/test/mboxddtest.H b/src/usr/mbox/test/mboxddtest.H
new file mode 100644
index 000000000..a1920d891
--- /dev/null
+++ b/src/usr/mbox/test/mboxddtest.H
@@ -0,0 +1,123 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mbox/test/mboxddtest.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __MBOXDDTEST_H
+#define __MBOXDDTEST_H
+
+/**
+ * @file mboxddtest.H
+ *
+ * @brief Test cases for MBOX Device Driver
+*/
+
+#include <cxxtest/TestSuite.H>
+#include <errl/errlentry.H>
+#include <errl/hberrltypes.H>
+#include <limits.h>
+#include <devicefw/driverif.H>
+#include <mbox/mboxif.H>
+
+extern trace_desc_t* g_trac_mbox;
+
+using namespace TARGETING;
+
+class MboxDDTest : public CxxTest::TestSuite
+{
+ public:
+
+ /**
+ * @brief MBOX DD test - Write (STUB)
+ * Perform basic write operation
+ */
+ void testWrite(void)
+ {
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWrite(STUB)> Begin");
+ /*
+ * This test function should be updated to perform TWO write
+ * operations. Without the SIMICS data loopback update, this
+ * should cause errors to occur due to no ack back from FSP.
+ *
+ * Currently, without proper SIMICS support, this test function
+ * will be stubbed out to allow checkin of this file.
+ */
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWrite(STUB)> End");
+ }
+
+ /**
+ * @brief MBOX DD test - Write/Read
+ * Perform basic write then read operation
+ * Requires SIMICS data loopback from SP-to-Host (PIB-to-LBUS)
+ */
+ void _testWriteRead(void)
+ {
+ uint64_t o_status = 0;
+ errlHndl_t l_err = NULL;
+ uint32_t in_mboxMsg [] = {0x12345678, 0x14785236, 0x96325874,
+ 0x98765432, 0x78910112, 0x66660000};
+ size_t in_size = sizeof(in_mboxMsg);
+ uint32_t out_mboxMsg[16] = {0};
+ size_t out_size = sizeof(out_mboxMsg);
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWriteRead> Begin");
+
+ TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
+ epath.addLast(TARGETING::TYPE_SYS,0);
+ epath.addLast(TARGETING::TYPE_NODE,0);
+ epath.addLast(TARGETING::TYPE_PROC,0);
+
+ l_err = DeviceFW::deviceWrite(
+ TARGETING::targetService().toTarget(epath),
+ static_cast<void*>(in_mboxMsg),in_size,
+ DEVICE_MBOX_ADDRESS(&o_status));
+ if (l_err)
+ {
+ TS_FAIL("Unable to write to mailbox device.\n");
+ }
+
+ l_err = DeviceFW::deviceRead(
+ TARGETING::targetService().toTarget(epath),
+ static_cast<void*>(out_mboxMsg),out_size,
+ DEVICE_MBOX_ADDRESS(&o_status));
+ if (l_err)
+ {
+ TS_FAIL("Unable to read mailbox device.\n");
+ }
+ if (o_status != 0x00000005)//Xdn & PIB Pending
+ {
+ TS_FAIL("PIB interrupt register shows unexpected interrupt.\n");
+ }
+
+ for (uint32_t i=0; i<sizeof(in_mboxMsg)/sizeof(uint32_t); ++i)
+ {
+ if (out_mboxMsg[i] != in_mboxMsg[i])
+ {
+ TS_FAIL("Loopback data area mismatch.\n");
+ break;
+ }
+ }
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWriteRead> End");
+ };
+
+};
+
+#endif
OpenPOWER on IntegriCloud