src/ssx/occhw/occhw_async_ocb.c
/// Create (initialize) an OcbQueue
///
/// \param queue An uninitialized or otherwise idle OcbQueue
///
/// \param engine A valid OCB engine id
///
/// \param cq_base The base address of the circular queue data area for the
/// queue. This address must be 8-byte aligned for write queues. Read queues
/// must be cache-line aligned and a multiple of the cache line in size.
///
/// \param cq_length The length of the circular queue measured in 8-byte
/// increments.
///
/// \param protocol The interrupt protocol, either OCB_PUSH_PULL_PROTOCOL_LAZY
/// or OCB_PUSH_PULL_PROTOCOL_AGGRESSIVE.  Lazy means that read queues only
/// interrupt when empty, and write queues only interrupt when full.
/// Agressive means that read queues interrupt when not empty and write queues
/// interrupt when not full.  In general the lazy read protocol will only work
/// for 1) queues of length 1, where lazy == aggressive, and 2) protocols
/// where a known fixed number of 8-byte entries is always expected to be
/// received.
///
/// \retval 0 Success
///
/// \retval -ASYNC_INVALID_OBJECT_OCB_QUEUE The \a queue was NULL (0).
///
/// \retval -ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \a cq_base is not properly
/// aligned, or the \a cq_length is invalid, or the \a protocol is invalid.
///
/// \retval -ASYNC_INVALID_ENGINE_OCB The \a engine is not an OCB engine.
///
/// Other errors may be returned by async_queue_create().
Create (initialize) an OcbQueue
\param queue An uninitialized or otherwise idle OcbQueue

\param engine A valid OCB engine id

\param cq_base The base address of the circular queue data area for the
queue. This address must be 8-byte aligned for write queues. Read queues
must be cache-line aligned and a multiple of the cache line in size.

\param cq_length The length of the circular queue measured in 8-byte
increments.

\param protocol The interrupt protocol, either OCB_PUSH_PULL_PROTOCOL_LAZY
or OCB_PUSH_PULL_PROTOCOL_AGGRESSIVE.  Lazy means that read queues only
interrupt when empty, and write queues only interrupt when full.
Agressive means that read queues interrupt when not empty and write queues
interrupt when not full.  In general the lazy read protocol will only work
for 1) queues of length 1, where lazy == aggressive, and 2) protocols
where a known fixed number of 8-byte entries is always expected to be
received.

\retval 0 Success

\retval -ASYNC_INVALID_OBJECT_OCB_QUEUE The \a queue was NULL (0).

\retval -ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \a cq_base is not properly
aligned, or the \a cq_length is invalid, or the \a protocol is invalid.

\retval -ASYNC_INVALID_ENGINE_OCB The \a engine is not an OCB engine.

Other errors may be returned by async_queue_create().
Create ( initialize ) an OcbQueue \ param queue An uninitialized or otherwise idle OcbQueue \ param engine A valid OCB engine id \ param cq_base The base address of the circular queue data area for the queue . This address must be 8 - byte aligned for write queues . Read queues must be cache - line aligned and a multiple of the cache line in size . \ param cq_length The length of the circular queue measured in 8 - byte increments . \ param protocol The interrupt protocol either OCB_PUSH_PULL_PROTOCOL_LAZY or OCB_PUSH_PULL_PROTOCOL_AGGRESSIVE . Lazy means that read queues only interrupt when empty and write queues only interrupt when full . Agressive means that read queues interrupt when not empty and write queues interrupt when not full . In general the lazy read protocol will only work for 1 ) queues of length 1 where lazy == aggressive and 2 ) protocols where a known fixed number of 8 - byte entries is always expected to be received . \ retval 0 Success \ retval - ASYNC_INVALID_OBJECT_OCB_QUEUE The \ a queue was NULL ( 0 ) . \ retval - ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \ a cq_base is not properly aligned or the \ a cq_length is invalid or the \ a protocol is invalid . \ retval - ASYNC_INVALID_ENGINE_OCB The \ a engine is not an OCB engine . Other errors may be returned by async_queue_create () .
int
ocb_queue_create(OcbQueue* queue,
                 int engine,
                 uint64_t* cq_base,
                 size_t cq_length,
                 int protocol)
{
    AsyncQueue* async_queue = (AsyncQueue*)queue;
    int align_mask = 0;
    if (SSX_ERROR_CHECK_API)
    {
        SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_OCB_QUEUE);
        SSX_ERROR_IF((cq_length < OCB_PUSH_PULL_LENGTH_MIN) ||
                     (cq_length > OCB_PUSH_PULL_LENGTH_MAX) ||
                     ((protocol != OCB_INTERRUPT_PROTOCOL_LAZY) &&
                      (protocol != OCB_INTERRUPT_PROTOCOL_AGGRESSIVE)),
                     ASYNC_INVALID_ARGUMENT_OCB_QUEUE);
    }
    queue->cq_base = cq_base;
    queue->cq_length = cq_length;
    switch (engine)
    {
        case ASYNC_ENGINE_OCB_PUSH0:
            queue->irq = OCCHW_IRQ_STRM0_PUSH;
            queue->engine = OCB_ENGINE_PUSH0;
            goto read_engine;
        case ASYNC_ENGINE_OCB_PUSH1:
            queue->irq = OCCHW_IRQ_STRM1_PUSH;
            queue->engine = OCB_ENGINE_PUSH1;
            goto read_engine;
        case ASYNC_ENGINE_OCB_PUSH2:
            queue->irq = OCCHW_IRQ_STRM2_PUSH;
            queue->engine = OCB_ENGINE_PUSH2;
            goto read_engine;
        case ASYNC_ENGINE_OCB_PUSH3:
            queue->irq = OCCHW_IRQ_STRM3_PUSH;
            queue->engine = OCB_ENGINE_PUSH3;
            goto read_engine;
        read_engine:
            align_mask = CACHE_LINE_SIZE - 1;
            async_queue_create(async_queue, engine);
            ocb_read_engine_reset(queue, cq_length, protocol);
            break;
        case ASYNC_ENGINE_OCB_PULL0:
            queue->irq = OCCHW_IRQ_STRM0_PULL;
            queue->engine = OCB_ENGINE_PULL0;
            goto write_engine;
        case ASYNC_ENGINE_OCB_PULL1:
            queue->irq = OCCHW_IRQ_STRM1_PULL;
            queue->engine = OCB_ENGINE_PULL1;
            goto write_engine;
        case ASYNC_ENGINE_OCB_PULL2:
            queue->irq = OCCHW_IRQ_STRM2_PULL;
            queue->engine = OCB_ENGINE_PULL2;
            goto write_engine;
        case ASYNC_ENGINE_OCB_PULL3:
            queue->irq = OCCHW_IRQ_STRM3_PULL;
            queue->engine = OCB_ENGINE_PULL3;
            goto write_engine;
        write_engine:
            align_mask = 8 - 1;
            async_queue_create(async_queue, engine);
            ocb_write_engine_reset(queue, cq_length, protocol);
            break;
        default:
            if (SSX_ERROR_CHECK_API)
            {
                SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_OCB);
            }
    }
    if (SSX_ERROR_CHECK_API)
    {
        SSX_ERROR_IF(((uint32_t)cq_base & align_mask) != 0,
                     ASYNC_INVALID_ARGUMENT_OCB_QUEUE2);
    }
    return 0;
}
int ocb_queue_create ( OcbQueue * queue , int engine , uint64_t * cq_base , size_t cq_length , int protocol ) { AsyncQueue * async_queue = ( AsyncQueue * ) queue ; int align_mask = 0 ; if ( SSX_ERROR_CHECK_API ) { SSX_ERROR_IF ( queue == 0 , ASYNC_INVALID_OBJECT_OCB_QUEUE ) ; SSX_ERROR_IF ( ( cq_length < OCB_PUSH_PULL_LENGTH_MIN ) || ( cq_length > OCB_PUSH_PULL_LENGTH_MAX ) || ( ( protocol != OCB_INTERRUPT_PROTOCOL_LAZY ) && ( protocol != OCB_INTERRUPT_PROTOCOL_AGGRESSIVE ) ) , ASYNC_INVALID_ARGUMENT_OCB_QUEUE ) ; } queue -> cq_base = cq_base ; queue -> cq_length = cq_length ; switch ( engine ) { case ASYNC_ENGINE_OCB_PUSH0 : queue -> irq = OCCHW_IRQ_STRM0_PUSH ; queue -> engine = OCB_ENGINE_PUSH0 ; goto read_engine ; case ASYNC_ENGINE_OCB_PUSH1 : queue -> irq = OCCHW_IRQ_STRM1_PUSH ; queue -> engine = OCB_ENGINE_PUSH1 ; goto read_engine ; case ASYNC_ENGINE_OCB_PUSH2 : queue -> irq = OCCHW_IRQ_STRM2_PUSH ; queue -> engine = OCB_ENGINE_PUSH2 ; goto read_engine ; case ASYNC_ENGINE_OCB_PUSH3 : queue -> irq = OCCHW_IRQ_STRM3_PUSH ; queue -> engine = OCB_ENGINE_PUSH3 ; goto read_engine ; read_engine : align_mask = CACHE_LINE_SIZE - 1 ; async_queue_create ( async_queue , engine ) ; ocb_read_engine_reset ( queue , cq_length , protocol ) ; break ; case ASYNC_ENGINE_OCB_PULL0 : queue -> irq = OCCHW_IRQ_STRM0_PULL ; queue -> engine = OCB_ENGINE_PULL0 ; goto write_engine ; case ASYNC_ENGINE_OCB_PULL1 : queue -> irq = OCCHW_IRQ_STRM1_PULL ; queue -> engine = OCB_ENGINE_PULL1 ; goto write_engine ; case ASYNC_ENGINE_OCB_PULL2 : queue -> irq = OCCHW_IRQ_STRM2_PULL ; queue -> engine = OCB_ENGINE_PULL2 ; goto write_engine ; case ASYNC_ENGINE_OCB_PULL3 : queue -> irq = OCCHW_IRQ_STRM3_PULL ; queue -> engine = OCB_ENGINE_PULL3 ; goto write_engine ; write_engine : align_mask = 8 - 1 ; async_queue_create ( async_queue , engine ) ; ocb_write_engine_reset ( queue , cq_length , protocol ) ; break ; default : if ( SSX_ERROR_CHECK_API ) { SSX_ERROR_IF ( 1 , ASYNC_INVALID_ENGINE_OCB ) ; } } if ( SSX_ERROR_CHECK_API ) { SSX_ERROR_IF ( ( ( uint32_t ) cq_base & align_mask ) != 0 , ASYNC_INVALID_ARGUMENT_OCB_QUEUE2 ) ; } return 0 ; }
Create (initialize) an OcbQueue
\param queue An uninitialized or otherwise idle OcbQueue
Create ( initialize ) an OcbQueue \ param queue An uninitialized or otherwise idle OcbQueue
// These are the read engines from OCC's perspective. // These are the write engines from OCC's perspective.