/* usb/semaphor.h
 *
 * (c) 2002 Simtec Electronics
 *
 * Ben Dooks
 *
 * semaphor defines and functions
 *
 * $Id: semaphor.h,v 1.9 2003/08/06 15:56:11 ben Exp $
 *
 * This Library file is part of the Simtec Electronics USB stack development
 *   suite.
 * Specific licence is granted to use this file by third parties for the
 *   development of USB device drivers.
 *
*/

#ifndef __USB_SEMAPHOR_H
#define __USB_SEMAPHOR_H "$Id: semaphor.h,v 1.9 2003/08/06 15:56:11 ben Exp $"

/* ---------- public modul specific ---------- */
/* access modes */
#define SEMAPHOR_ACCESS_READ        0x00000000
#define SEMAPHOR_ACCESS_WRITE       0x00000001
/* only internal usage */
#define SEMAPHOR_ACCESS_DROP        0x00000002
#define SEMAPHOR_ACCESS_CREATE      0x00000003
#define SEMAPHOR_ACCESS_REFERENCE   0x00000004
/* grants access without interruption by other processes
   immediately after getting the semaphor */
#define SEMAPHOR_ACCESS_PROTECTED   0x80000000
/* allows you to get access to a data structur where
   a dropping is pending */
#define SEMAPHOR_ACCESS_IGNORE_DROP 0x40000000
#define SEMAPHOR_ACCESS_MASK        0x3FFFFFFF

/* function results */
#define SEMAPHOR_RESULT_QUEUED             3
#define SEMAPHOR_RESULT_ACCESS             2
#define SEMAPHOR_RESULT_DROP_STRUCTUR      1
#define SEMAPHOR_RESULT_OK                 0
#define SEMAPHOR_RESULT_BUSY_SUPER        -1
#define SEMAPHOR_RESULT_BUSY              -2
#define SEMAPHOR_RESULT_BUSY_SUB          -3
#define SEMAPHOR_RESULT_STRUCTUR_DROPPED  -4
#define SEMAPHOR_RESULT_UNDEFINED_ACCESS  -5
#define SEMAPHOR_RESULT_NOT_ENOUGH_MEMORY -6
#define SEMAPHOR_RESULT_INVALID_PARAMETER -7


/* !!!!!!!!!!! data structures !!!!!!!!!! */
/** Semaphor structure
 */
struct semaphor_s {
  long valid;
  void *master_semaphor;
  long references;
  long references_sub;
  long pending_read_processes;
  long pending_read_processes_sub;
  long running_read_processes;
  long running_read_processes_sub;
  long pending_write_processes;
  long pending_write_processes_sub;
  long running_write_processes;
  long running_write_processes_sub;
  /* Only used at IRQ-Handling */
  int irqs_disabled;
};


typedef struct semaphor_s semaphor;

/** creates a semaphor
 */
extern semaphor * semaphor_create(semaphor *, int *);

/** free a semaphor
 */
extern int semaphor_drop(semaphor *act_semaphor);

/** free a request on a semaphor
 */
extern int semaphor_drop_request(semaphor *act_semaphor,
				 usb_wait_t *waiting_mode);


#if defined(DEBUG) || defined(CORE_DEBUG)
#define USB_DEBUG_SEMAPHOR_CLAIM
#endif

#ifndef USB_DEBUG_SEMAPHOR_CLAIM
/** Claim a semaphor
@param act_semaphor Semophore to wait on
@param access_mode type of claim
@param waiting_mode waiting structure
*/
extern int semaphor_claim(semaphor *act_semaphor,
			  unsigned long access_mode,
			  usb_wait_t *waiting_mode);
#else
extern int semaphor_claim_dbg(semaphor *act_semaphor,
			      unsigned long access_mode,
			      usb_wait_t *waiting_mode,
			      const char *src, int line );
#define semaphor_claim(a,b,c) semaphor_claim_dbg(a,b,c,__FILE__,__LINE__)
#endif

/** Releases a semaphor and checks it
@param act_semaphor Semophore to release
*/
extern int semaphor_release_and_check(semaphor *act_semaphor);

/** Releases a semaphor
@param act_semaphor Semophore to release
*/
extern void semaphor_release(semaphor *act_semaphor);

/** Adds a reference to a  Semophore
@param act_semaphor Semophore
*/
extern int semaphor_reference_register(semaphor *act_semaphor);

/** Removes a reference to a semophore
@param act_semaphor Semophore
*/
extern int semaphor_reference_deregister(semaphor *act_semaphor);

#endif /* SEMAPHOR_H */
