/* * 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 #include #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