diff --git a/packages/ti/ipc/family/tci6638/VirtQueue.c b/packages/ti/ipc/family/tci6638/VirtQueue.c
index ab8d90062729501c5a568cb2727f28261ab0a57d..804bf48059e1e10d4964ece36726761a8528a72b 100644 (file)
/*
- * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * Copyright (c) 2011-2019 Texas Instruments Incorporated - http://www.ti.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
/** ============================================================================
* @file VirtQueue.c
*
* @brief Virtio Queue implementation for BIOS
*
* Differences between BIOS version and Linux kernel (include/linux/virtio.h):
- * - Renamed module from virtio.h to VirtQueue_Object.h to match the API prefixes;
- * - BIOS (XDC) types and CamelCasing used;
- * - virtio_device concept removed (i.e, assumes no containing device);
- * - simplified scatterlist from Linux version;
- * - VirtQueue_Objects are created statically here, so just added a VirtQueue_Object_init()
- * fxn to take the place of the Virtio vring_new_virtqueue() API;
+ * - Renamed module from virtio.h to VirtQueue.h to match the API prefixes
+ * - XDC Standard Types and CamelCasing used
+ * - virtio_device concept removed (i.e, assumes no containing device)
+ * - simplified scatterlist from Linux version
+ * - VirtQueue objects are created statically, added VirtQueue_Instance_init()
+ * fxn to take the place of the Virtio vring_new_virtqueue() API
* - The notify function is implicit in the implementation, and not provided
- * by the client, as it is in Linux virtio.
+ * by the client, as it is in Linux virtio
*
* All VirtQueue operations can be called in any context.
- *
- * The virtio header should be included in an application as follows:
- * @code
- * #include <ti/ipc/rpmsg/VirtQueue.h>
- * @endcode
- *
*/
#include <xdc/std.h>
#include <xdc/runtime/Memory.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Diags.h>
-#include <xdc/runtime/SysMin.h>
#include <ti/sysbios/gates/GateAll.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/family/c66/Cache.h>
#include <ti/sysbios/knl/Swi.h>
-#include <ti/sdo/ipc/notifyDrivers/IInterrupt.h>
-#include <ti/ipc/family/tci6638/Interrupt.h>
#include <ti/ipc/remoteproc/Resource.h>
#include <ti/ipc/MultiProc.h>
#include <ti/ipc/rpmsg/virtio_ring.h>
/* Used for defining the size of the virtqueue registry */
-#define NUM_QUEUES 2
+#define NUM_QUEUES 2
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define RP_MSG_BUFS_SPACE (VirtQueue_RP_MSG_NUM_BUFS * RPMSG_BUF_SIZE * 2)
/* With 256 buffers, our vring will occupy 3 pages */
-#define RP_MSG_RING_SIZE ((DIV_ROUND_UP(vring_size(VirtQueue_RP_MSG_NUM_BUFS, \
- VirtQueue_RP_MSG_VRING_ALIGN), VirtQueue_PAGE_SIZE)) * VirtQueue_PAGE_SIZE)
+#define RP_MSG_RING_SIZE \
+ ((DIV_ROUND_UP(vring_size(VirtQueue_RP_MSG_NUM_BUFS, \
+ VirtQueue_RP_MSG_VRING_ALIGN), \
+ VirtQueue_PAGE_SIZE)) * VirtQueue_PAGE_SIZE)
/* The total IPC space needed to communicate with a remote processor */
#define RPMSG_IPC_MEM (RP_MSG_BUFS_SPACE + 2 * RP_MSG_RING_SIZE)
-#define ID_DSP_TO_A9 0
-#define ID_A9_TO_DSP 1
+#define ID_SELF_TO_HOST 0
+#define ID_HOST_TO_SELF 1
-extern volatile cregister Uns DNUM;
+extern volatile cregister UInt DNUM;
static VirtQueue_Object *queueRegistry[NUM_QUEUES] = {NULL};
Void VirtQueue_init()
{
extern cregister volatile UInt DNUM;
+ UInt16 clusterId;
UInt16 procId;
- /*
- * VirtQueue_init() must be called before MultiProcSetup_init().
- * (Check the xdc_runtime_Startup_firstFxns__A in the XDC generated code)
- * Abort if the procId has already been set. We must set it!
+ /* VirtQueue_init() must be called before MultiProcSetup_init().
+ * Check the xdc_runtime_Startup_firstFxns__A array in the XDC
+ * generated code. Abort if the procId has already been set; we
+ * must set it!
*/
if (MultiProc_self() != MultiProc_INVALIDID) {
System_abort("VirtQueue_init(): MultiProc_self already set!");
return;
}
- procId = DNUM + 1;
+ /* clusterId is needed to support single image loading */
+ clusterId = MultiProc_getBaseIdOfCluster();
- /* Set the local ID */
+ /* compute local procId, add one to account for HOST processor */
+ procId = clusterId + DNUM + 1;
+
+ /* set the local procId */
MultiProc_setLocalId(procId);
}
const VirtQueue_Params *params, Error_Block *eb)
{
void *vringAddr = NULL;
+#if !defined(xdc_runtime_Assert_DISABLE_ALL) \
+ || !defined(xdc_runtime_Log_DISABLE_ALL)
UInt32 marValue;
+#endif
VirtQueue_module->traceBufPtr = Resource_getTraceBufPtr();
- /* Create the thread protection gate */
+
+ /* create the thread protection gate */
vq->gateH = GateAll_create(NULL, eb);
if (Error_check(eb)) {
Log_error0("VirtQueue_create: could not create gate object");
vq->swiHandle = params->swiHandle;
switch (vq->id) {
- case ID_DSP_TO_A9:
- case ID_A9_TO_DSP:
+ case ID_SELF_TO_HOST:
+ case ID_HOST_TO_SELF:
vringAddr = (struct vring *)Resource_getVringDA(vq->id);
Assert_isTrue(vringAddr != NULL, NULL);
+#ifdef PER_CORE_VRING_PATCH
/* Add per core offset: must match on host side: */
vringAddr = (struct vring *)((UInt32)vringAddr +
(DNUM * VirtQueue_VRING_OFFSET));
-
+#endif
/* Also, assert that the vring address is non-cached: */
+#if !defined(xdc_runtime_Assert_DISABLE_ALL) \
+ || !defined(xdc_runtime_Log_DISABLE_ALL)
marValue = Cache_getMar((Ptr)vringAddr);
+#endif
Log_print1(Diags_USER1, "Vring cache is %s",
(IArg)(marValue & 0x1 ? "enabled" : "disabled"));
Assert_isTrue(!(marValue & 0x1), NULL);
return(0);
}
- Log_print3(Diags_USER1,
- "vring: %d 0x%x (0x%x)\n", vq->id, (IArg)vringAddr,
+ Log_print3(Diags_USER1, "vring: %d 0x%x (0x%x)", vq->id, (IArg)vringAddr,
RP_MSG_RING_SIZE);
- vring_init(vq->vringPtr, VirtQueue_RP_MSG_NUM_BUFS, vringAddr, VirtQueue_RP_MSG_VRING_ALIGN);
+ vring_init(vq->vringPtr, VirtQueue_RP_MSG_NUM_BUFS, vringAddr,
+ VirtQueue_RP_MSG_VRING_ALIGN);
queueRegistry[vq->id] = vq;
return(0);
Void VirtQueue_kick(VirtQueue_Handle vq)
{
struct vring *vring = vq->vringPtr;
- IInterrupt_IntInfo intInfo;
/* For now, simply interrupt remote processor */
if (vring->avail->flags & VRING_AVAIL_F_NO_INTERRUPT) {
- Log_print0(Diags_USER1,
- "VirtQueue_kick: no kick because of VRING_AVAIL_F_NO_INTERRUPT\n");
+ Log_print0(Diags_USER1, "VirtQueue_kick: no kick because of "
+ "VRING_AVAIL_F_NO_INTERRUPT");
return;
}
- Log_print2(Diags_USER1,
- "VirtQueue_kick: Sending interrupt to proc %d with payload 0x%x\n",
- (IArg)vq->procId, (IArg)vq->id);
+ Log_print2(Diags_USER1, "VirtQueue_kick: Sending interrupt to proc %d "
+ "with payload 0x%x", (IArg)vq->procId, (IArg)vq->id);
- intInfo.localIntId = Interrupt_SRCS_BITPOS_CORE0;
- Interrupt_intSend(vq->procId, &intInfo, vq->id);
+ VirtQueue_InterruptProxy_intSend(vq->procId, NULL, 0);
}
/*
IArg key;
key = GateAll_enter(vq->gateH);
- if ((head > vring->num) || (head < 0)) {
+ if (((unsigned int)head > vring->num) || (head < 0)) {
Error_raise(NULL, Error_E_generic, 0, 0);
}
else {
IArg key;
key = GateAll_enter(vq->gateH);
- Log_print6(Diags_USER1, "getAvailBuf vq: 0x%x %d %d %d 0x%x 0x%x\n",
- (IArg)vq,
- vq->last_avail_idx, vring->avail->idx, vring->num,
- (IArg)&vring->avail, (IArg)vring->avail);
+ Log_print6(Diags_USER1, "getAvailBuf vq: 0x%x %d %d %d 0x%x 0x%x",
+ (IArg)vq, (IArg)vq->last_avail_idx, (IArg)vring->avail->idx,
+ (IArg)vring->num, (IArg)&vring->avail, (IArg)vring->avail);
/* Clear flag here to avoid race condition with remote processor.
* This is a negative flag, clearing it means that we want to
* ======== VirtQueue_isr ========
* Note 'msg' is ignored: it is only used where there is a mailbox payload.
*/
-Void VirtQueue_isr(UArg msg)
+static Void VirtQueue_isr(UArg msg)
{
VirtQueue_Object *vq;
- Log_print1(Diags_USER1, "VirtQueue_isr received msg = 0x%x\n", msg);
+ Log_print1(Diags_USER1, "VirtQueue_isr received msg = 0x%x", msg);
vq = queueRegistry[0];
if (vq) {
/*
* ======== VirtQueue_startup ========
*/
-Void VirtQueue_startup(UInt16 remoteProcId, Bool isHost)
+Void VirtQueue_startup(UInt16 procId, Bool isHost)
{
- IInterrupt_IntInfo intInfo;
-
- intInfo.intVectorId = Interrupt_DSPINT;
- intInfo.localIntId = Interrupt_SRCS_BITPOS_HOST;
-
- /*
- * Wait for first kick from host, which happens to coincide with the
+ /* Wait for first kick from host, which happens to coincide with the
* priming of host's receive buffers, indicating host is ready to send.
* Since interrupt is cleared, we throw away this first kick, which is
* OK since we don't process this in the ISR anyway.
*/
- Log_print0(Diags_USER1, "VirtQueue_startup: Polling for host int...\n");
- while (!Interrupt_checkAndClear(remoteProcId, &intInfo));
-
- Interrupt_intRegister(remoteProcId, &intInfo, (Fxn)VirtQueue_isr, NULL);
+ Log_print0(Diags_USER1, "VirtQueue_startup: Polling for host int...");
+ while (!VirtQueue_InterruptProxy_intClear(procId, NULL));
- Log_print0(Diags_USER1, "Passed VirtQueue_startup\n");
+ VirtQueue_InterruptProxy_intRegister(procId, NULL, (Fxn)VirtQueue_isr, 0);
+ Log_print0(Diags_USER1, "Passed VirtQueue_startup");
}
/* By convention, Host VirtQueues host are the even number in the pair */
/* Flush the cache of the SysMin buffer only: */
Assert_isTrue((VirtQueue_module->traceBufPtr != NULL), NULL);
- Cache_wb(VirtQueue_module->traceBufPtr, SysMin_bufSize, Cache_Type_ALL,
+ Cache_wb(VirtQueue_module->traceBufPtr, Resource_getTraceBufSize(), Cache_Type_ALL,
FALSE);
}