2019-02-03 16:00:50 -08:00

193 lines
8.5 KiB
C

/*
Copyright (c) 2012, Broadcom Europe Ltd
All rights reserved.
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 the copyright holder 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 HOLDER 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.
*/
// MPHI videocore message driver
#ifndef _VCHI_MESSAGE_H_
#define _VCHI_MESSAGE_H_
#include "interface/vchi/vchi_cfg_internal.h"
#include "interface/vcos/vcos.h"
#include "interface/vchi/vchi_common.h"
typedef enum message_event_type {
MESSAGE_EVENT_NONE,
MESSAGE_EVENT_NOP,
MESSAGE_EVENT_MESSAGE,
MESSAGE_EVENT_SLOT_COMPLETE,
MESSAGE_EVENT_RX_BULK_PAUSED,
MESSAGE_EVENT_RX_BULK_COMPLETE,
MESSAGE_EVENT_TX_COMPLETE,
MESSAGE_EVENT_MSG_DISCARDED
} MESSAGE_EVENT_TYPE_T;
typedef enum vchi_msg_flags
{
VCHI_MSG_FLAGS_NONE = 0x0,
VCHI_MSG_FLAGS_TERMINATE_DMA = 0x1
} VCHI_MSG_FLAGS_T;
typedef enum message_tx_channel
{
MESSAGE_TX_CHANNEL_MESSAGE = 0,
MESSAGE_TX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards
} MESSAGE_TX_CHANNEL_T;
// Macros used for cycling through bulk channels
#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)
#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)
typedef enum message_rx_channel
{
MESSAGE_RX_CHANNEL_MESSAGE = 0,
MESSAGE_RX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards
} MESSAGE_RX_CHANNEL_T;
// Message receive slot information
typedef struct rx_msg_slot_info {
struct rx_msg_slot_info *next;
//struct slot_info *prev;
#if !defined VCHI_COARSE_LOCKING
VCOS_SEMAPHORE_T sem;
#endif
uint8_t *addr; // base address of slot
uint32_t len; // length of slot in bytes
uint32_t write_ptr; // hardware causes this to advance
uint32_t read_ptr; // this module does the reading
int active; // is this slot in the hardware dma fifo?
uint32_t msgs_parsed; // count how many messages are in this slot
uint32_t msgs_released; // how many messages have been released
void *state; // connection state information
uint8_t ref_count[VCHI_MAX_SERVICES_PER_CONNECTION]; // reference count for slots held by services
} RX_MSG_SLOTINFO_T;
// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out.
// In particular, it mustn't use addr and len - they're the client buffer, but the message
// driver will be tasked with sending the aligned core section.
typedef struct rx_bulk_slotinfo_t {
struct rx_bulk_slotinfo_t *next;
VCOS_SEMAPHORE_T *blocking;
// needed by DMA
void *addr;
uint32_t len;
// needed for the callback
void *service;
void *handle;
VCHI_FLAGS_T flags;
} RX_BULK_SLOTINFO_T;
/* ----------------------------------------------------------------------
* each connection driver will have a pool of the following struct.
*
* the pool will be managed by vchi_qman_*
* this means there will be multiple queues (single linked lists)
* a given struct message_info will be on exactly one of these queues
* at any one time
* -------------------------------------------------------------------- */
typedef struct rx_message_info {
struct message_info *next;
//struct message_info *prev;
uint8_t *addr;
uint32_t len;
RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message
uint32_t tx_timestamp;
uint32_t rx_timestamp;
} RX_MESSAGE_INFO_T;
typedef struct {
MESSAGE_EVENT_TYPE_T type;
struct {
// for messages
void *addr; // address of message
uint16_t slot_delta; // whether this message indicated slot delta
uint32_t len; // length of message
RX_MSG_SLOTINFO_T *slot; // slot this message is in
vcos_fourcc_t service; // service id this message is destined for
uint32_t tx_timestamp; // timestamp from the header
uint32_t rx_timestamp; // timestamp when we parsed it
} message;
// FIXME: cleanup slot reporting...
RX_MSG_SLOTINFO_T *rx_msg;
RX_BULK_SLOTINFO_T *rx_bulk;
void *tx_handle;
MESSAGE_TX_CHANNEL_T tx_channel;
} MESSAGE_EVENT_T;
// callbacks
typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state );
typedef struct {
VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback;
} VCHI_MESSAGE_DRIVER_OPEN_T;
// handle to this instance of message driver (as returned by ->open)
typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T;
struct opaque_vchi_message_driver_t {
VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state );
int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle );
int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle );
int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, vcos_bool_t enable );
int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot ); // rx message
int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot ); // rx data (bulk)
int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle ); // tx (message & bulk)
void (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event ); // get the next event from message_driver
int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle );
int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, vcos_fourcc_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void
*address, uint32_t length_avail, uint32_t max_total_length, vcos_bool_t pad_to_fill, vcos_bool_t allow_partial );
int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count );
int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length );
void * (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length );
void (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address );
int (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );
int (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );
vcos_bool_t (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
int (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
int (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel );
void (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len );
void (*debug)( VCHI_MDRIVER_HANDLE_T *handle );
};
#endif // _VCHI_MESSAGE_H_
/****************************** End of file ***********************************/