#define OSSET_C
/******************************************************************************
 *
 *       (C) Copyright 2006, Freescale Semiconductor, Inc. All Rights Reserved.
 *
 *       THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
 *       BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
 *       Freescale Semiconductor, Inc.
 *
 * Filename:     $Source: /u/OSEK/src/os2000/src/osesys/src/osset.c,v $
 * Author:       $Author: c-atroshikhin $
 * Revision:     $Revision: 1.14 $
 *
 * Functions:    
 *
 * History:      Use the CVS command rlog to display revision history
 *               information.
 *
 * Description:  OSEK OS set-up  
 *
 * Notes:        
 *
 ******************************************************************************/

#if !defined(OSPROPH)
#include "osprop.h"                     /* OS Properties */
#else                                   /* !defined(OSPROPH)    */
#include OSPROPH                        /* OS Properties */
#endif                                  /* !defined(OSPROPH)    */

#include <osapi.h>

#if defined(OSSTKCHECK_U)
/* additional stack size for underflowcheck */
#define OSSTKADDS_U                     (OSSTKCHECKPATTERNSIZE / 4)
#else
#define OSSTKADDS_U                     0
#endif

/*  Public OS Services  */

/***************************************************************************
 * Function : StartOS
 *
 * Description: OS data initialization from configuration tables
 *
 * Returns: none
 *
 * Notes:
 *
 **************************************************************************/

