diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/build/citest/etc/workarounds.postsimsetup | 4 | ||||
-rwxr-xr-x | src/build/citest/etc/workarounds.presimsetup | 2 | ||||
-rwxr-xr-x | src/build/simics/post_model_hook.simics | 7 | ||||
-rw-r--r-- | src/include/usr/mbox/mbox_queues.H | 92 | ||||
-rw-r--r-- | src/include/usr/mbox/mbox_reasoncodes.H | 13 | ||||
-rw-r--r-- | src/include/usr/mbox/mboxif.H | 64 | ||||
-rw-r--r-- | src/sys/vfs/vfs_main.C | 1 | ||||
-rw-r--r-- | src/usr/initservice/extinitsvc/extinitsvctasks.H | 3 | ||||
-rw-r--r-- | src/usr/mbox/mailboxsp.C | 856 | ||||
-rw-r--r-- | src/usr/mbox/mailboxsp.H | 222 | ||||
-rw-r--r-- | src/usr/mbox/makefile | 2 | ||||
-rw-r--r-- | src/usr/mbox/mboxdd.C | 65 | ||||
-rw-r--r-- | src/usr/mbox/mboxdd.H | 43 | ||||
-rw-r--r-- | src/usr/mbox/test/mboxddtest.H | 583 | ||||
-rw-r--r-- | src/usr/mbox/test/mboxsptest.H | 165 |
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(¬used)); + 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(¬used)); + 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(¬used)); + + 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(¬used)); + 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 + |