<commit_before>/* Copyright 2015 Stanford University, NVIDIA Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// templated priority queue

// nop, but helps IDEs
#include "pri_queue.h"

namespace Realm {

  ////////////////////////////////////////////////////////////////////////
  //
  // class PriorityQueue<T, LT>

  template <typename T, typename LT>
  inline PriorityQueue<T, LT>::PriorityQueue(void)
    : highest_priority (PRI_NEG_INF)
  {
  }

  template <typename T, typename LT>
  inline PriorityQueue<T, LT>::~PriorityQueue(void)
  {
    // STL cleans everything up
  }

  // two ways to add an item -
  //  1) add it to the end of the list at that priority (i.e. FIFO order)
  //  2) "unget" adds it to the front of the list (i.e. LIFO order)
  template <typename T, typename LT>
  inline void PriorityQueue<T, LT>::put(T item,
					priority_t priority,
					bool add_to_back /*= true*/)
  {
    // step 1: clamp the priority to the "finite" range
    if(priority > PRI_MAX_FINITE)
      priority = PRI_MAX_FINITE;
    else if(priority < PRI_MIN_FINITE)
      priority = PRI_MIN_FINITE;

    // step 2: take the lock
    lock.lock();

    // step 3: if this is higher priority than anybody else, do notification callbacks
    if(priority > highest_priority) {
      // remember the original one in case this gets immediately grabbed
      priority_t orig_highest = highest_priority;

      // now update the highest before we do notifications
      highest_priority = priority;

      // now the notifications, if any
      if(perform_notifications(item, priority)) {
	// item was taken, so restore original highest priority and exit
	highest_priority = orig_highest;
	lock.unlock();
	return;
      }
    }

    // get the right deque (this will create one if needed)
    std::deque<T>& dq = queue[-priority]; // remember negation...

    // and add the item
    if(add_to_back)
      dq.push_back(item);
    else
      dq.push_front(item);

    // all done
    lock.unlock();
  }

  // getting an item is always from the front of the list and can be filtered to
  //  ignore things that aren't above a specified priority
  // the priority of the retrieved item (if any) is returned in *item_priority
  template <typename T, typename LT>
  inline T PriorityQueue<T, LT>::get(priority_t *item_priority,
				     priority_t higher_than /*= PRI_NEG_INF*/)
  {
    // body is protected by lock
    lock.lock();

    // empty queue - early out
    if(queue.empty()) {
      lock.unlock();
      return 0; // TODO - EMPTY_VAL
    }

    typename std::map<priority_t, std::deque<T> >::iterator it = queue.begin();
    priority_t priority = -(it->first);

    // not interesting enough?
    if(priority <= higher_than) {
      lock.unlock();
      return 0; // TODO - EMPTY_VAL
    };

    // take item off front
    T item = it->second.front();
    it->second.pop_front();

    // if list is now empty, remove from the queue and adjust highest_priority
    if(it->second.empty()) {
      queue.erase(it);
      highest_priority = (queue.empty() ?
			    PRI_NEG_INF :
			    -(queue.begin()->first));
    }

    // release lock and then return result
    lock.unlock();

    if(item_priority)
      *item_priority = priority;
    return item;
  }

  // peek is like get, but doesn't remove the element (this is only really useful when
  //  you don't have multiple getters)
  template <typename T, typename LT>
  inline T PriorityQueue<T, LT>::peek(priority_t *item_priority,
				      priority_t higher_than /*= PRI_NEG_INF*/) const
  {
    // body is protected by lock
    lock.lock();

    // empty queue - early out
    if(queue.empty()) {
      lock.unlock();
      return 0; // TODO - EMPTY_VAL
    }

    typename std::map<priority_t, std::deque<T> >::const_iterator it = queue.begin();
    priority_t priority = -(it->first);

    // not interesting enough?
    if(priority <= higher_than) {
      lock.unlock();
      return 0; // TODO - EMPTY_VAL
    };

    // peek at item on front
    T item = it->second.front();

    // release lock and then return result
    lock.unlock();

    if(item_priority)
      *item_priority = priority;
    return item;
  }

  // similarly, the empty-ness query can also ignore things below a certain priority
  // this call is lock-free (and is again of questionable utility with multiple readers)
  template <typename T, typename LT>
  inline bool PriorityQueue<T, LT>::empty(priority_t higher_than /*= PRI_NEG_INF*/) const
  {
    return(highest_priority > higher_than);
  }

  // adds (or modifies) a subscription - only items above the specified priority will
  //  result in callbacks
  template <typename T, typename LT>
  inline void PriorityQueue<T, LT>::add_subscription(NotificationCallback *callback,
						     priority_t higher_than /*= PRI_NEG_INF*/)
  {
    // just take lock and update subscription map
    lock.lock();
    subscriptions[callback] = higher_than;
    lock.unlock();
  }

  template <typename T, typename LT>
  inline void PriorityQueue<T, LT>::remove_subscription(NotificationCallback *callback)
  {
    // just take lock and erase subscription map entry (if present)
    lock.lock();
    subscriptions.erase(callback);
    lock.unlock();
  }

  // helper that performs notifications for a new item - returns true if a callback
  //  consumes the item
  template <typename T, typename LT>
  inline bool PriorityQueue<T, LT>::perform_notifications(T item, priority_t item_priority)
  {
    // lock already held by caller

    for(typename std::map<NotificationCallback *, priority_t>::const_iterator it = subscriptions.begin();
	it != subscriptions.end();
	it++) {
      // skip if this isn't interesting to this callback
      if(item_priority <= it->second)
	continue;

      // do callback - a return of true means the item was consumed (so we shouldn't do
      //  any more callbacks
      if(it->first->item_available(item, item_priority))
	return true;
    }

    // got through all the callbacks and nobody wanted it
    return false;
  }

}; // namespace Realm
<commit_msg>fix polarity<commit_after>/* Copyright 2015 Stanford University, NVIDIA Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// templated priority queue

// nop, but helps IDEs
#include "pri_queue.h"

namespace Realm {

  ////////////////////////////////////////////////////////////////////////
  //
  // class PriorityQueue<T, LT>

  template <typename T, typename LT>
  inline PriorityQueue<T, LT>::PriorityQueue(void)
    : highest_priority (PRI_NEG_INF)
  {
  }

  template <typename T, typename LT>
  inline PriorityQueue<T, LT>::~PriorityQueue(void)
  {
    // STL cleans everything up
  }

  // two ways to add an item -
  //  1) add it to the end of the list at that priority (i.e. FIFO order)
  //  2) "unget" adds it to the front of the list (i.e. LIFO order)
  template <typename T, typename LT>
  inline void PriorityQueue<T, LT>::put(T item,
					priority_t priority,
					bool add_to_back /*= true*/)
  {
    // step 1: clamp the priority to the "finite" range
    if(priority > PRI_MAX_FINITE)
      priority = PRI_MAX_FINITE;
    else if(priority < PRI_MIN_FINITE)
      priority = PRI_MIN_FINITE;

    // step 2: take the lock
    lock.lock();

    // step 3: if this is higher priority than anybody else, do notification callbacks
    if(priority > highest_priority) {
      // remember the original one in case this gets immediately grabbed
      priority_t orig_highest = highest_priority;

      // now update the highest before we do notifications
      highest_priority = priority;

      // now the notifications, if any
      if(perform_notifications(item, priority)) {
	// item was taken, so restore original highest priority and exit
	highest_priority = orig_highest;
	lock.unlock();
	return;
      }
    }

    // get the right deque (this will create one if needed)
    std::deque<T>& dq = queue[-priority]; // remember negation...

    // and add the item
    if(add_to_back)
      dq.push_back(item);
    else
      dq.push_front(item);

    // all done
    lock.unlock();
  }

  // getting an item is always from the front of the list and can be filtered to
  //  ignore things that aren't above a specified priority
  // the priority of the retrieved item (if any) is returned in *item_priority
  template <typename T, typename LT>
  inline T PriorityQueue<T, LT>::get(priority_t *item_priority,
				     priority_t higher_than /*= PRI_NEG_INF*/)
  {
    // body is protected by lock
    lock.lock();

    // empty queue - early out
    if(queue.empty()) {
      lock.unlock();
      return 0; // TODO - EMPTY_VAL
    }

    typename std::map<priority_t, std::deque<T> >::iterator it = queue.begin();
    priority_t priority = -(it->first);

    // not interesting enough?
    if(priority <= higher_than) {
      lock.unlock();
      return 0; // TODO - EMPTY_VAL
    };

    // take item off front
    T item = it->second.front();
    it->second.pop_front();

    // if list is now empty, remove from the queue and adjust highest_priority
    if(it->second.empty()) {
      queue.erase(it);
      highest_priority = (queue.empty() ?
			    PRI_NEG_INF :
			    -(queue.begin()->first));
    }

    // release lock and then return result
    lock.unlock();

    if(item_priority)
      *item_priority = priority;
    return item;
  }

  // peek is like get, but doesn't remove the element (this is only really useful when
  //  you don't have multiple getters)
  template <typename T, typename LT>
  inline T PriorityQueue<T, LT>::peek(priority_t *item_priority,
				      priority_t higher_than /*= PRI_NEG_INF*/) const
  {
    // body is protected by lock
    lock.lock();

    // empty queue - early out
    if(queue.empty()) {
      lock.unlock();
      return 0; // TODO - EMPTY_VAL
    }

    typename std::map<priority_t, std::deque<T> >::const_iterator it = queue.begin();
    priority_t priority = -(it->first);

    // not interesting enough?
    if(priority <= higher_than) {
      lock.unlock();
      return 0; // TODO - EMPTY_VAL
    };

    // peek at item on front
    T item = it->second.front();

    // release lock and then return result
    lock.unlock();

    if(item_priority)
      *item_priority = priority;
    return item;
  }

  // similarly, the empty-ness query can also ignore things below a certain priority
  // this call is lock-free (and is again of questionable utility with multiple readers)
  template <typename T, typename LT>
  inline bool PriorityQueue<T, LT>::empty(priority_t higher_than /*= PRI_NEG_INF*/) const
  {
    return(highest_priority <= higher_than);
  }

  // adds (or modifies) a subscription - only items above the specified priority will
  //  result in callbacks
  template <typename T, typename LT>
  inline void PriorityQueue<T, LT>::add_subscription(NotificationCallback *callback,
						     priority_t higher_than /*= PRI_NEG_INF*/)
  {
    // just take lock and update subscription map
    lock.lock();
    subscriptions[callback] = higher_than;
    lock.unlock();
  }

  template <typename T, typename LT>
  inline void PriorityQueue<T, LT>::remove_subscription(NotificationCallback *callback)
  {
    // just take lock and erase subscription map entry (if present)
    lock.lock();
    subscriptions.erase(callback);
    lock.unlock();
  }

  // helper that performs notifications for a new item - returns true if a callback
  //  consumes the item
  template <typename T, typename LT>
  inline bool PriorityQueue<T, LT>::perform_notifications(T item, priority_t item_priority)
  {
    // lock already held by caller

    for(typename std::map<NotificationCallback *, priority_t>::const_iterator it = subscriptions.begin();
	it != subscriptions.end();
	it++) {
      // skip if this isn't interesting to this callback
      if(item_priority <= it->second)
	continue;

      // do callback - a return of true means the item was consumed (so we shouldn't do
      //  any more callbacks
      if(it->first->item_available(item, item_priority))
	return true;
    }

    // got through all the callbacks and nobody wanted it
    return false;
  }

}; // namespace Realm
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/cache/p9_hcd_cache_stopclocks.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file  p9_hcd_cache_stopclocks.C
/// @brief Quad Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@us.ibm.com>
// *HWP Backup HWP Owner   : Greg Still     <stillgs@us.ibm.com>
// *HWP FW Owner           : Sangeetha T S  <sangeet2@in.ibm.com>
// *HWP Team               : PM
// *HWP Consumed by        : HB:PERV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include <p9_common_clk_ctrl_state.H>
#include "p9_hcd_l2_stopclocks.H"
#include "p9_hcd_cache_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_CACHE_STOPCLOCKS_CONSTANTS
{
    CACHE_CLK_STOP_POLLING_HW_NS_DELAY     = 10000,
    CACHE_CLK_STOP_POLLING_SIM_CYCLE_DELAY = 320000
};

