/** * rpmsg_send_ns_message * * Sends name service announcement to remote device * * @param rdev - pointer to remote device * @param rp_chnl - pointer to rpmsg channel * @param flags - Channel creation/deletion flags * */ void rpmsg_send_ns_message(struct remote_device *rdev, struct rpmsg_channel *rp_chnl, unsigned long flags) { struct rpmsg_hdr *rp_hdr; struct rpmsg_ns_msg *ns_msg; unsigned short idx; int len; env_lock_mutex(rdev->lock); /* Get Tx buffer. */ rp_hdr = (struct rpmsg_hdr *) rpmsg_get_tx_buffer(rdev, &len, &idx); if (!rp_hdr) return; /* Fill out name service data. */ rp_hdr->dst = RPMSG_NS_EPT_ADDR; rp_hdr->len = sizeof(struct rpmsg_ns_msg); ns_msg = (struct rpmsg_ns_msg *) rp_hdr->data; env_strncpy(ns_msg->name, rp_chnl->name, sizeof(rp_chnl->name)); ns_msg->flags = flags; ns_msg->addr = rp_chnl->src; /* Place the buffer on virtqueue. */ rpmsg_enqueue_buffer(rdev, rp_hdr, len, idx); /* Notify the other side that it has data to process. */ virtqueue_kick(rdev->tvq); env_unlock_mutex(rdev->lock); }
/** * _rpmsg_create_channel * * Creates new rpmsg channel with the given parameters. * * @param rdev - pointer to remote device which contains the channel * @param name - name of the device * @param src - source address for the rpmsg channel * @param dst - destination address for the rpmsg channel * * @return - pointer to new rpmsg channel * */ struct rpmsg_channel *_rpmsg_create_channel(struct remote_device *rdev, char *name, unsigned long src, unsigned long dst) { struct rpmsg_channel *rp_chnl; struct llist *node; rp_chnl = env_allocate_memory(sizeof(struct rpmsg_channel)); if (rp_chnl) { env_memset(rp_chnl, 0x00, sizeof(struct rpmsg_channel)); env_strncpy(rp_chnl->name, name, sizeof(rp_chnl->name)); rp_chnl->src = src; rp_chnl->dst = dst; rp_chnl->rdev = rdev; /* Place channel on channels list */ node = env_allocate_memory(sizeof(struct llist)); if (!node) { env_free_memory(rp_chnl); return RPMSG_NULL ; } node->data = rp_chnl; env_lock_mutex(rdev->lock); add_to_list(&rdev->rp_channels , node); env_unlock_mutex(rdev->lock); } return rp_chnl; }
/** * 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); }