1 /*
2 * Copyright (c) 2014, Mentor Graphics Corporation
3 * All rights reserved.
4 * Copyright (c) 2015 Xilinx, Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. Neither the name of Mentor Graphics Corporation nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
31 /**************************************************************************
32 * FILE NAME
33 *
34 * rpmsg_core.c
35 *
36 * COMPONENT
37 *
38 * OpenAMP
39 *
40 * DESCRIPTION
41 *
42 * This file provides the core functionality of RPMSG messaging part like
43 * message parsing ,Rx/Tx callbacks handling , channel creation/deletion
44 * and address management.
45 *
46 *
47 **************************************************************************/
48 #include "openamp/rpmsg.h"
50 /* Internal functions */
51 static void rpmsg_rx_callback(struct virtqueue *vq);
52 static void rpmsg_tx_callback(struct virtqueue *vq);
54 /**
55 * rpmsg_start_ipc
56 *
57 * This function creates communication links(virtqueues) for remote device
58 * and notifies it to start IPC.
59 *
60 * @param rdev - remote device handle
61 *
62 * @return - status of function execution
63 *
64 */
65 int rpmsg_start_ipc(struct remote_device *rdev)
66 {
67 struct virtio_device *virt_dev;
68 struct rpmsg_endpoint *ns_ept;
69 void (*callback[2]) (struct virtqueue * vq);
70 const char *vq_names[2];
71 unsigned long dev_features;
72 int status;
73 struct virtqueue *vqs[2];
74 int i;
76 virt_dev = &rdev->virt_dev;
78 /* Initialize names and callbacks based on the device role */
79 if (rdev->role == RPMSG_MASTER) {
80 vq_names[0] = "tx_vq";
81 vq_names[1] = "rx_vq";
82 callback[0] = rpmsg_tx_callback;
83 callback[1] = rpmsg_rx_callback;
84 } else {
85 vq_names[0] = "rx_vq";
86 vq_names[1] = "tx_vq";
87 callback[0] = rpmsg_rx_callback;
88 callback[1] = rpmsg_tx_callback;
89 }
91 /* Create virtqueues for remote device */
92 status = virt_dev->func->create_virtqueues(virt_dev, 0,
93 RPMSG_MAX_VQ_PER_RDEV,
94 vq_names, callback,
95 RPMSG_NULL);
96 if (status != RPMSG_SUCCESS) {
97 return status;
98 }
100 dev_features = virt_dev->func->get_features(virt_dev);
102 /*
103 * Create name service announcement endpoint if device supports name
104 * service announcement feature.
105 */
106 if ((dev_features & (1 << VIRTIO_RPMSG_F_NS))) {
107 rdev->support_ns = RPMSG_TRUE;
108 ns_ept = _create_endpoint(rdev, rpmsg_ns_callback, rdev,
109 RPMSG_NS_EPT_ADDR);
110 if (!ns_ept) {
111 return RPMSG_ERR_NO_MEM;
112 }
113 }
115 /* Initialize notifications for vring. */
116 if (rdev->role == RPMSG_MASTER) {
117 vqs[0] = rdev->tvq;
118 vqs[1] = rdev->rvq;
119 } else {
120 vqs[0] = rdev->rvq;
121 vqs[1] = rdev->tvq;
122 }
123 for (i = 0; i <= 1; i++) {
124 status = hil_enable_vring_notifications(i, vqs[i]);
125 if (status != RPMSG_SUCCESS) {
126 return status;
127 }
128 }
130 status = rpmsg_rdev_notify(rdev);
132 return status;
133 }
135 /**
136 * _rpmsg_create_channel
137 *
138 * Creates new rpmsg channel with the given parameters.
139 *
140 * @param rdev - pointer to remote device which contains the channel
141 * @param name - name of the device
142 * @param src - source address for the rpmsg channel
143 * @param dst - destination address for the rpmsg channel
144 *
145 * @return - pointer to new rpmsg channel
146 *
147 */
148 struct rpmsg_channel *_rpmsg_create_channel(struct remote_device *rdev,
149 char *name, unsigned long src,
150 unsigned long dst)
151 {
152 struct rpmsg_channel *rp_chnl;
153 struct llist *node;
155 rp_chnl = env_allocate_memory(sizeof(struct rpmsg_channel));
156 if (rp_chnl) {
157 env_memset(rp_chnl, 0x00, sizeof(struct rpmsg_channel));
158 env_strncpy(rp_chnl->name, name, sizeof(rp_chnl->name));
159 rp_chnl->src = src;
160 rp_chnl->dst = dst;
161 rp_chnl->rdev = rdev;
162 /* Place channel on channels list */
163 node = env_allocate_memory(sizeof(struct llist));
164 if (!node) {
165 env_free_memory(rp_chnl);
166 return RPMSG_NULL;
167 }
168 node->data = rp_chnl;
169 env_lock_mutex(rdev->lock);
170 add_to_list(&rdev->rp_channels, node);
171 env_unlock_mutex(rdev->lock);
172 }
174 return rp_chnl;
175 }
177 /**
178 * _rpmsg_delete_channel
179 *
180 * Deletes given rpmsg channel.
181 *
182 * @param rp_chnl - pointer to rpmsg channel to delete
183 *
184 * return - none
185 */
186 void _rpmsg_delete_channel(struct rpmsg_channel *rp_chnl)
187 {
188 struct llist *node;
189 if (rp_chnl) {
190 node =
191 rpmsg_rdev_get_chnl_node_from_id(rp_chnl->rdev,
192 rp_chnl->name);
193 if (node) {
194 env_lock_mutex(rp_chnl->rdev->lock);
195 remove_from_list(&rp_chnl->rdev->rp_channels, node);
196 env_unlock_mutex(rp_chnl->rdev->lock);
197 env_free_memory(node);
198 }
199 env_free_memory(rp_chnl);
200 }
201 }
203 /**
204 * _create_endpoint
205 *
206 * This function creates rpmsg endpoint.
207 *
208 * @param rdev - pointer to remote device
209 * @param cb - Rx completion call back
210 * @param priv - private data
211 * @param addr - endpoint src address
212 *
213 * @return - pointer to endpoint control block
214 *
215 */
216 struct rpmsg_endpoint *_create_endpoint(struct remote_device *rdev,
217 rpmsg_rx_cb_t cb, void *priv,
218 unsigned long addr)
219 {
221 struct rpmsg_endpoint *rp_ept;
222 struct llist *node;
223 int status = RPMSG_SUCCESS;
225 rp_ept = env_allocate_memory(sizeof(struct rpmsg_endpoint));
226 if (!rp_ept) {
227 return RPMSG_NULL;
228 }
229 env_memset(rp_ept, 0x00, sizeof(struct rpmsg_endpoint));
231 node = env_allocate_memory(sizeof(struct llist));
232 if (!node) {
233 env_free_memory(rp_ept);
234 return RPMSG_NULL;
235 }
237 env_lock_mutex(rdev->lock);
239 if (addr != RPMSG_ADDR_ANY) {
240 /*
241 * Application has requested a particular src address for endpoint,
242 * first check if address is available.
243 */
244 if (!rpmsg_is_address_set
245 (rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr)) {
246 /* Mark the address as used in the address bitmap. */
247 rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE,
248 addr);
250 } else {
251 status = RPMSG_ERR_DEV_ADDR;
252 }
253 } else {
254 addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE);
255 if (addr < 0) {
256 status = RPMSG_ERR_DEV_ADDR;
257 }
258 }
260 /* Do cleanup in case of error and return */
261 if (status) {
262 env_free_memory(node);
263 env_free_memory(rp_ept);
264 env_unlock_mutex(rdev->lock);
265 return RPMSG_NULL;
266 }
268 rp_ept->addr = addr;
269 rp_ept->cb = cb;
270 rp_ept->priv = priv;
272 node->data = rp_ept;
273 add_to_list(&rdev->rp_endpoints, node);
275 env_unlock_mutex(rdev->lock);
277 return rp_ept;
278 }
280 /**
281 * rpmsg_destroy_ept
282 *
283 * This function deletes rpmsg endpoint and performs cleanup.
284 *
285 * @param rdev - pointer to remote device
286 * @param rp_ept - pointer to endpoint to destroy
287 *
288 */
289 void _destroy_endpoint(struct remote_device *rdev,
290 struct rpmsg_endpoint *rp_ept)
291 {
292 struct llist *node;
293 node = rpmsg_rdev_get_endpoint_from_addr(rdev, rp_ept->addr);
294 if (node) {
295 env_lock_mutex(rdev->lock);
296 rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE,
297 rp_ept->addr);
298 remove_from_list(&rdev->rp_endpoints, node);
299 env_unlock_mutex(rdev->lock);
300 env_free_memory(node);
301 }
302 env_free_memory(rp_ept);
303 }
305 /**
306 * rpmsg_send_ns_message
307 *
308 * Sends name service announcement to remote device
309 *
310 * @param rdev - pointer to remote device
311 * @param rp_chnl - pointer to rpmsg channel
312 * @param flags - Channel creation/deletion flags
313 *
314 */
315 void rpmsg_send_ns_message(struct remote_device *rdev,
316 struct rpmsg_channel *rp_chnl, unsigned long flags)
317 {
319 struct rpmsg_hdr *rp_hdr;
320 struct rpmsg_ns_msg *ns_msg;
321 unsigned short idx;
322 unsigned long len;
324 env_lock_mutex(rdev->lock);
326 /* Get Tx buffer. */
327 rp_hdr = (struct rpmsg_hdr *)rpmsg_get_tx_buffer(rdev, &len, &idx);
328 if (!rp_hdr)
329 return;
331 /* Fill out name service data. */
332 rp_hdr->dst = RPMSG_NS_EPT_ADDR;
333 rp_hdr->len = sizeof(struct rpmsg_ns_msg);
334 ns_msg = (struct rpmsg_ns_msg *)rp_hdr->data;
335 env_strncpy(ns_msg->name, rp_chnl->name, sizeof(rp_chnl->name));
336 ns_msg->flags = flags;
337 ns_msg->addr = rp_chnl->src;
339 /* Place the buffer on virtqueue. */
340 rpmsg_enqueue_buffer(rdev, rp_hdr, len, idx);
342 /* Notify the other side that it has data to process. */
343 virtqueue_kick(rdev->tvq);
345 env_unlock_mutex(rdev->lock);
346 }
348 /**
349 * rpmsg_enqueue_buffers
350 *
351 * Places buffer on the virtqueue for consumption by the other side.
352 *
353 * @param rdev - pointer to remote core
354 * @param buffer - buffer pointer
355 * @param len - buffer length
356 * @idx - buffer index
357 *
358 * @return - status of function execution
359 *
360 */
361 int rpmsg_enqueue_buffer(struct remote_device *rdev, void *buffer,
362 unsigned long len, unsigned short idx)
363 {
364 struct llist node;
365 int status;
367 /* Initialize buffer node */
368 node.data = buffer;
369 node.attr = len;
370 node.next = RPMSG_NULL;
371 node.prev = RPMSG_NULL;
373 if (rdev->role == RPMSG_REMOTE) {
374 status = virtqueue_add_buffer(rdev->tvq, &node, 0, 1, buffer);
375 } else {
376 status = virtqueue_add_consumed_buffer(rdev->tvq, idx, len);
377 }
379 return status;
380 }
382 /**
383 * rpmsg_return_buffer
384 *
385 * Places the used buffer back on the virtqueue.
386 *
387 * @param rdev - pointer to remote core
388 * @param buffer - buffer pointer
389 * @param len - buffer length
390 * @param idx - buffer index
391 *
392 */
393 void rpmsg_return_buffer(struct remote_device *rdev, void *buffer,
394 unsigned long len, unsigned short idx)
395 {
396 struct llist node;
398 /* Initialize buffer node */
399 node.data = buffer;
400 node.attr = len;
401 node.next = RPMSG_NULL;
402 node.prev = RPMSG_NULL;
404 if (rdev->role == RPMSG_REMOTE) {
405 virtqueue_add_buffer(rdev->rvq, &node, 0, 1, buffer);
406 } else {
407 virtqueue_add_consumed_buffer(rdev->rvq, idx, len);
408 }
409 }
411 /**
412 * rpmsg_get_tx_buffer
413 *
414 * Provides buffer to transmit messages.
415 *
416 * @param rdev - pointer to remote device
417 * @param len - length of returned buffer
418 * @param idx - buffer index
419 *
420 * return - pointer to buffer.
421 */
422 void *rpmsg_get_tx_buffer(struct remote_device *rdev, unsigned long *len,
423 unsigned short *idx)
424 {
425 void *data;
427 if (rdev->role == RPMSG_REMOTE) {
428 data = virtqueue_get_buffer(rdev->tvq, (uint32_t *) len);
429 if (data == RPMSG_NULL) {
430 data = sh_mem_get_buffer(rdev->mem_pool);
431 *len = RPMSG_BUFFER_SIZE;
432 }
433 } else {
434 data =
435 virtqueue_get_available_buffer(rdev->tvq, idx,
436 (uint32_t *) len);
437 }
438 return ((void *)env_map_vatopa(data));
439 }
441 /**
442 * rpmsg_get_rx_buffer
443 *
444 * Retrieves the received buffer from the virtqueue.
445 *
446 * @param rdev - pointer to remote device
447 * @param len - size of received buffer
448 * @param idx - index of buffer
449 *
450 * @return - pointer to received buffer
451 *
452 */
453 void *rpmsg_get_rx_buffer(struct remote_device *rdev, unsigned long *len,
454 unsigned short *idx)
455 {
457 void *data;
458 if (rdev->role == RPMSG_REMOTE) {
459 data = virtqueue_get_buffer(rdev->rvq, (uint32_t *) len);
460 } else {
461 data =
462 virtqueue_get_available_buffer(rdev->rvq, idx,
463 (uint32_t *) len);
464 }
465 return ((void *)env_map_vatopa(data));
466 }
468 /**
469 * rpmsg_free_buffer
470 *
471 * Frees the allocated buffers.
472 *
473 * @param rdev - pointer to remote device
474 * @param buffer - pointer to buffer to free
475 *
476 */
477 void rpmsg_free_buffer(struct remote_device *rdev, void *buffer)
478 {
479 if (rdev->role == RPMSG_REMOTE) {
480 sh_mem_free_buffer(rdev->mem_pool, buffer);
481 }
482 }
484 /**
485 * rpmsg_tx_callback
486 *
487 * Tx callback function.
488 *
489 * @param vq - pointer to virtqueue on which Tx is has been
490 * completed.
491 *
492 */
493 static void rpmsg_tx_callback(struct virtqueue *vq)
494 {
495 struct remote_device *rdev;
496 struct virtio_device *vdev;
497 struct rpmsg_channel *rp_chnl;
498 struct llist *chnl_hd;
500 vdev = (struct virtio_device *)vq->vq_dev;
501 rdev = (struct remote_device *)vdev;
502 chnl_hd = rdev->rp_channels;
504 /* Check if the remote device is master. */
505 if (rdev->role == RPMSG_MASTER) {
507 /* Notification is received from the master. Now the remote(us) can
508 * performs one of two operations;
509 *
510 * a. If name service announcement is supported then it will send NS message.
511 * else
512 * b. It will update the channel state to active so that further communication
513 * can take place.
514 */
515 while (chnl_hd != RPMSG_NULL) {
516 rp_chnl = (struct rpmsg_channel *)chnl_hd->data;
518 if (rp_chnl->state == RPMSG_CHNL_STATE_IDLE) {
520 if (rdev->support_ns) {
521 rp_chnl->state = RPMSG_CHNL_STATE_NS;
522 } else {
523 rp_chnl->state =
524 RPMSG_CHNL_STATE_ACTIVE;
525 }
527 if (rp_chnl->state == RPMSG_CHNL_STATE_NS) {
528 rpmsg_send_ns_message(rdev, rp_chnl,
529 RPMSG_NS_CREATE);
530 }
531 }
533 chnl_hd = chnl_hd->next;
534 }
535 }
536 }
538 /**
539 * rpmsg_rx_callback
540 *
541 * Rx callback function.
542 *
543 * @param vq - pointer to virtqueue on which messages is received
544 *
545 */
546 void rpmsg_rx_callback(struct virtqueue *vq)
547 {
548 struct remote_device *rdev;
549 struct virtio_device *vdev;
550 struct rpmsg_channel *rp_chnl;
551 struct rpmsg_endpoint *rp_ept;
552 struct rpmsg_hdr *rp_hdr;
553 struct llist *node;
554 unsigned long len;
555 unsigned short idx;
556 struct llist *chnl_hd;
558 vdev = (struct virtio_device *)vq->vq_dev;
559 rdev = (struct remote_device *)vdev;
561 chnl_hd = rdev->rp_channels;
562 if ((chnl_hd != RPMSG_NULL) && (rdev->role == RPMSG_MASTER)) {
563 rp_chnl = (struct rpmsg_channel *)chnl_hd->data;
564 if (rp_chnl->state == RPMSG_CHNL_STATE_IDLE) {
565 if (rdev->support_ns) {
566 rp_chnl->state = RPMSG_CHNL_STATE_NS;
567 rpmsg_send_ns_message(rdev, rp_chnl,
568 RPMSG_NS_CREATE);
569 } else {
570 rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
571 }
572 return;
573 }
574 }
576 env_lock_mutex(rdev->lock);
578 /* Process the received data from remote node */
579 rp_hdr = (struct rpmsg_hdr *)rpmsg_get_rx_buffer(rdev, &len, &idx);
581 env_unlock_mutex(rdev->lock);
583 while (rp_hdr) {
585 /* Get the channel node from the remote device channels list. */
586 node = rpmsg_rdev_get_endpoint_from_addr(rdev, rp_hdr->dst);
588 if (!node)
589 /* Fatal error no endpoint for the given dst addr. */
590 return;
592 rp_ept = (struct rpmsg_endpoint *)node->data;
594 rp_chnl = rp_ept->rp_chnl;
596 if ((rp_chnl) && (rp_chnl->state == RPMSG_CHNL_STATE_NS)) {
597 /* First message from RPMSG Master, update channel
598 * destination address and state */
599 rp_chnl->dst = rp_hdr->src;
600 rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
602 /* Notify channel creation to application */
603 if (rdev->channel_created) {
604 rdev->channel_created(rp_chnl);
605 }
606 } else {
607 rp_ept->cb(rp_chnl, rp_hdr->data, rp_hdr->len,
608 rp_ept->priv, rp_hdr->src);
609 }
611 env_lock_mutex(rdev->lock);
613 /* Return used buffers. */
614 rpmsg_return_buffer(rdev, rp_hdr, len, idx);
616 rp_hdr =
617 (struct rpmsg_hdr *)rpmsg_get_rx_buffer(rdev, &len, &idx);
618 env_unlock_mutex(rdev->lock);
619 }
620 }
622 /**
623 * rpmsg_ns_callback
624 *
625 * This callback handles name service announcement from the remote device
626 * and creates/deletes rpmsg channels.
627 *
628 * @param server_chnl - pointer to server channel control block.
629 * @param data - pointer to received messages
630 * @param len - length of received data
631 * @param priv - any private data
632 * @param src - source address
633 *
634 * @return - none
635 */
636 void rpmsg_ns_callback(struct rpmsg_channel *server_chnl, void *data, int len,
637 void *priv, unsigned long src)
638 {
639 struct remote_device *rdev;
640 struct rpmsg_channel *rp_chnl;
641 struct rpmsg_ns_msg *ns_msg;
642 struct llist *node;
644 rdev = (struct remote_device *)priv;
646 //FIXME: This assumes same name string size for channel name both on master
647 //and remote. If this is not the case then we will have to parse the
648 //message contents.
650 ns_msg = (struct rpmsg_ns_msg *)data;
651 ns_msg->name[len - 1] = '\0';
653 if (ns_msg->flags & RPMSG_NS_DESTROY) {
654 node = rpmsg_rdev_get_chnl_node_from_id(rdev, ns_msg->name);
655 if (node) {
656 rp_chnl = (struct rpmsg_channel *)node->data;
657 if (rdev->channel_destroyed) {
658 rdev->channel_destroyed(rp_chnl);
659 }
660 rpmsg_destroy_ept(rp_chnl->rp_ept);
661 _rpmsg_delete_channel(rp_chnl);
662 }
663 } else {
664 rp_chnl =
665 _rpmsg_create_channel(rdev, ns_msg->name, 0x00,
666 ns_msg->addr);
667 if (rp_chnl) {
668 rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE;
669 /* Create default endpoint for channel */
670 rp_chnl->rp_ept =
671 rpmsg_create_ept(rp_chnl, rdev->default_cb, rdev,
672 RPMSG_ADDR_ANY);
673 if (rp_chnl->rp_ept) {
674 rp_chnl->src = rp_chnl->rp_ept->addr;
675 /*
676 * Echo back the NS message to remote in order to
677 * complete the connection stage. Remote will know the endpoint
678 * address from this point onward which will enable it to send
679 * message without waiting for any application level message from
680 * master.
681 */
682 rpmsg_send(rp_chnl, data, len);
683 if (rdev->channel_created) {
684 rdev->channel_created(rp_chnl);
685 }
686 }
687 }
688 }
689 }
691 /**
692 * rpmsg_get_address
693 *
694 * This function provides unique 32 bit address.
695 *
696 * @param bitmap - bit map for addresses
697 * @param size - size of bitmap
698 *
699 * return - a unique address
700 */
701 int rpmsg_get_address(unsigned long *bitmap, int size)
702 {
703 int addr = -1;
704 int i, tmp32;
706 /* Find first available buffer */
707 for (i = 0; i < size; i++) {
708 tmp32 = get_first_zero_bit(bitmap[i]);
710 if (tmp32 < 32) {
711 addr = tmp32 + i + 1;
712 bitmap[i] |= (1 << tmp32);
713 break;
714 }
715 }
717 return addr;
718 }
720 /**
721 * rpmsg_release_address
722 *
723 * Frees the given address.
724 *
725 * @param bitmap - bit map for addresses
726 * @param size - size of bitmap
727 * @param addr - address to free
728 *
729 * return - none
730 */
731 int rpmsg_release_address(unsigned long *bitmap, int size, int addr)
732 {
733 unsigned int i, j;
734 unsigned long mask = 1;
736 if (addr >= size * 32)
737 return -1;
739 /* Mark the addr as available */
740 i = addr / 32;
741 j = addr % 32;
743 mask = mask << j;
744 bitmap[i] = bitmap[i] & (~mask);
746 return RPMSG_SUCCESS;
747 }
749 /**
750 * rpmsg_is_address_set
751 *
752 * Checks whether address is used or free.
753 *
754 * @param bitmap - bit map for addresses
755 * @param size - size of bitmap
756 * @param addr - address to free
757 *
758 * return - TRUE/FALSE
759 */
760 int rpmsg_is_address_set(unsigned long *bitmap, int size, int addr)
761 {
762 int i, j;
763 unsigned long mask = 1;
765 if (addr >= size * 32)
766 return -1;
768 /* Mark the id as available */
769 i = addr / 32;
770 j = addr % 32;
771 mask = mask << j;
773 return (bitmap[i] & mask);
774 }
776 /**
777 * rpmsg_set_address
778 *
779 * Marks the address as consumed.
780 *
781 * @param bitmap - bit map for addresses
782 * @param size - size of bitmap
783 * @param addr - address to free
784 *
785 * return - none
786 */
787 int rpmsg_set_address(unsigned long *bitmap, int size, int addr)
788 {
789 int i, j;
790 unsigned long mask = 1;
792 if (addr >= size * 32)
793 return -1;
795 /* Mark the id as available */
796 i = addr / 32;
797 j = addr % 32;
798 mask = mask << j;
799 bitmap[i] |= mask;
801 return RPMSG_SUCCESS;
802 }