void StartOS( AppModeType mode )
{
  OSCARDINAL i;
  OSIMSAVE                              /* OSINTMASKTYPE save;       */
#if defined(OSECC) || defined(OSRESOURCE) || defined(OSCC2) || \
    defined(OSEXTSTATUS) || defined(OSNOFASTTERMINATE)

  OSTSKCBPTR task_cb;
  const OSTSK* task_cfg;

#endif                                  /* defined(OSECC) || defined(OSRESOURCE) || defined(OSCC2) || \*/
  /* defined(OSEXTSTATUS) || defined(OSNOFASTTERMINATE) */

#if defined(OSSTKCHECK) || (OSORTIDEBUGLEVEL > 0)
  OSDWORD* pstk;
#if defined(OSSTKCHECK_U)
  volatile OSDWORD guard[OSSTKCHECKPATTERNSIZE];
#endif
#endif

  OSOrtiSetServiceWatch( OSServiceId_StartOS ); /* set watch to this service */
  OSDHI();
  OSOrtiSetOldServiceID( OSServiceId_StartOS );

#if defined(OSSTKCHECK_U)
  OSSTKSETGUARD(guard);
  OsMainTOS = guard;
#endif

#if (OSORTIDEBUGLEVEL > 0) || (OSNAPPMODES > 1)
  OsCurAppMode = mode;
#endif                                  /* (OSORTIDEBUGLEVEL > 0)  || (OSNAPPMODES > 1) */

#if (OSORTIDEBUGLEVEL > 0 )
  OsLastError = E_OK;
#endif                                  /* (OSORTIDEBUGLEVEL > 0 ) */
  OsSuspendLevelAll = 0;

#if defined(OSRESOURCEISR)
  OsISRLastResource = OSNULLRES;        /* The head of ISRs resource list  */
#endif                                  /* defined(OSRESOURCEISR) */

#if defined(OSSTKCHECK) && defined(OSHOOKERROR)
  OSSTKSETGUARD(OSSTACKEND);
#if defined(OSISRNORMAL) && defined(OSECC) && defined(OSISRSTACKSIZE)
  OSSTKSETGUARD(OsISRStack);
#if defined(OSSTKCHECK_U)
  OSSTKSETGUARD(OSISRTOS);
#endif
#endif                                  /* defined(OSISRNORMAL) && defined(OSECC) && defined(OSISRSTACKSIZE) */
#endif                                  /* defined(OSSTKCHECK) && defined(OSHOOKERROR) */

  /* ISR initialization   */
  OSInitializeISR();

  /* Tasks initialization */

  /* Scheduler initialization */
  OsSchedulerVector1 = 0;
#if defined(OSEXTPRIORS)
  OsSchedulerVector2 = 0;
#endif                                  /* defined(OSEXTPRIORS) */

  /* Init task's control blocks */
#if defined(OSECC) || defined(OSRESOURCE) || defined(OSCC2) ||\
    defined(OSEXTSTATUS) || defined(OSNOFASTTERMINATE)

#if defined(OSRESOURCE)
  for( i = 0; i < OSNPRIORS; i++ )
  {
    OsPrioLink[i] = OSNULLPRIOLINK;     /* Priority Link table  */
  }
#endif                                  /* defined(OSRESOURCE) */
  for( i = 0; i < OSNTSKS; i++ )
  {
    task_cb = &(OsTaskTable[i]);
    task_cfg = &(OsTaskCfgTable[i]);
    task_cb->entry = task_cfg->entry;   /* entry point of task */
    task_cb->taskId = task_cfg->taskId;
#if defined(OSINRES)
    task_cb->runprio = task_cfg->runprio;
#endif                                  /* defined(OSINRES) */

#if defined(OSRESOURCE) || defined(OSINRES)
    OsPrioLink[task_cfg->taskId] = task_cb; /* Init priorities link table */
#endif                                  /* defined(OSRESOURCE) || defined(OSINRES) */
    task_cb->status = (OSBYTE)( OSTCBFIRST | (task_cfg->property) );
    task_cb->context = &(OsTaskJmpBuf[i]);

#if defined(OSECC)
    if( (task_cfg->property & OSTSKEXTENDED) != 0 )
    {
      task_cb->tos = (OSDWORD*)(task_cfg->tos - (4 * OSSTKADDS)); /* -8 because it is necessary to reserve space for backchain */
#if defined(OSSTKCHECK) || (OSORTIDEBUGLEVEL > 0)
      task_cb->bos = (OSDWORD*)task_cfg->bos; /* bottom of task stack */
      for( pstk = task_cb->bos; pstk < (task_cb->tos + OSSTKADDS + OSSTKADDS_U
        ); pstk++ )
      {
        *pstk = OSORTISTACKPATTERN;
      }
#endif                                  /* defined(OSSTKCHECK) || (OSORTIDEBUGLEVEL > 0)             */
    }
    else
    {                                   /* for Basic tasks */
      task_cb->tos = 0;
#if defined(OSSTKCHECK) || (OSORTIDEBUGLEVEL > 0)
      task_cb->bos = 0;
#endif                                  /* defined(OSSTKCHECK) || (OSORTIDEBUGLEVEL > 0)             */
    }
#if OSNXTSKS > 0
    task_cb->set_event = OSNOEVENTS;
#endif                                  /* OSNXTSKS > 0 */
    /* set_event are cleared before task start */
#endif                                  /* defined(OSECC) */

#if defined(OSRESOURCE)
#if defined(OSEXTSTATUS)
    task_cb->resources = OSNULLRES;
#endif                                  /* defined(OSEXTSTATUS) */
#if (OSORTIDEBUGLEVEL > 0)
    task_cb->curPrio = (OSPRIOTYPE)(task_cb->taskId);
#endif                                  /* (OSORTIDEBUGLEVEL > 0) */
#endif                                  /* defined(OSRESOURCE) */
    /* Activate auto-startup tasks  */
#if (OSNAPPMODES > 1)
    if( (task_cfg->autostart & (1 << mode)) != 0 )
#else                                   /* (OSNAPPMODES > 1) */
    if( (task_cfg->property & OSTSKACTIVATE) != 0 ) /* compiler must reuse OsPrioLink[i] 
                                                       (else need local variable to storage OsPrioLink[i] */
#endif                                  /* (OSNAPPMODES > 1) */
    {
      task_cb->status |= OSTCBSTART;
      OSTask2Ready( task_cfg->taskId );
    }
  }

  OsTaskTable[OSNULLTASK].status &= (OSBYTE)(~OSTCBFIRST); /* Background task(os, nulltask) already running */
  OsTaskTable[OSNULLTASK].taskId = OSNULLTASK; /* Background task(os, nulltask) */
  OsRunning = &OsTaskTable[OSNULLTASK]; /* no running task yet  */

#else                                   /* defined(OSECC) || defined(OSRESOURCE) || defined(OSCC2) || \*/
  /* defined(OSEXTSTATUS) || defined(OSNOFASTTERMINATE) */

  for( i = 0; i < OSNTSKS; i++ )
  {
    OsTaskStatus[i] = OsTaskProperty[i];
#if (OSNAPPMODES > 1)
    if( (OsTaskAutostart[i] & (1 << mode)) != 0 )
#else                                   /* (OSNAPPMODES > 1) */
    if( (OsTaskStatus[i] & OSTSKACTIVATE) != 0 )
#endif                                  /* (OSNAPPMODES > 1) */
    {
      OsTaskStatus[i] |= OSTCBSTART;
      OSTask2Ready( i );
    }
#if defined(OSINRES)
    OsPrio2Task[i] = i;
#endif                                  /* defined(OSINRES) */
  }
  OsRunning = OSNULLTASK;               /* no running task yet  */
#endif                                  /* defined(OSECC) || defined(OSRESOURCE) || defined(OSCC2) || \*/
  /* defined(OSEXTSTATUS) || defined(OSNOFASTTERMINATE) */

#if defined(OSRESOURCE)
  /* Scheduler resource initialization */
  for( i = 0; i < OSNALLRES; i++ )
  {
    OsResources[i].prio = OsResPrioTbl[i];

    OsResources[i].prio2task = OSNULLPRIOLINK;
#if defined(OSEXTSTATUS) || (OSORTIDEBUGLEVEL > 0)
    OsResources[i].isUsed = 0;
#endif                                  /* defined(OSEXTSTATUS) || (OSORTIDEBUGLEVEL > 0) */
#if defined(OSEXTSTATUS)
    OsResources[i].nextRes = OSNULLRES;
#endif                                  /* defined(OSEXTSTATUS) */
#if (OSORTIDEBUGLEVEL > 0)
    OsResources[i].curPrio = 0;
#endif                                  /*  (OSORTIDEBUGLEVEL > 0) */
  }
#endif                                  /* defined(OSRESOURCE) */

#if defined(OSRES_SCHEDULER)
#if defined(OSEXTSTATUS) || (OSORTIDEBUGLEVEL > 0)
  OsResScheduler.prio = (OSSCHWIDE*OSSCHMAXBITNUM + 1); /* resource scheduler not use any priority */
  OsResScheduler.prio2task = OSNULLPRIOLINK;
#if defined(OSEXTSTATUS)
  OsResScheduler.nextRes = OSNULLRES;
#endif                                  /* defined(OSEXTSTATUS) */
#if defined(OSEXTSTATUS) || (OSORTIDEBUGLEVEL > 0)
  OsResScheduler.isUsed = 0;
#endif                                  /* defined(OSEXTSTATUS) || (OSORTIDEBUGLEVEL > 0) */
#if (OSORTIDEBUGLEVEL > 0)
  OsResScheduler.curPrio = 0;
#endif                                  /* (OSORTIDEBUGLEVEL > 0) */
#endif                                  /* defined(OSEXTSTATUS) || (OSORTIDEBUGLEVEL > 0) */
#endif                                  /* defined(OSRES_SCHEDULER) */

  /* Counters initialization */
#if defined(OSCOUNTER)

  for( i = 0; i < OSNCTRS; i++ )
  {
#if defined(OSALARM)
    OsCounters[i].alarm = OSALM0;       /*pointer to assigned running alarms    */
    /*  Configuration Data  */
#endif                                  /* defined(OSALARM) */
    OsCounters[i].info = &OsCountersCfg[i];
    OsCounters[i].value = 0;
  }
#endif                                  /* defined(OSCOUNTER) */

  /* Alarms inititalization */
#if defined(OSALARM)
  for( i = 0; i < OSNALMS; i++ )
  {
    OsAlarms[i].taskId = OsAlarmsCfg[i].taskId;
    /* for BCC1 events are not supported, action is only activate task */
#if defined(OSECC) && defined(OSALMSETEVENT) && (OSNXTSKS > 0) /* for ECC1 events are supported if necessary */
    OsAlarms[i].event = OsAlarmsCfg[i].event; /* if event==0 then alarm activates task 
                                                 else it set event for this task */
#endif                                  /*  defined(OSECC) && defined(OSALMSETEVENT) && (OSNXTSKS>0) */
    OsAlarms[i].ctrId = OsAlarmsCfg[i].ctrId; /* attached Counter ID  */
    OsAlarms[i].prev = OSALMCBPTR0;
    OsAlarms[i].next = OSALMCBPTR0;
#if defined(OSALMCALLBACK)
    OsAlarms[i].callBack = OsAlarmsCfg[i].callBack;
#endif                                  /* defined(OSALMCALLBACK) */
  }
#endif                                  /* defined(OSALARM) */

  /* Messages inititalization */
#if OSNMSGS > 0
  OSMsgInit();                          /* init messages data, even user must do it himself */
#endif                                  /* OSNMSGS > 0 */

#if defined(OSHOOKSTARTUP)
#if defined(OSISRENTRYEXIT)             /* There are user interrupts category 2, 3 or systimer */
  OsIsrLevel |= OSISRHOOKLEVEL;         /*to block scheduler during StartupHook */
#endif                                  /* defined(OSISRENTRYEXIT) */
  OSOrtiSetServiceWatch( OSServiceId_StartupHook );
  /* set watch to this service */
  StartupHook();                        /* user hook or empty macro */
  OSOrtiServiceWatchOnExit( OSServiceId_StartupHook );
  /* clean service watch on hook leaving */
#if defined(OSISRENTRYEXIT)
  OsIsrLevel &= ~OSISRHOOKLEVEL;
#endif                                  /* defined(OSISRENTRYEXIT) */
#endif                                  /* defined(OSHOOKSTARTUP) */

  /* Init systimer. It shall be after StartupHook call for compatibility with OS 2.1 */
#if defined(OSSYSTIMER)
  OSInitializeSystemTimer();
#endif                                  /* defined(OSSYSTIMER) */

#if defined(OSAUTOALARMS)
#if (OSNAPPMODES > 1)
  OSInitAutoAlarms (mode);
#else                                   /* (OSNAPPMODES > 1) */
  OSInitAutoAlarms ();
#endif                                  /* (OSNAPPMODES > 1) */
#endif                                  /* defined(OSAUTOALARMS) */

  /* if there are isr 2 pended at this point, then dispatch can be performed in LeaveISR service */

  /*  Start scheduler */
  OSDI();
  OSCLEARPARAM();
  OSTaskForceDispatch();                /* we may return if no task were activated during start-up  */
  OSEI();                               /* End of initialization, run pended interrupts */

#if defined(OSHCLOWPOWER)
  OSSETHID0( (OSGETHID0() & 0xFF1FFFFF) | 0x00800000 ); /* set DOZE as lower power mode */
  OSSETMSR( OSGETMSR() | OSMSR_POW );   /* set POW bit in MSR */
#endif                                  /* defined(OSHCLOWPOWER) */
  for(;; )
  {                                     /* scheduler idle loop  */
#if defined(OSHOOKSCHEDULER)
    OSOrtiSetServiceWatch( OSServiceId_IdleLoopHook );
    /* set watch to this service */
    IdleLoopHook();
    OSOrtiServiceWatchOnExit( OSServiceId_IdleLoopHook );
    /* clean service watch on hook leaving */
#endif                                  /* defined(OSHOOKSCHEDULER) */
  }
}