//------------------------------------------------------------------------------
// Procedure: Quad Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_cache_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
    const p9hcd::P9_HCD_CLK_CTRL_CONSTANTS      i_select_regions,
    const p9hcd::P9_HCD_EX_CTRL_CONSTANTS       i_select_ex)
{
    FAPI_INF(">>p9_hcd_cache_stopclocks: regions[%016llx] ex[%d]",
             i_select_regions, i_select_ex);
    fapi2::ReturnCode                              l_rc;
    fapi2::buffer<uint64_t>                        l_data64;
    fapi2::buffer<uint64_t>                        l_temp64;
    uint64_t                                       l_l3mask_pscom = 0;
    uint32_t                                       l_loops1ms;
    uint8_t                                        l_attr_chip_unit_pos = 0;
    uint8_t                                        l_attr_vdm_enable;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys;
    auto l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLE,    l_sys,
                           l_attr_vdm_enable));
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_perv,
                           l_attr_chip_unit_pos));
//  l_attr_chip_unit_pos = l_attr_chip_unit_pos - p9hcd::PERV_TO_QUAD_POS_OFFSET;
    l_attr_chip_unit_pos = l_attr_chip_unit_pos - 0x10;

    if (i_select_regions & p9hcd::CLK_REGION_EX0_L3)
    {
        l_l3mask_pscom |= (BIT64(4) | BIT64(6) | BIT64(8));
    }

    if (i_select_regions & p9hcd::CLK_REGION_EX1_L3)
    {
        l_l3mask_pscom |= (BIT64(5) | BIT64(7) | BIT64(9));
    }

    // -----------------------------
    // Prepare to stop cache clocks
    // -----------------------------

    FAPI_DBG("Check PM_RESET_STATE_INDICATOR via GPMMR[15]");
    FAPI_TRY(getScom(i_target, EQ_PPM_GPMMR_SCOM, l_data64));

    if (!l_data64.getBit<15>())
    {
        FAPI_DBG("Gracefully turn off power management, if fail, continue anyways");
        /// @todo suspend_pm()
    }

    FAPI_DBG("Check cache clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_EQ>(i_target);

    if (l_rc)
    {
        FAPI_INF("Clock controller of this cache chiplet is inaccessible, return");
        goto fapi_try_exit;
    }

    FAPI_DBG("Check PERV clock status for access to CME via CLOCK_STAT[4]");
    FAPI_TRY(getScom(i_target, EQ_CLOCK_STAT_SL, l_data64));

    FAPI_DBG("Check PERV fence status for access to CME via CPLT_CTRL1[4]");
    FAPI_TRY(getScom(i_target, EQ_CPLT_CTRL1, l_temp64));

    if (l_data64.getBit<4>() == 0 && l_temp64.getBit<4>() == 0)
    {
        /// @todo RTC158181 disable l2 snoop? disable lco? assert refresh quiesce?
        FAPI_DBG("Assert L3 pscom masks via RING_FENCE_MASK_LATCH_REG[4-9]");
        FAPI_TRY(putScom(i_target, EQ_RING_FENCE_MASK_LATCH_REG, l_l3mask_pscom));
    }

    FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]");
    FAPI_TRY(putScom(i_target, EQ_NET_CTRL0_WOR, MASK_SET(18)));

    // -------------------------------
    // Stop L2 clocks
    // -------------------------------

    if (i_select_ex)
        FAPI_EXEC_HWP(fapi2::current_err,
                      p9_hcd_l2_stopclocks,
                      i_target, i_select_ex);

    // -------------------------------
    // Stop cache clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, EQ_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop cache clocks via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD  |
                i_select_regions     |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, EQ_CLK_REGION, l_data64));

    FAPI_DBG("Poll for cache clocks stopped via CPLT_STAT0[8]");
    l_loops1ms = 1E6 / CACHE_CLK_STOP_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CACHE_CLK_STOP_POLLING_HW_NS_DELAY,
                     CACHE_CLK_STOP_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, EQ_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CACHECLKSTOP_TIMEOUT().set_EQCPLTSTAT(l_data64),
                "Cache Clock Stop Timeout");

    FAPI_DBG("Check cache clocks stopped");
    FAPI_TRY(getScom(i_target, EQ_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & i_select_regions) == 0),
                fapi2::PMPROC_CACHECLKSTOP_FAILED().set_EQCLKSTAT(l_data64),
                "Cache Clock Stop Failed");
    FAPI_DBG("Cache clocks stopped now");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]");
    FAPI_TRY(putScom(i_target, EQ_CPLT_CTRL1_OR, MASK_SET(3)));

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]");
    FAPI_TRY(putScom(i_target, EQ_CPLT_CTRL1_OR, i_select_regions));

    // -------------------------------
    // Disable VDM
    // -------------------------------

    if (l_attr_vdm_enable == fapi2::ENUM_ATTR_VDM_ENABLE_ON)
    {
        FAPI_DBG("Drop vdm enable via QPPM_VDMCR[0]");
        FAPI_TRY(putScom(i_target, EQ_PPM_VDMCR_CLEAR, MASK_SET(0)));
    }

    // -------------------------------
    // Shutdown edram
    // -------------------------------
    // QCCR[0/4] EDRAM_ENABLE_DC
    // QCCR[1/5] EDRAM_VWL_ENABLE_DC
    // QCCR[2/6] L3_EX0/1_EDRAM_VROW_VBLH_ENABLE_DC
    // QCCR[3/7] EDRAM_VPP_ENABLE_DC

    if (i_select_regions & p9hcd::CLK_REGION_EX0_REFR)
    {
        FAPI_DBG("Sequence EX0 EDRAM disables via QPPM_QCCR[0-3]");
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(3)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(2)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(1)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(0)));
    }

    if (i_select_regions & p9hcd::CLK_REGION_EX1_REFR)
    {
        FAPI_DBG("Sequence EX1 EDRAM disables via QPPM_QCCR[4-7]");
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(7)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(6)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(5)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(4)));
    }

    // -------------------------------
    // Update QSSR and STOP history
    // -------------------------------

    FAPI_DBG("Set cache as stopped in QSSR");
    FAPI_TRY(putScom(l_chip, PU_OCB_OCI_QSSR_OR,
                     BIT64(l_attr_chip_unit_pos + 14)));

    FAPI_DBG("Set cache as stopped in STOP history register");
    FAPI_TRY(putScom(i_target, EQ_PPM_SSHSRC, BIT64(0)));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_cache_stopclocks");
    return fapi2::current_err;
}
<commit_msg>Istep4: clean up istep4 todo items and mark them with RTC<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/cache/p9_hcd_cache_stopclocks.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file  p9_hcd_cache_stopclocks.C
/// @brief Quad Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@us.ibm.com>
// *HWP Backup HWP Owner   : Greg Still     <stillgs@us.ibm.com>
// *HWP FW Owner           : Sangeetha T S  <sangeet2@in.ibm.com>
// *HWP Team               : PM
// *HWP Consumed by        : HB:PERV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include <p9_common_clk_ctrl_state.H>
#include "p9_hcd_l2_stopclocks.H"
#include "p9_hcd_cache_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_CACHE_STOPCLOCKS_CONSTANTS
{
    CACHE_CLK_STOP_POLLING_HW_NS_DELAY     = 10000,
    CACHE_CLK_STOP_POLLING_SIM_CYCLE_DELAY = 320000
};

//------------------------------------------------------------------------------
// Procedure: Quad Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_cache_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_EQ>& i_target,
    const p9hcd::P9_HCD_CLK_CTRL_CONSTANTS      i_select_regions,
    const p9hcd::P9_HCD_EX_CTRL_CONSTANTS       i_select_ex)
{
    FAPI_INF(">>p9_hcd_cache_stopclocks: regions[%016llx] ex[%d]",
             i_select_regions, i_select_ex);
    fapi2::ReturnCode                              l_rc;
    fapi2::buffer<uint64_t>                        l_data64;
    fapi2::buffer<uint64_t>                        l_temp64;
    uint64_t                                       l_l3mask_pscom = 0;
    uint32_t                                       l_loops1ms;
    uint8_t                                        l_attr_chip_unit_pos = 0;
    uint8_t                                        l_attr_vdm_enable;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys;
    auto l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLE,    l_sys,
                           l_attr_vdm_enable));
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_perv,
                           l_attr_chip_unit_pos));
