1 /*
2 * Copyright (c) 2012-2015 Texas Instruments Incorporated - http://www.ti.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * ======== SharedRegion.c ========
34 * Implementation of functions specified in SharedRegion.xdc.
35 */
37 #include <xdc/std.h>
38 #include <string.h>
39 #include <xdc/runtime/Assert.h>
40 #include <xdc/runtime/Error.h>
41 #include <xdc/runtime/IHeap.h>
42 #include <xdc/runtime/Memory.h>
44 #include <ti/sysbios/hal/Cache.h>
45 #include <ti/sysbios/hal/Hwi.h>
47 #include <ti/sdo/ipc/_Ipc.h>
48 #include <ti/sdo/utils/_MultiProc.h>
49 #include <ti/sdo/ipc/_SharedRegion.h>
50 #include <ti/sdo/ipc/heaps/_HeapMemMP.h>
52 #include "package/internal/SharedRegion.xdc.h"
54 #ifdef __ti__
55 #pragma FUNC_EXT_CALLED(SharedRegion_clearEntry);
56 #pragma FUNC_EXT_CALLED(SharedRegion_getCacheLineSize);
57 #pragma FUNC_EXT_CALLED(SharedRegion_getEntry);
58 #pragma FUNC_EXT_CALLED(SharedRegion_getEntryPtr);
59 #pragma FUNC_EXT_CALLED(SharedRegion_getHeap);
60 #pragma FUNC_EXT_CALLED(SharedRegion_getId);
61 #pragma FUNC_EXT_CALLED(SharedRegion_getIdByName);
62 #pragma FUNC_EXT_CALLED(SharedRegion_getNumRegions);
63 #pragma FUNC_EXT_CALLED(SharedRegion_getPtr);
64 #pragma FUNC_EXT_CALLED(SharedRegion_getSRPtr);
65 #pragma FUNC_EXT_CALLED(SharedRegion_isCacheEnabled);
66 #pragma FUNC_EXT_CALLED(SharedRegion_setEntry);
67 #pragma FUNC_EXT_CALLED(SharedRegion_translateEnabled);
68 #pragma FUNC_EXT_CALLED(SharedRegion_invalidSRPtr);
69 #endif
71 /*
72 *************************************************************************
73 * Common Header Functions
74 *************************************************************************
75 */
77 /*
78 * ======== SharedRegion_clearEntry ========
79 * Clears the region in the table.
80 */
81 Int SharedRegion_clearEntry(UInt16 id)
82 {
83 ti_sdo_ipc_SharedRegion_Region *region;
84 HeapMemMP_Handle heapMemHandle;
85 UInt16 myId, ownerProcId;
86 Int status = HeapMemMP_S_SUCCESS;
87 UInt key;
89 /* Need to make sure id is smaller than numEntries */
90 Assert_isTrue((id < ti_sdo_ipc_SharedRegion_numEntries), ti_sdo_ipc_SharedRegion_A_idTooLarge);
92 /* Need to make sure not trying to clear Region 0 */
93 Assert_isTrue(id != 0, ti_sdo_ipc_SharedRegion_A_region0Clear);
95 myId = MultiProc_self();
97 /* get the region */
98 region = &(SharedRegion_module->regions[id]);
100 /* store these fields to local variables */
101 ownerProcId = region->entry.ownerProcId;
102 heapMemHandle = (HeapMemMP_Handle)region->heap;
104 /* needs to be thread safe */
105 key = Hwi_disable();
107 /* clear region to their defaults */
108 region->entry.isValid = FALSE;
109 region->entry.base = NULL;
110 region->entry.len = 0;
111 region->entry.ownerProcId = 0;
112 region->entry.cacheEnable = TRUE;
113 region->entry.cacheLineSize = ti_sdo_ipc_SharedRegion_cacheLineSize;
114 region->entry.createHeap = TRUE;
115 region->entry.name = NULL;
116 region->reservedSize = 0;
117 region->heap = NULL;
119 /* leave the gate */
120 Hwi_restore(key);
122 /* delete or close previous created heap outside the gate */
123 if (heapMemHandle != NULL) {
124 if (ownerProcId == myId) {
125 status = HeapMemMP_delete(&heapMemHandle);
126 }
127 else if (ownerProcId != MultiProc_INVALIDID) {
128 status = HeapMemMP_close(&heapMemHandle);
129 }
130 }
132 if (status == HeapMemMP_S_SUCCESS) {
133 status = SharedRegion_S_SUCCESS;
134 }
135 else {
136 status = SharedRegion_E_FAIL;
137 }
139 return (status);
140 }
142 /*
143 * ======== SharedRegion_getCacheLineSize ========
144 */
145 SizeT SharedRegion_getCacheLineSize(UInt16 id)
146 {
147 SizeT cacheLineSize = 0;
149 /*
150 * if translate == TRUE or translate == FALSE
151 * and 'id' is not INVALIDREGIONID, then Assert id is valid.
152 * Return the heap associated with the region id.
153 *
154 * If those conditions are not met, the id is from
155 * an addres in local memory so return NULL.
156 */
157 if ((ti_sdo_ipc_SharedRegion_translate) ||
158 ((ti_sdo_ipc_SharedRegion_translate == FALSE) &&
159 (id != SharedRegion_INVALIDREGIONID))) {
160 /* Need to make sure id is smaller than numEntries */
161 Assert_isTrue((id < ti_sdo_ipc_SharedRegion_numEntries),
162 ti_sdo_ipc_SharedRegion_A_idTooLarge);
164 cacheLineSize = SharedRegion_module->regions[id].entry.cacheLineSize;
165 }
167 return (cacheLineSize);
168 }
170 /*
171 * ======== SharedRegion_getEntry ========
172 */
173 Int SharedRegion_getEntry(UInt16 id, SharedRegion_Entry *entry)
174 {
175 ti_sdo_ipc_SharedRegion_Region *region;
177 /* Make sure entry is not NULL */
178 Assert_isTrue((entry != NULL), ti_sdo_ipc_Ipc_A_nullArgument);
180 /* Need to make sure id is smaller than numEntries */
181 Assert_isTrue((id < ti_sdo_ipc_SharedRegion_numEntries), ti_sdo_ipc_SharedRegion_A_idTooLarge);
183 region = &(SharedRegion_module->regions[id]);
185 entry->base = region->entry.base;
186 entry->len = region->entry.len;
187 entry->ownerProcId = region->entry.ownerProcId;
188 entry->isValid = region->entry.isValid;
189 entry->cacheEnable = region->entry.cacheEnable;
190 entry->cacheLineSize = region->entry.cacheLineSize;
191 entry->createHeap = region->entry.createHeap;
192 entry->name = region->entry.name;
194 return (SharedRegion_S_SUCCESS);
195 }
197 /*
198 * ======== SharedRegion_getEntryPtr ========
199 */
200 SharedRegion_Entry *SharedRegion_getEntryPtr(UInt16 id)
201 {
202 ti_sdo_ipc_SharedRegion_Region *region;
204 region = &(SharedRegion_module->regions[id]);
205 return ((SharedRegion_Entry *)(®ion->entry));
206 }
208 /*
209 * ======== SharedRegion_getId ========
210 * Returns the id of shared region that the pointer resides in.
211 * Returns SharedRegion_INVALIDREGIONID if no region is found.
212 */
213 UInt16 SharedRegion_getId(Ptr addr)
214 {
215 ti_sdo_ipc_SharedRegion_Region *region;
216 UInt i;
217 UInt key;
218 UInt16 regionId = SharedRegion_INVALIDREGIONID;
220 /* Try to find the entry that contains the address */
221 for (i = 0; i < ti_sdo_ipc_SharedRegion_numEntries; i++) {
222 region = &(SharedRegion_module->regions[i]);
224 /* needs to be thread safe */
225 key = Hwi_disable();
227 if ((region->entry.isValid) && (addr >= region->entry.base) &&
228 (addr < (Ptr)((UInt32)region->entry.base + region->entry.len))) {
229 regionId = i;
231 /* leave the gate */
232 Hwi_restore(key);
233 break;
234 }
236 /* leave the gate */
237 Hwi_restore(key);
238 }
240 return (regionId);
241 }
243 /*
244 * ======== SharedRegion_getIdByName ========
245 * Returns the id of shared region that matches name.
246 * Returns SharedRegion_INVALIDREGIONID if no region is found.
247 */
248 UInt16 SharedRegion_getIdByName(String name)
249 {
250 ti_sdo_ipc_SharedRegion_Region *region;
251 UInt16 i;
252 UInt key;
253 UInt16 regionId = SharedRegion_INVALIDREGIONID;
255 /* loop through entries to find matching name */
256 for (i = 0; i < ti_sdo_ipc_SharedRegion_numEntries; i++) {
257 region = &(SharedRegion_module->regions[i]);
259 /* needs to be thread safe */
260 key = Hwi_disable();
262 if (region->entry.isValid) {
263 if (strcmp(region->entry.name, name) == 0) {
264 regionId = i;
266 /* leave the gate */
267 Hwi_restore(key);
268 break;
269 }
270 }
272 /* leave the gate */
273 Hwi_restore(key);
274 }
276 return (regionId);
277 }
279 /*
280 * ======== SharedRegion_getNumRegions ========
281 */
282 UInt16 SharedRegion_getNumRegions(Void)
283 {
284 return (ti_sdo_ipc_SharedRegion_numEntries);
285 }
287 /*
288 * ======== SharedRegion_getPtr ========
289 * This function takes a shared region pointer and returns a pointer.
290 */
291 Ptr SharedRegion_getPtr(SharedRegion_SRPtr srPtr)
292 {
293 ti_sdo_ipc_SharedRegion_Region *region;
294 Ptr returnPtr;
295 UInt16 regionId;
297 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
298 returnPtr = (Ptr)srPtr;
299 }
300 else if (srPtr == ti_sdo_ipc_SharedRegion_INVALIDSRPTR) {
301 returnPtr = NULL;
302 }
303 else {
304 /* find regionId from srPtr */
305 regionId = (UInt32)srPtr >> ti_sdo_ipc_SharedRegion_numOffsetBits;
307 /* make sure regionId of SRPtr less than numEntries */
308 Assert_isTrue(regionId < ti_sdo_ipc_SharedRegion_numEntries,
309 ti_sdo_ipc_SharedRegion_A_idTooLarge);
311 region = &(SharedRegion_module->regions[regionId]);
313 /* Make sure the region is valid */
314 Assert_isTrue(region->entry.isValid == TRUE,
315 ti_sdo_ipc_SharedRegion_A_regionInvalid);
317 returnPtr = (Ptr)((srPtr & ti_sdo_ipc_SharedRegion_offsetMask) +
318 (UInt32)region->entry.base);
319 }
321 return (returnPtr);
322 }
324 /*
325 * ======== SharedRegion_getSRPtr ========
326 * This function takes a pointer and an id and returns a shared region
327 * pointer.
328 */
329 SharedRegion_SRPtr SharedRegion_getSRPtr(Ptr addr, UInt16 id)
330 {
331 ti_sdo_ipc_SharedRegion_Region *region;
332 SharedRegion_SRPtr retPtr;
334 /* if translate == false, set SRPtr to addr */
335 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
336 retPtr = (SharedRegion_SRPtr)addr;
337 }
338 else if (addr == NULL) {
339 retPtr = ti_sdo_ipc_SharedRegion_INVALIDSRPTR;
340 }
341 else {
342 /* Need to make sure id is smaller than numEntries */
343 Assert_isTrue(id < ti_sdo_ipc_SharedRegion_numEntries,
344 ti_sdo_ipc_SharedRegion_A_idTooLarge);
346 region = &(SharedRegion_module->regions[id]);
348 /*
349 * Note: The very last byte on the very last id cannot be mapped
350 * because ti_sdo_ipc_SharedRegion_INVALIDSRPTR which is ~0 denotes an
351 * error. Since pointers should be word aligned, we don't
352 * expect this to be a problem.
353 *
354 * ie: numEntries = 4,
355 * id = 3, base = 0x00000000, len = 0x40000000
356 * ==> address 0x3fffffff would be invalid because the
357 * SRPtr for this address is 0xffffffff
358 */
359 if (((UInt32)addr >= (UInt32)region->entry.base) &&
360 ((UInt32)addr < ((UInt32)region->entry.base + region->entry.len))) {
361 retPtr = (SharedRegion_SRPtr)((id << ti_sdo_ipc_SharedRegion_numOffsetBits)
362 | ((UInt32)addr - (UInt32)region->entry.base));
363 }
364 else {
365 Assert_isTrue(FALSE, ti_sdo_ipc_SharedRegion_A_addrOutOfRange);
366 retPtr = ti_sdo_ipc_SharedRegion_INVALIDSRPTR;
367 }
368 }
370 return (retPtr);
371 }
373 /*
374 * ======== SharedRegion_isCacheEnabled ========
375 */
376 Bool SharedRegion_isCacheEnabled(UInt16 id)
377 {
378 Bool cacheEnable = FALSE;
380 /*
381 * if translate == TRUE or translate == FALSE
382 * and 'id' is not INVALIDREGIONID, then Assert id is valid.
383 * Return the heap associated with the region id.
384 *
385 * If those conditions are not met, the id is from
386 * an address in local memory so return NULL.
387 */
388 if ((ti_sdo_ipc_SharedRegion_translate) ||
389 ((ti_sdo_ipc_SharedRegion_translate == FALSE) &&
390 (id != SharedRegion_INVALIDREGIONID))) {
391 /* Need to make sure id is smaller than numEntries */
392 Assert_isTrue((id < ti_sdo_ipc_SharedRegion_numEntries),
393 ti_sdo_ipc_SharedRegion_A_idTooLarge);
395 cacheEnable = SharedRegion_module->regions[id].entry.cacheEnable;
396 }
398 return (cacheEnable);
399 }
401 /*
402 * ======== SharedRegion_setEntry ========
403 * Sets the region specified in the table.
404 */
405 Int SharedRegion_setEntry(UInt16 id, SharedRegion_Entry *entry)
406 {
407 ti_sdo_ipc_SharedRegion_Region *region;
408 HeapMemMP_Params params;
409 HeapMemMP_Handle heapHandle;
410 HeapMemMP_Handle *heapHandlePtr;
411 UInt key;
412 Ptr sharedAddr;
413 Int status = SharedRegion_S_SUCCESS;
414 Error_Block eb;
416 /* Need to make sure id is smaller than numEntries */
417 Assert_isTrue((id < ti_sdo_ipc_SharedRegion_numEntries),
418 ti_sdo_ipc_SharedRegion_A_idTooLarge);
420 /* Make sure entry is not NULL */
421 Assert_isTrue((entry != NULL), ti_sdo_ipc_Ipc_A_nullArgument);
423 Error_init(&eb);
425 region = &(SharedRegion_module->regions[id]);
427 /* make sure region does not overlap existing ones */
428 status = SharedRegion_checkOverlap(entry->base, entry->len);
430 if (status == SharedRegion_S_SUCCESS) {
431 /* region entry should be invalid at this point */
432 if (region->entry.isValid) {
433 /* Assert that a region already exists */
434 Assert_isTrue(FALSE, ti_sdo_ipc_SharedRegion_A_alreadyExists);
435 status = SharedRegion_E_ALREADYEXISTS;
436 return (status);
437 }
439 /* Assert if cacheEnabled and cacheLineSize equal 0 */
440 if ((entry->cacheEnable) && (entry->cacheLineSize == 0)) {
441 /* if cache enabled, cache line size must != 0 */
442 Assert_isTrue(FALSE, ti_sdo_ipc_SharedRegion_A_cacheLineSizeIsZero);
443 }
445 /* needs to be thread safe */
446 key = Hwi_disable();
448 /* set specified region id to entry values */
449 region->entry.base = entry->base;
450 region->entry.len = entry->len;
451 region->entry.ownerProcId = entry->ownerProcId;
452 region->entry.cacheEnable = entry->cacheEnable;
453 region->entry.cacheLineSize = entry->cacheLineSize;
454 region->entry.createHeap = entry->createHeap;
455 region->entry.name = entry->name;
456 region->entry.isValid = entry->isValid;
458 /* leave gate */
459 Hwi_restore(key);
461 if (!region->entry.isValid) {
462 /* Region isn't valid yet */
463 return (status);
464 }
466 if (entry->ownerProcId == MultiProc_self()) {
467 if ((entry->createHeap) && (region->heap == NULL)) {
468 /* get current Ptr (reserve memory with size of 0) */
469 sharedAddr = ti_sdo_ipc_SharedRegion_reserveMemory(id, 0);
471 HeapMemMP_Params_init(¶ms);
472 params.sharedAddr = sharedAddr;
473 params.sharedBufSize = region->entry.len -
474 region->reservedSize;
476 /*
477 * Calculate size of HeapMemMP_Attrs and adjust sharedBufSize
478 * Size of HeapMemMP_Attrs = HeapMemMP_sharedMemReq(¶ms) -
479 * params.sharedBufSize
480 */
481 params.sharedBufSize -= (HeapMemMP_sharedMemReq(¶ms)
482 - params.sharedBufSize);
484 heapHandle = HeapMemMP_create(¶ms);
485 if (heapHandle == NULL) {
486 region->entry.isValid = FALSE;
487 return (SharedRegion_E_MEMORY);
488 }
490 region->heap = (IHeap_Handle)heapHandle;
491 }
492 }
493 else {
494 if ((entry->createHeap) && (region->heap == NULL)) {
495 /* sharedAddr should match creator's for each region */
496 sharedAddr = (Ptr)((UInt32)entry->base +
497 region->reservedSize);
499 /* set the pointer to a heap handle */
500 heapHandlePtr = (HeapMemMP_Handle *)&(region->heap);
502 /* open the heap by address */
503 if (HeapMemMP_openByAddr(sharedAddr, heapHandlePtr) !=
504 HeapMemMP_S_SUCCESS) {
505 status = SharedRegion_E_FAIL;
506 region->entry.isValid = FALSE;
507 }
508 }
509 }
510 }
512 return (status);
513 }
515 /*
516 * ======== SharedRegion_checkOverlap ========
517 * Checks to make sure overlap does not exists.
518 */
519 Int SharedRegion_checkOverlap(Ptr base, SizeT len)
520 {
521 ti_sdo_ipc_SharedRegion_Region *region;
522 UInt i;
523 UInt key;
525 /* needs to be thread safe */
526 key = Hwi_disable();
528 /* check to make sure new region does not overlap existing ones */
529 for (i = 0; i < ti_sdo_ipc_SharedRegion_numEntries; i++) {
530 region = &(SharedRegion_module->regions[i]);
531 if (region->entry.isValid) {
532 if (base >= region->entry.base) {
533 if (base < (Ptr)((UInt32)region->entry.base +
534 region->entry.len)) {
535 Hwi_restore(key);
536 Assert_isTrue(FALSE, ti_sdo_ipc_SharedRegion_A_overlap);
537 return (SharedRegion_E_FAIL);
538 }
539 }
540 else {
541 if ((Ptr)((UInt32)base + len) > region->entry.base) {
542 Hwi_restore(key);
543 Assert_isTrue(FALSE, ti_sdo_ipc_SharedRegion_A_overlap);
544 return (SharedRegion_E_FAIL);
545 }
546 }
547 }
548 }
550 Hwi_restore(key);
552 return (SharedRegion_S_SUCCESS);
553 }
556 /*
557 * ======== SharedRegion_entryInit ========
558 */
559 Void SharedRegion_entryInit(SharedRegion_Entry *entry)
560 {
561 /* Make sure entry is not NULL */
562 Assert_isTrue((entry != NULL), ti_sdo_ipc_Ipc_A_nullArgument);
564 /* init the entry to default values */
565 entry->base = NULL;
566 entry->len = 0;
567 entry->ownerProcId = 0;
568 entry->cacheEnable = TRUE;
569 entry->cacheLineSize = ti_sdo_ipc_SharedRegion_cacheLineSize;
570 entry->createHeap = TRUE;
571 entry->name = NULL;
572 entry->isValid = FALSE;
573 }
575 /*
576 * ======== SharedRegion_getHeap ========
577 */
578 Ptr SharedRegion_getHeap(UInt16 id)
579 {
580 IHeap_Handle heap = NULL;
582 /*
583 * if translate == TRUE or translate == FALSE
584 * and 'id' is not INVALIDREGIONID, then Assert id is valid.
585 * Return the heap associated with the region id.
586 *
587 * If those conditions are not met, the id is from
588 * an addres in local memory so return NULL.
589 */
590 if ((ti_sdo_ipc_SharedRegion_translate) ||
591 ((ti_sdo_ipc_SharedRegion_translate == FALSE) &&
592 (id != SharedRegion_INVALIDREGIONID))) {
594 /* assert id is valid */
595 Assert_isTrue(id < ti_sdo_ipc_SharedRegion_numEntries,
596 ti_sdo_ipc_SharedRegion_A_idTooLarge);
598 heap = SharedRegion_module->regions[id].heap;
599 }
601 return (heap);
602 }
604 /*
605 * ======== SharedRegion_translateEnabled ========
606 */
607 Bool SharedRegion_translateEnabled(Void)
608 {
609 return (ti_sdo_ipc_SharedRegion_translate);
610 }
612 /*
613 * ======== SharedRegion_invalidSRPtr ========
614 */
615 SharedRegion_SRPtr SharedRegion_invalidSRPtr(Void)
616 {
617 return (ti_sdo_ipc_SharedRegion_INVALIDSRPTR);
618 }
620 /*
621 *************************************************************************
622 * Module functions
623 *************************************************************************
624 */
626 /*
627 * ======== ti_sdo_ipc_SharedRegion_attach ========
628 */
629 Int ti_sdo_ipc_SharedRegion_attach(UInt16 remoteProcId)
630 {
631 Int i;
632 Ptr sharedAddr;
633 ti_sdo_ipc_SharedRegion_Region *region;
634 HeapMemMP_Handle *heapHandlePtr;
635 Int status = SharedRegion_S_SUCCESS;
637 /*
638 * Loop through the regions and open the heap if not owner
639 */
640 for (i = 0; i < ti_sdo_ipc_SharedRegion_numEntries; i++) {
641 region = &(SharedRegion_module->regions[i]);
642 if ((region->entry.isValid) &&
643 (region->entry.ownerProcId != MultiProc_self()) &&
644 (region->entry.ownerProcId != MultiProc_INVALIDID) &&
645 (region->entry.createHeap) &&
646 (region->heap == NULL)) {
647 /* sharedAddr should match creator's for each region */
648 sharedAddr = (Ptr)((UInt32)region->entry.base +
649 region->reservedSize);
651 /* get the heap handle from SharedRegion Module state */
652 heapHandlePtr = (HeapMemMP_Handle *)&(region->heap);
654 /* heap should already be created so open by address */
655 status = HeapMemMP_openByAddr(sharedAddr, heapHandlePtr);
656 }
657 }
659 return(status);
660 }
662 /*
663 * ======== ti_sdo_ipc_SharedRegion_detach ========
664 */
665 Int ti_sdo_ipc_SharedRegion_detach(UInt16 remoteProcId)
666 {
667 Int i;
668 ti_sdo_ipc_SharedRegion_Region *region;
669 HeapMemMP_Handle *heapHandlePtr;
670 Int status = SharedRegion_S_SUCCESS;
672 /*
673 * Loop through the regions and close the heap only when
674 * detaching from owner of heap.
675 */
676 for (i = 0; i < ti_sdo_ipc_SharedRegion_numEntries; i++) {
677 region = &(SharedRegion_module->regions[i]);
678 if ((region->entry.isValid) &&
679 (region->entry.ownerProcId == remoteProcId) &&
680 (region->heap != NULL)) {
681 /* get the heap handle from SharedRegion Module state */
682 heapHandlePtr = (HeapMemMP_Handle *)&(region->heap);
684 /* heap should already be created so open by address */
685 status = HeapMemMP_close(heapHandlePtr);
686 }
687 }
689 return(status);
690 }
692 /*
693 * ======== ti_sdo_ipc_SharedRegion_clearReservedMemory ========
694 * Clears the reserve memory for each region in the table.
695 */
696 Void ti_sdo_ipc_SharedRegion_clearReservedMemory()
697 {
698 Int i;
699 ti_sdo_ipc_SharedRegion_Region *region;
701 /*
702 * Loop through shared regions. If an owner of a region is specified,
703 * the owner zeros out the reserved memory in each region.
704 */
705 for (i = 0; i < ti_sdo_ipc_SharedRegion_numEntries; i++) {
706 region = &(SharedRegion_module->regions[i]);
707 if ((region->entry.isValid) &&
708 (region->entry.ownerProcId == MultiProc_self())) {
709 /* clear reserved memory */
710 memset(region->entry.base, 0, region->reservedSize);
712 /* writeback invalidate the cache if enabled in region */
713 if (region->entry.cacheEnable) {
714 Cache_wbInv(region->entry.base, region->reservedSize,
715 Cache_Type_ALL, TRUE);
716 }
717 }
718 }
719 }
721 /*
722 * ======== ti_sdo_ipc_SharedRegion_reserveMemory ========
723 */
724 Ptr ti_sdo_ipc_SharedRegion_reserveMemory(UInt16 id, SizeT size)
725 {
726 ti_sdo_ipc_SharedRegion_Region *region;
727 UInt32 minAlign;
728 SizeT curSize, newSize;
729 Ptr retPtr;
731 /* Need to make sure id is smaller than numEntries */
732 Assert_isTrue((id < ti_sdo_ipc_SharedRegion_numEntries),
733 ti_sdo_ipc_SharedRegion_A_idTooLarge);
735 /* assert that region at specified id is valid */
736 Assert_isTrue(SharedRegion_module->regions[id].entry.isValid == TRUE,
737 ti_sdo_ipc_SharedRegion_A_regionInvalid);
739 minAlign = Memory_getMaxDefaultTypeAlign();
740 if (SharedRegion_getCacheLineSize(id) > minAlign) {
741 minAlign = SharedRegion_getCacheLineSize(id);
742 }
744 region = &(SharedRegion_module->regions[id]);
746 /* Set the current size to the reservedSize */
747 curSize = region->reservedSize;
749 /* No need to round here since curSize is already aligned */
750 retPtr = (Ptr)((UInt32)region->entry.base + curSize);
752 /* Round the new size to the min alignment since */
753 newSize = _Ipc_roundup(size, minAlign);
755 /* Need to make sure (curSize + newSize) is smaller than region len */
756 Assert_isTrue((region->entry.len >= (curSize + newSize)),
757 ti_sdo_ipc_SharedRegion_A_reserveTooMuch);
759 /* Add the new size to current size */
760 region->reservedSize = curSize + newSize;
762 return (retPtr);
763 }
765 /*
766 * ======== ti_sdo_ipc_SharedRegion_resetInternalFields ========
767 */
768 Void ti_sdo_ipc_SharedRegion_resetInternalFields(UInt16 id)
769 {
770 ti_sdo_ipc_SharedRegion_Region *region;
772 /* Need to make sure id is smaller than numEntries */
773 Assert_isTrue((id < ti_sdo_ipc_SharedRegion_numEntries),
774 ti_sdo_ipc_SharedRegion_A_idTooLarge);
776 region = &(SharedRegion_module->regions[id]);
778 region->reservedSize = 0;
779 }
781 /*
782 * ======== ti_sdo_ipc_SharedRegion_start ========
783 */
784 Int ti_sdo_ipc_SharedRegion_start(Void)
785 {
786 Int i;
787 ti_sdo_ipc_SharedRegion_Region *region;
788 HeapMemMP_Params params;
789 HeapMemMP_Handle heapHandle;
790 Ptr sharedAddr;
791 Int status = SharedRegion_S_SUCCESS;
793 /* assert that region 0 is valid */
794 Assert_isTrue((ti_sdo_ipc_SharedRegion_numEntries > 0) &&
795 (SharedRegion_module->regions[0].entry.isValid),
796 ti_sdo_ipc_SharedRegion_A_region0Invalid);
798 /*
799 * Loop through shared regions. If an owner of a region is specified
800 * and createHeap has been specified for the SharedRegion, then
801 * the owner creates a HeapMemMP and the other processors open it.
802 */
803 for (i = 0; i < ti_sdo_ipc_SharedRegion_numEntries; i++) {
804 region = &(SharedRegion_module->regions[i]);
805 if ((region->entry.isValid) &&
806 (region->entry.ownerProcId == MultiProc_self()) &&
807 (region->entry.createHeap) &&
808 (region->heap == NULL)) {
809 /* get the next free address in each region */
810 sharedAddr = (Ptr)((UInt32)region->entry.base +
811 region->reservedSize);
813 /* Create the HeapMemMP in the region. */
814 HeapMemMP_Params_init(¶ms);
815 params.sharedAddr = sharedAddr;
816 params.sharedBufSize = region->entry.len - region->reservedSize;
818 /* Adjust to account for the size of HeapMemMP_Attrs */
819 params.sharedBufSize -= (HeapMemMP_sharedMemReq(¶ms)
820 - params.sharedBufSize);
821 heapHandle = HeapMemMP_create(¶ms);
823 if (heapHandle == NULL) {
824 status = SharedRegion_E_FAIL;
825 }
826 else {
827 /* put heap handle into SharedRegion Module state */
828 region->heap = (IHeap_Handle)heapHandle;
829 }
830 }
831 }
833 return (status);
834 }
836 /*
837 * ======== ti_sdo_ipc_SharedRegion_stop ========
838 */
839 Int ti_sdo_ipc_SharedRegion_stop(Void)
840 {
841 Int i;
842 ti_sdo_ipc_SharedRegion_Region *region;
843 HeapMemMP_Handle *heapHandlePtr;
844 Int status = SharedRegion_S_SUCCESS;
846 /*
847 * Loop through shared regions. If owner then delete the heap,
848 * otherwise the heap should have been closed in detach().
849 */
850 for (i = 0; i < ti_sdo_ipc_SharedRegion_numEntries; i++) {
851 region = &(SharedRegion_module->regions[i]);
852 if ((region->entry.isValid) &&
853 (region->entry.ownerProcId == MultiProc_self()) &&
854 (region->heap != NULL)) {
855 /* get the heap handle from SharedRegion Module state */
856 heapHandlePtr = (HeapMemMP_Handle *)&(region->heap);
858 /* delete the HeapMemMP */
859 status = HeapMemMP_delete(heapHandlePtr);
860 }
861 }
863 return (status);
864 }