/***************************************************************************
 * Function : ShutdownOS
 *
 * Description: Calls shutdown hook, disables interrupts from system timers,
 *              Sets Power-down mode
 *
 * Returns: none
 *
 * Notes:
 *
 **************************************************************************/

void ShutdownOS( StatusType error )
{
  OSMPC_DCI();                          /* disable ALL interrupts   */

#if defined(OSSYSTIMER)

  OSShutdownSystemTimer();              /* shutdown system timer (hardware) */

#endif                                  /* defined(OSSYSTIMER)   */
#if defined(OSHOOKSHUTDOWN)
  OSOrtiSetServiceWatch( OSServiceId_ShutdownHook );
  /* set watch to this service */
  ShutdownHook( error );
  OSOrtiServiceWatchOnExit( OSServiceId_ShutdownHook );
  /* clean service watch on hook leaving */
#endif                                  /* defined(OSHOOKSHUTDOWN) */
  /* Set Power-down mode */
  OSOrtiServiceWatchOnExit( OSServiceId_ShutdownOS ); /* clean service watch on leaving service */

  OSSETHID0( (OSGETHID0() & 0xFF1FFFFF) | OSHID0_SLEEP ); /* Enable SLEEP mode */
  OSSETMSR( OSGETMSR() | OSMSR_POW );   /* set POW bit in MSR */

  for(;; )
  {}                                    /* wait forever */
}
