Skip to content

Instantly share code, notes, and snippets.

@erincandescent
Created June 4, 2014 15:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erincandescent/f386b33f6943e9fb3a9c to your computer and use it in GitHub Desktop.
Save erincandescent/f386b33f6943e9fb3a9c to your computer and use it in GitHub Desktop.
udirect.h
#ifndef UDIRECT_H
#define UDIRECT_H
#if !defined(UDIRECT_VERSION)
#error UDIRECT_VERSION must be defined(supported: 0x000)
#elif (UDIRECT_VERSION != 0x000)
#error Unsupported UDIRECT_VERSION
#endif
#ifndef _UDI_H
#error udi.h must be included first
#endif
#ifndef _UDI_PHYSIO_H
#error udi_physio.h must be included first
#endif
#define UDIRECT_STAT_MUST_COPY (UDI_STAT_META_SPECIFIC | 0)
#define UDIRECT_BIND_CB_NUM 1
#define UDIRECT_BUF_CB_NUM 2
typedef struct {
udi_cb_t gcb;
} udirect_bind_cb_t;
/*! Buffer is mapped device memory */
#define UDIRECT_BUF_FLAG_IS_MAPPED (1 << 0)
/*! Buffer is mapped coherently (driver does not need to perform udirect_sync ops) */
#define UDIRECT_BUF_FLAG_IS_COHERENT (1 << 1)
/*! Buffer is cached in processor local caches.
* For coherent buffers, the driver MUST use udirect_*_barrier operations if
* it is not using udirect_sync_req.
*/
#define UDIRECT_BUF_FLAG_IS_CACHED (1 << 2)
typedef struct {
udi_cb_t gcb;
udi_buf_t *buf;
void *private;
udi_ubit32_t flags
} udirect_buf_cb_t;
typedef void udirect_query_req_op_t(udirect_bind_cb_t *cb);
/*! Returns whether the UDirect implementation has the ability to map device
* memory as the backing store of a buffer. */
#define UDIRECT_CAP_CAN_MAP (1 << 0)
/*! Returns the result of querying the UDirect implementation for its'
* capabilities. `caps` may contain the `UDIRECT_CAP_CAN_MAP` bit set; all
* other bits are reserved.
*
* `granularity` returns the minimum granularity that must be met by the device
* memory to be mappable (if UDIREC_CAP_CAN_MAP is returned). All buffer
* segments must be aligned to a multiple of this value, and have size a
* multiple of this value.
*/
typedef void udirect_query_ack_op_t(
udirect_bind_cb_t *cb,
udi_ubit32_t caps,
udi_size_t granularity);
#define UDIRECT_MAP_DISPOSITION_DONT_CARE (0)
#define UDIRECT_MAP_DISPOSITION_NEVER (1)
#define UDIRECT_MAP_DISPOSITION_PREFER (2)
#define UDIRECT_MAP_DISPOSITION_MUST (3)
#define UDIRECT_MAP_REQ_MUST_MAP (1 << 0)
#define UDIRECT_MAP_REQ_MAY_DISCARD (1 << 1)
#define UDIRECT_MAP_REQ_SET_COHERENCY(disposition) ((disposition) << 24)
#define UDIRECT_MAP_REQ_SET_CACHEABILITY(disposition) ((disposition) << 28)
#define UDIRECT_MAP_REQ_GET_COHERENCY(flags) ((flags) >> 24 & 3)
#define UDIRECT_MAP_REQ_GET_CACHEABILITY(flags) ((flags) >> 28 & 3)
/*! Request that the implementation map the passed device memory addresses as
* the backing store for `buf`.
*
* `cb` is the bind CB
* `buf` is the buffer to be mapped
* `regset_idx` has the same meaning as for udi_pio_map
* `num_parts` is the number of entries in `parts`
* `parts` is a 64-bit scatter-gather list, in driver mapped format,
* containing a list of the segments of the buffer to be mapped.
* All addresses are offets from the base of the window pointed
* to by `regset_idx`
* `flags` is a set of properties controlling the behaviour of the
* mapping
*
* If `UDIRECT_MAP_REQ_MUST_MAP` is not set, then invoking this method will
* always succeed, unless the implementation experiences a memory exhaustion
* situation.
*
* In all successful cases, `buf` is resized to match exactly the sum of the
* lengths of all elements in `parts`.
*
* If `UDIRECT_MAP_REQ_MAY_DISCARD` is set, then the contents of `buf` may be
* discarded by this operation. Otherwise, the common subset of the passed
* buffer and the returned buffer must match once this call is complete. This
* data is synchronized on the driver side, but not on the device side. The
* driver must perform the appropriate synchronization operations
*
* Drivers may set their preferences regarding coherency and cacheability using
* `UDIRECT_MAP_REQ_SET_COHERENCY` and `UDIRECT_MAP_REQ_SET_CACHEABILITY`.
*
* The driver may write to the buffer as desired. The data is guaranteed to be
* visible to the device
* * Immediately, for coherent uncached buffers
* * After execution of `udirect_barrier` with the `UDI_DMA_OUT` flag for
* cached coherent buffers
* * After execution of `udirect_sync_req` with the `UDI_DMA_OUT` flag for all
* other buffer types
*
* The driver may read from the buffer as desired. Data written by the device is
* guaranteed to be visible
* * Immediately, for coherent uncached buffers
* * After execution of `udirect_barrier` with the `UDI_DMA_IN` flag for
* cached coherent buffers
* * After execution of `udirect_sync_req` with the `UDI_DMA_IN`flag for other
* buffer types
*
* If modification of the buffer causes it to change size, then the mapping will
* be invalidated. If the buffer is coherent, this property will be
* invalidated. This error will be reported at the next `udirect_sync` operation.
*/
typedef void udirect_map_req_op_t(
udirect_bind_cb_t *cb,
udi_buf_t *buf,
udi_ubit32_t regset_idx,
udi_ubit16_t num_parts,
udi_scgth_element_64_t *parts,
udi_ubit32_t flags);
/*! Successful mapping. */
typedef void udirect_map_ack_op_t(
udirect_bind_cb_t *cb,
udirect_buf_cb_t *bcb);
/*! Unsuccessful mapping.
*
* `UDI_STAT_NOT_SUPPORTED` The requested flags could not be accomodated */
typedef void udirect_map_nak_op_t(
udirect_bind_cb_t *cb,
udi_buf_t *buf,
udi_status_t status,
);
/*! Synchronize the backing store with the buffer
*
* `offset` and `length` indicate the portion of the buffer to be synchronized.
* `flags` as per udi_dma_sync
*/
typedef void udirect_sync_req_op_t(
udirect_buf_cb_t *cb,
udi_size_t offset, udi_size_t length,
ubit32_t flags);
/*! Synchronization successful */
typedef void udirect_sync_ack_op_t(
udirect_buf_cb_t *cb);
/*! Synchronization could not be pefrormed (trivially)
* `UDI_STAT_INVALID_STATE`
* The mapping has become invalid (for example, the buffer has been
* resized). The driver must perform a remap operation
* `UDIRECT_STAT_MUST_COPY`
* The buffer is not backed by the device memory passed to the map
* operation. You must manually copy the data. The recommended approach is
* to configure the device to perform a DMA copy (in|out) of the buffer.
*
* Flags are as passed to `udirect_sync_req`.
*/
typedef void udirect_sync_nak_op_t(
udirect_buf_cb_t *cb,
udi_ubit32_t flags,
udi_status_t status);
/*! Remaps a backing buffer. Parameters posess the same meanings as
`udirect_map_req_op_t` */
typedef void udirect_remap_req_op_t(
udirect_buf_cb_t *cb,
udi_ubit32_t regset_idx,
udi_ubit16_t num_parts,
udi_scgth_element_64_t *parts,
udi_ubit32_t flags);
typedef void udirect_remap_ack_op_t(
udirect_buf_cb_t *cb,
udi_status_t status);
#define UDIRECT_UNMAP_REQ_PRESERVE (1 << 0)
typedef void udirect_unmap_req_op_t(udirect_buf_cb_t *cb, ubit32_t flags);
/* Function prototypes of Driver-to-Environment operations */
udirect_query_req_op_t udirect_query_req;
udirect_map_req_op_t udirect_map_req;
udirect_sync_req_op_t udirect_sync_req;
udirect_remap_req_op_t udirect_remap_req;
udirect_unmap_req_op_t udirect_unmap_req;
/* Environment to Driver operations */
udirect_query_ack_op_t udirect_query_ack;
udirect_map_ack_op_t udirect_map_ack;
udirect_map_nak_op_t udirect_map_nak;
udirect_sync_ack_op_t udirect_sync_ack;
udirect_sync_nak_op_t udirect_sync_nak;
udirect_remap_ack_op_t udirect_remap_ack;
/*! Memory barrier. Same flags as per `udirect_sync_req`. */
void udirect_barrier(udi_ubit32_t flags);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment