////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002 Xilinx, Inc.  All rights reserved.
//
// Xilinx, Inc.
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A 
// COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
// ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR 
// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE 
// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.  
// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO 
// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO 
// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 
// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE.
// 
//
// $Id: queue.c,v 1.1.2.2 2003/03/18 19:01:35 mohan Exp $
//
//////////////////////////////////////////////////////////////////////////////

/**************************************************************************/
/**
 * @file queue.c 
 *
 * This contains the Queue Handling routines.
 ***************************************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/queue.h>
#include <sys/mem.h>


/**************************************************************************/
/**
 * Initialise the Queue's - Allocate array of memory to the Queue. Called
 * during initilaization.
 *
 * @param	queue is the queue of items.
 * @param	max_items is the maximum queue length.
 * @param	size is size of the elements in the queue.
 * @param 	qtype is the type of Q. Each Q is allocated a static memory
 * @param 	qno is the queue number, In case of multiple queue's of 
 * 		the same type.
 *
 * @return
 * 	None
 * 	
 * @note
 * 	None
 * 
 ***************************************************************************/
void alloc_q( queuep queue, unsigned char max_items, 
		unsigned char qtype, unsigned short size, unsigned char qno ) 
{
	queue->item_count = queue->qfront = queue->qend = 0 ;
	queue->max_items = max_items ;
	queue->item_size = size ;
	if( qtype != MSG_Q )
		alloc_pidq_mem( queue, qtype, qno ) ; 
	#ifdef CONFIG_MSGQ
	else 
		alloc_msgq_mem( queue, qno ) ;
	#endif
	/* Check for NULL */
}


/**************************************************************************/
/**
 * Intialize the Queue. 
 *
 * @param	queue is the queue of items.
 * 
 * @return
 * 	None
 * 	
 * @note
 * 	None
 * 
 ***************************************************************************/
void qinit( queuep queue ) 
{
	queue->item_count = queue->qfront = queue->qend = 0 ;
}


/**************************************************************************/
/**
 * Enqueue the item in the Queue.
 * 
 * @param	queue is the queue of items.
 * @param	item is the queue element.
 * @param 	key for insertion into the Queue. Can be priority.
 *
 * @return
 * 	None
 * 	
 * @note
 * 	key is not used currently
 * 
 ***************************************************************************/
void enq( queuep queue, const void *item, unsigned short key ) 
{
	unsigned char qend = queue->qend ;
	
	if( queue->item_count == queue->max_items ) {
		return ;	/* Queue full */
	}
	memcpy((queue->items+(qend*queue->item_size)),item,queue->item_size);
	queue->qend = (qend+1)%(queue->max_items) ;
	queue->item_count++ ;
}

/**************************************************************************/
/**
 * Dequeue the process from the Queue, based on the schemes.
 * 
 * @param 	queue is the queue of items.
 * @param	item is buffer where queue element is returned. 
 * 		If queue is empty then NULL is returned.
 * @param	key for removing from the Queue.
 *
 * @return
 * - Queue element is returned in item.
 * - Null is assigned to item if Error.
 *   
 * @note
 * 	None
 * 
 ***************************************************************************/
void deq( queuep queue, void *item, unsigned short key ) 
{
	unsigned char qfront = queue->qfront ;
	
	if( queue->item_count == 0 ) {
		item = NULL ;
		return ;	/* Queue EMPTY */
	}
	memcpy(item,(queue->items+(qfront*queue->item_size)),queue->item_size);
	queue->qfront = (qfront+1)%(queue->max_items) ;
	queue->item_count-- ;
	return ;
}

/**
 * Enqueue the item in the Queue.
 * 
 * @param	queue is the queue of items.
 * @param	item is the queue element.
 * @param 	key for insertion into the Queue. Can be priority.
 *
 * @return
 * 	None
 * 	
 * @note
 * 	key is not used currently
 * 
 ***************************************************************************/
void penq( queuep queue, unsigned char item, unsigned short key ) 
{
	unsigned char qend = queue->qend ;
        unsigned char * citems = (unsigned char *)(queue->items);

	
	if( queue->item_count == queue->max_items ) {
		return ;	/* Queue full */
	}
        citems[qend] = item;
	queue->qend = (qend+1)%(queue->max_items) ;
	queue->item_count++ ;
}

/**************************************************************************/
/**
 * Dequeue the process from the Queue, based on the schemes.
 * 
 * @param 	queue is the queue of items.
 * @param	item is buffer where queue element is returned. 
 * 		If queue is empty then NULL is returned.
 * @param	key for removing from the Queue.
 *
 * @return
 * - Queue element is returned in item.
 * - Null is assigned to item if Error.
 *   
 * @note
 * 	None
 * 
 ***************************************************************************/
void pdeq( queuep queue, unsigned char *item, unsigned short key ) 
{
	unsigned char qfront = queue->qfront ;
	unsigned char *citems = (unsigned char *) (queue->items);
	if( queue->item_count == 0 ) {
		*item = 255 ;
		return ;	/* Queue EMPTY */
	}
	// memcpy(item,(queue->items+(qfront*queue->item_size)),queue->item_size);
        *item = (unsigned char) (citems[qfront]);
	queue->qfront = (qfront+1)%(queue->max_items) ;
	queue->item_count-- ;
	return ;
}

/**************************************************************************/
/**
 * Delete the Element from the Queue.
 *
 * @param 	queue is the queue of items.
 * @param	item is buffer where queue element is returned. 
 * 		If queue is empty then NULL is returned.
 * 		
 * @return
 * - Queue element is returned in item.
 * - Null is assigned to item if Error.
 *   
 * @note
 * - Since the Queue implementation is array, this operation is very 
 *   expensive as other entries needs to be copied. But hopefully this 
 *   wld not be called often. (Called during process kill.. )
 * - Function included only if CONFIG_PROCESS_KILL is defined (os_config.h)
 * 
 ***************************************************************************/
#ifdef CONFIG_PROCESS_KILL
signed char delq( queuep queue, unsigned char item ) 
{
  unsigned char qfront = queue->qfront ;
  unsigned char qend = queue->qend ;
  unsigned char item_count = queue->item_count ;
  unsigned char max_items = queue->max_items ;
  unsigned int item_size = queue->item_size ;
  unsigned char *citems = (unsigned char *) (queue->items);      	
  if( item_count == 0 ) {
    return -1 ;	/* Queue EMPTY */
  }
  while( (item_count) && (item != citems[qfront])) {
    // memcmp(item,(queue->items+(qfront*item_size)),item_size)){
    item_count -- ;
    qfront = (qfront+1)%max_items ;
  }
  if( !item_count ) return -1 ;
  if( qfront == queue->qfront )
    queue->qfront = (qfront+1)%max_items ;
  else {
    unsigned int temp = qfront ;
    while( qfront != qend ) {
      qfront = (qfront+1)%max_items ;
      //memcpy((queue->items+(temp*item_size)), 
      // (queue->items+(qfront*item_size)),item_size);
      citems[temp] = citems[qfront];
      temp = qfront ;
    }
    queue->qend = (qend+max_items-1)%max_items ;
  }
  queue->item_count-- ;
  return 0 ;
}
#endif /* CONFIG_PROCESS_KILL */
