utils/context.c
changeset 0 10c42ec6c05f
equal deleted inserted replaced
-1:000000000000 0:10c42ec6c05f
       
     1 /*
       
     2  * context.c
       
     3  *
       
     4  * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.      
       
     5  * All rights reserved.      
       
     6  * 
       
     7  * This program and the accompanying materials are made available under the 
       
     8  * terms of the Eclipse Public License v1.0 or BSD License which accompanies
       
     9  * this distribution. The Eclipse Public License is available at
       
    10  * http://www.eclipse.org/legal/epl-v10.html and the BSD License is as below.                                   
       
    11  *                                                                       
       
    12  * Redistribution and use in source and binary forms, with or without    
       
    13  * modification, are permitted provided that the following conditions    
       
    14  * are met:                                                              
       
    15  *                                                                       
       
    16  *  * Redistributions of source code must retain the above copyright     
       
    17  *    notice, this list of conditions and the following disclaimer.      
       
    18  *  * Redistributions in binary form must reproduce the above copyright  
       
    19  *    notice, this list of conditions and the following disclaimer in    
       
    20  *    the documentation and/or other materials provided with the         
       
    21  *    distribution.                                                      
       
    22  *  * Neither the name Texas Instruments nor the names of its            
       
    23  *    contributors may be used to endorse or promote products derived    
       
    24  *    from this software without specific prior written permission.      
       
    25  *                                                                       
       
    26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   
       
    27  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     
       
    28  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
       
    29  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  
       
    30  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
       
    31  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      
       
    32  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
       
    33  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
       
    34  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   
       
    35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
       
    36  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    37  */
       
    38 
       
    39 
       
    40 /** \file   context.c 
       
    41  *  \brief  The Context-Engine is an OS independent module, which provides the
       
    42  *            infrustracture for switching from external contexts to the driver's context.
       
    43  *          This includes also the driver task itself , which invokes the 
       
    44  *            driver specific handlers in the driver's context.
       
    45  *          The OS specific implementation under this module (e.g. task-switching or 
       
    46  *            protection-locking) is provided by the OS abstraction layer (osapi.c).
       
    47  * 
       
    48  *  \see    context.h, osapi.c
       
    49  */
       
    50 
       
    51 
       
    52 #define __FILE_ID__  FILE_ID_125
       
    53 #include "osApi.h"
       
    54 #include "report.h"
       
    55 #include "context.h"
       
    56 #include "TWDriver.h"
       
    57 
       
    58 
       
    59 /** 
       
    60  * \fn     context_Create 
       
    61  * \brief  Create the module 
       
    62  * 
       
    63  * Allocate and clear the module object.
       
    64  * 
       
    65  * \note    
       
    66  * \param  hOs      - Handle to Os Abstraction Layer
       
    67  * \return Handle of the allocated object 
       
    68  * \sa     context_Destroy
       
    69  */ 
       
    70 TI_HANDLE context_Create (TI_HANDLE hOs)
       
    71 {
       
    72 	TI_HANDLE hContext;
       
    73 
       
    74 	/* allocate module object */
       
    75 	hContext = os_memoryAlloc (hOs, sizeof(TContext),MemoryNormal);
       
    76 	
       
    77 	if (!hContext)
       
    78 	{
       
    79 		WLAN_OS_REPORT (("context_Create():  Allocation failed!!\n"));
       
    80 		return NULL;
       
    81 	}
       
    82 	
       
    83     os_memoryZero (hOs, hContext, (sizeof(TContext)));
       
    84 
       
    85 	return (hContext);
       
    86 }
       
    87 
       
    88 
       
    89 /** 
       
    90  * \fn     context_Destroy
       
    91  * \brief  Destroy the module. 
       
    92  * 
       
    93  * Free the module memory.
       
    94  * 
       
    95  * \note   
       
    96  * \param  hContext - The module object
       
    97  * \return TI_OK on success or TI_NOK on failure 
       
    98  * \sa     context_Create
       
    99  */ 
       
   100 TI_STATUS context_Destroy (TI_HANDLE hContext)
       
   101 {
       
   102     TContext *pContext = (TContext *)hContext;
       
   103 
       
   104     /* Destroy the protection handle */
       
   105     os_protectDestroy (pContext->hOs, pContext->hProtectionLock);
       
   106 
       
   107     /* free module object */
       
   108 	os_memoryFree (pContext->hOs, pContext, sizeof(TContext));
       
   109 	
       
   110     return TI_OK;
       
   111 }
       
   112 
       
   113 
       
   114 /** 
       
   115  * \fn     context_Init 
       
   116  * \brief  Init required handles 
       
   117  * 
       
   118  * Init required handles.
       
   119  * 
       
   120  * \note    
       
   121  * \param  hContext  - The queue object
       
   122  * \param  hOs       - Handle to Os Abstraction Layer
       
   123  * \param  hReport   - Handle to report module
       
   124  * \return void        
       
   125  * \sa     
       
   126  */ 
       
   127 void context_Init (TI_HANDLE hContext, TI_HANDLE hOs, TI_HANDLE hReport)
       
   128 {
       
   129 	TContext *pContext = (TContext *)hContext;
       
   130 
       
   131     pContext->hOs     = hOs;
       
   132     pContext->hReport = hReport;
       
   133 	
       
   134     /* Create the module's protection lock and save its handle */
       
   135     pContext->hProtectionLock = os_protectCreate (pContext->hOs);
       
   136 }
       
   137 
       
   138 
       
   139 /** 
       
   140  * \fn     context_RegisterClient
       
   141  * \brief  Save client's parameters
       
   142  * 
       
   143  * This function is used by the Context clients in their init process, for registering 
       
   144  *   their information, 
       
   145  * This includes their callback function that should be invoked from the driver context
       
   146  *   when they are pending. 
       
   147  * 
       
   148  * \note   
       
   149  * \param  hContext - The module handle
       
   150  * \param  fCbFunc  - The client's callback function.
       
   151  * \param  hCbHndl  - The client's callback function handle.
       
   152  * \param  bEnable  - TRUE = Enabled.
       
   153  * \return TI_UINT32 - The index allocated for the client
       
   154  * \sa     
       
   155  */ 
       
   156 TI_UINT32 context_RegisterClient (TI_HANDLE       hContext,
       
   157                                   TContextCbFunc  fCbFunc,
       
   158                                   TI_HANDLE       hCbHndl,
       
   159                                   TI_BOOL         bEnable,
       
   160                                   char           *sName,
       
   161                                   TI_UINT32       uNameSize)
       
   162 {
       
   163 	TContext *pContext = (TContext *)hContext;
       
   164     TI_UINT32 uClientId = pContext->uNumClients;
       
   165 
       
   166     /* If max number of clients is exceeded, report error and exit. */
       
   167     if (uClientId == MAX_CLIENTS) 
       
   168     {
       
   169         TRACE0(pContext->hReport, REPORT_SEVERITY_ERROR , "context_RegisterClient() MAX_CLIENTS limit exceeded!!\n");
       
   170         return 0;
       
   171     }
       
   172 
       
   173     /* Save the new client's parameters. */
       
   174     pContext->aClientCbFunc[uClientId]  = fCbFunc;
       
   175     pContext->aClientCbHndl[uClientId]  = hCbHndl;
       
   176     pContext->aClientEnabled[uClientId] = bEnable;
       
   177     pContext->aClientPending[uClientId] = TI_FALSE;
       
   178 
       
   179 #ifdef TI_DBG
       
   180     if (uNameSize <= MAX_NAME_SIZE) 
       
   181     {
       
   182         os_memoryCopy(pContext->hOs, 
       
   183                       (void *)(pContext->aClientName[uClientId].sName),
       
   184                       (void *)sName, 
       
   185                       uNameSize);
       
   186         pContext->aClientName[uClientId].uSize = uNameSize;
       
   187     }
       
   188     else 
       
   189     {
       
   190         TRACE0(pContext->hReport, REPORT_SEVERITY_ERROR , "context_RegisterClient() MAX_NAME_SIZE limit exceeded!\n");
       
   191     }
       
   192 #endif /* TI_DBG */
       
   193 
       
   194     /* Increment clients number and return new client ID. */
       
   195     pContext->uNumClients++;
       
   196 
       
   197     TRACE2(pContext->hReport, REPORT_SEVERITY_INIT , "context_RegisterClient(): Client=, ID=%d, enabled=%d\n", uClientId, bEnable);
       
   198 
       
   199     return uClientId;
       
   200 }
       
   201 
       
   202 
       
   203 /** 
       
   204  * \fn     context_RequestSchedule
       
   205  * \brief  Handle client's switch to driver's context.
       
   206  * 
       
   207  * This function is called by a client from external context event.
       
   208  * It sets the client's Pending flag and requests the driver's task scheduling.
       
   209  * Thus, the client's callback will be called afterwards from the driver context.
       
   210  * 
       
   211  * \note   
       
   212  * \param  hContext   - The module handle
       
   213  * \param  uClientId  - The client's index
       
   214  * \return void 
       
   215  * \sa     context_DriverTask
       
   216  */ 
       
   217 void context_RequestSchedule (TI_HANDLE hContext, TI_UINT32 uClientId)
       
   218 {
       
   219 	TContext *pContext = (TContext *)hContext;
       
   220 
       
   221 #ifdef TI_DBG
       
   222     pContext->aRequestCount[uClientId]++; 
       
   223     TRACE3(pContext->hReport, REPORT_SEVERITY_INFORMATION , "context_RequestSchedule(): Client=, ID=%d, enabled=%d, pending=%d\n", uClientId, pContext->aClientEnabled[uClientId], pContext->aClientPending[uClientId]);
       
   224 #endif /* TI_DBG */
       
   225 
       
   226     /* Set client's Pending flag */
       
   227     pContext->aClientPending[uClientId] = TI_TRUE;
       
   228 
       
   229     /* 
       
   230      * If configured to switch context, request driver task scheduling.
       
   231      * Else (context switch not required) call the driver task directly.
       
   232 	 * OS_REQUEST_SCHEDULE is OS depend macro, in case that the Os not support scheduling
       
   233 	 * that macro should return TI_NOK.
       
   234      */
       
   235 	if(TI_OK != OS_REQUEST_SCHEDULE(pContext->hOs))
       
   236     {
       
   237         context_DriverTask (hContext);
       
   238     }
       
   239 }
       
   240 
       
   241 
       
   242 /** 
       
   243  * \fn     context_DriverTask
       
   244  * \brief  The driver task
       
   245  * 
       
   246  * This function is the driver's main task that always runs in the driver's 
       
   247  * single context, scheduled through the OS . 
       
   248  * Only one instantiation of this task may run at a time!
       
   249  * 
       
   250  * \note   
       
   251  * \param  hContext   - The module handle
       
   252  * \return void 
       
   253  * \sa     context_RequestSchedule
       
   254  */ 
       
   255 void context_DriverTask (TI_HANDLE hContext)
       
   256 {
       
   257 	TContext       *pContext = (TContext *)hContext;
       
   258     TContextCbFunc  fCbFunc;
       
   259     TI_HANDLE       hCbHndl;
       
   260     TI_UINT32       i;
       
   261 
       
   262     TRACE0(pContext->hReport, REPORT_SEVERITY_INFORMATION , "context_DriverTask():\n");
       
   263 
       
   264     /* For all registered clients do: */
       
   265 	for (i = 0; i < pContext->uNumClients; i++)
       
   266     {
       
   267         /* If client is pending and enabled */
       
   268         if (pContext->aClientPending[i]  &&  pContext->aClientEnabled[i])
       
   269         {
       
   270             #ifdef TI_DBG
       
   271                 pContext->aInvokeCount[i]++; 
       
   272                 TRACE1(pContext->hReport, REPORT_SEVERITY_INFORMATION , "Invoking - Client=, ID=%d\n", i);
       
   273             #endif /* TI_DBG */
       
   274 
       
   275             /* Clear client's pending flag */
       
   276             pContext->aClientPending[i] = TI_FALSE;
       
   277 
       
   278             /* Call client's callback function */
       
   279             fCbFunc = pContext->aClientCbFunc[i];
       
   280             hCbHndl = pContext->aClientCbHndl[i];
       
   281             fCbFunc(hCbHndl);
       
   282         }
       
   283     }
       
   284 }
       
   285 
       
   286 
       
   287 /** 
       
   288  * \fn     context_EnableClient / context_DisableClient
       
   289  * \brief  Enable a specific client activation
       
   290  * 
       
   291  * Called by the driver main when needed to enble/disable a specific event handling.
       
   292  * The Enable function also schedules the driver-task if the specified client is pending.
       
   293  * 
       
   294  * \note   
       
   295  * \param  hContext   - The module handle
       
   296  * \param  uClientId  - The client's index
       
   297  * \return void 
       
   298  * \sa     context_DriverTask
       
   299  */ 
       
   300 void context_EnableClient (TI_HANDLE hContext, TI_UINT32 uClientId)
       
   301 {
       
   302 	TContext *pContext = (TContext *)hContext;
       
   303 
       
   304 #ifdef TI_DBG
       
   305     if (pContext->aClientEnabled[uClientId])
       
   306     {
       
   307         TRACE0(pContext->hReport, REPORT_SEVERITY_ERROR , "context_EnableClient() Client  already enabled!!\n");
       
   308         return;
       
   309     }
       
   310     TRACE3(pContext->hReport, REPORT_SEVERITY_INFORMATION , "context_EnableClient(): Client=, ID=%d, enabled=%d, pending=%d\n", uClientId, pContext->aClientEnabled[uClientId], pContext->aClientPending[uClientId]);
       
   311 #endif /* TI_DBG */
       
   312 
       
   313     /* Enable client */
       
   314     pContext->aClientEnabled[uClientId] = TI_TRUE;
       
   315 
       
   316     /* If client is pending, schedule driver task */
       
   317     if (pContext->aClientPending[uClientId])
       
   318     {
       
   319         /* 
       
   320          * If configured to switch context, request driver task scheduling.
       
   321          * Else (context switch not required) call the driver task directly. 
       
   322          */
       
   323 		if (TI_OK != OS_REQUEST_SCHEDULE(pContext->hOs)) 
       
   324         {
       
   325             context_DriverTask (hContext);
       
   326         }
       
   327     }
       
   328 }
       
   329 
       
   330 void context_DisableClient (TI_HANDLE hContext, TI_UINT32 uClientId)
       
   331 {
       
   332 	TContext *pContext = (TContext *)hContext;
       
   333 
       
   334 #ifdef TI_DBG
       
   335     if (!pContext->aClientEnabled[uClientId])
       
   336     {
       
   337         TRACE0(pContext->hReport, REPORT_SEVERITY_ERROR , "context_DisableClient() Client  already disabled!!\n");
       
   338         return;
       
   339     }
       
   340     TRACE3(pContext->hReport, REPORT_SEVERITY_INFORMATION , "context_DisableClient(): Client=, ID=%d, enabled=%d, pending=%d\n", uClientId, pContext->aClientEnabled[uClientId], pContext->aClientPending[uClientId]);
       
   341 #endif /* TI_DBG */
       
   342 
       
   343     /* Disable client */
       
   344     pContext->aClientEnabled[uClientId] = TI_FALSE;
       
   345 }
       
   346 
       
   347 /** 
       
   348  * \fn     context_Print
       
   349  * \brief  Print module information
       
   350  * 
       
   351  * Print the module's clients parameters.
       
   352  * 
       
   353  * \note   
       
   354  * \param  hContext - The queue object
       
   355  * \return void
       
   356  * \sa     
       
   357  */ 
       
   358 
       
   359 #ifdef TI_DBG
       
   360 
       
   361 void context_Print(TI_HANDLE hContext)
       
   362 {
       
   363 	TContext *pContext = (TContext *)hContext;
       
   364     TI_UINT32 i;
       
   365 
       
   366     WLAN_OS_REPORT(("context_Print():  %d Clients Registered:\n", pContext->uNumClients));
       
   367     WLAN_OS_REPORT(("=======================================\n"));
       
   368 
       
   369 	for (i = 0; i < pContext->uNumClients; i++)
       
   370 	{
       
   371 		WLAN_OS_REPORT(("Client %d - %s: CbFunc=0x%x, CbHndl=0x%x, Enabled=%d, Pending=%d, Requests=%d, Invoked=%d\n",
       
   372                         i,
       
   373                         pContext->aClientName[i].sName,
       
   374                         pContext->aClientCbFunc[i],
       
   375                         pContext->aClientCbHndl[i],
       
   376                         pContext->aClientEnabled[i],
       
   377                         pContext->aClientPending[i],
       
   378                         pContext->aRequestCount[i],
       
   379                         pContext->aInvokeCount[i] ));
       
   380 	}
       
   381 }
       
   382 
       
   383 #endif /* TI_DBG */
       
   384 
       
   385