//  l_attr_chip_unit_pos = l_attr_chip_unit_pos - p9hcd::PERV_TO_QUAD_POS_OFFSET;
    l_attr_chip_unit_pos = l_attr_chip_unit_pos - 0x10;

    if (i_select_regions & p9hcd::CLK_REGION_EX0_L3)
    {
        l_l3mask_pscom |= (BIT64(4) | BIT64(6) | BIT64(8));
    }

    if (i_select_regions & p9hcd::CLK_REGION_EX1_L3)
    {
        l_l3mask_pscom |= (BIT64(5) | BIT64(7) | BIT64(9));
    }

    // -----------------------------
    // Prepare to stop cache clocks
    // -----------------------------

    FAPI_DBG("Check PM_RESET_STATE_INDICATOR via GPMMR[15]");
    FAPI_TRY(getScom(i_target, EQ_PPM_GPMMR_SCOM, l_data64));

    if (!l_data64.getBit<15>())
    {
        FAPI_DBG("Gracefully turn off power management, if fail, continue anyways");
        /// @todo RTC158181 suspend_pm()
    }

    FAPI_DBG("Check cache clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_EQ>(i_target);

    if (l_rc)
    {
        FAPI_INF("Clock controller of this cache chiplet is inaccessible, return");
        goto fapi_try_exit;
    }

    FAPI_DBG("Check PERV clock status for access to CME via CLOCK_STAT[4]");
    FAPI_TRY(getScom(i_target, EQ_CLOCK_STAT_SL, l_data64));

    FAPI_DBG("Check PERV fence status for access to CME via CPLT_CTRL1[4]");
    FAPI_TRY(getScom(i_target, EQ_CPLT_CTRL1, l_temp64));

    if (l_data64.getBit<4>() == 0 && l_temp64.getBit<4>() == 0)
    {
        /// @todo RTC158181 disable l2 snoop? disable lco? assert refresh quiesce?
        FAPI_DBG("Assert L3 pscom masks via RING_FENCE_MASK_LATCH_REG[4-9]");
        FAPI_TRY(putScom(i_target, EQ_RING_FENCE_MASK_LATCH_REG, l_l3mask_pscom));
    }

    FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]");
    FAPI_TRY(putScom(i_target, EQ_NET_CTRL0_WOR, MASK_SET(18)));

    // -------------------------------
    // Stop L2 clocks
    // -------------------------------

    if (i_select_ex)
        FAPI_EXEC_HWP(fapi2::current_err,
                      p9_hcd_l2_stopclocks,
                      i_target, i_select_ex);

    // -------------------------------
    // Stop cache clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, EQ_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop cache clocks via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD  |
                i_select_regions     |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, EQ_CLK_REGION, l_data64));

    FAPI_DBG("Poll for cache clocks stopped via CPLT_STAT0[8]");
    l_loops1ms = 1E6 / CACHE_CLK_STOP_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CACHE_CLK_STOP_POLLING_HW_NS_DELAY,
                     CACHE_CLK_STOP_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, EQ_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CACHECLKSTOP_TIMEOUT().set_EQCPLTSTAT(l_data64),
                "Cache Clock Stop Timeout");

    FAPI_DBG("Check cache clocks stopped");
    FAPI_TRY(getScom(i_target, EQ_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & i_select_regions) == 0),
                fapi2::PMPROC_CACHECLKSTOP_FAILED().set_EQCLKSTAT(l_data64),
                "Cache Clock Stop Failed");
    FAPI_DBG("Cache clocks stopped now");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]");
    FAPI_TRY(putScom(i_target, EQ_CPLT_CTRL1_OR, MASK_SET(3)));

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]");
    FAPI_TRY(putScom(i_target, EQ_CPLT_CTRL1_OR, i_select_regions));

    // -------------------------------
    // Disable VDM
    // -------------------------------

    if (l_attr_vdm_enable == fapi2::ENUM_ATTR_VDM_ENABLE_ON)
    {
        FAPI_DBG("Drop vdm enable via QPPM_VDMCR[0]");
        FAPI_TRY(putScom(i_target, EQ_PPM_VDMCR_CLEAR, MASK_SET(0)));
    }

    // -------------------------------
    // Shutdown edram
    // -------------------------------
    // QCCR[0/4] EDRAM_ENABLE_DC
    // QCCR[1/5] EDRAM_VWL_ENABLE_DC
    // QCCR[2/6] L3_EX0/1_EDRAM_VROW_VBLH_ENABLE_DC
    // QCCR[3/7] EDRAM_VPP_ENABLE_DC

    if (i_select_regions & p9hcd::CLK_REGION_EX0_REFR)
    {
        FAPI_DBG("Sequence EX0 EDRAM disables via QPPM_QCCR[0-3]");
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(3)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(2)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(1)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(0)));
    }

    if (i_select_regions & p9hcd::CLK_REGION_EX1_REFR)
    {
        FAPI_DBG("Sequence EX1 EDRAM disables via QPPM_QCCR[4-7]");
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(7)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(6)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(5)));
        FAPI_TRY(putScom(i_target, EQ_QPPM_QCCR_WCLEAR, MASK_SET(4)));
    }

    // -------------------------------
    // Update QSSR and STOP history
    // -------------------------------

    FAPI_DBG("Set cache as stopped in QSSR");
    FAPI_TRY(putScom(l_chip, PU_OCB_OCI_QSSR_OR,
                     BIT64(l_attr_chip_unit_pos + 14)));

    FAPI_DBG("Set cache as stopped in STOP history register");
    FAPI_TRY(putScom(i_target, EQ_PPM_SSHSRC, BIT64(0)));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_cache_stopclocks");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file bcw_load_ddr4.C
/// @brief Run and manage the DDR4 bcw loading
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mc_scom_addresses.H>

#include <generic/memory/lib/utils/c_str.H>
#include <lib/utils/conversions.H>
#include <lib/eff_config/timing.H>
#include <lib/ccs/ccs.H>
#include <lib/dimm/bcw_load_ddr4.H>
#include <lib/dimm/ddr4/control_word_ddr4.H>
#include <lib/dimm/ddr4/data_buffer_ddr4.H>
#include <lib/mss_attribute_accessors.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;

using fapi2::FAPI2_RC_SUCCESS;

namespace mss
{

///
/// @brief Perform the bcw_load_ddr4 operations - TARGET_TYPE_DIMM specialization
/// @param[in] i_target a DIMM target
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode bcw_load_ddr4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
                                 std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& io_inst)
{
    FAPI_INF("bcw_load_ddr4 %s", mss::c_str(i_target) );

    // Per DDR4BC01
    uint64_t l_tDLLK = 0;
    FAPI_TRY( tdllk(i_target, l_tDLLK), "Failed to get tDLLK for %s", mss::c_str(i_target) );

    {
        static const std::vector< cw_data > l_bcw_4bit_data =
        {
            // function space #, bcw #, attribute accessor, timing delay
            { FUNC_SPACE_0,  DQ_RTT_NOM_CW,         eff_dimm_ddr4_bc00,  mss::tmrc() },
            { FUNC_SPACE_0,  DQ_RTT_WR_CW,          eff_dimm_ddr4_bc01,  mss::tmrc() },
            { FUNC_SPACE_0,  DQ_RTT_PARK_CW,        eff_dimm_ddr4_bc02,  mss::tmrc() },
            { FUNC_SPACE_0,  DQ_DRIVER_CW,          eff_dimm_ddr4_bc03,  mss::tmrc() },
            { FUNC_SPACE_0,  MDQ_RTT_CW,            eff_dimm_ddr4_bc04,  mss::tmrc() },
            { FUNC_SPACE_0,  MDQ_DRIVER_CW,         eff_dimm_ddr4_bc05,  mss::tmrc() },
            { FUNC_SPACE_0,  RANK_PRESENCE_CW,      eff_dimm_ddr4_bc07,  mss::tmrc() },
            { FUNC_SPACE_0,  RANK_SELECTION_CW,     eff_dimm_ddr4_bc08,  mss::tmrc() },
            { FUNC_SPACE_0,  POWER_SAVING_CW,       eff_dimm_ddr4_bc09,  mss::tmrc() },
            { FUNC_SPACE_0,  OPERATING_SPEED,       eff_dimm_ddr4_bc0a,  l_tDLLK     },
            { FUNC_SPACE_0,  VOLT_AND_SLEW_RATE_CW, eff_dimm_ddr4_bc0b,  mss::tmrc() },
            { FUNC_SPACE_0,  BUFF_TRAIN_MODE_CW,    eff_dimm_ddr4_bc0c,  mss::tmrc() },
            { FUNC_SPACE_0,  LDQ_OPERATION_CW,      eff_dimm_ddr4_bc0d,  mss::tmrc() },
            { FUNC_SPACE_0,  PARITY_CW,             eff_dimm_ddr4_bc0e,  mss::tmrc() },
            { FUNC_SPACE_0,  ERROR_STATUS_CW,       eff_dimm_ddr4_bc0f,  mss::tmrc() },
        };

        // This initialization may be vendor specific.  We might need a different
        // sequence for Montage vs. IDT for example.
        // We'll know better once we initialize more than one...

        //
        // IDT BCW init
        //

        // We set the 4-bit buffer control words first (they live in function space 0
        // hw is supposed to default to function space 0 but Just.In.Case.
        FAPI_TRY( ddr4::function_space_select<0>(i_target, io_inst) );
        FAPI_TRY( control_word_engine<BCW_4BIT>(i_target, l_bcw_4bit_data, io_inst) );

        // We set our 8-bit buffer control words but have to switch function space
        // number for different control words.  So it doesn't fit cleanly into a
        // vector like the 4-bit buffer control words that are all in function space 0
        // (feels like we should be initializing more control word....)
        {
            cw_data l_data(FUNC_SPACE_6, BUFF_TRAIN_CONFIG_CW, eff_dimm_ddr4_f6bc4x, mss::tmrc());
            FAPI_TRY( ddr4::function_space_select<6>(i_target, io_inst) );
            FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst) );
        }

        {
            cw_data l_data(FUNC_SPACE_5, DRAM_VREF_CW, eff_dimm_ddr4_f5bc6x, mss::tmrc());
            FAPI_TRY( ddr4::function_space_select<5>(i_target, io_inst) );
            FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst) );
        }

        // Its recommended to always return to the function space
        // "pointer" back to 0 so we always know where we are starting from
        FAPI_TRY( ddr4::function_space_select<0>(i_target, io_inst) );
    }

fapi_try_exit:
    return fapi2::current_err;
}

} // namespace
<commit_msg>L3 draminit and mss_lib<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/dimm/bcw_load_ddr4.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file bcw_load_ddr4.C
/// @brief Run and manage the DDR4 bcw loading
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mc_scom_addresses.H>

#include <generic/memory/lib/utils/c_str.H>
#include <lib/utils/conversions.H>
#include <lib/eff_config/timing.H>
#include <lib/ccs/ccs.H>
#include <lib/dimm/bcw_load_ddr4.H>
#include <lib/dimm/ddr4/control_word_ddr4.H>
#include <lib/dimm/ddr4/data_buffer_ddr4.H>
#include <lib/mss_attribute_accessors.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;

using fapi2::FAPI2_RC_SUCCESS;

namespace mss
{

///
/// @brief Perform the bcw_load_ddr4 operations
/// @param[in] i_target a DIMM target
/// @param[in,out] io_inst a vector of CCS instructions we should add to
/// @return FAPI2_RC_SUCCESS if and only if ok
///
fapi2::ReturnCode bcw_load_ddr4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
                                 std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> >& io_inst)
{
    FAPI_INF("bcw_load_ddr4 %s", mss::c_str(i_target) );

    // Per DDR4BC01
    uint64_t l_tDLLK = 0;
    FAPI_TRY( tdllk(i_target, l_tDLLK), "Failed to get tDLLK for %s in bcw_load_ddr4", mss::c_str(i_target) );

    {
        static const std::vector< cw_data > l_bcw_4bit_data =
        {
            // function space #, bcw #, attribute accessor, timing delay
            { FUNC_SPACE_0,  DQ_RTT_NOM_CW,         eff_dimm_ddr4_bc00,  mss::tmrc() },
            { FUNC_SPACE_0,  DQ_RTT_WR_CW,          eff_dimm_ddr4_bc01,  mss::tmrc() },
            { FUNC_SPACE_0,  DQ_RTT_PARK_CW,        eff_dimm_ddr4_bc02,  mss::tmrc() },
            { FUNC_SPACE_0,  DQ_DRIVER_CW,          eff_dimm_ddr4_bc03,  mss::tmrc() },
            { FUNC_SPACE_0,  MDQ_RTT_CW,            eff_dimm_ddr4_bc04,  mss::tmrc() },
            { FUNC_SPACE_0,  MDQ_DRIVER_CW,         eff_dimm_ddr4_bc05,  mss::tmrc() },
            { FUNC_SPACE_0,  RANK_PRESENCE_CW,      eff_dimm_ddr4_bc07,  mss::tmrc() },
            { FUNC_SPACE_0,  RANK_SELECTION_CW,     eff_dimm_ddr4_bc08,  mss::tmrc() },
            { FUNC_SPACE_0,  POWER_SAVING_CW,       eff_dimm_ddr4_bc09,  mss::tmrc() },
            { FUNC_SPACE_0,  OPERATING_SPEED,       eff_dimm_ddr4_bc0a,  l_tDLLK     },
            { FUNC_SPACE_0,  VOLT_AND_SLEW_RATE_CW, eff_dimm_ddr4_bc0b,  mss::tmrc() },
            { FUNC_SPACE_0,  BUFF_TRAIN_MODE_CW,    eff_dimm_ddr4_bc0c,  mss::tmrc() },
            { FUNC_SPACE_0,  LDQ_OPERATION_CW,      eff_dimm_ddr4_bc0d,  mss::tmrc() },
            { FUNC_SPACE_0,  PARITY_CW,             eff_dimm_ddr4_bc0e,  mss::tmrc() },
            { FUNC_SPACE_0,  ERROR_STATUS_CW,       eff_dimm_ddr4_bc0f,  mss::tmrc() },
        };

        // This initialization may be vendor specific.  We might need a different
        // sequence for Montage vs. IDT for example.
        // We'll know better once we initialize more than one...

        //
        // IDT BCW init
        //

        // We set the 4-bit buffer control words first (they live in function space 0
        // hw is supposed to default to function space 0 but Just.In.Case.
        FAPI_TRY( ddr4::function_space_select<0>(i_target, io_inst), "Failed function space select 0", mss::c_str(i_target));
        FAPI_TRY( control_word_engine<BCW_4BIT>(i_target, l_bcw_4bit_data, io_inst) , "Failed control_word_engine",
                  mss::c_str(i_target));

        // We set our 8-bit buffer control words but have to switch function space
        // number for different control words.  So it doesn't fit cleanly into a
        // vector like the 4-bit buffer control words that are all in function space 0
        // (feels like we should be initializing more control word....)
        {
            cw_data l_data(FUNC_SPACE_6, BUFF_TRAIN_CONFIG_CW, eff_dimm_ddr4_f6bc4x, mss::tmrc());
            FAPI_TRY( ddr4::function_space_select<6>(i_target, io_inst), "Failed function space select 6", mss::c_str(i_target) );
            FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst), "Failed control_word_engine",
                      mss::c_str(i_target) );
        }

        {
            cw_data l_data(FUNC_SPACE_5, DRAM_VREF_CW, eff_dimm_ddr4_f5bc6x, mss::tmrc());
            FAPI_TRY( ddr4::function_space_select<5>(i_target, io_inst), "Failed function space select 5", mss::c_str(i_target) );
            FAPI_TRY( control_word_engine<BCW_8BIT>(i_target, l_data, io_inst), "Failed control_word_engine",
                      mss::c_str(i_target) );
        }

        // Its recommended to always return to the function space
        // "pointer" back to 0 so we always know where we are starting from
        FAPI_TRY( ddr4::function_space_select<0>(i_target, io_inst), "Error in bcw_load_ddr4 for function space select 0" );
    }

fapi_try_exit:
    return fapi2::current_err;
}

} // namespace
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_cpu_special_wakeup_core.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
///  @file          :    p9_cpu_special_wakeup_core.C
///  @brief         :    HWP to perform special wakeup of a core

// *HWP HW Owner    :    Greg Still <stillgs@us.ibm.com>
// *HWP FW Owner    :    Prem S Jha <premjha2@in.ibm.com>
// *HWP Team        :    PM
// *HWP Level       :    2
// *HWP Consumed by :    OCC:FSP:HOST:CRO

// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include <p9_cpu_special_wakeup.H>
#include <p9_cpu_special_wakeup_lib.H>

/// ----------------------------------------------------------------------------
///
/// @brief       Sets a normal core chiplet into special wakeup state.
///
fapi2::ReturnCode p9_cpu_special_wakeup_core(
    const fapi2::Target < fapi2::TARGET_TYPE_CORE>& i_target,
    const p9specialWakeup::PROC_SPCWKUP_OPS i_operation,
    const p9specialWakeup::PROC_SPCWKUP_ENTITY i_entity )
{
    FAPI_DBG("> p9_cpu_special_wakeup_core");
    FAPI_TRY(_special_wakeup<fapi2::TARGET_TYPE_CORE> (
                 i_target,
                 i_operation,
                 i_entity ));

fapi_try_exit:
    FAPI_INF("< p9_cpu_special_wakeup_core" );
    return fapi2::current_err;
}

// -----------------------------------------------------------------------------

fapi2::ReturnCode spwkup_deassert(  const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_chipletTarget,
                                    const ProcessingValues_t i_processing_info,
                                    p9specialWakeup::SpecialWakeUpMsg i_msgId )
{
    FAPI_INF("> spwkup_deassert Core" );

    uint64_t l_address = i_processing_info.spwkup_address[0];
    FAPI_TRY(_spwkup_deassert(i_chipletTarget, l_address, i_msgId));

fapi_try_exit:
    FAPI_INF("< spwkup_deassert Core" );
    return fapi2::current_err;
}

// -----------------------------------------------------------------------------
///
/// @brief Set addresses for a core target type
///
template<>
fapi2::ReturnCode set_addresses(const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target,
                                ProcessingValues_t& i_structure,
                                const uint32_t i_entity )
{
    FAPI_INF("> set_addresses for Core");

    uint8_t l_core_num = 0;

    FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS, i_target, l_core_num),
             "fapiGetAttribute of ATTR_CHIP_UNIT_POS");

    FAPI_DBG("Core %d being procesed.", l_core_num);

    i_structure.spwkup_address[0]  = SPCWKUP_ADDR[i_entity][p9specialWakeup::SPW_CORE]
                                     + 0x01000000 * l_core_num;
    i_structure.history_address[0] = SPCWKUP_HIST_ADDR[i_entity][p9specialWakeup::SPW_CORE]
                                     + 0x01000000 * l_core_num;
    i_structure.netctrl_address[0] = SPCWKUP_NETCTRL0_ADDR[p9specialWakeup::SPW_CORE]
                                     + 0x01000000 * l_core_num;
    i_structure.gpmmr_address[0] = SPCWKUP_GPMMR_ADDR[p9specialWakeup::SPW_CORE]
                                   + 0x01000000 * l_core_num;
    i_structure.num_addresses = 1;

    FAPI_DBG("i_structure.spwkup_address[%d]  = 0x%08llX \n "
             "i_structure.history_address[%d] = 0x%08llX \n "
             "i_structure.netctrl_address[%d] = 0x%08llX \n "
             "i_structure.gpmmr_addresss[%d]  = 0x%08llX \n " ,
             0, i_structure.spwkup_address[0],
             0, i_structure.history_address[0],
             0, i_structure.netctrl_address[0],
             0, i_structure.gpmmr_address[0]);

fapi_try_exit:
    FAPI_INF("< set_addresses for Core");
    return fapi2::current_err;
}
<commit_msg>PM: Level3 Special Wakeup Hardware Procedure<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/pm/p9_cpu_special_wakeup_core.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
///  @file          :    p9_cpu_special_wakeup_core.C
///  @brief         :    HWP to perform special wakeup of a core

// *HWP HW Owner    :    Greg Still <stillgs@us.ibm.com>
// *HWP FW Owner    :    Prem S Jha <premjha2@in.ibm.com>
// *HWP Team        :    PM
// *HWP Level       :    3
// *HWP Consumed by :    OCC:FSP:HOST:CRO

// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#include <p9_cpu_special_wakeup.H>
#include <p9_cpu_special_wakeup_lib.H>
#include <p9_ppe_defs.H>
#include <p9_ppe_utils.H>

fapi2::ReturnCode collectCoreTimeoutFailInfo( const fapi2::Target < fapi2::TARGET_TYPE_CORE>& i_target,
        ProcessingValues_t i_processing_info );

