summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDoug Gilbert <dgilbert@us.ibm.com>2012-03-22 14:34:06 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-04-05 15:20:19 -0500
commit3b9b970812926d1cbc063174dd7f097b4fcb3793 (patch)
tree3b191befecbef21c540540f8c2fde42d68fb9e54 /src
parentd26e75088c24cdf95e02575b0d172068cdb1a58b (diff)
downloadtalos-hostboot-3b9b970812926d1cbc063174dd7f097b4fcb3793.tar.gz
talos-hostboot-3b9b970812926d1cbc063174dd7f097b4fcb3793.zip
Mailbox service provider
RTC: 35323 Change-Id: Ifd626870fcc31f94a684f8a19fdc7816e092a7fa Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/798 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rwxr-xr-xsrc/build/citest/etc/workarounds.postsimsetup4
-rwxr-xr-xsrc/build/citest/etc/workarounds.presimsetup2
-rwxr-xr-xsrc/build/simics/post_model_hook.simics7
-rw-r--r--src/include/usr/mbox/mbox_queues.H92
-rw-r--r--src/include/usr/mbox/mbox_reasoncodes.H13
-rw-r--r--src/include/usr/mbox/mboxif.H64
-rw-r--r--src/sys/vfs/vfs_main.C1
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvctasks.H3
-rw-r--r--src/usr/mbox/mailboxsp.C856
-rw-r--r--src/usr/mbox/mailboxsp.H222
-rw-r--r--src/usr/mbox/makefile2
-rw-r--r--src/usr/mbox/mboxdd.C65
-rw-r--r--src/usr/mbox/mboxdd.H43
-rw-r--r--src/usr/mbox/test/mboxddtest.H583
-rw-r--r--src/usr/mbox/test/mboxsptest.H165
15 files changed, 2022 insertions, 100 deletions
diff --git a/src/build/citest/etc/workarounds.postsimsetup b/src/build/citest/etc/workarounds.postsimsetup
index 8e14b6f12..629ad7392 100755
--- a/src/build/citest/etc/workarounds.postsimsetup
+++ b/src/build/citest/etc/workarounds.postsimsetup
@@ -27,7 +27,7 @@
## to setup the sandbox
##
-
echo "+++ FIXME Temporarily copying cec-chip.so to eliminate verbose errors"
rm $sb/../simics/amd64-linux/lib/cec-chip.so
-cp /afs/rch/usr8/dsanner/public/fsi2host.correct/bin/cec-chip.so $sb/../simics/amd64-linux/lib/
+cp /afs/rch/usr8/dsanner/public/quiet.cecchip/cec-chip.so $sb/../simics/amd64-linux/lib/
+
diff --git a/src/build/citest/etc/workarounds.presimsetup b/src/build/citest/etc/workarounds.presimsetup
index ff56666d8..eb9455f21 100755
--- a/src/build/citest/etc/workarounds.presimsetup
+++ b/src/build/citest/etc/workarounds.presimsetup
@@ -65,5 +65,7 @@ echo "+++ Update to new phyp and mambo level."
mkdir -p $sb/simu/data
cp --update $BACKING_BUILD/src/simu/data/simicsInfo $sb/simu/data/simicsInfo
#sed -i -e's/^WSALIAS HOSTBOOT_LEVEL MAMBOLEVEL.*/WSALIAS HOSTBOOT_LEVEL MAMBOLEVEL env\/mamboa\/2011_11_10__4.2/' $sb/simu/data/simicsInfo
+# RTC task 39991 - update bbuild and remove this when it gets into a build
+sed -i -e's/^WSALIAS DEFAULT FIPSLEVEL.*/WSALIAS DEFAULT FIPSLEVEL env\/gfwb\/simics-4.2.0\/simics-4.2.85\/fips\/fld36\/fi120327b700.42/' $sb/simu/data/simicsInfo
sed -i -e's/^WSALIAS DEFAULT PHYPLEVEL.*/WSALIAS DEFAULT PHYPLEVEL env\/phypa\/simics-4.2.0\/simics-4.2.85\/ph120319a700.42/' $sb/simu/data/simicsInfo
sed -i -e's/^WSALIAS DEFAULT PHYP_PATCH_LEVEL.*/WSALIAS DEFAULT PHYP_PATCH_LEVEL env\/phypa\/simics-4.2.0\/simics-4.2.85\/patches\/ph120319a700.42/' $sb/simu/data/simicsInfo
diff --git a/src/build/simics/post_model_hook.simics b/src/build/simics/post_model_hook.simics
index d102862af..979cbeb17 100755
--- a/src/build/simics/post_model_hook.simics
+++ b/src/build/simics/post_model_hook.simics
@@ -36,3 +36,10 @@ run-python-file hb-simdebug.py
#Load PNOR image into phys_mem
phys_mem.load-file ../img/simics.pnor 0x400000
+
+#Setup the mailbox
+venice_cec_chip_cmp0.psi_hb->psihb_psihbcr=0x5f00000000000000
+venice_cec_chip_cmp0.psi_hb->psihb_xivr_fsi=0x0140000000 #02010917
+venice_cec_chip_cmp0.psi_hb->psihb_irsn=0x00030000FFFF0000 #0201091b
+p8Proc0.proc_fsi2host_mbox->responder_enable=1
+
diff --git a/src/include/usr/mbox/mbox_queues.H b/src/include/usr/mbox/mbox_queues.H
new file mode 100644
index 000000000..1e19b62eb
--- /dev/null
+++ b/src/include/usr/mbox/mbox_queues.H
@@ -0,0 +1,92 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/include/usr/mbox/mbox_queues.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_QUEUES_H
+#define __MBOX_QUEUES_H
+
+/**
+ * @file mbox_queues.H
+ * @brief Mailbox queue identifiers. This file is shared between
+ * Hostboot and FSP.
+ */
+
+namespace MBOX
+{
+ /**
+ * message queue IDs
+ * FSP msg_queue range 0x80000000 - 0xFFFFFFFF
+ * Hostboot msg_queue range 0x00000001 - 0x7FFFFFFF
+ */
+ enum queue_id_t
+ {
+ NOT_FOUND = 0,
+ HB_MAILBOX_MSGQ,
+ HB_ISTEP_MSGQ,
+ // Add HB services here:
+
+ HB_TEST_MSGQ = 0x7FFFFFFF,
+
+ // FSP mailboxes
+ FSP_FIRST_MSGQ = 0x80000000,
+ FSP_MAILBOX_MSGQ = FSP_FIRST_MSGQ,
+ FSP_ECHO_MSGQ,
+ FSP_PROGRESS_CODES_MSGQ,
+ FSP_TRACE_MSGQ,
+ FSP_ERRL_MSGQ,
+ // Add FSP services here:
+ };
+
+ // Message types are only unique with in each message queue. Each message queue can
+ // use the entire range limited only by the restrictions listed below.
+ //
+ // Each HB and FSP service will need it's own list of message types
+ // Not sure where they belong.
+ //
+ // types 0x00000000 - 0x3FFFFFFF are considered secure messages
+ // and are disabled when under SecureBoot environment
+ // types 0x40000000 - 0x7FFFFFFF can be done at anytime
+ // types 0x80000000 - 0xFFFFFFFF are reserved on hostboot for kernel services
+ // This means hostboot services can't use them, but this is not a restriction
+ // on FSP services
+ enum
+ {
+ FIRST_SECURE_MSG = 0,
+ LAST_SECURE_MSG = 0x3FFFFFFF,
+ FIRST_UNSECURE_MSG = 0x40000000,
+ LAST_UNSECURE_MSG = 0x7FFFFFFF,
+ FIRST_HB_KERNEL_MSG = 0x80000000,
+ LAST_KERNEL_MSG = 0xFFFFFFFF
+ };
+
+ /**
+ * MBOX to MBOX service message types.
+ */
+ enum msg_type_t
+ {
+ MSG_REQUEST_DMA_BUFFERS = FIRST_UNSECURE_MSG,
+ };
+
+
+};
+
+#endif
+
diff --git a/src/include/usr/mbox/mbox_reasoncodes.H b/src/include/usr/mbox/mbox_reasoncodes.H
index 0ee58ff58..f90870a8d 100644
--- a/src/include/usr/mbox/mbox_reasoncodes.H
+++ b/src/include/usr/mbox/mbox_reasoncodes.H
@@ -32,6 +32,10 @@ namespace MBOX
MOD_MBOXDD_INVALID = 0x00, /**< Zero is an invalid module id */
MOD_MBOXDD_READ = 0x01,
MOD_MBOXDD_WRITE = 0x02,
+ MOD_MBOXSRV_SEND = 0x03, // MailboxSp::send
+ MOD_MBOXSRV_HNDLR = 0x04, // MailboxSp::msgHandler
+ MOD_MBOXSRV_RCV = 0x05, // MailboxSp::recv_msg
+ MOD_MBOXREGISTER = 0x06, // MailboxSp::msgq_register
};
enum MBOXReasonCode
@@ -40,6 +44,15 @@ namespace MBOX
RC_INVALID_MESSAGE_TYPE = HBMBOX_COMP_ID | 0x02,
RC_NO_PERM_TO_SEND = HBMBOX_COMP_ID | 0x03,
RC_MSG_PENDING = HBMBOX_COMP_ID | 0x04,
+ RC_INVALID_QUEUE = HBMBOX_COMP_ID | 0x05,
+ RC_RETRY_FAILED = HBMBOX_COMP_ID | 0x06,
+ RC_ALREADY_REGISTERED = HBMBOX_COMP_ID | 0x07,
+ RC_UNREGISTERED_MSG_QUEUE = HBMBOX_COMP_ID | 0x08,
+ RC_ILLEGAL_OP = HBMBOX_COMP_ID | 0x09,
+ RC_DATA_WRITE_ERR = HBMBOX_COMP_ID | 0x0A,
+ RC_PARITY_ERR = HBMBOX_COMP_ID | 0x0B,
+ RC_INVALID_MBOX_MSG_TYPE = HBMBOX_COMP_ID | 0x0C,
+ RC_MBOX_SERVICE_NOT_READY = HBMBOX_COMP_ID | 0x0D,
};
};
diff --git a/src/include/usr/mbox/mboxif.H b/src/include/usr/mbox/mboxif.H
index cb6b23ffe..fc321f757 100644
--- a/src/include/usr/mbox/mboxif.H
+++ b/src/include/usr/mbox/mboxif.H
@@ -23,8 +23,68 @@
#ifndef __MBOX_MBOXIF_H
#define __MBOX_MBOXIF_H
+#include <sys/msg.h>
+#include <errl/errlentry.H>
+#include <mbox/mbox_queues.H>
+
namespace MBOX
{
- // TODO add mailbox service interfaces
-};
+ /**
+ * Register a message queue to receive mailbox messages
+ * @param[in] i_queueu_id, The queue identifier
+ * @param[in] i_msgQ, The message queue created with msg_q_create()
+ * @see sys/msg.h
+ * @return errlHndl_t on error
+ */
+ errlHndl_t msgq_register(queue_id_t i_queue_id, msg_q_t i_msgQ);
+
+ /**
+ * Un register a message queue from the mailbox service
+ * @param[in] i_queue_id, The queue identifier
+ * @return The message queue | NULL if i_queue_id not registered.
+ */
+ msg_q_t msgq_unregister(queue_id_t i_queue_id);
+
+ /**
+ * Send message asynchronously
+ * @param[in] i_q_id id, of the FSP message queue to send the msg to.
+ * @param[in] i_msg. The message to send.
+ *
+ * @return errlHndl_t on error.
+ *
+ * @pre i_msg->extra_data == NULL If there is no extra data is associated
+ * with the message.
+ *
+ * @pre i_msg->extra_data = malloc(size); i_msg->data[1] = size;
+ * Any extra data associated with i_msg was obtained from the heap
+ * using malloc and i_msg->data[1] contains the length of that data.
+ *
+ * @post free(i_msg->extra_dat) was done (if no error)
+ * @post msg_free(i_msg) was done (if no error)
+ */
+ errlHndl_t send(queue_id_t i_q_id, msg_t * i_msg);
+
+ /**
+ * Send message synchronously
+ * @param[in] i_q_id id, of the FSP message queue to send the msg to.
+ * @param[in/out] io_msg. The message sent and returned.
+ *
+ * @return errlHndl_t on error
+ *
+ * @pre io_msg->extra_data == NULL If there is no extra data is associated
+ * with the message.
+ *
+ * @pre io_msg->extra_data = malloc(size); io_msg->data[1] = size;
+ * Any extra data associated with io_msg was obtained from the heap
+ * using malloc and io_msg->data[1] contains the length of that data.
+ *
+ * @post free(i_msg->extra_data) was done (if no error)
+ *
+ * @note: On return, if io_msg->extra_data != NULL, the caller must
+ * call free(io_msg->extra_data);
+ */
+ errlHndl_t sendrecv(queue_id_t i_q_id, msg_t * io_msg);
+
+}; // end namespace MBOX
+
#endif
diff --git a/src/sys/vfs/vfs_main.C b/src/sys/vfs/vfs_main.C
index 38f420720..bc03d3c87 100644
--- a/src/sys/vfs/vfs_main.C
+++ b/src/sys/vfs/vfs_main.C
@@ -36,6 +36,7 @@ const char* VFS_ROOT_BIN = "/bin/";
const char* VFS_ROOT_DATA = "/data/";
const char* VFS_ROOT_MSG = "/msg/";
const char* VFS_ROOT_MSG_VFS = "/msg/vfs";
+const char* VFS_ROOT_MSG_MBOX = "/msg/mbox";
void vfs_module_init();
diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H
index 00c46b220..6a5cf8afe 100644
--- a/src/usr/initservice/extinitsvc/extinitsvctasks.H
+++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H
@@ -84,7 +84,8 @@ const TaskInfo g_exttaskinfolist[] = {
"libmbox.so", // taskname
NULL, // no ptr to fnct
{
- INIT_TASK, // task type
+
+ START_TASK, // task type
EXT_IMAGE, // Extended Module
}
},
diff --git a/src/usr/mbox/mailboxsp.C b/src/usr/mbox/mailboxsp.C
new file mode 100644
index 000000000..10f0db347
--- /dev/null
+++ b/src/usr/mbox/mailboxsp.C
@@ -0,0 +1,856 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mailbox/mailboxsp.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
+/**
+ * @file mailboxsp.C
+ * @brief mailbox service provider definition
+ */
+
+#include "mailboxsp.H"
+#include "mboxdd.H"
+#include <sys/task.h>
+#include <initservice/taskargs.H>
+#include <sys/vfs.h>
+#include <devicefw/userif.H>
+#include <mbox/mbox_reasoncodes.H>
+
+using namespace MBOX;
+
+// Defined in mboxdd.C
+extern trace_desc_t * g_trac_mbox;
+
+/**
+ * setup _start and handle barrier
+ */
+TASK_ENTRY_MACRO( MailboxSp::init );
+
+
+MailboxSp::MailboxSp()
+ :
+ iv_msgQ(),
+ iv_sendq(),
+ iv_respondq(),
+ iv_trgt(NULL),
+ iv_rts(true),
+ iv_dma_pend(false)
+{
+ // mailbox target
+ TARGETING::targetService().masterProcChipTargetHandle(iv_trgt);
+}
+
+MailboxSp::~MailboxSp()
+{
+ msg_q_destroy(iv_msgQ);
+}
+
+void MailboxSp::init(errlHndl_t& o_errl)
+{
+ o_errl = Singleton<MailboxSp>::instance()._init();
+}
+
+// helper function to start mailbox message handler
+void MailboxSp::msg_handler(void * unused)
+{
+ Singleton<MailboxSp>::instance().msgHandler();
+}
+
+
+errlHndl_t MailboxSp::_init()
+{
+ errlHndl_t err = NULL;
+ size_t rc = 0;
+ iv_msgQ = msg_q_create();
+ rc = msg_q_register(iv_msgQ, VFS_ROOT_MSG_MBOX);
+
+ // Register to get interrupts for mailbox
+ err = INTR::registerMsgQ(iv_msgQ, INTR::FSP_MAILBOX);
+
+ if(!err)
+ {
+ err = MboxDD::init(iv_trgt);
+
+ task_create(MailboxSp::msg_handler, NULL);
+ }
+
+ return err;
+}
+
+
+void MailboxSp::msgHandler()
+{
+ errlHndl_t err = NULL;
+
+ while(1)
+ {
+ msg_t* msg = msg_wait(iv_msgQ);
+
+ // First look for responses to messages sent to HB msg queues
+ // Theses are responses to sync messages from FSP to HB.
+ msg_respond_t * response = iv_respondq.find(msg);
+ if(response)
+ {
+ iv_respondq.erase(response);
+
+ mbox_msg_t mbox_msg;
+ mbox_msg.msg_id = response->msg_id;
+ mbox_msg.msg_queue_id = response->msg_queue_id;
+ mbox_msg.msg_payload = *msg;
+
+ msg_free(msg);
+ delete response;
+
+ send_msg(&mbox_msg);
+
+ continue;
+ }
+
+ // Now look for other messages
+ switch(msg->type)
+ {
+ // Interrupt from the mailbox hardware
+ case MSG_INTR:
+ {
+ mbox_msg_t mbox_msg;
+ size_t mbox_msg_size = sizeof(mbox_msg_t);
+ uint64_t mbox_status = 0;
+
+ // Read message from DD
+ err = DeviceFW::deviceRead(iv_trgt,
+ static_cast<void*>(&mbox_msg),
+ mbox_msg_size,
+ DEVICE_MBOX_ADDRESS(&mbox_status)
+ );
+
+ TRACDCOMP(g_trac_mbox,"MBOXSP status=%lx",mbox_status);
+
+ if(!err && (mbox_status & MboxDD::MBOX_DOORBELL_ERROR))
+ {
+ TRACFCOMP(g_trac_mbox,
+ ERR_MRK"MBOX status 0x%lx",
+ mbox_status);
+
+ if(mbox_status & MboxDD::MBOX_DATA_WRITE_ERR)
+ {
+ // Write attempted before ACK - HB code error
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid MOD_MBOXSRV_HNDLR
+ * @reasoncode RC_DATA_WRITE_ERR
+ * @userdata1 Status from MB device driver
+ * @defdesc Mailbox Data Write attempted
+ * before ACK.
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ MBOX::MOD_MBOXSRV_HNDLR,
+ MBOX::RC_DATA_WRITE_ERR, // reason Code
+ mbox_status, // Status from DD
+ 0
+ );
+
+ err->collectTrace(HBMBOX_COMP_NAME);
+ }
+
+ else if(mbox_status & MboxDD::MBOX_PARITY_ERR)
+ {
+ // Hardware detected parity error - TODO How does BB handle this error ???
+ // Log it and continue
+
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_INFORMATIONAL
+ * @moduleid MOD_MBOXSRV_HNDLR
+ * @reasoncode RC_PARITY_ERR
+ * @userdata1 Status from MB device driver
+ * @defdesc Mailbox Hardware detected
+ * parity error.
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ MBOX::MOD_MBOXSRV_HNDLR,
+ MBOX::RC_PARITY_ERR, // reason Code
+ mbox_status, // Status from DD
+ 0
+ );
+
+ errlCommit(err,HBMBOX_COMP_ID);
+ err = NULL;
+ }
+ else if(mbox_status & MboxDD::MBOX_ILLEGAL_OP)
+ {
+ // Code problem could be FSP or HB - log error and continue.
+
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_INFORMATIONAL
+ * @moduleid MOD_MBOXSRV_HNDLR
+ * @reasoncode RC_ILLEGAL_OP
+ * @userdata1 Status from MB device driver
+ * @defdesc Retry failed. Bad status
+ * indicated in PIB status reg.
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ MBOX::MOD_MBOXSRV_HNDLR,
+ MBOX::RC_ILLEGAL_OP, // reason Code
+ mbox_status, // Status from DD
+ 0
+ );
+ errlCommit(err,HBMBOX_COMP_ID);
+ err = NULL;
+ }
+
+ //else if(mbox_status & MboxDD::MBOX_DATA_READ_ERR)
+ //{
+ // // Read when no message available - Just ignore this one!
+ //}
+
+
+ // The code has the ability to retry sending a message, but currently
+ // there is no error state that requires it.
+ }
+
+
+ if(!err && (mbox_status & MboxDD::MBOX_HW_ACK))
+ {
+ // send next message if there is one.
+ iv_rts = true;
+ send_msg();
+ }
+
+ if(!err && (mbox_status & MboxDD::MBOX_DATA_PENDING))
+ {
+ err = recv_msg(mbox_msg);
+ }
+
+
+ if(err)
+ {
+ // Probably dead in the water here.
+ // TODO Mask off MB interrupts??
+ // No where to send the error so submit it.
+ // need to still respond to INTR handler.
+ errlCommit(err,HBMBOX_COMP_ID);
+ err = NULL;
+ }
+
+
+ // Respond to the interrupt handler
+ msg->data[0] = 0;
+ msg->data[1] = 0;
+ msg_respond(iv_msgQ,msg);
+ }
+
+ break;
+
+
+ case MSG_SEND:
+ {
+ // Build mailbox message
+ mbox_msg_t mbox_msg;
+ mbox_msg.msg_queue_id = static_cast<uint32_t>(msg->data[0]);
+ msg_t * payload = reinterpret_cast<msg_t*>(msg->extra_data);
+ mbox_msg.msg_payload = *payload; //copy in payload
+
+ if(msg_is_async(msg))
+ {
+ msg_free(payload);
+ msg_free(msg);
+ }
+ else //synchronous
+ {
+ msg->data[1] = 0; // used later for return value
+
+ // need to watch for a response
+ response = new msg_respond_t(msg);
+
+ // Convert a 64 bit pointer to a 32 bit unsigned int.
+ mbox_msg.msg_id =
+ static_cast<uint32_t>
+ (reinterpret_cast<uint64_t>(response->key));
+
+ iv_respondq.insert(response);
+ }
+
+ send_msg(&mbox_msg);
+
+ }
+ break;
+
+ case MSG_REGISTER_MSGQ:
+ {
+ errlHndl_t err = NULL;
+ queue_id_t queue_id = static_cast<queue_id_t>(msg->data[0]);
+ msg_q_t msgQ = reinterpret_cast<msg_q_t>(msg->data[1]);
+ err = msgq_register(queue_id,msgQ);
+ msg->data[1] = reinterpret_cast<uint64_t>(err);
+ msg_respond(iv_msgQ,msg);
+ }
+ break;
+
+ case MSG_UNREGISTER_MSGQ:
+ {
+ queue_id_t queue_id = static_cast<queue_id_t>(msg->data[0]);
+ msg_q_t msgQ = msgq_unregister(queue_id);
+ msg->data[1] = reinterpret_cast<uint64_t>(msgQ);
+ msg_respond(iv_msgQ,msg);
+ }
+ break;
+
+ default: //Huh? Ignore it.
+
+ TRACFCOMP(g_trac_mbox, ERR_MRK "MailboxSp::msgHandler() "
+ "invalid message received 0x%08x",msg->type);
+
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_INFORMATIONAL
+ * @moduleid MOD_MBOXSRV_HNDLR
+ * @reasoncode RC_INVALID_MBOX_MSG_TYPE
+ * @userdata1 Message type
+ * @defdesc Invalid message type sent to mailbox msgQ
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_INFORMATIONAL,
+ MBOX::MOD_MBOXSRV_HNDLR,
+ MBOX::RC_INVALID_MBOX_MSG_TYPE, // reason Code
+ msg->type, // msg type
+ 0
+ );
+
+ errlCommit(err,HBMBOX_COMP_ID);
+ err = NULL;
+
+ msg_free(msg);
+
+ break;
+ }
+
+ } // while(1)
+}
+
+
+
+// Note: When called due to an ACK or retry, iv_rts should be true.
+void MailboxSp::send_msg(mbox_msg_t * i_msg)
+{
+ if(i_msg)
+ {
+ iv_sendq.push_back(*i_msg);
+ }
+
+ // Can't send now if:
+ // - busy (waiting for ACK)
+ // - a DMA buffer request is pending
+ // - there is nothing to send
+ //
+ // TODO future optimization: If both iv_rts and iv_dma_pend are true then
+ // could look for a mesaage in the sendq that does not require a DMA
+ // buffer and send it.
+ if(!iv_rts || iv_dma_pend || iv_sendq.size() == 0)
+ {
+ return;
+ }
+
+ errlHndl_t err = NULL;
+
+ mbox_msg_t * mbox_msg = &(iv_sendq.front());;
+ msg_t * payload = &(mbox_msg->msg_payload);
+
+ iv_msg_to_send = *mbox_msg; //copy
+
+ // TODO remove the following line when DMA buffer support is available
+ payload->extra_data = NULL;
+
+ // Is a DMA buffer needed?
+ if(payload->extra_data != NULL)
+
+ {
+ size_t size = payload->data[1];
+ void * dma_buffer = NULL;
+ // TODO getDMA buffer
+
+ if(dma_buffer)
+ {
+ memcpy(dma_buffer,payload->extra_data,size);
+ iv_msg_to_send.msg_payload.extra_data = dma_buffer;
+
+ free(payload->extra_data);
+ iv_sendq.pop_front();
+ }
+ else // can't get buffer
+ {
+ // -- can't send the current message - leave it on the queue
+ // -- Instead send a message to FSP for more buffers
+ // TODO set sync flag when implementing DMA buffer
+ iv_msg_to_send.msg_id = 0;
+ iv_msg_to_send.msg_queue_id = FSP_MAILBOX_MSGQ;
+ iv_msg_to_send.msg_payload.type = MSG_REQUEST_DMA_BUFFERS;
+ iv_msg_to_send.msg_payload.data[0] = 0;
+ iv_msg_to_send.msg_payload.data[1] = 0;
+ iv_msg_to_send.msg_payload.extra_data = NULL;
+ iv_dma_pend = true;
+ }
+ }
+ else // simple message
+ {
+ iv_sendq.pop_front();
+ }
+
+ size_t mbox_msg_len = sizeof(mbox_msg_t);
+ iv_rts = false;
+
+ // TODO make these part of a "fast" trace (Story 39989)
+ TRACFCOMP(g_trac_mbox,
+ "MBOXSP SEND MSG HEAD: msg_id:0x%x msg_queue_id:0x%x",
+ iv_msg_to_send.msg_id,
+ iv_msg_to_send.msg_queue_id);
+
+ TRACFCOMP(g_trac_mbox,
+ "MBOXSP SEND MSG: 0x%08x 0x%016lx 0x%016lx %p",
+ iv_msg_to_send.msg_payload.type,
+ iv_msg_to_send.msg_payload.data[0],
+ iv_msg_to_send.msg_payload.data[1],
+ iv_msg_to_send.msg_payload.extra_data);
+
+ err = DeviceFW::deviceWrite(iv_trgt,
+ &iv_msg_to_send,
+ mbox_msg_len,
+ DeviceFW::MAILBOX);
+
+ if(err)
+ {
+ // If the message that could not be sent was a sync msg
+ // originating from HB then there is a task waiting for a response.
+ if(!msg_is_async(&(iv_msg_to_send.msg_payload)))
+ {
+ if(iv_msg_to_send.msg_queue_id >= FSP_FIRST_MSGQ)
+ {
+ msg_t * key = reinterpret_cast<msg_t *>(iv_msg_to_send.msg_id);
+ msg_respond_t * response = iv_respondq.find(key);
+ if(response)
+ {
+ iv_respondq.erase(response);
+ msg_t * msg = response->key;
+ msg->data[1] = reinterpret_cast<uint64_t>(err);
+ err = NULL;
+ msg_respond(iv_msgQ,msg);
+ delete response;
+ }
+ // else could be request for more DMA buffers
+ // - for now just commit the error. TODO recovery options?
+ }
+ // else msg is a HB response to a FSP originating sync msg
+ // What do we do here? Can't respond to the FSP.
+ // For now just commit the error. TODO recovery options?
+ }
+ // else msg was HB originating async - Just commit it.
+
+ if(err) // have error log and no where to respond to, so commit it.
+ {
+ errlCommit(err,HBMBOX_COMP_ID);
+ err = NULL;
+ }
+ }
+}
+
+
+errlHndl_t MailboxSp::recv_msg(mbox_msg_t & i_mbox_msg)
+{
+ errlHndl_t err = NULL;
+ int rc = 0;
+
+ // TODO look for response to requests for more DMA buffers
+ // and handle now
+ // add dma buffers
+ // iv_dma_pend = false;
+ // call send_msg to send next message if available and rts
+ //
+ // TODO - check for secure vs unsecure message types!
+
+ msg_t * msg = msg_allocate();
+ *msg = i_mbox_msg.msg_payload; // copy
+
+ // TODO make these part of a "fast" trace (Story 39989)
+ TRACFCOMP(g_trac_mbox,
+ "MBOXSP MSG HEAD: msg_id:0x%x msg_queue_id:0x%x",
+ i_mbox_msg.msg_id,
+ i_mbox_msg.msg_queue_id);
+
+ TRACFCOMP(g_trac_mbox,
+ "MBOXSP RECV MSG: 0x%08x 0x%016lx 0x%016lx %p",
+ msg->type,
+ msg->data[0],
+ msg->data[1],
+ msg->extra_data);
+
+ // Handle moving data from DMA buffer
+ if(msg->extra_data != NULL)
+ {
+ uint64_t msg_sz = msg->data[1];
+ void * buf = malloc(msg_sz);
+ memcpy(buf,msg->extra_data,msg_sz);
+
+ // DMArelease(msg->extra_data,msg_sz); TODO
+ msg->extra_data = buf;
+ // receiver of the message frees buffer.
+ }
+
+
+ // Is sync response message from FSP
+
+ msg_t * key = reinterpret_cast<msg_t *>(i_mbox_msg.msg_id);
+
+ msg_respond_t * response = iv_respondq.find(key);
+
+ // msg_id matches and the msg_queue_id is an FSP queue id
+ // If it's a hostboot target then it's not a response.
+ if(response && i_mbox_msg.msg_queue_id >= FSP_FIRST_MSGQ)
+ {
+ // remove from the list
+ iv_respondq.erase(response);
+
+ *(response->key) = *msg; // copy
+
+ msg_free(msg);
+
+ msg_respond(iv_msgQ,response->key);
+
+ delete response;
+ }
+ else
+ {
+ msg_q_t msgq = NULL;
+
+ registry_t::iterator r = iv_registry.find
+ (static_cast<queue_id_t>(i_mbox_msg.msg_queue_id));
+
+ if(r != iv_registry.end())
+ {
+ msgq = r->second;
+
+
+ if(msg_is_async(msg))
+ {
+ // send msg to queue
+ rc = msg_send(msgq,msg);
+ }
+ else //sync message from FSP
+ {
+ // Need to save queue_id and msg_id and msg ptr
+ // for reponse
+ msg_respond_t * response = new msg_respond_t(msg);
+ response->msg_id = i_mbox_msg.msg_id;
+ response->msg_queue_id = i_mbox_msg.msg_queue_id;
+
+ iv_respondq.insert(response);
+
+ rc = msg_sendrecv_noblk(msgq,msg,iv_msgQ);
+ }
+ }
+ else // unregistered msg_queue_id
+ {
+
+ TRACFCOMP(g_trac_mbox,
+ ERR_MRK
+ "MailboxSp::recv_msg - Message dropped. "
+ "Unregistered msg queue id 0x%x",
+ i_mbox_msg.msg_queue_id);
+
+ // TODO send a response back to the FSP
+ // msgqueue_id = 0x80000001
+ // msg type = 0x40000001
+
+ // TODO add an error log with a user data section containing the
+ // dropped message, including it's extra_data section
+ // Do this after the fake fsp mbserver is no longer being used.
+ // (Story 39989)
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid MOD_MBOXSRV_RCV
+ * @reasoncode RC_UNREGISTERED_MSG_QUEUE
+ * @userdata1 msg queueid
+ * @defdesc msg queue type is not registered with the
+ * mailbox
+ *
+ */
+ //err = new ERRORLOG::ErrlEntry
+ // (
+ // ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ // MBOX::MOD_MBOXSRV_RCV,
+ // MBOX::RC_UNREGISTERED_MSG_QUEUE, // reason Code
+ // i_mbox_msg.msg_queue_id, // rc from msg_send
+ // 0
+ // );
+ free(msg->extra_data);
+ msg_free(msg);
+ }
+ }
+
+ if(rc)
+ {
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid MOD_MBOXSRV_RCV
+ * @reasoncode RC_INVALID_QUEUE
+ * @userdata1 rc from msg_send()
+ * @defdesc Ivalid msg or msg queue
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
+ MBOX::MOD_MBOXSRV_RCV,
+ MBOX::RC_INVALID_QUEUE, // reason Code
+ rc, // rc from msg_send
+ 0
+ );
+ }
+
+ return err;
+}
+
+/**
+ * Send message to mailbox service to send a remote message
+ */
+errlHndl_t MailboxSp::send(queue_id_t i_q_id, msg_t * io_msg)
+{
+ errlHndl_t err = NULL;
+ int rc = 0;
+
+ msg_q_t mboxQ = msg_q_resolve(VFS_ROOT_MSG_MBOX);
+
+ msg_t* msg = msg_allocate();
+ msg->type = MBOX::MSG_SEND;
+ msg->data[0] = static_cast<uint64_t>(i_q_id);
+ msg->extra_data = reinterpret_cast<void*>(io_msg); // Payload message
+
+ if(msg_is_async(io_msg))
+ {
+ rc = msg_send(mboxQ, msg);
+ }
+ else
+ {
+ rc = msg_sendrecv(mboxQ, msg);
+
+ if(0 == rc)
+ {
+ err = reinterpret_cast<errlHndl_t>(msg->data[1]);
+ }
+
+ msg_free(msg);
+
+ // io_msg now contains response message
+ }
+
+ if(rc != 0)
+ {
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_CRITICAL_SYS_TERM
+ * @moduleid MOD_MBOXSRV_SEND
+ * @reasoncode RC_INVALID_QUEUE
+ * @userdata1 returncode from msg_sendrecv()
+ *
+ * @defdesc Invalid message or message queue
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, // severity
+ MBOX::MOD_MBOXSRV_SEND, // moduleid
+ MBOX::RC_INVALID_QUEUE, // reason Code
+ rc, // msg_sendrecv errno
+ i_q_id // msg queue id
+ );
+
+ // TODO add user section to error log containing io_msg (Story 39989)
+ }
+
+ return err;
+}
+
+
+errlHndl_t MailboxSp::msgq_register(queue_id_t i_queue_id, msg_q_t i_msgQ)
+{
+ errlHndl_t err = NULL;
+
+ registry_t::iterator r = iv_registry.find(i_queue_id);
+ if(r == iv_registry.end())
+ {
+ iv_registry[i_queue_id] = i_msgQ;
+
+ TRACFCOMP(g_trac_mbox,INFO_MRK"MailboxSp::msgq_register queue id %d",
+ i_queue_id);
+ }
+ else
+ {
+ // If its the same queue being registered again, just ignore it.
+ // If its a different queue then error.
+ if(r->second != i_msgQ)
+ {
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_INFORMATIONAL
+ * @moduleid MBOX::MOD_MBOXREGISTER
+ * @reasoncode MBOX::RC_ALREADY_REGISTERED
+ * @userdata1 queue_id_t queueId
+ * @userdata2 0
+ *
+ * @defdesc Message queue already registered with mailbox
+ * using a different queue.
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_INFORMATIONAL, // severity
+ MBOX::MOD_MBOXREGISTER, // moduleid
+ MBOX::RC_ALREADY_REGISTERED, // reason code
+ i_queue_id,
+ 0
+ );
+ }
+ }
+ return err;
+}
+
+msg_q_t MailboxSp::msgq_unregister(queue_id_t i_queue_id)
+{
+ msg_q_t msgQ = NULL;
+ registry_t::iterator r = iv_registry.find(i_queue_id);
+ if(r != iv_registry.end())
+ {
+ msgQ = r->second;
+ iv_registry.erase(r);
+ TRACFCOMP(g_trac_mbox,INFO_MRK"MailboxSp::msgq_unregister queue id %d",
+ i_queue_id);
+ }
+ return msgQ;
+}
+
+// ----------------------------------------------------------------------------
+// External Interfaces @see mboxif.H
+// ----------------------------------------------------------------------------
+
+errlHndl_t MBOX::send(queue_id_t i_q_id, msg_t * i_msg)
+{
+ i_msg->__reserved__async = 0;
+ return MailboxSp::send(i_q_id, i_msg);
+}
+
+errlHndl_t MBOX::sendrecv(queue_id_t i_q_id, msg_t * io_msg)
+{
+ io_msg->__reserved__async = 1;
+ return MailboxSp::send(i_q_id, io_msg);
+}
+
+errlHndl_t MBOX::msgq_register(queue_id_t i_queue_id, msg_q_t i_msgQ)
+{
+ // Could use a mutex to protect the queueid to msgQ map, but since
+ // registering is a rare thing, just send a message to the mailbox service.
+ errlHndl_t err = NULL;
+ msg_q_t mboxQ = msg_q_resolve(VFS_ROOT_MSG_MBOX);
+
+ if(mboxQ)
+ {
+ msg_t * msg = msg_allocate();
+ msg->type = MSG_REGISTER_MSGQ;
+ msg->data[0] = static_cast<uint64_t>(i_queue_id);
+ msg->data[1] = reinterpret_cast<uint64_t>(i_msgQ);
+
+ int rc = msg_sendrecv(mboxQ, msg);
+
+ if(!rc)
+ {
+ err = reinterpret_cast<errlHndl_t>(msg->data[1]);
+ }
+ else
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK
+ "MBOX::msgq_register - msg_sendrecv failed. errno = %d",
+ rc);
+ }
+ msg_free(msg);
+ }
+ else
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK"Mailbox Service not available");
+
+ /*@ errorlog tag
+ * @errortype ERRL_SEV_INFORMATIONAL
+ * @moduleid MBOX::MOD_MBOXREGISTER
+ * @reasoncode MBOX::RC_MBOX_SERVICE_NOT_READY
+ * @userdata1 queue_id_t queueId
+ * @userdata2 0
+ *
+ * @defdesc Mailbox service is not available now.
+ *
+ */
+ err = new ERRORLOG::ErrlEntry
+ (
+ ERRORLOG::ERRL_SEV_INFORMATIONAL, // severity
+ MBOX::MOD_MBOXREGISTER, // moduleid
+ MBOX::RC_MBOX_SERVICE_NOT_READY, // reason code
+ i_queue_id,
+ 0
+ );
+ }
+
+ return err;
+}
+
+msg_q_t MBOX::msgq_unregister(queue_id_t i_queue_id)
+{
+ msg_q_t msgQ = NULL;
+ msg_q_t mboxQ = msg_q_resolve(VFS_ROOT_MSG_MBOX);
+ if(mboxQ)
+ {
+ msg_t * msg = msg_allocate();
+ msg->type = MSG_UNREGISTER_MSGQ;
+ msg->data[0] = static_cast<uint64_t>(i_queue_id);
+
+ int rc = msg_sendrecv(mboxQ, msg);
+
+ if(!rc)
+ {
+ msgQ = reinterpret_cast<msg_q_t>(msg->data[1]);
+ }
+ else
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK
+ "MBOX::msgq_unregister - msg_sendrecv failed. errno = %d",
+ rc);
+ }
+
+ msg_free(msg);
+ }
+ else
+ {
+ TRACFCOMP(g_trac_mbox, ERR_MRK"Mailbox Service not available");
+ }
+
+ return msgQ;
+}
+
+
+
diff --git a/src/usr/mbox/mailboxsp.H b/src/usr/mbox/mailboxsp.H
new file mode 100644
index 000000000..41b582fbd
--- /dev/null
+++ b/src/usr/mbox/mailboxsp.H
@@ -0,0 +1,222 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mailbox/mailboxsp.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
+#if !defined(__MBOXSP__)
+#define __MBOXSP__
+/**
+ * @file mailboxrp.C
+ * @brief Mailbox service provider declariation
+ */
+#include <stdint.h>
+#include <builtins.h>
+#include <mbox/mboxif.H>
+#include <errl/errlentry.H>
+#include <sys/msg.h>
+#include <sys/sync.h>
+#include <list>
+#include <map>
+#include <util/locked/list.H>
+#include <intr/interrupt.H>
+
+extern const char* VFS_ROOT_MSG_MBOX;
+
+namespace TARGETING
+{
+ class Target;
+};
+
+namespace MBOX
+{
+ /**
+ * Messages to the mailbox queue
+ */
+ enum msgq_msg_t
+ {
+ MSG_SEND,
+ MSG_REGISTER_MSGQ,
+ MSG_UNREGISTER_MSGQ,
+
+ // TODO currently this is progammed to 0x1A in simics, but could change.
+ // Fix this when intr handler is changed to return this as data[0]
+ // instead of type.
+ MSG_INTR = INTR::FSP_MAILBOX, // Currently defined in intr/interupt.H
+ };
+
+
+ class MailboxSp
+ {
+ public:
+
+ /**
+ * Initialize the mailbox service
+ * @param[in] i_taskArgs
+ */
+ static void init(errlHndl_t& o_errl);
+
+ /**
+ * Send a message to the mailbox service
+ * @param[in] i_q_id, the queue id
+ * @param[in/out] io_msg the message to send and if async, the
+ * message returned
+ * @return errlHndl_t on error
+ */
+ static errlHndl_t send(queue_id_t i_q_id, msg_t * io_msg);
+
+
+
+
+ protected:
+
+ /**
+ * Default constructor
+ */
+ MailboxSp();
+
+ /**
+ * Destructor
+ */
+ ~MailboxSp();
+
+ /**
+ * Start message handler
+ */
+ static void msg_handler(void * unused);
+
+ private:
+
+ /**
+ * mailbox message header
+ * @note We decided to send this
+ */
+ struct mbox_msg_t
+ {
+ /**
+ * @brief Identifier assigned by originating endpoint for correlating
+ * sync message responses.
+ */
+ uint32_t msg_id;
+
+ /**
+ * Message queue id.
+ * @see src/include/usr/mbox/mbox_queues.H
+ */
+ uint32_t msg_queue_id;
+
+ /**
+ * Message
+ */
+ msg_t msg_payload;
+
+ /**
+ * Default constructor
+ */
+ mbox_msg_t() : msg_id(0), msg_queue_id(0), msg_payload() {}
+ };
+
+ // Private functions
+
+ /* See init() above */
+ errlHndl_t _init();
+
+ /**
+ * The mailbox service provider task
+ */
+ void msgHandler();
+
+ /**
+ * Send or queue up a message to the device driver
+ * @param[in] i_mbox_msg, the mailbox message
+ */
+ void send_msg(mbox_msg_t * i_msg = NULL);
+
+ /**
+ * Handle a mailbox message received from the device driver
+ * @param[in] i_mbox_msg, the mailbox message
+ * @return errlHndl_t on error
+ */
+ errlHndl_t recv_msg(mbox_msg_t & i_mbox_msg);
+
+ /**
+ * Register a message queue to receive mailbox messages
+ * @param[in] i_queueu_id, The queue identifier
+ * @param[in] i_msgQ, The message queue created with msg_q_create()
+ * @see sys/msg.h
+ * @return errlHndl_t on error
+ */
+ errlHndl_t msgq_register(queue_id_t i_queue_id, msg_q_t i_msgQ);
+
+
+ /**
+ * Un register a message queue from the mailbox service
+ * @param[in] i_queue_id, The queue identifier
+ * @return The message queue
+ */
+ msg_q_t msgq_unregister(queue_id_t i_queue_id);
+
+
+ enum
+ {
+ MAX_RETRY_COUNT = 3,
+ };
+
+ /**
+ * Information needed for a resonse to a sync message
+ */
+ struct msg_respond_t
+ {
+ public:
+ msg_respond_t * next;
+ msg_respond_t * prev;
+ msg_t * key; //!< ptr to original msg
+
+ //These fields are only used in sync message from FSP to HB
+ uint32_t msg_id; //!< The message_id
+ uint32_t msg_queue_id; //!< The msg queue id
+
+ /**
+ * Ctor
+ */
+ msg_respond_t(msg_t * i_msg) :
+ next(NULL),
+ prev(NULL),
+ key(i_msg),
+ msg_id(0),
+ msg_queue_id(0) {}
+ };
+
+ typedef std::list<mbox_msg_t> send_q_t;
+ typedef Util::Locked::List<msg_respond_t, msg_t *> respond_q_t;
+ typedef std::map<queue_id_t,msg_q_t> registry_t;
+
+ msg_q_t iv_msgQ; //!< mailbox mesage queue
+ send_q_t iv_sendq; //!< msg to send queue
+ mbox_msg_t iv_msg_to_send; //!< message being sent
+ respond_q_t iv_respondq; //!< msg respond pending list
+ registry_t iv_registry; //!< Registered queue
+
+ TARGETING::Target * iv_trgt;//!< mailbox device driver target
+ bool iv_rts; //!< ready to send flag
+ bool iv_dma_pend; //!< Request pending for more DMA buffers
+ };
+};
+
+#endif
diff --git a/src/usr/mbox/makefile b/src/usr/mbox/makefile
index 816d6dd37..455b5e581 100644
--- a/src/usr/mbox/makefile
+++ b/src/usr/mbox/makefile
@@ -23,7 +23,7 @@
ROOTPATH = ../../..
MODULE = mbox
-OBJS = mboxdd.o
+OBJS = mboxdd.o mailboxsp.o
SUBDIRS = test.d
diff --git a/src/usr/mbox/mboxdd.C b/src/usr/mbox/mboxdd.C
index 3c41dee34..1aff9405c 100644
--- a/src/usr/mbox/mboxdd.C
+++ b/src/usr/mbox/mboxdd.C
@@ -237,41 +237,33 @@ errlHndl_t MboxDD::read(TARGETING::Target* i_target,void *o_buffer,
* 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
+ * Bit29 : LBUS Slave B Pending Doorbell 1
+ * Bit28 : PIB 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
+ * Bit23-20 : Header Count PIB Slave A Doorbell 1
+ * Bit19-12 : Data Count PIB Slave A Doorbell 1
+ * Bit11-8 : Header Count LBUS Slave B Doorbell 1
+ * Bit7-0 : Data Count LBUS Slave B Doorbell 1
*/
- //Check for Abort
- if ((l_IntReg[0] & MBOX_ABORT_LAST_MSG) ==
- MBOX_ABORT_LAST_MSG &&
- (l_64bitBuf[0] & 0x40000000) == 0x40000000)
+ //Check for Xup
+ if ((l_IntReg[0] & MBOX_HW_ACK) ==
+ MBOX_HW_ACK &&
+ (l_64bitBuf[0] & 0x02000000) == 0x02000000)
{
- l_stat |= MBOX_ABORT_LAST_MSG;
- l_StatusReg[0] |= 0x40000000;
- }
- //Check for Xdn
- if ((l_IntReg[0] & MBOX_XDN_ACK) ==
- MBOX_XDN_ACK &&
- (l_64bitBuf[0] & 0x04000000) == 0x04000000)
- {
- l_stat |= MBOX_XDN_ACK;
- l_StatusReg[0] |= 0x04000000;
+ l_stat |= MBOX_HW_ACK;
+ l_StatusReg[0] |= 0x02000000;
}
//Check for PIB Pending
if ((l_IntReg[0] & MBOX_DATA_PENDING) ==
MBOX_DATA_PENDING &&
- (l_64bitBuf[0] & 0x20000000) == 0x20000000)
+ (l_64bitBuf[0] & 0x10000000) == 0x10000000)
{
l_stat |= MBOX_DATA_PENDING;
//Read how many bytes are significant
- io_buflen = ((l_64bitBuf[0] & 0x000FF000) >> 12);
+ io_buflen = (l_64bitBuf[0] & 0x000000FF);
if (buflen < io_buflen)
{
TRACFCOMP(g_trac_mbox, INFO_MRK "MBOX::read> Data truncated, input buffer length less than number of significant bytes");
@@ -306,13 +298,13 @@ errlHndl_t MboxDD::read(TARGETING::Target* i_target,void *o_buffer,
break;
}
- //Write-to-Clear PIB Pending,and bits 23-12 (data and header count)
+ //Write-to-Clear PIB Pending,and bits 20-32 (data and header count)
//Write to set Xup
- l_StatusReg[0] |= 0x22FFF000;
+ l_StatusReg[0] |= 0x14000FFF;
}
- //Write to clear PIB Pending, Abort, and Xdn (all that apply)
+ //Write to clear PIB Pending, Abort, and XUP (all that apply)
if(l_StatusReg[0])
{
l_err = deviceOp(DeviceFW::WRITE,i_target,
@@ -391,19 +383,19 @@ errlHndl_t MboxDD::write(TARGETING::Target* i_target,void* i_buffer,
* 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
+ * Bit29 : LBUS Slave B Pending Doorbell 1
+ * Bit28 : PIB 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
+ * Bit23-20 : Header Count PIB Slave A Doorbell 1
+ * Bit19-12 : Data Count PIB Slave A Doorbell 1
+ * Bit11-8 : Header Count LBUS Slave B Doorbell 1
+ * Bit7-0 : Data Count LBUS Slave B Doorbell 1
*/
//Verify LBUS Pending,
- if ((l_64bitBuf[0] & 0x10000FFF) == 0)
+ if ((l_64bitBuf[0] & 0x20FFF000) == 0)
{
uint32_t i = 0;
uint32_t l_data[2] = {0};
@@ -430,7 +422,7 @@ errlHndl_t MboxDD::write(TARGETING::Target* i_target,void* i_buffer,
}
//Write LBUS Pending(28) and Data Count bits(11-0)
- l_64bitBuf[0] = 0x10000000 | i_buflen;
+ l_64bitBuf[0] = 0x20000000 | (0x000FF000 & (i_buflen << 12));
l_err = deviceOp(DeviceFW::WRITE,i_target,
l_64bitBuf,l_64bitSize,
DEVICE_XSCOM_ADDRESS(MBOX_DB_STAT_CNTRL_1));
@@ -541,11 +533,10 @@ errlHndl_t MboxDD::init(TARGETING::Target* i_target)
{
errlHndl_t err = NULL;
// Setup mailbox intr mask reg
- // Set bits 6,4,2,0
+ // Set bits 2,1,0
// assume we always use mailbox 1
- uint64_t scom_data = (static_cast<uint64_t>(MBOX_ABORT_LAST_MSG) |
- static_cast<uint64_t>(MBOX_DOORBELL_ERROR) |
- static_cast<uint64_t>(MBOX_XDN_ACK) |
+ uint64_t scom_data = (static_cast<uint64_t>(MBOX_DOORBELL_ERROR) |
+ static_cast<uint64_t>(MBOX_HW_ACK) |
static_cast<uint64_t>(MBOX_DATA_PENDING)) << 32;
size_t scom_len = sizeof(uint64_t);
diff --git a/src/usr/mbox/mboxdd.H b/src/usr/mbox/mboxdd.H
index b8f59716f..5fa291178 100644
--- a/src/usr/mbox/mboxdd.H
+++ b/src/usr/mbox/mboxdd.H
@@ -50,9 +50,8 @@ class MboxDD
*/
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_DOORBELL_ERROR = 0x00000004, /* Error Set In Error Register */
+ MBOX_HW_ACK = 0x00000002, /* 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 */
@@ -115,33 +114,33 @@ class MboxDD
//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)
+ MBOX_DB_STAT_CNTRL_1 = 0x00050020, //LBUS(rw),PIB(rw) Stat/Cntrl 1
+ MBOX_DB_ERR_STAT_PIB = 0x00050031, //LBUS(ro),PIB(rw) Err Stat B
+ MBOX_DB_ERR_STAT_LBUS = 0x00050030, //LBUS(rw),PIB(ro) Err Stat A
+ MBOX_DB_INT_REG_LBUS = 0x00050035, //LBUS(rw),PIB(ro) Int Reg A
+ MBOX_DB_INT_MASK_LBUS_RS = 0x00050036, //LBUS(r/set),PIB(ro) Int Mask A
+ MBOX_DB_INT_MASK_LBUS_RC = 0x00050037, //LBUS(r/clear),PIB(ro/zero)
+ MBOX_DB_INT_REG_PIB = 0x00050032, //LBUS(ro),PIB(rw) Int Reg B
+ MBOX_DB_INT_MASK_PIB_RS = 0x00050033, //LBUS(ro),PIB(r/set) Int Mask B
+ MBOX_DB_INT_MASK_PIB_RC = 0x00050034, //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
+ MBOX_HEAD_CMD_LBUS0 = 0x00050025, //LBUS(rw),PIB(ro) H/C 0A
+ MBOX_HEAD_CMD_LBUS1 = 0x00050026, //LBUS(rw),PIB(ro) H/C 1A
+ MBOX_HEAD_CMD_LBUS2 = 0x00050027, //LBUS(rw),PIB(ro) H/C 2A
+ MBOX_HEAD_CMD_PIB0 = 0x00050021, //LBUS(ro),PIB(rw) H/C 0B
+ MBOX_HEAD_CMD_PIB1 = 0x00050022, //LBUS(ro),PIB(rw) H/C 1B
+ MBOX_HEAD_CMD_PIB2 = 0x00050023, //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
+ MBOX_DATA_LBUS_START = 0x00050080, //LBUS(rw),PIB(ro) First address
+ MBOX_DATA_LBUS_END = 0x0005008F, //LBUS(rw),PIB(ro) Last address
+ MBOX_DATA_PIB_START = 0x00050040, //LBUS(ro),PIB(rw) First address
+ MBOX_DATA_PIB_END = 0x0005004F, //LBUS(ro),PIB(rw) Last address
};
};
diff --git a/src/usr/mbox/test/mboxddtest.H b/src/usr/mbox/test/mboxddtest.H
index a1920d891..5b6c7e0fa 100644
--- a/src/usr/mbox/test/mboxddtest.H
+++ b/src/usr/mbox/test/mboxddtest.H
@@ -30,54 +30,50 @@
*/
#include <cxxtest/TestSuite.H>
+#include <intr/interrupt.H>
#include <errl/errlentry.H>
#include <errl/hberrltypes.H>
#include <limits.h>
#include <devicefw/driverif.H>
#include <mbox/mboxif.H>
+#include <sys/time.h>
+#include "../mboxdd.H"
extern trace_desc_t* g_trac_mbox;
using namespace TARGETING;
-
+using namespace MBOX;
class MboxDDTest : public CxxTest::TestSuite
{
public:
+
/**
* @brief MBOX DD test - Write (STUB)
* Perform basic write operation
*/
- void testWrite(void)
+ void _testRead(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)
+ * @brief MBOX DD test - Write (STUB)
+ * Perform basic write operation
*/
- void _testWriteRead(void)
+ void testEcho(void)
{
+ // this test messes up the mailbox services test
+ // and requires proper simics support
+#if defined(__testEcho__)
uint64_t o_status = 0;
errlHndl_t l_err = NULL;
uint32_t in_mboxMsg [] = {0x12345678, 0x14785236, 0x96325874,
- 0x98765432, 0x78910112, 0x66660000};
+ 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");
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testEcho> Begin");
TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
epath.addLast(TARGETING::TYPE_SYS,0);
@@ -85,37 +81,554 @@ class MboxDDTest : public CxxTest::TestSuite
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));
+ 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));
+ 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
- {
+ }
+ if (o_status != (MboxDD::MBOX_DATA_PENDING | MboxDD::MBOX_HW_ACK))//HW Ack & 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])
{
+ if (out_mboxMsg[i] != in_mboxMsg[i])
+ {
TS_FAIL("Loopback data area mismatch.\n");
break;
+ }
+ }
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testEcho> End");
+#endif
+ }
+
+ /**
+ * @brief MBOX DD test - Write/Read
+ * Perform basic write then read operation
+ * Requires SIMICS data loopback from SP-to-Host (PIB-to-LBUS)
+ */
+
+ enum {
+ NUM_TESTS = 0x3,
+ MAX_DATA = 13,
+ MAX_SIZE = 16,
+ CTL_SIZE = 3,
+ HOST_EYE = 0xBADCAFE0,
+ RSP_FLAG = 0x00000001,
+
+ };
+
+
+ errlHndl_t readMessage(TARGETING::Target* i_target, uint32_t o_msg[], size_t& io_size, uint64_t& o_status)
+ {
+ errlHndl_t l_err = NULL;
+ o_status = 0x0;
+ size_t buf_size = io_size;
+ io_size = 0x0;
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMessage> Entering loop waiting for read");
+ while (!o_status && !io_size && !l_err)
+ {
+
+ /* Reset io_size to passed in buffer size*/
+ io_size = buf_size;
+ l_err = DeviceFW::deviceRead(i_target,
+ static_cast<void*>(o_msg),io_size,
+ DEVICE_MBOX_ADDRESS(&o_status));
+ if (l_err)
+ {
+ TS_FAIL("Unable to read mailbox device.\n");
+ }
+
+ nanosleep(0,1000);
+ }
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMessage> Got MSG size[%d] status[%08x]", io_size, o_status);
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMessage> Data %08x %08x %08x %08x",
+ o_msg[0], o_msg[1], o_msg[2], o_msg[3]);
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMessage> Data %08x %08x %08x %08x",
+ o_msg[4], o_msg[5], o_msg[6], o_msg[7]);
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMessage> Data %08x %08x %08x %08x",
+ o_msg[8], o_msg[9], o_msg[10], o_msg[11]);
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMessage> Data %08x %08x %08x %08x",
+ o_msg[12], o_msg[13], o_msg[14], o_msg[15]);
+ TRACFCOMP(g_trac_mbox, " ");
+
+ return l_err;
+ }
+
+ errlHndl_t readMessageInt(TARGETING::Target* i_target, uint32_t o_msg[], size_t& io_size, uint64_t& o_status)
+ {
+ errlHndl_t l_err = NULL;
+ o_status = 0x0;
+ size_t buf_size = io_size;
+ io_size = 0x0;
+
+ /* Reset io_size to passed in buffer size*/
+ io_size = buf_size;
+ l_err = DeviceFW::deviceRead(i_target,
+ static_cast<void*>(o_msg),io_size,
+ DEVICE_MBOX_ADDRESS(&o_status));
+ if (l_err)
+ {
+ TS_FAIL("Unable to read mailbox device.\n");
+ }
+
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMsgInt> Got MSG size[%d] status[%08x]", io_size, o_status);
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMsgInt> Data %08x %08x %08x %08x",
+ o_msg[0], o_msg[1], o_msg[2], o_msg[3]);
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMsgInt> Data %08x %08x %08x %08x",
+ o_msg[4], o_msg[5], o_msg[6], o_msg[7]);
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMsgInt> Data %08x %08x %08x %08x",
+ o_msg[8], o_msg[9], o_msg[10], o_msg[11]);
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::readMsgInt> Data %08x %08x %08x %08x",
+ o_msg[12], o_msg[13], o_msg[14], o_msg[15]);
+ TRACFCOMP(g_trac_mbox, " ");
+
+ return l_err;
+ }
+
+ uint32_t psuedo_rand(uint32_t seed)
+ {
+ uint32_t top, bottom;
+ uint32_t rc;
+ bottom = ((seed*59) %29)*2131*137;
+ top = (bottom*941);
+ rc = (top<<16) | (0x0000FFFF &bottom);
+ return rc;
+ }
+
+ void bld_message(int which, uint32_t o_msg[])
+ {
+ o_msg[0] = HOST_EYE;
+ o_msg[1] = ((uint32_t)(which<<16) | 0x0000A5A5);
+ o_msg[2] = (psuedo_rand((uint64_t)&o_msg) % (MAX_DATA-1))+1;
+ for(uint32_t i=3; i < (o_msg[2]+3); i++)
+ {
+ o_msg[i] =psuedo_rand(o_msg[i-1]);
+ }
+ }
+
+ void cpy_msg(uint32_t i_msg[], uint32_t o_msg[])
+ {
+ for(uint32_t i=0; i < MAX_SIZE; i++)
+ {
+ o_msg[i] = i_msg[i];
+ }
+ }
+
+ int chk_msg(uint32_t in_msg[], uint32_t orig_msg[])
+ {
+ uint32_t xor_mask = orig_msg[1] | (orig_msg[1] <<16);
+
+ if (in_msg[0] != orig_msg[0])
+ return 1;
+
+ if (in_msg[1] != orig_msg[1])
+ return 1;
+
+ if (in_msg[2] != orig_msg[2])
+ return 1;
+
+ for(uint32_t i = 3; i < (orig_msg[2]+3); i++)
+ {
+ if (in_msg[i] != (xor_mask ^ orig_msg[i]))
+ return 1;
+ }
+
+ return 0;
+ }
+
+ void apply_xor(uint32_t msg[])
+ {
+ uint32_t xor_mask = msg[1] | (msg[1] <<16);
+
+ for(uint32_t i = 3; i < (msg[2]+3); i++)
+ {
+ msg[i] = msg[i] ^ xor_mask;
+ }
+ }
+
+ void _testWRPoll(void)
+ {
+ /* plan of attack is to send a slew of random messages down the mailbox and expect other side to
+ echo them back. Note that the other side will be doing the same
+
+ 1st message: Data 0 -- Hostboot eyecatcher, Data 1 -- number of messages to echo
+ <<< wait for FSP to respond: Data 0 -- Hostboot eyecatcher w Resp indicate
+
+ From this point on pump as many messages, as quickly as possible down the pipe in the following format
+ Note that host also has to respond to FSP as fast as possible. Note that responses take preference
+ Data 0 -- Hostboot eyecatcher
+ Data 1 -- sequence id (top 16 bits), XOR mask (bottom 16 bits, expand to 32 bits)
+ Data 2 -- number of valid words (1-13)
+ Data 3-15 -- data
+ Must get back:
+ Data 0 -- Hostboot eyecatcher with RSP bit on
+ Data 1 -- sequence id (top 16 bits), N/A (bottom 16 bits)
+ Data 2 -- number of valid words 1-13)
+ Data 3-15 -- data XORed
+ */
+
+ uint64_t o_status = 0;
+ uint64_t notused = 0;
+ errlHndl_t l_err = NULL;
+ size_t write_size = CTL_SIZE *sizeof(uint32_t);
+ uint32_t read_mboxMsg[MAX_SIZE] = {0};
+ size_t read_size;
+ uint32_t toggle = 0;
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> 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);
+ TARGETING::Target* my_target = TARGETING::targetService().toTarget(epath);
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> Waiting for FSP to send # tests...");
+ /* Wait for FSP to ack message before starting the test*/
+ while ((o_status & MboxDD::MBOX_DATA_PENDING) != MboxDD::MBOX_DATA_PENDING)
+ {
+ read_size = CTL_SIZE * sizeof(uint32_t);
+ l_err = readMessage(my_target, read_mboxMsg, read_size, o_status);
+ if (l_err)
+ {
+ TS_FAIL("Unable to read FSP control response\n");
+ }
+ }
+
+ size_t num_tests = read_mboxMsg[1];
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> Ack to FSP the # of messages of %d", num_tests);
+ /* Send message to FSP stating how many messages I want to test*/
+ l_err = DeviceFW::deviceWrite(
+ my_target,
+ static_cast<void*>(read_mboxMsg), read_size,
+ DEVICE_MBOX_ADDRESS(&notused));
+ if (l_err)
+ {
+ TS_FAIL("Unable to write to mailbox device.\n");
+ }
+
+ size_t num_msg_send = num_tests;
+ size_t num_msg_chk = num_tests;
+ size_t num_msg_resp = num_tests;
+ uint32_t sent_msg[num_tests][16];
+ memset(sent_msg, 0x0, sizeof(uint32_t)*num_tests*16);
+
+ uint32_t reply_msg[num_tests][16];
+ memset(reply_msg, 0x0, sizeof(uint32_t)*num_tests*16);
+ size_t reply_num = 0;
+
+ /* Enter big control loop*/
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> Enter control loop");
+ while( (num_msg_send || num_msg_resp || num_msg_chk) && !l_err)
+ {
+
+ /*read the mailbox waiting for next action*/
+ read_size = MAX_SIZE * sizeof(uint32_t);
+ l_err = readMessage(my_target, read_mboxMsg, read_size, o_status);
+ if (l_err)
+ {
+ TS_FAIL("Unable to read FSP control response\n");
+ }
+
+ /*If we have a message for us, process it*/
+ if(o_status & MboxDD::MBOX_DATA_PENDING)
+ {
+ if(!read_size)
+ {
+ TS_FAIL("Data pending without message size returned\n");
+ }
+
+ /*determine if this is a echo response or a new message*/
+ if(read_mboxMsg[0] == HOST_EYE)
+ {
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> Got response, match and check");
+
+ /*response*/
+ /*use the idx to match to sent message*/
+ size_t ridx = read_mboxMsg[1] >> 16;
+
+ /* check message */
+ if(chk_msg(read_mboxMsg, sent_msg[ridx]))
+ {
+ TS_FAIL("Response message wasn't sent correctly\n");
+ }
+ num_msg_chk--;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> FSP msg -- send back");
+ /*new message from FSP -- apply xor and send back*/
+ reply_num++;
+ cpy_msg(read_mboxMsg, reply_msg[reply_num]);
+ apply_xor(reply_msg[reply_num]);
+ }
+ }
+
+
+ /*see if we can send a message to the FSP*/
+ if ((o_status & MboxDD::MBOX_HW_ACK) && (num_msg_send || reply_num))
+ {
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> Send msg -- reply_num[%d] send_num[%d]",
+ reply_num, num_msg_send);
+
+ uint32_t *msg = NULL;
+ /*toggle between replies and new sends*/
+ if(reply_num && ((toggle++ %2) || !num_msg_send))
+ {
+ msg = reply_msg[reply_num];
+ reply_num--;
+ num_msg_resp--;
+ }
+ else if (num_msg_send)
+ {
+ /*Build a message*/
+ bld_message((num_msg_send-1), sent_msg[num_msg_send-1]);
+ msg = sent_msg[(num_msg_send-1)];
+ /* Decrement number of messages to send*/
+ num_msg_send--;
+ }
+
+ if(msg)
+ {
+ /*Send the message*/
+ write_size = (CTL_SIZE+msg[2]) *sizeof(uint32_t);
+ l_err = DeviceFW::deviceWrite(
+ my_target,
+ static_cast<void*>(msg),
+ write_size,
+ DEVICE_MBOX_ADDRESS(&notused));
+ if (l_err)
+ {
+ TS_FAIL("Unable to write to mailbox device.\n");
+ }
+ }
+ }
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> Next loop 2reply[%d] 2send[%d] chk[%d]",
+ num_msg_resp, num_msg_send, num_msg_chk);
+ }
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRPoll> End");
+ };
+
+
+ void _testWRInt(void)
+ {
+ /* plan of attack is to send a slew of random messages down the mailbox and expect other side to
+ echo them back. Note that the other side will be doing the same
+
+ 1st message: Data 0 -- Hostboot eyecatcher, Data 1 -- number of messages to echo
+ <<< wait for FSP to respond: Data 0 -- Hostboot eyecatcher w Resp indicate
+
+ From this point on pump as many messages, as quickly as possible down the pipe in the following format
+ Note that host also has to respond to FSP as fast as possible. Note that responses take preference
+ Data 0 -- Hostboot eyecatcher
+ Data 1 -- sequence id (top 16 bits), XOR mask (bottom 16 bits, expand to 32 bits)
+ Data 2 -- number of valid words (1-13)
+ Data 3-15 -- data
+ Must get back:
+ Data 0 -- Hostboot eyecatcher with RSP bit on
+ Data 1 -- sequence id (top 16 bits), N/A (bottom 16 bits)
+ Data 2 -- number of valid words 1-13)
+ Data 3-15 -- data XORed
+ */
+
+ uint64_t o_status = 0;
+ uint64_t notused = 0;
+ errlHndl_t l_err = NULL;
+ size_t write_size = CTL_SIZE *sizeof(uint32_t);
+ uint32_t read_mboxMsg[MAX_SIZE] = {0};
+ size_t read_size;
+ uint32_t toggle = 0;
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> 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);
+ TARGETING::Target* my_target = TARGETING::targetService().toTarget(epath);
+
+ /*Register for interrupt*/
+ msg_q_t msgQ = msg_q_create();
+ l_err = INTR::registerMsgQ(msgQ,(INTR::ext_intr_t)0x1A); //Simics is setup to send IRQ on 26
+ if(l_err)
+ {
+ TS_FAIL("Errl from INTR::registerMsgQ()");
+ delete l_err;
+ l_err = NULL;
+ }
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> Enable interrupts on MBOX");
+ l_err = MboxDD::init(my_target);
+ if(l_err)
+ {
+ TS_FAIL("Errl from MboxDD::init()");
+ delete l_err;
+ l_err = NULL;
+ }
+
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> Waiting for FSP to send # tests...");
+ msg_t* msg = msg_wait(msgQ); // wait for interrupt msg
+
+ /*got the IRQ -- need to read the mailbox message and handle*/
+ read_size = CTL_SIZE * sizeof(uint32_t);
+ l_err = readMessageInt(my_target, read_mboxMsg, read_size, o_status);
+ if (l_err)
+ {
+ TS_FAIL("Unable to read FSP control response\n");
+ }
+
+ /*Ack the IRQ*/
+ msg_respond(msgQ,msg);
+
+ if ((o_status & MboxDD::MBOX_DATA_PENDING) != MboxDD::MBOX_DATA_PENDING
+ || !read_size)
+ {
+ TS_FAIL("First message Unable to read FSP control response\n");
+ }
+
+ size_t num_tests = read_mboxMsg[1];
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> Ack to FSP the # of messages of %d", num_tests);
+ /* Send message to FSP stating how many messages I want to test*/
+ l_err = DeviceFW::deviceWrite(
+ my_target,
+ static_cast<void*>(read_mboxMsg), read_size,
+ DEVICE_MBOX_ADDRESS(&notused));
+
+ TRACFCOMP(g_trac_mbox, "Write complete");
+ if (l_err)
+ {
+ TS_FAIL("Unable to write to mailbox device.\n");
+ }
+
+ size_t num_msg_send = num_tests;
+ size_t num_msg_chk = num_tests;
+ size_t num_msg_resp = num_tests;
+ uint32_t sent_msg[num_tests][16];
+ memset(sent_msg, 0x0, sizeof(uint32_t)*num_tests*16);
+
+ uint32_t reply_msg[num_tests][16];
+ memset(reply_msg, 0x0, sizeof(uint32_t)*num_tests*16);
+ size_t reply_num = 0;
+
+ /* Enter big control loop*/
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> Enter control loop");
+ while( (num_msg_send || num_msg_resp || num_msg_chk) && !l_err)
+ {
+ msg = msg_wait(msgQ); // wait for interrupt msg
+
+ /*got the IRQ -- need to read the mailbox message and handle*/
+ read_size = MAX_SIZE * sizeof(uint32_t);
+ l_err = readMessageInt(my_target, read_mboxMsg, read_size, o_status);
+ if (l_err)
+ {
+ TS_FAIL("Unable to read FSP control response\n");
+ }
+
+ /*Ack the IRQ*/
+ msg_respond(msgQ,msg);
+
+ /*If we have a message for us, process it*/
+ if(o_status & MboxDD::MBOX_DATA_PENDING)
+ {
+ if(!read_size)
+ {
+ TS_FAIL("Data pending without message size returned\n");
+ }
+
+ /*determine if this is a echo response or a new message*/
+ if(read_mboxMsg[0] == HOST_EYE)
+ {
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> Got response, match and check");
+
+ /*response*/
+ /*use the idx to match to sent message*/
+ size_t ridx = read_mboxMsg[1] >> 16;
+
+ /* check message */
+ if(chk_msg(read_mboxMsg, sent_msg[ridx]))
+ {
+ TS_FAIL("Response message wasn't sent correctly\n");
+ }
+ num_msg_chk--;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> FSP msg -- send back");
+ /*new message from FSP -- apply xor and send back*/
+ reply_num++;
+ cpy_msg(read_mboxMsg, reply_msg[reply_num]);
+ apply_xor(reply_msg[reply_num]);
+ }
+ }
+
+
+ /*see if we can send a message to the FSP*/
+ if ((o_status & MboxDD::MBOX_HW_ACK) && (num_msg_send || reply_num))
+ {
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> Send msg -- reply_num[%d] send_num[%d]",
+ reply_num, num_msg_send);
+
+ uint32_t *msg = NULL;
+ /*toggle between replies and new sends*/
+ if(reply_num && ((toggle++ %2) || !num_msg_send))
+ {
+ msg = reply_msg[reply_num];
+ reply_num--;
+ num_msg_resp--;
+ }
+ else if (num_msg_send)
+ {
+ /*Build a message*/
+ num_msg_send--;
+ bld_message((num_msg_send), sent_msg[num_msg_send]);
+ msg = sent_msg[(num_msg_send)];
+ /* Decrement number of messages to send*/
+ ;
+ }
+
+ if(msg)
+ {
+ /*Send the message*/
+ write_size = (CTL_SIZE+msg[2]) *sizeof(uint32_t);
+ l_err = DeviceFW::deviceWrite(
+ my_target,
+ static_cast<void*>(msg),
+ write_size,
+ DEVICE_MBOX_ADDRESS(&notused));
+ if (l_err)
+ {
+ TS_FAIL("Unable to write to mailbox device.\n");
+ }
+ }
+ }
+
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> Next loop 2reply[%d] 2send[%d] chk[%d]",
+ num_msg_resp, num_msg_send, num_msg_chk);
}
- }
- TRACFCOMP(g_trac_mbox, "MboxDDTest::testWriteRead> End");
+ TRACFCOMP(g_trac_mbox, "MboxDDTest::testWRInt> End");
};
};
diff --git a/src/usr/mbox/test/mboxsptest.H b/src/usr/mbox/test/mboxsptest.H
new file mode 100644
index 000000000..7a40d1f3b
--- /dev/null
+++ b/src/usr/mbox/test/mboxsptest.H
@@ -0,0 +1,165 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/mbox/test/mboxsptest.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 __MBOXSPTEST_H
+#define __MBOXSPTEST_H
+
+/**
+ * @file mboxsptest.H
+ *
+ * @brief Test cases for MBOX service provider
+*/
+
+#include <cxxtest/TestSuite.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <errl/hberrltypes.H>
+#include <limits.h>
+#include <mbox/mboxif.H>
+#include <targeting/util.H>
+
+extern trace_desc_t* g_trac_mbox;
+
+using namespace TARGETING;
+
+class MboxSPTest : public CxxTest::TestSuite
+{
+ public:
+
+ /**
+ * @brief MBOX - Send asynchronous message
+ */
+ void testSendAsync(void)
+ {
+ // TODO Temporaritly DISABLE in VBU until INTR BAR is set
+ if( TARGETING::is_vpo() )
+ {
+ return;
+ }
+ // requires proper simics model
+ // msg will get echoed which looks like a new msg from FSP
+ // Register a message queue to receive it.
+ msg_q_t msgQ = msg_q_create();
+ errlHndl_t err = MBOX::msgq_register(MBOX::HB_TEST_MSGQ,msgQ);
+
+ if(err)
+ {
+ TS_FAIL("MBOX: Could not register message queue");
+ errlCommit(err,HBMBOX_COMP_ID);
+ }
+
+ // Send some messages
+ for(size_t i = 1; i < 2; ++i)
+ {
+ msg_t* msg = msg_allocate();
+ msg->type = 1;
+ msg->data[1] = 0xFFFFFFFFFFFFFFFFul;
+ msg->extra_data = NULL;
+
+ msg->data[0] = i;
+ MBOX::send(MBOX::HB_TEST_MSGQ,msg);
+ }
+
+ // Send last message
+ msg_t * msg = msg_allocate();
+ msg->type = 3; // use this to terminate while loop below
+ msg->extra_data = NULL;
+ MBOX::send(MBOX::HB_TEST_MSGQ,msg);
+
+ // now get the messages - they will look like async messages
+ // from FSP, even though they are just the echo of the
+ // async messages that hostboot just sent above.
+ size_t msg_idx = 0;
+ while(1)
+ {
+ msg_t* msg = msg_wait(msgQ);
+
+ if(msg->type == 3)
+ {
+ msg_free(msg);
+ break;
+ }
+
+ ++msg_idx;
+
+ if(msg->type != 1 ||
+ msg->data[0] != msg_idx ||
+ msg->data[1] != 0xFFFFFFFFFFFFFFFFul)
+ {
+ TS_FAIL("MBOX: Unexpected message from FSP");
+
+ TRACFCOMP(g_trac_mbox,
+ "MSG from FSP: %d %lx %lx %p",
+ msg->type,
+ msg->data[0],
+ msg->data[1],
+ msg->extra_data);
+ }
+
+ msg_free(msg);
+ }
+
+ msgQ = MBOX::msgq_unregister(MBOX::HB_TEST_MSGQ);
+ msg_q_destroy(msgQ);
+ }
+
+ /**
+ * @brief MBOX - Send sync message
+ */
+ void testSendSync(void)
+ {
+ // TODO Temporaritly DISABLE in VBU until INTR BAR is set
+ if( TARGETING::is_vpo() )
+ {
+ return;
+ }
+ // Echo What gets sent comes back
+ // Will get changed to invert data (or something like that)
+ msg_t * msg = msg_allocate();
+ msg->type = 2;
+ msg->data[0] = 0x001122334455667788;
+ msg->data[1] = 1;
+ msg->extra_data = NULL;
+
+ MBOX::sendrecv(MBOX::FSP_ECHO_MSGQ,msg);
+
+ // TODO eventually the return data will be inverted or modified in
+ // some way.
+ if(msg->type != 2 ||
+ msg->data[0] != 0x001122334455667788 ||
+ msg->data[1] != 1)
+ {
+ TS_FAIL("Unexpected mailbox sync message returned");
+
+ TRACFCOMP(g_trac_mbox,
+ "SYNC response: %d %lx %lx %p",
+ msg->type,
+ msg->data[0],
+ msg->data[1],
+ msg->extra_data);
+ }
+ msg_free(msg);
+ }
+};
+
+#endif
+
OpenPOWER on IntegriCloud