Files
xtensa_dsp/driver/xrp-user/include/xrp_api.h
2022-09-13 10:33:44 +08:00

613 lines
19 KiB
C

/*
* Copyright (c) 2016 - 2017 Cadence Design Systems Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*!
* \file xrp_api.h
* \brief This section defines XRP API.
*
* General API properties:
* - All status pointers can be NULL.
* - Reference counting is not meant to work across host/DSP boundary, i.e.
* DSP may not retain the host buffer.
* - A buffer allocated for one device can be passed as command parameter to
* a different device; implementation should do reasonable thing, e.g. use
* the original data if possible or transparently migrate it to suitable
* memory.
* - A group of API calls may be host side only, DSP side only, or usable on
* both sides. When it's usable on both sides there may be additional
* restrictions on the DSP side.
*/
#ifndef _XRP_API_H
#define _XRP_API_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* User API.
*/
struct xrp_device;
struct xrp_queue;
struct xrp_buffer;
struct xrp_buffer_group;
struct xrp_event;
struct xrp_report;
/*!
* Status codes of XRP calls.
*/
enum xrp_status {
/*! Call completed successfully. */
XRP_STATUS_SUCCESS,
/*! Call failed. */
XRP_STATUS_FAILURE,
/*! Call has not completed. */
XRP_STATUS_PENDING,
};
enum xrp_access_flags {
XRP_READ = 0x1,
XRP_WRITE = 0x2,
XRP_READ_WRITE = 0x3,
};
/*!
* Types of information that may be queried for a buffer object.
*/
enum xrp_buffer_info {
/*! Size of the buffer. */
XRP_BUFFER_SIZE_SIZE_T,
/*! Host pointer of the buffer. */
XRP_BUFFER_HOST_POINTER_PTR,
XRP_BUFFER_PHY_ADDR,
XRP_BUFFER_USER_ADDR,
};
/*!
* Types of information that may be queried for a buffer group object.
*/
enum xrp_buffer_group_info {
/*! Access flags associated with a buffer. Requires buffer index. */
XRP_BUFFER_GROUP_BUFFER_FLAGS_ENUM,
/*! Number of buffers in the buffer group. Buffer index is ignored. */
XRP_BUFFER_GROUP_SIZE_SIZE_T,
};
#define XRP_NAMESPACE_ID_SIZE 16
/*!
* \defgroup device_api Device API
* These calls are available on the host side and on the DSP side with the
* following restriction:
* - only device 0 may be opened.
* @{
*/
/*!
* Open device by index.
* A device is reference counted and is opened with reference count of 1.
* Devices are numbered sequentially starting at 0, they can be probed with
* simple loop.
* \param idx: device index to open
* \param[out] status: operation status
* \return pointer to the opened device or NULL in case of error
*/
struct xrp_device *xrp_open_device(int idx, enum xrp_status *status);
/*!
* Increment device reference count.
*/
void xrp_retain_device(struct xrp_device *device);
/*!
* Decrement device reference count (and free associated resources once the
* counter gets down to zero).
*/
void xrp_release_device(struct xrp_device *device);
/*!
* @}
*/
/*!
* \defgroup buffer_api Buffer API
* These calls are available on the host side and on the DSP side with the
* following restriction:
* - buffers may not be created on the DSP side.
* @{
*/
/*!
* Create memory buffer and allocate device-specific storage (host_ptr == NULL)
* or use host buffer (host_ptr != NULL, treated as virtual address in the
* current process).
* A buffer is reference counted and is created with reference count of 1.
* \param[out] status: operation status
*/
struct xrp_buffer *xrp_create_buffer(struct xrp_device *device,
size_t size, void *host_ptr,
enum xrp_status *status);
/*!
* Increment buffer reference count.
*/
void xrp_retain_buffer(struct xrp_buffer *buffer);
/*!
* Decrement buffer reference count (and free the storage if it was allocated
* once the counter gets down to zero).
*/
void xrp_release_buffer(struct xrp_buffer *buffer);
/*!
* Map subbuffer of the buffer. Buffer may be mapped multiple times.
*
* \param map_flags: access to the mapping requested by the mapper. Access
* to buffers on DSP side is subject to restrictions set by the host side.
* \param[out] status: operation status
*/
void *xrp_map_buffer(struct xrp_buffer *buffer, size_t offset, size_t size,
enum xrp_access_flags map_flags, enum xrp_status *status);
/*!
* Unmap previously mapped buffer.
* \param[out] status: operation status
*/
void xrp_unmap_buffer(struct xrp_buffer *buffer, void *p,
enum xrp_status *status);
/*!
* Get information about the buffer object.
*
* \param info: information type to retrieve.
* \param[out] out: pointer to return information to.
* \param out_sz: size of out buffer.
* \param[out] status: operation status
*/
void xrp_buffer_get_info(struct xrp_buffer *buffer, enum xrp_buffer_info info,
void *out, size_t out_sz, enum xrp_status *status);
/*!
* @}
*/
/*!
* \defgroup buffer_group_api Buffer Group API
* These calls are available on the host side and on the DSP side with the
* following restrictions:
* - buffer groups may not be created on the DSP side;
* - existing buffer groups may not be modified on the DSP side.
* @{
*/
/*!
* Create a group of shared buffers. Group is reference counted and is
* created with reference count of 1.
* \param[out] status: operation status
*/
struct xrp_buffer_group *xrp_create_buffer_group(enum xrp_status *status);
/*!
* Increment buffer group reference count.
*/
void xrp_retain_buffer_group(struct xrp_buffer_group *group);
/*!
* Decrement group reference count (and free it once the counter gets down
* to zero).
*/
void xrp_release_buffer_group(struct xrp_buffer_group *group);
/*!
* Add buffer to the group and get its index.
* This adds a reference to the buffer.
*
* \param access_flags: granted access. User of the buffer on the DSP side
* will be able to map it only for this type of access.
* \param[out] status: operation status
*/
size_t xrp_add_buffer_to_group(struct xrp_buffer_group *group,
struct xrp_buffer *buffer,
enum xrp_access_flags access_flags,
enum xrp_status *status);
/*!
* Put new buffer to the existing index in the group.
* When operation succeeds it releases the buffer previously contained at
* that index and adds a reference to the new buffer.
*
* \param access_flags: granted access. User of the buffer on the DSP side
* will be able to map it only for this type of access.
* \param[out] status: operation status
*/
void xrp_set_buffer_in_group(struct xrp_buffer_group *group,
size_t index,
struct xrp_buffer *buffer,
enum xrp_access_flags access_flags,
enum xrp_status *status);
/*!
* Get buffer from the group by its index.
* Buffer must be freed with release_buffer.
* \param[out] status: operation status
*/
struct xrp_buffer *xrp_get_buffer_from_group(struct xrp_buffer_group *group,
size_t idx,
enum xrp_status *status);
/*!
* Get information about the buffer group object.
*
* \param info: information type to retrieve.
* \param idx: buffer index (if applicable).
* \param[out] out: pointer to return information to.
* \param out_sz: size of out buffer.
* \param[out] status: operation status
*/
void xrp_buffer_group_get_info(struct xrp_buffer_group *group,
enum xrp_buffer_group_info info, size_t idx,
void *out, size_t out_sz,
enum xrp_status *status);
/*!
* @}
*/
/*!
* \defgroup queue_api Queue API
* These calls are available only on the host side.
* @{
*/
/*!
* Create queue to the default namespace of the device.
* Queue is an ordered device communication channel. Queue is reference
* counted and is created with reference count of 1.
* \param[out] status: operation status
*/
struct xrp_queue *xrp_create_queue(struct xrp_device *device,
enum xrp_status *status);
/*!
* Create queue to the specified namespace of the device.
* Queue is an ordered device communication channel. Queue is reference
* counted and is created with reference count of 1.
* \param[out] status: operation status
*/
struct xrp_queue *xrp_create_ns_queue(struct xrp_device *device,
const void *nsid,
enum xrp_status *status);
/*!
* Create queue to the specified namespace of the device with specific
* priority.
* Queue is an ordered device communication channel. Queue is reference
* counted and is created with reference count of 1.
* \param[out] status: operation status
*/
struct xrp_queue *xrp_create_nsp_queue(struct xrp_device *device,
const void *nsid,
int priority,
enum xrp_status *status);
/*!
* Increment queue reference count.
*/
void xrp_retain_queue(struct xrp_queue *queue);
/*!
* Decrement queue reference count (and free it once the counter gets down
* to zero).
*/
void xrp_release_queue(struct xrp_queue *queue);
/*!
* @}
*/
/*!
* \defgroup event_api Event API
* These calls are available only on the host side.
* @{
*/
/*!
* Increment event reference count.
*/
void xrp_retain_event(struct xrp_event *event);
/*!
* Decrement event reference count (and free it once the counter gets down
* to zero).
*/
void xrp_release_event(struct xrp_event *event);
/*!
* Get status of the event/associated command.
* The function may be called at any time, it sets *status to
* XRP_STATUS_PENDING if the command has not been executed yet, or to the
* command execution status. See status description of xrp_run_command_sync()
* for the description of command execution status.
* \param[out] status: operation status
*/
void xrp_event_status(struct xrp_event *event, enum xrp_status *status);
/*!
* @}
*/
/*!
* \defgroup communication_api Communication API
* These calls are available only on the host side.
* @{
*/
/*
* Even more internal API related to command passing between cores.
* These are tightly coupled to the host-DSP communication model and
* are likely to be changed/enhanced as the model evolves.
*/
/*!
* Synchronously send command from host to DSP.
*
* When this is invoked on the host it synchronously runs a command on DSP,
* passing a group of shared buffers and two additional (small) buffers
* with opaque command description (in_data) and results (out_data).
*
* in_data is used at the function call and is not referenced afterwards.
* out_data is updated with the value returned by DSP before the function
* returns.
*
* Optimal processing is guaranteed for in_data and out_data buffers not
* exceeding 16 bytes in size. Larger buffers may require additional data
* copying depending on the implementation.
*
* status is the result of command execution. Command execution is
* successful if the command was delivered to the DSP and the response was
* delivered back. Otherwise the command execution has failed. IOW execution
* success means that the out_data contains command-specific response received
* from the DSP, execution failure means that out_data does not contain useful
* information.
*
* \param[out] status: operation status
*/
void xrp_run_command_sync(struct xrp_queue *queue,
const void *in_data, size_t in_data_size,
void *out_data, size_t out_data_size,
struct xrp_buffer_group *buffer_group,
enum xrp_status *status);
/*!
* Asynchronously send command from host to DSP.
*
* When this is invoked on the host it queues a command to DSP,
* passing a group of shared buffers and two additional (small) buffers
* with opaque command description (in_data) and results (out_data).
*
* in_data is used at the function call and is not referenced afterwards.
* out_data must stay valid after this function call until command completion,
* at which point it is updated with the value returned by DSP.
*
* Optimal processing is guaranteed for in_data and out_data buffers not
* exceeding 16 bytes in size. Larger buffers may require additional data
* copying depending on the implementation.
*
* If event is non-NULL then a pointer to an event corresponding to the
* queued command is returned. This event can be waited for with xrp_wait,
* it is signaled when the command execution is complete.
* The returned event object is reference counted and is created with
* reference count of 1.
*
* status is the result of command enqueuing. Command enqueuing is
* successful if the command was enqueued on the host side and an associated
* event has been returned (if requested). Otherwise the command enqueuing has
* failed. IOW enqueuing success means that if event is non-NULL then *event
* contains valid event, enqueuing failure means that *event does not contain
* useful information.
*
* \param[out] status: operation status
*/
void xrp_enqueue_command(struct xrp_queue *queue,
const void *in_data, size_t in_data_size,
void *out_data, size_t out_data_size,
struct xrp_buffer_group *buffer_group,
struct xrp_event **event,
enum xrp_status *status);
/*!
* Wait for the event.
* Waiting for already signaled event completes immediately.
* Successful completion of this function does not alter the event state,
* i.e. the event remains signaled.
* status is the result of waiting, not the result of the command execution.
* Use xrp_event_status() to get the command execution status.
* \param[out] status: operation status
*/
void xrp_wait(struct xrp_event *event, enum xrp_status *status);
/*!
* Wait for any event in the group.
* Waiting for a group with already signaled event completes immediately.
* Successful completion of this function does not alter the event state,
* i.e. signaled events remain signaled.
* status is the result of waiting, not the result of the command execution.
* Use xrp_event_status() with individual events to get the corresponding
* command execution status.
*
* \param[in] event: an array of pointers to events to wait for
* \param[i] n_events: number of events in the events array
* \param[out] status: operation status
* \return index of a completed event in the event array
*/
size_t xrp_wait_any(struct xrp_event **event, size_t n_events,
enum xrp_status *status);
int xrp_add_report_item_with_id(struct xrp_report *report,
int (*cb)(void*context,void*data),
int report_id,
void* context,
size_t data_size);
int xrp_add_report_item(struct xrp_report *report,
int (*cb)(void*context,void*data),
void* context,
size_t data_size);
void xrp_remove_report_item(struct xrp_report *report,int report_id);
struct xrp_report *xrp_create_reporter(struct xrp_device *device,size_t size);
int xrp_release_reporter(struct xrp_device *device,struct xrp_report *report);
void xrp_import_dma_buf(struct xrp_device *device, int fd,enum xrp_access_flags flag ,uint64_t *phy_addr,
uint64_t *user_addr,size_t* size,enum xrp_status *status);
void xrp_release_dma_buf(struct xrp_device *device, int fd,enum xrp_status *status);
void xrp_flush_dma_buf(struct xrp_device *device, int fd,enum xrp_access_flags flag ,enum xrp_status *status);
/*!
* @}
*/
/*!
* \defgroup dsp_specific_api DSP-specific Interface (Library-Style)
* These calls are available only on the DSP side.
* @{
*/
/*!
* Check if there's a command from the host in the hardware queue.
* Returns XRP_STATUS_PENDING if the queue is empty or XRP_STATUS_SUCCESS
* if there is a command ready for processing.
*
* The check is quick and may be issued in any context.
*/
enum xrp_status xrp_device_poll(struct xrp_device *device);
/*!
* Check if there's a command from the host in the hardware queue and invoke
* command handler if there's one.
* Returns XRP_STATUS_PENDING if the queue is empty, or the status returned by
* the command handler.
*/
enum xrp_status xrp_device_dispatch(struct xrp_device *device);
/*!
* Function type for command handler.
*
* This callback is called on the DSP side to process queued command.
* in_data, out_data and buffer_group correspond to the same parameters of the
* host side API calls.
*
* On return from this function buffer group and individual buffer reference
* counters shall be restored to their entry values. out_data buffer shall be
* updated with command return value.
* Neither in_data nor out_data may be referenced after this function returns.
*
* Return value shall describe whether xrp_command_handler itself was
* successful or not, not the command it was requested to run.
* I.e. if the command was not recognized or its handler could not be called
* due to insufficient memory, that's XRP_STATUS_FAILURE returned in status.
* The host will also receive XRP_STATUS_FAILURE as a completion status.
* If the command was run that's XRP_STATUS_SUCCESS regardless of the
* command-specific status, which should be returned in out_data.
*
* \param handler_context: context that was passed to the
* xrp_device_register_namespace
*/
typedef enum xrp_status
(xrp_command_handler)(void *handler_context,
const void *in_data, size_t in_data_size,
void *out_data, size_t out_data_size,
struct xrp_buffer_group *buffer_group);
/*!
* Register namespace handler.
*
* There may be only one handler for a namespace, second attempt to register
* a handler for the same namespace will fail.
*
* \param device: device for which namespace handler is registered
* \param nsid: namespace identifier, XRP_NAMESPACE_ID_SIZE bytes long
* \param handler: pointer to the handler function
* \param handler_context: first argument that will be passed to the handler
* function
* \param[out] status: operation status
*/
void xrp_device_register_namespace(struct xrp_device *device,
const void *nsid,
xrp_command_handler *handler,
void *handler_context,
enum xrp_status *status);
/*!
* Unregister namespace handler.
*
* Only registered namespace handler may be unregistered.
*
* \param device: device for which namespace handler is registered
* \param nsid: namespace identifier, XRP_NAMESPACE_ID_SIZE bytes long
* \param[out] status: operation status
*/
void xrp_device_unregister_namespace(struct xrp_device *device,
const void *nsid,
enum xrp_status *status);
/*!
* Enable or disable shared memory cache management.
* Note that this call does not change memory caching attributes, it only
* enables flushing and invalidating used regions of shared memory in the
* XRP code.
*
* \param device: device for which shared memory cache management state is
* changed
* \param enable: whether cache management shall be enabled (non-zero) or
* disabled (0)
*/
void xrp_device_enable_cache(struct xrp_device *device, int enable);
/*!
* @}
*/
/*!
* Helper function that terminates fast simulation.
*/
void xrp_exit(void);
#ifdef __cplusplus
}
#endif
#endif