/// ----------------------------------------------------------------------------
///
/// @brief      Sets a normal core chiplet into special wakeup state.
/// @param[in]  i_target     core target
/// @param[in]  i_operation  Special Wakeup Operation i.e. assert or deassert
/// @param[in]  i_entity     entity to be considered for special wakeup.
/// @return     fapi2 return code.
///
fapi2::ReturnCode p9_cpu_special_wakeup_core(
    const fapi2::Target < fapi2::TARGET_TYPE_CORE>& i_target,
    const p9specialWakeup::PROC_SPCWKUP_OPS i_operation,
    const p9specialWakeup::PROC_SPCWKUP_ENTITY i_entity )
{
    FAPI_INF(">> p9_cpu_special_wakeup_core");
    fapi2::ReturnCode l_rc;
    uint8_t l_spWakeUpInProg = 0;
    ProcessingValues_t l_processing_info;
    auto l_eqTarget = i_target.getParent<fapi2::TARGET_TYPE_EQ>();

    FAPI_ATTR_GET( fapi2::ATTR_CORE_INSIDE_SPECIAL_WAKEUP,
                   i_target,
                   l_spWakeUpInProg );

    // A special wakeup is already in progress. In all likelyhood, a special
    // wakeup has timed out and we are in FFDC collection path. During this
    // FFDC collection, we SCOMed a register which itself needs a special
    // wakeup.

    if( l_spWakeUpInProg )
    {
        FAPI_INF("exiting core recurssion");
        return fapi2::FAPI2_RC_SUCCESS;
    }

    p9specialWakeup::blockWakeupRecurssion( l_eqTarget, p9specialWakeup::BLOCK );

    l_rc = _special_wakeup<fapi2::TARGET_TYPE_CORE> (
               i_target,
               i_operation,
               i_entity,
               l_processing_info );

    if( l_rc == (uint32_t)fapi2::RC_INTERNAL_SPCWKUP_TIMEOUT )
    {
        collectCoreTimeoutFailInfo( i_target, l_processing_info );
    }

    p9specialWakeup::blockWakeupRecurssion( l_eqTarget, p9specialWakeup::UNBLOCK );

    FAPI_INF("<< p9_cpu_special_wakeup_core" );
    return fapi2::current_err;
}

// -----------------------------------------------------------------------------

///
/// @brief      Collect FFDC for EQ Special Wakeup timeout
/// @param[in]  i_target     core target
/// @param[in]  i_operation  info pertaining to special wakeup
/// @return     fapi2 return code.
///
fapi2::ReturnCode collectCoreTimeoutFailInfo( const fapi2::Target < fapi2::TARGET_TYPE_CORE>& i_target,
        ProcessingValues_t i_processing_info )
{
    FAPI_INF(">> collectCoreTimeoutFailInfo" );
    fapi2::buffer<uint64_t> l_CPMMR;
    fapi2::buffer<uint64_t> l_GPMMR;
    fapi2::buffer<uint64_t> l_spWakeupRegVal;
    fapi2::buffer<uint64_t> l_histRegVal;

    fapi2::getScom( i_target, C_CPPM_CPMMR, l_CPMMR );
    fapi2::getScom( i_target, C_PPM_GPMMR_SCOM, l_GPMMR );
    fapi2::getScom( i_target, i_processing_info.spwkup_address[0], l_spWakeupRegVal );
    fapi2::getScom( i_target, i_processing_info.history_address[0], l_histRegVal );
    fapi2::Target < fapi2::TARGET_TYPE_EX> parentExTgt = i_target.getParent <fapi2::TARGET_TYPE_EX>();
    uint8_t l_exPos = 0;
    FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS, parentExTgt, l_exPos );

    std::vector<uint64_t> l_cmeBaseAddress;
    std::vector<uint64_t> l_sgpeBaseAddress;
    l_sgpeBaseAddress.push_back( SGPE_BASE_ADDRESS );
    l_cmeBaseAddress.push_back( getCmeBaseAddress( l_exPos ) );

    FAPI_ASSERT( false ,
                 fapi2::SPCWKUP_CORE_TIMEOUT().
                 set_POLLCOUNT( i_processing_info.poll_count ).
                 set_SP_WKUP_REG_VALUE( l_spWakeupRegVal ).
                 set_HISTORY_VALUE( l_histRegVal ).
                 set_ENTITY( i_processing_info.entity ).
                 set_CPMMR( l_CPMMR ).
                 set_GPMMR( l_GPMMR ).
                 set_EQ_TARGET( i_target.getParent <fapi2::TARGET_TYPE_EQ>() ).
                 set_EX_TARGET( parentExTgt ).
                 set_CORE_TARGET( i_target ).
                 set_PROC_CHIP_TARGET( i_processing_info.procTgt ).
                 set_CME_BASE_ADDRESS( l_cmeBaseAddress ).
                 set_SGPE_BASE_ADDRESS( l_sgpeBaseAddress ).
                 set_CME_STATE_MODE( SNAPSHOT ).
                 set_SGPE_STATE_MODE( XIRS ),
                 "Timed Out In Setting Core Special Wakeup");
fapi_try_exit:
    FAPI_INF("<< collectCoreTimeoutFailInfo" );
    return fapi2::current_err;
}
// -----------------------------------------------------------------------------
/// @param[in]  i_chipletTarget     core target
/// @param[in]  i_processing_info   struct storing processing info
/// @param[in]  i_msgId             Id pertaining to debug message string.
/// @return     fapi2 return code.
fapi2::ReturnCode spwkup_deassert(  const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_chipletTarget,
                                    const ProcessingValues_t i_processing_info,
                                    p9specialWakeup::SpecialWakeUpMsg i_msgId )
{
    FAPI_INF("> spwkup_deassert Core" );

    uint64_t l_address = i_processing_info.spwkup_address[0];
    FAPI_TRY(_spwkup_deassert(i_chipletTarget, l_address, i_msgId));

fapi_try_exit:
    FAPI_INF("< spwkup_deassert Core" );
    return fapi2::current_err;
}

// -----------------------------------------------------------------------------
///
/// @brief Set addresses for a core target type
/// @param[in]  i_target         core target
/// @param[in]  i_structure      struct storing processing info
/// @param[in]  i_entity         entity to be considered for special wakeup.
/// @return fapi2 return code.
///
template<>
fapi2::ReturnCode set_addresses(const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target,
                                ProcessingValues_t& i_structure,
                                const uint32_t i_entity )
{
    FAPI_INF(">> set_addresses for Core");

    uint8_t l_core_num = 0;

    FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CHIP_UNIT_POS, i_target, l_core_num),
             "fapiGetAttribute of ATTR_CHIP_UNIT_POS");

    FAPI_DBG("Core %d being procesed.", l_core_num);

    i_structure.spwkup_address[0]  = SPCWKUP_ADDR[i_entity][p9specialWakeup::SPW_CORE]
                                     + 0x01000000 * l_core_num;
    i_structure.history_address[0] = SPCWKUP_HIST_ADDR[i_entity][p9specialWakeup::SPW_CORE]
                                     + 0x01000000 * l_core_num;
    i_structure.netctrl_address[0] = SPCWKUP_NETCTRL0_ADDR[p9specialWakeup::SPW_CORE]
                                     + 0x01000000 * l_core_num;
    i_structure.gpmmr_address[0] = SPCWKUP_GPMMR_ADDR[p9specialWakeup::SPW_CORE]
                                   + 0x01000000 * l_core_num;
    i_structure.num_addresses = 1;

    FAPI_DBG("i_structure.spwkup_address[%d]  = 0x%08llX \n "
             "i_structure.history_address[%d] = 0x%08llX \n "
             "i_structure.netctrl_address[%d] = 0x%08llX \n "
             "i_structure.gpmmr_addresss[%d]  = 0x%08llX \n " ,
             0, i_structure.spwkup_address[0],
             0, i_structure.history_address[0],
             0, i_structure.netctrl_address[0],
             0, i_structure.gpmmr_address[0]);

fapi_try_exit:
    FAPI_INF("<< set_addresses for Core");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>#ifndef RECURSE_HPP
#define RECURSE_HPP

#include <QCoreApplication>
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QHash>
#include <QStringBuilder>
#include <QVector>
#include <QSharedPointer>
#include <functional>

using std::function;
using std::bind;
using std::ref;

#include "request.hpp"
#include "response.hpp"

typedef function<void(Request &request, Response &response, function<void()> next)> next_f;

//!
//! \brief The Recurse class
//! main class of the app
//!
class Recurse : public QObject
{
public:

    Recurse(int & argc, char ** argv, QObject *parent = NULL);
    ~Recurse();

    bool listen(quint64 port, QHostAddress address = QHostAddress::Any);
    void use(next_f next);
    void end(Request &request, Response &response);

private:
    QCoreApplication app;
    QTcpServer m_tcp_server;

    quint64 m_port;
    QVector<next_f> m_middleware;
    void http_parse(Request &request);
    QString create_reply(Response &response);
    QRegExp httpRx = QRegExp("^(?=[A-Z]).* \\/.* HTTP\\/[0-9]\\.[0-9]\\r\\n");

    struct Client {
        Request request;
        Response response;
    };

    void m_next(QSharedPointer<Client> client, int current_middleware);
};

Recurse::Recurse(int & argc, char ** argv, QObject *parent) : app(argc, argv)
{
    Q_UNUSED(parent);
};

Recurse::~Recurse()
{

};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! \param port tcp server port
//! \param address tcp server listening address
//!
//! \return true on success
//!
bool Recurse::listen(quint64 port, QHostAddress address)
{
    m_port = port;
    int bound = m_tcp_server.listen(address, port);
    if (!bound)
        return false;

    connect(&m_tcp_server, &QTcpServer::newConnection, [this] {
        qDebug() << "client connected";

        QSharedPointer<Client> client = QSharedPointer<Client>::create();
        client->request.socket = m_tcp_server.nextPendingConnection();

        connect(client->request.socket, &QTcpSocket::readyRead, [this, client] {
            client->request.data += client->request.socket->readAll();
            qDebug() << "client request: " << client->request.data;

            http_parse(client->request);

            if (client->request.body_length < client->request.header["content-length"].toLongLong())
                    return;

            if (m_middleware.count() > 0) {
                client->response.end = bind(&Recurse::end, this, std::ref(client->request), std::ref(client->response));

                m_middleware[0](
                    client->request,
                    client->response,
                    bind(&Recurse::m_next, this, client, 0));
            }
        });
    });

    return app.exec();
};

//!
//! \brief Recurse::m_next
//! call next middleware
//!
void Recurse::m_next(QSharedPointer<Client> client, int current_middleware)
{
    qDebug() << "calling next:" << current_middleware << " num:" << m_middleware.size();

    if (++current_middleware >= m_middleware.size()) {
        return;
    };

    m_middleware[current_middleware](
        client->request,
        client->response,
        bind(&Recurse::m_next, this, client, current_middleware));
};

//!
//! \brief Recurse::use
//! add new middleware
//!
//! \param f middleware function that will be called later
//!
void Recurse::use(next_f f)
{
    m_middleware.push_back(f);
};

//!
//! \brief Recurse::end
//! final function to be called for creating/sending response
//! \param request
//! \param response
//!
void Recurse::end(Request &request, Response &response)
{
    qDebug() << "calling end with:" << response.body();

    QString header;

    response.method = request.method;
    response.proto = request.proto;

    if (response.status() == 0)
        response.status(200);

    QString reply = create_reply(response);

    qDebug() << "create reply" << reply;

    // send response to the client
    qint64 check = request.socket->write(
                reply.toStdString().c_str(),
                reply.size());

    qDebug() << "socket write debug:" << check;
    request.socket->close();
};

//!
//! \brief Recurse::http_parse
//! parse http data
//!
//! \param data reference to data received from the tcp connection
//!
void Recurse::http_parse(Request &request)
{
    // if no header is present, just append all data to request.body
    if (!request.data.contains(httpRx)) {
        request.body.append(request.data);
        return;
    }

    QStringList data_list = request.data.split("\r\n");
    bool is_body = false;

    for (int i = 0; i < data_list.size(); ++i) {
        if (is_body) {
            request.body.append(data_list.at(i));
            request.body_length += request.body.size();
            continue;
        }

        QStringList entity_item = data_list.at(i).split(":");

        if (entity_item.length() < 2 && entity_item.at(0).size() < 1 && !is_body) {
            is_body = true;
            continue;
        }
        else if (i == 0 && entity_item.length() < 2) {
            QStringList first_line = entity_item.at(0).split(" ");
            request.method = first_line.at(0);
            request.url = first_line.at(1).trimmed();
            request.proto = first_line.at(2).trimmed();
            continue;
        }

        request.header[entity_item.at(0).toLower()] = entity_item.at(1).trimmed();
    }

    qDebug() << "request object populated: "
        << request.method << request.url << request.header << request.proto << request.body
        << request.body_length;
};

//!
//! \brief Recurse::create_reply
//! create response data for sending to client
//!
//! \param response reference to the Response instance
//!
QString Recurse::create_reply(Response &response)
{
    qDebug() << "response.header:" << response.header;

    qDebug() << __FUNCTION__ << response.body();

    QString data = response.proto % " " % QString::number(response.status()) % " "
        % response.http_codes[response.status()] % "\r\n";

    // set content length
    response.header["content-length"] = QString::number(response.body().size());

    // set content type if not set
    if (!response.header.contains("content-type"))
        response.header["content-type"] = "text/plain";

    // set custom header fields
    QHash<QString, QString>::const_iterator i;
    for (i = response.header.constBegin(); i != response.header.constEnd(); ++i)
        data += i.key() % ": " % i.value() % "\r\n";

    return data % "\r\n" % response.body() % "\r\n";
}

#endif // RECURSE_HPP
<commit_msg>replace qsharedpointer with plain pointer<commit_after>#ifndef RECURSE_HPP
#define RECURSE_HPP

#include <QCoreApplication>
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QHash>
#include <QStringBuilder>
#include <QVector>
#include <functional>

using std::function;
using std::bind;
using std::ref;

#include "request.hpp"
#include "response.hpp"

typedef function<void(Request &request, Response &response, function<void()> next)> next_f;

struct Client {
    Request request;
    Response response;
};

//!
//! \brief The Recurse class
//! main class of the app
//!
class Recurse : public QObject
{
public:

    Recurse(int & argc, char ** argv, QObject *parent = NULL);
    ~Recurse();

    bool listen(quint64 port, QHostAddress address = QHostAddress::Any);
    void use(next_f next);
    void end(Client *client);

private:
    QCoreApplication app;
    QTcpServer m_tcp_server;

    quint64 m_port;
    QVector<next_f> m_middleware;
    void http_parse(Request &request);
    QString create_reply(Response &response);
    QRegExp httpRx = QRegExp("^(?=[A-Z]).* \\/.* HTTP\\/[0-9]\\.[0-9]\\r\\n");

    Client *client;

    void m_next(Client *client, int current_middleware);
};

Recurse::Recurse(int & argc, char ** argv, QObject *parent) : app(argc, argv)
{
    Q_UNUSED(parent);
};

Recurse::~Recurse()
{

};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! \param port tcp server port
//! \param address tcp server listening address
//!
//! \return true on success
//!
bool Recurse::listen(quint64 port, QHostAddress address)
{
    m_port = port;
    int bound = m_tcp_server.listen(address, port);
    if (!bound)
        return false;

    connect(&m_tcp_server, &QTcpServer::newConnection, [this] {
        qDebug() << "client connected";

        auto client = new Client;
        client->request.socket = m_tcp_server.nextPendingConnection();

        connect(client->request.socket, &QTcpSocket::readyRead, [this, client] {

            client->request.data += client->request.socket->readAll();
            qDebug() << "client request: " << client->request.data;

            http_parse(client->request);

            if (client->request.body_length < client->request.header["content-length"].toLongLong())
                    return;

            if (m_middleware.count() > 0) {
                client->response.end = bind(&Recurse::end, this, client);

                m_middleware[0](
                    client->request,
                    client->response,
                    bind(&Recurse::m_next, this, client, 0));
            }
        });
    });

    return app.exec();
};

//!
//! \brief Recurse::m_next
//! call next middleware
//!
void Recurse::m_next(Client *client, int current_middleware)
{
    qDebug() << "calling next:" << current_middleware << " num:" << m_middleware.size();

    if (++current_middleware >= m_middleware.size()) {
        return;
    };

    m_middleware[current_middleware](
        client->request,
        client->response,
        bind(&Recurse::m_next, this, client, current_middleware));
};

//!
//! \brief Recurse::use
//! add new middleware
//!
//! \param f middleware function that will be called later
//!
void Recurse::use(next_f f)
{
    m_middleware.push_back(f);
};

//!
//! \brief Recurse::end
//! final function to be called for creating/sending response
//! \param request
//! \param response
//!
void Recurse::end(Client *client)
{

    QString header;

    Request &request = client->request;
    Response &response = client->response;

    qDebug() << "calling end with:" << response.body();

    response.method = request.method;
    response.proto = request.proto;

    if (response.status() == 0)
        response.status(200);

    QString reply = create_reply(response);

    qDebug() << "create reply" << reply;

    // send response to the client
    qint64 check = request.socket->write(
                reply.toStdString().c_str(),
                reply.size());

    qDebug() << "socket write debug:" << check;
    request.socket->close();

    delete client;
};

//!
//! \brief Recurse::http_parse
//! parse http data
//!
//! \param data reference to data received from the tcp connection
//!
void Recurse::http_parse(Request &request)
{
    // if no header is present, just append all data to request.body
    if (!request.data.contains(httpRx)) {
        request.body.append(request.data);
        return;
    }

    QStringList data_list = request.data.split("\r\n");
    bool is_body = false;

    for (int i = 0; i < data_list.size(); ++i) {
        if (is_body) {
            request.body.append(data_list.at(i));
            request.body_length += request.body.size();
            continue;
        }

        QStringList entity_item = data_list.at(i).split(":");

        if (entity_item.length() < 2 && entity_item.at(0).size() < 1 && !is_body) {
            is_body = true;
            continue;
        }
        else if (i == 0 && entity_item.length() < 2) {
            QStringList first_line = entity_item.at(0).split(" ");
            request.method = first_line.at(0);
            request.url = first_line.at(1).trimmed();
            request.proto = first_line.at(2).trimmed();
            continue;
        }

        request.header[entity_item.at(0).toLower()] = entity_item.at(1).trimmed();
    }

    qDebug() << "request object populated: "
        << request.method << request.url << request.header << request.proto << request.body
        << request.body_length;
};

//!
//! \brief Recurse::create_reply
//! create response data for sending to client
//!
//! \param response reference to the Response instance
//!
QString Recurse::create_reply(Response &response)
{
    qDebug() << "response.header:" << response.header;

    qDebug() << __FUNCTION__ << response.body();

    QString data = response.proto % " " % QString::number(response.status()) % " "
        % response.http_codes[response.status()] % "\r\n";

    // set content length
    response.header["content-length"] = QString::number(response.body().size());

    // set content type if not set
    if (!response.header.contains("content-type"))
        response.header["content-type"] = "text/plain";

    // set custom header fields
    QHash<QString, QString>::const_iterator i;
    for (i = response.header.constBegin(); i != response.header.constEnd(); ++i)
        data += i.key() % ": " % i.value() % "\r\n";

    return data % "\r\n" % response.body() % "\r\n";
}

#endif // RECURSE_HPP
<|endoftext|>


<commit_before>#ifndef FROG_GAMEOBJECT_HPP
#define FROG_GAMEOBJECT_HPP

#include "FROG/Transform.hpp"
#include "FROG/ComponentHolder.hpp"

#include <string>

namespace frog{

  /*!
   * GameObjects are main bricks of a scene.
   */
  class GameObject : virtual public ComponentHolder
  {
    //// attributes ////
  protected:
    GameObject * parent;

    //// operations ////
  public :

    std::shared_ptr<Transform> transform;

    GameObject(GameObject * parent = nullptr);

    virtual ~GameObject();

    /*!
     * @brief Adds components and properties by loading from a file
     * @param file XML file to extract data from
     */
    bool loadFromFile(const std::string& file);

    /*!
     * @brief Updates the gameobject.
     */
    virtual void update();

  };

}

#endif
<commit_msg>alias for std::shared_ptr<GameObject> -> PTR_GameObject<commit_after>#ifndef FROG_GAMEOBJECT_HPP
#define FROG_GAMEOBJECT_HPP

#include "FROG/Transform.hpp"
#include "FROG/ComponentHolder.hpp"

#include <memory>
#include <string>

namespace frog{

  /*!
   * GameObjects are main bricks of a scene.
   */
  class GameObject : virtual public ComponentHolder
  {

  public:
    typedef std::shared_ptr<GameObject> PTR_GameObject;

    //// attributes ////
  protected:
    GameObject * parent;

    //// operations ////
  public :

    std::shared_ptr<Transform> transform;

    GameObject(GameObject * parent = nullptr);

    virtual ~GameObject();

    /*!
     * @brief Adds components and properties by loading from a file
     * @param file XML file to extract data from
     */
    bool loadFromFile(const std::string& file);

    /*!
     * @brief Updates the gameobject.
     */
    virtual void update();

  };

}

#endif
<|endoftext|>


<commit_before>#ifndef VALUE_STORE_VALUESTORE_HPP_
#define VALUE_STORE_VALUESTORE_HPP_

#include <cassert>
#include <memory>
#include <string>
#include <vector>

#include <boost/optional.hpp>

namespace sm {
class ConstPropertyTree;
class PropertyTree;

namespace value_store {

template <typename T>
class ValueHandleImpl {
 public:
  virtual bool isUpdateable() const { return false; }
  virtual void update(T newValue) = 0;
  virtual T get() const = 0;
  virtual ~ValueHandleImpl(){}
};

template <typename T>
class ConstValueHandleImpl : public ValueHandleImpl<T> {
 public:
  ConstValueHandleImpl(T v) : v(v) {}
  virtual bool isUpdateable() const { return false; }
  virtual void update(T /*newValue*/) { assert(false); }
  virtual T get() const { return v; }
  virtual ~ConstValueHandleImpl() {}
 private:
  const T v;
};

template <typename T>
class ValueHandle {
 public:
  explicit ValueHandle(ValueHandleImpl<T> * pImpl) : impl(pImpl) { assert(pImpl); }
  ValueHandle(T v) : impl(new ConstValueHandleImpl<T>(v)){ }
  ValueHandle(ValueHandle && move) = default;
  ValueHandle() = default;
  ValueHandle & operator = (ValueHandle && move) = default;

  bool isUpdateable() const { return impl->isUpdateable(); }
  void update(T newValue) { impl->update(newValue); }
  T get() const { return impl->get(); }
  inline operator T () const { return get(); }

  bool empty() const { return !impl; }

  ValueHandleImpl<T> & getImplementation() { return *impl; }
 private:
  std::unique_ptr<ValueHandleImpl<T> > impl;
};

class KeyValueStorePair;
class ValueStore {
 public:
  typedef std::shared_ptr<ValueStore> SharedPtr;
  //TODO (HannesSommer) Fix constness (probably requires ConstValueStore as for PropertyTree)
  virtual ValueHandle<bool> getBool(const std::string & path, boost::optional<bool> def = boost::optional<bool>()) const = 0;
  virtual ValueHandle<int> getInt(const std::string & path, boost::optional<int> def = boost::optional<int>()) const = 0;
  virtual ValueHandle<double> getDouble(const std::string & path, boost::optional<double> def = boost::optional<double>()) const = 0;
  virtual ValueHandle<std::string> getString(const std::string & path, boost::optional<std::string> def = boost::optional<std::string>()) const = 0;

  virtual bool hasKey(const std::string & path) const = 0;

  virtual KeyValueStorePair getChild(const std::string & key) const = 0;

  virtual std::vector<KeyValueStorePair> getChildren() const = 0;

  virtual bool isChildSupported() const { return true ; }

  virtual ~ValueStore(){}
};

namespace internal {
template <typename Class, typename T>
struct AccessorMap;

template <typename Class>
struct AccessorMap<Class, bool> {
  static constexpr ValueHandle<bool> (Class ::*getter) (const std::string & path, boost::optional<bool>) const = &Class::getBool;
};
template <typename Class>
struct AccessorMap<Class, int> {
  static constexpr ValueHandle<int> (Class ::*getter) (const std::string & path, boost::optional<int>) const = &Class::getInt;
};
template <typename Class>
struct AccessorMap<Class, double> {
  static constexpr ValueHandle<double> (Class ::*getter) (const std::string & path, boost::optional<double>) const = &Class::getDouble;
};
template <typename Class>
struct AccessorMap<Class, std::string> {
  static constexpr ValueHandle<std::string> (Class ::*getter) (const std::string & path, boost::optional<std::string>) const = &Class::getString;
};
}

class ValueStoreRef {
 public:
  /// brief create a value store reference pointing to a fresh empty value store (based on @see sm::BoostPropertyTree)
  ValueStoreRef();
  ValueStoreRef(ValueStore::SharedPtr spVs);
  explicit ValueStoreRef(ValueStore & vs) : _vs(ValueStore::SharedPtr(&vs, [](ValueStore*){})) {}
  ValueStoreRef(sm::PropertyTree bpt);

  ValueHandle<bool> getBool(const std::string & path, boost::optional<bool> def = boost::optional<bool>()) const {
    return _vs->getBool(path, def);
  }
  ValueHandle<int> getInt(const std::string & path, boost::optional<int> def = boost::optional<int>()) const {
    return _vs->getInt(path, def);
  }
  ValueHandle<double> getDouble(const std::string & path, boost::optional<double> def = boost::optional<double>()) const {
    return _vs->getDouble(path, def);
  }
  ValueHandle<std::string> getString(const std::string & path, boost::optional<std::string> def = boost::optional<std::string>()) const {
    return _vs->getString(path, def);
  }

  bool hasKey(const std::string & path) const{
    return _vs->hasKey(path);
  }

  template <typename T>
  ValueHandle<T> get(const std::string & path, boost::optional<T> def = boost::optional<T>()) const {
    return (this->*internal::AccessorMap<ValueStoreRef, T>::getter)(path, def);
  }

  ValueStore & getValueStore() { return *_vs; }

  ValueStoreRef getChild(const std::string & key) const;

  sm::ConstPropertyTree asPropertyTree() const;

  std::vector<KeyValueStorePair> getChildren() const { return _vs->getChildren(); }

  std::shared_ptr<ValueStore> getValueStoreSharedPtr() { return _vs; }
  std::shared_ptr<const ValueStore> getValueStoreSharedPtr() const { return std::const_pointer_cast<const ValueStore>(_vs); }

  operator std::shared_ptr<ValueStore> () { return getValueStoreSharedPtr(); }
  operator ValueStore & () { return *getValueStoreSharedPtr(); }
  operator bool () const { return bool(_vs); }

  /// brief Create a ValueStoreRef to a BoostPropertyTree loaded from string using @see sm::BoostPropertyTree::loadString .
  static ValueStoreRef fromString(const std::string & contentString);
 private:
  std::shared_ptr<ValueStore> _vs;
  friend class ExtendibleValueStoreRef;
};

class ConstKeyValueStorePair : public ValueStoreRef {
 public:
  ConstKeyValueStorePair(const std::string& key, const std::shared_ptr<ValueStore> & vs) : ValueStoreRef(vs), _key(key){}

  const std::string& getKey() const { return _key; }
 private:
  std::string _key;
};

class KeyValueStorePair : public ValueStoreRef {
 public:
  KeyValueStorePair(const std::string& key, const std::shared_ptr<ValueStore> & vs) : ValueStoreRef(vs), _key(key){}

  const std::string& getKey() const { return _key; }
 private:
  std::string _key;
};

class ExtendibleKeyValueStorePair;
class ExtendibleValueStore : public ValueStore {
 public:
  typedef std::shared_ptr<ExtendibleValueStore> SharedPtr;
  virtual ValueHandle<bool> addBool(const std::string & path, bool initialValue) = 0;
  virtual ValueHandle<int> addInt(const std::string & path, int initialValue) = 0;
  virtual ValueHandle<double> addDouble(const std::string & path, double initialValue) = 0;
  virtual ValueHandle<std::string> addString(const std::string & path, std::string initialValue) = 0;

  virtual ExtendibleKeyValueStorePair addChild(const std::string & key) = 0;

  virtual ExtendibleKeyValueStorePair getExtendibleChild(const std::string & key) const = 0;
  virtual std::vector<ExtendibleKeyValueStorePair> getExtendibleChildren() const = 0;

  virtual ~ExtendibleValueStore(){}
};

class ExtendibleValueStoreRef : public ValueStoreRef {
 public:
  ExtendibleValueStoreRef(sm::PropertyTree bpt);
  ExtendibleValueStoreRef(ExtendibleValueStore::SharedPtr spVs) : ValueStoreRef(spVs), _evs(spVs) {}

  ValueHandle<bool> addBool(const std::string & path, bool initialValue) {
    return _evs->addBool(path, initialValue);
  }
  ValueHandle<int> addInt(const std::string & path, int initialValue) const {
    return _evs->addInt(path, initialValue);
  }
  ValueHandle<double> addDouble(const std::string & path, double initialValue) {
    return _evs->addDouble(path, initialValue);
  }
  ValueHandle<std::string> addString(const std::string & path, std::string initialValue) {
    return _evs->addString(path, initialValue);
  }

  inline ExtendibleKeyValueStorePair addChild(const std::string & key);

  ExtendibleValueStore & getValueStore() { return *_evs; }

  inline ExtendibleKeyValueStorePair getExtendibleChild(const std::string & key) const;
  std::vector<ExtendibleKeyValueStorePair> getExtendibleChildren() const { return _evs->getExtendibleChildren(); }

  ExtendibleValueStore::SharedPtr getValueStoreSharedPtr() const { return _evs; }
  operator ExtendibleValueStore::SharedPtr () const { return getValueStoreSharedPtr(); }

  operator ExtendibleValueStore & () const { return *getValueStoreSharedPtr(); }
 private:
  ExtendibleValueStore::SharedPtr  _evs;
};

class ExtendibleKeyValueStorePair : public ExtendibleValueStoreRef {
 public:
  ExtendibleKeyValueStorePair(const std::string& key, const std::shared_ptr<ExtendibleValueStore> & vs) : ExtendibleValueStoreRef(vs), _key(key){}

  const std::string& getKey() const { return _key; }
 private:
  std::string _key;
};

ExtendibleKeyValueStorePair ExtendibleValueStoreRef::getExtendibleChild(const std::string & key) const { return _evs->getExtendibleChild(key); }
inline ExtendibleKeyValueStorePair ExtendibleValueStoreRef::addChild(const std::string & key) { return _evs->addChild(key);}

}
using namespace value_store;

}

#endif /* VALUE_STORE_VALUESTORE_HPP_ */
<commit_msg>Fixed getValueStoreSharedPtr constness and added explicit ValueStoreRef(ValueStore * vsPtr) (taking ownership)<commit_after>#ifndef VALUE_STORE_VALUESTORE_HPP_
#define VALUE_STORE_VALUESTORE_HPP_

#include <cassert>
#include <memory>
#include <string>
#include <vector>

#include <boost/optional.hpp>

namespace sm {
class ConstPropertyTree;
class PropertyTree;

namespace value_store {

template <typename T>
class ValueHandleImpl {
 public:
  virtual bool isUpdateable() const { return false; }
  virtual void update(T newValue) = 0;
  virtual T get() const = 0;
  virtual ~ValueHandleImpl(){}
};

template <typename T>
class ConstValueHandleImpl : public ValueHandleImpl<T> {
 public:
  ConstValueHandleImpl(T v) : v(v) {}
  virtual bool isUpdateable() const { return false; }
  virtual void update(T /*newValue*/) { assert(false); }
  virtual T get() const { return v; }
  virtual ~ConstValueHandleImpl() {}
 private:
  const T v;
};

template <typename T>
class ValueHandle {
 public:
  explicit ValueHandle(ValueHandleImpl<T> * pImpl) : impl(pImpl) { assert(pImpl); }
  ValueHandle(T v) : impl(new ConstValueHandleImpl<T>(v)){ }
  ValueHandle(ValueHandle && move) = default;
  ValueHandle() = default;
  ValueHandle & operator = (ValueHandle && move) = default;

