/******************************************************/
/* Copyright (C) 2008 Arch Rock Corporation           */
/* License Agreement: refer to LICENSE.txt            */
/*                                                    */
/******************************************************/
  
#ifndef _ASYNC_H
#define _ASYNC_H   1

#ifdef __GNUC__
#include <sys/types.h>
#endif
#include <event.h>

/*! Disable global interrupt for 
 *  the start of a critical section.
 */
void atomic_begin();

/*! Enable global interrupt for 
 *  the end of a critical section.
 */
void atomic_end();


/*! Request a unique resource identifier that enables
 *  scheduling a continatuion from the interrupt context
 *  to Arch Rock's application context.  Note this call
 *  is safe to be invoked in the interrupt context.
 *
 *  \return a non-zero resource identifiier if succeed or
 *     ENFILE all unique resource identifier has been used up.
 *     Note that errno is not used since this is in the 
 *     interrupt context.
 *
 */
int16_t continuation();

/*! To schedule a continatuion from the interrupt context
 *  to Arch Rock's application context.  Note this call
 *  is safe to be invoked in the interrupt context.
 *
 *  @param[in] resid a valid resouce id return by continuation().
 *  @param[in] app_handler the continuation callback handler
 *             that will be fired in application context.
 *             If NULL is passed here, the call will fail.
 *  @param[in] resource no requirement here.
 *  @param[in] context user context
 *  \return 0 if succeed or EBUSY if the resource with 
 *         \em resid is busy or EINVAL if invalid parameters are passed.
 *          Note that errno is not used because this is in the
 *          interrupt context.
 *
 *  \section schedule_handler Callback Descriptions
 *  \subsection app_handler app_handler
 *     @param[in] event Type is SCH_CONTINUATION in #EventsEnum.
 *     @param[in] cbargs return \em resource in sch_continuation().
 *     @param[in] context return \em context in sch_continuation().
 *  \return None.
 *
 *  \section sch_continuation_exp Code Example
 *  \code
 *  #include <sys/async.h>
 *
 *  int16_t  g_resid;
 *
 *  void __TIMER1_OVF_vect() {
 *    // interrupt context code
 *    g_resid = continuation();
 *    sch_continuation(g_resid, user_handler, NULL, NULL);
 *  }
 *
 *  void user_handler(event_t event, void * cbaargs, void * context) {
 *    // ... user context action here
 *  }
 * \endcode
 */
int16_t sch_continuation(int16_t resid, 
			 void (*app_handler)(event_t event,
					     void * cbargs,
					     void * context),
			 void * resource,
			 void * context);


/*! Bind a callback handler to a particular interrupt vector that are 
 *  partially used by or shared with the kernel.  Kernel services that
 *  requires interrupt context notification should use this to bind
 *  with notification handler.  Note that this API is platform 
 *  dependent and the handler will be fired within
 *  interrupt context.  Once bind has called, subsequent call of this function
 *  will replace the old handler with a new handler.
 *  
 *  @param[in] intr_enum platform dependent interrupt enumeration number.
 *                       Refer to #InterruptTypesEnum for details.
 *  @param[in] async_handler the continuation callback handler
 *             that will be fired in interrupt context.
 *             If NULL is passed here, the call will fail.
 *  @param[in] resource pass NULL, will be ignored
 *  @param[in] context pass NULL, will be igonred
 *  \return 0 if succeed or EINVAL if invalid.  Note errno
 *          is not used because this is in the interrupt context.
 *   
 *  \section async_io_handler Callback Descriptions
 *  \subsection async_handler async_handler
 *     @param[in] event type is ASYNC_IO in #EventsEnum.
 *                      subtype defines which interrupt is
 *                      firing using #InterruptTypesEnum defined
 *                      in platform specific header files.
 *     @param[in] cbargs return NULL
 *     @param[in] context return NULL
 *  \return None.
 */
int16_t async_irqbind(int16_t intr_enum,
		      void (*async_io_handler)(event_t event,
					       void * cbargs,
					       void * context),
		      void * resource,
		      void * context);

/*! Unbind a previously installed callback handler to a particular interrupt vector 
 *  that are partially used by or shared with the kernel.  
 *  Note that this API is platform dependent and the handler will be fired within
 *  interrupt context.  Once unbind has called, subsequent interrupts firing will not
 *  be notified.
 *  
 *  @param[in] intr_enum platform dependent interrupt enumeration number.
 *                       Refer to #InterruptTypesEnum for details.
 *
 *  \return 0 if succeed or EINVAL if invalid.  Note errno
 *          is not used because this is in the interrupt context.
 */
int16_t async_irqunbind(int16_t intr_enum);

/*! A system call that closes a continuation identifier 
 *  so that it may be reused.  This is safe to be called
 *  within the interrupt context.
 *
 *  \return 0 on success, EINVAL for bad identifier, and
 *     EBUSY for waiting for an action to be executed
 *           before resource identifier can be freed.
 */
int16_t continuation_close(int16_t id);

#endif  // _ASYNC_H
