mirror of
https://github.com/Stichting-MINIX-Research-Foundation/netbsd.git
synced 2025-08-12 15:39:27 -04:00
553 lines
23 KiB
C
553 lines
23 KiB
C
/*-
|
|
* Copyright (C) 2001-2003 by NBMK Encryption Technologies.
|
|
* All rights reserved.
|
|
*
|
|
* NBMK Encryption Technologies provides no support of any kind for
|
|
* this software. Questions or concerns about it may be addressed to
|
|
* the members of the relevant open-source community at
|
|
* <tech-crypto@netbsd.org>.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following
|
|
* disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS 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 THE COPYRIGHT
|
|
* OWNER OR 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.
|
|
*/
|
|
|
|
static char const n8_id[] = "$Id: n8_contextM.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
|
|
/*****************************************************************************/
|
|
/** @file n8_contextM.c
|
|
* @brief Contains Crypto Context management Interface.
|
|
*
|
|
* Managing the context memory is left to the user.
|
|
* SAPI provides interfaces to allocate and initialize a context entry, and to
|
|
* free an entry. The user must allocate and initialize a context entry before
|
|
* it can be used (presumably when an SSL connection is opened), specify which
|
|
* context entry to use in the calls that require context memory, and finally
|
|
* free the context entry when finished (presumably when an SSL connection is
|
|
* closed). Limited error checking is done, and if the user makes errors such as
|
|
* specifying the wrong context entry for a call (e.g., specifying a context
|
|
* entry containing an ARC4 key for encrypting an SSL packet on a connection
|
|
* established with DES in the cipher suite), incorrect results will be
|
|
* produced without a warning or error occurring.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* Revision history:
|
|
* 05/20/03 brr Remove obsolete functions resultHandlerFreeContext &
|
|
* n8_numCommandsToLoadContext
|
|
* 05/20/02 brr Free the request for all error conditions.
|
|
* 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
|
|
* 03/29/02 hml Now validate the unit and the context in
|
|
* N8_Read/WriteContext. (BUGS 657, 658).
|
|
* 03/26/02 hml Enhanced N8_AllocateContext and N8_FreeContext to retrieve
|
|
* the status from the lower level calls. (Bugs 637,642).
|
|
* 03/26/02 brr Allocate the data buffer as part of the API request.
|
|
* 03/22/02 hml Removed unneeded sessionID param from call to
|
|
* N8_ContextMemAlloc.
|
|
* 03/18/02 brr Removed obsolete references to queue_p & validateContextHandle.
|
|
* 02/28/02 brr Do not include any QMgr include files.
|
|
* 02/18/02 brr Support queue selection.
|
|
* 02/15/02 brr Moved context memory management to the driver.
|
|
* 01/25/02 bac Changed allocation search algorithm to always start at the
|
|
* index after the one last assigned. This should be a much
|
|
* better search than simply starting at the beginning every
|
|
* time, which clusters the allocated contexts from 0..n.
|
|
* 01/22/02 bac Added function n8_numCommandsToLoadContext.
|
|
* 01/22/02 bac Conditionally removed the clearing of context memory when
|
|
* N8_FreeContext is called.
|
|
* 12/07/01 brr Removed userID to reduce memory consumption until supported.
|
|
* 12/07/01 mel Fixed bug #404: added checks for aligned address.
|
|
* 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
|
|
* 11/12/01 hml Fixed bug for freeing lock not held.
|
|
* 11/08/01 mel Fixed bug #289 : by passing unitID parameter
|
|
* 11/08/01 mel Fixed comments (bug #292).
|
|
* 11/08/01 mel Fixed bug #299 : N8_ReadContext does not check length parameter.
|
|
* Fixed bug #300 : N8_WriteContext does not check length parameter.
|
|
* 11/07/01 hml Ensured that validateContextHandle only release a semaphore
|
|
* if it has acquired it (BUG 236).
|
|
* 11/05/01 hml Added some error checking and the structure verification.
|
|
* 10/11/01 brr Fixed memory leak in N8_ReadContext.
|
|
* 10/02/01 bac Added use of RESULT_HANDLER_WARNING in all result handlers.
|
|
* 10/01/01 hml Completed multichip support.
|
|
* 09/20/01 hml Added multichip support.
|
|
* 09/20/01 bac The interface to the command block generators changed and now
|
|
* accept the command block buffer. All calls to cb_ea methods
|
|
* changed herein.
|
|
* 09/18/01 bac Reformat to standardize, changed interaction with cb_ea
|
|
* functions.
|
|
* 09/13/01 mel Added event parameter to N8_FreeContext.
|
|
* 08/29/01 mel Fixed bug #191 : bad DBG print statement.
|
|
* 08/27/01 mel Added Write/Read context APIs.
|
|
* 08/20/01 hml Fixed bug in allocate context getting wrong semaphore.
|
|
* 08/08/01 hml Added use of semaphore to protect the context table.
|
|
* 08/06/01 bac Fixed a bug in the result handler where it was freeing a
|
|
* request though it should not.
|
|
* 07/31/01 bac Added call to N8_preamble for all public interfaces.
|
|
* 07/30/01 bac Pass chip id to createEARequestBuffer.
|
|
* 06/25/01 bac Small bug fix for allocationg ccm_register_gp.
|
|
* 06/20/01 mel Corrected use of kernel memory.
|
|
* 05/21/01 bac Converted to use N8_ContextHandle_t.
|
|
* 05/04/01 bac Removed include of n8_define as it duplicated n8_util
|
|
* definitions.
|
|
* 04/16/01 mel Original version.
|
|
****************************************************************************/
|
|
/** @defgroup Context Context Management
|
|
*/
|
|
|
|
|
|
#include "n8_cb_ea.h" /* contains encryption/authentication qeueu declarations */
|
|
|
|
#include "n8_util.h"
|
|
#include "n8_API_Initialize.h"
|
|
#include "n8_common.h"
|
|
#include "n8_malloc_common.h"
|
|
|
|
|
|
/*****************************************************************************
|
|
* N8_AllocateContext
|
|
*****************************************************************************/
|
|
/** @ingroup Context
|
|
* @brief Allocates a context entry for future use.
|
|
*
|
|
* The context index of the allocated context memory entry is returned in
|
|
* contextIndex. The context memory entry must then be initialized by a call
|
|
* to Encrypt Initialize or Packet Initialize before it can be used in
|
|
* encrypt/decrypt or packet level operations. This call can fail if all
|
|
* context entries have been allocated. To avoid running out of context entries,
|
|
* N8_FreeContext should be called when a context entry is no longer needed.
|
|
*
|
|
* @param contextHandle_p WO: Unsigned integer >= 0 and less than
|
|
* 2 power of 18 specifying the context entry in context memory allocated to
|
|
* the caller and whose contents are initialized with Context.
|
|
*
|
|
* @return
|
|
* contextHandler_p - context entry in allocated context memory.
|
|
* ret - returns N8_STATUS_OK if successful or Error value.
|
|
*
|
|
* @par Locks:
|
|
* This function acquires the context list semaphore from the queue structure.
|
|
*
|
|
* @par Errors:
|
|
* N8_NO_MORE_RESOURCE - There are no more context memory entries available
|
|
* for allocation. The call may succeed at a later
|
|
* time if context entries are freed.
|
|
* N8_MALLOC_FAILED - for some reasons malloc is failed
|
|
*
|
|
*****************************************************************************/
|
|
N8_Status_t N8_AllocateContext(N8_ContextHandle_t *contextHandle_p,
|
|
N8_Unit_t unitID)
|
|
|
|
{
|
|
|
|
N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
|
|
unsigned int index;
|
|
N8_Unit_t validatedUnit = unitID;
|
|
|
|
DBG(("N8_AllocateContext\n"));
|
|
|
|
do
|
|
{
|
|
ret = N8_preamble();
|
|
CHECK_RETURN(ret);
|
|
|
|
CHECK_OBJECT(contextHandle_p, ret);
|
|
|
|
ret = N8_ContextMemAlloc(&validatedUnit, &index);
|
|
|
|
if (ret == N8_STATUS_OK)
|
|
{
|
|
contextHandle_p->index = index; /* return allocated context index */
|
|
contextHandle_p->inUse = N8_TRUE;
|
|
contextHandle_p->unitID = validatedUnit;
|
|
/* set the structure pointer to the correct state */
|
|
contextHandle_p->structureID = N8_CONTEXT_STRUCT_ID;
|
|
|
|
DBG(("Context index %d\n", index));
|
|
}
|
|
} while(FALSE);
|
|
|
|
DBG(("N8_AllocateContext - FINISHED\n"));
|
|
|
|
return ret;
|
|
} /* N8_AllocateContext */
|
|
|
|
|
|
/*****************************************************************************
|
|
* N8_FreeContext
|
|
*****************************************************************************/
|
|
/** @ingroup Context
|
|
* @brief Frees previously allocated context entry and allows for its later re-use.
|
|
*
|
|
* ContextIndex specifies the context memory entry to be deallocated. The contents
|
|
* of the entry are cleared to zero when this call is made. Any further calls made
|
|
* with this ContextIndex value will fail (until the entry is re-allocated by an
|
|
* N8_AllocateContext call). Context memory entries must be freed when no
|
|
* longer needed to avoid exhausting the supply. Note that by adding the
|
|
* MEMORY_IN_PROGRESS state we are able to avoid having to use the context
|
|
* lock in the callback function.
|
|
*
|
|
* @param ctxHndl RO: A previously allocated context entry value as returned
|
|
* from N8_AllocateContext that is to be freed.
|
|
*
|
|
* @return
|
|
* ret - returns N8_STATUS_OK if successful or Error value.
|
|
*
|
|
* @par Errors:
|
|
* N8_INVALID_PARAMETER - The value of contextIndex is less than 0 or more
|
|
* than (2 power of 18) - 1.
|
|
* N8_UNALLOCATED_CONTEXT - contextIndex does not specify an allocated context
|
|
* entry index.
|
|
*
|
|
* @par Locks:
|
|
* This function acquires the context list semaphore from the queue structure.
|
|
* Note that we make sure the lock is released before we queue the request.
|
|
*
|
|
* @par Assumptions:
|
|
* Limited error checking is done, and if the user makes errors such as
|
|
* specifying the wrong context entry for a call (e.g., specifying a context
|
|
* entry containing an ARC4 key for encrypting an SSL packet on a connection
|
|
* established with DES in the cipher suite), incorrect results will be
|
|
* produced without a warning or error occurring
|
|
*****************************************************************************/
|
|
N8_Status_t N8_FreeContext(N8_ContextHandle_t ctxHndl,
|
|
N8_Event_t *event_p)
|
|
|
|
{
|
|
N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
|
|
|
|
DBG(("N8_FreeContext\n"));
|
|
|
|
do
|
|
{
|
|
ret = N8_preamble();
|
|
CHECK_RETURN(ret);
|
|
|
|
if (ctxHndl.inUse != N8_TRUE)
|
|
{
|
|
ret = N8_UNALLOCATED_CONTEXT;
|
|
break;
|
|
}
|
|
|
|
if (ctxHndl.structureID != N8_CONTEXT_STRUCT_ID)
|
|
{
|
|
ret = N8_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
ret = N8_ContextMemFree(ctxHndl.unitID, ctxHndl.index);
|
|
|
|
DBG(("ctxHndl.index = %d\n", ctxHndl.index));
|
|
|
|
} while(FALSE);
|
|
|
|
if (event_p != NULL)
|
|
{
|
|
N8_SET_EVENT_FINISHED(event_p, N8_EA);
|
|
}
|
|
|
|
DBG(("N8_FreeContext - FINISHED\n"));
|
|
|
|
return ret;
|
|
|
|
} /* N8_FreeContext */
|
|
|
|
/*****************************************************************************
|
|
* N8_WriteContext
|
|
*****************************************************************************/
|
|
/** @ingroup Context
|
|
* @brief Writes a context entry for future use.
|
|
*
|
|
* Writes ContextLength number of bytes from Context into the crypto controller
|
|
* context memory entry denoted by ContextHandle. Up to 512 bytes may be loaded
|
|
* into a context entry; if less than 512 bytes are supplied the remaining bytes
|
|
* will be set to bytes of 0. The content / format of the bytes depends on the
|
|
* intended use, and is specified in the Crypto Controller specification [CCH].
|
|
* However this routine simply treats them as uninterpreted values; no checking
|
|
* or processing of the bytes written to the context entry is done. All previous
|
|
* contents of the context entry are overwritten and lost. It is important to note
|
|
* that the context information is treated by the hardware as a sequence of 32-bit
|
|
* values; the byte values written to a hardware context by this call are written
|
|
* by the hardware as a series of 32-bit quantities, and these 32-bit values must
|
|
* be in the appropriate big endian or little endian format depending on the byte
|
|
* order of the host processor. A context read from the hardware via N8_ReadContext
|
|
* is read in this same way, and is always in the proper format to be written back
|
|
* via N8_WriteContext
|
|
*
|
|
* @param contextHandle RO: The handle of a previously allocated context
|
|
* entry as returned by N8_AllocateContext.
|
|
|
|
* @param context_p RO: The bytes to be written to the context entry
|
|
* @param contextLength RO: Length of Context in bytes, from 0 to 512
|
|
* bytes inclusive. A length of 0 is legal,
|
|
* but no bytes will actually be written
|
|
* @param event_p RW: On input, if null the call is synchronous
|
|
* and no event is returned. The operation is
|
|
* complete when the call returns. If non-null,
|
|
* then the call is asynchronous; an event is
|
|
* returned that can be used to determine when
|
|
* the operation completes
|
|
*
|
|
*
|
|
* @return
|
|
* ret - returns N8_STATUS_OK if successful or Error value.
|
|
*
|
|
* @par Locks:
|
|
* This function acquires the context list semaphore from the queue structure.
|
|
*
|
|
* @par Errors:
|
|
* N8_NO_MORE_RESOURCE - There are no more context memory entries available
|
|
* for allocation. The call may succeed at a later
|
|
* time if context entries are freed.
|
|
* N8_MALLOC_FAILED - for some reasons malloc is failed
|
|
* N8_INVALID_INPUT_SIZE - context length is more than 512
|
|
* N8_UNALIGNED_ADDRESS - passed address (context_p) is not 32-bit aligned
|
|
*
|
|
*****************************************************************************/
|
|
N8_Status_t N8_WriteContext(N8_ContextHandle_t contextHandle,
|
|
N8_Buffer_t *context_p,
|
|
uint32_t contextLength,
|
|
N8_Event_t *event_p )
|
|
|
|
{
|
|
|
|
N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
|
|
API_Request_t *req_p = NULL; /* request buffer */
|
|
N8_Boolean_t unitValid;
|
|
|
|
DBG(("N8_WriteContext\n"));
|
|
|
|
do
|
|
{
|
|
ret = N8_preamble();
|
|
CHECK_RETURN(ret);
|
|
|
|
CHECK_OBJECT(context_p, ret);
|
|
|
|
if ((int)context_p % 4)
|
|
{
|
|
ret = N8_UNALIGNED_ADDRESS;
|
|
break;
|
|
}
|
|
|
|
if (contextLength > EA_CTX_Record_Byte_Length)
|
|
{
|
|
ret = N8_INVALID_INPUT_SIZE;
|
|
break;
|
|
}
|
|
|
|
CHECK_STRUCTURE(contextHandle.structureID,
|
|
N8_CONTEXT_STRUCT_ID,
|
|
ret);
|
|
|
|
unitValid = n8_validateUnit(contextHandle.unitID);
|
|
if (!unitValid)
|
|
{
|
|
ret= N8_INVALID_UNIT;
|
|
break;
|
|
}
|
|
|
|
ret = N8_ContextMemValidate(contextHandle.unitID, contextHandle.index);
|
|
CHECK_RETURN(ret);
|
|
|
|
/* allocate request buffer */
|
|
ret = createEARequestBuffer(&req_p,
|
|
contextHandle.unitID,
|
|
N8_CB_EA_WRITECONTEXT_NUMCMDS,
|
|
resultHandlerGeneric,
|
|
CONTEXT_ENTRY_SIZE);
|
|
CHECK_RETURN(ret);
|
|
|
|
/* create "write buffer to context memory" command */
|
|
ret = cb_ea_writeContext(req_p,
|
|
req_p->EA_CommandBlock_ptr,
|
|
contextHandle.index,
|
|
context_p,
|
|
contextLength);
|
|
CHECK_RETURN(ret);
|
|
/* nothing needs to be done in the result handler. it will be called only
|
|
* to print a debug messag if an error occurs. */
|
|
|
|
/* send command to write to specified context memory */
|
|
QUEUE_AND_CHECK(event_p, req_p, ret);
|
|
HANDLE_EVENT(event_p, req_p, ret);
|
|
|
|
} while(FALSE);
|
|
|
|
DBG(("N8_WriteContext - FINISHED\n"));
|
|
|
|
/*
|
|
* Deallocate the request if we arrived from an error condition.
|
|
*/
|
|
if (ret != N8_STATUS_OK)
|
|
{
|
|
freeRequest(req_p);
|
|
}
|
|
return ret;
|
|
} /* N8_WriteContext */
|
|
|
|
|
|
/*****************************************************************************
|
|
* N8_ReadContext
|
|
*****************************************************************************/
|
|
/** @ingroup Context
|
|
* @brief Reads a context entry.
|
|
*
|
|
* Copies ContextLength number of bytes from the crypto controller context
|
|
* memory context entry specified by ContextHandle into Context. The contents
|
|
* of the context memory entry are unchanged. Up to 512 bytes [This value should
|
|
* really be some sort of configuration constant or value defined that the user
|
|
* can determine at run time.] may be read from a context entry. If the
|
|
* specified context entry has not previously been initialized with
|
|
* N8_EncryptInitialize or N8_PacketInitialize or written with an N8_WriteContext
|
|
* call, then the bytes returned are undefined. The actual content / format of
|
|
* the bytes returned depends on how the context entry was used, and is
|
|
* specified in the Crypto Controller specification [CCH]. However
|
|
* N8_ReadContext simply treats them as uninterpreted values, suitable for
|
|
* reloading at a later time using N8_WriteContext. No checking or processing
|
|
* of the bytes read from the context entry is done. It is important to note
|
|
* that the context information is treated by the hardware as a sequence of
|
|
* 32-bit values; the byte values read from a hardware context and returned
|
|
* by this call are returned as a series of 32-bit quantities, and these
|
|
* 32-bit values will be returned in either big endian or little endian format
|
|
* depending on the byte order of the host processor.
|
|
*
|
|
* @param contextHandle RO: The handle of a previously allocated context
|
|
* entry as returned by N8_AllocateContext.
|
|
|
|
* @param context_p RO: The bytes to be written to the context entry
|
|
* @param contextLength RO: Length of Context in bytes, from 0 to 512
|
|
* bytes inclusive. A length of 0 is legal,
|
|
* but no bytes will actually be written
|
|
* @param event_p RW: On input, if null the call is synchronous
|
|
* and no event is returned. The operation is
|
|
* complete when the call returns. If non-null,
|
|
* then the call is asynchronous; an event is
|
|
* returned that can be used to determine when
|
|
* the operation completes
|
|
*
|
|
* @return
|
|
* ret - returns N8_STATUS_OK if successful or Error value.
|
|
*
|
|
* @par Locks:
|
|
* This function acquires the context list semaphore from the queue structure.
|
|
*
|
|
* @par Errors:
|
|
* N8_NO_MORE_RESOURCE - There are no more context memory entries available
|
|
* for allocation. The call may succeed at a later
|
|
* time if context entries are freed.
|
|
* N8_MALLOC_FAILED - for some reasons malloc is failed
|
|
* N8_INVALID_INPUT_SIZE - context length is more than 512
|
|
* N8_UNALIGNED_ADDRESS - passed address (context_p) is not 32-bit aligned
|
|
*
|
|
*****************************************************************************/
|
|
N8_Status_t N8_ReadContext(N8_ContextHandle_t contextHandle,
|
|
N8_Buffer_t *context_p,
|
|
uint32_t contextLength,
|
|
N8_Event_t *event_p )
|
|
|
|
{
|
|
|
|
N8_Status_t ret = N8_STATUS_OK; /* return status*/
|
|
API_Request_t *req_p = NULL; /* request buffer */
|
|
N8_Buffer_t *contextMemory_p = NULL;
|
|
uint32_t contextMemory_a;
|
|
N8_Boolean_t unitValid;
|
|
|
|
DBG(("N8_ReadContext\n"));
|
|
|
|
do
|
|
{
|
|
ret = N8_preamble();
|
|
CHECK_RETURN(ret);
|
|
|
|
CHECK_OBJECT(context_p, ret);
|
|
|
|
if ((int)context_p % 4)
|
|
{
|
|
ret = N8_UNALIGNED_ADDRESS;
|
|
break;
|
|
}
|
|
|
|
if (contextLength > EA_CTX_Record_Byte_Length)
|
|
{
|
|
ret = N8_INVALID_INPUT_SIZE;
|
|
break;
|
|
}
|
|
|
|
CHECK_STRUCTURE(contextHandle.structureID,
|
|
N8_CONTEXT_STRUCT_ID,
|
|
ret);
|
|
|
|
unitValid = n8_validateUnit(contextHandle.unitID);
|
|
if (!unitValid)
|
|
{
|
|
ret= N8_INVALID_UNIT;
|
|
break;
|
|
}
|
|
|
|
ret = N8_ContextMemValidate(contextHandle.unitID, contextHandle.index);
|
|
CHECK_RETURN(ret);
|
|
|
|
/* allocate request buffer */
|
|
ret = createEARequestBuffer(&req_p,
|
|
contextHandle.unitID,
|
|
N8_CB_EA_READCONTEXT_NUMCMDS,
|
|
resultHandlerGeneric,
|
|
CONTEXT_ENTRY_SIZE);
|
|
CHECK_RETURN(ret);
|
|
|
|
contextMemory_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
|
|
contextMemory_a = req_p->qr.physicalAddress + req_p->dataoffset;
|
|
|
|
req_p->copyBackTo_p = context_p;
|
|
req_p->copyBackFrom_p = contextMemory_p;
|
|
req_p->copyBackSize = contextLength;
|
|
|
|
/* create "write buffer to context memory" command */
|
|
ret = cb_ea_readContext(req_p,
|
|
req_p->EA_CommandBlock_ptr,
|
|
contextHandle.index,
|
|
contextMemory_a,
|
|
contextLength);
|
|
CHECK_RETURN(ret);
|
|
|
|
/* send command to write to specified context memory */
|
|
QUEUE_AND_CHECK(event_p, req_p, ret);
|
|
HANDLE_EVENT(event_p, req_p, ret);
|
|
|
|
} while(FALSE);
|
|
|
|
DBG(("N8_ReadContext - FINISHED\n"));
|
|
|
|
/*
|
|
* Deallocate the request if we arrived from an error condition.
|
|
*/
|
|
if (ret != N8_STATUS_OK)
|
|
{
|
|
freeRequest(req_p);
|
|
}
|
|
return ret;
|
|
} /* N8_ReadContext */
|
|
|
|
|