Exemplo n.º 1
0
/**
 * 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);
}
Exemplo n.º 2
0
/**
 * _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;
}
Exemplo n.º 3
0
/**
 * 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);
}