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