view src/nucleus/mbs.c @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/*************************************************************************/
/*                                                                       */
/*               Copyright Mentor Graphics Corporation 2002              */
/*                         All Rights Reserved.                          */
/*                                                                       */
/* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS  */
/* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS   */
/* SUBJECT TO LICENSE TERMS.                                             */
/*                                                                       */
/*************************************************************************/

/*************************************************************************/
/*                                                                       */
/* FILE NAME                                               VERSION       */
/*                                                                       */
/*      mbs.c                                          Nucleus PLUS 1.14 */
/*                                                                       */
/* COMPONENT                                                             */
/*                                                                       */
/*      MB - Mailbox Management                                          */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This file contains the core routines for the Mailbox management  */
/*      component.                                                       */
/*                                                                       */
/* DATA STRUCTURES                                                       */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* FUNCTIONS                                                             */
/*                                                                       */
/*      MBS_Reset_Mailbox                   Reset a mailbox              */
/*      MBS_Broadcast_To_Mailbox            Broadcast a mailbox message  */
/*                                                                       */
/* DEPENDENCIES                                                          */
/*                                                                       */
/*      cs_extr.h                           Common Service functions     */
/*      tc_extr.h                           Thread Control functions     */
/*      mb_extr.h                           Mailbox functions            */
/*      hi_extr.h                           History functions            */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1994      Initial version of supplemental                  */
/*                      mailbox service file,                            */
/*                      version 1.1                                      */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*      04-17-1996      updated to version 1.2                           */
/*      03-24-1998      Released version 1.3                             */
/*      03-26-1999      Released 1.11m (new release                      */
/*                        numbering scheme)                              */
/*      04-23-2001      Fixed problem with resuming task in              */
/*                        MBS_Broadcast_To_Mailbox                       */
/*      04-17-2002      Released version 1.13m                           */
/*      11-07-2002      Released version 1.14                            */
/*************************************************************************/
#define         NU_SOURCE_FILE


#include        "cs_extr.h"                 /* Common service functions  */
#include        "tc_extr.h"                 /* Thread control functions  */
#include        "mb_extr.h"                 /* Mailbox functions         */
#include        "hi_extr.h"                 /* History functions         */
#include        "profiler.h"                /* ProView interface         */


/* Define internal component function prototypes.  */

VOID    MBC_Cleanup(VOID *information);


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      MBS_Reset_Mailbox                                                */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function resets a mailbox back to the initial state.  Any   */
/*      message in the mailbox is discarded.  Also, all tasks suspended  */
/*      on the mailbox are resumed with the reset completion status.     */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      MBSE_Reset_Mailbox                  Error checking shell         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCC_Resume_Task                     Resume a suspended task      */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Control_To_System               Transfer control to system   */
/*      TCT_System_Protect                  Protect mailbox              */
/*      TCT_Unprotect                       Release protection           */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      mailbox_ptr                         Mailbox control block pointer*/
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                                                       */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         NAME            DATE                    REMARKS               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Changed function interface to                    */
/*                      match the prototype, added                       */
/*                      register variable logic,                         */
/*                      optimized protection logic,                      */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  MBS_Reset_Mailbox(NU_MAILBOX *mailbox_ptr)
{

R1 MB_MCB      *mailbox;                    /* Mailbox control block ptr */
R2 MB_SUSPEND  *suspend_ptr;                /* Suspend block pointer     */
MB_SUSPEND     *next_ptr;                   /* Next suspend block pointer*/
STATUS          preempt;                    /* Status for resume call    */
NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Move input mailbox pointer into internal pointer.  */
    mailbox =  (MB_MCB *) mailbox_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_RESET_MAILBOX_ID, (UNSIGNED) mailbox,
                                        (UNSIGNED) 0, (UNSIGNED) 0);

#endif

    /* Protect against access to the mailbox.  */
    TCT_System_Protect();

    /* Pickup the suspended task pointer list.  */
    suspend_ptr =  mailbox -> mb_suspension_list;

    /* Walk the chain task(s) currently suspended on the mailbox.  */
    preempt =  0;
    while (suspend_ptr)
    {

        /* Resume the suspended task.  Insure that the status returned is
           NU_MAILBOX_RESET.  */
        suspend_ptr -> mb_return_status =  NU_MAILBOX_RESET;

        /* Point to the next suspend structure in the link.  */
        next_ptr =  (MB_SUSPEND *) (suspend_ptr -> mb_suspend_link.cs_next);

        /* Resume the specified task.  */
        preempt =  preempt |
                TCC_Resume_Task((NU_TASK *) suspend_ptr -> mb_suspended_task,
                                                        NU_MAILBOX_SUSPEND);

        /* Determine if the next is the same as the head pointer.  */
        if (next_ptr == mailbox -> mb_suspension_list)

            /* Clear the suspension pointer to signal the end of the list
               traversal.  */
            suspend_ptr =  NU_NULL;
        else

            /* Position the suspend pointer to the next suspend block.  */
            suspend_ptr =  next_ptr;
    }

    /* Initialize the mailbox.  */
    mailbox -> mb_message_present =  NU_FALSE;
    mailbox -> mb_tasks_waiting =    0;
    mailbox -> mb_suspension_list =  NU_NULL;

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpMailBox(RT_PROF_RESET_MAILBOX,mailbox,RT_PROF_OK);
#endif /* INCLUDE_PROVIEW */

    /* Determine if preemption needs to occur.  */
    if (preempt)

        /* Transfer control to system to facilitate preemption.  */
        TCT_Control_To_System();

    /* Release protection.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();

    /* Return a successful completion.  */
    return(NU_SUCCESS);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      MBS_Broadcast_To_Mailbox                                         */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function sends a message to all tasks currently waiting for */
/*      a message from the mailbox.  If no tasks are waiting, this       */
/*      service behaves like a normal send message.                      */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      MBSE_Broadcast_To_Mailbox           Broadcast to a mailbox       */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      CSC_Place_On_List                   Place on suspend list        */
/*      CSC_Priority_Place_On_List          Place on priority list       */
/*      CSC_Remove_From_List                Remove from suspend list     */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCC_Resume_Task                     Resume a suspended task      */
/*      TCC_Suspend_Task                    Suspend calling task         */
/*      TCC_Task_Priority                   Priority of specified task   */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Control_To_System               Transfer control to system   */
/*      TCT_Current_Thread                  Pickup current thread pointer*/
/*      TCT_System_Protect                  Protect mailbox              */
/*      TCT_Unprotect                       Release protection           */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      mailbox_ptr                         Mailbox control block pointer*/
/*      message                             Pointer to message to send   */
/*      suspend                             Suspension option if full    */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                          If service is successful     */
/*      NU_MAILBOX_FULL                     If mailbox is currently full */
/*      NU_TIMEOUT                          If timeout on service expires*/
/*      NU_MAILBOX_DELETED                  If mailbox is deleted during */
/*                                            suspension                 */
/*      NU_MAILBOX_RESET                    If mailbox is deleted during */
/*                                            suspension                 */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Changed function interface to                    */
/*                      match the prototype, added                       */
/*                      register variable logic,                         */
/*                      optimized protection logic,                      */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  MBS_Broadcast_To_Mailbox(NU_MAILBOX *mailbox_ptr, VOID *message,
                                                        UNSIGNED suspend)
{

R1 MB_MCB      *mailbox;                    /* Mailbox control block ptr */
MB_SUSPEND      suspend_block;              /* Allocate suspension block */
R2 MB_SUSPEND  *suspend_ptr;                /* Pointer to suspend block  */
MB_SUSPEND     *suspend_head;               /* Pointer to suspend head   */
MB_SUSPEND     *next_suspend_ptr;           /* Get before restarting task*/
STATUS          preempt;                    /* Preemption flag           */
R3 UNSIGNED    *source_ptr;                 /* Pointer to source         */
R4 UNSIGNED    *destination_ptr;            /* Pointer to destination    */
TC_TCB         *task;                       /* Task pointer              */
STATUS          status;                     /* Completion status         */
NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Move input mailbox pointer into internal pointer.  */
    mailbox =  (MB_MCB *) mailbox_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_BROADCAST_TO_MAILBOX_ID, (UNSIGNED) mailbox,
                                       (UNSIGNED) message, (UNSIGNED) suspend);

