/**HEADER********************************************************************
* 
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
*************************************************************************** 
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR 
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: tcpip.c$
* $Version : 3.0.5.0$
* $Date    : Nov-21-2008$
*
* Comments:
*
*   This is the main task for the TCP/IP protocol suite.
*
*END************************************************************************/

#include <rtcs.h>
#include "rtcs_prv.h"
#include "ticker.h"
#include "tcpip.h"
#include "arp.h"


uint_32 (_CODE_PTR_ TCP_tick)(void);

/*FUNCTION*-------------------------------------------------------------
*
* Function Name   : TCPIP_fake_tick
* Returned Value  : 0
* Comments        :
*
*  The fake TCP_Tick_server(), used when TCP is not installed.
*
*END*-----------------------------------------------------------------*/

static uint_32 TCPIP_fake_tick
   (
      void
   )
{ /* Body */
   return 0;
} /* Endbody */

/*TASK*------------------------------------------------------------------
*
* Task Name      :   TCPIP_task
* Comments       :
*     This task services requests from the socket layer and the
*     application, and services incoming packets from the link layer(s).
*
*END*------------------------------------------------------------------*/

void TCPIP_task
   (
      pointer  dummy,
      pointer  creator
   )
{ /* Body */
   TCPIP_CFG_STRUCT           TCPIP_cfg;
   RTCS_DATA_PTR              RTCS_data_ptr;
   uint_32                    i;
   TCPIP_MESSAGE_PTR          tcpip_msg;
   uint_32                    timeout, timebefore, timeafter, timedelta;
   uint_32                    status;           /* Return status */
   _queue_id                  tcpip_qid;

   RTCS_data_ptr = RTCS_get_data();
   RTCS_setcfg(TCPIP, &TCPIP_cfg);

   TCPIP_cfg.status = RTCS_OK;

   tcpip_qid = RTCS_msgq_open(TCPIP_QUEUE, 0);
   if (tcpip_qid == 0) {
      RTCS_task_exit(creator, RTCSERR_OPEN_QUEUE_FAILED);
   } /* Endif */

   RTCS_data_ptr->TCPIP_TASKID = RTCS_task_getid();

   /*
   ** Initialize the Time Service
   */
   TCP_tick = TCPIP_fake_tick;
   TCPIP_Event_init();
   timebefore = RTCS_time_get();

   /*
   ** Allocate a block of PCBs
   */
   status = RTCSPCB_init();
   if (status != RTCS_OK) {
      RTCS_task_exit(creator, status);
   } /* Endif */

   /*
   ** Initialize the protocols
   */

   status = IP_init();
   if (status) {
      RTCS_task_exit(creator, status);
   } /* Endif */

#if RTCSCFG_ENABLE_ICMP
   status = ICMP_init();
   if (status) {
      RTCS_task_exit(creator, status);
   } /* Endif */
#endif

   for (i = 0; RTCS_protocol_table[i]; i++) {
      status = (*RTCS_protocol_table[i])();
      if (status) {
         RTCS_task_exit(creator, status);
      } /* Endif */
   } /* Endfor */

   ARP_init();
   BOOT_init();

   _RTCS_initialized= TRUE;
   RTCS_task_resume_creator(creator, RTCS_OK);

   while (1) {
      /*
      ** Update any option that can be changed
      */
#if 0
      RTCS_data_ptr->IP_FORWARD_COPY =    _IP_forward;
      RTCS_data_ptr->TCP_BYPASS_RX_COPY = _TCP_bypass_rx;
      RTCS_data_ptr->TCP_BYPASS_TX_COPY = _TCP_bypass_tx;
      RTCS_data_ptr->TCP_RTO_MIN_COPY =   _TCP_rto_min;
#endif

      /*
      ** Process TCP events
      */
      timeout = TCP_tick();

      /*
      ** Set up the timeout to hit at exactly the time of the next timeout.
      */
      timeafter = RTCS_time_get();
      timedelta = timeafter - timebefore;
      timebefore = timeafter;
      timedelta = TCPIP_Event_time(timedelta);

      if (timedelta != 0) {
         if ((timedelta < timeout) || (timeout == 0)) {
            timeout = timedelta;
         } /* Endif */
      } /* Endif */

      tcpip_msg = (TCPIP_MESSAGE_PTR)RTCS_msgq_receive(tcpip_qid, timeout,
         RTCS_data_ptr->TCPIP_msg_pool);

      /* Update TCP's time */
      TCP_tick();

      timeafter = RTCS_time_get();
      timedelta = timeafter - timebefore;
      timebefore = timeafter;
      TCPIP_Event_time(timedelta);

      if (tcpip_msg) {
         tcpip_msg->COMMAND(tcpip_msg->DATA);
         RTCS_msg_free(tcpip_msg);
      } /* Endif */

   } /* Endwhile */

} /* Endbody */


/* EOF */