  bool isUpdateable() const { return impl->isUpdateable(); }
  void update(T newValue) { impl->update(newValue); }
  T get() const { return impl->get(); }
  inline operator T () const { return get(); }

  bool empty() const { return !impl; }

  ValueHandleImpl<T> & getImplementation() { return *impl; }
 private:
  std::unique_ptr<ValueHandleImpl<T> > impl;
};

class KeyValueStorePair;
class ValueStore {
 public:
  typedef std::shared_ptr<ValueStore> SharedPtr;
  //TODO (HannesSommer) Fix constness (probably requires ConstValueStore as for PropertyTree)
  virtual ValueHandle<bool> getBool(const std::string & path, boost::optional<bool> def = boost::optional<bool>()) const = 0;
  virtual ValueHandle<int> getInt(const std::string & path, boost::optional<int> def = boost::optional<int>()) const = 0;
  virtual ValueHandle<double> getDouble(const std::string & path, boost::optional<double> def = boost::optional<double>()) const = 0;
  virtual ValueHandle<std::string> getString(const std::string & path, boost::optional<std::string> def = boost::optional<std::string>()) const = 0;

  virtual bool hasKey(const std::string & path) const = 0;

  virtual KeyValueStorePair getChild(const std::string & key) const = 0;

  virtual std::vector<KeyValueStorePair> getChildren() const = 0;

  virtual bool isChildSupported() const { return true ; }

  virtual ~ValueStore(){}
};

namespace internal {
template <typename Class, typename T>
struct AccessorMap;

template <typename Class>
struct AccessorMap<Class, bool> {
  static constexpr ValueHandle<bool> (Class ::*getter) (const std::string & path, boost::optional<bool>) const = &Class::getBool;
};
template <typename Class>
struct AccessorMap<Class, int> {
  static constexpr ValueHandle<int> (Class ::*getter) (const std::string & path, boost::optional<int>) const = &Class::getInt;
};
template <typename Class>
struct AccessorMap<Class, double> {
  static constexpr ValueHandle<double> (Class ::*getter) (const std::string & path, boost::optional<double>) const = &Class::getDouble;
};
template <typename Class>
struct AccessorMap<Class, std::string> {
  static constexpr ValueHandle<std::string> (Class ::*getter) (const std::string & path, boost::optional<std::string>) const = &Class::getString;
};
}

class ValueStoreRef {
 public:
  /// brief create a value store reference pointing to a fresh empty value store (based on @see sm::BoostPropertyTree)
  ValueStoreRef();
  ValueStoreRef(ValueStore::SharedPtr spVs);
  explicit ValueStoreRef(ValueStore * vsPtr) : _vs(ValueStore::SharedPtr(vsPtr)) {}
  explicit ValueStoreRef(ValueStore & vs) : _vs(ValueStore::SharedPtr(&vs, [](ValueStore*){})) {}
  ValueStoreRef(sm::PropertyTree bpt);

  ValueHandle<bool> getBool(const std::string & path, boost::optional<bool> def = boost::optional<bool>()) const {
    return _vs->getBool(path, def);
  }
  ValueHandle<int> getInt(const std::string & path, boost::optional<int> def = boost::optional<int>()) const {
    return _vs->getInt(path, def);
  }
  ValueHandle<double> getDouble(const std::string & path, boost::optional<double> def = boost::optional<double>()) const {
    return _vs->getDouble(path, def);
  }
  ValueHandle<std::string> getString(const std::string & path, boost::optional<std::string> def = boost::optional<std::string>()) const {
    return _vs->getString(path, def);
  }

  bool hasKey(const std::string & path) const{
    return _vs->hasKey(path);
  }

  template <typename T>
  ValueHandle<T> get(const std::string & path, boost::optional<T> def = boost::optional<T>()) const {
    return (this->*internal::AccessorMap<ValueStoreRef, T>::getter)(path, def);
  }

  ValueStore & getValueStore() { return *_vs; }

  ValueStoreRef getChild(const std::string & key) const;

  sm::ConstPropertyTree asPropertyTree() const;

  std::vector<KeyValueStorePair> getChildren() const { return _vs->getChildren(); }

  std::shared_ptr<ValueStore> getValueStoreSharedPtr() const { return _vs; }

  operator std::shared_ptr<ValueStore> () { return getValueStoreSharedPtr(); }
  operator ValueStore & () { return *getValueStoreSharedPtr(); }
  operator bool () const { return bool(_vs); }

  /// brief Create a ValueStoreRef to a BoostPropertyTree loaded from string using @see sm::BoostPropertyTree::loadString .
  static ValueStoreRef fromString(const std::string & contentString);
 private:
  std::shared_ptr<ValueStore> _vs;
  friend class ExtendibleValueStoreRef;
};

class ConstKeyValueStorePair : public ValueStoreRef {
 public:
  ConstKeyValueStorePair(const std::string& key, const std::shared_ptr<ValueStore> & vs) : ValueStoreRef(vs), _key(key){}

  const std::string& getKey() const { return _key; }
 private:
  std::string _key;
};

class KeyValueStorePair : public ValueStoreRef {
 public:
  KeyValueStorePair(const std::string& key, const std::shared_ptr<ValueStore> & vs) : ValueStoreRef(vs), _key(key){}

  const std::string& getKey() const { return _key; }
 private:
  std::string _key;
};

class ExtendibleKeyValueStorePair;
class ExtendibleValueStore : public ValueStore {
 public:
  typedef std::shared_ptr<ExtendibleValueStore> SharedPtr;
  virtual ValueHandle<bool> addBool(const std::string & path, bool initialValue) = 0;
  virtual ValueHandle<int> addInt(const std::string & path, int initialValue) = 0;
  virtual ValueHandle<double> addDouble(const std::string & path, double initialValue) = 0;
  virtual ValueHandle<std::string> addString(const std::string & path, std::string initialValue) = 0;

  virtual ExtendibleKeyValueStorePair addChild(const std::string & key) = 0;

  virtual ExtendibleKeyValueStorePair getExtendibleChild(const std::string & key) const = 0;
  virtual std::vector<ExtendibleKeyValueStorePair> getExtendibleChildren() const = 0;

  virtual ~ExtendibleValueStore(){}
};

class ExtendibleValueStoreRef : public ValueStoreRef {
 public:
  ExtendibleValueStoreRef(sm::PropertyTree bpt);
  ExtendibleValueStoreRef(ExtendibleValueStore::SharedPtr spVs) : ValueStoreRef(spVs), _evs(spVs) {}

  ValueHandle<bool> addBool(const std::string & path, bool initialValue) {
    return _evs->addBool(path, initialValue);
  }
  ValueHandle<int> addInt(const std::string & path, int initialValue) const {
    return _evs->addInt(path, initialValue);
  }
  ValueHandle<double> addDouble(const std::string & path, double initialValue) {
    return _evs->addDouble(path, initialValue);
  }
  ValueHandle<std::string> addString(const std::string & path, std::string initialValue) {
    return _evs->addString(path, initialValue);
  }

  inline ExtendibleKeyValueStorePair addChild(const std::string & key);

  ExtendibleValueStore & getValueStore() { return *_evs; }

  inline ExtendibleKeyValueStorePair getExtendibleChild(const std::string & key) const;
  std::vector<ExtendibleKeyValueStorePair> getExtendibleChildren() const { return _evs->getExtendibleChildren(); }

  ExtendibleValueStore::SharedPtr getValueStoreSharedPtr() const { return _evs; }
  operator ExtendibleValueStore::SharedPtr () const { return getValueStoreSharedPtr(); }

  operator ExtendibleValueStore & () const { return *getValueStoreSharedPtr(); }
 private:
  ExtendibleValueStore::SharedPtr  _evs;
};

class ExtendibleKeyValueStorePair : public ExtendibleValueStoreRef {
 public:
  ExtendibleKeyValueStorePair(const std::string& key, const std::shared_ptr<ExtendibleValueStore> & vs) : ExtendibleValueStoreRef(vs), _key(key){}

  const std::string& getKey() const { return _key; }
 private:
  std::string _key;
};

ExtendibleKeyValueStorePair ExtendibleValueStoreRef::getExtendibleChild(const std::string & key) const { return _evs->getExtendibleChild(key); }
inline ExtendibleKeyValueStorePair ExtendibleValueStoreRef::addChild(const std::string & key) { return _evs->addChild(key);}

}
using namespace value_store;

}

#endif /* VALUE_STORE_VALUESTORE_HPP_ */
<|endoftext|>


<commit_before>/* Copyright 2015 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "iotjs_def.h"
#include "iotjs_module_console.h"

#include <stdio.h>

namespace iotjs {

static void Print(JHandlerInfo& handler, FILE* out_fd) {
  JHANDLER_CHECK(handler.GetArgLength() == 1);
  JHANDLER_CHECK(handler.GetArg(0)->IsString());

  String msg = handler.GetArg(0)->GetString();
  fprintf(out_fd, "%s", msg.data());
}

JHANDLER_FUNCTION(Stdout) {
  Print(handler, stdout);
  return true;
}

JHANDLER_FUNCTION(Stderr) {
  Print(handler, stderr);
  return true;
}

JObject* InitConsole() {
  Module* module = GetBuiltinModule(MODULE_CONSOLE);
  JObject* console = module->module;

  if (console == NULL) {
    console = new JObject();
    console->SetMethod("stdout", Stdout);
    console->SetMethod("stderr", Stderr);

    module->module = console;
  }

  return console;
}

} // namespace iotjs
<commit_msg>Fixed a compilation warning form console builtin, Fix #259.<commit_after>/* Copyright 2015 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "iotjs_def.h"
#include "iotjs_module_console.h"

#include <stdio.h>

namespace iotjs {

static bool Print(JHandlerInfo& handler, FILE* out_fd) {
  JHANDLER_CHECK(handler.GetArgLength() == 1);
  JHANDLER_CHECK(handler.GetArg(0)->IsString());

  String msg = handler.GetArg(0)->GetString();
  fprintf(out_fd, "%s", msg.data());

  return true;
}

JHANDLER_FUNCTION(Stdout) {
  return Print(handler, stdout);
}

JHANDLER_FUNCTION(Stderr) {
  return Print(handler, stderr);
}

JObject* InitConsole() {
  Module* module = GetBuiltinModule(MODULE_CONSOLE);
  JObject* console = module->module;

  if (console == NULL) {
    console = new JObject();
    console->SetMethod("stdout", Stdout);
    console->SetMethod("stderr", Stderr);

    module->module = console;
  }

  return console;
}

} // namespace iotjs
<|endoftext|>