📄 fdi_que.c
字号:
/* ###########################################################################
### Intel Confidential
### Copyright (c) Intel Corporation 1995-2002
### All Rights Reserved.
### -------------------------------------------------------------------------
### Project: Flash Data Integrator
###
### Module: QUEUE.C - FDI Data Queue - prioritized message queue
### currently uses malloc, has scanning capabilities.
###
### $Archive: /FDI/SRC/COMMON/fdi_que.c $
### $Revision: 77 $
### $Date: 10/21/04 11:40a $
### $Author: Pcmcgint $
### $NoKeywords $
########################################################################### */
/*
*****************************************************************
* NOTICE OF LICENSE AGREEMENT
*
* This code is provided by Intel Corp., and the use is governed
* under the terms of a license agreement. See license agreement
* for complete terms of license.
*
* YOU MAY ONLY USE THE SOFTWARE WITH INTEL FLASH PRODUCTS. YOUR
* USE OF THE SOFTWARE WITH ANY OTHER FLASH PRODUCTS IS EXPRESSLY
* PROHIBITED UNLESS AND UNTIL YOU APPLY FOR, AND ARE GRANTED IN
* INTEL'S SOLE DISCRETION, A SEPARATE WRITTEN SOFTWARE LICENSE
* FROM INTEL LICENSING ANY SUCH USE.
*****************************************************************
*/
/* ### Include Files
* ################################# */
#include "fdi_type.h"
#ifdef CUSTOM_SEM_MTX
#include "fdi_mutx.h"
#endif
#include "fdi_ext.h"
#include "fdi_int.h"
#include "fdi_que.h"
/*#undef RESERVED_FIX*/
/* ### Local Declarations
* ################################# */
#ifndef WORD_LOW
#define WORD_LOW(x) (WORD)((x) & 0xffff)
#endif
#if (PACKET_DATA == TRUE)
#include "fdi_pckt.h"
#endif /* PACKET_DATA */
/* This mask is used to round values down to the nearest multiple of 4
*/
#define Q_DWORD_MASK 0xFFFC
/*
* This define is used to calculate the absolute minimum number of bytes
* needed to implement a queue of two items of one byte in size. If the
* Q_ALIGN_CHECKING option is set, an extra three bytes will be added to
* this value to allow for possible alignment shifting.
*/
/* E.5.1.762 Start */
/* Moved Q_MIN_SIZE to que.h */
/*
#if (Q_ERROR_CHECKING == TRUE)
#if (Q_ALIGN_CHECKING == FALSE)
#define Q_MIN_SIZE (sizeof(Q_DESCRIPTOR) + sizeof(Q_PRIORITY_HEADER) + \
(((sizeof(Q_ITEM_INFO) + 3) & Q_DWORD_MASK) * 2))
#else
#define Q_MIN_SIZE (sizeof(Q_DESCRIPTOR) + sizeof(Q_PRIORITY_HEADER) + \
(((sizeof(Q_ITEM_INFO) + 3) & Q_DWORD_MASK) * 2) + 3)
#endif
#endif
*/
/* E.5.1.762 End */
#if (Q_VERIFICATION == TRUE)
#define VALID_QUEUE_PTR(x) (BYTE)((x != NULL) && \
(x->queue_id ==WORD_LOW( (DWORD)x)) && \
(x->queue_signature == WORD_LOW(~(DWORD)x)))
#endif
/*
* Maximum number of queue items that can be in the queue at any given time.
* Used to reserve allocation control arrays
*/
/*
* Calculate the maximum number of queue items that is possible. This is used
* used to determine the size of, and manage, the queue control structures.
* Two worst case possibilities exist: 1) All zero data COMMAND items w/
* PRIORITY_HEADERs, 2) All zero data COMMAND items w/o PRIORITY_HEADERs. If
* the size of PRIORITY_HEADER is less than that of COMMAND plus
* Q_ITEM_INFO, then case 1 is the worst case, otherwise case 2. Two or Three
* is added to account for the q_descriptor and q_priority_header, plus 1 for
* rounding.
*/
/* E.5.0.690 Begin */
/*remove MAX_QUEUE_ITEMS, now defined in fdi_que.h*/
/* #define MAX_QUEUE_ITEMS ( (sizeof(Q_PRIORITY_HEADER) < (sizeof(COMMAND) + \
sizeof(Q_ITEM_INFO))) ? \
((((FDI_QUEUE_SIZE - sizeof(Q_DESCRIPTOR)) / \
((sizeof(Q_PRIORITY_HEADER) + \
sizeof(COMMAND)) + \
sizeof(Q_ITEM_INFO))) * \
2) + \
2) : \
(((FDI_QUEUE_SIZE - sizeof(Q_DESCRIPTOR)) - \
sizeof(Q_PRIORITY_HEADER)) / \
(sizeof(COMMAND) + \
sizeof(Q_ITEM_INFO)) + \
3) )
*/
/* E.5.0.690 End */
/* ### Type Definitions
* ################################# */
/*
* Node Control for FindItem
*/
typedef enum
{
Q_FIND_LAST,
Q_VISIT_EACH
} Q_NODE_CNTRL;
/* ### Local Declarations
* ################################# */
/* Queue buffer and allocation/free controls */
static BYTE Queue[FDI_QUEUE_SIZE];
static BYTE_PTR QitemPtr[MAX_QUEUE_ITEMS];
static WORD QitemSize[MAX_QUEUE_ITEMS];
static BYTE QitemFree[MAX_QUEUE_ITEMS];
/* ### Local Functions
* ################################# */
static Q_ERROR
FindItem(Q_DESC_PTR, VOID_PTR_PTR, WORD_PTR, Q_HDR_PTR *, BYTE, Q_NODE_CNTRL);
/* ### Global Declarations
* ################################# */
/*E.5.0.603.START*/
/* define these semaphores for static creation by GSM_MS initialization */
#if(SEM_CREATE_DESTROY == FALSE)
SEM_ID SEM_cntrl_sync; /* true when an item is in queue */
SEM_MTX_ID SEM_cntrl_mutex; /* mutex queue protection */
#endif
/*E.5.0.603.END*/
/* ### Global Functions
* ################################# */
#if (PERF_TEST == TRUE)
extern SEM_ID PERF_SEM_Bkgd;
#endif
/*############################################################################
*### Q_Create
*###
*### DESCRIPTION:
*### This function is used to create a new message queue. The capacity
*### of queue is given by the "max_queue_size" input parameter. The
*### maximum queue size is 65532 bytes, and the minumum size is 32 bytes.
*### The size includes both the space required for storing messages in
*### the queue, as well as space for the internal control structures
*### needed to manage the queue. The size should be an even multiple of
*### of 4 bytes -- if it is not, it will be rounded down to the nearest
*### multiple.
*###
*### If the application wants to control where the queue gets its memory
*### from, it can supply a pointer to memory for the queue to use in the
*### "queue_memory" input parameter. If the "queue_memory" parameter
*### is NULL, the queue code will attempt to allocate its own
*### memory by using the MALLOC macro. Allowing the queue to manage
*### its own memory is the preferred method, since it better protects the
*### queue's data from other processes, though this may not be possible
*### (or feasible) on every system.
*###
*### An error code will be returned indicating the success or failure
*### of the queue creation in the parameter "status_ptr".
*###
*### The queue's identifier is returned from the function as a Q_ID type.
*###
*### PARAMETERS:
*### IN:
*### max_queue_size - The maximum total size of the queue (bytes)
*### queue_memory_ptr - Address of memory to use for queue
*### OUT:
*### Returns the following errors codes in the status_ptr
*### Q_ERR_NONE
*### Q_ERR_INVALID_SIZE
*### Q_ERR_NO_MEMORY
*### Q_ERR_SEMAPHORE
*###
*### RETURNS:
*### the queue's identifier
*###*/
Q_ID
Q_Create(WORD max_queue_size, VOID_PTR queue_memory_ptr, Q_ERROR * status_ptr)
{
register BYTE_PTR queue_ptr = (BYTE_PTR) queue_memory_ptr;
#if (Q_ALIGN_CHECKING == TRUE)
WORD alignment_size;
#endif
/* Initialize queue allocation controls */
WORD i;
QitemFree[0] = 1;
QitemPtr [0] = Queue;
QitemSize[0] = FDI_QUEUE_SIZE;
for (i=1 ; i<MAX_QUEUE_ITEMS ; i++)
{
QitemFree[i] = 0;
QitemPtr [i] = NULL;
QitemSize[i] = 0;
}
*status_ptr = Q_ERR_NONE;
/* E.5.1.762 Start */
/*
Make sure the requested queue size is not too big. This can
prevent users from adding more than FFFF items to the queue.
*/
#if (Q_ERROR_CHECKING == TRUE)
if (max_queue_size > Q_MAX_SIZE)
{
*status_ptr = Q_ERR_INVALID_SIZE;
}
/* E.5.1.762 End */
/* Make sure the requested queue size is not too small */
if (max_queue_size < Q_MIN_SIZE)
{
*status_ptr = Q_ERR_INVALID_SIZE;
}
#endif
if (*status_ptr == Q_ERR_NONE)
{
/*
* If a memory region was supplied by the caller, store its address in
* the memory referenced by the "queue_id_ptr" input parameter.
*/
if (queue_memory_ptr != NULL)
{
queue_ptr = (BYTE_PTR) queue_memory_ptr;
}
/*
* Otherwise, try to allocate the memory needed for a queue of the
* requested size, and store its address.
*/
else
{
#if (Q_ALIGN_CHECKING == FALSE)
/* Allocate descriptor */
queue_ptr = (BYTE_PTR) FDI_MALLOC(sizeof(Q_DESCRIPTOR));
#else
/*
* Add 3 to the MALLOC size to ensure that we will be able to align
* our data regardless of where the memory is allocated from. If the
* memory is not available, return an error.
*/
queue_ptr = (BYTE_PTR) FDI_MALLOC(sizeof(Q_DESCRIPTOR) + 3);
#endif
/* If the memory is not available, return an error */
if (queue_ptr == NULL)
{
*status_ptr = Q_ERR_NO_MEMORY;
return (Q_ID) queue_ptr;
}
} /* ENDELSE queue_memory == NULL */
#if (Q_ALIGN_CHECKING == TRUE)
/*
* Make sure that the queue memory is DWORD aligned. The number of
* bytes that the memory pointer is advanced will be stored in
* alignment_size.
*/
alignment_size = (WORD) ((4 - (DWORD) queue_ptr) & 3);
queue_ptr += alignment_size;
/*
* If the memory was provided externally, subract the shift count from
* the total known size of the provided memory region.
*/
if (queue_memory_ptr != NULL)
{
max_queue_size -= alignment_size;
}
#endif
max_queue_size &= Q_DWORD_MASK;
/*
* keep track of the free space in the descriptor table with the field
* free_count
*/
/* Queue align checking was not originally used to adjust free count here */
#if (Q_ALIGN_CHECKING == FALSE)
((Q_DESC_PTR) queue_ptr)->free_count = max_queue_size -
sizeof(Q_DESCRIPTOR);
#else
((Q_DESC_PTR) queue_ptr)->free_count = max_queue_size -
(sizeof(Q_DESCRIPTOR) +3);
#endif
/*
* Indicate whether the memory was allocated or provided by the caller,
* and how far the pointer was shifted for alignment.
*/
/* E.5.1.762 Start */
#if (Q_ALIGN_CHECKING == TRUE)
if (queue_memory_ptr != NULL)
{
((Q_DESC_PTR) queue_ptr)->alignment_shift = 0;
}
else
{
((Q_DESC_PTR) queue_ptr)->alignment_shift = (BYTE) alignment_size;
}
#endif
/* E.5.1.762 End */
#if (Q_VERIFICATION == TRUE)
/* Set up the validation entries in the queue descriptor */
((Q_DESC_PTR) queue_ptr)->queue_id = WORD_LOW((DWORD) queue_ptr);
((Q_DESC_PTR) queue_ptr)->queue_signature = WORD_LOW(~(DWORD) queue_ptr);
#endif
#if(SEM_CREATE_DESTROY == TRUE)
/* create a binary semaphore for the sem_queue_cntrl_sync field of queue_ptr */
/*E.5.0.702.Start*/
((Q_DESC_PTR) queue_ptr)->sem_queue_cntrl_sync = SEM_BIN_CREATE();
/*E.5.0.702.End*/
#else /* SEM_CREATE_DESTROY */
/*E.5.0.702.Start*/
((Q_DESC_PTR) queue_ptr)->sem_queue_cntrl_sync = SEM_cntrl_sync;
/*E.5.0.702.End*/
#endif /* SEM_CREATE_DESTROY */
/*E.5.0.702.Start*/
if (((Q_DESC_PTR) queue_ptr)->sem_queue_cntrl_sync == NULL)
/*E.5.0.702.End*/
{
*status_ptr = Q_ERR_SEMAPHORE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -