// Copyright(c) 2017, Intel Corporation
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
/**
* @file event.h
* @brief Functions for registering events and managing the lifecycle for
* `fpga_event_handle`s.
*
* OPAE provides an interface to asynchronous events that can be generated by
* different FPGA resources. The event API provides functions to register for
* these events; associated with every event a process has registered for is an
* fpga_event_handle, which encapsulates the OS-specific data structure for
* event objects. On Linux, an fpga_event_handle can be used as a file
* descriptor and passed to select(), poll(), epoll() and similar functions to
* wait for asynchronous events.
*/
#ifndef __FPGA_EVENT_H__
#define __FPGA_EVENT_H__
#include <opae/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Initialize an event_handle
*
* Platform independent way to initialize an event_handle used for
* notifications from the driver to application. For Linux, this function
* creates an eventfd and returns the eventfd file descriptor in
* `*event_handle`.
*
* @param[out] event_handle Pointer to event handle variable.
*
* @returns FPGA_OK on success. FPGA_INVALID_PARAM if `event_handle` is NULL.
* FPGA_NOT_SUPPORTED if platform does not support events.
*/
fpga_result fpgaCreateEventHandle(fpga_event_handle *event_handle);
/**
* Destroy an event_handle
*
* Destroy handle and free resources. On Linux this corresponds
* to closing the file descriptor pointed to by handle
*
* @note fpgaDestroyEventHandle() requires the address of an
* event_handle as created by fpgaCreateEventHandle(). Passing
* any other value results in undefined behavior.
*
* @param[in] event_handle Pointer to handle to be destroyed
*
* @returns FPGA_OK on success. FPGA_INVALID_PARAM if `event_handle` is NULL.
*/
fpga_result fpgaDestroyEventHandle(fpga_event_handle *event_handle);
/**
* Get OS object from event handle
*
* Check validity of event handle, and get the OS object used to
* subscribe and unsubscribe to events. On Linux, the object corresponds
* to a file descriptor.
*
* @param[in] eh Event handle to get the descriptor value from
* @param[out] fd integer to store the descriptor value
*
* @returns FPGA_OK on success. FPGA_INVALID_PARAM if `event_handle` is invalid.
*/
fpga_result fpgaGetOSObjectFromEventHandle(const fpga_event_handle eh, int *fd);
/**
* Register an FPGA event
*
* This function tells the driver that the caller is interested in notification
* for the event specified by the type and flags pair.
*
* The event_handle points to an OS specific mechanism for event notification.
* An event_handle is associated with only a single event.
*
* In case of user interrupts, the flags parameter will be used to specify
* the vector ID. The value of the flags parameter indicates the vector ID,
* no bit encoding is used.
*
* @todo define if calling fpgaRegisterEvent multiple times with the
* same event_handle is an error condition or if it is silently ignored.
*
* @param[in] handle Handle to previously opened FPGA resource.
* @param[in] event_type Type of event
* @param[in] event_handle Handle to previously opened resource for event
* notification.
* @param[in] flags Optional argument for specifying additional
* information about event. For example irq number
* for interrupt events.
* @returns FPGA_OK on success. FPGA_INVALID_PARAM if handle does not refer to
* a resource supporting the requested event, or if event_handle is not valid.
* FPGA_EXCEPTION if an internal exception occurred while accessing the handle
* or the event_handle. On Linux: FPGA_NO_DAEMON if the driver does not support
* the requested event and there is no FPGA Daemon (fpgad) running to proxy it.
*/
fpga_result fpgaRegisterEvent(fpga_handle handle,
fpga_event_type event_type,
fpga_event_handle event_handle,
uint32_t flags);
/**
* Unregister an FPGA event
*
* This function tells the driver that the caller is no longer interested in
* notification for the event associated with the event_handle
*
* The event_handle points to an OS specific mechanism for event notification.
* An event_handle is associated with only a single event.
*
* @todo define if calling fpgaUnregisterEvent multiple times with the
* same event_handle is an error condition or if it is silently ignored.
*
* @param[in] handle Handle to previously opened FPGA resource.
* @param[in] event_type Type of event to unregister.
* @param[in] event_handle Handle to previously registered resource for event
* notification.
* @returns FPGA_OK on success. FPGA_INVALID_PARAM if handle does
* not refer to a resource supporting the requested event,
* or if event_handle is not valid. FPGA_EXCEPTION if an
* internal error occurred accessing the handle or the
* event_handle.
*/
fpga_result fpgaUnregisterEvent(fpga_handle handle,
fpga_event_type event_type,
fpga_event_handle event_handle);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // __FPGA_EVENT_H__