lib: added initial version of openamp
This patch contains initial version of xilopenamp library. Currently the library supports cortex-R5 processor Signed-off-by: Kinjal Pravinbhai Patel <patelki@xilinx.com>
This commit is contained in:
parent
dc90d1033a
commit
322504c6c6
35 changed files with 9228 additions and 0 deletions
51
ThirdParty/sw_services/xilopenamp/data/xilopenamp.mld
vendored
Normal file
51
ThirdParty/sw_services/xilopenamp/data/xilopenamp.mld
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
###############################################################################
|
||||
#
|
||||
# Copyright (C) 2015 Xilinx, Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Use of the Software is limited solely to applications:
|
||||
# (a) running on a Xilinx device, or
|
||||
# (b) that interact with a Xilinx device through a bus or interconnect.
|
||||
#
|
||||
# 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
|
||||
# XILINX CONSORTIUM 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.
|
||||
#
|
||||
# Except as contained in this notice, the name of the Xilinx shall not be used
|
||||
# in advertising or otherwise to promote the sale, use or other dealings in
|
||||
# this Software without prior written authorization from Xilinx.
|
||||
#
|
||||
###############################################################################
|
||||
#
|
||||
# Modification History
|
||||
#
|
||||
# Ver Who Date Changes
|
||||
# ----- ---- -------- -----------------------------------------------
|
||||
# 1.00 pkp 12/03/15 Initial Release
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
OPTION psf_version = 2.1;
|
||||
|
||||
BEGIN LIBRARY xilopenamp
|
||||
OPTION DRC = openamp_drc;
|
||||
OPTION COPYFILES = all;
|
||||
OPTION REQUIRES_OS = (standalone);
|
||||
OPTION APP_LINKER_FLAGS = "-Wl,--start-group,-lxil,-lxilopenamp,-lgcc,-lc,--end-group";
|
||||
OPTION DESC = "Xilinx openamp Library ";
|
||||
OPTION VERSION = 1.0;
|
||||
OPTION NAME = xilopenamp;
|
||||
END LIBRARY
|
86
ThirdParty/sw_services/xilopenamp/data/xilopenamp.tcl
vendored
Normal file
86
ThirdParty/sw_services/xilopenamp/data/xilopenamp.tcl
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
###############################################################################
|
||||
#
|
||||
# Copyright (C) 2015 Xilinx, Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Use of the Software is limited solely to applications:
|
||||
# (a) running on a Xilinx device, or
|
||||
# (b) that interact with a Xilinx device through a bus or interconnect.
|
||||
#
|
||||
# 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
|
||||
# XILINX CONSORTIUM 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.
|
||||
#
|
||||
# Except as contained in this notice, the name of the Xilinx shall not be used
|
||||
# in advertising or otherwise to promote the sale, use or other dealings in
|
||||
# this Software without prior written authorization from Xilinx.
|
||||
#
|
||||
###############################################################################
|
||||
#
|
||||
# Modification History
|
||||
#
|
||||
# Ver Who Date Changes
|
||||
# ----- ---- -------- -----------------------------------------------
|
||||
# 1.00 pkp 12/03/15 Initial Release
|
||||
##############################################################################
|
||||
|
||||
#---------------------------------------------
|
||||
# openamp_drc
|
||||
#---------------------------------------------
|
||||
proc openamp_drc {libhandle} {
|
||||
|
||||
}
|
||||
|
||||
proc generate {libhandle} {
|
||||
|
||||
}
|
||||
|
||||
#-------
|
||||
# post_generate: called after generate called on all libraries
|
||||
#-------
|
||||
proc post_generate {libhandle} {
|
||||
|
||||
xgen_opts_file $libhandle
|
||||
}
|
||||
|
||||
#-------
|
||||
# execs_generate: called after BSP's, libraries and drivers have been compiled
|
||||
# This procedure builds the libxilopenamp.a library
|
||||
#-------
|
||||
proc execs_generate {libhandle} {
|
||||
|
||||
}
|
||||
|
||||
proc xgen_opts_file {libhandle} {
|
||||
# Copy the include files to the include directory
|
||||
set srcdir src
|
||||
set dstdir [file join .. .. include]
|
||||
|
||||
# Create dstdir if it does not exist
|
||||
if { ! [file exists $dstdir] } {
|
||||
file mkdir $dstdir
|
||||
}
|
||||
puts "its openamp"
|
||||
|
||||
# Get list of files in the srcdir
|
||||
set sources [glob -join $srcdir *.h]
|
||||
|
||||
# Copy each of the files in the list to dstdir
|
||||
foreach source $sources {
|
||||
file copy -force $source $dstdir
|
||||
}
|
||||
|
||||
}
|
115
ThirdParty/sw_services/xilopenamp/src/Makefile
vendored
Normal file
115
ThirdParty/sw_services/xilopenamp/src/Makefile
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
###############################################################################
|
||||
#
|
||||
# Copyright (C) 2015 Xilinx, Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Use of the Software is limited solely to applications:
|
||||
# (a) running on a Xilinx device, or
|
||||
# (b) that interact with a Xilinx device through a bus or interconnect.
|
||||
#
|
||||
# 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
|
||||
# XILINX CONSORTIUM 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.
|
||||
#
|
||||
# Except as contained in this notice, the name of the Xilinx shall not be used
|
||||
# in advertising or otherwise to promote the sale, use or other dealings in
|
||||
# this Software without prior written authorization from Xilinx.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
COMPILER=
|
||||
ARCHIVER=
|
||||
CP=cp
|
||||
COMPILER_FLAGS =
|
||||
EXTRA_ARCHIVE_FLAGS=rc
|
||||
CC_FLAGS= -mcpu=cortex-r5
|
||||
RELEASEDIR=../../../lib
|
||||
#RELEASEDIR= .
|
||||
INCLUDEDIR=../../../include
|
||||
INCLUDES=-I./include/ -I${INCLUDEDIR}
|
||||
OPENAMP_DIR = .
|
||||
|
||||
LIB_SRCS = $(OPENAMP_DIR)/config.c \
|
||||
$(OPENAMP_DIR)/bm_env.c \
|
||||
$(OPENAMP_DIR)/elf_loader.c \
|
||||
$(OPENAMP_DIR)/hil.c \
|
||||
$(OPENAMP_DIR)/llist.c \
|
||||
$(OPENAMP_DIR)/remote_device.c \
|
||||
$(OPENAMP_DIR)/remoteproc.c \
|
||||
$(OPENAMP_DIR)/remoteproc_loader.c \
|
||||
$(OPENAMP_DIR)/rpmsg.c \
|
||||
$(OPENAMP_DIR)/rpmsg_core.c \
|
||||
$(OPENAMP_DIR)/rpmsg_retarget.c\
|
||||
$(OPENAMP_DIR)/rsc_table_parser.c \
|
||||
$(OPENAMP_DIR)/sh_mem.c \
|
||||
$(OPENAMP_DIR)/virtio.c \
|
||||
$(OPENAMP_DIR)/virtqueue.c
|
||||
|
||||
|
||||
# create SECURE_SRCS based on configured options
|
||||
|
||||
OPENAMP_SRCS = $(LIB_SRCS)
|
||||
|
||||
OPENAMP_OBJS = $(OPENAMP_SRCS:%.c=%.o)
|
||||
|
||||
|
||||
EXPORT_INCLUDE_FILES = $(OPENAMP_DIR)/config.h \
|
||||
$(OPENAMP_DIR)/bm_env.h \
|
||||
$(OPENAMP_DIR)/elf_loader.h \
|
||||
$(OPENAMP_DIR)/env.h \
|
||||
$(OPENAMP_DIR)/hil.h \
|
||||
$(OPENAMP_DIR)/llist.h \
|
||||
$(OPENAMP_DIR)/open_amp.h \
|
||||
$(OPENAMP_DIR)/remoteproc.h \
|
||||
$(OPENAMP_DIR)/remoteproc_loader.h \
|
||||
$(OPENAMP_DIR)/rpmsg_retarget.h \
|
||||
$(OPENAMP_DIR)/rpmsg.h \
|
||||
$(OPENAMP_DIR)/rpmsg_core.h \
|
||||
$(OPENAMP_DIR)/rsc_table_parser.h \
|
||||
$(OPENAMP_DIR)/sh_mem.h \
|
||||
$(OPENAMP_DIR)/virtio.h \
|
||||
$(OPENAMP_DIR)/virtio_ring.h\
|
||||
$(OPENAMP_DIR)/virtqueue.h
|
||||
|
||||
|
||||
libs: libxilopenamp.a
|
||||
cp libxilopenamp.a $(RELEASEDIR)
|
||||
make clean
|
||||
|
||||
include:
|
||||
@for i in $(EXPORT_INCLUDE_FILES); do \
|
||||
${CP} -r $$i ${INCLUDEDIR}; \
|
||||
done
|
||||
|
||||
clean:
|
||||
rm -rf obj/config.o obj/bm_env.o obj/rpmsg_retarget.o obj/elf_loader.o obj/hil.o obj/llist.o obj/remote_device.o obj/remoteproc.o obj/remoteproc_loader.o obj/rpmsg.o obj/rpmsg_core.o obj/rsc_table_parser.o obj/sh_mem.o obj/virtio.o obj/virtqueue.o
|
||||
rmdir obj
|
||||
rm libxilopenamp.a
|
||||
|
||||
|
||||
libxilopenamp.a: obj_dir print_msg_secure_base $(OPENAMP_OBJS)
|
||||
@echo "Creating archive $@"
|
||||
$(ARCHIVER) $(EXTRA_ARCHIVE_FLAGS) $@ obj/config.o obj/bm_env.o obj/rpmsg_retarget.o obj/elf_loader.o obj/hil.o obj/llist.o obj/remote_device.o obj/remoteproc.o obj/remoteproc_loader.o obj/rpmsg.o obj/rpmsg_core.o obj/rsc_table_parser.o obj/sh_mem.o obj/virtio.o obj/virtqueue.o
|
||||
|
||||
|
||||
obj_dir:
|
||||
mkdir obj
|
||||
|
||||
print_msg_secure_base:
|
||||
@echo "Compiling XilOpenAmp Library"
|
||||
|
||||
.c.o:
|
||||
$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(CC_FLAGS) $(INCLUDES) -c $< -o obj/$(@F)
|
609
ThirdParty/sw_services/xilopenamp/src/bm_env.c
vendored
Normal file
609
ThirdParty/sw_services/xilopenamp/src/bm_env.c
vendored
Normal file
|
@ -0,0 +1,609 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (C) 2015 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* bm_env.c
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file is Bare Metal Implementation of env layer for OpenAMP.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "env.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "xil_exception.h"
|
||||
#include "xpseudo_asm.h"
|
||||
#include "bm_env.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
#if (defined(__CC_ARM))
|
||||
#define MEM_BARRIER() __schedule_barrier()
|
||||
#elif (defined(__GNUC__))
|
||||
#define MEM_BARRIER() asm volatile("" ::: "memory")
|
||||
#else
|
||||
#define MEM_BARRIER()
|
||||
#endif
|
||||
static void acquire_spin_lock(void *plock);
|
||||
static void release_spin_lock(void *plock);
|
||||
|
||||
struct isr_info isr_table[ISR_COUNT];
|
||||
int Intr_Count = 0;
|
||||
/* Flag to show status of global interrupts. 0 for disabled and 1 for enabled. This
|
||||
* is added to prevent recursive global interrupts enablement/disablement.
|
||||
*/
|
||||
int Intr_Enable_Flag = 1;
|
||||
|
||||
unsigned int old_value = 0;
|
||||
/**
|
||||
* env_init
|
||||
*
|
||||
* Initializes OS/BM environment.
|
||||
*
|
||||
*/
|
||||
int env_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* env_deinit
|
||||
*
|
||||
* Uninitializes OS/BM environment.
|
||||
*
|
||||
* @returns - execution status
|
||||
*/
|
||||
|
||||
int env_deinit() {
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* env_allocate_memory - implementation
|
||||
*
|
||||
* @param size
|
||||
*/
|
||||
void *env_allocate_memory(unsigned int size)
|
||||
{
|
||||
return (malloc(size));
|
||||
}
|
||||
|
||||
/**
|
||||
* env_free_memory - implementation
|
||||
*
|
||||
* @param ptr
|
||||
*/
|
||||
void env_free_memory(void *ptr)
|
||||
{
|
||||
if (ptr != NULL)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* env_memset - implementation
|
||||
*
|
||||
* @param ptr
|
||||
* @param value
|
||||
* @param size
|
||||
*/
|
||||
void env_memset(void *ptr, int value, unsigned long size)
|
||||
{
|
||||
memset(ptr, value, size);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* env_memcpy - implementation
|
||||
*
|
||||
* @param dst
|
||||
* @param src
|
||||
* @param len
|
||||
*/
|
||||
void env_memcpy(void *dst, void const * src, unsigned long len) {
|
||||
memcpy(dst,src,len);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* env_strcmp - implementation
|
||||
*
|
||||
* @param dst
|
||||
* @param src
|
||||
*/
|
||||
|
||||
int env_strcmp(const char *dst, const char *src){
|
||||
return (strcmp(dst, src));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* env_strncpy - implementation
|
||||
*
|
||||
* @param dest
|
||||
* @param src
|
||||
* @param len
|
||||
*/
|
||||
void env_strncpy(char * dest, const char *src, unsigned long len)
|
||||
{
|
||||
strncpy(dest, src, len);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* env_strncmp - implementation
|
||||
*
|
||||
* @param dest
|
||||
* @param src
|
||||
* @param len
|
||||
*/
|
||||
int env_strncmp(char * dest, const char *src, unsigned long len)
|
||||
{
|
||||
return (strncmp(dest, src, len));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* env_mb - implementation
|
||||
*
|
||||
*/
|
||||
void env_mb()
|
||||
{
|
||||
MEM_BARRIER();
|
||||
}
|
||||
|
||||
/**
|
||||
* osalr_mb - implementation
|
||||
*/
|
||||
void env_rmb()
|
||||
{
|
||||
MEM_BARRIER();
|
||||
}
|
||||
|
||||
/**
|
||||
* env_wmb - implementation
|
||||
*/
|
||||
void env_wmb()
|
||||
{
|
||||
MEM_BARRIER();
|
||||
}
|
||||
|
||||
/**
|
||||
* env_map_vatopa - implementation
|
||||
*
|
||||
* @param address
|
||||
*/
|
||||
unsigned long env_map_vatopa(void *address)
|
||||
{
|
||||
return platform_vatopa(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_map_patova - implementation
|
||||
*
|
||||
* @param address
|
||||
*/
|
||||
void *env_map_patova(unsigned long address)
|
||||
{
|
||||
return platform_patova(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_create_mutex
|
||||
*
|
||||
* Creates a mutex with the given initial count.
|
||||
*
|
||||
*/
|
||||
int env_create_mutex(void **lock, int count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* env_delete_mutex
|
||||
*
|
||||
* Deletes the given lock
|
||||
*
|
||||
*/
|
||||
void env_delete_mutex(void *lock)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* env_lock_mutex
|
||||
*
|
||||
* Tries to acquire the lock, if lock is not available then call to
|
||||
* this function will suspend.
|
||||
*/
|
||||
void env_lock_mutex(void *lock)
|
||||
{
|
||||
env_disable_interrupts();
|
||||
}
|
||||
|
||||
/**
|
||||
* env_unlock_mutex
|
||||
*
|
||||
* Releases the given lock.
|
||||
*/
|
||||
|
||||
void env_unlock_mutex(void *lock)
|
||||
{
|
||||
env_restore_interrupts();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* env_create_sync_lock
|
||||
*
|
||||
* Creates a synchronization lock primitive. It is used
|
||||
* when signal has to be sent from the interrupt context to main
|
||||
* thread context.
|
||||
*/
|
||||
int env_create_sync_lock(void **lock , int state) {
|
||||
int *slock;
|
||||
|
||||
slock = (int *)malloc(sizeof(int));
|
||||
if(slock){
|
||||
*slock = state;
|
||||
*lock = slock;
|
||||
}
|
||||
else{
|
||||
*lock = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* env_delete_sync_lock
|
||||
*
|
||||
* Deletes the given lock
|
||||
*
|
||||
*/
|
||||
void env_delete_sync_lock(void *lock){
|
||||
if(lock)
|
||||
free(lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_acquire_sync_lock
|
||||
*
|
||||
* Tries to acquire the lock, if lock is not available then call to
|
||||
* this function waits for lock to become available.
|
||||
*/
|
||||
void env_acquire_sync_lock(void *lock){
|
||||
acquire_spin_lock(lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_release_sync_lock
|
||||
*
|
||||
* Releases the given lock.
|
||||
*/
|
||||
|
||||
void env_release_sync_lock(void *lock){
|
||||
release_spin_lock(lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_sleep_msec
|
||||
*
|
||||
* Suspends the calling thread for given time , in msecs.
|
||||
*/
|
||||
|
||||
void env_sleep_msec(int num_msec)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* env_disable_interrupts
|
||||
*
|
||||
* Disables system interrupts
|
||||
*
|
||||
*/
|
||||
void env_disable_interrupts()
|
||||
{
|
||||
if(Intr_Enable_Flag == 1) {
|
||||
disable_global_interrupts();
|
||||
Intr_Enable_Flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* env_restore_interrupts
|
||||
*
|
||||
* Enables system interrupts
|
||||
*
|
||||
*/
|
||||
void env_restore_interrupts()
|
||||
{
|
||||
if(Intr_Enable_Flag == 0) {
|
||||
restore_global_interrupts();
|
||||
Intr_Enable_Flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* env_register_isr
|
||||
*
|
||||
* Registers interrupt handler for the given interrupt vector.
|
||||
*
|
||||
* @param vector - interrupt vector number
|
||||
* @param isr - interrupt handler
|
||||
*/
|
||||
void env_register_isr(int vector , void *data ,
|
||||
void (*isr)(int vector , void *data))
|
||||
{
|
||||
env_disable_interrupts();
|
||||
|
||||
if(Intr_Count < ISR_COUNT)
|
||||
{
|
||||
/* Save interrupt data */
|
||||
isr_table[Intr_Count].vector = vector;
|
||||
isr_table[Intr_Count].data = data;
|
||||
isr_table[Intr_Count++].isr = isr;
|
||||
}
|
||||
|
||||
env_restore_interrupts();
|
||||
}
|
||||
|
||||
void env_update_isr(int vector , void *data ,
|
||||
void (*isr)(int vector , void *data))
|
||||
{
|
||||
int idx;
|
||||
struct isr_info *info;
|
||||
|
||||
env_disable_interrupts();
|
||||
|
||||
for(idx = 0; idx < ISR_COUNT; idx++)
|
||||
{
|
||||
info = &isr_table[idx];
|
||||
if(info->vector == vector)
|
||||
{
|
||||
info->data = data;
|
||||
info->isr = isr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
env_restore_interrupts();
|
||||
}
|
||||
|
||||
/**
|
||||
* env_enable_interrupt
|
||||
*
|
||||
* Enables the given interrupt
|
||||
*
|
||||
* @param vector - interrupt vector number
|
||||
* @param priority - interrupt priority
|
||||
* @param polarity - interrupt polarity
|
||||
*/
|
||||
|
||||
void env_enable_interrupt(unsigned int vector , unsigned int priority ,
|
||||
unsigned int polarity)
|
||||
{
|
||||
int idx;
|
||||
|
||||
env_disable_interrupts();
|
||||
|
||||
for(idx = 0; idx < ISR_COUNT; idx++)
|
||||
{
|
||||
if(isr_table[idx].vector == vector)
|
||||
{
|
||||
isr_table[idx].priority = priority;
|
||||
isr_table[idx].type = polarity;
|
||||
XScuGic_EnableIntr(XPAR_SCUGIC_0_DIST_BASEADDR,vector);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
env_restore_interrupts();
|
||||
}
|
||||
|
||||
/**
|
||||
* env_disable_interrupt
|
||||
*
|
||||
* Disables the given interrupt
|
||||
*
|
||||
* @param vector - interrupt vector number
|
||||
*/
|
||||
|
||||
void env_disable_interrupt(unsigned int vector)
|
||||
{
|
||||
XScuGic_DisableIntr(XPAR_SCUGIC_0_DIST_BASEADDR,vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_map_memory
|
||||
*
|
||||
* Enables memory mapping for given memory region.
|
||||
*
|
||||
* @param pa - physical address of memory
|
||||
* @param va - logical address of memory
|
||||
* @param size - memory size
|
||||
* param flags - flags for cache/uncached and access type
|
||||
*/
|
||||
|
||||
void env_map_memory(unsigned int pa, unsigned int va, unsigned int size,
|
||||
unsigned int flags) {
|
||||
int is_mem_mapped = 0;
|
||||
int cache_type = 0;
|
||||
|
||||
if ((flags & (0x0f << 4 )) == MEM_MAPPED)
|
||||
{
|
||||
is_mem_mapped = 1;
|
||||
}
|
||||
|
||||
if ((flags & 0x0f) == WB_CACHE) {
|
||||
cache_type = WRITEBACK;
|
||||
}
|
||||
else if((flags & 0x0f) == WT_CACHE) {
|
||||
cache_type = WRITETHROUGH;
|
||||
}
|
||||
else {
|
||||
cache_type = NOCACHE;
|
||||
}
|
||||
|
||||
platform_map_mem_region(va, pa, size, is_mem_mapped, cache_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_disable_cache
|
||||
*
|
||||
* Disables system caches.
|
||||
*
|
||||
*/
|
||||
|
||||
void env_disable_cache() {
|
||||
platform_cache_all_flush_invalidate();
|
||||
platform_cache_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* env_get_timestamp
|
||||
*
|
||||
* Returns a 64 bit time stamp.
|
||||
*
|
||||
*
|
||||
*/
|
||||
unsigned long long env_get_timestamp(void) {
|
||||
|
||||
/* TODO: Provide implementation for baremetal*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*========================================================= */
|
||||
/* Util data / functions for BM */
|
||||
|
||||
void bm_env_isr(int vector) {
|
||||
int idx;
|
||||
struct isr_info *info;
|
||||
|
||||
env_disable_interrupt(vector);
|
||||
for(idx = 0; idx < ISR_COUNT; idx++)
|
||||
{
|
||||
info = &isr_table[idx];
|
||||
if(info->vector == vector)
|
||||
{
|
||||
info->isr(info->vector , info->data);
|
||||
env_enable_interrupt(info->vector , info->priority, info->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned int xchg(void* plock, unsigned int lockVal)
|
||||
{
|
||||
volatile unsigned int tmpVal = 0;
|
||||
volatile unsigned int tmpVal1 = 0;
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
|
||||
asm (
|
||||
"1: \n\t"
|
||||
"LDREX %[tmpVal], [%[plock]] \n\t"
|
||||
"STREX %[tmpVal1], %[lockVal], [%[plock]] \n\t"
|
||||
"CMP %[tmpVal1], #0 \n\t"
|
||||
"BNE 1b \n\t"
|
||||
"DMB \n\t"
|
||||
: [tmpVal] "=&r"(tmpVal)
|
||||
: [tmpVal1] "r" (tmpVal1), [lockVal] "r"(lockVal), [plock] "r"(plock)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
return tmpVal;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* acquire_spin_lock
|
||||
*
|
||||
*/
|
||||
static void acquire_spin_lock(void *plock)
|
||||
{
|
||||
const int lockVal = 0;
|
||||
volatile unsigned int retVal;
|
||||
|
||||
do {
|
||||
retVal = xchg(plock, lockVal);
|
||||
} while (retVal==lockVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* release_spin_lock
|
||||
*/
|
||||
static void release_spin_lock(void *plock)
|
||||
{
|
||||
MEM_BARRIER();
|
||||
|
||||
xchg(plock, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* restore global interrupts
|
||||
*/
|
||||
void restore_global_interrupts() {
|
||||
|
||||
ARM_AR_INT_BITS_SET(old_value);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* disable global interrupts
|
||||
*/
|
||||
void disable_global_interrupts() {
|
||||
|
||||
unsigned int value = 0;
|
||||
|
||||
ARM_AR_INT_BITS_GET(&value);
|
||||
|
||||
if (value != old_value) {
|
||||
|
||||
ARM_AR_INT_BITS_SET(CORTEXR5_CPSR_INTERRUPTS_BITS);
|
||||
|
||||
old_value = value;
|
||||
|
||||
}
|
||||
|
||||
}
|
133
ThirdParty/sw_services/xilopenamp/src/bm_env.h
vendored
Normal file
133
ThirdParty/sw_services/xilopenamp/src/bm_env.h
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (C) 2015 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the <ORGANIZATION> 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.
|
||||
*/
|
||||
|
||||
#ifndef _BM_ENV_H
|
||||
#define _BM_ENV_H
|
||||
|
||||
#include "xil_cache.h"
|
||||
#include "xreg_cortexr5.h"
|
||||
#include "xpseudo_asm_gcc.h"
|
||||
#include "xparameters.h"
|
||||
|
||||
/* IPI REGs OFFSET */
|
||||
#define IPI_TRIG_OFFSET 0x00000000 /* IPI trigger register offset */
|
||||
#define IPI_OBS_OFFSET 0x00000004 /* IPI observation register offset */
|
||||
#define IPI_ISR_OFFSET 0x00000010 /* IPI interrupt status register offset */
|
||||
#define IPI_IMR_OFFSET 0x00000014 /* IPI interrupt mask register offset */
|
||||
#define IPI_IER_OFFSET 0x00000018 /* IPI interrupt enable register offset */
|
||||
#define IPI_IDR_OFFSET 0x0000001C /* IPI interrupt disable register offset */
|
||||
|
||||
#ifndef BAREMETAL_MASTER
|
||||
#define BAREMETAL_MASTER 0
|
||||
#endif
|
||||
|
||||
/* The vector table address is the same as image entry point */
|
||||
#define RAM_VECTOR_TABLE_ADDR ELF_START
|
||||
|
||||
typedef enum {
|
||||
TRIG_NOT_SUPPORTED,
|
||||
TRIG_RISING_EDGE,
|
||||
TRIG_FALLING_EDGE,
|
||||
TRIG_LEVEL_LOW,
|
||||
TRIG_LEVEL_HIGH,
|
||||
TRIG_RISING_FALLING_EDGES,
|
||||
TRIG_HIGH_LOW_RISING_FALLING_EDGES
|
||||
} INT_TRIG_TYPE;
|
||||
|
||||
typedef enum {
|
||||
NOCACHE,
|
||||
WRITEBACK,
|
||||
WRITETHROUGH
|
||||
} CACHE_TYPE;
|
||||
|
||||
#define CORTEXR5_CPSR_INTERRUPTS_BITS (XREG_CPSR_IRQ_ENABLE | XREG_CPSR_FIQ_ENABLE)
|
||||
|
||||
/* This macro writes the current program status register (CPSR - all fields) */
|
||||
#define ARM_AR_CPSR_CXSF_WRITE(cpsr_cxsf_value) \
|
||||
{ \
|
||||
asm volatile(" MSR CPSR_cxsf, %0" \
|
||||
: /* No outputs */ \
|
||||
: "r" (cpsr_cxsf_value) ); \
|
||||
}
|
||||
|
||||
/* This macro sets the interrupt related bits in the status register / control
|
||||
register to the specified value. */
|
||||
#define ARM_AR_INT_BITS_SET(set_bits) \
|
||||
{ \
|
||||
int tmp_val; \
|
||||
tmp_val = mfcpsr(); \
|
||||
tmp_val &= ~((unsigned int)CORTEXR5_CPSR_INTERRUPTS_BITS); \
|
||||
tmp_val |= set_bits; \
|
||||
ARM_AR_CPSR_CXSF_WRITE(tmp_val); \
|
||||
}
|
||||
|
||||
/* This macro gets the interrupt related bits from the status register / control
|
||||
register. */
|
||||
#define ARM_AR_INT_BITS_GET(get_bits_ptr) \
|
||||
{ \
|
||||
int tmp_val; \
|
||||
tmp_val = mfcpsr(); \
|
||||
tmp_val &= CORTEXR5_CPSR_INTERRUPTS_BITS; \
|
||||
*get_bits_ptr = tmp_val; \
|
||||
}
|
||||
|
||||
#define SWITCH_TO_SYS_MODE() \
|
||||
{ \
|
||||
mtcpsr((mfcpsr() | XREG_CPSR_SYSTEM_MODE) & ~((unsigned int)CORTEXR5_CPSR_INTERRUPTS_BITS));\
|
||||
}
|
||||
|
||||
void restore_global_interrupts();
|
||||
void disable_global_interrupts();
|
||||
|
||||
/* define function macros for OpenAMP API */
|
||||
#define platform_cache_all_flush_invalidate() \
|
||||
{ \
|
||||
Xil_DCacheFlush(); \
|
||||
Xil_DCacheInvalidate(); \
|
||||
Xil_ICacheInvalidate(); \
|
||||
}
|
||||
|
||||
#define platform_cache_disable() \
|
||||
{ \
|
||||
Xil_DCacheDisable(); \
|
||||
Xil_ICacheDisable(); \
|
||||
}
|
||||
|
||||
#define platform_dcache_all_flush() { Xil_DCacheFlush(); }
|
||||
|
||||
#define platform_dcache_flush_range(addr, len) { Xil_DCacheFlushRange(addr, len); }
|
||||
|
||||
#define platform_map_mem_region(...)
|
||||
|
||||
#define platform_vatopa(addr) ((unsigned long)addr)
|
||||
#define platform_patova(addr) ((void *)addr)
|
||||
|
||||
#endif /* _BAREMETAL_H */
|
101
ThirdParty/sw_services/xilopenamp/src/config.c
vendored
Normal file
101
ThirdParty/sw_services/xilopenamp/src/config.c
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* config.c
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP stack.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* Start and end addresses of firmware image for remotes. These are defined in the
|
||||
* object files that are obtained by converting the remote ELF Image into object
|
||||
* files. These symbols are not used for remotes.
|
||||
*/
|
||||
extern unsigned char _binary_firmware1_start;
|
||||
extern unsigned char _binary_firmware1_end;
|
||||
|
||||
extern unsigned char _binary_firmware2_start;
|
||||
extern unsigned char _binary_firmware2_end;
|
||||
|
||||
#define FIRMWARE1_START (void *)&_binary_firmware1_start
|
||||
#define FIRMWARE1_END (void *)&_binary_firmware1_end
|
||||
|
||||
#define FIRMWARE2_START (void *)&_binary_firmware2_start
|
||||
#define FIRMWARE2_END (void *)&_binary_firmware2_end
|
||||
/* IPI REGs OFFSET */
|
||||
#define IPI_TRIG_OFFSET 0x00000000 /* IPI trigger register offset */
|
||||
#define IPI_OBS_OFFSET 0x00000004 /* IPI observation register offset */
|
||||
#define IPI_ISR_OFFSET 0x00000010 /* IPI interrupt status register offset */
|
||||
#define IPI_IMR_OFFSET 0x00000014 /* IPI interrupt mask register offset */
|
||||
#define IPI_IER_OFFSET 0x00000018 /* IPI interrupt enable register offset */
|
||||
#define IPI_IDR_OFFSET 0x0000001C /* IPI interrupt disable register offset */
|
||||
/* Init firmware table */
|
||||
|
||||
const struct firmware_info fw_table[] = { { "firmware1",
|
||||
(unsigned int) FIRMWARE1_START, (unsigned int) FIRMWARE1_END },
|
||||
{ "firmware2", (unsigned int) FIRMWARE2_START,
|
||||
(unsigned int) FIRMWARE2_END } };
|
||||
|
||||
/**
|
||||
* config_get_firmware
|
||||
*
|
||||
* Searches the given firmware in firmware table list and provides
|
||||
* it to caller.
|
||||
*
|
||||
* @param fw_name - name of the firmware
|
||||
* @param start_addr - pointer t hold start address of firmware
|
||||
* @param size - pointer to hold size of firmware
|
||||
*
|
||||
* returns - status of function execution
|
||||
*
|
||||
*/
|
||||
|
||||
int config_get_firmware(char *fw_name, unsigned int *start_addr, unsigned int *size) {
|
||||
int idx;
|
||||
for (idx = 0; idx < sizeof(fw_table) / (sizeof(struct firmware_info));
|
||||
idx++) {
|
||||
if (!env_strncmp((char *) fw_table[idx].name, fw_name,
|
||||
sizeof(fw_table[idx].name))) {
|
||||
*start_addr = fw_table[idx].start_addr;
|
||||
*size = fw_table[idx].end_addr - fw_table[idx].start_addr + 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
59
ThirdParty/sw_services/xilopenamp/src/config.h
vendored
Normal file
59
ThirdParty/sw_services/xilopenamp/src/config.h
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include "env.h"
|
||||
|
||||
/* Max supprted ISR counts */
|
||||
#define ISR_COUNT 4
|
||||
|
||||
/* Max supported firmwares */
|
||||
#define FW_COUNT 4
|
||||
/**
|
||||
* Structure to keep track of registered ISR's.
|
||||
*/
|
||||
struct isr_info {
|
||||
int vector;
|
||||
int priority;
|
||||
int type;
|
||||
void *data;
|
||||
void (*isr)(int vector, void *data);
|
||||
};
|
||||
|
||||
struct firmware_info {
|
||||
char name[32];
|
||||
unsigned int start_addr;
|
||||
unsigned int end_addr;
|
||||
};
|
||||
|
||||
int config_get_firmware(char *fw_name, unsigned int *start_addr, unsigned int *size);
|
||||
|
||||
#endif
|
643
ThirdParty/sw_services/xilopenamp/src/elf_loader.c
vendored
Normal file
643
ThirdParty/sw_services/xilopenamp/src/elf_loader.c
vendored
Normal file
|
@ -0,0 +1,643 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
#include "elf_loader.h"
|
||||
|
||||
/* Local functions. */
|
||||
|
||||
static int elf_loader_get_needed_sections(struct elf_decode_info *elf_info);
|
||||
static int elf_loader_relocs_specific(struct elf_decode_info *elf_info,
|
||||
Elf32_Shdr *section);
|
||||
static void *elf_loader_get_entry_point_address(
|
||||
struct elf_decode_info *elf_info);
|
||||
static int elf_loader_relocate_link(struct elf_decode_info *elf_info);
|
||||
static int elf_loader_seek_and_read(void *firmware, void *destination,
|
||||
Elf32_Off offset, Elf32_Word size);
|
||||
static int elf_loader_read_headers(void *firmware,
|
||||
struct elf_decode_info *elf_info);
|
||||
static int elf_loader_load_sections(void *firmware,
|
||||
struct elf_decode_info *elf_info);
|
||||
static int elf_loader_get_decode_info(void *firmware,
|
||||
struct elf_decode_info *elf_info);
|
||||
static int elf_loader_reloc_entry(struct elf_decode_info *elf_info,
|
||||
Elf32_Rel *rel_entry);
|
||||
static Elf32_Addr elf_loader_get_dynamic_symbol_addr(
|
||||
struct elf_decode_info *elf_info, int index);
|
||||
|
||||
/**
|
||||
* elf_loader_init
|
||||
*
|
||||
* Initializes ELF loader.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
int elf_loader_init(struct remoteproc_loader *loader) {
|
||||
|
||||
/* Initialize loader function table */
|
||||
loader->load_firmware = elf_loader_load_remote_firmware;
|
||||
loader->retrieve_entry = elf_loader_retrieve_entry_point;
|
||||
loader->retrieve_rsc = elf_loader_retrieve_resource_section;
|
||||
loader->attach_firmware = elf_loader_attach_firmware;
|
||||
loader->detach_firmware = elf_loader_detach_firmware;
|
||||
loader->retrieve_load_addr = elf_get_load_address;
|
||||
|
||||
return RPROC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_attach_firmware
|
||||
*
|
||||
* Attaches an ELF firmware to the loader
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
* @param firmware - pointer to the firmware start location
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
int elf_loader_attach_firmware(struct remoteproc_loader *loader, void *firmware) {
|
||||
|
||||
struct elf_decode_info *elf_info;
|
||||
int status;
|
||||
|
||||
/* Allocate memory for decode info structure. */
|
||||
elf_info = env_allocate_memory(sizeof(struct elf_decode_info));
|
||||
|
||||
if (!elf_info) {
|
||||
return RPROC_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
/* Clear the ELF decode struct. */
|
||||
env_memset(elf_info, 0, sizeof(struct elf_decode_info));
|
||||
|
||||
/* Get the essential information to decode the ELF. */
|
||||
status = elf_loader_get_decode_info(firmware, elf_info);
|
||||
|
||||
if (status) {
|
||||
/* Free memory. */
|
||||
env_free_memory(elf_info);
|
||||
return status;
|
||||
}
|
||||
|
||||
elf_info->firmware = firmware;
|
||||
loader->fw_decode_info = elf_info;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_detach_firmware
|
||||
*
|
||||
* Detaches ELF firmware from the loader
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
int elf_loader_detach_firmware(struct remoteproc_loader *loader) {
|
||||
|
||||
struct elf_decode_info *elf_info =
|
||||
(struct elf_decode_info *) loader->fw_decode_info;
|
||||
if (elf_info) {
|
||||
/* Free memory. */
|
||||
env_free_memory(elf_info->shstrtab);
|
||||
env_free_memory(elf_info->section_headers_start);
|
||||
env_free_memory(elf_info);
|
||||
}
|
||||
|
||||
return RPROC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_retrieve_entry_point
|
||||
*
|
||||
* Retrieves the ELF entrypoint.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - entrypoint
|
||||
*/
|
||||
void *elf_loader_retrieve_entry_point(struct remoteproc_loader *loader) {
|
||||
|
||||
return elf_loader_get_entry_point_address(
|
||||
(struct elf_decode_info *)loader->fw_decode_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_retrieve_resource_section
|
||||
*
|
||||
* Retrieves the resource section.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
* @param size - pointer to contain the size of the section
|
||||
*
|
||||
* @return - pointer to resource section
|
||||
*/
|
||||
void *elf_loader_retrieve_resource_section(struct remoteproc_loader *loader,
|
||||
unsigned int *size) {
|
||||
|
||||
Elf32_Shdr *rsc_header;
|
||||
void* resource_section = NULL;
|
||||
struct elf_decode_info *elf_info =
|
||||
(struct elf_decode_info *) loader->fw_decode_info;
|
||||
|
||||
if (elf_info->rsc) {
|
||||
/* Retrieve resource section header. */
|
||||
rsc_header = elf_info->rsc;
|
||||
/* Retrieve resource section size. */
|
||||
*size = rsc_header->sh_size;
|
||||
|
||||
/* Locate the start of resource section. */
|
||||
resource_section = (void *) ((unsigned int) elf_info->firmware
|
||||
+ rsc_header->sh_offset);
|
||||
}
|
||||
|
||||
/* Return the address of resource section. */
|
||||
return resource_section;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_load_remote_firmware
|
||||
*
|
||||
* Loads the ELF firmware.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
int elf_loader_load_remote_firmware(struct remoteproc_loader *loader) {
|
||||
|
||||
struct elf_decode_info *elf_info =
|
||||
(struct elf_decode_info *) loader->fw_decode_info;
|
||||
int status;
|
||||
|
||||
/* Load ELF sections. */
|
||||
status = elf_loader_load_sections(elf_info->firmware, elf_info);
|
||||
|
||||
if (!status) {
|
||||
|
||||
/* Perform dynamic relocations if needed. */
|
||||
status = elf_loader_relocate_link(elf_info);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_get_load_address
|
||||
*
|
||||
* Provides firmware load address.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - load address pointer
|
||||
*/
|
||||
void *elf_get_load_address(struct remoteproc_loader *loader) {
|
||||
|
||||
struct elf_decode_info *elf_info =
|
||||
(struct elf_decode_info *) loader->fw_decode_info;
|
||||
int status = 0;
|
||||
Elf32_Shdr *current = (Elf32_Shdr *) (elf_info->section_headers_start);
|
||||
|
||||
/* Traverse all sections except the reserved null section. */
|
||||
int section_count = elf_info->elf_header.e_shnum - 1;
|
||||
while ((section_count > 0) && (status == 0)) {
|
||||
/* Compute the pointer to section header. */
|
||||
current = (Elf32_Shdr *) (((unsigned char *) current)
|
||||
+ elf_info->elf_header.e_shentsize);
|
||||
/* Get the name of current section. */
|
||||
char *current_name = elf_info->shstrtab + current->sh_name;
|
||||
if(!env_strcmp(current_name , ".text")){
|
||||
return ((void *) (current->sh_addr));
|
||||
}
|
||||
/* Move to the next section. */
|
||||
section_count--;
|
||||
}
|
||||
|
||||
return (RPROC_ERR_PTR);
|
||||
}
|
||||
/**
|
||||
* elf_loader_get_needed_sections
|
||||
*
|
||||
* Retrieves the sections we need during the load and link from the
|
||||
* section headers list.
|
||||
*
|
||||
* @param elf_info - ELF object decode info container.
|
||||
*
|
||||
* @return- Pointer to the ELF section header.
|
||||
*/
|
||||
|
||||
static int elf_loader_get_needed_sections(struct elf_decode_info *elf_info) {
|
||||
Elf32_Shdr *current = (Elf32_Shdr *) (elf_info->section_headers_start);
|
||||
|
||||
/* We are interested in the following sections:
|
||||
.dynsym
|
||||
.dynstr
|
||||
.rel.plt
|
||||
.rel.dyn
|
||||
*/
|
||||
int sections_to_find = 5;
|
||||
|
||||
/* Search for sections but skip the reserved null section. */
|
||||
|
||||
int section_count = elf_info->elf_header.e_shnum - 1;
|
||||
while ((section_count > 0) && (sections_to_find > 0)) {
|
||||
/* Compute the section header pointer. */
|
||||
current = (Elf32_Shdr *) (((unsigned char *) current)
|
||||
+ elf_info->elf_header.e_shentsize);
|
||||
|
||||
/* Get the name of current section. */
|
||||
char *current_name = elf_info->shstrtab + current->sh_name;
|
||||
|
||||
/* Proceed if the section is allocatable and is not executable. */
|
||||
if ((current->sh_flags & SHF_ALLOC)
|
||||
&& !(current->sh_flags & SHF_EXECINSTR)) {
|
||||
/* Check for '.dynsym' or '.dynstr' or '.rel.plt' or '.rel.dyn'. */
|
||||
if (*current_name == '.') {
|
||||
current_name++;
|
||||
|
||||
/* Check for '.dynsym' or 'dynstr'. */
|
||||
if (*current_name == 'd') {
|
||||
current_name++;
|
||||
|
||||
/* Check for '.dynsym'. */
|
||||
if (env_strncmp(current_name, "ynsym", 5) == 0) {
|
||||
elf_info->dynsym = current;
|
||||
sections_to_find--;
|
||||
}
|
||||
|
||||
/* Check for '.dynstr'. */
|
||||
else if (env_strncmp(current_name, "ynstr", 5) == 0) {
|
||||
elf_info->dynstr = current;
|
||||
sections_to_find--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for '.rel.plt' or '.rel.dyn'. */
|
||||
else if (*current_name == 'r') {
|
||||
current_name++;
|
||||
|
||||
/* Check for '.rel.plt'. */
|
||||
if (env_strncmp(current_name, "el.plt", 6) == 0) {
|
||||
elf_info->rel_plt = current;
|
||||
sections_to_find--;
|
||||
}
|
||||
|
||||
/* Check for '.rel.dyn'. */
|
||||
else if (env_strncmp(current_name, "el.dyn", 6) == 0) {
|
||||
elf_info->rel_dyn = current;
|
||||
sections_to_find--;
|
||||
}
|
||||
|
||||
/* Check for '.resource_table'. */
|
||||
else if (env_strncmp(current_name, "esource_table", 13)
|
||||
== 0) {
|
||||
elf_info->rsc = current;
|
||||
sections_to_find--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to the next section. */
|
||||
section_count--;
|
||||
}
|
||||
|
||||
/* Return remaining sections section. */
|
||||
return (sections_to_find);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_relocs_specific
|
||||
*
|
||||
* Processes the relocations contained in the specified section.
|
||||
*
|
||||
* @param elf_info - elf decoding information.
|
||||
* @param section - header of the specified relocation section.
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
static int elf_loader_relocs_specific(struct elf_decode_info *elf_info,
|
||||
Elf32_Shdr *section) {
|
||||
|
||||
unsigned char *section_load_addr = (unsigned char*) section->sh_addr;
|
||||
int status = 0;
|
||||
int i;
|
||||
|
||||
/* Check the section type. */
|
||||
if (section->sh_type == SHT_REL) {
|
||||
/* Traverse the list of relocation entries contained in the section. */
|
||||
for (i = 0; (i < section->sh_size) && (status == 0);
|
||||
i += section->sh_entsize) {
|
||||
/* Compute the relocation entry address. */
|
||||
Elf32_Rel *rel_entry = (Elf32_Rel *) (section_load_addr + i);
|
||||
|
||||
/* Process the relocation entry. */
|
||||
status = elf_loader_reloc_entry(elf_info, rel_entry);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status to caller. */
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_get_entry_point_address
|
||||
*
|
||||
* Retrieves the entry point address from the specified ELF object.
|
||||
*
|
||||
* @param elf_info - elf object decode info container.
|
||||
* @param runtime_buffer - buffer containing ELF sections which are
|
||||
* part of runtime.
|
||||
*
|
||||
* @return - entry point address of the specified ELF object.
|
||||
*/
|
||||
static void *elf_loader_get_entry_point_address(
|
||||
struct elf_decode_info *elf_info) {
|
||||
return ((void *) elf_info->elf_header.e_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_relocate_link
|
||||
*
|
||||
* Relocates and links the given ELF object.
|
||||
*
|
||||
* @param elf_info - elf object decode info container.
|
||||
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
|
||||
static int elf_loader_relocate_link(struct elf_decode_info *elf_info) {
|
||||
int status = 0;
|
||||
|
||||
/* Check of .rel.dyn section exists in the ELF. */
|
||||
if (elf_info->rel_dyn) {
|
||||
/* Relocate and link .rel.dyn section. */
|
||||
status = elf_loader_relocs_specific(elf_info, elf_info->rel_dyn);
|
||||
}
|
||||
|
||||
/* Proceed to check if .rel.plt section exists, if no error encountered yet. */
|
||||
if (status == 0 && elf_info->rel_plt) {
|
||||
/* Relocate and link .rel.plt section. */
|
||||
status = elf_loader_relocs_specific(elf_info, elf_info->rel_plt);
|
||||
}
|
||||
|
||||
/* Return status to caller */
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_seek_and_read
|
||||
*
|
||||
* Seeks to the specified offset in the given file and reads the data
|
||||
* into the specified destination location.
|
||||
*
|
||||
* @param firmware - firmware to read from.
|
||||
* @param destination - Location into which the data should be read.
|
||||
* @param offset - Offset to seek in the file.
|
||||
* @param size - Size of the data to read.
|
||||
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
|
||||
static int elf_loader_seek_and_read(void *firmware, void *destination,
|
||||
Elf32_Off offset, Elf32_Word size) {
|
||||
char *src = (char *) firmware;
|
||||
|
||||
/* Seek to the specified offset. */
|
||||
src = src + offset;
|
||||
|
||||
/* Read the data. */
|
||||
env_memcpy((char *) destination, src, size);
|
||||
|
||||
/* Return status to caller. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_read_headers
|
||||
*
|
||||
* Reads the ELF headers (ELF header, section headers and the section
|
||||
* headers string table) essential to access further information from
|
||||
* the file containing the ELF object.
|
||||
*
|
||||
* @param firmware - firmware to read from.
|
||||
* @param elf_info - ELF object decode info container.
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
static int elf_loader_read_headers(void *firmware,
|
||||
struct elf_decode_info *elf_info) {
|
||||
int status = 0;
|
||||
unsigned int section_count;
|
||||
|
||||
/* Read the ELF header. */
|
||||
status = elf_loader_seek_and_read(firmware, &(elf_info->elf_header), 0,
|
||||
sizeof(Elf32_Ehdr));
|
||||
|
||||
/* Ensure the read was successful. */
|
||||
if (!status) {
|
||||
/* Get section count from the ELF header. */
|
||||
section_count = elf_info->elf_header.e_shnum;
|
||||
|
||||
/* Allocate memory to read in the section headers. */
|
||||
elf_info->section_headers_start = env_allocate_memory(
|
||||
section_count * elf_info->elf_header.e_shentsize);
|
||||
|
||||
/* Check if the allocation was successful. */
|
||||
if (elf_info->section_headers_start) {
|
||||
/* Read the section headers list. */
|
||||
status = elf_loader_seek_and_read(firmware,
|
||||
elf_info->section_headers_start,
|
||||
elf_info->elf_header.e_shoff,
|
||||
section_count * elf_info->elf_header.e_shentsize);
|
||||
|
||||
/* Ensure the read was successful. */
|
||||
if (!status) {
|
||||
/* Compute the pointer to section header string table section. */
|
||||
Elf32_Shdr *section_header_string_table =
|
||||
(Elf32_Shdr *) (elf_info->section_headers_start
|
||||
+ elf_info->elf_header.e_shstrndx
|
||||
* elf_info->elf_header.e_shentsize);
|
||||
|
||||
/* Allocate the memory for section header string table. */
|
||||
elf_info->shstrtab = env_allocate_memory(
|
||||
section_header_string_table->sh_size);
|
||||
|
||||
/* Ensure the allocation was successful. */
|
||||
if (elf_info->shstrtab) {
|
||||
/* Read the section headers string table. */
|
||||
status = elf_loader_seek_and_read(firmware,
|
||||
elf_info->shstrtab,
|
||||
section_header_string_table->sh_offset,
|
||||
section_header_string_table->sh_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status to caller. */
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_file_read_sections
|
||||
*
|
||||
* Reads the ELF section contents from the specified file containing
|
||||
* the ELF object.
|
||||
*
|
||||
* @param firmware - firmware to read from.
|
||||
* @param elf_info - ELF object decode info container.
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
static int elf_loader_load_sections(void *firmware,
|
||||
struct elf_decode_info *elf_info) {
|
||||
int status = 0;
|
||||
Elf32_Shdr *current = (Elf32_Shdr *) (elf_info->section_headers_start);
|
||||
|
||||
/* Traverse all sections except the reserved null section. */
|
||||
int section_count = elf_info->elf_header.e_shnum - 1;
|
||||
while ((section_count > 0) && (status == 0)) {
|
||||
/* Compute the pointer to section header. */
|
||||
current = (Elf32_Shdr *) (((unsigned char *) current)
|
||||
+ elf_info->elf_header.e_shentsize);
|
||||
|
||||
/* Make sure the section can be allocated and is not empty. */
|
||||
if ((current->sh_flags & SHF_ALLOC) && (current->sh_size)) {
|
||||
char *destination = NULL;
|
||||
|
||||
/* Check if the section is part of runtime and is not section with
|
||||
* no-load attributes such as BSS or heap. */
|
||||
if ((current->sh_type & SHT_NOBITS) == 0) {
|
||||
/* Compute the destination address where the section should
|
||||
* be copied. */
|
||||
destination = (char *) (current->sh_addr);
|
||||
status = elf_loader_seek_and_read(firmware, destination,
|
||||
current->sh_offset, current->sh_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to the next section. */
|
||||
section_count--;
|
||||
}
|
||||
|
||||
/* Return status to caller. */
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_get_decode_info
|
||||
*
|
||||
* Retrieves the information necessary to decode the ELF object for
|
||||
* loading, relocating and linking.
|
||||
*
|
||||
* @param firmware - firmware to read from.
|
||||
* @param elf_info - ELF object decode info container.
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
static int elf_loader_get_decode_info(void *firmware,
|
||||
struct elf_decode_info *elf_info) {
|
||||
int status;
|
||||
|
||||
/* Read the ELF headers (ELF header and section headers including
|
||||
* the section header string table). */
|
||||
status = elf_loader_read_headers(firmware, elf_info);
|
||||
|
||||
/* Ensure that ELF headers were read successfully. */
|
||||
if (!status) {
|
||||
/* Retrieve the sections required for load. */
|
||||
elf_loader_get_needed_sections(elf_info);
|
||||
|
||||
}
|
||||
|
||||
/* Return status to caller. */
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_get_dynamic_symbol_addr
|
||||
*
|
||||
* Retrieves the (relocatable) address of the symbol specified as
|
||||
* index from the given ELF object.
|
||||
*
|
||||
* @param elf_info - ELF object decode info container.
|
||||
* @param index - Index of the desired symbol in the dynamic symbol table.
|
||||
*
|
||||
* @return - Address of the specified symbol.
|
||||
*/
|
||||
static Elf32_Addr elf_loader_get_dynamic_symbol_addr(
|
||||
struct elf_decode_info *elf_info, int index) {
|
||||
Elf32_Sym *symbol_entry = (Elf32_Sym *) (elf_info->dynsym_addr
|
||||
+ index * elf_info->dynsym->sh_entsize);
|
||||
|
||||
/* Return the symbol address. */
|
||||
return (symbol_entry->st_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_loader_reloc_entry
|
||||
*
|
||||
* Processes the specified relocation entry. It handles the relocation
|
||||
* and linking both cases.
|
||||
*
|
||||
*
|
||||
* @param elf_info - ELF object decode info container.
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
static int elf_loader_reloc_entry(struct elf_decode_info *elf_info,
|
||||
Elf32_Rel *rel_entry) {
|
||||
unsigned char rel_type = ELF32_R_TYPE(rel_entry->r_info);
|
||||
int status = 0;
|
||||
|
||||
switch (rel_type) {
|
||||
case R_ARM_ABS32: /* 0x02 */
|
||||
{
|
||||
Elf32_Addr sym_addr = elf_loader_get_dynamic_symbol_addr(elf_info,
|
||||
ELF32_R_SYM(rel_entry->r_info));
|
||||
|
||||
if (sym_addr) {
|
||||
*((unsigned int *) (rel_entry->r_offset)) = (unsigned int) sym_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
234
ThirdParty/sw_services/xilopenamp/src/elf_loader.h
vendored
Normal file
234
ThirdParty/sw_services/xilopenamp/src/elf_loader.h
vendored
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ELF_LOADER_H_
|
||||
#define ELF_LOADER_H_
|
||||
|
||||
#include "remoteproc_loader.h"
|
||||
|
||||
/* ELF base types - 32-bit. */
|
||||
typedef unsigned int Elf32_Addr;
|
||||
typedef unsigned short Elf32_Half;
|
||||
typedef unsigned int Elf32_Off;
|
||||
typedef signed int Elf32_Sword;
|
||||
typedef unsigned int Elf32_Word;
|
||||
|
||||
/* Size of ELF identifier field in the ELF file header. */
|
||||
#define EI_NIDENT 16
|
||||
|
||||
/* ELF file header */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf32_Half e_type;
|
||||
Elf32_Half e_machine;
|
||||
Elf32_Word e_version;
|
||||
Elf32_Addr e_entry;
|
||||
Elf32_Off e_phoff;
|
||||
Elf32_Off e_shoff;
|
||||
Elf32_Word e_flags;
|
||||
Elf32_Half e_ehsize;
|
||||
Elf32_Half e_phentsize;
|
||||
Elf32_Half e_phnum;
|
||||
Elf32_Half e_shentsize;
|
||||
Elf32_Half e_shnum;
|
||||
Elf32_Half e_shstrndx;
|
||||
|
||||
} Elf32_Ehdr;
|
||||
|
||||
/* e_ident */
|
||||
#define ET_NONE 0
|
||||
#define ET_REL 1 /* Re-locatable file */
|
||||
#define ET_EXEC 2 /* Executable file */
|
||||
#define ET_DYN 3 /* Shared object file */
|
||||
#define ET_CORE 4 /* Core file */
|
||||
#define ET_LOOS 0xfe00 /* Operating system-specific */
|
||||
#define ET_HIOS 0xfeff /* Operating system-specific */
|
||||
#define ET_LOPROC 0xff00 /* remote_proc-specific */
|
||||
#define ET_HIPROC 0xffff /* remote_proc-specific */
|
||||
|
||||
/* e_machine */
|
||||
#define EM_ARM 40 /* ARM/Thumb Architecture */
|
||||
|
||||
/* e_version */
|
||||
#define EV_CURRENT 1 /* Current version */
|
||||
|
||||
/* e_ident[] Identification Indexes */
|
||||
#define EI_MAG0 0 /* File identification */
|
||||
#define EI_MAG1 1 /* File identification */
|
||||
#define EI_MAG2 2 /* File identification */
|
||||
#define EI_MAG3 3 /* File identification */
|
||||
#define EI_CLASS 4 /* File class */
|
||||
#define EI_DATA 5 /* Data encoding */
|
||||
#define EI_VERSION 6 /* File version */
|
||||
#define EI_OSABI 7 /* Operating system/ABI identification */
|
||||
#define EI_ABIVERSION 8 /* ABI version */
|
||||
#define EI_PAD 9 /* Start of padding bytes */
|
||||
#define EI_NIDENT 16 /* Size of e_ident[] */
|
||||
|
||||
/* EI_MAG0 to EI_MAG3 - A file's first 4 bytes hold amagic number, identifying the file as an ELF object file */
|
||||
#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
|
||||
#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
|
||||
#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
|
||||
#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
|
||||
|
||||
/* EI_CLASS - The next byte, e_ident[EI_CLASS], identifies the file's class, or capacity. */
|
||||
#define ELFCLASSNONE 0 /* Invalid class */
|
||||
#define ELFCLASS32 1 /* 32-bit objects */
|
||||
#define ELFCLASS64 2 /* 64-bit objects */
|
||||
|
||||
/* EI_DATA - Byte e_ident[EI_DATA] specifies the data encoding of the remote_proc-specific data in the object
|
||||
file. The following encodings are currently defined. */
|
||||
#define ELFDATANONE 0 /* Invalid data encoding */
|
||||
#define ELFDATA2LSB 1 /* See Data encodings, below */
|
||||
#define ELFDATA2MSB 2 /* See Data encodings, below */
|
||||
|
||||
/* EI_OSABI - We do not define an OS specific ABI */
|
||||
#define ELFOSABI_NONE 0
|
||||
|
||||
/* ELF section header. */
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Word sh_name;
|
||||
Elf32_Word sh_type;
|
||||
Elf32_Word sh_flags;
|
||||
Elf32_Addr sh_addr;
|
||||
Elf32_Off sh_offset;
|
||||
Elf32_Word sh_size;
|
||||
Elf32_Word sh_link;
|
||||
Elf32_Word sh_info;
|
||||
Elf32_Word sh_addralign;
|
||||
Elf32_Word sh_entsize;
|
||||
|
||||
} Elf32_Shdr;
|
||||
|
||||
/* sh_type */
|
||||
#define SHT_NULL 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3
|
||||
#define SHT_RELA 4
|
||||
#define SHT_HASH 5
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOTE 7
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
#define SHT_SHLIB 10
|
||||
#define SHT_DYNSYM 11
|
||||
#define SHT_INIT_ARRAY 14
|
||||
#define SHT_FINI_ARRAY 15
|
||||
#define SHT_PREINIT_ARRAY 16
|
||||
#define SHT_GROUP 17
|
||||
#define SHT_SYMTAB_SHNDX 18
|
||||
#define SHT_LOOS 0x60000000
|
||||
#define SHT_HIOS 0x6fffffff
|
||||
#define SHT_LOPROC 0x70000000
|
||||
#define SHT_HIPROC 0x7fffffff
|
||||
#define SHT_LOUSER 0x80000000
|
||||
#define SHT_HIUSER 0xffffffff
|
||||
|
||||
/* sh_flags */
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_ALLOC 0x2
|
||||
#define SHF_EXECINSTR 0x4
|
||||
#define SHF_MASKPROC 0xf0000000
|
||||
|
||||
/* Relocation entry (without addend) */
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Addr r_offset;
|
||||
Elf32_Word r_info;
|
||||
|
||||
} Elf32_Rel;
|
||||
|
||||
/* Relocation entry with addend */
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Addr r_offset;
|
||||
Elf32_Word r_info;
|
||||
Elf32_Sword r_addend;
|
||||
|
||||
} Elf32_Rela;
|
||||
|
||||
/* Macros to extract information from 'r_info' field of relocation entries */
|
||||
#define ELF32_R_SYM(i) ((i)>>8)
|
||||
#define ELF32_R_TYPE(i) ((unsigned char)(i))
|
||||
|
||||
/* Symbol table entry */
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Word st_name;
|
||||
Elf32_Addr st_value;
|
||||
Elf32_Word st_size;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf32_Half st_shndx;
|
||||
|
||||
} Elf32_Sym;
|
||||
|
||||
/* ARM specific dynamic relocation codes */
|
||||
#define R_ARM_GLOB_DAT 21 /* 0x15 */
|
||||
#define R_ARM_JUMP_SLOT 22 /* 0x16 */
|
||||
#define R_ARM_RELATIVE 23 /* 0x17 */
|
||||
#define R_ARM_ABS32 2 /* 0x02 */
|
||||
|
||||
|
||||
/* ELF decoding information */
|
||||
struct elf_decode_info
|
||||
{
|
||||
Elf32_Ehdr elf_header;
|
||||
unsigned char *section_headers_start;
|
||||
char *shstrtab;
|
||||
|
||||
Elf32_Shdr *dynsym;
|
||||
Elf32_Shdr *dynstr;
|
||||
Elf32_Shdr *rel_plt;
|
||||
Elf32_Shdr *rel_dyn;
|
||||
Elf32_Shdr *rsc;
|
||||
|
||||
unsigned char *dynsym_addr;
|
||||
unsigned char *dynstr_addr;
|
||||
|
||||
char *firmware;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* ELF Loader functions. */
|
||||
int elf_loader_init(struct remoteproc_loader *loader);
|
||||
void *elf_loader_retrieve_entry_point(struct remoteproc_loader *loader);
|
||||
void *elf_loader_retrieve_resource_section(struct remoteproc_loader *loader, unsigned int *size);
|
||||
int elf_loader_load_remote_firmware(struct remoteproc_loader *loader);
|
||||
int elf_loader_attach_firmware(struct remoteproc_loader *loader, void *firmware);
|
||||
int elf_loader_detach_firmware(struct remoteproc_loader *loader);
|
||||
void *elf_get_load_address(struct remoteproc_loader *loader);
|
||||
|
||||
#endif /* ELF_LOADER_H_ */
|
428
ThirdParty/sw_services/xilopenamp/src/env.h
vendored
Normal file
428
ThirdParty/sw_services/xilopenamp/src/env.h
vendored
Normal file
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* env.h
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP stack.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file defines abstraction layer for OpenAMP stack. The implementor
|
||||
* must provide definition of all the functions.
|
||||
*
|
||||
* DATA STRUCTURES
|
||||
*
|
||||
* none
|
||||
*
|
||||
* FUNCTIONS
|
||||
*
|
||||
* env_allocate_memory
|
||||
* env_free_memory
|
||||
* env_memset
|
||||
* env_memcpy
|
||||
* env_strlen
|
||||
* env_strcpy
|
||||
* env_strncpy
|
||||
* env_print
|
||||
* env_map_vatopa
|
||||
* env_map_patova
|
||||
* env_mb
|
||||
* env_rmb
|
||||
* env_wmb
|
||||
* env_create_mutex
|
||||
* env_delete_mutex
|
||||
* env_lock_mutex
|
||||
* env_unlock_mutex
|
||||
* env_sleep_msec
|
||||
* env_disable_interrupts
|
||||
* env_restore_interrupts
|
||||
*
|
||||
**************************************************************************/
|
||||
#ifndef _ENV_H_
|
||||
#define _ENV_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* env_init
|
||||
*
|
||||
* Initializes OS/BM environment.
|
||||
*
|
||||
* @returns - execution status
|
||||
*/
|
||||
|
||||
int env_init();
|
||||
|
||||
/**
|
||||
* env_deinit
|
||||
*
|
||||
* Uninitializes OS/BM environment.
|
||||
*
|
||||
* @returns - execution status
|
||||
*/
|
||||
|
||||
int env_deinit();
|
||||
/**
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Dynamic memory management functions. The parameters
|
||||
* are similar to standard c functions.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
**/
|
||||
|
||||
/**
|
||||
* env_allocate_memory
|
||||
*
|
||||
* Allocates memory with the given size.
|
||||
*
|
||||
* @param size - size of memory to allocate
|
||||
*
|
||||
* @return - pointer to allocated memory
|
||||
*/
|
||||
void *env_allocate_memory(unsigned int size);
|
||||
|
||||
/**
|
||||
* env_free_memory
|
||||
*
|
||||
* Frees memory pointed by the given parameter.
|
||||
*
|
||||
* @param ptr - pointer to memory to free
|
||||
*/
|
||||
void env_free_memory(void *ptr);
|
||||
|
||||
/**
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* RTL Functions
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void env_memset(void *, int, unsigned long);
|
||||
void env_memcpy(void *, void const *, unsigned long);
|
||||
size_t env_strlen(const char *);
|
||||
void env_strcpy(char *, const char *);
|
||||
int env_strcmp(const char *, const char *);
|
||||
void env_strncpy(char *, const char *, unsigned long);
|
||||
int env_strncmp(char *, const char *, unsigned long);
|
||||
#define env_print(...) printf(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Functions to convert physical address to virtual address and vice versa.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* env_map_vatopa
|
||||
*
|
||||
* Converts logical address to physical address
|
||||
*
|
||||
* @param address - pointer to logical address
|
||||
*
|
||||
* @return - physical address
|
||||
*/
|
||||
unsigned long env_map_vatopa(void *address);
|
||||
|
||||
/**
|
||||
* env_map_patova
|
||||
*
|
||||
* Converts physical address to logical address
|
||||
*
|
||||
* @param address - pointer to physical address
|
||||
*
|
||||
* @return - logical address
|
||||
*
|
||||
*/
|
||||
void *env_map_patova(unsigned long address);
|
||||
|
||||
/**
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Abstractions for memory barrier instructions.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* env_mb
|
||||
*
|
||||
* Inserts memory barrier.
|
||||
*/
|
||||
|
||||
void env_mb();
|
||||
|
||||
/**
|
||||
* env_rmb
|
||||
*
|
||||
* Inserts read memory barrier
|
||||
*/
|
||||
|
||||
void env_rmb();
|
||||
|
||||
/**
|
||||
* env_wmb
|
||||
*
|
||||
* Inserts write memory barrier
|
||||
*/
|
||||
|
||||
void env_wmb();
|
||||
|
||||
/**
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
* Abstractions for OS lock primitives.
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* env_create_mutex
|
||||
*
|
||||
* Creates a mutex with given initial count.
|
||||
*
|
||||
* @param lock - pointer to created mutex
|
||||
* @param count - initial count 0 or 1
|
||||
*
|
||||
* @return - status of function execution
|
||||
*/
|
||||
int env_create_mutex(void **lock , int count);
|
||||
|
||||
/**
|
||||
* env_delete_mutex
|
||||
*
|
||||
* Deletes the given lock.
|
||||
*
|
||||
* @param lock - mutex to delete
|
||||
*/
|
||||
|
||||
void env_delete_mutex(void *lock);
|
||||
|
||||
/**
|
||||
* env_lock_mutex
|
||||
*
|
||||
* Tries to acquire the lock, if lock is not available then call to
|
||||
* this function will suspend.
|
||||
*
|
||||
* @param lock - mutex to lock
|
||||
*
|
||||
*/
|
||||
|
||||
void env_lock_mutex(void *lock);
|
||||
|
||||
/**
|
||||
* env_unlock_mutex
|
||||
*
|
||||
* Releases the given lock.
|
||||
*
|
||||
* @param lock - mutex to unlock
|
||||
*/
|
||||
|
||||
void env_unlock_mutex(void *lock);
|
||||
|
||||
/**
|
||||
* env_create_sync_lock
|
||||
*
|
||||
* Creates a synchronization lock primitive. It is used
|
||||
* when signal has to be sent from the interrupt context to main
|
||||
* thread context.
|
||||
*
|
||||
* @param lock - pointer to created sync lock object
|
||||
* @param state - initial state , lock or unlocked
|
||||
*
|
||||
* @returns - status of function execution
|
||||
*/
|
||||
#define LOCKED 0
|
||||
#define UNLOCKED 1
|
||||
|
||||
int env_create_sync_lock(void **lock , int state);
|
||||
|
||||
/**
|
||||
* env_create_sync_lock
|
||||
*
|
||||
* Deletes given sync lock object.
|
||||
*
|
||||
* @param lock - sync lock to delete.
|
||||
*
|
||||
*/
|
||||
|
||||
void env_delete_sync_lock(void *lock);
|
||||
|
||||
|
||||
/**
|
||||
* env_acquire_sync_lock
|
||||
*
|
||||
* Tries to acquire the sync lock.
|
||||
*
|
||||
* @param lock - sync lock to acquire.
|
||||
*/
|
||||
void env_acquire_sync_lock(void *lock);
|
||||
|
||||
/**
|
||||
* env_release_sync_lock
|
||||
*
|
||||
* Releases synchronization lock.
|
||||
*
|
||||
* @param lock - sync lock to release.
|
||||
*/
|
||||
void env_release_sync_lock(void *lock);
|
||||
|
||||
/**
|
||||
* env_sleep_msec
|
||||
*
|
||||
* Suspends the calling thread for given time in msecs.
|
||||
*
|
||||
* @param num_msec - delay in msecs
|
||||
*/
|
||||
void env_sleep_msec(int num_msec);
|
||||
|
||||
/**
|
||||
* env_disable_interrupts
|
||||
*
|
||||
* Disables system interrupts
|
||||
*
|
||||
*/
|
||||
void env_disable_interrupts();
|
||||
|
||||
/**
|
||||
* env_restore_interrupts
|
||||
*
|
||||
* Enables system interrupts
|
||||
*
|
||||
*/
|
||||
void env_restore_interrupts();
|
||||
|
||||
/**
|
||||
* env_register_isr
|
||||
*
|
||||
* Registers interrupt handler for the given interrupt vector.
|
||||
*
|
||||
* @param vector - interrupt vector number
|
||||
* @param data - private data
|
||||
* @param isr - interrupt handler
|
||||
*/
|
||||
|
||||
void env_register_isr(int vector, void *data,
|
||||
void (*isr)(int vector, void *data));
|
||||
|
||||
void env_update_isr(int vector, void *data,
|
||||
void (*isr)(int vector, void *data));
|
||||
|
||||
/**
|
||||
* env_enable_interrupt
|
||||
*
|
||||
* Enables the given interrupt.
|
||||
*
|
||||
* @param vector - interrupt vector number
|
||||
* @param priority - interrupt priority
|
||||
* @param polarity - interrupt polarity
|
||||
*/
|
||||
|
||||
void env_enable_interrupt(unsigned int vector, unsigned int priority,
|
||||
unsigned int polarity);
|
||||
|
||||
/**
|
||||
* env_disable_interrupt
|
||||
*
|
||||
* Disables the given interrupt.
|
||||
*
|
||||
* @param vector - interrupt vector number
|
||||
*/
|
||||
|
||||
void env_disable_interrupt(unsigned int vector);
|
||||
|
||||
/**
|
||||
* env_map_memory
|
||||
*
|
||||
* Enables memory mapping for given memory region.
|
||||
*
|
||||
* @param pa - physical address of memory
|
||||
* @param va - logical address of memory
|
||||
* @param size - memory size
|
||||
* param flags - flags for cache/uncached and access type
|
||||
*
|
||||
* Currently only first byte of flag parameter is used and bits mapping is defined as follow;
|
||||
*
|
||||
* Cache bits
|
||||
* 0x0000_0001 = No cache
|
||||
* 0x0000_0010 = Write back
|
||||
* 0x0000_0100 = Write through
|
||||
* 0x0000_x000 = Not used
|
||||
*
|
||||
* Memory types
|
||||
*
|
||||
* 0x0001_xxxx = Memory Mapped
|
||||
* 0x0010_xxxx = IO Mapped
|
||||
* 0x0100_xxxx = Shared
|
||||
* 0x1000_xxxx = TLB
|
||||
*/
|
||||
|
||||
/* Macros for caching scheme used by the shared memory */
|
||||
#define UNCACHED (1 << 0)
|
||||
#define WB_CACHE (1 << 1)
|
||||
#define WT_CACHE (1 << 2)
|
||||
|
||||
/* Memory Types */
|
||||
#define MEM_MAPPED (1 << 4)
|
||||
#define IO_MAPPED (1 << 5)
|
||||
#define SHARED_MEM (1 << 6)
|
||||
#define TLB_MEM (1 << 7)
|
||||
|
||||
void env_map_memory(unsigned int pa, unsigned int va, unsigned int size,
|
||||
unsigned int flags);
|
||||
|
||||
/**
|
||||
* env_get_timestamp
|
||||
*
|
||||
* Returns a 64 bit time stamp.
|
||||
*
|
||||
*
|
||||
*/
|
||||
unsigned long long env_get_timestamp(void);
|
||||
|
||||
/**
|
||||
* env_disable_cache
|
||||
*
|
||||
* Disables system caches.
|
||||
*
|
||||
*/
|
||||
|
||||
void env_disable_cache();
|
||||
|
||||
typedef void LOCK;
|
||||
|
||||
#endif /* _ENV_H_ */
|
406
ThirdParty/sw_services/xilopenamp/src/hil.c
vendored
Normal file
406
ThirdParty/sw_services/xilopenamp/src/hil.c
vendored
Normal file
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* hil.c
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP Stack.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file is implementation of generic part of HIL.
|
||||
*
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "hil.h"
|
||||
|
||||
/*--------------------------- Globals ---------------------------------- */
|
||||
struct hil_proc_list procs;
|
||||
|
||||
#if defined (OPENAMP_BENCHMARK_ENABLE)
|
||||
|
||||
unsigned long long boot_time_stamp;
|
||||
unsigned long long shutdown_time_stamp;
|
||||
|
||||
#endif
|
||||
|
||||
extern int platform_get_processor_info(struct hil_proc *proc, int cpu_id);
|
||||
extern int platform_get_processor_for_fw(char *fw_name);
|
||||
|
||||
/**
|
||||
* hil_create_proc
|
||||
*
|
||||
* This function creates a HIL proc instance for given CPU id and populates
|
||||
* it with platform info.
|
||||
*
|
||||
* @param cpu_id - cpu id
|
||||
*
|
||||
* @return - pointer to proc instance
|
||||
*
|
||||
*/
|
||||
struct hil_proc *hil_create_proc(int cpu_id) {
|
||||
struct hil_proc *proc = NULL;
|
||||
struct llist *node = NULL;
|
||||
struct llist *proc_hd = procs.proc_list;
|
||||
int status;
|
||||
|
||||
/* If proc already exists then return it */
|
||||
while (proc_hd != NULL) {
|
||||
proc = (struct hil_proc *) proc_hd->data;
|
||||
if (proc->cpu_id == cpu_id) {
|
||||
return proc;
|
||||
}
|
||||
proc_hd = proc_hd->next;
|
||||
}
|
||||
|
||||
/* Allocate memory for proc instance */
|
||||
proc = env_allocate_memory(sizeof(struct hil_proc));
|
||||
if (!proc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get HW specfic info */
|
||||
status = platform_get_processor_info(proc, cpu_id);
|
||||
if (status) {
|
||||
env_free_memory(proc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Enable mapping for the shared memory region */
|
||||
env_map_memory((unsigned int) proc->sh_buff.start_addr,
|
||||
(unsigned int) proc->sh_buff.start_addr, proc->sh_buff.size,
|
||||
(SHARED_MEM | UNCACHED));
|
||||
|
||||
/* Put the new proc in the procs list */
|
||||
node = env_allocate_memory(sizeof(struct llist));
|
||||
|
||||
if (!node) {
|
||||
env_free_memory(proc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->data = proc;
|
||||
add_to_list(&procs.proc_list, node);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_get_cpuforfw
|
||||
*
|
||||
* This function provides the CPU ID for the given firmware.
|
||||
*
|
||||
* @param fw_name - name of firmware
|
||||
*
|
||||
* @return - cpu id
|
||||
*
|
||||
*/
|
||||
int hil_get_cpuforfw(char *fw_name) {
|
||||
return (platform_get_processor_for_fw(fw_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_delete_proc
|
||||
*
|
||||
* This function deletes the given proc instance and frees the
|
||||
* associated resources.
|
||||
*
|
||||
* @param proc - pointer to hil remote_proc instance
|
||||
*
|
||||
*/
|
||||
void hil_delete_proc(struct hil_proc *proc) {
|
||||
struct llist *proc_hd = NULL;
|
||||
|
||||
if (!proc)
|
||||
return;
|
||||
|
||||
proc_hd = procs.proc_list;
|
||||
|
||||
while (proc_hd != NULL) {
|
||||
if (proc_hd->data == proc) {
|
||||
remove_from_list(&procs.proc_list, proc_hd);
|
||||
env_free_memory(proc_hd);
|
||||
break;
|
||||
}
|
||||
proc_hd = proc_hd->next;
|
||||
}
|
||||
|
||||
env_free_memory(proc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hil_isr()
|
||||
*
|
||||
* This function is called when interrupt is received for the vring.
|
||||
* This function gets the corresponding virtqueue and generates
|
||||
* call back for it.
|
||||
*
|
||||
* @param vring_hw - pointer to vring control block
|
||||
*
|
||||
*/
|
||||
void hil_isr(struct proc_vring *vring_hw){
|
||||
virtqueue_notification(vring_hw->vq);
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_get_proc
|
||||
*
|
||||
* This function finds the proc instance based on the given ID
|
||||
* from the proc list and returns it to user.
|
||||
*
|
||||
* @param cpu_id - cpu id
|
||||
*
|
||||
* @return - pointer to hil proc instance
|
||||
*
|
||||
*/
|
||||
struct hil_proc *hil_get_proc(int cpu_id) {
|
||||
struct llist *proc_hd = procs.proc_list;
|
||||
|
||||
if (!proc_hd)
|
||||
return NULL;
|
||||
|
||||
while (proc_hd != NULL) {
|
||||
struct hil_proc *proc = (struct hil_proc *) proc_hd->data;
|
||||
if (proc->cpu_id == cpu_id) {
|
||||
return proc;
|
||||
}
|
||||
proc_hd = proc_hd->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_get_chnl_info
|
||||
*
|
||||
* This function returns channels info for given proc.
|
||||
*
|
||||
* @param proc - pointer to proc info struct
|
||||
* @param num_chnls - pointer to integer variable to hold
|
||||
* number of available channels
|
||||
*
|
||||
* @return - pointer to channel info control block
|
||||
*
|
||||
*/
|
||||
struct proc_chnl *hil_get_chnl_info(struct hil_proc *proc, int *num_chnls) {
|
||||
*num_chnls = proc->num_chnls;
|
||||
return (proc->chnls);
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_get_vdev_info
|
||||
*
|
||||
* This function return virtio device for remote core.
|
||||
*
|
||||
* @param proc - pointer to remote proc
|
||||
*
|
||||
* @return - pointer to virtio HW device.
|
||||
*
|
||||
*/
|
||||
|
||||
struct proc_vdev *hil_get_vdev_info(struct hil_proc *proc) {
|
||||
return (&proc->vdev);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_get_vring_info
|
||||
*
|
||||
* This function returns vring_info_table. The caller will use
|
||||
* this table to get the vring HW info which will be subsequently
|
||||
* used to create virtqueues.
|
||||
*
|
||||
* @param vdev - pointer to virtio HW device
|
||||
* @param num_vrings - pointer to hold number of vrings
|
||||
*
|
||||
* @return - pointer to vring hardware info table
|
||||
*/
|
||||
struct proc_vring *hil_get_vring_info(struct proc_vdev *vdev, int *num_vrings) {
|
||||
|
||||
*num_vrings = vdev->num_vrings;
|
||||
return (vdev->vring_info);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_get_shm_info
|
||||
*
|
||||
* This function returns shared memory info control block. The caller
|
||||
* will use this information to create and manage memory buffers for
|
||||
* vring descriptor table.
|
||||
*
|
||||
* @param proc - pointer to proc instance
|
||||
*
|
||||
* @return - pointer to shared memory region used for buffers
|
||||
*
|
||||
*/
|
||||
struct proc_shm *hil_get_shm_info(struct hil_proc *proc) {
|
||||
return (&proc->sh_buff);
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_enable_vring_notifications()
|
||||
*
|
||||
* This function is called after successful creation of virtqueues.
|
||||
* This function saves queue handle in the vring_info_table which
|
||||
* will be used during interrupt handling .This function setups
|
||||
* interrupt handlers.
|
||||
*
|
||||
* @param vring_index - index to vring HW table
|
||||
* @param vq - pointer to virtqueue to save in vring HW table
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int hil_enable_vring_notifications(int vring_index, struct virtqueue *vq) {
|
||||
struct hil_proc *proc_hw = (struct hil_proc *) vq->vq_dev->device;
|
||||
struct proc_vring *vring_hw = &proc_hw->vdev.vring_info[vring_index];
|
||||
/* Save virtqueue pointer for later reference */
|
||||
vring_hw->vq = vq;
|
||||
|
||||
if (proc_hw->ops->enable_interrupt) {
|
||||
proc_hw->ops->enable_interrupt(vring_hw);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_vring_notify()
|
||||
*
|
||||
* This function generates IPI to let the other side know that there is
|
||||
* job available for it. The required information to achieve this, like interrupt
|
||||
* vector, CPU id etc is be obtained from the proc_vring table.
|
||||
*
|
||||
* @param vq - pointer to virtqueue
|
||||
*
|
||||
*/
|
||||
void hil_vring_notify(struct virtqueue *vq) {
|
||||
struct hil_proc *proc_hw = (struct hil_proc *) vq->vq_dev->device;
|
||||
struct proc_vring *vring_hw = &proc_hw->vdev.vring_info[vq->vq_queue_index];
|
||||
|
||||
if (proc_hw->ops->notify) {
|
||||
proc_hw->ops->notify(proc_hw->cpu_id, &vring_hw->intr_info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_get_status
|
||||
*
|
||||
* This function is used to check if the given core is up and running.
|
||||
* This call will return after it is confirmed that remote core has
|
||||
* started.
|
||||
*
|
||||
* @param proc - pointer to proc instance
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int hil_get_status(struct hil_proc *proc) {
|
||||
/* For future use only.*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_set_status
|
||||
*
|
||||
* This function is used to update the status
|
||||
* of the given core i.e it is ready for IPC.
|
||||
*
|
||||
* @param proc - pointer to remote proc
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int hil_set_status(struct hil_proc *proc) {
|
||||
/* For future use only.*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_boot_cpu
|
||||
*
|
||||
* This function boots the remote processor.
|
||||
*
|
||||
* @param proc - pointer to remote proc
|
||||
* @param start_addr - start address of remote cpu
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int hil_boot_cpu(struct hil_proc *proc, unsigned int start_addr) {
|
||||
|
||||
if (proc->ops->boot_cpu) {
|
||||
proc->ops->boot_cpu(proc->cpu_id, start_addr);
|
||||
}
|
||||
|
||||
#if defined (OPENAMP_BENCHMARK_ENABLE)
|
||||
boot_time_stamp = env_get_timestamp();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_shutdown_cpu
|
||||
*
|
||||
* This function shutdowns the remote processor
|
||||
*
|
||||
* @param proc - pointer to remote proc
|
||||
*
|
||||
*/
|
||||
void hil_shutdown_cpu(struct hil_proc *proc) {
|
||||
if (proc->ops->shutdown_cpu) {
|
||||
proc->ops->shutdown_cpu(proc->cpu_id);
|
||||
}
|
||||
|
||||
#if defined (OPENAMP_BENCHMARK_ENABLE)
|
||||
shutdown_time_stamp = env_get_timestamp();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* hil_get_firmware
|
||||
*
|
||||
* This function returns address and size of given firmware name passed as
|
||||
* parameter.
|
||||
*
|
||||
* @param fw_name - name of the firmware
|
||||
* @param start_addr - pointer t hold start address of firmware
|
||||
* @param size - pointer to hold size of firmware
|
||||
*
|
||||
* returns - status of function execution
|
||||
*
|
||||
*/
|
||||
int hil_get_firmware(char *fw_name, unsigned int *start_addr, unsigned int *size){
|
||||
return (config_get_firmware(fw_name , start_addr, size));
|
||||
}
|
486
ThirdParty/sw_services/xilopenamp/src/hil.h
vendored
Normal file
486
ThirdParty/sw_services/xilopenamp/src/hil.h
vendored
Normal file
|
@ -0,0 +1,486 @@
|
|||
#ifndef _HIL_H_
|
||||
#define _HIL_H_
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the <ORGANIZATION> 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* hil.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file defines interface layer to access hardware features. This
|
||||
* interface is used by both RPMSG and remoteproc components.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "virtio.h"
|
||||
#include "config.h"
|
||||
|
||||
/* Configurable parameters */
|
||||
#define HIL_MAX_CORES 2
|
||||
#define HIL_MAX_NUM_VRINGS 2
|
||||
#define HIL_MAX_NUM_CHANNELS 1
|
||||
/* Reserved CPU id */
|
||||
#define HIL_RSVD_CPU_ID 0xffffffff
|
||||
|
||||
/**
|
||||
* struct proc_shm
|
||||
*
|
||||
* This structure is maintained by hardware interface layer for
|
||||
* shared memory information. The shared memory provides buffers
|
||||
* for use by the vring to exchange messages between the cores.
|
||||
*
|
||||
*/
|
||||
struct proc_shm
|
||||
{
|
||||
/* Start address of shared memory used for buffers. */
|
||||
void *start_addr;
|
||||
/* Size of shared memory. */
|
||||
unsigned long size;
|
||||
/* Attributes for shared memory - cached or uncached. */
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct proc_intr
|
||||
*
|
||||
* This structure is maintained by hardware interface layer for
|
||||
* notification(interrupts) mechanism. The most common notification mechanism
|
||||
* is Inter-Processor Interrupt(IPI). There can be other mechanism depending
|
||||
* on SoC architecture.
|
||||
*
|
||||
*/
|
||||
struct proc_intr
|
||||
{
|
||||
/* Interrupt number for vring - use for IPI */
|
||||
unsigned int vect_id;
|
||||
/* Interrupt priority */
|
||||
unsigned int priority;
|
||||
/* Interrupt trigger type */
|
||||
unsigned int trigger_type;
|
||||
/* Private data */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct proc_vring
|
||||
*
|
||||
* This structure is maintained by hardware interface layer to keep
|
||||
* vring physical memory and notification info.
|
||||
*
|
||||
*/
|
||||
struct proc_vring
|
||||
{
|
||||
/* Pointer to virtqueue encapsulating the vring */
|
||||
struct virtqueue *vq;
|
||||
/* Vring physical address */
|
||||
void *phy_addr;
|
||||
/* Number of vring descriptors */
|
||||
unsigned short num_descs;
|
||||
/* Vring alignment*/
|
||||
unsigned long align;
|
||||
/* Vring interrupt control block */
|
||||
struct proc_intr intr_info;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct proc_vdev
|
||||
*
|
||||
* This structure represents a virtio HW device for remote processor.
|
||||
* Currently only one virtio device per processor is supported.
|
||||
*
|
||||
*/
|
||||
struct proc_vdev
|
||||
{
|
||||
/* Number of vrings*/
|
||||
unsigned int num_vrings;
|
||||
/* Virtio device features */
|
||||
unsigned int dfeatures;
|
||||
/* Virtio gen features */
|
||||
unsigned int gfeatures;
|
||||
/* Vring info control blocks */
|
||||
struct proc_vring vring_info[HIL_MAX_NUM_VRINGS];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct proc_chnl
|
||||
*
|
||||
* This structure represents channel IDs that would be used by
|
||||
* the remote in the name service message. This will be extended
|
||||
* further to support static channel creation.
|
||||
*
|
||||
*/
|
||||
struct proc_chnl
|
||||
{
|
||||
/* Channel ID */
|
||||
char name[32];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hil_proc
|
||||
*
|
||||
* This structure represents a remote processor and encapsulates shared
|
||||
* memory and notification info required for IPC.
|
||||
*
|
||||
*/
|
||||
struct hil_proc
|
||||
{
|
||||
/* CPU ID as defined by the platform */
|
||||
unsigned long cpu_id;
|
||||
/* Shared memory info */
|
||||
struct proc_shm sh_buff;
|
||||
/* Virtio device hardware info */
|
||||
struct proc_vdev vdev;
|
||||
/* Number of RPMSG channels */
|
||||
unsigned long num_chnls;
|
||||
/* RPMsg channels array */
|
||||
struct proc_chnl chnls[HIL_MAX_NUM_CHANNELS];
|
||||
/* HIL platform ops table */
|
||||
struct hil_platform_ops *ops;
|
||||
/* Attrbites to represent processor role, master or remote . This field is for
|
||||
* future use. */
|
||||
unsigned long attr;
|
||||
/*
|
||||
* CPU bitmask - shared variable updated by each core
|
||||
* after it has been initialized. This field is for future use.
|
||||
*/
|
||||
unsigned long cpu_bitmask;
|
||||
/* Spin lock - This field is for future use. */
|
||||
volatile unsigned int *slock;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hil_proc_list
|
||||
*
|
||||
* This structure serves as lists for cores present in the system.
|
||||
* It provides entry point to access remote core parameters.
|
||||
*
|
||||
*/
|
||||
struct hil_proc_list {
|
||||
struct llist *proc_list;
|
||||
};
|
||||
|
||||
/**
|
||||
* hil_create_proc
|
||||
*
|
||||
* This function creates a HIL proc instance for given CPU id and populates
|
||||
* it with platform info.
|
||||
*
|
||||
* @param cpu_id - cpu id
|
||||
*
|
||||
* @return - pointer to proc instance
|
||||
*
|
||||
*/
|
||||
struct hil_proc *hil_create_proc(int cpu_id);
|
||||
|
||||
/**
|
||||
* hil_delete_proc
|
||||
*
|
||||
* This function deletes the given proc instance and frees the
|
||||
* associated resources.
|
||||
*
|
||||
* @param proc - pointer to HIL proc instance
|
||||
*
|
||||
*/
|
||||
void hil_delete_proc(struct hil_proc *proc);
|
||||
|
||||
/**
|
||||
* hil_get_proc
|
||||
*
|
||||
* This function finds the proc instance based on the given ID
|
||||
* from the proc list and returns it to user.
|
||||
*
|
||||
* @param cpu_id - cpu id
|
||||
*
|
||||
* @return - pointer to proc instance
|
||||
*
|
||||
*/
|
||||
struct hil_proc *hil_get_proc(int cpu_id);
|
||||
|
||||
/**
|
||||
* hil_isr()
|
||||
*
|
||||
* This function is called when interrupt is received for the vring.
|
||||
* This function gets the corresponding virtqueue and generates
|
||||
* call back for it.
|
||||
*
|
||||
* @param vring_hw - pointer to vring control block
|
||||
*
|
||||
*/
|
||||
void hil_isr(struct proc_vring *vring_hw);
|
||||
|
||||
/**
|
||||
* hil_get_cpuforfw
|
||||
*
|
||||
* This function provides the CPU ID for the given firmware.
|
||||
*
|
||||
* @param fw_name - name of firmware
|
||||
*
|
||||
* @return - cpu id
|
||||
*
|
||||
*/
|
||||
int hil_get_cpuforfw(char *fw_name);
|
||||
|
||||
/**
|
||||
* hil_get_vdev_info
|
||||
*
|
||||
* This function return virtio device for remote core.
|
||||
*
|
||||
* @param proc - pointer to remote proc
|
||||
*
|
||||
* @return - pointer to virtio HW device.
|
||||
*
|
||||
*/
|
||||
struct proc_vdev *hil_get_vdev_info(struct hil_proc *proc);
|
||||
|
||||
/**
|
||||
* hil_get_chnl_info
|
||||
*
|
||||
* This function returns channels info for given proc.
|
||||
*
|
||||
* @param proc - pointer to proc info struct
|
||||
* @param num_chnls - pointer to integer variable to hold
|
||||
* number of available channels
|
||||
*
|
||||
* @return - pointer to channel info control block
|
||||
*
|
||||
*/
|
||||
struct proc_chnl *hil_get_chnl_info(struct hil_proc *proc , int *num_chnls);
|
||||
|
||||
/**
|
||||
* hil_get_vring_info
|
||||
*
|
||||
* This function returns vring_info_table. The caller will use
|
||||
* this table to get the vring HW info which will be subsequently
|
||||
* used to create virtqueues.
|
||||
*
|
||||
* @param vdev - pointer to virtio HW device
|
||||
* @param num_vrings - pointer to hold number of vrings
|
||||
*
|
||||
* @return - pointer to vring hardware info table
|
||||
*/
|
||||
struct proc_vring *hil_get_vring_info(struct proc_vdev *vdev, int *num_vrings);
|
||||
|
||||
/**
|
||||
* hil_get_shm_info
|
||||
*
|
||||
* This function returns shared memory info control block. The caller
|
||||
* will use this information to create and manage memory buffers for
|
||||
* vring descriptor table.
|
||||
*
|
||||
* @param proc - pointer to proc instance
|
||||
*
|
||||
* @return - pointer to shared memory region used for buffers
|
||||
*
|
||||
*/
|
||||
struct proc_shm *hil_get_shm_info(struct hil_proc *proc);
|
||||
|
||||
/**
|
||||
* hil_enable_vring_notifications()
|
||||
*
|
||||
* This function is called after successful creation of virtqueues.
|
||||
* This function saves queue handle in the vring_info_table which
|
||||
* will be used during interrupt handling .This function setups
|
||||
* interrupt handlers.
|
||||
*
|
||||
* @param vring_index - index to vring HW table
|
||||
* @param vq - pointer to virtqueue to save in vring HW table
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int hil_enable_vring_notifications(int vring_index, struct virtqueue *vq);
|
||||
|
||||
/**
|
||||
* hil_vring_notify()
|
||||
*
|
||||
* This function generates IPI to let the other side know that there is
|
||||
* job available for it. The required information to achieve this, like interrupt
|
||||
* vector, CPU id etc is be obtained from the proc_vring table.
|
||||
*
|
||||
* @param vq - pointer to virtqueue
|
||||
*
|
||||
*/
|
||||
void hil_vring_notify(struct virtqueue *vq);
|
||||
|
||||
/**
|
||||
* hil_get_status
|
||||
*
|
||||
* This function is used to check if the given core is up and running.
|
||||
* This call will return after it is confirmed that remote core has
|
||||
* started.
|
||||
*
|
||||
* @param proc - pointer to proc instance
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int hil_get_status(struct hil_proc *proc);
|
||||
|
||||
/**
|
||||
* hil_set_status
|
||||
*
|
||||
* This function is used to update the status
|
||||
* of the given core i.e it is ready for IPC.
|
||||
*
|
||||
* @param proc - pointer to remote proc
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
|
||||
int hil_set_status(struct hil_proc *proc);
|
||||
|
||||
/**
|
||||
* hil_boot_cpu
|
||||
*
|
||||
* This function starts remote processor at given address.
|
||||
*
|
||||
* @param proc - pointer to remote proc
|
||||
* @param load_addr - load address of remote firmware
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int hil_boot_cpu(struct hil_proc *proc , unsigned int load_addr);
|
||||
|
||||
/**
|
||||
* hil_shutdown_cpu
|
||||
*
|
||||
* This function shutdowns the remote processor
|
||||
*
|
||||
* @param proc - pointer to remote proc
|
||||
*
|
||||
*/
|
||||
void hil_shutdown_cpu(struct hil_proc *proc);
|
||||
|
||||
/**
|
||||
* hil_get_firmware
|
||||
*
|
||||
* This function returns address and size of given firmware name passed as
|
||||
* parameter.
|
||||
*
|
||||
* @param fw_name - name of the firmware
|
||||
* @param start_addr - pointer t hold start address of firmware
|
||||
* @param size - pointer to hold size of firmware
|
||||
*
|
||||
* returns - status of function execution
|
||||
*
|
||||
*/
|
||||
int hil_get_firmware(char *fw_name, unsigned int *start_addr, unsigned int *size);
|
||||
|
||||
/**
|
||||
*
|
||||
* This structure is an interface between HIL and platform porting
|
||||
* component. It is required for the user to provide definitions of
|
||||
* these functions when framework is ported to new hardware platform.
|
||||
*
|
||||
*/
|
||||
struct hil_platform_ops
|
||||
{
|
||||
/**
|
||||
* enable_interrupt()
|
||||
*
|
||||
* This function enables interrupt(IPI) for given vring.
|
||||
*
|
||||
* @param vring_hw - pointer to vring control block
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int (*enable_interrupt)(struct proc_vring *vring_hw);
|
||||
|
||||
/**
|
||||
* reg_ipi_after_deinit()
|
||||
* This function register interrupt(IPI) after openamp resource .
|
||||
*
|
||||
* @param vring_hw - pointer to vring control block
|
||||
*/
|
||||
void (*reg_ipi_after_deinit)(struct proc_vring *vring_hw);
|
||||
|
||||
/**
|
||||
* notify()
|
||||
*
|
||||
* This function generates IPI to let the other side know that there is
|
||||
* job available for it.
|
||||
*
|
||||
* @param cpu_id - ID of CPU which is to be notified
|
||||
* @param intr_info - pointer to interrupt info control block
|
||||
*/
|
||||
void (*notify)(int cpu_id , struct proc_intr *intr_info);
|
||||
|
||||
/**
|
||||
* get_status
|
||||
*
|
||||
* This function is used to check if the given core is
|
||||
* up and running. This call will return after it is confirmed
|
||||
* that remote core is initialized.
|
||||
*
|
||||
* @param cpu_id - ID of CPU for which status is requested.
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int (*get_status)(int cpu_id);
|
||||
|
||||
/**
|
||||
* set_status
|
||||
*
|
||||
* This function is used to update the status
|
||||
* of the given core i.e it is ready for IPC.
|
||||
*
|
||||
* @param cpu_id - ID of CPU for which status is to be set
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
|
||||
int (*set_status)(int cpu_id);
|
||||
|
||||
/**
|
||||
* boot_cpu
|
||||
*
|
||||
* This function boots the remote processor.
|
||||
*
|
||||
* @param cpu_id - ID of CPU to boot
|
||||
* @param start_addr - start address of remote cpu
|
||||
*
|
||||
* @return - execution status
|
||||
*/
|
||||
int (*boot_cpu)(int cpu_id , unsigned int start_addr);
|
||||
|
||||
/**
|
||||
* shutdown_cpu
|
||||
*
|
||||
* This function shutdowns the remote processor.
|
||||
*
|
||||
* @param cpu_id - ID of CPU to shutdown
|
||||
*
|
||||
*/
|
||||
void (*shutdown_cpu)(int cpu_id);
|
||||
|
||||
};
|
||||
|
||||
#endif /* _HIL_H_ */
|
100
ThirdParty/sw_services/xilopenamp/src/llist.c
vendored
Normal file
100
ThirdParty/sw_services/xilopenamp/src/llist.c
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* llist.c
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP stack.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Source file for basic linked list service.
|
||||
*
|
||||
**************************************************************************/
|
||||
#include "llist.h"
|
||||
|
||||
#define LIST_NULL ((void *)0)
|
||||
/**
|
||||
* add_to_list
|
||||
*
|
||||
* Places new element at the start of the list.
|
||||
*
|
||||
* @param head - list head
|
||||
* @param node - new element to add
|
||||
*
|
||||
*/
|
||||
void add_to_list(struct llist **head, struct llist *node) {
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
if (*head) {
|
||||
/* Place the new element at the start of list. */
|
||||
node->next = *head;
|
||||
node->prev = LIST_NULL;
|
||||
(*head)->prev = node;
|
||||
*head = node;
|
||||
} else {
|
||||
/* List is empty - assign new element to list head. */
|
||||
*head = node;
|
||||
(*head)->next = LIST_NULL;
|
||||
(*head)->prev = LIST_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove_from_list
|
||||
*
|
||||
* Removes the given element from the list.
|
||||
*
|
||||
* @param head - list head
|
||||
* @param element - element to remove from list
|
||||
*
|
||||
*/
|
||||
void remove_from_list(struct llist **head, struct llist *node) {
|
||||
|
||||
if (!(*head) || !(node))
|
||||
return;
|
||||
|
||||
if (node == *head) {
|
||||
/* First element has to be removed. */
|
||||
*head = (*head)->next;
|
||||
} else if (node->next == LIST_NULL) {
|
||||
/* Last element has to be removed. */
|
||||
node->prev->next = node->next;
|
||||
} else {
|
||||
/* Intermediate element has to be removed. */
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
}
|
59
ThirdParty/sw_services/xilopenamp/src/llist.h
vendored
Normal file
59
ThirdParty/sw_services/xilopenamp/src/llist.h
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* llist.h
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP stack.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Header file for linked list service.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef LLIST_H_
|
||||
#define LLIST_H_
|
||||
|
||||
struct llist {
|
||||
void *data;
|
||||
unsigned int attr;
|
||||
struct llist *next;
|
||||
struct llist *prev;
|
||||
};
|
||||
|
||||
void add_to_list(struct llist **head, struct llist *node);
|
||||
void remove_from_list(struct llist **head, struct llist *node);
|
||||
|
||||
#endif /* LLIST_H_ */
|
37
ThirdParty/sw_services/xilopenamp/src/open_amp.h
vendored
Normal file
37
ThirdParty/sw_services/xilopenamp/src/open_amp.h
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
#ifndef OPEN_AMP_H_
|
||||
#define OPEN_AMP_H_
|
||||
|
||||
#include "rpmsg.h"
|
||||
#include "remoteproc.h"
|
||||
|
||||
|
||||
#endif /* OPEN_AMP_H_ */
|
513
ThirdParty/sw_services/xilopenamp/src/remote_device.c
vendored
Normal file
513
ThirdParty/sw_services/xilopenamp/src/remote_device.c
vendored
Normal file
|
@ -0,0 +1,513 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* remote_device.c
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP Stack
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file provides services to manage the remote devices.It also implements
|
||||
* the interface defined by the virtio and provides few other utility functions.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "rpmsg.h"
|
||||
|
||||
/* Macro to initialize vring HW info */
|
||||
#define INIT_VRING_ALLOC_INFO(ring_info,vring_hw) \
|
||||
(ring_info).phy_addr = (vring_hw).phy_addr; \
|
||||
(ring_info).align = (vring_hw).align; \
|
||||
(ring_info).num_descs = (vring_hw).num_descs
|
||||
|
||||
/* Local functions */
|
||||
static int rpmsg_rdev_init_channels(struct remote_device *rdev);
|
||||
|
||||
/* Ops table for virtio device */
|
||||
virtio_dispatch rpmsg_rdev_config_ops =
|
||||
{
|
||||
rpmsg_rdev_create_virtqueues,
|
||||
rpmsg_rdev_get_status,
|
||||
rpmsg_rdev_set_status,
|
||||
rpmsg_rdev_get_feature,
|
||||
rpmsg_rdev_set_feature,
|
||||
rpmsg_rdev_negotiate_feature,
|
||||
rpmsg_rdev_read_config,
|
||||
rpmsg_rdev_write_config,
|
||||
rpmsg_rdev_reset
|
||||
};
|
||||
|
||||
/**
|
||||
* rpmsg_rdev_init
|
||||
*
|
||||
* This function creates and initializes the remote device. The remote device
|
||||
* encapsulates virtio device.
|
||||
*
|
||||
* @param rdev - pointer to newly created remote device
|
||||
* @param dev-id - ID of device to create , remote cpu id
|
||||
* @param role - role of the other device, Master or Remote
|
||||
* @param channel_created - callback function for channel creation
|
||||
* @param channel_destroyed - callback function for channel deletion
|
||||
* @param default_cb - default callback for channel
|
||||
*
|
||||
* @return - status of function execution
|
||||
*
|
||||
*/
|
||||
int rpmsg_rdev_init(struct remote_device **rdev, int dev_id, int role,
|
||||
rpmsg_chnl_cb_t channel_created,
|
||||
rpmsg_chnl_cb_t channel_destroyed,
|
||||
rpmsg_rx_cb_t default_cb) {
|
||||
|
||||
struct remote_device *rdev_loc;
|
||||
struct virtio_device *virt_dev;
|
||||
struct hil_proc *proc;
|
||||
struct proc_shm *shm;
|
||||
int status;
|
||||
|
||||
/* Initialize HIL data structures for given device */
|
||||
proc = hil_create_proc(dev_id);
|
||||
|
||||
if (!proc) {
|
||||
return RPMSG_ERR_DEV_ID;
|
||||
}
|
||||
|
||||
/* Create software representation of remote processor. */
|
||||
rdev_loc = (struct remote_device *) env_allocate_memory(
|
||||
sizeof(struct remote_device));
|
||||
|
||||
if (!rdev_loc) {
|
||||
return RPMSG_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
env_memset(rdev_loc, 0x00, sizeof(struct remote_device));
|
||||
status = env_create_mutex(&rdev_loc->lock, 1);
|
||||
|
||||
if (status != RPMSG_SUCCESS) {
|
||||
|
||||
/* Cleanup required in case of error is performed by caller */
|
||||
return status;
|
||||
}
|
||||
|
||||
rdev_loc->proc = proc;
|
||||
rdev_loc->role = role;
|
||||
rdev_loc->channel_created = channel_created;
|
||||
rdev_loc->channel_destroyed = channel_destroyed;
|
||||
rdev_loc->default_cb = default_cb;
|
||||
|
||||
/* Initialize the virtio device */
|
||||
virt_dev = &rdev_loc->virt_dev;
|
||||
virt_dev->device = proc;
|
||||
virt_dev->func = &rpmsg_rdev_config_ops;
|
||||
if (virt_dev->func->set_features != RPMSG_NULL) {
|
||||
virt_dev->func->set_features(virt_dev, proc->vdev.dfeatures);
|
||||
}
|
||||
|
||||
if (rdev_loc->role == RPMSG_REMOTE) {
|
||||
/*
|
||||
* Since device is RPMSG Remote so we need to manage the
|
||||
* shared buffers. Create shared memory pool to handle buffers.
|
||||
*/
|
||||
shm = hil_get_shm_info(proc);
|
||||
rdev_loc->mem_pool = sh_mem_create_pool(shm->start_addr, shm->size,
|
||||
RPMSG_BUFFER_SIZE);
|
||||
|
||||
if (!rdev_loc->mem_pool) {
|
||||
return RPMSG_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize channels for RPMSG Remote */
|
||||
status = rpmsg_rdev_init_channels(rdev_loc);
|
||||
|
||||
if (status != RPMSG_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
*rdev = rdev_loc;
|
||||
|
||||
return RPMSG_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_rdev_deinit
|
||||
*
|
||||
* This function un-initializes the remote device.
|
||||
*
|
||||
* @param rdev - pointer to remote device to deinit.
|
||||
*
|
||||
* @return - none
|
||||
*
|
||||
*/
|
||||
void rpmsg_rdev_deinit(struct remote_device *rdev) {
|
||||
struct llist *rp_chnl_head, *rp_chnl_temp, *node;
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
|
||||
rp_chnl_head = rdev->rp_channels;
|
||||
|
||||
while (rp_chnl_head != RPMSG_NULL ) {
|
||||
|
||||
rp_chnl_temp = rp_chnl_head->next;
|
||||
rp_chnl = (struct rpmsg_channel *) rp_chnl_head->data;
|
||||
|
||||
if (rdev->channel_destroyed) {
|
||||
rdev->channel_destroyed(rp_chnl);
|
||||
}
|
||||
|
||||
if ((rdev->support_ns) && (rdev->role == RPMSG_MASTER)) {
|
||||
rpmsg_send_ns_message(rdev, rp_chnl, RPMSG_NS_DESTROY);
|
||||
}
|
||||
|
||||
/* Delete default endpoint for channel */
|
||||
if (rp_chnl->rp_ept) {
|
||||
rpmsg_destroy_ept(rp_chnl->rp_ept);
|
||||
}
|
||||
|
||||
_rpmsg_delete_channel(rp_chnl);
|
||||
rp_chnl_head = rp_chnl_temp;
|
||||
}
|
||||
|
||||
/* Delete name service endpoint */
|
||||
node = rpmsg_rdev_get_endpoint_from_addr(rdev,RPMSG_NS_EPT_ADDR);
|
||||
if (node) {
|
||||
_destroy_endpoint(rdev, (struct rpmsg_endpoint *) node->data);
|
||||
}
|
||||
|
||||
if (rdev->rvq) {
|
||||
virtqueue_free(rdev->rvq);
|
||||
}
|
||||
if (rdev->tvq) {
|
||||
virtqueue_free(rdev->tvq);
|
||||
}
|
||||
if (rdev->mem_pool) {
|
||||
sh_mem_delete_pool(rdev->mem_pool);
|
||||
}
|
||||
if (rdev->lock) {
|
||||
env_delete_mutex(rdev->lock);
|
||||
}
|
||||
|
||||
env_free_memory(rdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_rdev_get_chnl_node_from_id
|
||||
*
|
||||
* This function returns channel node based on channel name.
|
||||
*
|
||||
* @param stack - pointer to remote device
|
||||
* @param rp_chnl_id - rpmsg channel name
|
||||
*
|
||||
* @return - channel node
|
||||
*
|
||||
*/
|
||||
struct llist *rpmsg_rdev_get_chnl_node_from_id(struct remote_device *rdev,
|
||||
char *rp_chnl_id) {
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
struct llist *rp_chnl_head;
|
||||
|
||||
rp_chnl_head = rdev->rp_channels;
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
while (rp_chnl_head) {
|
||||
rp_chnl = (struct rpmsg_channel *) rp_chnl_head->data;
|
||||
if (env_strncmp(rp_chnl->name, rp_chnl_id, sizeof(rp_chnl->name))
|
||||
== 0) {
|
||||
env_unlock_mutex(rdev->lock);
|
||||
return rp_chnl_head;
|
||||
}
|
||||
rp_chnl_head = rp_chnl_head->next;
|
||||
}
|
||||
env_unlock_mutex(rdev->lock);
|
||||
|
||||
return RPMSG_NULL ;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_rdev_get_chnl_from_addr
|
||||
*
|
||||
* This function returns channel node based on src/dst address.
|
||||
*
|
||||
* @param rdev - pointer remote device control block
|
||||
* @param addr - src/dst address
|
||||
*
|
||||
* @return - channel node
|
||||
*
|
||||
*/
|
||||
struct llist *rpmsg_rdev_get_chnl_from_addr(struct remote_device *rdev,
|
||||
unsigned long addr) {
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
struct llist *rp_chnl_head;
|
||||
|
||||
rp_chnl_head = rdev->rp_channels;
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
while (rp_chnl_head) {
|
||||
rp_chnl = (struct rpmsg_channel *) rp_chnl_head->data;
|
||||
if ((rp_chnl->src == addr) || (rp_chnl->dst == addr)) {
|
||||
env_unlock_mutex(rdev->lock);
|
||||
return rp_chnl_head;
|
||||
}
|
||||
rp_chnl_head = rp_chnl_head->next;
|
||||
}
|
||||
env_unlock_mutex(rdev->lock);
|
||||
|
||||
return RPMSG_NULL ;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_rdev_get_endpoint_from_addr
|
||||
*
|
||||
* This function returns endpoint node based on src address.
|
||||
*
|
||||
* @param rdev - pointer remote device control block
|
||||
* @param addr - src address
|
||||
*
|
||||
* @return - endpoint node
|
||||
*
|
||||
*/
|
||||
struct llist *rpmsg_rdev_get_endpoint_from_addr(struct remote_device *rdev,
|
||||
unsigned long addr) {
|
||||
struct llist *rp_ept_lut_head;
|
||||
|
||||
rp_ept_lut_head = rdev->rp_endpoints;
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
while (rp_ept_lut_head) {
|
||||
struct rpmsg_endpoint *rp_ept =
|
||||
(struct rpmsg_endpoint *) rp_ept_lut_head->data;
|
||||
if (rp_ept->addr == addr) {
|
||||
env_unlock_mutex(rdev->lock);
|
||||
return rp_ept_lut_head;
|
||||
}
|
||||
rp_ept_lut_head = rp_ept_lut_head->next;
|
||||
}
|
||||
env_unlock_mutex(rdev->lock);
|
||||
|
||||
return RPMSG_NULL ;
|
||||
}
|
||||
/*
|
||||
* rpmsg_rdev_notify
|
||||
*
|
||||
* This function checks whether remote device is up or not. If it is up then
|
||||
* notification is sent based on device role to start IPC.
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
*
|
||||
* @return - status of function execution
|
||||
*
|
||||
*/
|
||||
int rpmsg_rdev_notify(struct remote_device *rdev) {
|
||||
int status = RPMSG_SUCCESS;
|
||||
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
status = hil_get_status(rdev->proc);
|
||||
|
||||
/*
|
||||
* Let the remote device know that Master is ready for
|
||||
* communication.
|
||||
*/
|
||||
if (!status)
|
||||
virtqueue_kick(rdev->rvq);
|
||||
|
||||
} else {
|
||||
status = hil_set_status(rdev->proc);
|
||||
}
|
||||
|
||||
if (status == RPMSG_SUCCESS) {
|
||||
rdev->state = RPMSG_DEV_STATE_ACTIVE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/**
|
||||
* rpmsg_rdev_init_channels
|
||||
*
|
||||
* This function is only applicable to RPMSG remote. It obtains channel IDs
|
||||
* from the HIL and creates RPMSG channels corresponding to each ID.
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
*
|
||||
* @return - status of function execution
|
||||
*
|
||||
*/
|
||||
int rpmsg_rdev_init_channels(struct remote_device *rdev) {
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
struct proc_chnl *chnl_info;
|
||||
int num_chnls, idx;
|
||||
|
||||
if (rdev->role == RPMSG_MASTER) {
|
||||
|
||||
chnl_info = hil_get_chnl_info(rdev->proc, &num_chnls);
|
||||
for (idx = 0; idx < num_chnls; idx++) {
|
||||
|
||||
rp_chnl = _rpmsg_create_channel(rdev, chnl_info[idx].name, 0x00,
|
||||
RPMSG_NS_EPT_ADDR);
|
||||
if (!rp_chnl) {
|
||||
return RPMSG_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
rp_chnl->rp_ept = rpmsg_create_ept(rp_chnl, rdev->default_cb, rdev,
|
||||
RPMSG_ADDR_ANY);
|
||||
|
||||
if (!rp_chnl->rp_ept) {
|
||||
return RPMSG_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
rp_chnl->src = rp_chnl->rp_ept->addr;
|
||||
}
|
||||
}
|
||||
|
||||
return RPMSG_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
*------------------------------------------------------------------------
|
||||
* The rest of the file implements the virtio device interface as defined
|
||||
* by the virtio.h file.
|
||||
*------------------------------------------------------------------------
|
||||
*/
|
||||
int rpmsg_rdev_create_virtqueues(struct virtio_device *dev, int flags, int nvqs,
|
||||
const char *names[], vq_callback *callbacks[],
|
||||
struct virtqueue *vqs_[]) {
|
||||
struct remote_device *rdev;
|
||||
struct vring_alloc_info ring_info;
|
||||
struct virtqueue *vqs[RPMSG_MAX_VQ_PER_RDEV];
|
||||
struct proc_vring *vring_table;
|
||||
void *buffer;
|
||||
struct llist node;
|
||||
int idx, num_vrings, status;
|
||||
|
||||
rdev = (struct remote_device*) dev;
|
||||
|
||||
/* Get the vring HW info for the given virtio device */
|
||||
vring_table = hil_get_vring_info(&rdev->proc->vdev,
|
||||
&num_vrings);
|
||||
|
||||
if (num_vrings > nvqs) {
|
||||
return RPMSG_ERR_MAX_VQ;
|
||||
}
|
||||
|
||||
/* Create virtqueue for each vring. */
|
||||
for (idx = 0; idx < num_vrings; idx++) {
|
||||
|
||||
INIT_VRING_ALLOC_INFO( ring_info, vring_table[idx]);
|
||||
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
env_memset((void*) ring_info.phy_addr, 0x00,
|
||||
vring_size(vring_table[idx].num_descs,
|
||||
vring_table[idx].align));
|
||||
}
|
||||
|
||||
status = virtqueue_create(dev, idx, (char *) names[idx], &ring_info,
|
||||
callbacks[idx], hil_vring_notify,
|
||||
&vqs[idx]);
|
||||
|
||||
if (status != RPMSG_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME - a better way to handle this , tx for master is rx for remote and vice versa.
|
||||
if (rdev->role == RPMSG_MASTER) {
|
||||
rdev->tvq = vqs[0];
|
||||
rdev->rvq = vqs[1];
|
||||
} else {
|
||||
rdev->tvq = vqs[1];
|
||||
rdev->rvq = vqs[0];
|
||||
}
|
||||
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
for (idx = 0; ((idx < rdev->rvq->vq_nentries)
|
||||
&& (idx < rdev->mem_pool->total_buffs / 2));
|
||||
idx++) {
|
||||
|
||||
/* Initialize TX virtqueue buffers for remote device */
|
||||
buffer = sh_mem_get_buffer(rdev->mem_pool);
|
||||
|
||||
if (!buffer) {
|
||||
return RPMSG_ERR_NO_BUFF;
|
||||
}
|
||||
|
||||
node.data = buffer;
|
||||
node.attr = RPMSG_BUFFER_SIZE;
|
||||
node.next = RPMSG_NULL;
|
||||
|
||||
env_memset(buffer, 0x00, RPMSG_BUFFER_SIZE);
|
||||
status = virtqueue_add_buffer(rdev->rvq, &node, 0, 1, buffer);
|
||||
|
||||
if (status != RPMSG_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RPMSG_SUCCESS;
|
||||
}
|
||||
|
||||
unsigned char rpmsg_rdev_get_status(struct virtio_device *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rpmsg_rdev_set_status(struct virtio_device *dev, unsigned char status) {
|
||||
|
||||
}
|
||||
|
||||
unsigned long rpmsg_rdev_get_feature(struct virtio_device *dev) {
|
||||
return dev->features;
|
||||
}
|
||||
|
||||
void rpmsg_rdev_set_feature(struct virtio_device *dev, unsigned long feature) {
|
||||
dev->features |= feature;
|
||||
}
|
||||
|
||||
unsigned long rpmsg_rdev_negotiate_feature(struct virtio_device *dev,
|
||||
unsigned long features) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Read/write a variable amount from the device specific (ie, network)
|
||||
* configuration region. This region is encoded in the same endian as
|
||||
* the guest.
|
||||
*/
|
||||
void rpmsg_rdev_read_config(struct virtio_device *dev, unsigned long offset,
|
||||
void *dst, int length) {
|
||||
return;
|
||||
}
|
||||
void rpmsg_rdev_write_config(struct virtio_device *dev, unsigned long offset,
|
||||
void *src, int length) {
|
||||
return;
|
||||
}
|
||||
void rpmsg_rdev_reset(struct virtio_device *dev) {
|
||||
return;
|
||||
}
|
359
ThirdParty/sw_services/xilopenamp/src/remoteproc.c
vendored
Normal file
359
ThirdParty/sw_services/xilopenamp/src/remoteproc.c
vendored
Normal file
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
#include "remoteproc.h"
|
||||
#include "remoteproc_loader.h"
|
||||
#include "rsc_table_parser.h"
|
||||
#include "env.h"
|
||||
#include "hil.h"
|
||||
|
||||
/**
|
||||
* remoteproc_resource_init
|
||||
*
|
||||
* Initializes resources for remoteproc remote configuration. Only
|
||||
* remoteproc remote applications are allowed to call this function.
|
||||
*
|
||||
* @param rsc_info - pointer to resource table info control
|
||||
* block
|
||||
* @param channel_created - callback function for channel creation
|
||||
* @param channel_destroyed - callback function for channel deletion
|
||||
* @param default_cb - default callback for channel I/O
|
||||
* @param rproc_handle - pointer to new remoteproc instance
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*
|
||||
*/
|
||||
int remoteproc_resource_init(struct rsc_table_info *rsc_info,
|
||||
rpmsg_chnl_cb_t channel_created, rpmsg_chnl_cb_t channel_destroyed,
|
||||
rpmsg_rx_cb_t default_cb, struct remote_proc** rproc_handle) {
|
||||
|
||||
struct remote_proc *rproc;
|
||||
int status;
|
||||
|
||||
if(!rsc_info) {
|
||||
return RPROC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Initialize environment component */
|
||||
status = env_init();
|
||||
if (status != RPROC_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
rproc = env_allocate_memory(sizeof(struct remote_proc));
|
||||
if (rproc) {
|
||||
env_memset(rproc, 0x00, sizeof(struct remote_proc));
|
||||
/* There can be only one master for remote configuration so use the
|
||||
* rsvd cpu id for creating hil proc */
|
||||
rproc->proc = hil_create_proc(HIL_RSVD_CPU_ID);
|
||||
if (rproc->proc) {
|
||||
/* Parse resource table */
|
||||
status = handle_rsc_table(rproc, rsc_info->rsc_tab, rsc_info->size);
|
||||
if (status == RPROC_SUCCESS) {
|
||||
/* Initialize RPMSG "messaging" component */
|
||||
*rproc_handle = rproc;
|
||||
status = rpmsg_init(rproc->proc->cpu_id, &rproc->rdev,
|
||||
channel_created, channel_destroyed, default_cb,
|
||||
RPMSG_MASTER);
|
||||
} else {
|
||||
status = RPROC_ERR_NO_RSC_TABLE;
|
||||
}
|
||||
} else {
|
||||
status = RPROC_ERR_CPU_ID;
|
||||
}
|
||||
} else {
|
||||
status = RPROC_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
/* Cleanup in case of error */
|
||||
if (status != RPROC_SUCCESS) {
|
||||
*rproc_handle = 0;
|
||||
(void) remoteproc_resource_deinit(rproc);
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_resource_deinit
|
||||
*
|
||||
* Uninitializes resources for remoteproc "remote" configuration.
|
||||
*
|
||||
* @param rproc - pointer to rproc instance
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*
|
||||
*/
|
||||
|
||||
int remoteproc_resource_deinit(struct remote_proc *rproc) {
|
||||
int i = 0;
|
||||
struct proc_vring *vring_hw = 0;
|
||||
if (rproc) {
|
||||
if (rproc->rdev) {
|
||||
/* disable IPC interrupts */
|
||||
if (rproc->proc->ops->reg_ipi_after_deinit) {
|
||||
for(i = 0; i < 2; i++) {
|
||||
vring_hw = &rproc->proc->vdev.vring_info[i];
|
||||
rproc->proc->ops->reg_ipi_after_deinit(vring_hw);
|
||||
}
|
||||
}
|
||||
rpmsg_deinit(rproc->rdev);
|
||||
}
|
||||
if (rproc->proc) {
|
||||
hil_delete_proc(rproc->proc);
|
||||
}
|
||||
|
||||
env_free_memory(rproc);
|
||||
}
|
||||
|
||||
env_deinit();
|
||||
|
||||
/* Disable the caches - This is required if master boots firmwares
|
||||
* multiple times without hard reset on same core. If caches are
|
||||
* not invalidated at this point in time then subsequent firmware
|
||||
* boots on the same core may experience cache inconsistencies.
|
||||
*
|
||||
*/
|
||||
env_disable_cache();
|
||||
|
||||
return RPROC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_init
|
||||
*
|
||||
* Initializes resources for remoteproc master configuration. Only
|
||||
* remoteproc master applications are allowed to call this function.
|
||||
*
|
||||
* @param fw_name - name of frimware
|
||||
* @param channel_created - callback function for channel creation
|
||||
* @param channel_destroyed - callback function for channel deletion
|
||||
* @param default_cb - default callback for channel I/O
|
||||
* @param rproc_handle - pointer to new remoteproc instance
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*
|
||||
*/
|
||||
int remoteproc_init(char *fw_name, rpmsg_chnl_cb_t channel_created,
|
||||
rpmsg_chnl_cb_t channel_destroyed, rpmsg_rx_cb_t default_cb,
|
||||
struct remote_proc** rproc_handle) {
|
||||
|
||||
struct remote_proc *rproc;
|
||||
struct resource_table *rsc_table;
|
||||
unsigned int fw_addr, fw_size, rsc_size;
|
||||
int status, cpu_id;
|
||||
|
||||
if (!fw_name) {
|
||||
return RPROC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Initialize environment component */
|
||||
status = env_init();
|
||||
if (status != RPROC_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
rproc = env_allocate_memory(sizeof(struct remote_proc));
|
||||
if (rproc) {
|
||||
env_memset((void *) rproc, 0x00, sizeof(struct remote_proc));
|
||||
/* Get CPU ID for the given firmware name */
|
||||
cpu_id = hil_get_cpuforfw(fw_name);
|
||||
if (cpu_id >= 0) {
|
||||
/* Create proc instance */
|
||||
rproc->proc = hil_create_proc(cpu_id);
|
||||
if (rproc->proc) {
|
||||
/* Retrieve firmware attributes */
|
||||
status = hil_get_firmware(fw_name, &fw_addr, &fw_size);
|
||||
if (!status) {
|
||||
/* Initialize ELF loader - currently only ELF format is supported */
|
||||
rproc->loader = remoteproc_loader_init(ELF_LOADER);
|
||||
if (rproc->loader) {
|
||||
/* Attach the given firmware with the ELF parser/loader */
|
||||
status = remoteproc_loader_attach_firmware(
|
||||
rproc->loader, (void *) fw_addr);
|
||||
} else {
|
||||
status = RPROC_ERR_LOADER;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status = RPROC_ERR_NO_MEM;
|
||||
}
|
||||
} else {
|
||||
status = RPROC_ERR_INVLD_FW;
|
||||
}
|
||||
} else {
|
||||
status = RPROC_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
rproc->role = RPROC_MASTER;
|
||||
|
||||
/* Get resource table from firmware */
|
||||
rsc_table = remoteproc_loader_retrieve_resource_section(rproc->loader,
|
||||
&rsc_size);
|
||||
if (rsc_table) {
|
||||
/* Parse resource table */
|
||||
status = handle_rsc_table(rproc, rsc_table, rsc_size);
|
||||
} else {
|
||||
status = RPROC_ERR_NO_RSC_TABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup in case of error */
|
||||
if (status != RPROC_SUCCESS) {
|
||||
(void) remoteproc_deinit(rproc);
|
||||
return status;
|
||||
}
|
||||
|
||||
rproc->channel_created = channel_created;
|
||||
rproc->channel_destroyed = channel_destroyed;
|
||||
rproc->default_cb = default_cb;
|
||||
|
||||
*rproc_handle = rproc;
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_deinit
|
||||
*
|
||||
* Uninitializes resources for remoteproc "master" configuration.
|
||||
*
|
||||
* @param rproc - pointer to remote proc instance
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*
|
||||
*/
|
||||
int remoteproc_deinit(struct remote_proc *rproc) {
|
||||
|
||||
if (rproc) {
|
||||
if (rproc->loader) {
|
||||
(void) remoteproc_loader_delete(rproc->loader);
|
||||
rproc->loader = RPROC_NULL;
|
||||
}
|
||||
if (rproc->proc) {
|
||||
hil_delete_proc(rproc->proc);
|
||||
rproc->proc = RPROC_NULL;
|
||||
}
|
||||
env_free_memory(rproc);
|
||||
}
|
||||
|
||||
env_deinit();
|
||||
|
||||
return RPROC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_boot
|
||||
*
|
||||
* This function loads the image on the remote processor and starts
|
||||
* its execution from image load address.
|
||||
*
|
||||
* @param rproc - pointer to remoteproc instance to boot
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*/
|
||||
int remoteproc_boot(struct remote_proc *rproc) {
|
||||
|
||||
void *load_addr;
|
||||
int status;
|
||||
|
||||
if (!rproc) {
|
||||
return RPROC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Stop the remote CPU */
|
||||
hil_shutdown_cpu(rproc->proc);
|
||||
|
||||
/* Load the firmware */
|
||||
status = remoteproc_loader_load_remote_firmware(rproc->loader);
|
||||
if (status == RPROC_SUCCESS) {
|
||||
load_addr = remoteproc_get_load_address(rproc->loader);
|
||||
if (load_addr != RPROC_ERR_PTR) {
|
||||
/* Start the remote cpu */
|
||||
status = hil_boot_cpu(rproc->proc,
|
||||
(unsigned int) load_addr);
|
||||
if (status == RPROC_SUCCESS) {
|
||||
/* Wait for remote side to come up. This delay is arbitrary and may
|
||||
* need adjustment for different configuration of remote systems */
|
||||
env_sleep_msec(RPROC_BOOT_DELAY);
|
||||
|
||||
/* Initialize RPMSG "messaging" component */
|
||||
|
||||
/* It is a work-around to work with remote Linux context.
|
||||
Since the upstream Linux rpmsg implementation always
|
||||
assumes itself to be an rpmsg master, we initialize
|
||||
the remote device as an rpmsg master for remote Linux
|
||||
configuration only. */
|
||||
#if defined (OPENAMP_REMOTE_LINUX_ENABLE)
|
||||
status = rpmsg_init(rproc->proc->cpu_id, &rproc->rdev,
|
||||
rproc->channel_created,
|
||||
rproc->channel_destroyed, rproc->default_cb,
|
||||
RPMSG_MASTER);
|
||||
#else
|
||||
status = rpmsg_init(rproc->proc->cpu_id, &rproc->rdev,
|
||||
rproc->channel_created,
|
||||
rproc->channel_destroyed, rproc->default_cb,
|
||||
RPMSG_REMOTE);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
status = RPROC_ERR_LOADER;
|
||||
}
|
||||
} else {
|
||||
status = RPROC_ERR_LOADER;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_shutdown
|
||||
*
|
||||
* This function shutdowns the remote execution context
|
||||
*
|
||||
* @param rproc - pointer to remote proc instance to shutdown
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*/
|
||||
int remoteproc_shutdown(struct remote_proc *rproc) {
|
||||
|
||||
if (rproc) {
|
||||
if (rproc->rdev) {
|
||||
rpmsg_deinit(rproc->rdev);
|
||||
rproc->rdev = RPROC_NULL;
|
||||
}
|
||||
if (rproc->proc) {
|
||||
hil_shutdown_cpu(rproc->proc);
|
||||
}
|
||||
}
|
||||
|
||||
return RPROC_SUCCESS;
|
||||
}
|
466
ThirdParty/sw_services/xilopenamp/src/remoteproc.h
vendored
Normal file
466
ThirdParty/sw_services/xilopenamp/src/remoteproc.h
vendored
Normal file
|
@ -0,0 +1,466 @@
|
|||
/*
|
||||
* Remote remote_proc Framework
|
||||
*
|
||||
* Copyright(c) 2011 Texas Instruments, Inc.
|
||||
* Copyright(c) 2011 Google, Inc.
|
||||
* 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 Texas Instruments 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
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef REMOTEPROC_H
|
||||
#define REMOTEPROC_H
|
||||
|
||||
#include "rpmsg.h"
|
||||
#include "config.h"
|
||||
/**
|
||||
* struct resource_table - firmware resource table header
|
||||
* @ver: version number
|
||||
* @num: number of resource entries
|
||||
* @reserved: reserved (must be zero)
|
||||
* @offset: array of offsets pointing at the various resource entries
|
||||
*
|
||||
* A resource table is essentially a list of system resources required
|
||||
* by the remote remote_proc. It may also include configuration entries.
|
||||
* If needed, the remote remote_proc firmware should contain this table
|
||||
* as a dedicated ".resource_table" ELF section.
|
||||
*
|
||||
* Some resources entries are mere announcements, where the host is informed
|
||||
* of specific remoteproc configuration. Other entries require the host to
|
||||
* do something (e.g. allocate a system resource). Sometimes a negotiation
|
||||
* is expected, where the firmware requests a resource, and once allocated,
|
||||
* the host should provide back its details (e.g. address of an allocated
|
||||
* memory region).
|
||||
*
|
||||
* The header of the resource table, as expressed by this structure,
|
||||
* contains a version number (should we need to change this format in the
|
||||
* future), the number of available resource entries, and their offsets
|
||||
* in the table.
|
||||
*
|
||||
* Immediately following this header are the resource entries themselves,
|
||||
* each of which begins with a resource entry header (as described below).
|
||||
*/
|
||||
struct resource_table {
|
||||
unsigned int ver;
|
||||
unsigned int num;
|
||||
unsigned int reserved[2];
|
||||
unsigned int offset[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/**
|
||||
* struct fw_rsc_hdr - firmware resource entry header
|
||||
* @type: resource type
|
||||
* @data: resource data
|
||||
*
|
||||
* Every resource entry begins with a 'struct fw_rsc_hdr' header providing
|
||||
* its @type. The content of the entry itself will immediately follow
|
||||
* this header, and it should be parsed according to the resource type.
|
||||
*/
|
||||
struct fw_rsc_hdr {
|
||||
unsigned int type;
|
||||
unsigned char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/**
|
||||
* enum fw_resource_type - types of resource entries
|
||||
*
|
||||
* @RSC_CARVEOUT: request for allocation of a physically contiguous
|
||||
* memory region.
|
||||
* @RSC_DEVMEM: request to iommu_map a memory-based peripheral.
|
||||
* @RSC_TRACE: announces the availability of a trace buffer into which
|
||||
* the remote remote_proc will be writing logs.
|
||||
* @RSC_VDEV: declare support for a virtio device, and serve as its
|
||||
* virtio header.
|
||||
* @RSC_LAST: just keep this one at the end
|
||||
*
|
||||
* For more details regarding a specific resource type, please see its
|
||||
* dedicated structure below.
|
||||
*
|
||||
* Please note that these values are used as indices to the rproc_handle_rsc
|
||||
* lookup table, so please keep them sane. Moreover, @RSC_LAST is used to
|
||||
* check the validity of an index before the lookup table is accessed, so
|
||||
* please update it as needed.
|
||||
*/
|
||||
enum fw_resource_type {
|
||||
RSC_CARVEOUT = 0,
|
||||
RSC_DEVMEM = 1,
|
||||
RSC_TRACE = 2,
|
||||
RSC_VDEV = 3,
|
||||
RSC_LAST = 4,
|
||||
};
|
||||
|
||||
#define FW_RSC_ADDR_ANY (0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
/**
|
||||
* struct fw_rsc_carveout - physically contiguous memory request
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @flags: iommu protection flags
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the requested memory region
|
||||
*
|
||||
* This resource entry requests the host to allocate a physically contiguous
|
||||
* memory region.
|
||||
*
|
||||
* These request entries should precede other firmware resource entries,
|
||||
* as other entries might request placing other data objects inside
|
||||
* these memory regions (e.g. data/code segments, trace resource entries, ...).
|
||||
*
|
||||
* Allocating memory this way helps utilizing the reserved physical memory
|
||||
* (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
|
||||
* needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
|
||||
* pressure is important; it may have a substantial impact on performance.
|
||||
*
|
||||
* If the firmware is compiled with static addresses, then @da should specify
|
||||
* the expected device address of this memory region. If @da is set to
|
||||
* FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then
|
||||
* overwrite @da with the dynamically allocated address.
|
||||
*
|
||||
* We will always use @da to negotiate the device addresses, even if it
|
||||
* isn't using an iommu. In that case, though, it will obviously contain
|
||||
* physical addresses.
|
||||
*
|
||||
* Some remote remote_procs needs to know the allocated physical address
|
||||
* even if they do use an iommu. This is needed, e.g., if they control
|
||||
* hardware accelerators which access the physical memory directly (this
|
||||
* is the case with OMAP4 for instance). In that case, the host will
|
||||
* overwrite @pa with the dynamically allocated physical address.
|
||||
* Generally we don't want to expose physical addresses if we don't have to
|
||||
* (remote remote_procs are generally _not_ trusted), so we might want to
|
||||
* change this to happen _only_ when explicitly required by the hardware.
|
||||
*
|
||||
* @flags is used to provide IOMMU protection flags, and @name should
|
||||
* (optionally) contain a human readable name of this carveout region
|
||||
* (mainly for debugging purposes).
|
||||
*/
|
||||
struct fw_rsc_carveout {
|
||||
unsigned int type;
|
||||
unsigned int da;
|
||||
unsigned int pa;
|
||||
unsigned int len;
|
||||
unsigned int flags;
|
||||
unsigned int reserved;
|
||||
unsigned char name[32];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/**
|
||||
* struct fw_rsc_devmem - iommu mapping request
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @flags: iommu protection flags
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the requested region to be mapped
|
||||
*
|
||||
* This resource entry requests the host to iommu map a physically contiguous
|
||||
* memory region. This is needed in case the remote remote_proc requires
|
||||
* access to certain memory-based peripherals; _never_ use it to access
|
||||
* regular memory.
|
||||
*
|
||||
* This is obviously only needed if the remote remote_proc is accessing memory
|
||||
* via an iommu.
|
||||
*
|
||||
* @da should specify the required device address, @pa should specify
|
||||
* the physical address we want to map, @len should specify the size of
|
||||
* the mapping and @flags is the IOMMU protection flags. As always, @name may
|
||||
* (optionally) contain a human readable name of this mapping (mainly for
|
||||
* debugging purposes).
|
||||
*
|
||||
* Note: at this point we just "trust" those devmem entries to contain valid
|
||||
* physical addresses, but this isn't safe and will be changed: eventually we
|
||||
* want remoteproc implementations to provide us ranges of physical addresses
|
||||
* the firmware is allowed to request, and not allow firmwares to request
|
||||
* access to physical addresses that are outside those ranges.
|
||||
*/
|
||||
struct fw_rsc_devmem {
|
||||
unsigned int type;
|
||||
unsigned int da;
|
||||
unsigned int pa;
|
||||
unsigned int len;
|
||||
unsigned int flags;
|
||||
unsigned int reserved;
|
||||
unsigned char name[32];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/**
|
||||
* struct fw_rsc_trace - trace buffer declaration
|
||||
* @da: device address
|
||||
* @len: length (in bytes)
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the trace buffer
|
||||
*
|
||||
* This resource entry provides the host information about a trace buffer
|
||||
* into which the remote remote_proc will write log messages.
|
||||
*
|
||||
* @da specifies the device address of the buffer, @len specifies
|
||||
* its size, and @name may contain a human readable name of the trace buffer.
|
||||
*
|
||||
* After booting the remote remote_proc, the trace buffers are exposed to the
|
||||
* user via debugfs entries (called trace0, trace1, etc..).
|
||||
*/
|
||||
struct fw_rsc_trace {
|
||||
unsigned int type;
|
||||
unsigned int da;
|
||||
unsigned int len;
|
||||
unsigned int reserved;
|
||||
unsigned char name[32];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vdev_vring - vring descriptor entry
|
||||
* @da: device address
|
||||
* @align: the alignment between the consumer and producer parts of the vring
|
||||
* @num: num of buffers supported by this vring (must be power of two)
|
||||
* @notifyid is a unique rproc-wide notify index for this vring. This notify
|
||||
* index is used when kicking a remote remote_proc, to let it know that this
|
||||
* vring is triggered.
|
||||
* @reserved: reserved (must be zero)
|
||||
*
|
||||
* This descriptor is not a resource entry by itself; it is part of the
|
||||
* vdev resource type (see below).
|
||||
*
|
||||
* Note that @da should either contain the device address where
|
||||
* the remote remote_proc is expecting the vring, or indicate that
|
||||
* dynamically allocation of the vring's device address is supported.
|
||||
*/
|
||||
struct fw_rsc_vdev_vring {
|
||||
unsigned int da;
|
||||
unsigned int align;
|
||||
unsigned int num;
|
||||
unsigned int notifyid;
|
||||
unsigned int reserved;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vdev - virtio device header
|
||||
* @id: virtio device id (as in virtio_ids.h)
|
||||
* @notifyid is a unique rproc-wide notify index for this vdev. This notify
|
||||
* index is used when kicking a remote remote_proc, to let it know that the
|
||||
* status/features of this vdev have changes.
|
||||
* @dfeatures specifies the virtio device features supported by the firmware
|
||||
* @gfeatures is a place holder used by the host to write back the
|
||||
* negotiated features that are supported by both sides.
|
||||
* @config_len is the size of the virtio config space of this vdev. The config
|
||||
* space lies in the resource table immediate after this vdev header.
|
||||
* @status is a place holder where the host will indicate its virtio progress.
|
||||
* @num_of_vrings indicates how many vrings are described in this vdev header
|
||||
* @reserved: reserved (must be zero)
|
||||
* @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'.
|
||||
*
|
||||
* This resource is a virtio device header: it provides information about
|
||||
* the vdev, and is then used by the host and its peer remote remote_procs
|
||||
* to negotiate and share certain virtio properties.
|
||||
*
|
||||
* By providing this resource entry, the firmware essentially asks remoteproc
|
||||
* to statically allocate a vdev upon registration of the rproc (dynamic vdev
|
||||
* allocation is not yet supported).
|
||||
*
|
||||
* Note: unlike virtualization systems, the term 'host' here means
|
||||
* the Linux side which is running remoteproc to control the remote
|
||||
* remote_procs. We use the name 'gfeatures' to comply with virtio's terms,
|
||||
* though there isn't really any virtualized guest OS here: it's the host
|
||||
* which is responsible for negotiating the final features.
|
||||
* Yeah, it's a bit confusing.
|
||||
*
|
||||
* Note: immediately following this structure is the virtio config space for
|
||||
* this vdev (which is specific to the vdev; for more info, read the virtio
|
||||
* spec). the size of the config space is specified by @config_len.
|
||||
*/
|
||||
struct fw_rsc_vdev {
|
||||
unsigned int type;
|
||||
unsigned int id;
|
||||
unsigned int notifyid;
|
||||
unsigned int dfeatures;
|
||||
unsigned int gfeatures;
|
||||
unsigned int config_len;
|
||||
unsigned char status;
|
||||
unsigned char num_of_vrings;
|
||||
unsigned char reserved[2];
|
||||
struct fw_rsc_vdev_vring vring[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/**
|
||||
* struct remote_proc
|
||||
*
|
||||
* This structure is maintained by the remoteproc to represent the remote
|
||||
* processor instance. This structure acts as a prime parameter to use
|
||||
* the remoteproc APIs.
|
||||
*
|
||||
* @proc : hardware interface layer processor control
|
||||
* @rdev : remote device , used by RPMSG "messaging" framework.
|
||||
* @loader : pointer remoteproc loader
|
||||
* @channel_created : create channel callback
|
||||
* @channel_destroyed : delete channel callback
|
||||
* @default_cb : default callback for channel
|
||||
* @role : remote proc role , RPROC_MASTER/RPROC_REMOTE
|
||||
*
|
||||
*/
|
||||
struct remote_proc {
|
||||
struct hil_proc *proc;
|
||||
struct remote_device *rdev;
|
||||
struct remoteproc_loader *loader;
|
||||
rpmsg_chnl_cb_t channel_created;
|
||||
rpmsg_chnl_cb_t channel_destroyed;
|
||||
rpmsg_rx_cb_t default_cb;
|
||||
int role;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct resc_table_info
|
||||
*
|
||||
* This structure is maintained by the remoteproc to allow applications
|
||||
* to pass resource table info during remote initialization.
|
||||
*
|
||||
* @rsc_tab : pointer to resource table control block
|
||||
* @size : size of resource table.
|
||||
*
|
||||
*/
|
||||
struct rsc_table_info {
|
||||
struct resource_table *rsc_tab;
|
||||
int size;
|
||||
};
|
||||
|
||||
/* Definitions for device types , null pointer, etc.*/
|
||||
#define RPROC_SUCCESS 0
|
||||
#define RPROC_NULL (void *)0
|
||||
#define RPROC_TRUE 1
|
||||
#define RPROC_FALSE 0
|
||||
#define RPROC_MASTER 1
|
||||
#define RPROC_REMOTE 0
|
||||
/* Number of msecs to wait for remote context to come up */
|
||||
#define RPROC_BOOT_DELAY 500
|
||||
|
||||
/* Remoteproc error codes */
|
||||
#define RPROC_ERR_BASE -4000
|
||||
#define RPROC_ERR_CPU_ID (RPROC_ERR_BASE -1)
|
||||
#define RPROC_ERR_NO_RSC_TABLE (RPROC_ERR_BASE -2)
|
||||
#define RPROC_ERR_NO_MEM (RPROC_ERR_BASE -3)
|
||||
#define RPROC_ERR_RSC_TAB_TRUNC (RPROC_ERR_BASE -4)
|
||||
#define RPROC_ERR_RSC_TAB_VER (RPROC_ERR_BASE -5)
|
||||
#define RPROC_ERR_RSC_TAB_RSVD (RPROC_ERR_BASE -6)
|
||||
#define RPROC_ERR_RSC_TAB_VDEV_NRINGS (RPROC_ERR_BASE -7)
|
||||
#define RPROC_ERR_RSC_TAB_NP (RPROC_ERR_BASE -8)
|
||||
#define RPROC_ERR_RSC_TAB_NS (RPROC_ERR_BASE -9)
|
||||
#define RPROC_ERR_INVLD_FW (RPROC_ERR_BASE -10)
|
||||
#define RPROC_ERR_LOADER (RPROC_ERR_BASE -11)
|
||||
#define RPROC_ERR_PARAM (RPROC_ERR_BASE -12)
|
||||
#define RPROC_ERR_PTR (void*)0xDEADBEAF
|
||||
|
||||
/**
|
||||
* remoteproc_resource_init
|
||||
*
|
||||
* Initializes resources for remoteproc remote configuration.Only
|
||||
* remoteproc remote applications are allowed to call this function.
|
||||
*
|
||||
* @param rsc_info - pointer to resource table info control
|
||||
* block
|
||||
* @param channel_created - callback function for channel creation
|
||||
* @param channel_destroyed - callback function for channel deletion
|
||||
* @param default_cb - default callback for channel I/O
|
||||
* @param rproc_handle - pointer to new remoteproc instance
|
||||
*
|
||||
* @param returns - status of execution
|
||||
*
|
||||
*/
|
||||
int remoteproc_resource_init(
|
||||
struct rsc_table_info *rsc_info,
|
||||
rpmsg_chnl_cb_t channel_created,
|
||||
rpmsg_chnl_cb_t channel_destroyed,
|
||||
rpmsg_rx_cb_t default_cb,
|
||||
struct remote_proc** rproc_handle);
|
||||
|
||||
|
||||
/**
|
||||
* remoteproc_resource_deinit
|
||||
*
|
||||
* Uninitializes resources for remoteproc remote configuration.
|
||||
*
|
||||
* @param rproc - pointer to remoteproc instance
|
||||
*
|
||||
* @param returns - status of execution
|
||||
*
|
||||
*/
|
||||
|
||||
int remoteproc_resource_deinit(struct remote_proc *rproc);
|
||||
|
||||
/**
|
||||
* remoteproc_init
|
||||
*
|
||||
* Initializes resources for remoteproc master configuration. Only
|
||||
* remoteproc master applications are allowed to call this function.
|
||||
*
|
||||
* @param fw_name - name of firmware
|
||||
* @param channel_created - callback function for channel creation
|
||||
* @param channel_destroyed - callback function for channel deletion
|
||||
* @param default_cb - default callback for channel I/O
|
||||
* @param rproc_handle - pointer to new remoteproc instance
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*
|
||||
*/
|
||||
int remoteproc_init(char *fw_name,
|
||||
rpmsg_chnl_cb_t channel_created,
|
||||
rpmsg_chnl_cb_t channel_destroyed,
|
||||
rpmsg_rx_cb_t default_cb, struct remote_proc** rproc_handle);
|
||||
|
||||
/**
|
||||
* remoteproc_deinit
|
||||
*
|
||||
* Uninitializes resources for remoteproc "master" configuration.
|
||||
*
|
||||
* @param rproc - pointer to remoteproc instance
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*
|
||||
*/
|
||||
int remoteproc_deinit(struct remote_proc *rproc);
|
||||
|
||||
/**
|
||||
* remoteproc_boot
|
||||
*
|
||||
* This function loads the image on the remote processor and starts
|
||||
* its execution from image load address.
|
||||
*
|
||||
* @param rproc - pointer to remoteproc instance to boot
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*/
|
||||
int remoteproc_boot(struct remote_proc *rproc);
|
||||
|
||||
/**
|
||||
* remoteproc_shutdown
|
||||
*
|
||||
* This function shutdowns the remote execution context.
|
||||
*
|
||||
* @param rproc - pointer to remoteproc instance to shutdown
|
||||
*
|
||||
* @param returns - status of function execution
|
||||
*/
|
||||
int remoteproc_shutdown(struct remote_proc *rproc);
|
||||
|
||||
#endif /* REMOTEPROC_H_ */
|
241
ThirdParty/sw_services/xilopenamp/src/remoteproc_loader.c
vendored
Normal file
241
ThirdParty/sw_services/xilopenamp/src/remoteproc_loader.c
vendored
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
#include "remoteproc_loader.h"
|
||||
|
||||
/**
|
||||
* remoteproc_loader_init
|
||||
*
|
||||
* Initializes the remoteproc loader.
|
||||
*
|
||||
* @param type - loader type
|
||||
*
|
||||
* @return - remoteproc_loader
|
||||
*/
|
||||
struct remoteproc_loader * remoteproc_loader_init(enum loader_type type) {
|
||||
|
||||
struct remoteproc_loader *loader;
|
||||
|
||||
/* Check for valid loader type. */
|
||||
if (type >= LAST_LOADER) {
|
||||
return RPROC_NULL ;
|
||||
}
|
||||
|
||||
/* Allocate a loader handle. */
|
||||
loader = env_allocate_memory(sizeof(struct remoteproc_loader));
|
||||
|
||||
if (!loader) {
|
||||
return RPROC_NULL ;
|
||||
}
|
||||
|
||||
/* Clear loader handle. */
|
||||
env_memset(loader, 0, sizeof(struct remoteproc_loader));
|
||||
|
||||
/* Save loader type. */
|
||||
loader->type = type;
|
||||
|
||||
switch (type) {
|
||||
|
||||
case ELF_LOADER:
|
||||
elf_loader_init(loader);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Loader not supported. */
|
||||
env_free_memory(loader);
|
||||
loader = RPROC_NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_loader_delete
|
||||
*
|
||||
* Deletes the remoteproc loader.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
int remoteproc_loader_delete(struct remoteproc_loader *loader) {
|
||||
|
||||
int status = 0;
|
||||
|
||||
if (!loader) {
|
||||
return RPROC_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Check if a firmware is attached. */
|
||||
if (loader->remote_firmware) {
|
||||
|
||||
/* Detach firmware first. */
|
||||
status = loader->detach_firmware(loader);
|
||||
}
|
||||
|
||||
/* Recover the allocated memory. */
|
||||
env_free_memory(loader);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_loader_attach_firmware
|
||||
*
|
||||
* Attaches an ELF firmware to the loader
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
* @param firmware - pointer to the firmware start location
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
int remoteproc_loader_attach_firmware(struct remoteproc_loader *loader,
|
||||
void *firmware_image) {
|
||||
|
||||
int status = RPROC_SUCCESS;
|
||||
|
||||
if (!loader || !firmware_image) {
|
||||
return RPROC_ERR_PARAM;
|
||||
}
|
||||
|
||||
if (loader->attach_firmware) {
|
||||
|
||||
/* Check if a firmware is already attached. */
|
||||
if (loader->remote_firmware) {
|
||||
|
||||
/* Detach firmware first. */
|
||||
status = loader->detach_firmware(loader);
|
||||
}
|
||||
|
||||
/* Attach firmware. */
|
||||
if (!status) {
|
||||
status = loader->attach_firmware(loader, firmware_image);
|
||||
|
||||
/* Save firmware address. */
|
||||
if (!status) {
|
||||
loader->remote_firmware = firmware_image;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
status = RPROC_ERR_LOADER;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_loader_retrieve_entry_point
|
||||
*
|
||||
* Provides entry point address.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - entrypoint
|
||||
*/
|
||||
void *remoteproc_loader_retrieve_entry_point(struct remoteproc_loader *loader) {
|
||||
|
||||
if (!loader) {
|
||||
return RPROC_NULL ;
|
||||
}
|
||||
|
||||
if (loader->retrieve_entry) {
|
||||
return loader->retrieve_entry(loader);
|
||||
} else {
|
||||
return RPROC_NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_loader_retrieve_resource_section
|
||||
*
|
||||
* Provides resource section address.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
* @param size - pointer to hold size of resource section
|
||||
*
|
||||
* @return - pointer to resource section
|
||||
*/
|
||||
void *remoteproc_loader_retrieve_resource_section(
|
||||
struct remoteproc_loader *loader, unsigned int *size) {
|
||||
|
||||
if (!loader) {
|
||||
return RPROC_NULL ;
|
||||
}
|
||||
|
||||
if (loader->retrieve_rsc) {
|
||||
return loader->retrieve_rsc(loader, size);
|
||||
} else {
|
||||
return RPROC_NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_loader_load_remote_firmware
|
||||
*
|
||||
* Loads the firmware in memory
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - 0 if success, error otherwise
|
||||
*/
|
||||
int remoteproc_loader_load_remote_firmware(struct remoteproc_loader *loader) {
|
||||
|
||||
if (!loader) {
|
||||
return RPROC_ERR_PARAM;
|
||||
}
|
||||
|
||||
if (loader->load_firmware) {
|
||||
return loader->load_firmware(loader);
|
||||
} else {
|
||||
return RPROC_ERR_LOADER;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_get_load_address
|
||||
*
|
||||
* Provides firmware load address.
|
||||
*
|
||||
* @param loader - pointer to remoteproc loader
|
||||
*
|
||||
* @return - load address pointer
|
||||
*/
|
||||
void *remoteproc_get_load_address(struct remoteproc_loader *loader){
|
||||
|
||||
if (!loader) {
|
||||
return RPROC_ERR_PTR;
|
||||
}
|
||||
|
||||
if (loader->retrieve_load_addr) {
|
||||
return loader->retrieve_load_addr(loader);
|
||||
} else {
|
||||
return RPROC_ERR_PTR;
|
||||
}
|
||||
}
|
92
ThirdParty/sw_services/xilopenamp/src/remoteproc_loader.h
vendored
Normal file
92
ThirdParty/sw_services/xilopenamp/src/remoteproc_loader.h
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* remoteproc_loader.h
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP stack.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file provides definitions for remoteproc loader
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
#ifndef REMOTEPROC_LOADER_H_
|
||||
#define REMOTEPROC_LOADER_H_
|
||||
|
||||
#include "remoteproc.h"
|
||||
|
||||
/**
|
||||
* enum loader_type - dynamic name service announcement flags
|
||||
*
|
||||
* @ELF_LOADER: an ELF loader
|
||||
* @FIT_LOADER: a loader for Flattened Image Trees
|
||||
*/
|
||||
enum loader_type {
|
||||
ELF_LOADER = 0, FIT_LOADER = 1, LAST_LOADER = 2,
|
||||
};
|
||||
|
||||
/* Loader structure definition. */
|
||||
|
||||
struct remoteproc_loader {
|
||||
enum loader_type type;
|
||||
void *remote_firmware;
|
||||
/* Pointer to firmware decoded info control block */
|
||||
void *fw_decode_info;
|
||||
|
||||
/* Loader callbacks. */
|
||||
void *(*retrieve_entry)(struct remoteproc_loader *loader);
|
||||
void *(*retrieve_rsc)(struct remoteproc_loader *loader, unsigned int *size);
|
||||
int (*load_firmware)(struct remoteproc_loader *loader);
|
||||
int (*attach_firmware)(struct remoteproc_loader *loader, void *firmware);
|
||||
int (*detach_firmware)(struct remoteproc_loader *loader);
|
||||
void *(*retrieve_load_addr)(struct remoteproc_loader *loader);
|
||||
|
||||
};
|
||||
|
||||
/* RemoteProc Loader functions. */
|
||||
struct remoteproc_loader * remoteproc_loader_init(enum loader_type type);
|
||||
int remoteproc_loader_delete(struct remoteproc_loader *loader);
|
||||
int remoteproc_loader_attach_firmware(struct remoteproc_loader *loader,
|
||||
void *firmware_image);
|
||||
void *remoteproc_loader_retrieve_entry_point(struct remoteproc_loader *loader);
|
||||
void *remoteproc_loader_retrieve_resource_section(
|
||||
struct remoteproc_loader *loader, unsigned int* size);
|
||||
int remoteproc_loader_load_remote_firmware(struct remoteproc_loader *loader);
|
||||
void *remoteproc_get_load_address(struct remoteproc_loader *loader);
|
||||
|
||||
/* Supported loaders */
|
||||
extern int elf_loader_init(struct remoteproc_loader *loader);
|
||||
|
||||
#endif /* REMOTEPROC_LOADER_H_ */
|
414
ThirdParty/sw_services/xilopenamp/src/rpmsg.c
vendored
Normal file
414
ThirdParty/sw_services/xilopenamp/src/rpmsg.c
vendored
Normal file
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* rpmsg.c
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP stack.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Main file for the RPMSG driver. This file implements APIs as defined by
|
||||
* RPMSG documentation(Linux docs) and also provides some utility functions.
|
||||
*
|
||||
* RPMSG driver represents each processor/core to which it communicates with
|
||||
* remote_device control block.
|
||||
* Each remote device(processor) defines its role in the communication i.e
|
||||
* whether it is RPMSG Master or Remote. If the device(processor) to which
|
||||
* driver is talking is RPMSG master then RPMSG driver implicitly behaves as
|
||||
* Remote and vice versa.
|
||||
* RPMSG Master is responsible for initiating communications with the Remote
|
||||
* and shared buffers management. Terms remote device/core/proc are used
|
||||
* interchangeably for the processor to which RPMSG driver is communicating
|
||||
* irrespective of the fact whether it is RPMSG Remote or Master.
|
||||
*
|
||||
**************************************************************************/
|
||||
#include "rpmsg.h"
|
||||
|
||||
/**
|
||||
* rpmsg_init
|
||||
*
|
||||
* Thus function allocates and initializes the rpmsg driver resources for
|
||||
* given device ID(cpu id). The successful return from this function leaves
|
||||
* fully enabled IPC link.
|
||||
*
|
||||
* @param dev_id - remote device for which driver is to
|
||||
* be initialized
|
||||
* @param rdev - pointer to newly created remote device
|
||||
* @param channel_created - callback function for channel creation
|
||||
* @param channel_destroyed - callback function for channel deletion
|
||||
* @param default_cb - default callback for channel I/O
|
||||
* @param role - role of the other device, Master or Remote
|
||||
*
|
||||
* @return - status of function execution
|
||||
*
|
||||
*/
|
||||
|
||||
int rpmsg_init(int dev_id, struct remote_device **rdev,
|
||||
rpmsg_chnl_cb_t channel_created,
|
||||
rpmsg_chnl_cb_t channel_destroyed,
|
||||
rpmsg_rx_cb_t default_cb, int role) {
|
||||
int status;
|
||||
|
||||
/* Initialize IPC environment */
|
||||
status = env_init();
|
||||
if (status == RPMSG_SUCCESS) {
|
||||
/* Initialize the remote device for given cpu id */
|
||||
status = rpmsg_rdev_init(rdev, dev_id, role, channel_created,
|
||||
channel_destroyed, default_cb);
|
||||
if (status == RPMSG_SUCCESS) {
|
||||
/* Kick off IPC with the remote device */
|
||||
status = rpmsg_start_ipc(*rdev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Deinit system in case of error */
|
||||
if (status != RPMSG_SUCCESS) {
|
||||
rpmsg_deinit(*rdev);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_deinit
|
||||
*
|
||||
* Thus function frees rpmsg driver resources for given remote device.
|
||||
*
|
||||
* @param rdev - pointer to device to de-init
|
||||
*
|
||||
*/
|
||||
|
||||
void rpmsg_deinit(struct remote_device *rdev) {
|
||||
if (rdev) {
|
||||
rpmsg_rdev_deinit(rdev);
|
||||
env_deinit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function sends rpmsg "message" to remote device.
|
||||
*
|
||||
* @param rp_chnl - pointer to rpmsg channel
|
||||
* @param src - source address of channel
|
||||
* @param dst - destination address of channel
|
||||
* @param data - data to transmit
|
||||
* @param size - size of data
|
||||
* @param wait - boolean, wait or not for buffer to become
|
||||
* available
|
||||
*
|
||||
* @return - status of function execution
|
||||
*
|
||||
*/
|
||||
|
||||
int rpmsg_send_offchannel_raw(struct rpmsg_channel *rp_chnl, unsigned long src,
|
||||
unsigned long dst, char *data, int size, int wait) {
|
||||
struct remote_device *rdev;
|
||||
struct rpmsg_hdr *rp_hdr;
|
||||
void *buffer;
|
||||
int status = RPMSG_SUCCESS;
|
||||
unsigned short idx;
|
||||
int tick_count = 0;
|
||||
int buff_len;
|
||||
|
||||
if (!rp_chnl) {
|
||||
return RPMSG_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Get the associated remote device for channel. */
|
||||
rdev = rp_chnl->rdev;
|
||||
|
||||
/* Validate device state */
|
||||
if (rp_chnl->state != RPMSG_CHNL_STATE_ACTIVE
|
||||
|| rdev->state != RPMSG_DEV_STATE_ACTIVE) {
|
||||
return RPMSG_ERR_DEV_STATE;
|
||||
}
|
||||
|
||||
/* Lock the device to enable exclusive access to virtqueues */
|
||||
env_lock_mutex(rdev->lock);
|
||||
/* Get rpmsg buffer for sending message. */
|
||||
buffer = rpmsg_get_tx_buffer(rdev, &buff_len, &idx);
|
||||
if (!buffer && !wait) {
|
||||
status = RPMSG_ERR_NO_MEM;
|
||||
}
|
||||
env_unlock_mutex(rdev->lock);
|
||||
|
||||
if (status == RPMSG_SUCCESS) {
|
||||
|
||||
while (!buffer) {
|
||||
/*
|
||||
* Wait parameter is true - pool the buffer for
|
||||
* 15 secs as defined by the APIs.
|
||||
*/
|
||||
env_sleep_msec(RPMSG_TICKS_PER_INTERVAL);
|
||||
env_lock_mutex(rdev->lock);
|
||||
buffer = rpmsg_get_tx_buffer(rdev, &buff_len, &idx);
|
||||
env_unlock_mutex(rdev->lock);
|
||||
tick_count += RPMSG_TICKS_PER_INTERVAL;
|
||||
if (tick_count >= (RPMSG_TICK_COUNT / RPMSG_TICKS_PER_INTERVAL)) {
|
||||
status = RPMSG_ERR_NO_BUFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == RPMSG_SUCCESS) {
|
||||
//FIXME : may be just copy the data size equal to buffer length and Tx it.
|
||||
if (size > (buff_len - sizeof(struct rpmsg_hdr)))
|
||||
status = RPMSG_ERR_BUFF_SIZE;
|
||||
|
||||
if (status == RPMSG_SUCCESS) {
|
||||
rp_hdr = (struct rpmsg_hdr *) buffer;
|
||||
|
||||
/* Initialize RPMSG header. */
|
||||
rp_hdr->dst = dst;
|
||||
rp_hdr->src = src;
|
||||
rp_hdr->len = size;
|
||||
|
||||
/* Copy data to rpmsg buffer. */
|
||||
env_memcpy(rp_hdr->data, data, size);
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
/* Enqueue buffer on virtqueue. */
|
||||
status = rpmsg_enqueue_buffer(rdev, buffer, buff_len, idx);
|
||||
if (status == RPMSG_SUCCESS) {
|
||||
/* Let the other side know that there is a job to process. */
|
||||
virtqueue_kick(rdev->tvq);
|
||||
}
|
||||
env_unlock_mutex(rdev->lock);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Do cleanup in case of error.*/
|
||||
if (status != RPMSG_SUCCESS) {
|
||||
rpmsg_free_buffer(rdev, buffer);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_get_buffer_size
|
||||
*
|
||||
* Returns buffer size available for sending messages.
|
||||
*
|
||||
* @param channel - pointer to rpmsg channel
|
||||
*
|
||||
* @return - buffer size
|
||||
*
|
||||
*/
|
||||
int rpmsg_get_buffer_size(struct rpmsg_channel *rp_chnl) {
|
||||
struct remote_device *rdev;
|
||||
int length;
|
||||
|
||||
if (!rp_chnl) {
|
||||
return RPMSG_ERR_PARAM;
|
||||
}
|
||||
|
||||
/* Get associated remote device for channel. */
|
||||
rdev = rp_chnl->rdev;
|
||||
|
||||
/* Validate device state */
|
||||
if (rp_chnl->state != RPMSG_CHNL_STATE_ACTIVE
|
||||
|| rdev->state != RPMSG_DEV_STATE_ACTIVE) {
|
||||
return RPMSG_ERR_DEV_STATE;
|
||||
}
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
/*
|
||||
* If device role is Remote then buffers are provided by us
|
||||
* (RPMSG Master), so just provide the macro.
|
||||
*/
|
||||
length = RPMSG_BUFFER_SIZE - sizeof(struct rpmsg_hdr);
|
||||
} else {
|
||||
/*
|
||||
* If other core is Master then buffers are provided by it,
|
||||
* so get the buffer size from the virtqueue.
|
||||
*/
|
||||
length = (int) virtqueue_get_desc_size(rdev->tvq) - sizeof(struct rpmsg_hdr);
|
||||
}
|
||||
|
||||
env_unlock_mutex(rdev->lock);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_create_ept
|
||||
*
|
||||
* This function creates rpmsg endpoint for the rpmsg channel.
|
||||
*
|
||||
* @param channel - pointer to rpmsg channel
|
||||
* @param cb - Rx completion call back
|
||||
* @param priv - private data
|
||||
* @param addr - endpoint src address
|
||||
*
|
||||
* @return - pointer to endpoint control block
|
||||
*
|
||||
*/
|
||||
struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rp_chnl,
|
||||
rpmsg_rx_cb_t cb, void *priv, unsigned long addr) {
|
||||
|
||||
struct remote_device *rdev = RPMSG_NULL;
|
||||
struct rpmsg_endpoint *rp_ept = RPMSG_NULL;
|
||||
|
||||
if (!rp_chnl || !cb) {
|
||||
return RPMSG_NULL ;
|
||||
}
|
||||
|
||||
rdev = rp_chnl->rdev;
|
||||
|
||||
rp_ept = _create_endpoint(rdev, cb, priv, addr);
|
||||
|
||||
if (rp_ept) {
|
||||
rp_ept->rp_chnl = rp_chnl;
|
||||
}
|
||||
|
||||
return rp_ept;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_destroy_ept
|
||||
*
|
||||
* This function deletes rpmsg endpoint and performs cleanup.
|
||||
*
|
||||
* @param rp_ept - pointer to endpoint to destroy
|
||||
*
|
||||
*/
|
||||
void rpmsg_destroy_ept(struct rpmsg_endpoint *rp_ept) {
|
||||
|
||||
struct remote_device *rdev;
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
|
||||
if (!rp_ept)
|
||||
return;
|
||||
|
||||
rp_chnl = rp_ept->rp_chnl;
|
||||
rdev = rp_chnl->rdev;
|
||||
|
||||
_destroy_endpoint(rdev, rp_ept);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_create_channel
|
||||
*
|
||||
* This function provides facility to create channel dynamically. It sends
|
||||
* Name Service announcement to remote device to let it know about the channel
|
||||
* creation. There must be an active communication among the cores (or atleast
|
||||
* one rpmsg channel must already exist) before using this API to create new
|
||||
* channels.
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
* @param name - channel name
|
||||
*
|
||||
* @return - pointer to new rpmsg channel
|
||||
*
|
||||
*/
|
||||
struct rpmsg_channel *rpmsg_create_channel(struct remote_device *rdev,
|
||||
char *name) {
|
||||
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
struct rpmsg_endpoint *rp_ept;
|
||||
|
||||
if (!rdev || !name) {
|
||||
return RPMSG_NULL ;
|
||||
}
|
||||
|
||||
/* Create channel instance */
|
||||
rp_chnl = _rpmsg_create_channel(rdev, name, RPMSG_NS_EPT_ADDR,
|
||||
RPMSG_NS_EPT_ADDR);
|
||||
if (!rp_chnl) {
|
||||
return RPMSG_NULL ;
|
||||
}
|
||||
|
||||
/* Create default endpoint for the channel */
|
||||
rp_ept = rpmsg_create_ept(rp_chnl , rdev->default_cb, rdev,
|
||||
RPMSG_ADDR_ANY);
|
||||
|
||||
if (!rp_ept) {
|
||||
_rpmsg_delete_channel(rp_chnl);
|
||||
return RPMSG_NULL;
|
||||
}
|
||||
|
||||
rp_chnl->rp_ept = rp_ept;
|
||||
rp_chnl->src = rp_ept->addr;
|
||||
rp_chnl->state = RPMSG_CHNL_STATE_NS;
|
||||
|
||||
/* Notify the application of channel creation event */
|
||||
if (rdev->channel_created) {
|
||||
rdev->channel_created(rp_chnl);
|
||||
}
|
||||
|
||||
/* Send NS announcement to remote processor */
|
||||
rpmsg_send_ns_message(rdev, rp_chnl, RPMSG_NS_CREATE);
|
||||
|
||||
return rp_chnl;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_delete_channel
|
||||
*
|
||||
* Deletes the given RPMSG channel. The channel must first be created with the
|
||||
* rpmsg_create_channel API.
|
||||
*
|
||||
* @param rp_chnl - pointer to rpmsg channel to delete
|
||||
*
|
||||
*/
|
||||
void rpmsg_delete_channel(struct rpmsg_channel *rp_chnl) {
|
||||
|
||||
struct remote_device *rdev;
|
||||
|
||||
if (!rp_chnl) {
|
||||
return;
|
||||
}
|
||||
|
||||
rdev = rp_chnl->rdev;
|
||||
|
||||
if (rp_chnl->state > RPMSG_CHNL_STATE_IDLE) {
|
||||
/* Notify the other processor that channel no longer exists */
|
||||
rpmsg_send_ns_message(rdev, rp_chnl, RPMSG_NS_DESTROY);
|
||||
}
|
||||
|
||||
/* Notify channel deletion to application */
|
||||
if (rdev->channel_destroyed) {
|
||||
rdev->channel_destroyed(rp_chnl);
|
||||
}
|
||||
|
||||
rpmsg_destroy_ept(rp_chnl->rp_ept);
|
||||
_rpmsg_delete_channel(rp_chnl);
|
||||
|
||||
return;
|
||||
}
|
402
ThirdParty/sw_services/xilopenamp/src/rpmsg.h
vendored
Normal file
402
ThirdParty/sw_services/xilopenamp/src/rpmsg.h
vendored
Normal file
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* Remote processor messaging
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments, Inc.
|
||||
* Copyright (C) 2011 Google, Inc.
|
||||
* 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 Texas Instruments 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
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef _RPMSG_H_
|
||||
#define _RPMSG_H_
|
||||
|
||||
#include "rpmsg_core.h"
|
||||
|
||||
/* The feature bitmap for virtio rpmsg */
|
||||
#define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */
|
||||
#define RPMSG_NAME_SIZE 32
|
||||
|
||||
/**
|
||||
* struct rpmsg_hdr - common header for all rpmsg messages
|
||||
* @src: source address
|
||||
* @dst: destination address
|
||||
* @reserved: reserved for future use
|
||||
* @len: length of payload (in bytes)
|
||||
* @flags: message flags
|
||||
* @data: @len bytes of message payload data
|
||||
*
|
||||
* Every message sent(/received) on the rpmsg bus begins with this header.
|
||||
*/
|
||||
struct rpmsg_hdr {
|
||||
unsigned long src;
|
||||
unsigned long dst;
|
||||
unsigned long reserved;
|
||||
unsigned short len;
|
||||
unsigned short flags;
|
||||
unsigned char data[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* struct rpmsg_ns_msg - dynamic name service announcement message
|
||||
* @name: name of remote service that is published
|
||||
* @addr: address of remote service that is published
|
||||
* @flags: indicates whether service is created or destroyed
|
||||
*
|
||||
* This message is sent across to publish a new service, or announce
|
||||
* about its removal. When we receive these messages, an appropriate
|
||||
* rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe()
|
||||
* or ->remove() handler of the appropriate rpmsg driver will be invoked
|
||||
* (if/as-soon-as one is registered).
|
||||
*/
|
||||
struct rpmsg_ns_msg {
|
||||
char name[RPMSG_NAME_SIZE];
|
||||
unsigned long addr;
|
||||
unsigned long flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* enum rpmsg_ns_flags - dynamic name service announcement flags
|
||||
*
|
||||
* @RPMSG_NS_CREATE: a new remote service was just created
|
||||
* @RPMSG_NS_DESTROY: a known remote service was just destroyed
|
||||
*/
|
||||
enum rpmsg_ns_flags {
|
||||
RPMSG_NS_CREATE = 0,
|
||||
RPMSG_NS_DESTROY = 1,
|
||||
};
|
||||
|
||||
#define RPMSG_ADDR_ANY 0xFFFFFFFF
|
||||
|
||||
|
||||
/**
|
||||
* rpmsg_channel - devices that belong to the rpmsg bus are called channels
|
||||
* @name: channel name
|
||||
* @src: local address
|
||||
* @dst: destination address
|
||||
* rdev: rpmsg remote device
|
||||
* @ept: the rpmsg endpoint of this channel
|
||||
* @state: channel state
|
||||
*/
|
||||
struct rpmsg_channel {
|
||||
char name[RPMSG_NAME_SIZE];
|
||||
unsigned long src;
|
||||
unsigned long dst;
|
||||
struct remote_device *rdev;
|
||||
struct rpmsg_endpoint *rp_ept;
|
||||
unsigned int state;
|
||||
};
|
||||
|
||||
/**
|
||||
* channel_info - channel info
|
||||
* @name: channel name
|
||||
* @src: local address
|
||||
* @dst: destination address
|
||||
*/
|
||||
|
||||
struct channel_info {
|
||||
char name[RPMSG_NAME_SIZE];
|
||||
unsigned long src;
|
||||
unsigned long dest;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rpmsg_endpoint - binds a local rpmsg address to its user
|
||||
* @rp_chnl: rpmsg channel device
|
||||
* @cb: rx callback handler
|
||||
* @addr: local rpmsg address
|
||||
* @priv: private data for the driver's use
|
||||
*
|
||||
* In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as
|
||||
* it binds an rpmsg address with an rx callback handler.
|
||||
*
|
||||
* Simple rpmsg drivers shouldn't use this struct directly, because
|
||||
* things just work: every rpmsg driver provides an rx callback upon
|
||||
* registering to the bus, and that callback is then bound to its rpmsg
|
||||
* address when the driver is probed. When relevant inbound messages arrive
|
||||
* (i.e. messages which their dst address equals to the src address of
|
||||
* the rpmsg channel), the driver's handler is invoked to process it.
|
||||
*
|
||||
* More complicated drivers though, that do need to allocate additional rpmsg
|
||||
* addresses, and bind them to different rx callbacks, must explicitly
|
||||
* create additional endpoints by themselves (see rpmsg_create_ept()).
|
||||
*/
|
||||
struct rpmsg_endpoint {
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
rpmsg_rx_cb_t cb;
|
||||
unsigned long addr;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rp_chnl,
|
||||
rpmsg_rx_cb_t cb, void *priv, unsigned long addr);
|
||||
|
||||
void rpmsg_destroy_ept(struct rpmsg_endpoint *rp_ept);
|
||||
|
||||
int
|
||||
rpmsg_send_offchannel_raw(struct rpmsg_channel *, unsigned long, unsigned long, char *, int, int);
|
||||
|
||||
/**
|
||||
* rpmsg_sendto() - send a message across to the remote processor, specify dst
|
||||
* @rpdev: the rpmsg channel
|
||||
* @data: payload of message
|
||||
* @len: length of payload
|
||||
* @dst: destination address
|
||||
*
|
||||
* This function sends @data of length @len to the remote @dst address.
|
||||
* The message will be sent to the remote processor which the @rpdev
|
||||
* channel belongs to, using @rpdev's source address.
|
||||
* In case there are no TX buffers available, the function will block until
|
||||
* one becomes available, or a timeout of 15 seconds elapses. When the latter
|
||||
* happens, -ERESTARTSYS is returned.
|
||||
*
|
||||
* Can only be called from process context (for now).
|
||||
*
|
||||
* Returns 0 on success and an appropriate error value on failure.
|
||||
*/
|
||||
static inline
|
||||
int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, unsigned long dst)
|
||||
{
|
||||
if (!rpdev || !data)
|
||||
return RPMSG_ERR_PARAM;
|
||||
|
||||
return rpmsg_send_offchannel_raw(rpdev, rpdev->src, dst, (char *)data, len, RPMSG_TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_send() - send a message across to the remote processor
|
||||
* @rpdev: the rpmsg channel
|
||||
* @data: payload of message
|
||||
* @len: length of payload
|
||||
*
|
||||
* This function sends @data of length @len on the @rpdev channel.
|
||||
* The message will be sent to the remote processor which the @rpdev
|
||||
* channel belongs to, using @rpdev's source and destination addresses.
|
||||
* In case there are no TX buffers available, the function will block until
|
||||
* one becomes available, or a timeout of 15 seconds elapses. When the latter
|
||||
* happens, -ERESTARTSYS is returned.
|
||||
*
|
||||
* Can only be called from process context (for now).
|
||||
*
|
||||
* Returns 0 on success and an appropriate error value on failure.
|
||||
*/
|
||||
static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len)
|
||||
{
|
||||
if (!rpdev || !data)
|
||||
return RPMSG_ERR_PARAM;
|
||||
|
||||
return rpmsg_send_offchannel_raw(rpdev, rpdev->src, rpdev->dst, (char*)data, len, RPMSG_TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_send_offchannel() - send a message using explicit src/dst addresses
|
||||
* @rpdev: the rpmsg channel
|
||||
* @src: source address
|
||||
* @dst: destination address
|
||||
* @data: payload of message
|
||||
* @len: length of payload
|
||||
*
|
||||
* This function sends @data of length @len to the remote @dst address,
|
||||
* and uses @src as the source address.
|
||||
* The message will be sent to the remote processor which the @rpdev
|
||||
* channel belongs to.
|
||||
* In case there are no TX buffers available, the function will block until
|
||||
* one becomes available, or a timeout of 15 seconds elapses. When the latter
|
||||
* happens, -ERESTARTSYS is returned.
|
||||
*
|
||||
* Can only be called from process context (for now).
|
||||
*
|
||||
* Returns 0 on success and an appropriate error value on failure.
|
||||
*/
|
||||
static inline
|
||||
int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, unsigned long src, unsigned long dst,
|
||||
void *data, int len)
|
||||
{
|
||||
if (!rpdev || !data)
|
||||
return RPMSG_ERR_PARAM;
|
||||
|
||||
return rpmsg_send_offchannel_raw(rpdev, src, dst, (char *)data, len, RPMSG_TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_trysend() - send a message across to the remote processor
|
||||
* @rpdev: the rpmsg channel
|
||||
* @data: payload of message
|
||||
* @len: length of payload
|
||||
*
|
||||
* This function sends @data of length @len on the @rpdev channel.
|
||||
* The message will be sent to the remote processor which the @rpdev
|
||||
* channel belongs to, using @rpdev's source and destination addresses.
|
||||
* In case there are no TX buffers available, the function will immediately
|
||||
* return -ENOMEM without waiting until one becomes available.
|
||||
*
|
||||
* Can only be called from process context (for now).
|
||||
*
|
||||
* Returns 0 on success and an appropriate error value on failure.
|
||||
*/
|
||||
static inline
|
||||
int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
|
||||
{
|
||||
|
||||
if (!rpdev || !data)
|
||||
return RPMSG_ERR_PARAM;
|
||||
|
||||
return rpmsg_send_offchannel_raw(rpdev, rpdev->src, rpdev->dst, (char *)data, len, RPMSG_FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_trysendto() - send a message across to the remote processor, specify dst
|
||||
* @rpdev: the rpmsg channel
|
||||
* @data: payload of message
|
||||
* @len: length of payload
|
||||
* @dst: destination address
|
||||
*
|
||||
* This function sends @data of length @len to the remote @dst address.
|
||||
* The message will be sent to the remote processor which the @rpdev
|
||||
* channel belongs to, using @rpdev's source address.
|
||||
* In case there are no TX buffers available, the function will immediately
|
||||
* return -ENOMEM without waiting until one becomes available.
|
||||
*
|
||||
* Can only be called from process context (for now).
|
||||
*
|
||||
* Returns 0 on success and an appropriate error value on failure.
|
||||
*/
|
||||
static inline
|
||||
int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, unsigned long dst)
|
||||
{
|
||||
unsigned long src;
|
||||
|
||||
if (!rpdev || !data)
|
||||
return RPMSG_ERR_PARAM;
|
||||
|
||||
src = rpdev->src;
|
||||
|
||||
return rpmsg_send_offchannel_raw(rpdev, src, dst, (char *)data, len, RPMSG_FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_trysend_offchannel() - send a message using explicit src/dst addresses
|
||||
* @rpdev: the rpmsg channel
|
||||
* @src: source address
|
||||
* @dst: destination address
|
||||
* @data: payload of message
|
||||
* @len: length of payload
|
||||
*
|
||||
* This function sends @data of length @len to the remote @dst address,
|
||||
* and uses @src as the source address.
|
||||
* The message will be sent to the remote processor which the @rpdev
|
||||
* channel belongs to.
|
||||
* In case there are no TX buffers available, the function will immediately
|
||||
* return -ENOMEM without waiting until one becomes available.
|
||||
*
|
||||
* Can only be called from process context (for now).
|
||||
*
|
||||
* Returns 0 on success and an appropriate error value on failure.
|
||||
*/
|
||||
static inline
|
||||
int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, unsigned long src, unsigned long dst,
|
||||
void *data, int len)
|
||||
{
|
||||
if (!rpdev || !data)
|
||||
return RPMSG_ERR_PARAM;
|
||||
|
||||
return rpmsg_send_offchannel_raw(rpdev, src, dst, (char *)data, len, RPMSG_FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_init
|
||||
*
|
||||
* Thus function allocates and initializes the rpmsg driver resources for given
|
||||
* device id (cpu id).The successful return from this function leaves
|
||||
* fully enabled IPC link.
|
||||
*
|
||||
* @param dev_id - rpmsg remote device for which driver is to
|
||||
* be initialized
|
||||
* @param rdev - pointer to newly created remote device
|
||||
* @param channel_created - callback function for channel creation
|
||||
* @param channel_destroyed - callback function for channel deletion
|
||||
* @default_cb - default callback for channel
|
||||
* @param role - role of the other device, Master or Remote
|
||||
* @return - status of function execution
|
||||
*
|
||||
*/
|
||||
|
||||
int rpmsg_init(int dev_id, struct remote_device **rdev,
|
||||
rpmsg_chnl_cb_t channel_created,
|
||||
rpmsg_chnl_cb_t channel_destroyed,
|
||||
rpmsg_rx_cb_t default_cb, int role);
|
||||
|
||||
/**
|
||||
* rpmsg_deinit
|
||||
*
|
||||
* Thus function releases the rpmsg driver resources for given remote
|
||||
* instance.
|
||||
*
|
||||
* @param rdev - pointer to device de-init
|
||||
*
|
||||
* @return - none
|
||||
*
|
||||
*/
|
||||
void rpmsg_deinit(struct remote_device *rdev);
|
||||
|
||||
/**
|
||||
* rpmsg_get_buffer_size
|
||||
*
|
||||
* Returns buffer size available for sending messages.
|
||||
*
|
||||
* @param channel - pointer to rpmsg channel/device
|
||||
*
|
||||
* @return - buffer size
|
||||
*
|
||||
*/
|
||||
int rpmsg_get_buffer_size(struct rpmsg_channel *rp_chnl);
|
||||
|
||||
/**
|
||||
* rpmsg_create_channel
|
||||
*
|
||||
* Creates RPMSG channel with the given name for remote device.
|
||||
*
|
||||
* @param rdev - pointer to rpmsg remote device
|
||||
* @param name - channel name
|
||||
*
|
||||
* @return - pointer to new rpmsg channel
|
||||
*
|
||||
*/
|
||||
struct rpmsg_channel *rpmsg_create_channel(struct remote_device *rdev, char *name);
|
||||
|
||||
/**
|
||||
* rpmsg_delete_channel
|
||||
*
|
||||
* Deletes the given RPMSG channel. The channel must first be created with the
|
||||
* rpmsg_create_channel API.
|
||||
*
|
||||
* @param rp_chnl - pointer to rpmsg channel to delete
|
||||
*
|
||||
*/
|
||||
void rpmsg_delete_channel(struct rpmsg_channel *rp_chnl);
|
||||
|
||||
#endif /* _RPMSG_H_ */
|
766
ThirdParty/sw_services/xilopenamp/src/rpmsg_core.c
vendored
Normal file
766
ThirdParty/sw_services/xilopenamp/src/rpmsg_core.c
vendored
Normal file
|
@ -0,0 +1,766 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* rpmsg_core.c
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file provides the core functionality of RPMSG messaging part like
|
||||
* message parsing ,Rx/Tx callbacks handling , channel creation/deletion
|
||||
* and address management.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
#include "rpmsg.h"
|
||||
|
||||
/* Internal functions */
|
||||
static void rpmsg_rx_callback(struct virtqueue *vq);
|
||||
static void rpmsg_tx_callback(struct virtqueue *vq);
|
||||
|
||||
/**
|
||||
* rpmsg_start_ipc
|
||||
*
|
||||
* This function creates communication links(virtqueues) for remote device
|
||||
* and notifies it to start IPC.
|
||||
*
|
||||
* @param rdev - remote device handle
|
||||
*
|
||||
* @return - status of function execution
|
||||
*
|
||||
*/
|
||||
int rpmsg_start_ipc(struct remote_device *rdev) {
|
||||
struct virtio_device *virt_dev;
|
||||
struct rpmsg_endpoint *ns_ept;
|
||||
void (*callback[2])(struct virtqueue *vq);
|
||||
const char *vq_names[2];
|
||||
unsigned long dev_features;
|
||||
int status;
|
||||
struct virtqueue *vqs[2];
|
||||
int i;
|
||||
|
||||
virt_dev = &rdev->virt_dev;
|
||||
|
||||
/* Initialize names and callbacks based on the device role */
|
||||
if (rdev->role == RPMSG_MASTER) {
|
||||
vq_names[0] = "tx_vq";
|
||||
vq_names[1] = "rx_vq";
|
||||
callback[0] = rpmsg_tx_callback;
|
||||
callback[1] = rpmsg_rx_callback;
|
||||
} else {
|
||||
vq_names[0] = "rx_vq";
|
||||
vq_names[1] = "tx_vq";
|
||||
callback[0] = rpmsg_rx_callback;
|
||||
callback[1] = rpmsg_tx_callback;
|
||||
}
|
||||
|
||||
/* Create virtqueues for remote device */
|
||||
status = virt_dev->func->create_virtqueues(virt_dev, 0,
|
||||
RPMSG_MAX_VQ_PER_RDEV, vq_names, callback, RPMSG_NULL);
|
||||
if (status != RPMSG_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
dev_features = virt_dev->func->get_features(virt_dev);
|
||||
|
||||
/*
|
||||
* Create name service announcement endpoint if device supports name
|
||||
* service announcement feature.
|
||||
*/
|
||||
if ((dev_features & (1 << VIRTIO_RPMSG_F_NS))) {
|
||||
rdev->support_ns = RPMSG_TRUE;
|
||||
ns_ept = _create_endpoint(rdev, rpmsg_ns_callback, rdev,
|
||||
RPMSG_NS_EPT_ADDR);
|
||||
if (!ns_ept) {
|
||||
return RPMSG_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize notifications for vring. */
|
||||
if (rdev->role == RPMSG_MASTER) {
|
||||
vqs[0] = rdev->tvq;
|
||||
vqs[1] = rdev->rvq;
|
||||
} else {
|
||||
vqs[0] = rdev->rvq;
|
||||
vqs[1] = rdev->tvq;
|
||||
}
|
||||
for(i = 0; i <= 1; i++) {
|
||||
status = hil_enable_vring_notifications(i, vqs[i]);
|
||||
if (status != RPMSG_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
status = rpmsg_rdev_notify(rdev);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* _rpmsg_create_channel
|
||||
*
|
||||
* Creates new rpmsg channel with the given parameters.
|
||||
*
|
||||
* @param rdev - pointer to remote device which contains the channel
|
||||
* @param name - name of the device
|
||||
* @param src - source address for the rpmsg channel
|
||||
* @param dst - destination address for the rpmsg channel
|
||||
*
|
||||
* @return - pointer to new rpmsg channel
|
||||
*
|
||||
*/
|
||||
struct rpmsg_channel *_rpmsg_create_channel(struct remote_device *rdev,
|
||||
char *name, unsigned long src, unsigned long dst) {
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
struct llist *node;
|
||||
|
||||
rp_chnl = env_allocate_memory(sizeof(struct rpmsg_channel));
|
||||
if (rp_chnl) {
|
||||
env_memset(rp_chnl, 0x00, sizeof(struct rpmsg_channel));
|
||||
env_strncpy(rp_chnl->name, name, sizeof(rp_chnl->name));
|
||||
rp_chnl->src = src;
|
||||
rp_chnl->dst = dst;
|
||||
rp_chnl->rdev = rdev;
|
||||
/* Place channel on channels list */
|
||||
node = env_allocate_memory(sizeof(struct llist));
|
||||
if (!node) {
|
||||
env_free_memory(rp_chnl);
|
||||
return RPMSG_NULL ;
|
||||
}
|
||||
node->data = rp_chnl;
|
||||
env_lock_mutex(rdev->lock);
|
||||
add_to_list(&rdev->rp_channels , node);
|
||||
env_unlock_mutex(rdev->lock);
|
||||
}
|
||||
|
||||
return rp_chnl;
|
||||
}
|
||||
|
||||
/**
|
||||
* _rpmsg_delete_channel
|
||||
*
|
||||
* Deletes given rpmsg channel.
|
||||
*
|
||||
* @param rp_chnl - pointer to rpmsg channel to delete
|
||||
*
|
||||
* return - none
|
||||
*/
|
||||
void _rpmsg_delete_channel(struct rpmsg_channel * rp_chnl) {
|
||||
struct llist *node;
|
||||
if (rp_chnl) {
|
||||
node = rpmsg_rdev_get_chnl_node_from_id(rp_chnl->rdev, rp_chnl->name);
|
||||
if (node) {
|
||||
env_lock_mutex(rp_chnl->rdev->lock);
|
||||
remove_from_list(&rp_chnl->rdev->rp_channels, node);
|
||||
env_unlock_mutex(rp_chnl->rdev->lock);
|
||||
env_free_memory(node);
|
||||
}
|
||||
env_free_memory(rp_chnl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _create_endpoint
|
||||
*
|
||||
* This function creates rpmsg endpoint.
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
* @param cb - Rx completion call back
|
||||
* @param priv - private data
|
||||
* @param addr - endpoint src address
|
||||
*
|
||||
* @return - pointer to endpoint control block
|
||||
*
|
||||
*/
|
||||
struct rpmsg_endpoint *_create_endpoint(struct remote_device *rdev,
|
||||
rpmsg_rx_cb_t cb, void *priv, unsigned long addr) {
|
||||
|
||||
struct rpmsg_endpoint *rp_ept;
|
||||
struct llist *node;
|
||||
int status = RPMSG_SUCCESS;
|
||||
|
||||
rp_ept = env_allocate_memory(sizeof(struct rpmsg_endpoint));
|
||||
if (!rp_ept) {
|
||||
return RPMSG_NULL ;
|
||||
}
|
||||
|
||||
node = env_allocate_memory(sizeof(struct llist));
|
||||
if (!node) {
|
||||
env_free_memory(rp_ept);
|
||||
return RPMSG_NULL;
|
||||
}
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
|
||||
if (addr != RPMSG_ADDR_ANY) {
|
||||
/*
|
||||
* Application has requested a particular src address for endpoint,
|
||||
* first check if address is available.
|
||||
*/
|
||||
if (!rpmsg_is_address_set(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr)) {
|
||||
/* Mark the address as used in the address bitmap. */
|
||||
rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr);
|
||||
|
||||
} else {
|
||||
status = RPMSG_ERR_DEV_ADDR;
|
||||
}
|
||||
} else {
|
||||
addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE);
|
||||
if (addr < 0) {
|
||||
status = RPMSG_ERR_DEV_ADDR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do cleanup in case of error and return */
|
||||
if (status) {
|
||||
env_free_memory(node);
|
||||
env_free_memory(rp_ept);
|
||||
env_unlock_mutex(rdev->lock);
|
||||
return RPMSG_NULL;
|
||||
}
|
||||
|
||||
rp_ept->addr = addr;
|
||||
rp_ept->cb = cb;
|
||||
rp_ept->priv = priv;
|
||||
|
||||
node->data = rp_ept;
|
||||
add_to_list(&rdev->rp_endpoints, node);
|
||||
|
||||
env_unlock_mutex(rdev->lock);
|
||||
|
||||
return rp_ept;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_destroy_ept
|
||||
*
|
||||
* This function deletes rpmsg endpoint and performs cleanup.
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
* @param rp_ept - pointer to endpoint to destroy
|
||||
*
|
||||
*/
|
||||
void _destroy_endpoint(struct remote_device *rdev,
|
||||
struct rpmsg_endpoint *rp_ept) {
|
||||
struct llist *node;
|
||||
node = rpmsg_rdev_get_endpoint_from_addr(rdev, rp_ept->addr);
|
||||
if (node) {
|
||||
env_lock_mutex(rdev->lock);
|
||||
rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, rp_ept->addr);
|
||||
remove_from_list(&rdev->rp_endpoints, node);
|
||||
env_unlock_mutex(rdev->lock);
|
||||
env_free_memory(node);
|
||||
}
|
||||
env_free_memory(rp_ept);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_send_ns_message
|
||||
*
|
||||
* Sends name service announcement to remote device
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
* @param rp_chnl - pointer to rpmsg channel
|
||||
* @param flags - Channel creation/deletion flags
|
||||
*
|
||||
*/
|
||||
void rpmsg_send_ns_message(struct remote_device *rdev,
|
||||
struct rpmsg_channel *rp_chnl, unsigned long flags) {
|
||||
|
||||
struct rpmsg_hdr *rp_hdr;
|
||||
struct rpmsg_ns_msg *ns_msg;
|
||||
unsigned short idx;
|
||||
int len;
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
|
||||
/* Get Tx buffer. */
|
||||
rp_hdr = (struct rpmsg_hdr *) rpmsg_get_tx_buffer(rdev, &len, &idx);
|
||||
if (!rp_hdr)
|
||||
return;
|
||||
|
||||
/* Fill out name service data. */
|
||||
rp_hdr->dst = RPMSG_NS_EPT_ADDR;
|
||||
rp_hdr->len = sizeof(struct rpmsg_ns_msg);
|
||||
ns_msg = (struct rpmsg_ns_msg *) rp_hdr->data;
|
||||
env_strncpy(ns_msg->name, rp_chnl->name, sizeof(rp_chnl->name));
|
||||
ns_msg->flags = flags;
|
||||
ns_msg->addr = rp_chnl->src;
|
||||
|
||||
/* Place the buffer on virtqueue. */
|
||||
rpmsg_enqueue_buffer(rdev, rp_hdr, len, idx);
|
||||
|
||||
/* Notify the other side that it has data to process. */
|
||||
virtqueue_kick(rdev->tvq);
|
||||
|
||||
env_unlock_mutex(rdev->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_enqueue_buffers
|
||||
*
|
||||
* Places buffer on the virtqueue for consumption by the other side.
|
||||
*
|
||||
* @param rdev - pointer to remote core
|
||||
* @param buffer - buffer pointer
|
||||
* @param len - buffer length
|
||||
* @idx - buffer index
|
||||
*
|
||||
* @return - status of function execution
|
||||
*
|
||||
*/
|
||||
int rpmsg_enqueue_buffer(struct remote_device *rdev, void *buffer,
|
||||
unsigned long len, unsigned short idx) {
|
||||
struct llist node;
|
||||
int status;
|
||||
|
||||
/* Initialize buffer node */
|
||||
node.data = buffer;
|
||||
node.attr = len;
|
||||
node.next = RPMSG_NULL;
|
||||
node.prev = RPMSG_NULL;
|
||||
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
status = virtqueue_add_buffer(rdev->tvq, &node, 0, 1, buffer);
|
||||
} else {
|
||||
status = virtqueue_add_consumed_buffer(rdev->tvq, idx, len);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_return_buffer
|
||||
*
|
||||
* Places the used buffer back on the virtqueue.
|
||||
*
|
||||
* @param rdev - pointer to remote core
|
||||
* @param buffer - buffer pointer
|
||||
* @param len - buffer length
|
||||
* @param idx - buffer index
|
||||
*
|
||||
*/
|
||||
void rpmsg_return_buffer(struct remote_device *rdev, void *buffer,
|
||||
unsigned long len, unsigned short idx) {
|
||||
struct llist node;
|
||||
|
||||
/* Initialize buffer node */
|
||||
node.data = buffer;
|
||||
node.attr = len;
|
||||
node.next = RPMSG_NULL;
|
||||
node.prev = RPMSG_NULL;
|
||||
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
virtqueue_add_buffer(rdev->rvq, &node, 0, 1, buffer);
|
||||
} else {
|
||||
virtqueue_add_consumed_buffer(rdev->rvq, idx, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_get_tx_buffer
|
||||
*
|
||||
* Provides buffer to transmit messages.
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
* @param len - length of returned buffer
|
||||
* @param idx - buffer index
|
||||
*
|
||||
* return - pointer to buffer.
|
||||
*/
|
||||
void *rpmsg_get_tx_buffer(struct remote_device *rdev, int *len,
|
||||
unsigned short *idx) {
|
||||
void *data;
|
||||
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
data = virtqueue_get_buffer(rdev->tvq, (unsigned long *) len);
|
||||
if (data == RPMSG_NULL) {
|
||||
data = sh_mem_get_buffer(rdev->mem_pool);
|
||||
*len = RPMSG_BUFFER_SIZE;
|
||||
}
|
||||
} else {
|
||||
data = virtqueue_get_available_buffer(rdev->tvq, idx,
|
||||
(unsigned long *) len);
|
||||
}
|
||||
return ((void *) env_map_vatopa(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_get_rx_buffer
|
||||
*
|
||||
* Retrieves the received buffer from the virtqueue.
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
* @param len - size of received buffer
|
||||
* @param idx - index of buffer
|
||||
*
|
||||
* @return - pointer to received buffer
|
||||
*
|
||||
*/
|
||||
void *rpmsg_get_rx_buffer(struct remote_device *rdev, unsigned long *len,
|
||||
unsigned short *idx) {
|
||||
|
||||
void *data;
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
data = virtqueue_get_buffer(rdev->rvq, len);
|
||||
} else {
|
||||
data = virtqueue_get_available_buffer(rdev->rvq, idx, len);
|
||||
}
|
||||
return ((void *) env_map_vatopa(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_free_buffer
|
||||
*
|
||||
* Frees the allocated buffers.
|
||||
*
|
||||
* @param rdev - pointer to remote device
|
||||
* @param buffer - pointer to buffer to free
|
||||
*
|
||||
*/
|
||||
void rpmsg_free_buffer(struct remote_device *rdev, void *buffer) {
|
||||
if (rdev->role == RPMSG_REMOTE) {
|
||||
sh_mem_free_buffer(rdev->mem_pool, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_tx_callback
|
||||
*
|
||||
* Tx callback function.
|
||||
*
|
||||
* @param vq - pointer to virtqueue on which Tx is has been
|
||||
* completed.
|
||||
*
|
||||
*/
|
||||
static void rpmsg_tx_callback(struct virtqueue *vq) {
|
||||
struct remote_device *rdev;
|
||||
struct virtio_device *vdev;
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
struct llist *chnl_hd;
|
||||
|
||||
vdev = (struct virtio_device *) vq->vq_dev;
|
||||
rdev = (struct remote_device *) vdev;
|
||||
chnl_hd = rdev->rp_channels;
|
||||
|
||||
/* Check if the remote device is master. */
|
||||
if (rdev->role == RPMSG_MASTER) {
|
||||
|
||||
/* Notification is received from the master. Now the remote(us) can
|
||||
* performs one of two operations;
|
||||
*
|
||||
* a. If name service announcement is supported then it will send NS message.
|
||||
* else
|
||||
* b. It will update the channel state to active so that further communication
|
||||
* can take place.
|
||||
*/
|
||||
while (chnl_hd != RPMSG_NULL) {
|
||||
rp_chnl = (struct rpmsg_channel *) chnl_hd->data;
|
||||
|
||||
if (rp_chnl->state == RPMSG_CHNL_STATE_IDLE) {
|
||||
|
||||
if (rdev->support_ns) {
|
||||
rp_chnl->state = RPMSG_CHNL_STATE_NS;
|
||||
} else {
|
||||
rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
|
||||
}
|
||||
|
||||
if (rp_chnl->state == RPMSG_CHNL_STATE_NS) {
|
||||
rpmsg_send_ns_message(rdev, rp_chnl, RPMSG_NS_CREATE);
|
||||
}
|
||||
}
|
||||
|
||||
chnl_hd = chnl_hd->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_rx_callback
|
||||
*
|
||||
* Rx callback function.
|
||||
*
|
||||
* @param vq - pointer to virtqueue on which messages is received
|
||||
*
|
||||
*/
|
||||
void rpmsg_rx_callback(struct virtqueue *vq) {
|
||||
struct remote_device *rdev;
|
||||
struct virtio_device *vdev;
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
struct rpmsg_endpoint *rp_ept;
|
||||
struct rpmsg_hdr *rp_hdr;
|
||||
struct llist *node;
|
||||
unsigned long len;
|
||||
unsigned short idx;
|
||||
struct llist *chnl_hd;
|
||||
|
||||
vdev = (struct virtio_device *) vq->vq_dev;
|
||||
rdev = (struct remote_device *) vdev;
|
||||
|
||||
chnl_hd = rdev->rp_channels;
|
||||
if ((chnl_hd != RPMSG_NULL) && (rdev->role == RPMSG_MASTER)) {
|
||||
rp_chnl = (struct rpmsg_channel *) chnl_hd->data;
|
||||
if (rp_chnl->state == RPMSG_CHNL_STATE_IDLE) {
|
||||
if (rdev->support_ns) {
|
||||
rp_chnl->state = RPMSG_CHNL_STATE_NS;
|
||||
rpmsg_send_ns_message(rdev, rp_chnl, RPMSG_NS_CREATE);
|
||||
} else {
|
||||
rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
|
||||
/* Process the received data from remote node */
|
||||
rp_hdr = (struct rpmsg_hdr *) rpmsg_get_rx_buffer(rdev, &len, &idx);
|
||||
|
||||
env_unlock_mutex(rdev->lock);
|
||||
|
||||
if (!rp_hdr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the channel node from the remote device channels list. */
|
||||
node = rpmsg_rdev_get_endpoint_from_addr(rdev, rp_hdr->dst);
|
||||
|
||||
if (!node)
|
||||
/* Fatal error no endpoint for the given dst addr. */
|
||||
return;
|
||||
|
||||
rp_ept = (struct rpmsg_endpoint *) node->data;
|
||||
|
||||
rp_chnl = rp_ept->rp_chnl;
|
||||
|
||||
if ((rp_chnl) && (rp_chnl->state == RPMSG_CHNL_STATE_NS)) {
|
||||
|
||||
/* First message from RPMSG Master, update channel
|
||||
* destination address and state */
|
||||
rp_chnl->dst = rp_hdr->src;
|
||||
rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
|
||||
|
||||
/* Notify channel creation to application */
|
||||
if (rdev->channel_created) {
|
||||
rdev->channel_created(rp_chnl);
|
||||
}
|
||||
} else {
|
||||
|
||||
rp_ept->cb(rp_chnl, rp_hdr->data, rp_hdr->len, rp_ept->priv,
|
||||
rp_hdr->src);
|
||||
}
|
||||
|
||||
env_lock_mutex(rdev->lock);
|
||||
|
||||
/* Return used buffers. */
|
||||
rpmsg_return_buffer(rdev, rp_hdr, len, idx);
|
||||
|
||||
env_unlock_mutex(rdev->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_ns_callback
|
||||
*
|
||||
* This callback handles name service announcement from the remote device
|
||||
* and creates/deletes rpmsg channels.
|
||||
*
|
||||
* @param server_chnl - pointer to server channel control block.
|
||||
* @param data - pointer to received messages
|
||||
* @param len - length of received data
|
||||
* @param priv - any private data
|
||||
* @param src - source address
|
||||
*
|
||||
* @return - none
|
||||
*/
|
||||
void rpmsg_ns_callback(struct rpmsg_channel *server_chnl, void *data, int len,
|
||||
void *priv, unsigned long src) {
|
||||
struct remote_device *rdev;
|
||||
struct rpmsg_channel *rp_chnl;
|
||||
struct rpmsg_ns_msg *ns_msg;
|
||||
struct llist *node;
|
||||
|
||||
rdev = (struct remote_device *) priv;
|
||||
|
||||
//FIXME: This assumes same name string size for channel name both on master
|
||||
//and remote. If this is not the case then we will have to parse the
|
||||
//message contents.
|
||||
|
||||
ns_msg = (struct rpmsg_ns_msg *) data;
|
||||
ns_msg->name[len - 1] = '\0';
|
||||
|
||||
if (ns_msg->flags & RPMSG_NS_DESTROY) {
|
||||
node = rpmsg_rdev_get_chnl_node_from_id(rdev, ns_msg->name);
|
||||
if (node) {
|
||||
rp_chnl = (struct rpmsg_channel *) node->data;
|
||||
if (rdev->channel_destroyed) {
|
||||
rdev->channel_destroyed(rp_chnl);
|
||||
}
|
||||
rpmsg_destroy_ept(rp_chnl->rp_ept);
|
||||
_rpmsg_delete_channel(rp_chnl);
|
||||
}
|
||||
} else {
|
||||
rp_chnl = _rpmsg_create_channel(rdev, ns_msg->name, 0x00, ns_msg->addr);
|
||||
if (rp_chnl) {
|
||||
rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
|
||||
/* Create default endpoint for channel */
|
||||
rp_chnl->rp_ept = rpmsg_create_ept(rp_chnl, rdev->default_cb, rdev,
|
||||
RPMSG_ADDR_ANY);
|
||||
if (rp_chnl->rp_ept) {
|
||||
rp_chnl->src = rp_chnl->rp_ept->addr;
|
||||
/*
|
||||
* Echo back the NS message to remote in order to
|
||||
* complete the connection stage. Remote will know the endpoint
|
||||
* address from this point onward which will enable it to send
|
||||
* message without waiting for any application level message from
|
||||
* master.
|
||||
*/
|
||||
rpmsg_send(rp_chnl,data,len);
|
||||
if (rdev->channel_created) {
|
||||
rdev->channel_created(rp_chnl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_get_address
|
||||
*
|
||||
* This function provides unique 32 bit address.
|
||||
*
|
||||
* @param bitmap - bit map for addresses
|
||||
* @param size - size of bitmap
|
||||
*
|
||||
* return - a unique address
|
||||
*/
|
||||
int rpmsg_get_address(unsigned long *bitmap, int size) {
|
||||
int addr = -1;
|
||||
int i, tmp32;
|
||||
|
||||
/* Find first available buffer */
|
||||
for (i = 0; i < size; i++) {
|
||||
tmp32 = get_first_zero_bit(bitmap[i]);
|
||||
|
||||
if (tmp32 < 32) {
|
||||
addr = tmp32 + i + 1;
|
||||
bitmap[i] |= (1 << tmp32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_release_address
|
||||
*
|
||||
* Frees the given address.
|
||||
*
|
||||
* @param bitmap - bit map for addresses
|
||||
* @param size - size of bitmap
|
||||
* @param addr - address to free
|
||||
*
|
||||
* return - none
|
||||
*/
|
||||
int rpmsg_release_address(unsigned long *bitmap, int size, int addr) {
|
||||
unsigned int i, j;
|
||||
unsigned long mask = 1;
|
||||
|
||||
if (addr >= size * 32)
|
||||
return -1;
|
||||
|
||||
/* Mark the addr as available */
|
||||
i = addr / 32;
|
||||
j = addr % 32;
|
||||
|
||||
mask = mask << j;
|
||||
bitmap[i] = bitmap[i] & (~mask);
|
||||
|
||||
return RPMSG_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_is_address_set
|
||||
*
|
||||
* Checks whether address is used or free.
|
||||
*
|
||||
* @param bitmap - bit map for addresses
|
||||
* @param size - size of bitmap
|
||||
* @param addr - address to free
|
||||
*
|
||||
* return - TRUE/FALSE
|
||||
*/
|
||||
int rpmsg_is_address_set(unsigned long *bitmap, int size,
|
||||
int addr) {
|
||||
int i, j;
|
||||
unsigned long mask = 1;
|
||||
|
||||
if (addr >= size * 32)
|
||||
return -1;
|
||||
|
||||
/* Mark the id as available */
|
||||
i = addr / 32;
|
||||
j = addr % 32;
|
||||
mask = mask << j;
|
||||
|
||||
return (bitmap[i] & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmsg_set_address
|
||||
*
|
||||
* Marks the address as consumed.
|
||||
*
|
||||
* @param bitmap - bit map for addresses
|
||||
* @param size - size of bitmap
|
||||
* @param addr - address to free
|
||||
*
|
||||
* return - none
|
||||
*/
|
||||
int rpmsg_set_address(unsigned long *bitmap, int size, int addr) {
|
||||
int i, j;
|
||||
unsigned long mask = 1;
|
||||
|
||||
if (addr >= size * 32)
|
||||
return -1;
|
||||
|
||||
/* Mark the id as available */
|
||||
i = addr / 32;
|
||||
j = addr % 32;
|
||||
mask = mask << j;
|
||||
bitmap[i] |= mask;
|
||||
|
||||
return RPMSG_SUCCESS;
|
||||
}
|
190
ThirdParty/sw_services/xilopenamp/src/rpmsg_core.h
vendored
Normal file
190
ThirdParty/sw_services/xilopenamp/src/rpmsg_core.h
vendored
Normal file
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _RPMSG_CORE_H_
|
||||
#define _RPMSG_CORE_H_
|
||||
|
||||
#include "env.h"
|
||||
#include "virtio.h"
|
||||
#include "hil.h"
|
||||
#include "sh_mem.h"
|
||||
#include "llist.h"
|
||||
#include "rpmsg.h"
|
||||
|
||||
/* Configurable parameters */
|
||||
#define RPMSG_BUFFER_SIZE 512
|
||||
#define RPMSG_MAX_VQ_PER_RDEV 2
|
||||
#define RPMSG_NS_EPT_ADDR 0x35
|
||||
#define RPMSG_ADDR_BMP_SIZE 4
|
||||
|
||||
/* Definitions for device types , null pointer, etc.*/
|
||||
#define RPMSG_SUCCESS 0
|
||||
#define RPMSG_NULL (void *)0
|
||||
#define RPMSG_REMOTE 0
|
||||
#define RPMSG_MASTER 1
|
||||
#define RPMSG_TRUE 1
|
||||
#define RPMSG_FALSE 0
|
||||
|
||||
/* RPMSG channel states. */
|
||||
#define RPMSG_CHNL_STATE_IDLE 0
|
||||
#define RPMSG_CHNL_STATE_NS 1
|
||||
#define RPMSG_CHNL_STATE_ACTIVE 2
|
||||
|
||||
/* Remote processor/device states. */
|
||||
#define RPMSG_DEV_STATE_IDLE 0
|
||||
#define RPMSG_DEV_STATE_ACTIVE 1
|
||||
|
||||
/* Total tick count for 15secs - 1msec tick. */
|
||||
#define RPMSG_TICK_COUNT 15000
|
||||
|
||||
/* Time to wait - In multiple of 10 msecs. */
|
||||
#define RPMSG_TICKS_PER_INTERVAL 10
|
||||
|
||||
/* Error macros. */
|
||||
#define RPMSG_ERRORS_BASE -3000
|
||||
#define RPMSG_ERR_NO_MEM (RPMSG_ERRORS_BASE - 1)
|
||||
#define RPMSG_ERR_NO_BUFF (RPMSG_ERRORS_BASE - 2)
|
||||
#define RPMSG_ERR_MAX_VQ (RPMSG_ERRORS_BASE - 3)
|
||||
#define RPMSG_ERR_PARAM (RPMSG_ERRORS_BASE - 4)
|
||||
#define RPMSG_ERR_DEV_STATE (RPMSG_ERRORS_BASE - 5)
|
||||
#define RPMSG_ERR_BUFF_SIZE (RPMSG_ERRORS_BASE - 6)
|
||||
#define RPMSG_ERR_DEV_ID (RPMSG_ERRORS_BASE - 7)
|
||||
#define RPMSG_ERR_DEV_ADDR (RPMSG_ERRORS_BASE - 8)
|
||||
|
||||
struct rpmsg_channel;
|
||||
typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, unsigned long);
|
||||
typedef void (*rpmsg_chnl_cb_t)(struct rpmsg_channel *rp_chl);
|
||||
/**
|
||||
* remote_device
|
||||
*
|
||||
* This structure is maintained by RPMSG driver to represent remote device/core.
|
||||
*
|
||||
* @virtd_dev - virtio device for remote core
|
||||
* @rvq - Rx virtqueue for virtio device
|
||||
* @tvq - Tx virtqueue for virtio device
|
||||
* @proc - reference to remote processor
|
||||
* @rp_channels - rpmsg channels list for the device
|
||||
* @rp_endpoints - rpmsg endpoints list for the device
|
||||
* @mem_pool - shared memory pool
|
||||
* @bitmap - bitmap for channels addresses
|
||||
* @channel_created - create channel callback
|
||||
* @channel_destroyed - delete channel callback
|
||||
* @default_cb - default callback handler for RX data on channel
|
||||
* @lock - remote device mutex
|
||||
* @role - role of the remote device, RPMSG_MASTER/RPMSG_REMOTE
|
||||
* @state - remote device state, IDLE/ACTIVE
|
||||
* @support_ns - if device supports name service announcement
|
||||
*
|
||||
*/
|
||||
struct remote_device {
|
||||
struct virtio_device virt_dev;
|
||||
struct virtqueue *rvq;
|
||||
struct virtqueue *tvq;
|
||||
struct hil_proc *proc;
|
||||
struct llist *rp_channels;
|
||||
struct llist *rp_endpoints;
|
||||
struct sh_mem_pool *mem_pool;
|
||||
unsigned long bitmap[RPMSG_ADDR_BMP_SIZE];
|
||||
rpmsg_chnl_cb_t channel_created;
|
||||
rpmsg_chnl_cb_t channel_destroyed;
|
||||
rpmsg_rx_cb_t default_cb;
|
||||
LOCK *lock;
|
||||
unsigned int role;
|
||||
unsigned int state;
|
||||
int support_ns;
|
||||
};
|
||||
|
||||
/* Core functions */
|
||||
int rpmsg_start_ipc(struct remote_device *rdev);
|
||||
struct rpmsg_channel *_rpmsg_create_channel(struct remote_device *rdev,
|
||||
char *name, unsigned long src, unsigned long dst);
|
||||
void _rpmsg_delete_channel(struct rpmsg_channel * rp_chnl);
|
||||
struct rpmsg_endpoint *_create_endpoint(struct remote_device *rdev,
|
||||
rpmsg_rx_cb_t cb, void *priv, unsigned long addr);
|
||||
void _destroy_endpoint(struct remote_device *rdev,
|
||||
struct rpmsg_endpoint *rp_ept);
|
||||
void rpmsg_send_ns_message(struct remote_device *rdev,
|
||||
struct rpmsg_channel *rp_chnl, unsigned long flags);
|
||||
int rpmsg_enqueue_buffer(struct remote_device *rdev, void *buffer,
|
||||
unsigned long len, unsigned short idx);
|
||||
void rpmsg_return_buffer(struct remote_device *rdev, void *buffer,
|
||||
unsigned long len, unsigned short idx);
|
||||
void *rpmsg_get_tx_buffer(struct remote_device *rdev, int *len,
|
||||
unsigned short *idx);
|
||||
void rpmsg_free_buffer(struct remote_device *rdev, void *buffer);
|
||||
void rpmsg_free_channel(struct rpmsg_channel* rp_chnl);
|
||||
void * rpmsg_get_rx_buffer(struct remote_device *rdev, unsigned long *len,
|
||||
unsigned short *idx);
|
||||
int rpmsg_get_address(unsigned long *bitmap, int size);
|
||||
int rpmsg_release_address(unsigned long *bitmap, int size, int addr);
|
||||
int rpmsg_is_address_set(unsigned long *bitmap, int size,
|
||||
int addr);
|
||||
int rpmsg_set_address(unsigned long *bitmap, int size, int addr);
|
||||
void rpmsg_ns_callback(struct rpmsg_channel *server_chnl,
|
||||
void *data, int len, void *priv, unsigned long src);
|
||||
|
||||
/* Remote device functions */
|
||||
int rpmsg_rdev_init(struct remote_device **rdev, int dev_id, int role,
|
||||
rpmsg_chnl_cb_t channel_created,
|
||||
rpmsg_chnl_cb_t channel_destroyed,
|
||||
rpmsg_rx_cb_t default_cb);
|
||||
void rpmsg_rdev_deinit(struct remote_device *rdev);
|
||||
struct llist *rpmsg_rdev_get_chnl_node_from_id(struct remote_device *rdev,
|
||||
char *rp_chnl_id);
|
||||
struct llist *rpmsg_rdev_get_chnl_from_addr(struct remote_device *rdev,
|
||||
unsigned long addr);
|
||||
struct llist *rpmsg_rdev_get_endpoint_from_addr(struct remote_device *rdev,
|
||||
unsigned long addr);
|
||||
int rpmsg_rdev_notify(struct remote_device *rdev);
|
||||
int rpmsg_rdev_create_virtqueues(struct virtio_device *dev, int flags, int nvqs,
|
||||
const char *names[], vq_callback *callbacks[],
|
||||
struct virtqueue *vqs[]);
|
||||
unsigned char rpmsg_rdev_get_status(struct virtio_device *dev);
|
||||
|
||||
void rpmsg_rdev_set_status(struct virtio_device *dev, unsigned char status);
|
||||
|
||||
unsigned long rpmsg_rdev_get_feature(struct virtio_device *dev);
|
||||
|
||||
void rpmsg_rdev_set_feature(struct virtio_device *dev, unsigned long feature);
|
||||
|
||||
unsigned long rpmsg_rdev_negotiate_feature(struct virtio_device *dev,
|
||||
unsigned long features);
|
||||
/*
|
||||
* Read/write a variable amount from the device specific (ie, network)
|
||||
* configuration region. This region is encoded in the same endian as
|
||||
* the guest.
|
||||
*/
|
||||
void rpmsg_rdev_read_config(struct virtio_device *dev, unsigned long offset,
|
||||
void *dst, int length);
|
||||
void rpmsg_rdev_write_config(struct virtio_device *dev, unsigned long offset,
|
||||
void *src, int length);
|
||||
void rpmsg_rdev_reset(struct virtio_device *dev);
|
||||
|
||||
#endif /* _RPMSG_CORE_H_ */
|
245
ThirdParty/sw_services/xilopenamp/src/rpmsg_retarget.c
vendored
Normal file
245
ThirdParty/sw_services/xilopenamp/src/rpmsg_retarget.c
vendored
Normal file
|
@ -0,0 +1,245 @@
|
|||
#include "open_amp.h"
|
||||
#include "rpmsg_retarget.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "sleep.h"
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Description
|
||||
* This files contains rpmsg based redefinitions for C RTL system calls
|
||||
* such as _open, _read, _write, _close.
|
||||
*************************************************************************/
|
||||
static struct _rpc_data* rpc_data;
|
||||
static unsigned int rpc_data_synclock = 0;
|
||||
int get_response = 0;
|
||||
|
||||
int send_rpc(void *data, int len);
|
||||
static int rpc_count=0;
|
||||
|
||||
void rpc_cb(struct rpmsg_channel *rtl_rp_chnl, void *data, int len, void * priv,
|
||||
unsigned long src) {
|
||||
memcpy(rpc_data->rpc_response, data, len);
|
||||
env_release_sync_lock(rpc_data->sync_lock);
|
||||
get_response=1;
|
||||
|
||||
|
||||
if (rpc_data->rpc_response->id == TERM_SYSCALL_ID) {
|
||||
/* Application terminate signal is received from the proxy app,
|
||||
* so let the application know of terminate message.
|
||||
*/
|
||||
rpc_data->shutdown_cb(rtl_rp_chnl);
|
||||
}
|
||||
}
|
||||
|
||||
int send_rpc(void *data, int len) {
|
||||
int retval;
|
||||
|
||||
retval = rpmsg_sendto(rpc_data->rpmsg_chnl, data, len, PROXY_ENDPOINT);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int rpmsg_retarget_init(struct rpmsg_channel *rp_chnl, rpc_shutdown_cb cb) {
|
||||
int status;
|
||||
|
||||
/* Allocate memory for rpc control block */
|
||||
rpc_data = (struct _rpc_data*) env_allocate_memory(
|
||||
sizeof(struct _rpc_data));
|
||||
|
||||
/* Create a mutex for synchronization */
|
||||
status = env_create_mutex(&rpc_data->rpc_lock, 1);
|
||||
|
||||
/* Create a mutex for synchronization */
|
||||
status = env_create_sync_lock(&rpc_data->sync_lock, LOCKED);
|
||||
|
||||
/* Create a endpoint to handle rpc response from master */
|
||||
rpc_data->rpmsg_chnl = rp_chnl;
|
||||
rpc_data->rp_ept = rpmsg_create_ept(rpc_data->rpmsg_chnl, rpc_cb,
|
||||
RPMSG_NULL, PROXY_ENDPOINT);
|
||||
rpc_data->rpc = env_allocate_memory(RPC_BUFF_SIZE);
|
||||
rpc_data->rpc_response = env_allocate_memory(RPC_BUFF_SIZE);
|
||||
rpc_data->shutdown_cb = cb;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int rpmsg_retarget_deinit(struct rpmsg_channel *rp_chnl) {
|
||||
env_free_memory(rpc_data->rpc);
|
||||
env_free_memory(rpc_data->rpc_response);
|
||||
env_delete_mutex(rpc_data->rpc_lock);
|
||||
env_delete_sync_lock(rpc_data->sync_lock);
|
||||
rpmsg_destroy_ept(rpc_data->rp_ept);
|
||||
env_free_memory(rpc_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* _open
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Open a file. Minimal implementation
|
||||
*
|
||||
*************************************************************************/
|
||||
int _open(const char * filename, int flags, int mode) {
|
||||
int filename_len = strlen(filename) + 1;
|
||||
int payload_size = sizeof(struct _sys_rpc) + filename_len;
|
||||
int retval = -1;
|
||||
|
||||
if ((!filename) || (filename_len > FILE_NAME_LEN)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Construct rpc payload */
|
||||
rpc_data->rpc->id = OPEN_SYSCALL_ID;
|
||||
rpc_data->rpc->sys_call_args.int_field1 = flags;
|
||||
rpc_data->rpc->sys_call_args.int_field2 = mode;
|
||||
rpc_data->rpc->sys_call_args.data_len = filename_len;
|
||||
memcpy(&rpc_data->rpc->sys_call_args.data, filename, filename_len);
|
||||
|
||||
/* Transmit rpc request */
|
||||
env_lock_mutex(rpc_data->rpc_lock);
|
||||
send_rpc((void*) rpc_data->rpc, payload_size);
|
||||
env_unlock_mutex(rpc_data->rpc_lock);
|
||||
|
||||
/* Wait for response from proxy on master */
|
||||
env_acquire_sync_lock(rpc_data->sync_lock);
|
||||
|
||||
/* Obtain return args and return to caller */
|
||||
if (rpc_data->rpc_response->id == OPEN_SYSCALL_ID) {
|
||||
retval = rpc_data->rpc_response->sys_call_args.int_field1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* _read
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Low level function to redirect IO to serial.
|
||||
*
|
||||
*************************************************************************/
|
||||
int _read(int fd, char * buffer, int buflen) {
|
||||
int payload_size = sizeof(struct _sys_rpc);
|
||||
int retval = -1;
|
||||
|
||||
if (!buffer || !buflen)
|
||||
return retval;
|
||||
|
||||
/* Construct rpc payload */
|
||||
rpc_data->rpc->id = READ_SYSCALL_ID;
|
||||
rpc_data->rpc->sys_call_args.int_field1 = fd;
|
||||
rpc_data->rpc->sys_call_args.int_field2 = buflen;
|
||||
rpc_data->rpc->sys_call_args.data_len = 0; /*not used*/
|
||||
|
||||
/* Transmit rpc request */
|
||||
env_lock_mutex(rpc_data->rpc_lock);
|
||||
get_response=0;
|
||||
send_rpc((void*) rpc_data->rpc, payload_size);
|
||||
env_unlock_mutex(rpc_data->rpc_lock);
|
||||
|
||||
/* Wait for response from proxy on master */
|
||||
env_acquire_sync_lock(rpc_data->sync_lock);
|
||||
|
||||
/* Obtain return args and return to caller */
|
||||
if (rpc_data->rpc_response->id == READ_SYSCALL_ID) {
|
||||
if (rpc_data->rpc_response->sys_call_args.int_field1 > 0) {
|
||||
memcpy(buffer, rpc_data->rpc_response->sys_call_args.data,
|
||||
rpc_data->rpc_response->sys_call_args.data_len);
|
||||
}
|
||||
|
||||
retval = rpc_data->rpc_response->sys_call_args.int_field1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* _write
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Low level function to redirect IO to serial.
|
||||
*
|
||||
*************************************************************************/
|
||||
int _write(int fd, const char * ptr, int len) {
|
||||
int retval = -1;
|
||||
int payload_size = sizeof(struct _sys_rpc) + len;
|
||||
int null_term = 0;
|
||||
|
||||
if (fd == 1) {
|
||||
null_term = 1;
|
||||
}
|
||||
|
||||
rpc_data->rpc->id = WRITE_SYSCALL_ID;
|
||||
rpc_data->rpc->sys_call_args.int_field1 = fd;
|
||||
rpc_data->rpc->sys_call_args.int_field2 = len;
|
||||
rpc_data->rpc->sys_call_args.data_len = len + null_term;
|
||||
memcpy(rpc_data->rpc->sys_call_args.data, ptr, len);
|
||||
if (null_term) {
|
||||
*(char*) (rpc_data->rpc->sys_call_args.data + len + null_term) = 0;
|
||||
}
|
||||
|
||||
env_lock_mutex(rpc_data->rpc_lock);
|
||||
send_rpc((void*) rpc_data->rpc, payload_size);
|
||||
env_unlock_mutex(rpc_data->rpc_lock);
|
||||
|
||||
env_acquire_sync_lock(rpc_data->sync_lock);
|
||||
|
||||
if (rpc_data->rpc_response->id == WRITE_SYSCALL_ID) {
|
||||
retval = rpc_data->rpc_response->sys_call_args.int_field1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* FUNCTION
|
||||
*
|
||||
* _close
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Close a file. Minimal implementation
|
||||
*
|
||||
*************************************************************************/
|
||||
int _close(int fd) {
|
||||
int payload_size = sizeof(struct _sys_rpc);
|
||||
int retval = -1;
|
||||
|
||||
rpc_data->rpc->id = CLOSE_SYSCALL_ID;
|
||||
rpc_data->rpc->sys_call_args.int_field1 = fd;
|
||||
rpc_data->rpc->sys_call_args.int_field2 = 0; /*not used*/
|
||||
rpc_data->rpc->sys_call_args.data_len = 0; /*not used*/
|
||||
|
||||
env_lock_mutex(rpc_data->rpc_lock);
|
||||
send_rpc((void*) rpc_data->rpc, payload_size);
|
||||
env_unlock_mutex(rpc_data->rpc_lock);
|
||||
|
||||
/* Wait for response from proxy on master */
|
||||
env_acquire_sync_lock(rpc_data->sync_lock);
|
||||
|
||||
if (rpc_data->rpc_response->id == CLOSE_SYSCALL_ID) {
|
||||
retval = rpc_data->rpc_response->sys_call_args.int_field1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
52
ThirdParty/sw_services/xilopenamp/src/rpmsg_retarget.h
vendored
Normal file
52
ThirdParty/sw_services/xilopenamp/src/rpmsg_retarget.h
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include "open_amp.h"
|
||||
/* RPC response buffer size */
|
||||
#define RPC_BUFF_SIZE 512
|
||||
|
||||
/* System call definitions */
|
||||
#define OPEN_SYSCALL_ID 1
|
||||
#define CLOSE_SYSCALL_ID 2
|
||||
#define WRITE_SYSCALL_ID 3
|
||||
#define READ_SYSCALL_ID 4
|
||||
#define ACK_STATUS_ID 5
|
||||
#define TERM_SYSCALL_ID 6
|
||||
|
||||
|
||||
#define FILE_NAME_LEN 50
|
||||
|
||||
/* Proxy device endpoint ID */
|
||||
#define PROXY_ENDPOINT 127
|
||||
|
||||
typedef void (*rpc_shutdown_cb)(struct rpmsg_channel *);
|
||||
|
||||
struct _rpc_data
|
||||
{
|
||||
struct rpmsg_channel* rpmsg_chnl;
|
||||
struct rpmsg_endpoint* rp_ept;
|
||||
void* rpc_lock;
|
||||
void* sync_lock;
|
||||
struct _sys_rpc* rpc;
|
||||
struct _sys_rpc* rpc_response;
|
||||
rpc_shutdown_cb shutdown_cb;
|
||||
};
|
||||
|
||||
struct _sys_call_args
|
||||
{
|
||||
int int_field1;
|
||||
int int_field2;
|
||||
unsigned int data_len;
|
||||
char data[0];
|
||||
};
|
||||
|
||||
/* System call rpc data structure */
|
||||
struct _sys_rpc
|
||||
{
|
||||
unsigned int id;
|
||||
struct _sys_call_args sys_call_args;
|
||||
};
|
||||
|
||||
|
||||
void debug_print(char* str, int len);
|
||||
|
||||
/* API prototypes */
|
||||
int rpmsg_retarget_init(struct rpmsg_channel *rp_chnl, rpc_shutdown_cb cb);
|
||||
int rpmsg_retarget_deinit(struct rpmsg_channel *rp_chnl);
|
234
ThirdParty/sw_services/xilopenamp/src/rsc_table_parser.c
vendored
Normal file
234
ThirdParty/sw_services/xilopenamp/src/rsc_table_parser.c
vendored
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
#include "rsc_table_parser.h"
|
||||
|
||||
/* Resources handler */
|
||||
rsc_handler rsc_handler_table[] =
|
||||
{
|
||||
handle_carve_out_rsc,
|
||||
handle_trace_rsc,
|
||||
handle_dev_mem_rsc,
|
||||
handle_vdev_rsc,
|
||||
handle_mmu_rsc
|
||||
};
|
||||
|
||||
/**
|
||||
* handle_rsc_table
|
||||
*
|
||||
* This function parses resource table.
|
||||
*
|
||||
* @param rproc - pointer to remote remote_proc
|
||||
* @param rsc_table - resource table to parse
|
||||
* @param size - size of rsc table
|
||||
*
|
||||
* @returns - execution status
|
||||
*
|
||||
*/
|
||||
int handle_rsc_table(struct remote_proc *rproc, struct resource_table *rsc_table,
|
||||
int size) {
|
||||
|
||||
unsigned char *rsc_start;
|
||||
unsigned int *rsc_offset;
|
||||
unsigned int rsc_type;
|
||||
int idx, status = 0;
|
||||
|
||||
/* Validate rsc table header fields*/
|
||||
|
||||
/* Minimum rsc table size */
|
||||
if (sizeof(struct resource_table) > size) {
|
||||
return (RPROC_ERR_RSC_TAB_TRUNC);
|
||||
}
|
||||
|
||||
/* Supported version */
|
||||
if (rsc_table->ver != RSC_TAB_SUPPORTED_VERSION) {
|
||||
return (RPROC_ERR_RSC_TAB_VER);
|
||||
}
|
||||
|
||||
/* Offset array */
|
||||
if (sizeof(struct resource_table)
|
||||
+ rsc_table->num * sizeof(rsc_table->offset[0]) > size) {
|
||||
return (RPROC_ERR_RSC_TAB_TRUNC);
|
||||
}
|
||||
|
||||
/* Reserved fields - must be zero */
|
||||
if ((rsc_table->reserved[0] != 0 || rsc_table->reserved[1]) != 0) {
|
||||
return RPROC_ERR_RSC_TAB_RSVD;
|
||||
}
|
||||
|
||||
rsc_start = (unsigned char *) rsc_table;
|
||||
|
||||
/* Loop through the offset array and parse each resource entry */
|
||||
for (idx = 0; idx < rsc_table->num; idx++) {
|
||||
rsc_offset = (unsigned int *) (rsc_start + rsc_table->offset[idx]);
|
||||
rsc_type = *rsc_offset;
|
||||
status = rsc_handler_table[rsc_type](rproc, (void *) rsc_offset);
|
||||
if (status != RPROC_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle_carve_out_rsc
|
||||
*
|
||||
* Carveout resource handler.
|
||||
*
|
||||
* @param rproc - pointer to remote remote_proc
|
||||
* @param rsc - pointer to carveout resource
|
||||
*
|
||||
* @returns - execution status
|
||||
*
|
||||
*/
|
||||
int handle_carve_out_rsc(struct remote_proc *rproc, void *rsc) {
|
||||
struct fw_rsc_carveout *carve_rsc = (struct fw_rsc_carveout *) rsc;
|
||||
|
||||
/* Validate resource fields */
|
||||
if (!carve_rsc) {
|
||||
return RPROC_ERR_RSC_TAB_NP;
|
||||
}
|
||||
|
||||
if (carve_rsc->reserved) {
|
||||
return RPROC_ERR_RSC_TAB_RSVD;
|
||||
}
|
||||
|
||||
if (rproc->role == RPROC_MASTER) {
|
||||
/* Map memory region for loading the image */
|
||||
env_map_memory(carve_rsc->da, carve_rsc->da, carve_rsc->len,
|
||||
(SHARED_MEM | UNCACHED));
|
||||
}
|
||||
|
||||
return RPROC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle_trace_rsc
|
||||
*
|
||||
* Trace resource handler.
|
||||
*
|
||||
* @param rproc - pointer to remote remote_proc
|
||||
* @param rsc - pointer to trace resource
|
||||
*
|
||||
* @returns - execution status
|
||||
*
|
||||
*/
|
||||
int handle_trace_rsc(struct remote_proc *rproc, void *rsc) {
|
||||
return RPROC_ERR_RSC_TAB_NS;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle_dev_mem_rsc
|
||||
*
|
||||
* Device memory resource handler.
|
||||
*
|
||||
* @param rproc - pointer to remote remote_proc
|
||||
* @param rsc - pointer to device memory resource
|
||||
*
|
||||
* @returns - execution status
|
||||
*
|
||||
*/
|
||||
int handle_dev_mem_rsc(struct remote_proc *rproc, void *rsc) {
|
||||
return RPROC_ERR_RSC_TAB_NS;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle_vdev_rsc
|
||||
*
|
||||
* Virtio device resource handler
|
||||
*
|
||||
* @param rproc - pointer to remote remote_proc
|
||||
* @param rsc - pointer to virtio device resource
|
||||
*
|
||||
* @returns - execution status
|
||||
*
|
||||
*/
|
||||
int handle_vdev_rsc(struct remote_proc *rproc, void *rsc) {
|
||||
|
||||
struct fw_rsc_vdev *vdev_rsc = (struct fw_rsc_vdev *) rsc;
|
||||
struct fw_rsc_vdev_vring *vring;
|
||||
struct proc_vdev *vdev;
|
||||
struct proc_vring *vring_table;
|
||||
int idx;
|
||||
|
||||
if (!vdev_rsc) {
|
||||
return RPROC_ERR_RSC_TAB_NP;
|
||||
}
|
||||
|
||||
/* Maximum supported vrings per Virtio device */
|
||||
if (vdev_rsc->num_of_vrings > RSC_TAB_MAX_VRINGS) {
|
||||
return RPROC_ERR_RSC_TAB_VDEV_NRINGS;
|
||||
}
|
||||
|
||||
/* Reserved fields - must be zero */
|
||||
if (vdev_rsc->reserved[0] || vdev_rsc->reserved[1]) {
|
||||
return RPROC_ERR_RSC_TAB_RSVD;
|
||||
}
|
||||
|
||||
/* Get the Virtio device from HIL proc */
|
||||
vdev = hil_get_vdev_info(rproc->proc);
|
||||
|
||||
/* Initialize HIL Virtio device resources */
|
||||
vdev->num_vrings = vdev_rsc->num_of_vrings;
|
||||
vdev->dfeatures = vdev_rsc->dfeatures;
|
||||
vdev->gfeatures = vdev_rsc->gfeatures;
|
||||
vring_table = &vdev->vring_info[0];
|
||||
|
||||
for (idx = 0; idx < vdev_rsc->num_of_vrings; idx++) {
|
||||
vring = &vdev_rsc->vring[idx];
|
||||
|
||||
/* Initialize HIL vring resources */
|
||||
vring_table[idx].phy_addr = (void *) vring->da;
|
||||
vring_table[idx].num_descs = vring->num;
|
||||
vring_table[idx].align = vring->align;
|
||||
|
||||
/* Enable access to vring memory regions */
|
||||
env_map_memory(vring->da, vring->da,
|
||||
vring_size(vring->num, vring->align),
|
||||
(SHARED_MEM | UNCACHED));
|
||||
}
|
||||
|
||||
return RPROC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle_mmu_rsc
|
||||
*
|
||||
* This function parses mmu resource , requested by the peripheral.
|
||||
*
|
||||
* @param rproc - pointer to remote remote_proc
|
||||
* @param rsc - pointer to mmu resource
|
||||
*
|
||||
* @returns - execution status
|
||||
*
|
||||
*/
|
||||
int handle_mmu_rsc(struct remote_proc *rproc, void *rsc) {
|
||||
return RPROC_ERR_RSC_TAB_NS;
|
||||
}
|
53
ThirdParty/sw_services/xilopenamp/src/rsc_table_parser.h
vendored
Normal file
53
ThirdParty/sw_services/xilopenamp/src/rsc_table_parser.h
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
#ifndef RSC_TABLE_PARSER_H
|
||||
#define RSC_TABLE_PARSER_H
|
||||
|
||||
#include "remoteproc.h"
|
||||
#include "env.h"
|
||||
#include "hil.h"
|
||||
|
||||
#define RSC_TAB_SUPPORTED_VERSION 1
|
||||
#define RSC_TAB_HEADER_SIZE 12
|
||||
#define RSC_TAB_MAX_VRINGS 2
|
||||
|
||||
/* Standard control request handling. */
|
||||
typedef int (*rsc_handler)(struct remote_proc *rproc, void * rsc);
|
||||
|
||||
/* Function prototypes */
|
||||
int handle_rsc_table(struct remote_proc *rproc, struct resource_table *rsc_table,
|
||||
int len);
|
||||
int handle_carve_out_rsc(struct remote_proc *rproc, void *rsc);
|
||||
int handle_trace_rsc(struct remote_proc *rproc, void *rsc);
|
||||
int handle_dev_mem_rsc(struct remote_proc *rproc, void *rsc);
|
||||
int handle_vdev_rsc(struct remote_proc *rproc, void *rsc);
|
||||
int handle_mmu_rsc(struct remote_proc *rproc, void *rsc);
|
||||
|
||||
#endif /* RSC_TABLE_PARSER_H */
|
230
ThirdParty/sw_services/xilopenamp/src/sh_mem.c
vendored
Normal file
230
ThirdParty/sw_services/xilopenamp/src/sh_mem.c
vendored
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* sh_mem.c
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* OpenAMP stack.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Source file for fixed buffer size memory management service. Currently
|
||||
* it is only being used to manage shared memory.
|
||||
*
|
||||
**************************************************************************/
|
||||
#include "sh_mem.h"
|
||||
|
||||
/**
|
||||
* sh_mem_create_pool
|
||||
*
|
||||
* Creates new memory pool with the given parameters.
|
||||
*
|
||||
* @param start_addr - start address of the memory region
|
||||
* @param size - size of the memory
|
||||
* @param buff_size - fixed buffer size
|
||||
*
|
||||
* @return - pointer to memory pool
|
||||
*
|
||||
*/
|
||||
struct sh_mem_pool * sh_mem_create_pool(void *start_addr, unsigned int size,
|
||||
unsigned int buff_size) {
|
||||
struct sh_mem_pool *mem_pool;
|
||||
int status, pool_size;
|
||||
int num_buffs, bmp_size;
|
||||
|
||||
if (!start_addr || !size || !buff_size)
|
||||
return NULL;
|
||||
|
||||
/* Word align the buffer size */
|
||||
buff_size = WORD_ALIGN(buff_size);
|
||||
|
||||
/* Get number of buffers. */
|
||||
num_buffs = (size / buff_size) + ((size % buff_size) == 0 ? 0 : 1);
|
||||
|
||||
/*
|
||||
* Size of the bitmap required to maintain buffers info. One word(32 bit) can
|
||||
* keep track of 32 buffers.
|
||||
*/
|
||||
bmp_size = (num_buffs / BITMAP_WORD_SIZE)
|
||||
+ ((num_buffs % BITMAP_WORD_SIZE) == 0 ? 0 : 1);
|
||||
|
||||
/* Total size required for pool control block. */
|
||||
pool_size = sizeof(struct sh_mem_pool) + WORD_SIZE * bmp_size;
|
||||
|
||||
/* Create pool control block. */
|
||||
mem_pool = env_allocate_memory(pool_size);
|
||||
|
||||
if (mem_pool) {
|
||||
/* Initialize pool parameters */
|
||||
env_memset(mem_pool, 0x00, pool_size);
|
||||
status = env_create_mutex(&mem_pool->lock , 1);
|
||||
if (status){
|
||||
env_free_memory(mem_pool);
|
||||
return NULL;
|
||||
}
|
||||
mem_pool->start_addr = start_addr;
|
||||
mem_pool->buff_size = buff_size;
|
||||
mem_pool->bmp_size = bmp_size;
|
||||
mem_pool->total_buffs = num_buffs;
|
||||
}
|
||||
|
||||
return mem_pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* sh_mem_get_buffer
|
||||
*
|
||||
* Allocates fixed size buffer from the given memory pool.
|
||||
*
|
||||
* @param pool - pointer to memory pool
|
||||
*
|
||||
* @return - pointer to allocated buffer
|
||||
*
|
||||
*/
|
||||
void * sh_mem_get_buffer(struct sh_mem_pool *pool) {
|
||||
void *buff = NULL;
|
||||
int idx, bit_idx;
|
||||
|
||||
if (!pool)
|
||||
return NULL;
|
||||
|
||||
env_lock_mutex(pool->lock);
|
||||
|
||||
if (pool->used_buffs >= pool->total_buffs) {
|
||||
env_unlock_mutex(pool->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < pool->bmp_size; idx++) {
|
||||
/*
|
||||
* Find the first 0 bit in the buffers bitmap. The 0th bit
|
||||
* represents a free buffer.
|
||||
*/
|
||||
bit_idx = get_first_zero_bit(pool->bitmap[idx]);
|
||||
if (bit_idx < 32) {
|
||||
/* Set bit to mark it as consumed. */
|
||||
pool->bitmap[idx] |= (1 << bit_idx);
|
||||
buff = (char *) pool->start_addr +
|
||||
pool->buff_size * (idx * BITMAP_WORD_SIZE + bit_idx);
|
||||
pool->used_buffs++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
env_unlock_mutex(pool->lock);
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
/**
|
||||
* sh_mem_free_buffer
|
||||
*
|
||||
* Frees the given buffer.
|
||||
*
|
||||
* @param pool - pointer to memory pool
|
||||
* @param buff - pointer to buffer
|
||||
*
|
||||
* @return - none
|
||||
*/
|
||||
void sh_mem_free_buffer(void *buff, struct sh_mem_pool *pool) {
|
||||
unsigned long *bitmask;
|
||||
int bmp_idx, bit_idx, buff_idx;
|
||||
|
||||
if (!pool || !buff)
|
||||
return;
|
||||
|
||||
/* Acquire the pool lock */
|
||||
env_lock_mutex(pool->lock);
|
||||
|
||||
/* Map the buffer address to its index. */
|
||||
buff_idx = ((char *) buff - (char*) pool->start_addr) / pool->buff_size;
|
||||
|
||||
/* Translate the buffer index to bitmap index. */
|
||||
bmp_idx = buff_idx / BITMAP_WORD_SIZE;
|
||||
bit_idx = buff_idx % BITMAP_WORD_SIZE;
|
||||
bitmask = &pool->bitmap[bmp_idx];
|
||||
|
||||
/* Mark the buffer as free */
|
||||
*bitmask ^= (1 << bit_idx);
|
||||
|
||||
pool->used_buffs--;
|
||||
|
||||
/* Release the pool lock. */
|
||||
env_unlock_mutex(pool->lock);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sh_mem_delete_pool
|
||||
*
|
||||
* Deletes the given memory pool.
|
||||
*
|
||||
* @param pool - pointer to memory pool
|
||||
*
|
||||
* @return - none
|
||||
*/
|
||||
void sh_mem_delete_pool(struct sh_mem_pool *pool) {
|
||||
|
||||
if (pool) {
|
||||
env_delete_mutex(pool->lock);
|
||||
env_free_memory(pool);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get_first_zero_bit
|
||||
*
|
||||
* Provides position of first 0 bit in a 32 bit value
|
||||
*
|
||||
* @param value - given value
|
||||
*
|
||||
* @return - 0th bit position
|
||||
*/
|
||||
unsigned int get_first_zero_bit(unsigned long value) {
|
||||
unsigned int idx;
|
||||
unsigned int tmp32;
|
||||
|
||||
/* Invert value */
|
||||
value = ~value;
|
||||
|
||||
/* (~value) & (2's complement of value) */
|
||||
value = (value & (-value)) - 1;
|
||||
|
||||
/* log2(value) */
|
||||
|
||||
tmp32 = value - ((value >> 1) & 033333333333)
|
||||
- ((value >> 2) & 011111111111);
|
||||
|
||||
idx = ((tmp32 + (tmp32 >> 3)) & 030707070707) % 63;
|
||||
|
||||
return idx;
|
||||
}
|
89
ThirdParty/sw_services/xilopenamp/src/sh_mem.h
vendored
Normal file
89
ThirdParty/sw_services/xilopenamp/src/sh_mem.h
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of Mentor Graphics Corporation 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.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* sh_mem.c
|
||||
*
|
||||
* COMPONENT
|
||||
*
|
||||
* IPC Stack for uAMP systems.
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Header file for fixed buffer size memory management service. Currently
|
||||
* it is being used to manage shared memory.
|
||||
*
|
||||
**************************************************************************/
|
||||
#ifndef SH_MEM_H_
|
||||
#define SH_MEM_H_
|
||||
|
||||
#include "env.h"
|
||||
|
||||
|
||||
/* Macros */
|
||||
#define BITMAP_WORD_SIZE 32
|
||||
#define WORD_SIZE sizeof(unsigned long)
|
||||
#define WORD_ALIGN(a) (((a) & (WORD_SIZE-1)) != 0)? \
|
||||
(((a) & (~(WORD_SIZE-1))) + 4):(a)
|
||||
/*
|
||||
* This structure represents a shared memory pool.
|
||||
*
|
||||
* @start_addr - start address of shared memory region
|
||||
* @lock - lock to ensure exclusive access
|
||||
* @size - size of shared memory*
|
||||
* @buff_size - size of each buffer
|
||||
* @total_buffs - total number of buffers in shared memory region
|
||||
* @used_buffs - number of used buffers
|
||||
* @bmp_size - size of bitmap array
|
||||
* @bitmap - array to keep record of free and used blocks
|
||||
*
|
||||
*/
|
||||
|
||||
struct sh_mem_pool {
|
||||
void *start_addr;
|
||||
LOCK *lock;
|
||||
int size;
|
||||
int buff_size;
|
||||
int total_buffs;
|
||||
int used_buffs;
|
||||
int bmp_size;
|
||||
unsigned long bitmap[0];
|
||||
};
|
||||
|
||||
/* APIs */
|
||||
struct sh_mem_pool *sh_mem_create_pool(void *start_addr, unsigned int size,
|
||||
unsigned int buff_size);
|
||||
void sh_mem_delete_pool(struct sh_mem_pool *pool);
|
||||
void *sh_mem_get_buffer(struct sh_mem_pool *pool);
|
||||
void sh_mem_free_buffer(void *ptr, struct sh_mem_pool *pool);
|
||||
unsigned int get_first_zero_bit(unsigned long value);
|
||||
|
||||
#endif /* SH_MEM_H_ */
|
95
ThirdParty/sw_services/xilopenamp/src/virtio.c
vendored
Normal file
95
ThirdParty/sw_services/xilopenamp/src/virtio.c
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*-
|
||||
* Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
#include "virtio.h"
|
||||
|
||||
static const char *virtio_feature_name(unsigned long feature, struct virtio_feature_desc *);
|
||||
|
||||
//TODO : This structure may change depending on the types of devices we support.
|
||||
static struct virtio_ident {
|
||||
unsigned short devid;
|
||||
const char *name;
|
||||
} virtio_ident_table[] = {
|
||||
{ VIRTIO_ID_NETWORK, "Network" },
|
||||
{ VIRTIO_ID_BLOCK, "Block" },
|
||||
{ VIRTIO_ID_CONSOLE, "Console" },
|
||||
{ VIRTIO_ID_ENTROPY, "Entropy" },
|
||||
{ VIRTIO_ID_BALLOON, "Balloon" },
|
||||
{ VIRTIO_ID_IOMEMORY, "IOMemory" },
|
||||
{ VIRTIO_ID_SCSI, "SCSI" },
|
||||
{ VIRTIO_ID_9P, "9P Transport" },
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* Device independent features. */
|
||||
static struct virtio_feature_desc virtio_common_feature_desc[] = {
|
||||
{ VIRTIO_F_NOTIFY_ON_EMPTY, "NotifyOnEmpty" },
|
||||
{ VIRTIO_RING_F_INDIRECT_DESC, "RingIndirect" },
|
||||
{ VIRTIO_RING_F_EVENT_IDX, "EventIdx" },
|
||||
{ VIRTIO_F_BAD_FEATURE, "BadFeature" },
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const char *
|
||||
virtio_dev_name(unsigned short devid)
|
||||
{
|
||||
struct virtio_ident *ident;
|
||||
|
||||
for (ident = virtio_ident_table; ident->name != NULL; ident++) {
|
||||
if (ident->devid == devid)
|
||||
return (ident->name);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static const char *
|
||||
virtio_feature_name(unsigned long val, struct virtio_feature_desc *desc)
|
||||
{
|
||||
int i, j;
|
||||
struct virtio_feature_desc *descs[2] = { desc,
|
||||
virtio_common_feature_desc };
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (descs[i] == NULL)
|
||||
continue;
|
||||
|
||||
for (j = 0; descs[i][j].vfd_val != 0; j++) {
|
||||
if (val == descs[i][j].vfd_val)
|
||||
return (descs[i][j].vfd_str);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void virtio_describe(struct virtio_device *dev, const char *msg,
|
||||
uint32_t features, struct virtio_feature_desc *desc)
|
||||
{
|
||||
// TODO: Not used currently - keeping it for future use
|
||||
virtio_feature_name(0,desc);
|
||||
}
|
151
ThirdParty/sw_services/xilopenamp/src/virtio.h
vendored
Normal file
151
ThirdParty/sw_services/xilopenamp/src/virtio.h
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*-
|
||||
* This header is BSD licensed so anyone can use the definitions to implement
|
||||
* compatible drivers/servers.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of IBM 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 IBM 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _VIRTIO_H_
|
||||
#define _VIRTIO_H_
|
||||
|
||||
#include "virtqueue.h"
|
||||
|
||||
/* VirtIO device IDs. */
|
||||
#define VIRTIO_ID_NETWORK 0x01
|
||||
#define VIRTIO_ID_BLOCK 0x02
|
||||
#define VIRTIO_ID_CONSOLE 0x03
|
||||
#define VIRTIO_ID_ENTROPY 0x04
|
||||
#define VIRTIO_ID_BALLOON 0x05
|
||||
#define VIRTIO_ID_IOMEMORY 0x06
|
||||
#define VIRTIO_ID_RPMSG 0x07 /* virtio remote remote_proc messaging */
|
||||
#define VIRTIO_ID_SCSI 0x08
|
||||
#define VIRTIO_ID_9P 0x09
|
||||
|
||||
/* Status byte for guest to report progress. */
|
||||
#define VIRTIO_CONFIG_STATUS_RESET 0x00
|
||||
#define VIRTIO_CONFIG_STATUS_ACK 0x01
|
||||
#define VIRTIO_CONFIG_STATUS_DRIVER 0x02
|
||||
#define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04
|
||||
#define VIRTIO_CONFIG_STATUS_FAILED 0x80
|
||||
|
||||
/*
|
||||
* Generate interrupt when the virtqueue ring is
|
||||
* completely used, even if we've suppressed them.
|
||||
*/
|
||||
#define VIRTIO_F_NOTIFY_ON_EMPTY (1 << 24)
|
||||
|
||||
/*
|
||||
* The guest should never negotiate this feature; it
|
||||
* is used to detect faulty drivers.
|
||||
*/
|
||||
#define VIRTIO_F_BAD_FEATURE (1 << 30)
|
||||
|
||||
/*
|
||||
* Some VirtIO feature bits (currently bits 28 through 31) are
|
||||
* reserved for the transport being used (eg. virtio_ring), the
|
||||
* rest are per-device feature bits.
|
||||
*/
|
||||
#define VIRTIO_TRANSPORT_F_START 28
|
||||
#define VIRTIO_TRANSPORT_F_END 32
|
||||
|
||||
typedef struct _virtio_dispatch_ virtio_dispatch;
|
||||
|
||||
struct virtio_feature_desc {
|
||||
uint32_t vfd_val;
|
||||
const char *vfd_str;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure definition for virtio devices for use by the
|
||||
* applications/drivers
|
||||
*
|
||||
*/
|
||||
|
||||
struct virtio_device {
|
||||
/*
|
||||
* Since there is no generic device structure so
|
||||
* keep its type as void. The driver layer will take
|
||||
* care of it.
|
||||
*/
|
||||
void *device;
|
||||
|
||||
/* Device name */
|
||||
char *name;
|
||||
|
||||
/* List of virtqueues encapsulated by virtio device. */
|
||||
//TODO : Need to implement a list service for ipc stack.
|
||||
void *vq_list;
|
||||
|
||||
/* Virtio device specific features */
|
||||
uint32_t features;
|
||||
|
||||
/* Virtio dispatch table */
|
||||
virtio_dispatch *func;
|
||||
|
||||
/*
|
||||
* Pointer to hold some private data, useful
|
||||
* in callbacks.
|
||||
*/
|
||||
void *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper functions.
|
||||
*/
|
||||
const char *virtio_dev_name(uint16_t devid);
|
||||
void virtio_describe(struct virtio_device *dev, const char *msg,
|
||||
uint32_t features, struct virtio_feature_desc *feature_desc);
|
||||
|
||||
/*
|
||||
* Functions for virtio device configuration as defined in Rusty Russell's paper.
|
||||
* Drivers are expected to implement these functions in their respective codes.
|
||||
*
|
||||
*/
|
||||
|
||||
struct _virtio_dispatch_ {
|
||||
int (*create_virtqueues)(struct virtio_device *dev, int flags, int nvqs,
|
||||
const char *names[], vq_callback *callbacks[],
|
||||
struct virtqueue *vqs[]);
|
||||
uint8_t (*get_status)(struct virtio_device *dev);
|
||||
void (*set_status)(struct virtio_device *dev, uint8_t status);
|
||||
uint32_t (*get_features)(struct virtio_device *dev);
|
||||
void (*set_features)(struct virtio_device *dev, uint32_t feature);
|
||||
uint32_t (*negotiate_features)(struct virtio_device *dev, uint32_t features);
|
||||
|
||||
/*
|
||||
* Read/write a variable amount from the device specific (ie, network)
|
||||
* configuration region. This region is encoded in the same endian as
|
||||
* the guest.
|
||||
*/
|
||||
void (*read_config)(struct virtio_device *dev, uint32_t offset, void *dst,
|
||||
int length);
|
||||
void (*write_config)(struct virtio_device *dev, uint32_t offset, void *src,
|
||||
int length);
|
||||
void (*reset_device)(struct virtio_device *dev);
|
||||
|
||||
};
|
||||
|
||||
#endif /* _VIRTIO_H_ */
|
165
ThirdParty/sw_services/xilopenamp/src/virtio_ring.h
vendored
Normal file
165
ThirdParty/sw_services/xilopenamp/src/virtio_ring.h
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*-
|
||||
* Copyright Rusty Russell IBM Corporation 2007.
|
||||
*
|
||||
* This header is BSD licensed so anyone can use the definitions to implement
|
||||
* compatible drivers/servers.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of IBM 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 IBM 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef VIRTIO_RING_H
|
||||
#define VIRTIO_RING_H
|
||||
|
||||
/* This marks a buffer as continuing via the next field. */
|
||||
#define VRING_DESC_F_NEXT 1
|
||||
/* This marks a buffer as write-only (otherwise read-only). */
|
||||
#define VRING_DESC_F_WRITE 2
|
||||
/* This means the buffer contains a list of buffer descriptors. */
|
||||
#define VRING_DESC_F_INDIRECT 4
|
||||
|
||||
/* The Host uses this in used->flags to advise the Guest: don't kick me
|
||||
* when you add a buffer. It's unreliable, so it's simply an
|
||||
* optimization. Guest will still kick if it's out of buffers. */
|
||||
#define VRING_USED_F_NO_NOTIFY 1
|
||||
/* The Guest uses this in avail->flags to advise the Host: don't
|
||||
* interrupt me when you consume a buffer. It's unreliable, so it's
|
||||
* simply an optimization. */
|
||||
#define VRING_AVAIL_F_NO_INTERRUPT 1
|
||||
|
||||
/* VirtIO ring descriptors: 16 bytes.
|
||||
* These can chain together via "next". */
|
||||
struct vring_desc {
|
||||
/* Address (guest-physical). */
|
||||
uint64_t addr;
|
||||
/* Length. */
|
||||
uint32_t len;
|
||||
/* The flags as indicated above. */
|
||||
uint16_t flags;
|
||||
/* We chain unused descriptors via this, too. */
|
||||
uint16_t next;
|
||||
};
|
||||
|
||||
struct vring_avail {
|
||||
uint16_t flags;
|
||||
uint16_t idx;
|
||||
uint16_t ring[0];
|
||||
};
|
||||
|
||||
/* uint32_t is used here for ids for padding reasons. */
|
||||
struct vring_used_elem {
|
||||
/* Index of start of used descriptor chain. */
|
||||
uint32_t id;
|
||||
/* Total length of the descriptor chain which was written to. */
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
struct vring_used {
|
||||
uint16_t flags;
|
||||
uint16_t idx;
|
||||
struct vring_used_elem ring[0];
|
||||
};
|
||||
|
||||
struct vring {
|
||||
unsigned int num;
|
||||
|
||||
struct vring_desc *desc;
|
||||
struct vring_avail *avail;
|
||||
struct vring_used *used;
|
||||
};
|
||||
|
||||
/* The standard layout for the ring is a continuous chunk of memory which
|
||||
* looks like this. We assume num is a power of 2.
|
||||
*
|
||||
* struct vring {
|
||||
* // The actual descriptors (16 bytes each)
|
||||
* struct vring_desc desc[num];
|
||||
*
|
||||
* // A ring of available descriptor heads with free-running index.
|
||||
* __u16 avail_flags;
|
||||
* __u16 avail_idx;
|
||||
* __u16 available[num];
|
||||
* __u16 used_event_idx;
|
||||
*
|
||||
* // Padding to the next align boundary.
|
||||
* char pad[];
|
||||
*
|
||||
* // A ring of used descriptor heads with free-running index.
|
||||
* __u16 used_flags;
|
||||
* __u16 used_idx;
|
||||
* struct vring_used_elem used[num];
|
||||
* __u16 avail_event_idx;
|
||||
* };
|
||||
*
|
||||
* NOTE: for VirtIO PCI, align is 4096.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We publish the used event index at the end of the available ring, and vice
|
||||
* versa. They are at the end for backwards compatibility.
|
||||
*/
|
||||
#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
|
||||
#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num])
|
||||
|
||||
static inline int
|
||||
vring_size(unsigned int num, unsigned long align)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = num * sizeof(struct vring_desc);
|
||||
size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)) +
|
||||
sizeof(uint16_t);
|
||||
size = (size + align - 1) & ~(align - 1);
|
||||
size += sizeof(struct vring_used) +
|
||||
(num * sizeof(struct vring_used_elem)) + sizeof(uint16_t);
|
||||
return (size);
|
||||
}
|
||||
|
||||
static inline void
|
||||
vring_init(struct vring *vr, unsigned int num, uint8_t *p,
|
||||
unsigned long align)
|
||||
{
|
||||
vr->num = num;
|
||||
vr->desc = (struct vring_desc *) p;
|
||||
vr->avail = (struct vring_avail *) (p +
|
||||
num * sizeof(struct vring_desc));
|
||||
vr->used = (void *)
|
||||
(((unsigned long) &vr->avail->ring[num] + align-1) & ~(align-1));
|
||||
}
|
||||
|
||||
/*
|
||||
* The following is used with VIRTIO_RING_F_EVENT_IDX.
|
||||
*
|
||||
* Assuming a given event_idx value from the other size, if we have
|
||||
* just incremented index from old to new_idx, should we trigger an
|
||||
* event?
|
||||
*/
|
||||
static inline int
|
||||
vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
|
||||
{
|
||||
|
||||
return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
|
||||
}
|
||||
#endif /* VIRTIO_RING_H */
|
691
ThirdParty/sw_services/xilopenamp/src/virtqueue.c
vendored
Normal file
691
ThirdParty/sw_services/xilopenamp/src/virtqueue.c
vendored
Normal file
|
@ -0,0 +1,691 @@
|
|||
/*-
|
||||
* Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include "virtqueue.h"
|
||||
|
||||
/* Prototype for internal functions. */
|
||||
static void vq_ring_init(struct virtqueue *);
|
||||
static void vq_ring_update_avail(struct virtqueue *, uint16_t);
|
||||
static uint16_t vq_ring_add_buffer(struct virtqueue *, struct vring_desc *,
|
||||
uint16_t, struct llist *, int, int);
|
||||
static int vq_ring_enable_interrupt(struct virtqueue *, uint16_t);
|
||||
static void vq_ring_free_chain(struct virtqueue *, uint16_t);
|
||||
static int vq_ring_must_notify_host(struct virtqueue *vq);
|
||||
static void vq_ring_notify_host(struct virtqueue *vq);
|
||||
static int virtqueue_nused(struct virtqueue *vq);
|
||||
|
||||
/**
|
||||
* virtqueue_create - Creates new VirtIO queue
|
||||
*
|
||||
* @param device - Pointer to VirtIO device
|
||||
* @param id - VirtIO queue ID , must be unique
|
||||
* @param name - Name of VirtIO queue
|
||||
* @param ring - Pointer to vring_alloc_info control block
|
||||
* @param callback - Pointer to callback function, invoked
|
||||
* when message is available on VirtIO queue
|
||||
* @param notify - Pointer to notify function, used to notify
|
||||
* other side that there is job available for it
|
||||
* @param v_queue - Created VirtIO queue.
|
||||
*
|
||||
* @return - Function status
|
||||
*/
|
||||
int virtqueue_create(struct virtio_device *virt_dev, unsigned short id, char *name,
|
||||
struct vring_alloc_info *ring, void (*callback)(struct virtqueue *vq),
|
||||
void (*notify)(struct virtqueue *vq),
|
||||
struct virtqueue **v_queue) {
|
||||
|
||||
struct virtqueue *vq = VQ_NULL;
|
||||
int status = VQUEUE_SUCCESS;
|
||||
uint32_t vq_size = 0;
|
||||
|
||||
VQ_PARAM_CHK(ring == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
|
||||
VQ_PARAM_CHK(ring->num_descs == 0, status, ERROR_VQUEUE_INVLD_PARAM);
|
||||
VQ_PARAM_CHK(ring->num_descs & (ring->num_descs - 1), status,
|
||||
ERROR_VRING_ALIGN);
|
||||
|
||||
//TODO : Error check for indirect buffer addition
|
||||
|
||||
if (status == VQUEUE_SUCCESS) {
|
||||
|
||||
vq_size = sizeof(struct virtqueue)
|
||||
+ (ring->num_descs) * sizeof(struct vq_desc_extra);
|
||||
vq = (struct virtqueue *) env_allocate_memory(vq_size);
|
||||
|
||||
if (vq == VQ_NULL) {
|
||||
return (ERROR_NO_MEM);
|
||||
}
|
||||
|
||||
env_memset(vq, 0x00, vq_size);
|
||||
|
||||
vq->vq_dev = virt_dev;
|
||||
env_strncpy(vq->vq_name, name, VIRTQUEUE_MAX_NAME_SZ);
|
||||
vq->vq_queue_index = id;
|
||||
vq->vq_alignment = ring->align;
|
||||
vq->vq_nentries = ring->num_descs;
|
||||
vq->vq_free_cnt = vq->vq_nentries;
|
||||
vq->callback = callback;
|
||||
vq->notify = notify;
|
||||
|
||||
//TODO : Whether we want to support indirect addition or not.
|
||||
vq->vq_ring_size = vring_size(ring->num_descs, ring->align);
|
||||
vq->vq_ring_mem = (void *) ring->phy_addr;
|
||||
|
||||
/* Initialize vring control block in virtqueue. */
|
||||
vq_ring_init(vq);
|
||||
|
||||
/* Disable callbacks - will be enabled by the application
|
||||
* once initialization is completed.
|
||||
*/
|
||||
virtqueue_disable_cb(vq);
|
||||
|
||||
*v_queue = vq;
|
||||
|
||||
//TODO : Need to add cleanup in case of error used with the indirect buffer addition
|
||||
//TODO: do we need to save the new queue in db based on its id
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_add_buffer() - Enqueues new buffer in vring for consumption
|
||||
* by other side. Readable buffers are always
|
||||
* inserted before writable buffers
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block.
|
||||
* @param buffer - Pointer to buffer list
|
||||
* @param readable - Number of readable buffers
|
||||
* @param writable - Number of writable buffers
|
||||
* @param cookie - Pointer to hold call back data
|
||||
*
|
||||
* @return - Function status
|
||||
*/
|
||||
int virtqueue_add_buffer(struct virtqueue *vq, struct llist *buffer,
|
||||
int readable, int writable, void *cookie) {
|
||||
|
||||
struct vq_desc_extra *dxp = VQ_NULL;
|
||||
int status = VQUEUE_SUCCESS;
|
||||
uint16_t head_idx;
|
||||
uint16_t idx;
|
||||
int needed;
|
||||
|
||||
needed = readable + writable;
|
||||
|
||||
VQ_PARAM_CHK(vq == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
|
||||
VQ_PARAM_CHK(needed < 1, status, ERROR_VQUEUE_INVLD_PARAM);
|
||||
VQ_PARAM_CHK(vq->vq_free_cnt == 0, status, ERROR_VRING_FULL);
|
||||
|
||||
//TODO: Add parameters validation for indirect buffer addition
|
||||
|
||||
VQUEUE_BUSY(vq);
|
||||
|
||||
if (status == VQUEUE_SUCCESS) {
|
||||
|
||||
//TODO : Indirect buffer addition support
|
||||
|
||||
VQASSERT(vq, cookie != VQ_NULL, "enqueuing with no cookie");
|
||||
|
||||
head_idx = vq->vq_desc_head_idx;
|
||||
VQ_RING_ASSERT_VALID_IDX(vq, head_idx);
|
||||
dxp = &vq->vq_descx[head_idx];
|
||||
|
||||
VQASSERT(vq, (dxp->cookie == VQ_NULL), "cookie already exists for index");
|
||||
|
||||
dxp->cookie = cookie;
|
||||
dxp->ndescs = needed;
|
||||
|
||||
/* Enqueue buffer onto the ring. */
|
||||
idx = vq_ring_add_buffer(vq, vq->vq_ring.desc, head_idx, buffer,
|
||||
readable, writable);
|
||||
|
||||
vq->vq_desc_head_idx = idx;
|
||||
vq->vq_free_cnt -= needed;
|
||||
|
||||
if (vq->vq_free_cnt == 0)
|
||||
VQ_RING_ASSERT_CHAIN_TERM(vq);
|
||||
else
|
||||
VQ_RING_ASSERT_VALID_IDX(vq, idx);
|
||||
|
||||
/*
|
||||
* Update vring_avail control block fields so that other
|
||||
* side can get buffer using it.
|
||||
*/
|
||||
vq_ring_update_avail(vq, head_idx);
|
||||
}
|
||||
|
||||
VQUEUE_IDLE(vq);
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_add_single_buffer - Enqueues single buffer in vring
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
* @param cookie - Pointer to hold call back data
|
||||
* @param buffer_addr - Address of buffer
|
||||
* @param len - Length of buffer
|
||||
* @param writable - If buffer writable
|
||||
* @param has_next - If buffers for subsequent call are
|
||||
* to be chained
|
||||
*
|
||||
* @return - Function status
|
||||
*/
|
||||
int virtqueue_add_single_buffer(struct virtqueue *vq, void *cookie,
|
||||
void *buffer_addr, uint_t len, int writable, boolean has_next) {
|
||||
|
||||
struct vq_desc_extra *dxp;
|
||||
struct vring_desc *dp;
|
||||
uint16_t head_idx;
|
||||
uint16_t idx;
|
||||
int status = VQUEUE_SUCCESS;
|
||||
|
||||
VQ_PARAM_CHK(vq == VQ_NULL, status, ERROR_VQUEUE_INVLD_PARAM);
|
||||
VQ_PARAM_CHK(vq->vq_free_cnt == 0, status, ERROR_VRING_FULL);
|
||||
|
||||
VQUEUE_BUSY(vq);
|
||||
|
||||
if (status == VQUEUE_SUCCESS) {
|
||||
|
||||
VQASSERT(vq, cookie != VQ_NULL, "enqueuing with no cookie");
|
||||
|
||||
head_idx = vq->vq_desc_head_idx;
|
||||
dxp = &vq->vq_descx[head_idx];
|
||||
|
||||
dxp->cookie = cookie;
|
||||
dxp->ndescs = 1;
|
||||
idx = head_idx;
|
||||
|
||||
dp = &vq->vq_ring.desc[idx];
|
||||
dp->addr = env_map_vatopa(buffer_addr);
|
||||
dp->len = len;
|
||||
dp->flags = 0;
|
||||
idx = dp->next;
|
||||
|
||||
if (has_next)
|
||||
dp->flags |= VRING_DESC_F_NEXT;
|
||||
if (writable)
|
||||
dp->flags |= VRING_DESC_F_WRITE;
|
||||
|
||||
vq->vq_desc_head_idx = idx;
|
||||
vq->vq_free_cnt--;
|
||||
|
||||
if (vq->vq_free_cnt == 0)
|
||||
VQ_RING_ASSERT_CHAIN_TERM(vq);
|
||||
else
|
||||
VQ_RING_ASSERT_VALID_IDX(vq, idx);
|
||||
|
||||
vq_ring_update_avail(vq, head_idx);
|
||||
}
|
||||
|
||||
VQUEUE_IDLE(vq);
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_get_buffer - Returns used buffers from VirtIO queue
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
* @param len - Length of conumed buffer
|
||||
*
|
||||
* @return - Pointer to used buffer
|
||||
*/
|
||||
void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len) {
|
||||
struct vring_used_elem *uep;
|
||||
void *cookie;
|
||||
uint16_t used_idx, desc_idx;
|
||||
|
||||
if ((vq == VQ_NULL) || (vq->vq_used_cons_idx == vq->vq_ring.used->idx))
|
||||
return (VQ_NULL);
|
||||
|
||||
VQUEUE_BUSY(vq);
|
||||
|
||||
used_idx = vq->vq_used_cons_idx++ & (vq->vq_nentries - 1);
|
||||
uep = &vq->vq_ring.used->ring[used_idx];
|
||||
|
||||
env_rmb();
|
||||
|
||||
desc_idx = (uint16_t) uep->id;
|
||||
if (len != VQ_NULL)
|
||||
*len = uep->len;
|
||||
|
||||
vq_ring_free_chain(vq, desc_idx);
|
||||
|
||||
cookie = vq->vq_descx[desc_idx].cookie;
|
||||
vq->vq_descx[desc_idx].cookie = VQ_NULL;
|
||||
|
||||
VQUEUE_IDLE(vq);
|
||||
|
||||
return (cookie);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_free - Frees VirtIO queue resources
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
*
|
||||
*/
|
||||
void virtqueue_free(struct virtqueue *vq) {
|
||||
|
||||
if (vq != VQ_NULL) {
|
||||
|
||||
if (vq->vq_free_cnt != vq->vq_nentries) {
|
||||
env_print("\r\nWARNING %s: freeing non-empty virtqueue\r\n", vq->vq_name);
|
||||
}
|
||||
|
||||
//TODO : Need to free indirect buffers here
|
||||
|
||||
if (vq->vq_ring_mem != VQ_NULL) {
|
||||
vq->vq_ring_size = 0;
|
||||
vq->vq_ring_mem = VQ_NULL;
|
||||
}
|
||||
|
||||
env_free_memory(vq);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_get_available_buffer - Returns buffer available for use in the
|
||||
* VirtIO queue
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
* @param avail_idx - Pointer to index used in vring desc table
|
||||
* @param len - Length of buffer
|
||||
*
|
||||
* @return - Pointer to available buffer
|
||||
*/
|
||||
void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx,
|
||||
uint32_t *len) {
|
||||
|
||||
uint16_t head_idx = 0;
|
||||
void *buffer;
|
||||
|
||||
if (vq->vq_available_idx == vq->vq_ring.avail->idx) {
|
||||
return (VQ_NULL);
|
||||
}
|
||||
|
||||
VQUEUE_BUSY(vq);
|
||||
|
||||
head_idx = vq->vq_available_idx++ & (vq->vq_nentries - 1);
|
||||
*avail_idx = vq->vq_ring.avail->ring[head_idx];
|
||||
|
||||
env_rmb();
|
||||
|
||||
buffer = env_map_patova(vq->vq_ring.desc[*avail_idx].addr);
|
||||
*len = vq->vq_ring.desc[*avail_idx].len;
|
||||
|
||||
VQUEUE_IDLE(vq);
|
||||
|
||||
return (buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_add_consumed_buffer - Returns consumed buffer back to VirtIO queue
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
* @param head_idx - Index of vring desc containing used buffer
|
||||
* @param len - Length of buffer
|
||||
*
|
||||
* @return - Function status
|
||||
*/
|
||||
int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx,
|
||||
uint_t len) {
|
||||
|
||||
struct vring_used_elem *used_desc = VQ_NULL;
|
||||
uint16_t used_idx;
|
||||
|
||||
if ((head_idx > vq->vq_nentries) || (head_idx < 0)) {
|
||||
return (ERROR_VRING_NO_BUFF);
|
||||
}
|
||||
|
||||
VQUEUE_BUSY(vq);
|
||||
|
||||
used_idx = vq->vq_ring.used->idx & (vq->vq_nentries - 1);
|
||||
used_desc = &(vq->vq_ring.used->ring[used_idx]);
|
||||
used_desc->id = head_idx;
|
||||
used_desc->len = len;
|
||||
|
||||
env_wmb();
|
||||
|
||||
vq->vq_ring.used->idx++;
|
||||
|
||||
VQUEUE_IDLE(vq);
|
||||
|
||||
return (VQUEUE_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_enable_cb - Enables callback generation
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
*
|
||||
* @return - Function status
|
||||
*/
|
||||
int virtqueue_enable_cb(struct virtqueue *vq) {
|
||||
|
||||
return (vq_ring_enable_interrupt(vq, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_enable_cb - Disables callback generation
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
*
|
||||
*/
|
||||
void virtqueue_disable_cb(struct virtqueue *vq) {
|
||||
|
||||
VQUEUE_BUSY(vq);
|
||||
|
||||
if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) {
|
||||
vring_used_event(&vq->vq_ring)= vq->vq_used_cons_idx - vq->vq_nentries
|
||||
- 1;
|
||||
} else {
|
||||
vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
|
||||
}
|
||||
|
||||
VQUEUE_IDLE(vq);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_kick - Notifies other side that there is buffer available for it.
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
*/
|
||||
void virtqueue_kick(struct virtqueue *vq) {
|
||||
|
||||
VQUEUE_BUSY(vq);
|
||||
|
||||
/* Ensure updated avail->idx is visible to host. */
|
||||
env_mb();
|
||||
|
||||
if (vq_ring_must_notify_host(vq))
|
||||
vq_ring_notify_host(vq);
|
||||
|
||||
vq->vq_queued_cnt = 0;
|
||||
|
||||
VQUEUE_IDLE(vq);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_dump Dumps important virtqueue fields , use for debugging purposes
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
*/
|
||||
void virtqueue_dump(struct virtqueue *vq) {
|
||||
|
||||
if (vq == VQ_NULL)
|
||||
return;
|
||||
|
||||
env_print("VQ: %s - size=%d; free=%d; used=%d; queued=%d; "
|
||||
"desc_head_idx=%d; avail.idx=%d; used_cons_idx=%d; "
|
||||
"used.idx=%d; avail.flags=0x%x; used.flags=0x%x\r\n", vq->vq_name,
|
||||
vq->vq_nentries, vq->vq_free_cnt, virtqueue_nused(vq),
|
||||
vq->vq_queued_cnt, vq->vq_desc_head_idx, vq->vq_ring.avail->idx,
|
||||
vq->vq_used_cons_idx, vq->vq_ring.used->idx,
|
||||
vq->vq_ring.avail->flags, vq->vq_ring.used->flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* virtqueue_get_desc_size - Returns vring descriptor size
|
||||
*
|
||||
* @param vq - Pointer to VirtIO queue control block
|
||||
*
|
||||
* @return - Descriptor length
|
||||
*/
|
||||
uint32_t virtqueue_get_desc_size(struct virtqueue *vq) {
|
||||
uint16_t head_idx = 0;
|
||||
uint16_t avail_idx = 0;
|
||||
uint32_t len = 0;
|
||||
|
||||
if (vq->vq_available_idx == vq->vq_ring.avail->idx) {
|
||||
return (VQ_NULL);
|
||||
}
|
||||
|
||||
VQUEUE_BUSY(vq);
|
||||
|
||||
head_idx = vq->vq_available_idx & (vq->vq_nentries - 1);
|
||||
avail_idx = vq->vq_ring.avail->ring[head_idx];
|
||||
len = vq->vq_ring.desc[avail_idx].len;
|
||||
|
||||
VQUEUE_IDLE(vq);
|
||||
|
||||
return (len);
|
||||
}
|
||||
/**************************************************************************
|
||||
* Helper Functions *
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* vq_ring_add_buffer
|
||||
*
|
||||
*/
|
||||
static uint16_t vq_ring_add_buffer(struct virtqueue *vq,
|
||||
struct vring_desc *desc, uint16_t head_idx, struct llist *buffer,
|
||||
int readable, int writable) {
|
||||
|
||||
struct vring_desc *dp;
|
||||
int i, needed;
|
||||
uint16_t idx;
|
||||
|
||||
needed = readable + writable;
|
||||
|
||||
for (i = 0, idx = head_idx; (i < needed && buffer != VQ_NULL);
|
||||
i++, idx = dp->next, buffer = buffer->next) {
|
||||
|
||||
VQASSERT(vq, idx != VQ_RING_DESC_CHAIN_END,
|
||||
"premature end of free desc chain");
|
||||
|
||||
dp = &desc[idx];
|
||||
dp->addr = env_map_vatopa(buffer->data);
|
||||
dp->len = buffer->attr;
|
||||
dp->flags = 0;
|
||||
|
||||
if (i < needed - 1)
|
||||
dp->flags |= VRING_DESC_F_NEXT;
|
||||
|
||||
/* Readable buffers are inserted into vring before the writable buffers.*/
|
||||
if (i >= readable)
|
||||
dp->flags |= VRING_DESC_F_WRITE;
|
||||
}
|
||||
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* vq_ring_free_chain
|
||||
*
|
||||
*/
|
||||
static void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) {
|
||||
struct vring_desc *dp;
|
||||
struct vq_desc_extra *dxp;
|
||||
|
||||
VQ_RING_ASSERT_VALID_IDX(vq, desc_idx);
|
||||
dp = &vq->vq_ring.desc[desc_idx];
|
||||
dxp = &vq->vq_descx[desc_idx];
|
||||
|
||||
if (vq->vq_free_cnt == 0)
|
||||
VQ_RING_ASSERT_CHAIN_TERM(vq);
|
||||
|
||||
vq->vq_free_cnt += dxp->ndescs;
|
||||
dxp->ndescs--;
|
||||
|
||||
if ((dp->flags & VRING_DESC_F_INDIRECT) == 0) {
|
||||
while (dp->flags & VRING_DESC_F_NEXT) {
|
||||
VQ_RING_ASSERT_VALID_IDX(vq, dp->next);
|
||||
dp = &vq->vq_ring.desc[dp->next];
|
||||
dxp->ndescs--;
|
||||
}
|
||||
}
|
||||
|
||||
VQASSERT(vq, (dxp->ndescs == 0),
|
||||
"failed to free entire desc chain, remaining");
|
||||
|
||||
/*
|
||||
* We must append the existing free chain, if any, to the end of
|
||||
* newly freed chain. If the virtqueue was completely used, then
|
||||
* head would be VQ_RING_DESC_CHAIN_END (ASSERTed above).
|
||||
*/
|
||||
dp->next = vq->vq_desc_head_idx;
|
||||
vq->vq_desc_head_idx = desc_idx;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* vq_ring_init
|
||||
*
|
||||
*/
|
||||
static void vq_ring_init(struct virtqueue *vq) {
|
||||
struct vring *vr;
|
||||
unsigned char *ring_mem;
|
||||
int i, size;
|
||||
|
||||
ring_mem = vq->vq_ring_mem;
|
||||
size = vq->vq_nentries;
|
||||
vr = &vq->vq_ring;
|
||||
|
||||
vring_init(vr, size, ring_mem, vq->vq_alignment);
|
||||
|
||||
for (i = 0; i < size - 1; i++)
|
||||
vr->desc[i].next = i + 1;
|
||||
vr->desc[i].next = VQ_RING_DESC_CHAIN_END;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* vq_ring_update_avail
|
||||
*
|
||||
*/
|
||||
static void vq_ring_update_avail(struct virtqueue *vq, uint16_t desc_idx) {
|
||||
uint16_t avail_idx;
|
||||
|
||||
/*
|
||||
* Place the head of the descriptor chain into the next slot and make
|
||||
* it usable to the host. The chain is made available now rather than
|
||||
* deferring to virtqueue_notify() in the hopes that if the host is
|
||||
* currently running on another CPU, we can keep it processing the new
|
||||
* descriptor.
|
||||
*/
|
||||
avail_idx = vq->vq_ring.avail->idx & (vq->vq_nentries - 1);
|
||||
vq->vq_ring.avail->ring[avail_idx] = desc_idx;
|
||||
|
||||
env_wmb();
|
||||
|
||||
vq->vq_ring.avail->idx++;
|
||||
|
||||
/* Keep pending count until virtqueue_notify(). */
|
||||
vq->vq_queued_cnt++;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* vq_ring_enable_interrupt
|
||||
*
|
||||
*/
|
||||
static int vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc) {
|
||||
|
||||
/*
|
||||
* Enable interrupts, making sure we get the latest index of
|
||||
* what's already been consumed.
|
||||
*/
|
||||
if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) {
|
||||
vring_used_event(&vq->vq_ring)= vq->vq_used_cons_idx + ndesc;
|
||||
} else {
|
||||
vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
|
||||
}
|
||||
|
||||
env_mb();
|
||||
|
||||
/*
|
||||
* Enough items may have already been consumed to meet our threshold
|
||||
* since we last checked. Let our caller know so it processes the new
|
||||
* entries.
|
||||
*/
|
||||
if (virtqueue_nused(vq) > ndesc) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* virtqueue_interrupt
|
||||
*
|
||||
*/
|
||||
void virtqueue_notification(struct virtqueue *vq) {
|
||||
|
||||
if (vq->callback != VQ_NULL)
|
||||
vq->callback(vq);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* vq_ring_must_notify_host
|
||||
*
|
||||
*/
|
||||
static int vq_ring_must_notify_host(struct virtqueue *vq) {
|
||||
uint16_t new_idx, prev_idx, event_idx;
|
||||
|
||||
if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) {
|
||||
new_idx = vq->vq_ring.avail->idx;
|
||||
prev_idx = new_idx - vq->vq_queued_cnt;
|
||||
event_idx = vring_avail_event(&vq->vq_ring);
|
||||
|
||||
return (vring_need_event(event_idx, new_idx, prev_idx) != 0);
|
||||
}
|
||||
|
||||
return ((vq->vq_ring.used->flags & VRING_USED_F_NO_NOTIFY) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* vq_ring_notify_host
|
||||
*
|
||||
*/
|
||||
static void vq_ring_notify_host(struct virtqueue *vq) {
|
||||
|
||||
if (vq->notify != VQ_NULL)
|
||||
vq->notify(vq);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* virtqueue_nused
|
||||
*
|
||||
*/
|
||||
static int virtqueue_nused(struct virtqueue *vq) {
|
||||
uint16_t used_idx, nused;
|
||||
|
||||
used_idx = vq->vq_ring.used->idx;
|
||||
|
||||
nused = (uint16_t) (used_idx - vq->vq_used_cons_idx);
|
||||
VQASSERT(vq, nused <= vq->vq_nentries, "used more than available");
|
||||
|
||||
return (nused);
|
||||
}
|
233
ThirdParty/sw_services/xilopenamp/src/virtqueue.h
vendored
Normal file
233
ThirdParty/sw_services/xilopenamp/src/virtqueue.h
vendored
Normal file
|
@ -0,0 +1,233 @@
|
|||
#ifndef VIRTQUEUE_H_
|
||||
#define VIRTQUEUE_H_
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice unmodified, this list of conditions, and the following
|
||||
* disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
typedef unsigned int uint_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef uint8_t boolean;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned long uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef signed long long int64_t;
|
||||
|
||||
#include "virtio_ring.h"
|
||||
#include "env.h"
|
||||
#include "llist.h"
|
||||
|
||||
/*Error Codes*/
|
||||
#define VQ_ERROR_BASE -3000
|
||||
#define ERROR_VRING_FULL (VQ_ERROR_BASE - 1)
|
||||
#define ERROR_INVLD_DESC_IDX (VQ_ERROR_BASE - 2)
|
||||
#define ERROR_EMPTY_RING (VQ_ERROR_BASE - 3)
|
||||
#define ERROR_NO_MEM (VQ_ERROR_BASE - 4)
|
||||
#define ERROR_VRING_MAX_DESC (VQ_ERROR_BASE - 5)
|
||||
#define ERROR_VRING_ALIGN (VQ_ERROR_BASE - 6)
|
||||
#define ERROR_VRING_NO_BUFF (VQ_ERROR_BASE - 7)
|
||||
#define ERROR_VQUEUE_INVLD_PARAM (VQ_ERROR_BASE - 8)
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define VQUEUE_SUCCESS 0
|
||||
#define VQUEUE_DEBUG false
|
||||
|
||||
//TODO:
|
||||
/* This is temporary macro to replace C NULL support.
|
||||
* At the moment all the RTL specific functions are present in env.
|
||||
* */
|
||||
#define VQ_NULL 0
|
||||
|
||||
/* The maximum virtqueue size is 2^15. Use that value as the end of
|
||||
* descriptor chain terminator since it will never be a valid index
|
||||
* in the descriptor table. This is used to verify we are correctly
|
||||
* handling vq_free_cnt.
|
||||
*/
|
||||
#define VQ_RING_DESC_CHAIN_END 32768
|
||||
#define VIRTQUEUE_FLAG_INDIRECT 0x0001
|
||||
#define VIRTQUEUE_FLAG_EVENT_IDX 0x0002
|
||||
#define VIRTQUEUE_MAX_NAME_SZ 32
|
||||
|
||||
/* Support for indirect buffer descriptors. */
|
||||
#define VIRTIO_RING_F_INDIRECT_DESC (1 << 28)
|
||||
|
||||
/* Support to suppress interrupt until specific index is reached. */
|
||||
#define VIRTIO_RING_F_EVENT_IDX (1 << 29)
|
||||
|
||||
/*
|
||||
* Hint on how long the next interrupt should be postponed. This is
|
||||
* only used when the EVENT_IDX feature is negotiated.
|
||||
*/
|
||||
typedef enum {
|
||||
VQ_POSTPONE_SHORT,
|
||||
VQ_POSTPONE_LONG,
|
||||
VQ_POSTPONE_EMPTIED /* Until all available desc are used. */
|
||||
} vq_postpone_t;
|
||||
|
||||
struct virtqueue {
|
||||
//TODO: Need to define proper structure for
|
||||
// virtio device with RPmsg and paravirtualization.
|
||||
|
||||
struct virtio_device *vq_dev;
|
||||
char vq_name[VIRTQUEUE_MAX_NAME_SZ];
|
||||
uint16_t vq_queue_index;
|
||||
uint16_t vq_nentries;
|
||||
uint32_t vq_flags;
|
||||
int vq_alignment;
|
||||
int vq_ring_size;
|
||||
boolean vq_inuse;
|
||||
void *vq_ring_mem;
|
||||
void (*callback)(struct virtqueue *vq);
|
||||
void (*notify)(struct virtqueue *vq);
|
||||
int vq_max_indirect_size;
|
||||
int vq_indirect_mem_size;
|
||||
struct vring vq_ring;
|
||||
uint16_t vq_free_cnt;
|
||||
uint16_t vq_queued_cnt;
|
||||
|
||||
/*
|
||||
* Head of the free chain in the descriptor table. If
|
||||
* there are no free descriptors, this will be set to
|
||||
* VQ_RING_DESC_CHAIN_END.
|
||||
*/
|
||||
uint16_t vq_desc_head_idx;
|
||||
|
||||
/*
|
||||
* Last consumed descriptor in the used table,
|
||||
* trails vq_ring.used->idx.
|
||||
*/
|
||||
uint16_t vq_used_cons_idx;
|
||||
|
||||
/*
|
||||
* Last consumed descriptor in the available table -
|
||||
* used by the consumer side.
|
||||
*/
|
||||
uint16_t vq_available_idx;
|
||||
|
||||
uint8_t padd;
|
||||
|
||||
/*
|
||||
* Used by the host side during callback. Cookie
|
||||
* holds the address of buffer received from other side.
|
||||
* Other fields in this structure are not used currently.
|
||||
*/
|
||||
|
||||
struct vq_desc_extra {
|
||||
void *cookie;
|
||||
struct vring_desc *indirect;
|
||||
uint32_t indirect_paddr;
|
||||
uint16_t ndescs;
|
||||
} vq_descx[0];
|
||||
};
|
||||
|
||||
/* struct to hold vring specific information */
|
||||
struct vring_alloc_info {
|
||||
void *phy_addr;
|
||||
uint32_t align;
|
||||
uint16_t num_descs;
|
||||
uint16_t pad;
|
||||
};
|
||||
|
||||
typedef void vq_callback(struct virtqueue *);
|
||||
typedef void vq_notify(struct virtqueue *);
|
||||
|
||||
#if (VQUEUE_DEBUG == true)
|
||||
|
||||
#define VQASSERT(_vq, _exp, _msg) do{ \
|
||||
if (!(_exp)){ env_print("%s: %s - "_msg, __func__, (_vq)->vq_name); while(1);} \
|
||||
} while(0)
|
||||
|
||||
#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) \
|
||||
VQASSERT((_vq), (_idx) < (_vq)->vq_nentries, \
|
||||
"invalid ring index")
|
||||
|
||||
#define VQ_RING_ASSERT_CHAIN_TERM(_vq) \
|
||||
VQASSERT((_vq), (_vq)->vq_desc_head_idx == \
|
||||
VQ_RING_DESC_CHAIN_END, "full ring terminated incorrectly: invalid head")
|
||||
|
||||
#define VQ_PARAM_CHK(condition, status_var, status_err) \
|
||||
if ((status_var == 0) && (condition)) \
|
||||
{ \
|
||||
status_var = status_err; \
|
||||
}
|
||||
|
||||
#define VQUEUE_BUSY(vq) if ((vq)->vq_inuse == false) \
|
||||
(vq)->vq_inuse = true; \
|
||||
else \
|
||||
VQASSERT(vq, (vq)->vq_inuse == false, \
|
||||
"VirtQueue already in use")
|
||||
|
||||
#define VQUEUE_IDLE(vq) ((vq)->vq_inuse = false)
|
||||
|
||||
#else
|
||||
|
||||
#define KASSERT(cond, str)
|
||||
#define VQASSERT(_vq, _exp, _msg)
|
||||
#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx)
|
||||
#define VQ_RING_ASSERT_CHAIN_TERM(_vq)
|
||||
#define VQ_PARAM_CHK(condition, status_var, status_err)
|
||||
#define VQUEUE_BUSY(vq)
|
||||
#define VQUEUE_IDLE(vq)
|
||||
|
||||
#endif
|
||||
|
||||
int virtqueue_create(struct virtio_device *device, unsigned short id, char *name,
|
||||
struct vring_alloc_info *ring, void (*callback)(struct virtqueue *vq),
|
||||
void (*notify)(struct virtqueue *vq), struct virtqueue **v_queue);
|
||||
|
||||
int virtqueue_add_buffer(struct virtqueue *vq, struct llist *buffer,
|
||||
int readable, int writable, void *cookie);
|
||||
|
||||
int virtqueue_add_single_buffer(struct virtqueue *vq, void *cookie,
|
||||
void* buffer_addr, uint_t len, int writable, boolean has_next);
|
||||
|
||||
void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len);
|
||||
|
||||
void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx,
|
||||
uint32_t *len);
|
||||
|
||||
int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx,
|
||||
uint_t len);
|
||||
|
||||
void virtqueue_disable_cb(struct virtqueue *vq);
|
||||
|
||||
int virtqueue_enable_cb(struct virtqueue *vq);
|
||||
|
||||
void virtqueue_kick(struct virtqueue *vq);
|
||||
|
||||
void virtqueue_free(struct virtqueue *vq);
|
||||
|
||||
void virtqueue_dump(struct virtqueue *vq);
|
||||
|
||||
void virtqueue_notification(struct virtqueue *vq);
|
||||
|
||||
uint32_t virtqueue_get_desc_size(struct virtqueue *vq);
|
||||
|
||||
#endif /* VIRTQUEUE_H_ */
|
Loading…
Add table
Reference in a new issue