#endif

    /* Initialize the status as successful.  */
    status =  NU_SUCCESS;

    /* Protect against simultaneous access to the mailbox.  */
    TCT_System_Protect();

    /* Determine if the mailbox is empty or full.  */
    if (mailbox -> mb_message_present)
    {

        /* Mailbox already has a message.  Determine if suspension is
           required.  */
        if (suspend)
        {

            /* Suspension is requested.  */

            /* Increment the number of tasks suspended on the mailbox. */
            mailbox -> mb_tasks_waiting++;

#ifdef INCLUDE_PROVIEW
            _RTProf_DumpMailBox(RT_PROF_BROADCAST_TO_MAILBOX,mailbox,RT_PROF_WAIT);
#endif /* INCLUDE_PROVIEW */

            /* Setup the suspend block and suspend the calling task.  */
            suspend_ptr =  &suspend_block;
            suspend_ptr -> mb_mailbox =                  mailbox;
            suspend_ptr -> mb_suspend_link.cs_next =     NU_NULL;
            suspend_ptr -> mb_suspend_link.cs_previous = NU_NULL;
            suspend_ptr -> mb_message_area =             (UNSIGNED *) message;
            task =                           (TC_TCB *)  TCT_Current_Thread();
            suspend_ptr -> mb_suspended_task =           task;

            /* Determine if priority or FIFO suspension is associated with the
               mailbox.  */
            if (mailbox -> mb_fifo_suspend)
            {

                /* FIFO suspension is required.  Link the suspend block into
                   the list of suspended tasks on this mailbox.  */
                CSC_Place_On_List((CS_NODE **) &(mailbox ->mb_suspension_list),
                                        &(suspend_ptr -> mb_suspend_link));
            }
            else
            {

                /* Get the priority of the current thread so the suspend block
                   can be placed in the appropriate place.  */
                suspend_ptr -> mb_suspend_link.cs_priority =
                                                    TCC_Task_Priority(task);

                CSC_Priority_Place_On_List((CS_NODE **)
                        &(mailbox -> mb_suspension_list),
                                        &(suspend_ptr -> mb_suspend_link));
            }

            /* Finally, suspend the calling task. Note that the suspension call
               automatically clears the protection on the mailbox.  */
            TCC_Suspend_Task((NU_TASK *) task, NU_MAILBOX_SUSPEND,
                                        MBC_Cleanup, suspend_ptr, suspend);

            /* Pickup the return status.  */
            status =  suspend_ptr -> mb_return_status;
        }
        else
        {

            /* Return a status of NU_MAILBOX_FULL because there is no
               room in the mailbox for the message.  */
            status =  NU_MAILBOX_FULL;

#ifdef INCLUDE_PROVIEW
            _RTProf_DumpMailBox(RT_PROF_BROADCAST_TO_MAILBOX,mailbox,RT_PROF_FAIL);
#endif /* INCLUDE_PROVIEW */

        }
    }
    else
    {

        /* Determine if a task is waiting on the mailbox.  */
        if (mailbox -> mb_suspension_list)
        {

#ifdef INCLUDE_PROVIEW
        _RTProf_DumpMailBox(RT_PROF_BROADCAST_TO_MAILBOX,mailbox,RT_PROF_OK);
#endif /* INCLUDE_PROVIEW */

            /* At least one task is waiting on mailbox for a message.  */

            /* Save off the suspension list and and then clear out the
               mailbox suspension.  */
            suspend_head =  mailbox -> mb_suspension_list;
            mailbox -> mb_suspension_list =  NU_NULL;

            /* Loop to wakeup all of the tasks waiting on the mailbox for
               a message.  */
            suspend_ptr =  suspend_head;
            preempt =      0;
            do
            {

                /* Setup the source and destination pointers.  */
                source_ptr =       (UNSIGNED *) message;
                destination_ptr =  suspend_ptr -> mb_message_area;

                /* Copy the message directly into the waiting task's
                   destination.  */
                *destination_ptr =        *source_ptr;
                *(destination_ptr + 1) =  *(source_ptr + 1);
                *(destination_ptr + 2) =  *(source_ptr + 2);
                *(destination_ptr + 3) =  *(source_ptr + 3);

                /* Setup the appropriate return value.  */
                suspend_ptr -> mb_return_status =  NU_SUCCESS;

                /* Move the suspend pointer along to the next block. */
                next_suspend_ptr =  (MB_SUSPEND *)
                                suspend_ptr -> mb_suspend_link.cs_next;

                /* Wakeup each task waiting.  */
                preempt =  preempt |
                 TCC_Resume_Task((NU_TASK *) suspend_ptr -> mb_suspended_task,
                                                        NU_MAILBOX_SUSPEND);
                suspend_ptr = next_suspend_ptr;

            } while (suspend_ptr != suspend_head);

            /* Clear the number of tasks waiting counter of the mailbox.  */
            mailbox -> mb_tasks_waiting =  0;

            /* Determine if a preempt condition is present.  */
            if (preempt)

                /* Transfer control to the system if the resumed task function
                   detects a preemption condition.  */
                TCT_Control_To_System();
        }
        else
        {

            /* Mailbox is empty and no task is waiting.  */

            /* Setup the source and destination pointers.  */
            source_ptr =       (UNSIGNED *) message;
            destination_ptr =  &(mailbox -> mb_message_area[0]);

            /* Place the message in the mailbox. */
            *destination_ptr =        *source_ptr;
            *(destination_ptr + 1) =  *(source_ptr + 1);
            *(destination_ptr + 2) =  *(source_ptr + 2);
            *(destination_ptr + 3) =  *(source_ptr + 3);

            /* Indicate that the mailbox has a message.  */
            mailbox -> mb_message_present =  NU_TRUE;

#ifdef INCLUDE_PROVIEW
        _RTProf_DumpMailBox(RT_PROF_BROADCAST_TO_MAILBOX,mailbox,RT_PROF_OK);
#endif /* INCLUDE_PROVIEW */
        }
    }

    /* Release protection.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();

    /* Return the completion status.  */
    return(status);
}