////////////////////////////////////////////////////////////////////////////
//
// 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: dump_sema.c,v 1.1.2.1 2003/03/12 22:30:28 mohan Exp $
//
//////////////////////////////////////////////////////////////////////////////

/***************************************************************************/
/**
 * @file sema.c 
 * 
 * Semaphore handling routines.
 *   - Restriction of this implementation :: The wait queue is a FIFO, 
 *     should be priority based, in case the processes have priorities.
 ***************************************************************************/
#include <sys/sema.h>
#include <sys/process.h>

#ifdef CONFIG_SEMA	/* Include the functions only if configured by user */

/**
 * Array of Semaphore structures. They are used to keep track of allocated
 * semaphore's. Also used for other bookkeeping operations on Semaphore.
 */
semaphore sema_heap[MAX_SEMA] ;	/* Memory for allocating semaphores */

/**************************************************************************/
/**
 * Initilize the semaphores.
 * - Intialize the semaphore data structure
 * - Allocate the memory for the semaphore Queue's
 *
 * @return
 * 	None
 * 	
 * @note
 * 	None
 * 
 ***************************************************************************/
void sema_heap_init()
{
  unsigned int i = 0 ;
  for( ; i < MAX_SEMA; i++ ){
    sema_heap[i].sema_id = -1 ;
    alloc_q( &sema_heap[i].wait_q, MAX_SEMA_WAITQ,
             SEMA_Q, sizeof(char), i ) ;
  }
}


/**************************************************************************/
/**
 * Get the Semaphore ID. This function is used to create a new semaphore.
 * - A new semaphore is created if none with the given key exists.
 * - If flag = IPC_CREAT, then existing semaphore ID for the given key is 
 *   returned.
 * - If flag = IPC_EXCL, if semaphore exists for the given key return -1
 *
 * @param 
 * @return
 *   
 * @note
 * 	- nsems should be always 1. i.e. semaphore module supports only one 
 *	semaphore in the set.
 *   	- supported flags are IPC_CREAT and IPC_EXCL.	
 ***************************************************************************/
int sys_semget( int key, int nsems, int flag ) 
{
  int i = 0 ;

  if( (key >= MAX_SEMA) || (nsems != 1) )
    return -1 ;
#ifdef CONFIG_PRIVATE_SEM
  if( key == IPC_PRIVATE ){
    while( (i < N_PRIVATE_SEM) && (sys_sema[i].semid != -1) )
      i++ ;
    if( i == N_PRIVATE_SEM )
      return -1 ;
    key = i ;
  }
#endif
  if( sys_sema[key].semid != -1 ) {
    if( flag == IPC_CREAT )
      return key ;
    else
      return -1 ;
  }	
  sys_sema[key].semid = key ;
  sys_sema[key].count = 1 ;
  qinit( &sys_sema[key].wait_q ) ;
  return key ;
}


/**************************************************************************/
/**
 * @return
 *   
 * @note
 * 	- semnum is ignored. It is assumed to be 0.
 *	- cmd can be: IPC_RMID, GETVAL and SETVAL
 ***************************************************************************/
int sys_semctl( int semid, int semnum, int cmd, union semun arg ) 
{
  int return_value = 0 ;

  if( sys_sema[semid].semid == -1 ) return -1 ;
  switch( cmd ){
  case SETVAL :
    sys_sema[semid].count = arg.val ;
    break ;
  case GETVAL :
    return_value = sys_sema[semid].count ;
    break ;
  case IPC_RMID :
    if( sys_sema[semid].count <= 0 ){
      return_value = -1 ;	// ??
    }else{
      syss_sema[semid].semid = -1 ;
    }
    break ;
  default :
    return_value = -1 ;
  }
  return return_value ;
}


/**************************************************************************/
/**
 * 
 * @return
 * @note
 *	- nops is always assumed to be 1. 
 ***************************************************************************/
int sys_semop( int semid, struct sembuf *semoparray, int nops ) 
{
	
}

#endif	/* CONFIG_SEMA */
