apps/samples/remote/baremetal/rpc_demo/rsc_table.h | 118 +-
apps/tests/remote/baremetal/echo_test/rsc_table.c | 246 ++--
apps/tests/remote/baremetal/echo_test/rsc_table.h | 118 +-
.../remote/baremetal/func_test_suite/rsc_table.c | 178 +--
.../remote/baremetal/func_test_suite/rsc_table.h | 102 +-
common/hil/hil.c | 812 ++++++------
common/hil/hil.h | 972 +++++++-------
common/llist/llist.c | 200 +--
common/llist/llist.h | 118 +-
common/shm/sh_mem.c | 460 +++----
common/shm/sh_mem.h | 178 +--
include/open_amp.h | 74 +-
libs/system/zc702evk/linux/boot.c | 1188 ++++++++---------
libs/system/zc702evk/linux/rsc_table.c | 178 +--
libs/system/zc702evk/linux/rsc_table.h | 102 +-
porting/config/config.c | 188 +--
porting/config/config.h | 118 +-
porting/env/env.h | 858 ++++++------
porting/zc702evk/platform.c | 264 ++--
porting/zc702evk/platform.h | 248 ++--
porting/zc702evk/platform_info.c | 464 +++----
remoteproc/elf_loader.c | 1286 +++++++++---------
remoteproc/elf_loader.h | 468 +++----
remoteproc/remoteproc_loader.c | 482 +++----
remoteproc/remoteproc_loader.h | 184 +--
remoteproc/rsc_table_parser.h | 106 +-
rpmsg/Makefile | 70 +-
rpmsg/remote_device.c | 1028 +++++++--------
rpmsg/rpmsg.c | 828 ++++++------
rpmsg/rpmsg_core.h | 380 +++---
virtio/Makefile | 66 +-
virtio/virtio.h | 302 ++---
virtio/virtio_ring.h | 330 ++---
virtio/virtqueue.c | 1382 ++++++++++----------
virtio/virtqueue.h | 452 +++----
35 files changed, 7274 insertions(+), 7274 deletions(-)
diff --git a/apps/samples/remote/baremetal/rpc_demo/rsc_table.h b/apps/samples/remote/baremetal/rpc_demo/rsc_table.h
index 60b602e..60a0548 100644
--- a/apps/samples/remote/baremetal/rpc_demo/rsc_table.h
+++ b/apps/samples/remote/baremetal/rpc_demo/rsc_table.h
@@ -1,59 +1,59 @@
-/* This file populates resource table for BM remote
- * for use by the Linux Master */
-
-#include <stddef.h>
-#include "open_amp.h"
-
-#define NO_RESOURCE_ENTRIES 8
-
-/* Resource table for the given remote */
-struct remote_resource_table {
- unsigned int version;
- unsigned int num;
- unsigned int reserved[2];
- unsigned int offset[NO_RESOURCE_ENTRIES];
- /* text carveout entry */
-#ifdef ZYNQMP_R5
- struct fw_rsc_carveout ocm_0_cout;
- struct fw_rsc_carveout ocm_1_cout;
-#else
-#ifdef ZYNQ_A9
- struct fw_rsc_carveout elf_cout;
-#endif
-#endif
- /* rpmsg vdev entry */
- struct fw_rsc_vdev rpmsg_vdev;
- struct fw_rsc_vdev_vring rpmsg_vring0;
- struct fw_rsc_vdev_vring rpmsg_vring1;
-};
-
+/* This file populates resource table for BM remote
+ * for use by the Linux Master */
+
+#include <stddef.h>
+#include "open_amp.h"
+
+#define NO_RESOURCE_ENTRIES 8
+
+/* Resource table for the given remote */
+struct remote_resource_table {
+ unsigned int version;
+ unsigned int num;
+ unsigned int reserved[2];
+ unsigned int offset[NO_RESOURCE_ENTRIES];
+ /* text carveout entry */
+#ifdef ZYNQMP_R5
+ struct fw_rsc_carveout ocm_0_cout;
+ struct fw_rsc_carveout ocm_1_cout;
+#else
+#ifdef ZYNQ_A9
+ struct fw_rsc_carveout elf_cout;
+#endif
+#endif
+ /* rpmsg vdev entry */
+ struct fw_rsc_vdev rpmsg_vdev;
+ struct fw_rsc_vdev_vring rpmsg_vring0;
+ struct fw_rsc_vdev_vring rpmsg_vring1;
+};
+
diff --git a/apps/tests/remote/baremetal/echo_test/rsc_table.c b/apps/tests/remote/baremetal/echo_test/rsc_table.c
index 20d4d0b..b2096d8 100644
--- a/apps/tests/remote/baremetal/echo_test/rsc_table.c
+++ b/apps/tests/remote/baremetal/echo_test/rsc_table.c
@@ -1,123 +1,123 @@
-/* This file populates resource table for BM remote
- * for use by the Linux Master */
-
-#include "open_amp.h"
-#include "rsc_table.h"
-
-/* Place resource table in special ELF section */
-#define __section(S) __attribute__((__section__(#S)))
-#define __resource __section(.resource_table)
-
-#define RPMSG_IPU_C0_FEATURES 1
-
-/* VirtIO rpmsg device id */
-#define VIRTIO_ID_RPMSG_ 7
-
-/* Remote supports Name Service announcement */
-#define VIRTIO_RPMSG_F_NS 0
-
-#ifdef ZYNQMP_R5
-#define OCM_0_START 0xFFFC0000
-#define OCM_0_LEN 0x20000
-#define OCM_1_START 0xFFFF0000
-#define OCM_1_LEN 0x10000
-#define TCM_0_START_DA 0x00000000
-#define TCM_0_LEN 0x10000
-#define TCM_0_START_PA 0xFFE00000
-#define TCM_1_START_DA 0x00020000
-#define TCM_1_LEN 0x10000
-#define TCM_1_START_PA 0xFFE40000
-#define NUM_VRINGS 0x02
-#define VRING_ALIGN 0x1000
-#define RING_TX 0x3ED00000
-#define RING_RX 0x3ED04000
-#define VRING_SIZE 256
-
-#define NUM_TABLE_ENTRIES 3
-#define CARVEOUT_SRC_OFFSETS offsetof(struct remote_resource_table, ocm_0_cout), \
- offsetof(struct remote_resource_table, ocm_1_cout),
-
-#define CARVEOUT_SRC {RSC_CARVEOUT, OCM_0_START, OCM_0_START, OCM_0_LEN, 0, 0, "OCM0_COUT",}, \
- {RSC_CARVEOUT, OCM_1_START, OCM_1_START, OCM_1_LEN, 0, 0, "ELF_DATA_COUT",},
-
-#else
-#ifdef ZYNQ_A9
-/* Resource table entries */
-#define ELF_START 0x00000000
-#define ELF_END 0x08000000
-#define NUM_VRINGS 0x02
-#define VRING_ALIGN 0x1000
-#define RING_TX 0x08000000
-#define RING_RX 0x08004000
-#define VRING_SIZE 256
-
-#define NUM_TABLE_ENTRIES 2
-#define CARVEOUT_SRC_OFFSETS offsetof(struct remote_resource_table, elf_cout),
-#define CARVEOUT_SRC { RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT", },
-
-#endif
-#endif
-
-
-const struct remote_resource_table __resource resources =
-{
- /* Version */
- 1,
-
- /* NUmber of table entries */
- NUM_TABLE_ENTRIES,
- /* reserved fields */
- { 0, 0,},
-
- /* Offsets of rsc entries */
- {
- CARVEOUT_SRC_OFFSETS
- offsetof(struct remote_resource_table, rpmsg_vdev),
- },
-
- /* End of ELF file */
- CARVEOUT_SRC
-
- /* Virtio device entry */
- { RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},
- },
-
- /* Vring rsc entry - part of vdev rsc entry */
- {
- RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0
- },
- {
- RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0
- },
-};
-
+/* This file populates resource table for BM remote
+ * for use by the Linux Master */
+
+#include "open_amp.h"
+#include "rsc_table.h"
+
+/* Place resource table in special ELF section */
+#define __section(S) __attribute__((__section__(#S)))
+#define __resource __section(.resource_table)
+
+#define RPMSG_IPU_C0_FEATURES 1
+
+/* VirtIO rpmsg device id */
+#define VIRTIO_ID_RPMSG_ 7
+
+/* Remote supports Name Service announcement */
+#define VIRTIO_RPMSG_F_NS 0
+
+#ifdef ZYNQMP_R5
+#define OCM_0_START 0xFFFC0000
+#define OCM_0_LEN 0x20000
+#define OCM_1_START 0xFFFF0000
+#define OCM_1_LEN 0x10000
+#define TCM_0_START_DA 0x00000000
+#define TCM_0_LEN 0x10000
+#define TCM_0_START_PA 0xFFE00000
+#define TCM_1_START_DA 0x00020000
+#define TCM_1_LEN 0x10000
+#define TCM_1_START_PA 0xFFE40000
+#define NUM_VRINGS 0x02
+#define VRING_ALIGN 0x1000
+#define RING_TX 0x3ED00000
+#define RING_RX 0x3ED04000
+#define VRING_SIZE 256
+
+#define NUM_TABLE_ENTRIES 3
+#define CARVEOUT_SRC_OFFSETS offsetof(struct remote_resource_table, ocm_0_cout), \
+ offsetof(struct remote_resource_table, ocm_1_cout),
+
+#define CARVEOUT_SRC {RSC_CARVEOUT, OCM_0_START, OCM_0_START, OCM_0_LEN, 0, 0, "OCM0_COUT",}, \
+ {RSC_CARVEOUT, OCM_1_START, OCM_1_START, OCM_1_LEN, 0, 0, "ELF_DATA_COUT",},
+
+#else
+#ifdef ZYNQ_A9
+/* Resource table entries */
+#define ELF_START 0x00000000
+#define ELF_END 0x08000000
+#define NUM_VRINGS 0x02
+#define VRING_ALIGN 0x1000
+#define RING_TX 0x08000000
+#define RING_RX 0x08004000
+#define VRING_SIZE 256
+
+#define NUM_TABLE_ENTRIES 2
+#define CARVEOUT_SRC_OFFSETS offsetof(struct remote_resource_table, elf_cout),
+#define CARVEOUT_SRC { RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT", },
+
+#endif
+#endif
+
+
+const struct remote_resource_table __resource resources =
+{
+ /* Version */
+ 1,
+
+ /* NUmber of table entries */
+ NUM_TABLE_ENTRIES,
+ /* reserved fields */
+ { 0, 0,},
+
+ /* Offsets of rsc entries */
+ {
+ CARVEOUT_SRC_OFFSETS
+ offsetof(struct remote_resource_table, rpmsg_vdev),
+ },
+
+ /* End of ELF file */
+ CARVEOUT_SRC
+
+ /* Virtio device entry */
+ { RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},
+ },
+
+ /* Vring rsc entry - part of vdev rsc entry */
+ {
+ RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0
+ },
+ {
+ RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0
+ },
+};
+
diff --git a/apps/tests/remote/baremetal/echo_test/rsc_table.h b/apps/tests/remote/baremetal/echo_test/rsc_table.h
index a045d03..cc0e118 100644
--- a/apps/tests/remote/baremetal/echo_test/rsc_table.h
+++ b/apps/tests/remote/baremetal/echo_test/rsc_table.h
@@ -1,59 +1,59 @@
-/* This file populates resource table for BM remote
- * for use by the Linux Master */
-
-#include <stddef.h>
-#include "open_amp.h"
-
-#define NO_RESOURCE_ENTRIES 8
-
-/* Resource table for the given remote */
-struct remote_resource_table {
- unsigned int version;
- unsigned int num;
- unsigned int reserved[2];
- unsigned int offset[NO_RESOURCE_ENTRIES];
- /* text carveout entry */
-#ifdef ZYNQMP_R5
- struct fw_rsc_carveout ocm_0_cout;
- struct fw_rsc_carveout ocm_1_cout;
-#else
-#ifdef ZYNQ_A9
- struct fw_rsc_carveout elf_cout;
-#endif
-#endif
- /* rpmsg vdev entry */
- struct fw_rsc_vdev rpmsg_vdev;
- struct fw_rsc_vdev_vring rpmsg_vring0;
- struct fw_rsc_vdev_vring rpmsg_vring1;
-};
-
+/* This file populates resource table for BM remote
+ * for use by the Linux Master */
+
+#include <stddef.h>
+#include "open_amp.h"
+
+#define NO_RESOURCE_ENTRIES 8
+
+/* Resource table for the given remote */
+struct remote_resource_table {
+ unsigned int version;
+ unsigned int num;
+ unsigned int reserved[2];
+ unsigned int offset[NO_RESOURCE_ENTRIES];
+ /* text carveout entry */
+#ifdef ZYNQMP_R5
+ struct fw_rsc_carveout ocm_0_cout;
+ struct fw_rsc_carveout ocm_1_cout;
+#else
+#ifdef ZYNQ_A9
+ struct fw_rsc_carveout elf_cout;
+#endif
+#endif
+ /* rpmsg vdev entry */
+ struct fw_rsc_vdev rpmsg_vdev;
+ struct fw_rsc_vdev_vring rpmsg_vring0;
+ struct fw_rsc_vdev_vring rpmsg_vring1;
+};
+
diff --git a/apps/tests/remote/baremetal/func_test_suite/rsc_table.c b/apps/tests/remote/baremetal/func_test_suite/rsc_table.c
index 85b11b1..af8e0e1 100644
--- a/apps/tests/remote/baremetal/func_test_suite/rsc_table.c
+++ b/apps/tests/remote/baremetal/func_test_suite/rsc_table.c
@@ -1,89 +1,89 @@
-/* This file populates resource table for BM remote
- * for use by the Linux Master */
-
-#include "open_amp.h"
-#include "rsc_table.h"
-
-/* Place resource table in special ELF section */
-#define __section(S) __attribute__((__section__(#S)))
-#define __resource __section(.resource_table)
-
-#define RPMSG_IPU_C0_FEATURES 1
-
-/* VirtIO rpmsg device id */
-#define VIRTIO_ID_RPMSG_ 7
-
-/* Remote supports Name Service announcement */
-#define VIRTIO_RPMSG_F_NS 0
-
-/* Resource table entries */
-#define ELF_START 0x00000000
-#define ELF_END 0x08000000
-#define NUM_VRINGS 0x02
-#define VRING_ALIGN 0x1000
-#define RING_TX 0x08000000
-#define RING_RX 0x08004000
-#define VRING_SIZE 256
-
-const struct remote_resource_table __resource resources =
-{
- /* Version */
- 1,
-
- /* NUmber of table entries */
- 2,
- /* reserved fields */
- { 0, 0,},
-
- /* Offsets of rsc entries */
- {
- offsetof(struct remote_resource_table, elf_cout),
- offsetof(struct remote_resource_table, rpmsg_vdev),
- },
-
- /* End of ELF file */
- {
- RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT",
- },
-
- /* Virtio device entry */
- { RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},
- },
-
- /* Vring rsc entry - part of vdev rsc entry */
- {
- RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0
- },
- {
- RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0
- },
-};
+/* This file populates resource table for BM remote
+ * for use by the Linux Master */
+
+#include "open_amp.h"
+#include "rsc_table.h"
+
+/* Place resource table in special ELF section */
+#define __section(S) __attribute__((__section__(#S)))
+#define __resource __section(.resource_table)
+
+#define RPMSG_IPU_C0_FEATURES 1
+
+/* VirtIO rpmsg device id */
+#define VIRTIO_ID_RPMSG_ 7
+
+/* Remote supports Name Service announcement */
+#define VIRTIO_RPMSG_F_NS 0
+
+/* Resource table entries */
+#define ELF_START 0x00000000
+#define ELF_END 0x08000000
+#define NUM_VRINGS 0x02
+#define VRING_ALIGN 0x1000
+#define RING_TX 0x08000000
+#define RING_RX 0x08004000
+#define VRING_SIZE 256
+
+const struct remote_resource_table __resource resources =
+{
+ /* Version */
+ 1,
+
+ /* NUmber of table entries */
+ 2,
+ /* reserved fields */
+ { 0, 0,},
+
+ /* Offsets of rsc entries */
+ {
+ offsetof(struct remote_resource_table, elf_cout),
+ offsetof(struct remote_resource_table, rpmsg_vdev),
+ },
+
+ /* End of ELF file */
+ {
+ RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT",
+ },
+
+ /* Virtio device entry */
+ { RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},
+ },
+
+ /* Vring rsc entry - part of vdev rsc entry */
+ {
+ RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0
+ },
+ {
+ RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0
+ },
+};
diff --git a/apps/tests/remote/baremetal/func_test_suite/rsc_table.h b/apps/tests/remote/baremetal/func_test_suite/rsc_table.h
index 0a8e957..842b423 100644
--- a/apps/tests/remote/baremetal/func_test_suite/rsc_table.h
+++ b/apps/tests/remote/baremetal/func_test_suite/rsc_table.h
@@ -1,51 +1,51 @@
-/* This file populates resource table for BM remote
- * for use by the Linux Master */
-
-#include <stddef.h>
-#include "open_amp.h"
-
-#define NO_RESOURCE_ENTRIES 8
-
-/* Resource table for the given remote */
-struct remote_resource_table {
- unsigned int version;
- unsigned int num;
- unsigned int reserved[2];
- unsigned int offset[NO_RESOURCE_ENTRIES];
- /* text carveout entry */
- struct fw_rsc_carveout elf_cout;
- /* rpmsg vdev entry */
- struct fw_rsc_vdev rpmsg_vdev;
- struct fw_rsc_vdev_vring rpmsg_vring0;
- struct fw_rsc_vdev_vring rpmsg_vring1;
-};
-
+/* This file populates resource table for BM remote
+ * for use by the Linux Master */
+
+#include <stddef.h>
+#include "open_amp.h"
+
+#define NO_RESOURCE_ENTRIES 8
+
+/* Resource table for the given remote */
+struct remote_resource_table {
+ unsigned int version;
+ unsigned int num;
+ unsigned int reserved[2];
+ unsigned int offset[NO_RESOURCE_ENTRIES];
+ /* text carveout entry */
+ struct fw_rsc_carveout elf_cout;
+ /* rpmsg vdev entry */
+ struct fw_rsc_vdev rpmsg_vdev;
+ struct fw_rsc_vdev_vring rpmsg_vring0;
+ struct fw_rsc_vdev_vring rpmsg_vring1;
+};
+
diff --git a/common/hil/hil.c b/common/hil/hil.c
index 69df059..31e1a71 100644
--- a/common/hil/hil.c
+++ b/common/hil/hil.c
@@ -1,406 +1,406 @@
- * 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));
-}
+ * 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));
+}
diff --git a/common/hil/hil.h b/common/hil/hil.h
index 3f276c9..0f5ce2d 100644
--- a/common/hil/hil.h
+++ b/common/hil/hil.h
@@ -1,419 +1,419 @@
+#include "../../virtio/virtio.h"
+#include "../../porting/config/config.h"
/**
* reg_ipi_after_deinit()
* This function register interrupt(IPI) after openamp resource .
@@ -422,73 +422,73 @@ struct hil_platform_ops
*/
diff --git a/common/llist/llist.c b/common/llist/llist.c
index 6c9c5cc..37e888c 100644
--- a/common/llist/llist.c
+++ b/common/llist/llist.c
@@ -1,100 +1,100 @@
- * 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;
- }
-}
+ * 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;
+ }
+}
diff --git a/common/llist/llist.h b/common/llist/llist.h
index 1909169..004f4e0 100644
--- a/common/llist/llist.h
+++ b/common/llist/llist.h
@@ -1,59 +1,59 @@
diff --git a/common/shm/sh_mem.c b/common/shm/sh_mem.c
index 100a336..6a290a4 100644
--- a/common/shm/sh_mem.c
+++ b/common/shm/sh_mem.c
@@ -1,230 +1,230 @@
-/**************************************************************************
- * 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;
-}
+/**************************************************************************
+ * 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;
+}
diff --git a/common/shm/sh_mem.h b/common/shm/sh_mem.h
index 65c97df..4ba830b 100644
--- a/common/shm/sh_mem.h
+++ b/common/shm/sh_mem.h
@@ -1,89 +1,89 @@
+#include "../../porting/env/env.h"
index 03b6ddb..7507bd8 100644
--- a/include/open_amp.h
+++ b/include/open_amp.h
@@ -1,37 +1,37 @@
-#ifndef OPEN_AMP_H_
-#define OPEN_AMP_H_
-
-#include "../rpmsg/rpmsg.h"
-#include "../remoteproc/remoteproc.h"
-
-
-#endif /* OPEN_AMP_H_ */
+#ifndef OPEN_AMP_H_
+#define OPEN_AMP_H_
+
+#include "../rpmsg/rpmsg.h"
+#include "../remoteproc/remoteproc.h"
+
+
+#endif /* OPEN_AMP_H_ */
diff --git a/libs/system/zc702evk/linux/boot.c b/libs/system/zc702evk/linux/boot.c
index 852906a..fa84dfc 100644
--- a/libs/system/zc702evk/linux/boot.c
+++ b/libs/system/zc702evk/linux/boot.c
@@ -1,594 +1,594 @@
-#include "libfdt/types.h"
-#include "libfdt/libfdt.h"
-#include "zlib/zlib.h"
-
-/* External variables. */
-extern unsigned int _image_start;
-extern unsigned int _image_end;
-extern unsigned int _bss_start;
-extern unsigned int _bss_end;
-
-/* Definitions.*/
-#define FIT_IMAGE_START (void *)&_image_start
-#define FIT_IMAGE_END (void *)&_image_end
-
-#define BSS_START (void *)&_bss_start
-#define BSS_END (void *)&_bss_end
-
-#define BSS_SIZE (((unsigned int)BSS_END) - ((unsigned int)BSS_START))
-
-#define XILINX_ARM_MACHINE 3343
-
-#define KERNEL_RESERVED_SPACE 0x7FF2000
-
-#define PUTC(a) ((*((volatile unsigned int *) 0xE0001030)) = (a))
-
-/* Globals. */
-unsigned int linux_kernel_start, dtb_start, linux_kernel_size, dtb_size;
-
-/* Static functions. */
-static void boot_linux_fit_image(void);
-
-static int process_and_relocate_fit_image(char *image_start, unsigned int image_size);
-
-extern void start_linux_with_dtb (void);
-
-static void clear_bss(void);
-static void invalidate_cache(void);
-static void clean_system(void);
-
-void put_char(char c)
-{
- PUTC(c);
-
- while (((*((volatile unsigned int *) 0xE000102C)) & 0x00000008) == 0 );
-}
-void putstring(const char *str)
-{
- while (*str)
- {
- put_char(*str++);
- }
-}
-
-/* Boots the linux kernel. */
-void boot_linux(void)
-{
- /* Clear BSS*/
- clear_bss();
-
- clean_system();
-
- putstring("\n\r********************************* \n\r");
- putstring("OpenAMP Linux Bootstrap.");
- putstring("\n\r********************************* \n\r");
-
- /* Currently supporting only FIT image format. */
- boot_linux_fit_image();
-}
-
-/* Boots a FIT format linux image. */
-static void boot_linux_fit_image(void)
-{
- unsigned int image_size, status;
-
- char *image_start;
-
- /* Retrieve linux image start and end addresses. */
- image_start = (char *)FIT_IMAGE_START;
-
- /* Retrieve linux image size. */
- image_size = (FIT_IMAGE_END - FIT_IMAGE_START);
-
- /* Check for a valid linux image size. */
- if(image_size > 0){
-
- /* let us parse and relocate the FIT image. */
- status = process_and_relocate_fit_image(image_start, image_size);
-
- /* Image processed and relocated successfully. */
- if(!status){
-
- putstring("\n\rLinux Bootstrap: Booting Linux. \n\r");
-
- /* Image has been processed and relocated. Now boot linux*/
- start_linux_with_dtb();
- }
- else
- {
- /* Go into an error loop. */
- while(1);
- }
- }
- else
- {
- /* Go into an error loop. */
- while (1);
- }
-}
-
-
-/* Returns zero for success. */
-static int process_and_relocate_fit_image(char *image_start, unsigned int image_size)
-{
- unsigned int fit_image_start, compressed = 0;
- unsigned long kernel_address;
- int size, load_size, load_address, dtb_address;
- char *conf_name = NULL;
- void *data;
- int cfg_offset, offset, ret;
- z_stream strm;
-
-
- putstring("\n\rLinux Bootstrap: Locating Linux Kernel and DTB from FIT image.\n\r");
-
- fit_image_start = (unsigned int)image_start;
-
- /* Retrieve default FIT image configuration node. */
- offset = fdt_path_offset((const void *)fit_image_start, "/configurations");
-
- if (offset >= 0)
- {
- /* Retrieve default configuration name. */
- conf_name = (char *)fdt_getprop((const void *)fit_image_start, offset, "default", &size);
- }
-
- if(conf_name)
- {
- /* Retrieve the offset of configuration node. */
- cfg_offset = fdt_subnode_offset((const void *)fit_image_start, offset, conf_name);
- }
-
- /* Retrieve kernel node using the config node. */
- conf_name = (char *)fdt_getprop((const void *)fit_image_start, cfg_offset, "kernel", &size);
-
- if(conf_name)
- {
- offset = fdt_path_offset((const void *)fit_image_start, "/images");
-
- if(offset >= 0)
- {
- offset = fdt_subnode_offset((const void *)fit_image_start, offset, conf_name);
- }
- }
-
- if (offset >= 0)
- {
- /* Retrieve kernel image address and size. */
- kernel_address = (unsigned long)fdt_getprop((const void *)fit_image_start, offset, "data", &load_size);
-
- /* Retrieve kernel load address. */
- data = (void *)fdt_getprop((const void *)fit_image_start, offset, "load", &size);
-
- load_address = *((int *)data);
-
- load_address = be32_to_cpu(load_address);
-
- /* Check kernel image for compression. */
- data = (void *)fdt_getprop((const void *)fit_image_start, offset, "compression", &size);
-
- if(data != NULL)
- {
- if(!(strcmp(data, "gzip")))
- {
- compressed =1;
- }
- }
- }
-
- memset((void *)load_address, 0, 0x0600000 - load_address);
-
- if(compressed == 1)
- {
- putstring("\n\rLinux Bootstrap: Kernel image is compressed. Starting decompression process. It may take a while...\n\r");
-
- /* Initialize zlib stream. */
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = 0;
- strm.next_in = Z_NULL;
-
- /* Initialize the zlib state for de-compression. */
- ret = inflateInit2(&strm, MAX_WBITS + 16);
-
- if(ret == Z_OK)
- {
- strm.next_in = (Bytef*)kernel_address;
- strm.avail_out = KERNEL_RESERVED_SPACE;
- strm.avail_in = load_size;
-
- /* Pointer to output space. */
- strm.next_out = (Bytef*)load_address;
-
- /* Call the de-compression engine. */
- ret = inflate(&strm, Z_FINISH);
- }
-
- (void)inflateEnd(&strm);
-
- if((ret != Z_OK) && (ret != Z_STREAM_END)){
-
- /* return with an error. */
- return 1;
- }
-
- putstring("\n\rLinux Bootstrap: Linux image decompression complete. \n\r");
-
- }
- else
- {
- /* Uncompressed image. Just load to the load address. */
- memcpy((void *)load_address, (void *)kernel_address, load_size);
- }
-
- putstring("\n\rLinux Bootstrap: Linux kernel image has been loaded into memory. \n\r");
-
- /* Save kernel load address and size. */
- linux_kernel_start = load_address;
- linux_kernel_size = load_size;
-
-
- /* Retrieve DTB node using the config node. */
- conf_name = (char *)fdt_getprop((const void *)fit_image_start, cfg_offset, "fdt", &size);
-
- if(conf_name)
- {
- offset = fdt_path_offset((const void *)fit_image_start, "/images");
-
- if(offset >= 0)
- {
- offset = fdt_subnode_offset((const void *)fit_image_start, offset, conf_name);
- }
- }
-
- if (offset >= 0)
- {
- /* Retrieve DTB address and size. */
- dtb_address = (unsigned long )fdt_getprop((const void *)fit_image_start, offset, "data", &load_size);
- }
-
- dtb_start = (linux_kernel_start + KERNEL_RESERVED_SPACE) & 0xFFFFFF00;
- dtb_size = load_size;
-
- memcpy((void *)dtb_start, (void *)dtb_address, load_size);
-
- putstring("\n\rLinux Bootstrap: Loaded DTB. \n\r");
-
- return 0;
-}
-
-static void clear_bss(void)
-{
- memset(BSS_START, 0, BSS_SIZE);
-}
-
-/*
- * The code in this section is for invalidating the cache at startup
- *
- */
-
-/* ARM Coprocessor registers */
-#define ARM_AR_CP0 p0
-#define ARM_AR_CP1 p1
-#define ARM_AR_CP2 p2
-#define ARM_AR_CP3 p3
-#define ARM_AR_CP4 p4
-#define ARM_AR_CP5 p5
-#define ARM_AR_CP6 p6
-#define ARM_AR_CP7 p7
-#define ARM_AR_CP8 p8
-#define ARM_AR_CP9 p9
-#define ARM_AR_CP10 p10
-#define ARM_AR_CP11 p11
-#define ARM_AR_CP12 p12
-#define ARM_AR_CP13 p13
-#define ARM_AR_CP14 p14
-#define ARM_AR_CP15 p15
-
-/* CRn and CRm register values */
-#define ARM_AR_C0 c0
-#define ARM_AR_C1 c1
-#define ARM_AR_C2 c2
-#define ARM_AR_C3 c3
-#define ARM_AR_C4 c4
-#define ARM_AR_C5 c5
-#define ARM_AR_C6 c6
-#define ARM_AR_C7 c7
-#define ARM_AR_C8 c8
-#define ARM_AR_C9 c9
-#define ARM_AR_C10 c10
-#define ARM_AR_C11 c11
-#define ARM_AR_C12 c12
-#define ARM_AR_C13 c13
-#define ARM_AR_C14 c14
-#define ARM_AR_C15 c15
-
-/* This define is used to add quotes to anything passed in */
-#define ARM_AR_QUOTES(x) #x
-
-/* This macro writes to a coprocessor register */
-#define ARM_AR_CP_WRITE(cp, op1, cp_value, crn, crm, op2) \
- { \
- asm volatile(" MCR " ARM_AR_QUOTES(cp) "," \
- #op1 \
- ", %0, " \
- ARM_AR_QUOTES(crn) "," \
- ARM_AR_QUOTES(crm) "," \
- #op2 \
- : /* No outputs */ \
- : "r" (cp_value)); \
- }
-
-/* This macro reads from a coprocessor register */
-#define ARM_AR_CP_READ(cp, op1, cp_value_ptr, crn, crm, op2) \
- { \
- asm volatile(" MRC " ARM_AR_QUOTES(cp) "," \
- #op1 \
- ", %0, " \
- ARM_AR_QUOTES(crn) "," \
- ARM_AR_QUOTES(crm) "," \
- #op2 \
- : "=r" (*(unsigned long *)(cp_value_ptr)) \
- : /* No inputs */ ); \
- }
-
-/* This macro executes a ISB instruction */
-#define ARM_AR_ISB_EXECUTE() \
- { \
- asm volatile(" ISB"); \
- }
-
-/* This macro executes a DSB instruction */
-#define ARM_AR_DSB_EXECUTE() \
- { \
- asm volatile(" DSB"); \
- }
-
-/* CLIDR and CCSIDR mask values */
-#define ARM_AR_MEM_CLIDR_LOC_MASK 0x7000000
-#define ARM_AR_MEM_CCSIDR_LINESIZE_MASK 0x7
-#define ARM_AR_MEM_CCSIDR_ASSOC_MASK 0x3FF
-#define ARM_AR_MEM_CCSIDR_NUMSET_MASK 0x7FFF
-
-/* CLIDR and CCSIDR shift values */
-#define ARM_AR_MEM_CLIDR_LOC_RSHT_OFFSET 24
-#define ARM_AR_MEM_CCSIDR_ASSOC_RSHT_OFFSET 3
-#define ARM_AR_MEM_CCSIDR_NUMSET_RSHT_OFFSET 13
-
-/* Extract 'encoded' line length of the cache */
-#define ARM_AR_MEM_CCSIDR_LINESIZE_GET(ccsidr_reg) (ccsidr_reg & \
- ARM_AR_MEM_CCSIDR_LINESIZE_MASK)
-
-/* Extract 'encoded' way size of the cache */
-#define ARM_AR_MEM_CCSIDR_ASSOC_GET(ccsidr_reg) (ARM_AR_MEM_CCSIDR_ASSOC_MASK & \
- (ccsidr_reg >> \
- ARM_AR_MEM_CCSIDR_ASSOC_RSHT_OFFSET))
-
-/* Extract 'encoded' maximum number of index size */
-#define ARM_AR_MEM_CCSIDR_NUMSET_GET(ccsidr_reg) (ARM_AR_MEM_CCSIDR_NUMSET_MASK & \
- (ccsidr_reg >> \
- ARM_AR_MEM_CCSIDR_NUMSET_RSHT_OFFSET))
-
-/* Refer to chapter B3.12.31 c7, Cache and branch predictor maintenance functions in the
- ARM Architecture Reference Manual ARMv7-A and ARMv7-R Edition 1360*/
-/* Calculate # of bits to be shifted for set size and way size */
-
-/* log2(line size in bytes) = ccsidr_linesize + 2 + logbase2(4) */
-#define ARM_AR_MEM_L_CALCULATE(linesize) (linesize + 2 + 2)
-
-/* log2(nsets) = 32 - way_size_bit_pos */
-
-/* Find the bit position of way size increment */
-#define ARM_AR_MEM_A_CALCULATE(assoc, a_offset_ref) \
- { \
- unsigned int temp_pos = 0x80000000; \
- \
- *a_offset_ref = 0; \
- \
- /* Logic to count the number of leading zeros before the first 1 */ \
- while(!((assoc & temp_pos) == temp_pos)) \
- { \
- (*a_offset_ref)++; \
- temp_pos = temp_pos >> 1; \
- } \
- }
-
-/* Factor way, cache number, index number */
-#define ARM_AR_MEM_DCCISW_SET(dccisw_ref, level, numsets, assoc, l_offset, a_offset) \
- { \
- *dccisw_ref = (level | (numsets << l_offset) | (assoc << a_offset)); \
- }
-
-/* This macro extracts line size, assoc and set size from CCSIDR */
-#define ARM_AR_MEM_CCSIDR_VALS_GET(linesize_ref, assoc_ref, numsets_ref, \
- l_offset_ref, a_offset_ref) \
- { \
- unsigned int ccsidr_val; \
- \
- /* Read the selected cache's CCSIDR */ \
- ARM_AR_CP_READ(ARM_AR_CP15, 1, &ccsidr_val, \
- ARM_AR_C0, ARM_AR_C0, 0); \
- \
- /* Extract 'encoded' line length of the cache */ \
- *linesize_ref = ARM_AR_MEM_CCSIDR_LINESIZE_GET(ccsidr_val); \
- \
- /* Extract 'encoded' way size of the cache */ \
- *assoc_ref = ARM_AR_MEM_CCSIDR_ASSOC_GET(ccsidr_val); \
- \
- /* Extract 'encoded' maximum number of index size */ \
- *numsets_ref = ARM_AR_MEM_CCSIDR_NUMSET_GET(ccsidr_val); \
- \
- /* Calculate # of bits to be shifted for set size and way size */ \
- \
- /* log2(line size in bytes) = ccsidr_linesize + 2 + log2(4) */ \
- *l_offset_ref = ARM_AR_MEM_L_CALCULATE(*linesize_ref); \
- \
- /* log2(nsets) = 32 - way_size_bit_pos */ \
- ARM_AR_MEM_A_CALCULATE(*assoc_ref, a_offset_ref); \
- }
-
-/* This macro invalidates all of the instruction cache at the core level. */
-#define ARM_AR_MEM_ICACHE_ALL_INVALIDATE() \
- { \
- ARM_AR_CP_WRITE(ARM_AR_CP15, 0, \
- 0, ARM_AR_C7, \
- ARM_AR_C5, 0); \
- }
-
-
-/* This macro invalidates all of the data cache at the core level. */
-void ARM_AR_MEM_DCACHE_ALL_OP( int type)
-{
- unsigned int clidr_val = 0;
- unsigned int clidr_loc = 0;
- unsigned int cache_number = 0;
- unsigned int cache_type = 0;
- unsigned int ccsidr_linesize = 0;
- unsigned int ccsidr_assoc = 0;
- int ccsidr_numsets = 0;
- int way_size_copy = 0;
- unsigned int set_size_bit_pos = 0;
- unsigned int cache_number_pos = 0;
- unsigned int way_size_bit_pos = 0;
- unsigned int set_way_value = 0;
-
-
- /* Read CLIDR to extract level of coherence (LOC) */
- ARM_AR_CP_READ(ARM_AR_CP15, 1, &clidr_val,
- ARM_AR_C0, ARM_AR_C0, 1);
-
- /* Extract LOC from CLIDR and align it at bit 1 */
- clidr_loc = (clidr_val & ARM_AR_MEM_CLIDR_LOC_MASK) >>
- ARM_AR_MEM_CLIDR_LOC_RSHT_OFFSET;
-
- /* Proceed only iff LOC is non-zero */
- if (clidr_loc != 0)
- {
- do
- {
- /* Extract cache type from CLIDR */
- cache_number_pos = cache_number + (cache_number >> 1);
- cache_type = (clidr_val >> cache_number_pos) & 0x7;
-
- /* Continue only iff data cache */
- if (cache_type >= 2)
- {
- /* Select desired cache level in CSSELR */
- ARM_AR_CP_WRITE(ARM_AR_CP15, 2, cache_number,
- ARM_AR_C0, ARM_AR_C0, 0);
-
- ARM_AR_ISB_EXECUTE();
-
- /* Get data like linesize, assoc and set size */
- ARM_AR_MEM_CCSIDR_VALS_GET(&ccsidr_linesize,
- &ccsidr_assoc,
- &ccsidr_numsets,
- &set_size_bit_pos,
- &way_size_bit_pos);
-
- do
- {
- way_size_copy = ccsidr_assoc;
-
- do
- {
- /* Factor way, cache number, index number */
- ARM_AR_MEM_DCCISW_SET(&set_way_value, cache_number,
- ccsidr_numsets, way_size_copy,
- set_size_bit_pos,
- way_size_bit_pos);
-
- /* Execute invalidate if type = 0 */
- if (type == 0)
- {
- ARM_AR_CP_WRITE(ARM_AR_CP15, 0,
- set_way_value,
- ARM_AR_C7,
- ARM_AR_C6, 2);
- }
- else
- {
- ARM_AR_CP_WRITE(ARM_AR_CP15, 0,
- set_way_value,
- ARM_AR_C7,
- ARM_AR_C14, 2);
- }
-
- /* decrement the way */
- } while((--way_size_copy) >= 0);
-
- /* decrement the set */
- } while((--ccsidr_numsets) >= 0);
-
- } /* end if */
-
- /* Increment cache number */
- cache_number += 2;
-
- /* end do-while */
- } while(clidr_loc >= cache_number);
-
- }
-
- /* Switch back to cache level 0 in CSSELR */
- ARM_AR_CP_WRITE(ARM_AR_CP15, 2, 0,
- ARM_AR_C0, ARM_AR_C0, 0);
-
- /* Sync */
- ARM_AR_DSB_EXECUTE();
- ARM_AR_ISB_EXECUTE();
-}
-
-/* This macro invalidates all of the data cache at the core level. */
-void ARM_AR_MEM_DCACHE_ALL_INVALIDATE(void)
-{
- ARM_AR_MEM_DCACHE_ALL_OP(0);
-}
-
-/* This macro invalidates all of the cache at the core level. */
-void ARM_AR_MEM_CACHE_ALL_INVALIDATE(void)
-{
- ARM_AR_MEM_ICACHE_ALL_INVALIDATE();
- ARM_AR_MEM_DCACHE_ALL_INVALIDATE();
-}
-
-
-static void clean_system(void){
-
- invalidate_cache();
-
-}
-static void invalidate_cache(void)
-{
- ARM_AR_MEM_CACHE_ALL_INVALIDATE();
-}
+#include "libfdt/types.h"
+#include "libfdt/libfdt.h"
+#include "zlib/zlib.h"
+
+/* External variables. */
+extern unsigned int _image_start;
+extern unsigned int _image_end;
+extern unsigned int _bss_start;
+extern unsigned int _bss_end;
+
+/* Definitions.*/
+#define FIT_IMAGE_START (void *)&_image_start
+#define FIT_IMAGE_END (void *)&_image_end
+
+#define BSS_START (void *)&_bss_start
+#define BSS_END (void *)&_bss_end
+
+#define BSS_SIZE (((unsigned int)BSS_END) - ((unsigned int)BSS_START))
+
+#define XILINX_ARM_MACHINE 3343
+
+#define KERNEL_RESERVED_SPACE 0x7FF2000
+
+#define PUTC(a) ((*((volatile unsigned int *) 0xE0001030)) = (a))
+
+/* Globals. */
+unsigned int linux_kernel_start, dtb_start, linux_kernel_size, dtb_size;
+
+/* Static functions. */
+static void boot_linux_fit_image(void);
+
+static int process_and_relocate_fit_image(char *image_start, unsigned int image_size);
+
+extern void start_linux_with_dtb (void);
+
+static void clear_bss(void);
+static void invalidate_cache(void);
+static void clean_system(void);
+
+void put_char(char c)
+{
+ PUTC(c);
+
+ while (((*((volatile unsigned int *) 0xE000102C)) & 0x00000008) == 0 );
+}
+void putstring(const char *str)
+{
+ while (*str)
+ {
+ put_char(*str++);
+ }
+}
+
+/* Boots the linux kernel. */
+void boot_linux(void)
+{
+ /* Clear BSS*/
+ clear_bss();
+
+ clean_system();
+
+ putstring("\n\r********************************* \n\r");
+ putstring("OpenAMP Linux Bootstrap.");
+ putstring("\n\r********************************* \n\r");
+
+ /* Currently supporting only FIT image format. */
+ boot_linux_fit_image();
+}
+
+/* Boots a FIT format linux image. */
+static void boot_linux_fit_image(void)
+{
+ unsigned int image_size, status;
+
+ char *image_start;
+
+ /* Retrieve linux image start and end addresses. */
+ image_start = (char *)FIT_IMAGE_START;
+
+ /* Retrieve linux image size. */
+ image_size = (FIT_IMAGE_END - FIT_IMAGE_START);
+
+ /* Check for a valid linux image size. */
+ if(image_size > 0){
+
+ /* let us parse and relocate the FIT image. */
+ status = process_and_relocate_fit_image(image_start, image_size);
+
+ /* Image processed and relocated successfully. */
+ if(!status){
+
+ putstring("\n\rLinux Bootstrap: Booting Linux. \n\r");
+
+ /* Image has been processed and relocated. Now boot linux*/
+ start_linux_with_dtb();
+ }
+ else
+ {
+ /* Go into an error loop. */
+ while(1);
+ }
+ }
+ else
+ {
+ /* Go into an error loop. */
+ while (1);
+ }
+}
+
+
+/* Returns zero for success. */
+static int process_and_relocate_fit_image(char *image_start, unsigned int image_size)
+{
+ unsigned int fit_image_start, compressed = 0;
+ unsigned long kernel_address;
+ int size, load_size, load_address, dtb_address;
+ char *conf_name = NULL;
+ void *data;
+ int cfg_offset, offset, ret;
+ z_stream strm;
+
+
+ putstring("\n\rLinux Bootstrap: Locating Linux Kernel and DTB from FIT image.\n\r");
+
+ fit_image_start = (unsigned int)image_start;
+
+ /* Retrieve default FIT image configuration node. */
+ offset = fdt_path_offset((const void *)fit_image_start, "/configurations");
+
+ if (offset >= 0)
+ {
+ /* Retrieve default configuration name. */
+ conf_name = (char *)fdt_getprop((const void *)fit_image_start, offset, "default", &size);
+ }
+
+ if(conf_name)
+ {
+ /* Retrieve the offset of configuration node. */
+ cfg_offset = fdt_subnode_offset((const void *)fit_image_start, offset, conf_name);
+ }
+
+ /* Retrieve kernel node using the config node. */
+ conf_name = (char *)fdt_getprop((const void *)fit_image_start, cfg_offset, "kernel", &size);
+
+ if(conf_name)
+ {
+ offset = fdt_path_offset((const void *)fit_image_start, "/images");
+
+ if(offset >= 0)
+ {
+ offset = fdt_subnode_offset((const void *)fit_image_start, offset, conf_name);
+ }
+ }
+
+ if (offset >= 0)
+ {
+ /* Retrieve kernel image address and size. */
+ kernel_address = (unsigned long)fdt_getprop((const void *)fit_image_start, offset, "data", &load_size);
+
+ /* Retrieve kernel load address. */
+ data = (void *)fdt_getprop((const void *)fit_image_start, offset, "load", &size);
+
+ load_address = *((int *)data);
+
+ load_address = be32_to_cpu(load_address);
+
+ /* Check kernel image for compression. */
+ data = (void *)fdt_getprop((const void *)fit_image_start, offset, "compression", &size);
+
+ if(data != NULL)
+ {
+ if(!(strcmp(data, "gzip")))
+ {
+ compressed =1;
+ }
+ }
+ }
+
+ memset((void *)load_address, 0, 0x0600000 - load_address);
+
+ if(compressed == 1)
+ {
+ putstring("\n\rLinux Bootstrap: Kernel image is compressed. Starting decompression process. It may take a while...\n\r");
+
+ /* Initialize zlib stream. */
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = 0;
+ strm.next_in = Z_NULL;
+
+ /* Initialize the zlib state for de-compression. */
+ ret = inflateInit2(&strm, MAX_WBITS + 16);
+
+ if(ret == Z_OK)
+ {
+ strm.next_in = (Bytef*)kernel_address;
+ strm.avail_out = KERNEL_RESERVED_SPACE;
+ strm.avail_in = load_size;
+
+ /* Pointer to output space. */
+ strm.next_out = (Bytef*)load_address;
+
+ /* Call the de-compression engine. */
+ ret = inflate(&strm, Z_FINISH);
+ }
+
+ (void)inflateEnd(&strm);
+
+ if((ret != Z_OK) && (ret != Z_STREAM_END)){
+
+ /* return with an error. */
+ return 1;
+ }
+
+ putstring("\n\rLinux Bootstrap: Linux image decompression complete. \n\r");
+
+ }
+ else
+ {
+ /* Uncompressed image. Just load to the load address. */
+ memcpy((void *)load_address, (void *)kernel_address, load_size);
+ }
+
+ putstring("\n\rLinux Bootstrap: Linux kernel image has been loaded into memory. \n\r");
+
+ /* Save kernel load address and size. */
+ linux_kernel_start = load_address;
+ linux_kernel_size = load_size;
+
+
+ /* Retrieve DTB node using the config node. */
+ conf_name = (char *)fdt_getprop((const void *)fit_image_start, cfg_offset, "fdt", &size);
+
+ if(conf_name)
+ {
+ offset = fdt_path_offset((const void *)fit_image_start, "/images");
+
+ if(offset >= 0)
+ {
+ offset = fdt_subnode_offset((const void *)fit_image_start, offset, conf_name);
+ }
+ }
+
+ if (offset >= 0)
+ {
+ /* Retrieve DTB address and size. */
+ dtb_address = (unsigned long )fdt_getprop((const void *)fit_image_start, offset, "data", &load_size);
+ }
+
+ dtb_start = (linux_kernel_start + KERNEL_RESERVED_SPACE) & 0xFFFFFF00;
+ dtb_size = load_size;
+
+ memcpy((void *)dtb_start, (void *)dtb_address, load_size);
+
+ putstring("\n\rLinux Bootstrap: Loaded DTB. \n\r");
+
+ return 0;
+}
+
+static void clear_bss(void)
+{
+ memset(BSS_START, 0, BSS_SIZE);
+}
+
+/*
+ * The code in this section is for invalidating the cache at startup
+ *
+ */
+
+/* ARM Coprocessor registers */
+#define ARM_AR_CP0 p0
+#define ARM_AR_CP1 p1
+#define ARM_AR_CP2 p2
+#define ARM_AR_CP3 p3
+#define ARM_AR_CP4 p4
+#define ARM_AR_CP5 p5
+#define ARM_AR_CP6 p6
+#define ARM_AR_CP7 p7
+#define ARM_AR_CP8 p8
+#define ARM_AR_CP9 p9
+#define ARM_AR_CP10 p10
+#define ARM_AR_CP11 p11
+#define ARM_AR_CP12 p12
+#define ARM_AR_CP13 p13
+#define ARM_AR_CP14 p14
+#define ARM_AR_CP15 p15
+
+/* CRn and CRm register values */
+#define ARM_AR_C0 c0
+#define ARM_AR_C1 c1
+#define ARM_AR_C2 c2
+#define ARM_AR_C3 c3
+#define ARM_AR_C4 c4
+#define ARM_AR_C5 c5
+#define ARM_AR_C6 c6
+#define ARM_AR_C7 c7
+#define ARM_AR_C8 c8
+#define ARM_AR_C9 c9
+#define ARM_AR_C10 c10
+#define ARM_AR_C11 c11
+#define ARM_AR_C12 c12
+#define ARM_AR_C13 c13
+#define ARM_AR_C14 c14
+#define ARM_AR_C15 c15
+
+/* This define is used to add quotes to anything passed in */
+#define ARM_AR_QUOTES(x) #x
+
+/* This macro writes to a coprocessor register */
+#define ARM_AR_CP_WRITE(cp, op1, cp_value, crn, crm, op2) \
+ { \
+ asm volatile(" MCR " ARM_AR_QUOTES(cp) "," \
+ #op1 \
+ ", %0, " \
+ ARM_AR_QUOTES(crn) "," \
+ ARM_AR_QUOTES(crm) "," \
+ #op2 \
+ : /* No outputs */ \
+ : "r" (cp_value)); \
+ }
+
+/* This macro reads from a coprocessor register */
+#define ARM_AR_CP_READ(cp, op1, cp_value_ptr, crn, crm, op2) \
+ { \
+ asm volatile(" MRC " ARM_AR_QUOTES(cp) "," \
+ #op1 \
+ ", %0, " \
+ ARM_AR_QUOTES(crn) "," \
+ ARM_AR_QUOTES(crm) "," \
+ #op2 \
+ : "=r" (*(unsigned long *)(cp_value_ptr)) \
+ : /* No inputs */ ); \
+ }
+
+/* This macro executes a ISB instruction */
+#define ARM_AR_ISB_EXECUTE() \
+ { \
+ asm volatile(" ISB"); \
+ }
+
+/* This macro executes a DSB instruction */
+#define ARM_AR_DSB_EXECUTE() \
+ { \
+ asm volatile(" DSB"); \
+ }
+
+/* CLIDR and CCSIDR mask values */
+#define ARM_AR_MEM_CLIDR_LOC_MASK 0x7000000
+#define ARM_AR_MEM_CCSIDR_LINESIZE_MASK 0x7
+#define ARM_AR_MEM_CCSIDR_ASSOC_MASK 0x3FF
+#define ARM_AR_MEM_CCSIDR_NUMSET_MASK 0x7FFF
+
+/* CLIDR and CCSIDR shift values */
+#define ARM_AR_MEM_CLIDR_LOC_RSHT_OFFSET 24
+#define ARM_AR_MEM_CCSIDR_ASSOC_RSHT_OFFSET 3
+#define ARM_AR_MEM_CCSIDR_NUMSET_RSHT_OFFSET 13
+
+/* Extract 'encoded' line length of the cache */
+#define ARM_AR_MEM_CCSIDR_LINESIZE_GET(ccsidr_reg) (ccsidr_reg & \
+ ARM_AR_MEM_CCSIDR_LINESIZE_MASK)
+
+/* Extract 'encoded' way size of the cache */
+#define ARM_AR_MEM_CCSIDR_ASSOC_GET(ccsidr_reg) (ARM_AR_MEM_CCSIDR_ASSOC_MASK & \
+ (ccsidr_reg >> \
+ ARM_AR_MEM_CCSIDR_ASSOC_RSHT_OFFSET))
+
+/* Extract 'encoded' maximum number of index size */
+#define ARM_AR_MEM_CCSIDR_NUMSET_GET(ccsidr_reg) (ARM_AR_MEM_CCSIDR_NUMSET_MASK & \
+ (ccsidr_reg >> \
+ ARM_AR_MEM_CCSIDR_NUMSET_RSHT_OFFSET))
+
+/* Refer to chapter B3.12.31 c7, Cache and branch predictor maintenance functions in the
+ ARM Architecture Reference Manual ARMv7-A and ARMv7-R Edition 1360*/
+/* Calculate # of bits to be shifted for set size and way size */
+
+/* log2(line size in bytes) = ccsidr_linesize + 2 + logbase2(4) */
+#define ARM_AR_MEM_L_CALCULATE(linesize) (linesize + 2 + 2)
+
+/* log2(nsets) = 32 - way_size_bit_pos */
+
+/* Find the bit position of way size increment */
+#define ARM_AR_MEM_A_CALCULATE(assoc, a_offset_ref) \
+ { \
+ unsigned int temp_pos = 0x80000000; \
+ \
+ *a_offset_ref = 0; \
+ \
+ /* Logic to count the number of leading zeros before the first 1 */ \
+ while(!((assoc & temp_pos) == temp_pos)) \
+ { \
+ (*a_offset_ref)++; \
+ temp_pos = temp_pos >> 1; \
+ } \
+ }
+
+/* Factor way, cache number, index number */
+#define ARM_AR_MEM_DCCISW_SET(dccisw_ref, level, numsets, assoc, l_offset, a_offset) \
+ { \
+ *dccisw_ref = (level | (numsets << l_offset) | (assoc << a_offset)); \
+ }
+
+/* This macro extracts line size, assoc and set size from CCSIDR */
+#define ARM_AR_MEM_CCSIDR_VALS_GET(linesize_ref, assoc_ref, numsets_ref, \
+ l_offset_ref, a_offset_ref) \
+ { \
+ unsigned int ccsidr_val; \
+ \
+ /* Read the selected cache's CCSIDR */ \
+ ARM_AR_CP_READ(ARM_AR_CP15, 1, &ccsidr_val, \
+ ARM_AR_C0, ARM_AR_C0, 0); \
+ \
+ /* Extract 'encoded' line length of the cache */ \
+ *linesize_ref = ARM_AR_MEM_CCSIDR_LINESIZE_GET(ccsidr_val); \
+ \
+ /* Extract 'encoded' way size of the cache */ \
+ *assoc_ref = ARM_AR_MEM_CCSIDR_ASSOC_GET(ccsidr_val); \
+ \
+ /* Extract 'encoded' maximum number of index size */ \
+ *numsets_ref = ARM_AR_MEM_CCSIDR_NUMSET_GET(ccsidr_val); \
+ \
+ /* Calculate # of bits to be shifted for set size and way size */ \
+ \
+ /* log2(line size in bytes) = ccsidr_linesize + 2 + log2(4) */ \
+ *l_offset_ref = ARM_AR_MEM_L_CALCULATE(*linesize_ref); \
+ \
+ /* log2(nsets) = 32 - way_size_bit_pos */ \
+ ARM_AR_MEM_A_CALCULATE(*assoc_ref, a_offset_ref); \
+ }
+
+/* This macro invalidates all of the instruction cache at the core level. */
+#define ARM_AR_MEM_ICACHE_ALL_INVALIDATE() \
+ { \
+ ARM_AR_CP_WRITE(ARM_AR_CP15, 0, \
+ 0, ARM_AR_C7, \
+ ARM_AR_C5, 0); \
+ }
+
+
+/* This macro invalidates all of the data cache at the core level. */
+void ARM_AR_MEM_DCACHE_ALL_OP( int type)
+{
+ unsigned int clidr_val = 0;
+ unsigned int clidr_loc = 0;
+ unsigned int cache_number = 0;
+ unsigned int cache_type = 0;
+ unsigned int ccsidr_linesize = 0;
+ unsigned int ccsidr_assoc = 0;
+ int ccsidr_numsets = 0;
+ int way_size_copy = 0;
+ unsigned int set_size_bit_pos = 0;
+ unsigned int cache_number_pos = 0;
+ unsigned int way_size_bit_pos = 0;
+ unsigned int set_way_value = 0;
+
+
+ /* Read CLIDR to extract level of coherence (LOC) */
+ ARM_AR_CP_READ(ARM_AR_CP15, 1, &clidr_val,
+ ARM_AR_C0, ARM_AR_C0, 1);
+
+ /* Extract LOC from CLIDR and align it at bit 1 */
+ clidr_loc = (clidr_val & ARM_AR_MEM_CLIDR_LOC_MASK) >>
+ ARM_AR_MEM_CLIDR_LOC_RSHT_OFFSET;
+
+ /* Proceed only iff LOC is non-zero */
+ if (clidr_loc != 0)
+ {
+ do
+ {
+ /* Extract cache type from CLIDR */
+ cache_number_pos = cache_number + (cache_number >> 1);
+ cache_type = (clidr_val >> cache_number_pos) & 0x7;
+
+ /* Continue only iff data cache */
+ if (cache_type >= 2)
+ {
+ /* Select desired cache level in CSSELR */
+ ARM_AR_CP_WRITE(ARM_AR_CP15, 2, cache_number,
+ ARM_AR_C0, ARM_AR_C0, 0);
+
+ ARM_AR_ISB_EXECUTE();
+
+ /* Get data like linesize, assoc and set size */
+ ARM_AR_MEM_CCSIDR_VALS_GET(&ccsidr_linesize,
+ &ccsidr_assoc,
+ &ccsidr_numsets,
+ &set_size_bit_pos,
+ &way_size_bit_pos);
+
+ do
+ {
+ way_size_copy = ccsidr_assoc;
+
+ do
+ {
+ /* Factor way, cache number, index number */
+ ARM_AR_MEM_DCCISW_SET(&set_way_value, cache_number,
+ ccsidr_numsets, way_size_copy,
+ set_size_bit_pos,
+ way_size_bit_pos);
+
+ /* Execute invalidate if type = 0 */
+ if (type == 0)
+ {
+ ARM_AR_CP_WRITE(ARM_AR_CP15, 0,
+ set_way_value,
+ ARM_AR_C7,
+ ARM_AR_C6, 2);
+ }
+ else
+ {
+ ARM_AR_CP_WRITE(ARM_AR_CP15, 0,
+ set_way_value,
+ ARM_AR_C7,
+ ARM_AR_C14, 2);
+ }
+
+ /* decrement the way */
+ } while((--way_size_copy) >= 0);
+
+ /* decrement the set */
+ } while((--ccsidr_numsets) >= 0);
+
+ } /* end if */
+
+ /* Increment cache number */
+ cache_number += 2;
+
+ /* end do-while */
+ } while(clidr_loc >= cache_number);
+
+ }
+
+ /* Switch back to cache level 0 in CSSELR */
+ ARM_AR_CP_WRITE(ARM_AR_CP15, 2, 0,
+ ARM_AR_C0, ARM_AR_C0, 0);
+
+ /* Sync */
+ ARM_AR_DSB_EXECUTE();
+ ARM_AR_ISB_EXECUTE();
+}
+
+/* This macro invalidates all of the data cache at the core level. */
+void ARM_AR_MEM_DCACHE_ALL_INVALIDATE(void)
+{
+ ARM_AR_MEM_DCACHE_ALL_OP(0);
+}
+
+/* This macro invalidates all of the cache at the core level. */
+void ARM_AR_MEM_CACHE_ALL_INVALIDATE(void)
+{
+ ARM_AR_MEM_ICACHE_ALL_INVALIDATE();
+ ARM_AR_MEM_DCACHE_ALL_INVALIDATE();
+}
+
+
+static void clean_system(void){
+
+ invalidate_cache();
+
+}
+static void invalidate_cache(void)
+{
+ ARM_AR_MEM_CACHE_ALL_INVALIDATE();
+}
diff --git a/libs/system/zc702evk/linux/rsc_table.c b/libs/system/zc702evk/linux/rsc_table.c
index 7e08efb..9e8ffc6 100644
--- a/libs/system/zc702evk/linux/rsc_table.c
+++ b/libs/system/zc702evk/linux/rsc_table.c
@@ -1,89 +1,89 @@
-/* This file populates resource table for BM remotes
- * for use by the Linux Master */
-
-#include "open_amp.h"
-#include "rsc_table.h"
-
-/* Place resource table in special ELF section */
-#define __section(S) __attribute__((__section__(#S)))
-#define __resource __section(.resource_table)
-
-#define RPMSG_IPU_C0_FEATURES 1
-
-/* VirtIO rpmsg device id */
-#define VIRTIO_ID_RPMSG_ 7
-
-/* Remote supports Name Service announcement */
-#define VIRTIO_RPMSG_F_NS 0
-
-/* Resource table entries */
-#define ELF_START 0x00000000
-#define ELF_END 0x08000000
-#define NUM_VRINGS 0x02
-#define VRING_ALIGN 0x1000
-#define RING_TX 0x08000000
-#define RING_RX 0x08004000
-#define VRING_SIZE 256
-
-const struct remote_resource_table __resource resources =
-{
- /* Version */
- 1,
-
- /* NUmber of table entries */
- 2,
- /* reserved fields */
- { 0, 0,},
-
- /* Offsets of rsc entries */
- {
- offsetof(struct remote_resource_table, elf_cout),
- offsetof(struct remote_resource_table, rpmsg_vdev),
- },
-
- /* End of ELF file */
- {
- RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT",
- },
-
- /* Virtio device entry */
- { RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},
- },
-
- /* Vring rsc entry - part of vdev rsc entry */
- {
- RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0
- },
- {
- RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0
- },
-};
+/* This file populates resource table for BM remotes
+ * for use by the Linux Master */
+
+#include "open_amp.h"
+#include "rsc_table.h"
+
+/* Place resource table in special ELF section */
+#define __section(S) __attribute__((__section__(#S)))
+#define __resource __section(.resource_table)
+
+#define RPMSG_IPU_C0_FEATURES 1
+
+/* VirtIO rpmsg device id */
+#define VIRTIO_ID_RPMSG_ 7
+
+/* Remote supports Name Service announcement */
+#define VIRTIO_RPMSG_F_NS 0
+
+/* Resource table entries */
+#define ELF_START 0x00000000
+#define ELF_END 0x08000000
+#define NUM_VRINGS 0x02
+#define VRING_ALIGN 0x1000
+#define RING_TX 0x08000000
+#define RING_RX 0x08004000
+#define VRING_SIZE 256
+
+const struct remote_resource_table __resource resources =
+{
+ /* Version */
+ 1,
+
+ /* NUmber of table entries */
+ 2,
+ /* reserved fields */
+ { 0, 0,},
+
+ /* Offsets of rsc entries */
+ {
+ offsetof(struct remote_resource_table, elf_cout),
+ offsetof(struct remote_resource_table, rpmsg_vdev),
+ },
+
+ /* End of ELF file */
+ {
+ RSC_CARVEOUT, ELF_START, ELF_START, ELF_END, 0, 0, "ELF_COUT",
+ },
+
+ /* Virtio device entry */
+ { RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0, NUM_VRINGS, {0, 0},
+ },
+
+ /* Vring rsc entry - part of vdev rsc entry */
+ {
+ RING_TX, VRING_ALIGN, VRING_SIZE, 1, 0
+ },
+ {
+ RING_RX, VRING_ALIGN, VRING_SIZE, 2, 0
+ },
+};
diff --git a/libs/system/zc702evk/linux/rsc_table.h b/libs/system/zc702evk/linux/rsc_table.h
index 0a8e957..842b423 100644
--- a/libs/system/zc702evk/linux/rsc_table.h
+++ b/libs/system/zc702evk/linux/rsc_table.h
@@ -1,51 +1,51 @@
-/* This file populates resource table for BM remote
- * for use by the Linux Master */
-
-#include <stddef.h>
-#include "open_amp.h"
-
-#define NO_RESOURCE_ENTRIES 8
-
-/* Resource table for the given remote */
-struct remote_resource_table {
- unsigned int version;
- unsigned int num;
- unsigned int reserved[2];
- unsigned int offset[NO_RESOURCE_ENTRIES];
- /* text carveout entry */
- struct fw_rsc_carveout elf_cout;
- /* rpmsg vdev entry */
- struct fw_rsc_vdev rpmsg_vdev;
- struct fw_rsc_vdev_vring rpmsg_vring0;
- struct fw_rsc_vdev_vring rpmsg_vring1;
-};
-
+/* This file populates resource table for BM remote
+ * for use by the Linux Master */
+
+#include <stddef.h>
+#include "open_amp.h"
+
+#define NO_RESOURCE_ENTRIES 8
+
+/* Resource table for the given remote */
+struct remote_resource_table {
+ unsigned int version;
+ unsigned int num;
+ unsigned int reserved[2];
+ unsigned int offset[NO_RESOURCE_ENTRIES];
+ /* text carveout entry */
+ struct fw_rsc_carveout elf_cout;
+ /* rpmsg vdev entry */
+ struct fw_rsc_vdev rpmsg_vdev;
+ struct fw_rsc_vdev_vring rpmsg_vring0;
+ struct fw_rsc_vdev_vring rpmsg_vring1;
+};
+
diff --git a/porting/config/config.c b/porting/config/config.c
index 38e72f5..0f28479 100644
--- a/porting/config/config.c
+++ b/porting/config/config.c
@@ -1,95 +1,95 @@
- * config.c
- *
- * COMPONENT
- *
- * OpenAMP stack.
- *
- * DESCRIPTION
- *
- *
- *
- * @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;
+ * config.c
+ *
+ * COMPONENT
+ *
+ * OpenAMP stack.
+ *
+ * DESCRIPTION
+ *
+ *
+ **************************************************************************/
+
+#include "config.h"
+ *
+ * @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;
}
diff --git a/porting/config/config.h b/porting/config/config.h
index 4eb3f83..6bba03e 100644
--- a/porting/config/config.h
+++ b/porting/config/config.h
@@ -1,59 +1,59 @@
-#ifndef CONFIG_H
-#define CONFIG_H
-
-#include "../env/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
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "../env/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
diff --git a/porting/env/env.h b/porting/env/env.h
index c90b74c..a02ad37 100644
--- a/porting/env/env.h
+++ b/porting/env/env.h
@@ -1,429 +1,429 @@
diff --git a/porting/zc702evk/platform.c b/porting/zc702evk/platform.c
index 90d1190..4db5e5e 100644
--- a/porting/zc702evk/platform.c
+++ b/porting/zc702evk/platform.c
@@ -1,132 +1,132 @@
- * platform.c
- *
- * DESCRIPTION
- *
- * This file is the Implementation of IPC hardware layer interface
- * for Xilinx Zynq ZC702EVK platform.
- *
- **************************************************************************/
-
-#include "platform.h"
-
-/*--------------------------- Globals ---------------------------------- */
-struct hil_platform_ops proc_ops = {
- .enable_interrupt = _enable_interrupt,
- .notify = _notify,
- .boot_cpu = _boot_cpu,
- .shutdown_cpu = _shutdown_cpu,
-};
-
-int _enable_interrupt(struct proc_vring *vring_hw) {
-
- /* Register ISR*/
- env_register_isr(vring_hw->intr_info.vect_id, vring_hw, platform_isr);
-
- /* Enable the interrupts */
- env_enable_interrupt(vring_hw->intr_info.vect_id,
- vring_hw->intr_info.priority,
- vring_hw->intr_info.trigger_type);
- return 0;
-}
-
-void _notify(int cpu_id, struct proc_intr *intr_info) {
-
- unsigned long mask = 0;
-
- mask = ((1 << (GIC_CPU_ID_BASE + cpu_id)) | (intr_info->vect_id))
- & (GIC_SFI_TRIG_CPU_MASK | GIC_SFI_TRIG_INTID_MASK);
-
- HIL_MEM_WRITE32((GIC_DIST_BASE + GIC_DIST_SOFTINT), mask);
-}
-
-extern char zynq_trampoline;
-extern char zynq_trampoline_jump;
-extern char zynq_trampoline_end;
-
-int _boot_cpu(int cpu_id, unsigned int load_addr) {
- unsigned int reg;
- unsigned int tramp_size;
- unsigned int tramp_addr = 0;
-
- if (load_addr) {
- tramp_size = zynq_trampoline_end - zynq_trampoline;
- if ((load_addr < tramp_size) || (load_addr & 0x3)) {
- return -1;
- }
-
- tramp_size = &zynq_trampoline_jump - &zynq_trampoline;
-
- /*
- * Trampoline code is copied to address 0 from where remote core is expected to
- * fetch first instruction after reset.If master is using the address 0 then
- * this mem copy will screwed the system. It is user responsibility to not
- * copy trampoline code in such cases.
- *
- */
- env_memcpy((char *)tramp_addr, &zynq_trampoline, tramp_size);
- /* Write image address at the word reserved at the trampoline end */
- HIL_MEM_WRITE32((char *)(tramp_addr + tramp_size), load_addr);
- }
-
- unlock_slcr();
-
- reg = HIL_MEM_READ32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL);
- reg &= ~(A9_CPU_SLCR_CLK_STOP << cpu_id);
- HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
- /* De-assert reset signal and start clock to start the core */
- reg &= ~(A9_CPU_SLCR_RST << cpu_id);
- HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
-
- lock_slcr();
-
- return 0;
-}
-
-void _shutdown_cpu(int cpu_id) {
- unsigned int reg;
-
- unlock_slcr();
-
- reg = HIL_MEM_READ32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL);
- /* Assert reset signal and stop clock to halt the core */
- reg |= (A9_CPU_SLCR_CLK_STOP | A9_CPU_SLCR_RST) << cpu_id;
- HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
-
- lock_slcr();
-}
-
-void platform_isr(int vect_id, void *data) {
- hil_isr(((struct proc_vring *) data));
-}
+ * platform.c
+ *
+ * DESCRIPTION
+ *
+ * This file is the Implementation of IPC hardware layer interface
+ * for Xilinx Zynq ZC702EVK platform.
+ *
+ **************************************************************************/
+
+#include "platform.h"
+
+/*--------------------------- Globals ---------------------------------- */
+struct hil_platform_ops proc_ops = {
+ .enable_interrupt = _enable_interrupt,
+ .notify = _notify,
+ .boot_cpu = _boot_cpu,
+ .shutdown_cpu = _shutdown_cpu,
+};
+
+int _enable_interrupt(struct proc_vring *vring_hw) {
+
+ /* Register ISR*/
+ env_register_isr(vring_hw->intr_info.vect_id, vring_hw, platform_isr);
+
+ /* Enable the interrupts */
+ env_enable_interrupt(vring_hw->intr_info.vect_id,
+ vring_hw->intr_info.priority,
+ vring_hw->intr_info.trigger_type);
+ return 0;
+}
+
+void _notify(int cpu_id, struct proc_intr *intr_info) {
+
+ unsigned long mask = 0;
+
+ mask = ((1 << (GIC_CPU_ID_BASE + cpu_id)) | (intr_info->vect_id))
+ & (GIC_SFI_TRIG_CPU_MASK | GIC_SFI_TRIG_INTID_MASK);
+
+ HIL_MEM_WRITE32((GIC_DIST_BASE + GIC_DIST_SOFTINT), mask);
+}
+
+extern char zynq_trampoline;
+extern char zynq_trampoline_jump;
+extern char zynq_trampoline_end;
+
+int _boot_cpu(int cpu_id, unsigned int load_addr) {
+ unsigned int reg;
+ unsigned int tramp_size;
+ unsigned int tramp_addr = 0;
+
+ if (load_addr) {
+ tramp_size = zynq_trampoline_end - zynq_trampoline;
+ if ((load_addr < tramp_size) || (load_addr & 0x3)) {
+ return -1;
+ }
+
+ tramp_size = &zynq_trampoline_jump - &zynq_trampoline;
+
+ /*
+ * Trampoline code is copied to address 0 from where remote core is expected to
+ * fetch first instruction after reset.If master is using the address 0 then
+ * this mem copy will screwed the system. It is user responsibility to not
+ * copy trampoline code in such cases.
+ *
+ */
+ env_memcpy((char *)tramp_addr, &zynq_trampoline, tramp_size);
+ /* Write image address at the word reserved at the trampoline end */
+ HIL_MEM_WRITE32((char *)(tramp_addr + tramp_size), load_addr);
+ }
+
+ unlock_slcr();
+
+ reg = HIL_MEM_READ32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL);
+ reg &= ~(A9_CPU_SLCR_CLK_STOP << cpu_id);
+ HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
+ /* De-assert reset signal and start clock to start the core */
+ reg &= ~(A9_CPU_SLCR_RST << cpu_id);
+ HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
+
+ lock_slcr();
+
+ return 0;
+}
+
+void _shutdown_cpu(int cpu_id) {
+ unsigned int reg;
+
+ unlock_slcr();
+
+ reg = HIL_MEM_READ32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL);
+ /* Assert reset signal and stop clock to halt the core */
+ reg |= (A9_CPU_SLCR_CLK_STOP | A9_CPU_SLCR_RST) << cpu_id;
+ HIL_MEM_WRITE32(ESAL_DP_SLCR_BASE + A9_CPU_SLCR_RESET_CTRL, reg);
+
+ lock_slcr();
+}
+
+void platform_isr(int vect_id, void *data) {
+ hil_isr(((struct proc_vring *) data));
+}
diff --git a/porting/zc702evk/platform.h b/porting/zc702evk/platform.h
index 8ddb231..4a3b10d 100644
--- a/porting/zc702evk/platform.h
+++ b/porting/zc702evk/platform.h
@@ -1,124 +1,124 @@
+#include "../common/hil/hil.h"
diff --git a/porting/zc702evk/platform_info.c b/porting/zc702evk/platform_info.c
index eba0ba5..c37df1d 100644
--- a/porting/zc702evk/platform_info.c
+++ b/porting/zc702evk/platform_info.c
@@ -1,233 +1,233 @@
- * platform_info.c
- *
- * DESCRIPTION
- *
- * This file implements APIs to get platform specific
- * information for OpenAMP.
- *
- **************************************************************************/
-
-#include "platform.h"
-
-/* Reference implementation that show cases platform_get_cpu_info and
- platform_get_for_firmware API implementation for Bare metal environment */
-
-extern struct hil_platform_ops proc_ops;
-
-/* IPC Device parameters */
-#define SHM_ADDR (void *)0x08008000
-#define SHM_SIZE 0x00200000
-#define VRING0_IPI_VECT 15
-#define VRING1_IPI_VECT 14
-#define MASTER_CPU_ID 0
-#define REMOTE_CPU_ID 1
-
-/**
- * This array provdes defnition of CPU nodes for master and remote
- * context. It contains two nodes beacuse the same file is intended
- * to use with both master and remote configurations. On zynq platform
- * only one node defintion is required for master/remote as there
- * are only two cores present in the platform.
- *
+ * platform_info.c
+ *
+ * DESCRIPTION
+ *
+ * This file implements APIs to get platform specific
+ * information for OpenAMP.
+ *
+ **************************************************************************/
+
+#include "platform.h"
+
+/* Reference implementation that show cases platform_get_cpu_info and
+ platform_get_for_firmware API implementation for Bare metal environment */
+
+extern struct hil_platform_ops proc_ops;
+
+/* IPC Device parameters */
+#define SHM_ADDR (void *)0x08008000
+#define SHM_SIZE 0x00200000
+#define VRING0_IPI_VECT 15
+#define VRING1_IPI_VECT 14
+#define MASTER_CPU_ID 0
+#define REMOTE_CPU_ID 1
+
+/**
+ * This array provdes defnition of CPU nodes for master and remote
+ * context. It contains two nodes beacuse the same file is intended
+ * to use with both master and remote configurations. On zynq platform
+ * only one node defintion is required for master/remote as there
+ * are only two cores present in the platform.
+ *
* Only platform specific info is populated here. Rest of information
- * is obtained during resource table parsing.The platform specific
- * information includes;
- *
- * -CPU ID
- * -Shared Memory
- * -Interrupts
- * -Channel info.
- *
- * Although the channel info is not platform specific information
- * but it is conveneient to keep it in HIL so that user can easily
- * provide it without modifying the generic part.
- *
- * It is good idea to define hil_proc structure with platform
- * specific fields populated as this can be easily copied to hil_proc
- * structure passed as parameter in platform_get_processor_info. The
- * other option is to populate the required structures individually
- * and copy them one by one to hil_proc structure in platform_get_processor_info
- * function. The first option is adopted here.
- *
- *
- * 1) First node in the array is intended for the remote contexts and it
- * defines Master CPU ID, shared memory, interrupts info, number of channels
- * and there names. This node defines only one channel
- * "rpmsg-openamp-demo-channel".
- *
- * 2)Second node is required by the master and it defines remote CPU ID,
- * shared memory and interrupts info. In general no channel info is required by the
- * Master node, however in baremetal master and linux remote case the linux
- * rpmsg bus driver behaves as master so the rpmsg driver on linux side still needs
- * channel info. This information is not required by the masters for baremetal
- * remotes.
- *
- */
-struct hil_proc proc_table []=
-{
-
- /* CPU node for remote context */
- {
-
- /* Number of RPMSG channels */
- 1,
-
- /* RPMSG channel info - Only channel name is expected currently */
- {
- {"rpmsg-openamp-demo-channel"}
- },
-
- /* HIL platform ops table. */
- &proc_ops,
-
- /* Next three fields are for future use only */
- 0,
- 0,
- NULL
- },
-
- /* CPU node for remote context */
- {
-
- /* Number of RPMSG channels */
- 1,
-
- /* RPMSG channel info - Only channel name is expected currently */
- {
- {"rpmsg-openamp-demo-channel"}
- },
-
- /* HIL platform ops table. */
- &proc_ops,
-
- /* Next three fields are for future use only */
- 0,
- 0,
- NULL
- }
-};
-
-/**
- * platform_get_processor_info
- *
- * Copies the target info from the user defined data structures to
- * HIL proc data structure.In case of remote contexts this function
- * is called with the reserved CPU ID HIL_RSVD_CPU_ID, because for
- * remotes there is only one master.
- *
- * @param proc - HIL proc to populate
- * @param cpu_id - CPU ID
- *
- * return - status of execution
- */
-int platform_get_processor_info(struct hil_proc *proc , int cpu_id) {
- int idx;
- for(idx = 0; idx < sizeof(proc_table)/sizeof(struct hil_proc); idx++) {
- if((cpu_id == HIL_RSVD_CPU_ID) || (proc_table[idx].cpu_id == cpu_id) ) {
- env_memcpy(proc,&proc_table[idx], sizeof(struct hil_proc));
- return 0;
- }
- }
- return -1;
-}
-
-int platform_get_processor_for_fw(char *fw_name) {
-
- return 1;
-}
+ * is obtained during resource table parsing.The platform specific
+ * information includes;
+ *
+ * -CPU ID
+ * -Shared Memory
+ * -Interrupts
+ * -Channel info.
+ *
+ * Although the channel info is not platform specific information
+ * but it is conveneient to keep it in HIL so that user can easily
+ * provide it without modifying the generic part.
+ *
+ * It is good idea to define hil_proc structure with platform
+ * specific fields populated as this can be easily copied to hil_proc
+ * structure passed as parameter in platform_get_processor_info. The
+ * other option is to populate the required structures individually
+ * and copy them one by one to hil_proc structure in platform_get_processor_info
+ * function. The first option is adopted here.
+ *
+ *
+ * 1) First node in the array is intended for the remote contexts and it
+ * defines Master CPU ID, shared memory, interrupts info, number of channels
+ * and there names. This node defines only one channel
+ * "rpmsg-openamp-demo-channel".
+ *
+ * 2)Second node is required by the master and it defines remote CPU ID,
+ * shared memory and interrupts info. In general no channel info is required by the
+ * Master node, however in baremetal master and linux remote case the linux
+ * rpmsg bus driver behaves as master so the rpmsg driver on linux side still needs
+ * channel info. This information is not required by the masters for baremetal
+ * remotes.
+ *
+ */
+struct hil_proc proc_table []=
+{
+
+ /* CPU node for remote context */
+ {
+ }
+ },
+ {
+ NULL, NULL, 0, 0,
+ {
+ VRING1_IPI_VECT,0x1006,1,NULL
+ }
+ }
+ }
+ },
+
+ /* Number of RPMSG channels */
+ 1,
+
+ /* RPMSG channel info - Only channel name is expected currently */
+ {
+ {"rpmsg-openamp-demo-channel"}
+ },
+
+ /* HIL platform ops table. */
+ &proc_ops,
+
+ /* Next three fields are for future use only */
+ 0,
+ 0,
+ NULL
+ },
+
+ /* CPU node for remote context */
+ {
+ /* CPU ID of remote */
+ REMOTE_CPU_ID,
+
+ /* Shared memory info - Last field is not used currently */
+ {
+ SHM_ADDR, SHM_SIZE, 0x00
+ },
+
+ /* VirtIO device info */
+ {
+ 0, 0, 0,
+ {
+ {
+ /* Provide vring interrupts info here. Other fields are obtained
+ * from the rsc table so leave them empty.
+ */
+ NULL, NULL, 0, 0,
+ {
+ VRING0_IPI_VECT,0x1006,1
+ }
+ },
+ {
+ NULL, NULL, 0, 0,
+ {
+ VRING1_IPI_VECT,0x1006,1
+ }
+ }
+ }
+ },
+
+ /* Number of RPMSG channels */
+ 1,
+
+ /* RPMSG channel info - Only channel name is expected currently */
+ {
+ {"rpmsg-openamp-demo-channel"}
+ },
+
+ /* HIL platform ops table. */
+ &proc_ops,
+
+ /* Next three fields are for future use only */
+ 0,
+ 0,
+ NULL
+ }
+};
+
+/**
+ * platform_get_processor_info
+ *
+ * Copies the target info from the user defined data structures to
+ * HIL proc data structure.In case of remote contexts this function
+ * is called with the reserved CPU ID HIL_RSVD_CPU_ID, because for
+ * remotes there is only one master.
+ *
+ * @param proc - HIL proc to populate
+ * @param cpu_id - CPU ID
+ *
+ * return - status of execution
+ */
+int platform_get_processor_info(struct hil_proc *proc , int cpu_id) {
+ int idx;
+ for(idx = 0; idx < sizeof(proc_table)/sizeof(struct hil_proc); idx++) {
+ if((cpu_id == HIL_RSVD_CPU_ID) || (proc_table[idx].cpu_id == cpu_id) ) {
+ env_memcpy(proc,&proc_table[idx], sizeof(struct hil_proc));
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int platform_get_processor_for_fw(char *fw_name) {
+
+ return 1;
+}
diff --git a/remoteproc/elf_loader.c b/remoteproc/elf_loader.c
index a551d23..7d4a21d 100644
--- a/remoteproc/elf_loader.c
+++ b/remoteproc/elf_loader.c
@@ -1,643 +1,643 @@
-#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;
-}
+#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;
+}
diff --git a/remoteproc/elf_loader.h b/remoteproc/elf_loader.h
index 8584368..003751c 100644
--- a/remoteproc/elf_loader.h
+++ b/remoteproc/elf_loader.h
@@ -1,234 +1,234 @@
+#include "remoteproc_loader.h"
diff --git a/remoteproc/remoteproc_loader.c b/remoteproc/remoteproc_loader.c
index a8f8707..487c913 100644
--- a/remoteproc/remoteproc_loader.c
+++ b/remoteproc/remoteproc_loader.c
@@ -1,241 +1,241 @@
-#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;
- }
-}
+#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;
+ }
+}
diff --git a/remoteproc/remoteproc_loader.h b/remoteproc/remoteproc_loader.h
index eca849c..eeb7bb3 100644
--- a/remoteproc/remoteproc_loader.h
+++ b/remoteproc/remoteproc_loader.h
@@ -1,92 +1,92 @@
+#include "remoteproc.h"
diff --git a/remoteproc/rsc_table_parser.h b/remoteproc/rsc_table_parser.h
index 4e436c8..2ed6fec 100644
--- a/remoteproc/rsc_table_parser.h
+++ b/remoteproc/rsc_table_parser.h
@@ -1,53 +1,53 @@
+#include "remoteproc.h"
+#include "../porting/env/env.h"
+#include "../common/hil/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 */
diff --git a/rpmsg/Makefile b/rpmsg/Makefile
index afd0589..2de6516 100644
--- a/rpmsg/Makefile
+++ b/rpmsg/Makefile
@@ -1,36 +1,36 @@
-# Make file to create rpmsg library.
-
-# Include commons make file to get platform and tool chain specific variables.
-include ../Makefile.commons
-
-LIB := librpmsg.a
-
-# Include the header and source files required by the virtio lib.
-HEADERS += \
-$(wildcard *.h) \
-$(wildcard ../include/*.h) \
-$(wildcard ../hil/*.h) \
-$(wildcard ../env/*.h)
-
-SRCFILES += \
-$(wildcard *.c) \
-$(wildcard ../hil/*/*.c) \
-$(wildcard ../common/*.c) \
-$(wildcard ../env/*.c)
-
-OBJFILES := $(patsubst %.c, %.o, $(SRCFILES))
-
-all: $(LIB)
-
-$(LIB): $(OBJFILES)
- @echo AR $@
- @$(AR) -r $@ $(OBJFILES)
-
-%.o:%.c $(HEADERS)
- @echo CC $(<:.c=.o)
- @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
-
-clean:
- -$(RM) $(LIB) $(OBJFILES)
-
+# Make file to create rpmsg library.
+
+# Include commons make file to get platform and tool chain specific variables.
+include ../Makefile.commons
+
+LIB := librpmsg.a
+
+# Include the header and source files required by the virtio lib.
+HEADERS += \
+$(wildcard *.h) \
+$(wildcard ../include/*.h) \
+$(wildcard ../hil/*.h) \
+$(wildcard ../env/*.h)
+
+SRCFILES += \
+$(wildcard *.c) \
+$(wildcard ../hil/*/*.c) \
+$(wildcard ../common/*.c) \
+$(wildcard ../env/*.c)
+
+OBJFILES := $(patsubst %.c, %.o, $(SRCFILES))
+
+all: $(LIB)
+
+$(LIB): $(OBJFILES)
+ @echo AR $@
+ @$(AR) -r $@ $(OBJFILES)
+
+%.o:%.c $(HEADERS)
+ @echo CC $(<:.c=.o)
+ @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+
+clean:
+ -$(RM) $(LIB) $(OBJFILES)
+
PHONY: all clean
\ No newline at end of file
diff --git a/rpmsg/remote_device.c b/rpmsg/remote_device.c
index d7f6945..29e721c 100644
--- a/rpmsg/remote_device.c
+++ b/rpmsg/remote_device.c
@@ -1,514 +1,514 @@
-/**************************************************************************
- * 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) {
-
-}
-
-uint32_t rpmsg_rdev_get_feature(struct virtio_device *dev) {
- return dev->features;
-}
-
-void rpmsg_rdev_set_feature(struct virtio_device *dev, uint32_t feature) {
- dev->features |= feature;
-}
-
-uint32_t rpmsg_rdev_negotiate_feature(struct virtio_device *dev,
- uint32_t 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, uint32_t offset,
- void *dst, int length) {
- return;
-}
-void rpmsg_rdev_write_config(struct virtio_device *dev, uint32_t offset,
- void *src, int length) {
- return;
-}
-void rpmsg_rdev_reset(struct virtio_device *dev) {
- return;
-}
+/**************************************************************************
+ * 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) {
+
+}
+
+uint32_t rpmsg_rdev_get_feature(struct virtio_device *dev) {
+ return dev->features;
+}
+
+void rpmsg_rdev_set_feature(struct virtio_device *dev, uint32_t feature) {
+ dev->features |= feature;
+}
+
+uint32_t rpmsg_rdev_negotiate_feature(struct virtio_device *dev,
+ uint32_t 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, uint32_t offset,
+ void *dst, int length) {
+ return;
+}
+void rpmsg_rdev_write_config(struct virtio_device *dev, uint32_t offset,
+ void *src, int length) {
+ return;
+}
+void rpmsg_rdev_reset(struct virtio_device *dev) {
+ return;
+}
diff --git a/rpmsg/rpmsg.c b/rpmsg/rpmsg.c
index 630f110..0066fca 100644
--- a/rpmsg/rpmsg.c
+++ b/rpmsg/rpmsg.c
@@ -1,414 +1,414 @@
- * 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;
- unsigned long 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;
-}
+ * 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;
+ unsigned long 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;
+}
diff --git a/rpmsg/rpmsg_core.h b/rpmsg/rpmsg_core.h
index 891ebb0..91718d8 100644
--- a/rpmsg/rpmsg_core.h
+++ b/rpmsg/rpmsg_core.h
@@ -1,190 +1,190 @@
+#include "../porting/env/env.h"
+#include "../virtio/virtio.h"
+#include "../common/hil/hil.h"
+#include "../common/shm/sh_mem.h"
+#include "../common/llist/llist.h"
+#include "rpmsg.h"
diff --git a/virtio/Makefile b/virtio/Makefile
index 523a2b3..2d16388 100644
--- a/virtio/Makefile
+++ b/virtio/Makefile
@@ -1,34 +1,34 @@
-# Make file to create virtio library.
-
-# Include commons make file to get platform and tool chain specific variables.
-include ../Makefile.commons
-
-LIB := libvirtio.a
-
-# Include the header and source files required by the virtio lib.
-HEADERS += \
-$(wildcard *.h) \
-$(wildcard ../hil/*.h) \
-$(wildcard ../env/*.h)
-
-SRCFILES += \
-$(wildcard *.c) \
-$(wildcard ../hil/*/*.c) \
-$(wildcard ../env/*.c)
-
-OBJFILES := $(patsubst %.c, %.o, $(SRCFILES))
-
-all: $(LIB)
-
-$(LIB): $(OBJFILES)
- @echo AR $@
- @$(AR) -r $@ $(OBJFILES)
-
-%.o:%.c $(HEADERS)
- @echo CC $(<:.c=.o)
- @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
-
-clean:
- -$(RM) $(LIB) $(OBJFILES)
-
+# Make file to create virtio library.
+
+# Include commons make file to get platform and tool chain specific variables.
+include ../Makefile.commons
+
+LIB := libvirtio.a
+
+# Include the header and source files required by the virtio lib.
+HEADERS += \
+$(wildcard *.h) \
+$(wildcard ../hil/*.h) \
+$(wildcard ../env/*.h)
+
+SRCFILES += \
+$(wildcard *.c) \
+$(wildcard ../hil/*/*.c) \
+$(wildcard ../env/*.c)
+
+OBJFILES := $(patsubst %.c, %.o, $(SRCFILES))
+
+all: $(LIB)
+
+$(LIB): $(OBJFILES)
+ @echo AR $@
+ @$(AR) -r $@ $(OBJFILES)
+
+%.o:%.c $(HEADERS)
+ @echo CC $(<:.c=.o)
+ @$(CC) $(CFLAGS) $(ARCH_CFLAGS) $(INCLUDE) -c $< -o $@
+
+clean:
+ -$(RM) $(LIB) $(OBJFILES)
+
PHONY: all clean
\ No newline at end of file
diff --git a/virtio/virtio.h b/virtio/virtio.h
index 19ea191..ab11dcd 100644
--- a/virtio/virtio.h
+++ b/virtio/virtio.h
@@ -1,151 +1,151 @@
+#include "virtqueue.h"
diff --git a/virtio/virtio_ring.h b/virtio/virtio_ring.h
index 966602a..8e902ab 100644
--- a/virtio/virtio_ring.h
+++ b/virtio/virtio_ring.h
@@ -1,165 +1,165 @@
diff --git a/virtio/virtqueue.c b/virtio/virtqueue.c
index 4286b4d..5bc91cd 100644
--- a/virtio/virtqueue.c
+++ b/virtio/virtqueue.c
@@ -1,691 +1,691 @@
-/*-
- * Copyright (c) 2011, Bryan Venteicher <bry...@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, uint32_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,
- uint32_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);
-}
+/*-
+ * Copyright (c) 2011, Bryan Venteicher <bry...@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, uint32_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,
+ uint32_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);
+}
diff --git a/virtio/virtqueue.h b/virtio/virtqueue.h
index 3362d5e..d86dbb8 100644
--- a/virtio/virtqueue.h
+++ b/virtio/virtqueue.h
@@ -1,226 +1,226 @@
+#include "virtio_ring.h"
+#include "../porting/env/env.h"
+#include "../common/llist/llist.h"
--
1.9.1