ath9k: Set IEEE80211_TX_CTL_RATE_CTRL_PROBE in rate control for probe rate
[linux-2.6/cjktty.git] / drivers / staging / epl / SharedBuff.c
blob9fb09d6bc28e96c9f32659568db40ad5a2a25a97
1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: Project independend shared buffer (linear + circular)
8 Description: Implementation of platform independend part for the
9 shared buffer
11 License:
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
24 3. Neither the name of SYSTEC electronic GmbH nor the names of its
25 contributors may be used to endorse or promote products derived
26 from this software without prior written permission. For written
27 permission, please contact info@systec-electronic.com.
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
39 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 POSSIBILITY OF SUCH DAMAGE.
42 Severability Clause:
44 If a provision of this License is or becomes illegal, invalid or
45 unenforceable in any jurisdiction, that shall not affect:
46 1. the validity or enforceability in that jurisdiction of any other
47 provision of this License; or
48 2. the validity or enforceability in other jurisdictions of that or
49 any other provision of this License.
51 -------------------------------------------------------------------------
53 2006/06/27 -rs: V 1.00 (initial version)
55 ****************************************************************************/
57 #if defined(WIN32) || defined(_WIN32)
59 #ifdef UNDER_RTSS
60 // RTX header
61 #include <windows.h>
62 #include <process.h>
63 #include <rtapi.h>
65 #elif __BORLANDC__
66 // borland C header
67 #include <windows.h>
68 #include <process.h>
70 #elif WINCE
71 #include <windows.h>
73 #else
74 // MSVC needs to include windows.h at first
75 // the following defines ar necessary for function prototypes for waitable timers
76 #define _WIN32_WINDOWS 0x0401
77 #define _WIN32_WINNT 0x0400
78 #include <windows.h>
79 #include <process.h>
80 #endif
82 #endif
84 #include "global.h"
85 #include "SharedBuff.h"
86 #include "ShbIpc.h"
88 // d.k. Linux kernel modules needs other header files for memcpy()
89 #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
90 #include <linux/string.h>
91 #else
92 #include <stdio.h>
93 #include <stdlib.h>
94 #include <string.h>
95 #endif
97 /***************************************************************************/
98 /* */
99 /* */
100 /* G L O B A L D E F I N I T I O N S */
101 /* */
102 /* */
103 /***************************************************************************/
105 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
107 //---------------------------------------------------------------------------
108 // Configuration
109 //---------------------------------------------------------------------------
111 //---------------------------------------------------------------------------
112 // Constant definitions
113 //---------------------------------------------------------------------------
115 #define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#")
116 #define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#")
118 //---------------------------------------------------------------------------
119 // Local types
120 //---------------------------------------------------------------------------
122 // structure to administrate circular shared buffer head
123 typedef struct {
124 unsigned long m_ShbCirMagicID; // magic ID ("SBC#")
125 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
126 unsigned long m_ulBufferDataSize; // size of complete data area
127 unsigned long m_ulWrIndex; // current write index (set bevore write)
128 unsigned long m_ulRdIndex; // current read index (set after read)
129 unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations
130 unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations)
131 unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1)
132 unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1)
133 unsigned long m_ulDataReadable; // buffer size with readable (complete written) data
134 unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks
135 tShbCirSigHndlrNewData m_pfnSigHndlrNewData; // application handler to signal new data
136 unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request)
137 tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done
138 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
140 } tShbCirBuff;
142 // structure to administrate linear shared buffer head
143 typedef struct {
144 unsigned int m_ShbLinMagicID; // magic ID ("SBL#")
145 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
146 unsigned long m_ulBufferDataSize; // size of complete data area
147 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
149 } tShbLinBuff;
151 // type to save size of a single data block inside the circular shared buffer
152 typedef struct {
153 unsigned int m_uiFullBlockSize:28; // a single block must not exceed a length of 256MByte :-)
154 unsigned int m_uiAlignFillBytes:4;
156 } tShbCirBlockSize;
158 #define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)!
159 #define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
161 #define SBL_BLOCK_ALIGNMENT 4
162 #define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
164 //---------------------------------------------------------------------------
165 // Global variables
166 //---------------------------------------------------------------------------
168 //---------------------------------------------------------------------------
169 // Local variables
170 //---------------------------------------------------------------------------
172 //---------------------------------------------------------------------------
173 // Prototypes of internal functions
174 //---------------------------------------------------------------------------
176 //---------------------------------------------------------------------------
177 // Get pointer to Circular Shared Buffer
178 //---------------------------------------------------------------------------
180 INLINE_FUNCTION tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p)
183 tShbCirBuff *pShbCirBuff;
185 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
186 ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
188 return (pShbCirBuff);
192 //---------------------------------------------------------------------------
193 // Get pointer to Linear Shared Buffer
194 //---------------------------------------------------------------------------
196 INLINE_FUNCTION tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p)
199 tShbLinBuff *pShbLinBuff;
201 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
202 ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
204 return (pShbLinBuff);
208 // not inlined internal functions
209 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p);
210 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
211 unsigned int fTimeOut_p);
213 #endif
215 //=========================================================================//
216 // //
217 // P U B L I C F U N C T I O N S //
218 // //
219 //=========================================================================//
221 #if !defined(INLINE_ENABLED)
222 // not inlined external functions
224 //---------------------------------------------------------------------------
225 // Initialize Shared Buffer Module
226 //---------------------------------------------------------------------------
228 tShbError ShbInit(void)
231 tShbError ShbError;
233 ShbError = ShbIpcInit();
235 return (ShbError);
239 //---------------------------------------------------------------------------
240 // Deinitialize Shared Buffer Module
241 //---------------------------------------------------------------------------
243 tShbError ShbExit(void)
246 tShbError ShbError;
248 ShbError = ShbIpcExit();
250 return (ShbError);
254 //-------------------------------------------------------------------------//
255 // //
256 // C i r c u l a r S h a r e d B u f f e r //
257 // //
258 //-------------------------------------------------------------------------//
260 //---------------------------------------------------------------------------
261 // Allocate Circular Shared Buffer
262 //---------------------------------------------------------------------------
264 tShbError ShbCirAllocBuffer(unsigned long ulBufferSize_p,
265 const char *pszBufferID_p,
266 tShbInstance * ppShbInstance_p,
267 unsigned int *pfShbNewCreated_p)
270 tShbInstance pShbInstance;
271 tShbCirBuff *pShbCirBuff;
272 unsigned int fShbNewCreated;
273 unsigned long ulBufferDataSize;
274 unsigned long ulBufferTotalSize;
275 tShbError ShbError;
277 // check arguments
278 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
279 return (kShbInvalidArg);
282 // calculate length of memory to allocate
283 ulBufferDataSize =
284 (ulBufferSize_p +
285 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
286 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
288 // allocate a new or open an existing shared buffer
289 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
290 &pShbInstance, &fShbNewCreated);
291 if (ShbError != kShbOk) {
292 goto Exit;
295 if (pShbInstance == NULL) {
296 ShbError = kShbOutOfMem;
297 goto Exit;
300 // get pointer to shared buffer
301 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance);
303 // if the shared buffer was new created, than this process has
304 // to initialize it, otherwise the buffer is already in use
305 // and *must not* be reseted
306 if (fShbNewCreated) {
307 #ifndef NDEBUG
309 memset(pShbCirBuff, 0xCC, ulBufferTotalSize);
311 #endif
313 pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID;
314 pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize;
315 pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize;
316 pShbCirBuff->m_ulWrIndex = 0;
317 pShbCirBuff->m_ulRdIndex = 0;
318 pShbCirBuff->m_ulNumOfWriteJobs = 0;
319 pShbCirBuff->m_ulDataInUse = 0;
320 pShbCirBuff->m_ulDataApended = 0;
321 pShbCirBuff->m_ulBlocksApended = 0;
322 pShbCirBuff->m_ulDataReadable = 0;
323 pShbCirBuff->m_ulBlocksReadable = 0;
324 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
325 pShbCirBuff->m_fBufferLocked = FALSE;
326 pShbCirBuff->m_pfnSigHndlrReset = NULL;
327 } else {
328 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
329 ShbError = kShbInvalidBufferType;
330 goto Exit;
334 Exit:
336 *ppShbInstance_p = pShbInstance;
337 *pfShbNewCreated_p = fShbNewCreated;
339 return (ShbError);
343 //---------------------------------------------------------------------------
344 // Release Circular Shared Buffer
345 //---------------------------------------------------------------------------
347 tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p)
350 tShbError ShbError;
352 // check arguments
353 if (pShbInstance_p == NULL) {
354 ShbError = kShbOk;
355 goto Exit;
358 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
360 Exit:
362 return (ShbError);
366 #endif // !defined(INLINE_ENABLED)
368 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
370 //---------------------------------------------------------------------------
371 // Reset Circular Shared Buffer
372 //---------------------------------------------------------------------------
374 INLINE_FUNCTION tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p,
375 unsigned long ulTimeOut_p,
376 tShbCirSigHndlrReset
377 pfnSignalHandlerReset_p)
380 tShbCirBuff *pShbCirBuff;
381 unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise
382 tShbError ShbError;
384 // check arguments
385 if (pShbInstance_p == NULL) {
386 ShbError = kShbInvalidArg;
387 goto Exit;
390 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
391 ShbError = kShbOk;
393 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
394 ShbError = kShbInvalidBufferType;
395 goto Exit;
398 // start reset job by setting request request in buffer header
399 ShbIpcEnterAtomicSection(pShbInstance_p);
401 if (!pShbCirBuff->m_fBufferLocked) {
402 ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
404 pShbCirBuff->m_fBufferLocked = TRUE;
405 pShbCirBuff->m_pfnSigHndlrReset =
406 pfnSignalHandlerReset_p;
407 } else {
408 ShbError = kShbAlreadyReseting;
411 ShbIpcLeaveAtomicSection(pShbInstance_p);
413 if (ShbError != kShbOk) {
414 goto Exit;
417 // if there is currently no running write operation then reset buffer
418 // immediately, otherwise wait until the last write job is ready by
419 // starting a signal process
420 if (ulNumOfWriteJobs == 0) {
421 // there is currently no running write operation
422 // -> reset buffer immediately
423 ShbCirSignalHandlerReset(pShbInstance_p, FALSE);
424 ShbError = kShbOk;
425 } else {
426 // there is currently at least one running write operation
427 // -> starting signal process to wait until the last write job is ready
428 ShbError =
429 ShbIpcStartSignalingJobReady(pShbInstance_p, ulTimeOut_p,
430 ShbCirSignalHandlerReset);
433 Exit:
435 return (ShbError);
439 //---------------------------------------------------------------------------
440 // Write data block to Circular Shared Buffer
441 //---------------------------------------------------------------------------
443 INLINE_FUNCTION tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p,
444 const void *pSrcDataBlock_p,
445 unsigned long ulDataBlockSize_p)
448 tShbCirBuff *pShbCirBuff;
449 tShbCirBlockSize ShbCirBlockSize;
450 unsigned int uiFullBlockSize;
451 unsigned int uiAlignFillBytes;
452 unsigned char *pShbCirDataPtr;
453 unsigned char *pScrDataPtr;
454 unsigned long ulDataSize;
455 unsigned long ulChunkSize;
456 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
457 unsigned int fSignalNewData;
458 unsigned int fSignalReset;
459 tShbError ShbError;
460 tShbError ShbError2;
461 int fRes;
463 // check arguments
464 if (pShbInstance_p == NULL) {
465 ShbError = kShbInvalidArg;
466 goto Exit;
469 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
470 // nothing to do here
471 ShbError = kShbOk;
472 goto Exit;
475 if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE) {
476 ShbError = kShbExceedDataSizeLimit;
477 goto Exit;
480 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
481 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
482 fSignalNewData = FALSE;
483 fSignalReset = FALSE;
484 ShbError = kShbOk;
486 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
487 ShbError = kShbInvalidBufferType;
488 goto Exit;
491 // calculate data block size in circular buffer
492 ulDataSize =
493 (ulDataBlockSize_p +
494 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
495 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
496 uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
498 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
499 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
501 // reserve the needed memory for the write operation to do now
502 // and make necessary adjustments in the circular buffer header
503 ShbIpcEnterAtomicSection(pShbInstance_p);
505 // check if there is sufficient memory available to store
506 // the new data
507 fRes =
508 uiFullBlockSize <=
509 (pShbCirBuff->m_ulBufferDataSize -
510 pShbCirBuff->m_ulDataInUse);
511 if (fRes) {
512 // set write pointer for the write operation to do now
513 // to the current write pointer of the circular buffer
514 ulWrIndex = pShbCirBuff->m_ulWrIndex;
516 // reserve the needed memory for the write operation to do now
517 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
519 // set new write pointer behind the reserved memory
520 // for the write operation to do now
521 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
522 pShbCirBuff->m_ulWrIndex %=
523 pShbCirBuff->m_ulBufferDataSize;
525 // increment number of currently (parallel running)
526 // write operations
527 pShbCirBuff->m_ulNumOfWriteJobs++;
530 ShbIpcLeaveAtomicSection(pShbInstance_p);
532 if (!fRes) {
533 ShbError = kShbBufferFull;
534 goto Exit;
537 // copy the data to the circular buffer
538 // (the copy process itself will be done outside of any
539 // critical/locked section)
540 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
542 // write real size of current block (incl. alignment fill bytes)
543 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
544 ulWrIndex += sizeof(tShbCirBlockSize);
545 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
547 if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize) {
548 // linear write operation
549 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
550 ulDataBlockSize_p);
551 } else {
552 // wrap-around write operation
553 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
554 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize);
555 memcpy(pShbCirDataPtr, pScrDataPtr + ulChunkSize,
556 ulDataBlockSize_p - ulChunkSize);
559 // adjust header information for circular buffer with properties
560 // of the wiritten data block
561 ShbIpcEnterAtomicSection(pShbInstance_p);
563 pShbCirBuff->m_ulDataApended += uiFullBlockSize;
564 pShbCirBuff->m_ulBlocksApended++;
566 // decrement number of currently (parallel running) write operations
567 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
568 // if there is no other write process running then
569 // set new size of readable (complete written) data and
570 // adjust number of readable blocks
571 pShbCirBuff->m_ulDataReadable +=
572 pShbCirBuff->m_ulDataApended;
573 pShbCirBuff->m_ulBlocksReadable +=
574 pShbCirBuff->m_ulBlocksApended;
576 pShbCirBuff->m_ulDataApended = 0;
577 pShbCirBuff->m_ulBlocksApended = 0;
579 fSignalNewData = TRUE;
580 fSignalReset = pShbCirBuff->m_fBufferLocked;
583 ShbIpcLeaveAtomicSection(pShbInstance_p);
585 // signal new data event to a potentially reading application
586 if (fSignalNewData) {
587 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
588 if (ShbError == kShbOk) {
589 ShbError = ShbError2;
592 // signal that the last write job has been finished to allow
593 // a waiting application to reset the buffer now
594 if (fSignalReset) {
595 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
596 if (ShbError == kShbOk) {
597 ShbError = ShbError2;
601 Exit:
603 return (ShbError);
607 //---------------------------------------------------------------------------
608 // Allocate block within the Circular Shared Buffer for chunk writing
609 //---------------------------------------------------------------------------
611 INLINE_FUNCTION tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p,
612 tShbCirChunk * pShbCirChunk_p,
613 unsigned long ulDataBufferSize_p)
616 tShbCirBuff *pShbCirBuff;
617 tShbCirBlockSize ShbCirBlockSize;
618 unsigned int uiFullBlockSize;
619 unsigned int uiAlignFillBytes;
620 unsigned char *pShbCirDataPtr;
621 unsigned long ulDataSize;
622 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
623 tShbError ShbError;
624 int fRes;
626 // check arguments
627 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)) {
628 ShbError = kShbInvalidArg;
629 goto Exit;
632 if (ulDataBufferSize_p == 0) {
633 ShbError = kShbInvalidArg;
634 goto Exit;
637 if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE) {
638 ShbError = kShbExceedDataSizeLimit;
639 goto Exit;
642 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
643 ShbError = kShbOk;
645 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
646 ShbError = kShbInvalidBufferType;
647 goto Exit;
650 // calculate data block size in circular buffer
651 ulDataSize =
652 (ulDataBufferSize_p +
653 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
654 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
655 uiAlignFillBytes = ulDataSize - ulDataBufferSize_p;
657 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
658 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
660 // reserve the needed memory for the write operation to do now
661 // and make necessary adjustments in the circular buffer header
662 ShbIpcEnterAtomicSection(pShbInstance_p);
664 // check if there is sufficient memory available to store
665 // the new data
666 fRes =
667 (uiFullBlockSize <=
668 (pShbCirBuff->m_ulBufferDataSize -
669 pShbCirBuff->m_ulDataInUse));
670 if (fRes) {
671 // set write pointer for the write operation to do now
672 // to the current write pointer of the circular buffer
673 ulWrIndex = pShbCirBuff->m_ulWrIndex;
675 // reserve the needed memory for the write operation to do now
676 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
678 // set new write pointer behind the reserved memory
679 // for the write operation to do now
680 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
681 pShbCirBuff->m_ulWrIndex %=
682 pShbCirBuff->m_ulBufferDataSize;
684 // increment number of currently (parallel running)
685 // write operations
686 pShbCirBuff->m_ulNumOfWriteJobs++;
689 ShbIpcLeaveAtomicSection(pShbInstance_p);
691 if (!fRes) {
692 ShbError = kShbBufferFull;
693 goto Exit;
696 // setup header information for allocated buffer
697 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
699 // write real size of current block (incl. alignment fill bytes)
700 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
701 ulWrIndex += sizeof(tShbCirBlockSize);
702 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
704 // setup chunk descriptor
705 pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize;
706 pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p;
707 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
708 pShbCirChunk_p->m_fBufferCompleted = FALSE;
710 Exit:
712 return (ShbError);
716 //---------------------------------------------------------------------------
717 // Write data chunk into an allocated buffer of the Circular Shared Buffer
718 //---------------------------------------------------------------------------
720 INLINE_FUNCTION tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p,
721 tShbCirChunk * pShbCirChunk_p,
722 const void *pSrcDataChunk_p,
723 unsigned long ulDataChunkSize_p,
724 unsigned int
725 *pfBufferCompleted_p)
728 tShbCirBuff *pShbCirBuff;
729 unsigned char *pShbCirDataPtr;
730 unsigned char *pScrDataPtr;
731 unsigned long ulSubChunkSize;
732 unsigned long ulWrIndex;
733 unsigned int fBufferCompleted;
734 unsigned int fSignalNewData;
735 unsigned int fSignalReset;
736 tShbError ShbError;
737 tShbError ShbError2;
739 // check arguments
740 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)
741 || (pfBufferCompleted_p == NULL)) {
742 ShbError = kShbInvalidArg;
743 goto Exit;
746 if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0)) {
747 // nothing to do here
748 ShbError = kShbOk;
749 goto Exit;
752 if (pShbCirChunk_p->m_fBufferCompleted) {
753 ShbError = kShbBufferAlreadyCompleted;
754 goto Exit;
757 if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize) {
758 ShbError = kShbExceedDataSizeLimit;
759 goto Exit;
762 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
763 pScrDataPtr = (unsigned char *)pSrcDataChunk_p;
764 fSignalNewData = FALSE;
765 fSignalReset = FALSE;
766 ShbError = kShbOk;
768 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
769 ShbError = kShbInvalidBufferType;
770 goto Exit;
773 ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
775 // copy the data to the circular buffer
776 // (the copy process itself will be done outside of any
777 // critical/locked section)
778 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
780 if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize) {
781 // linear write operation
782 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
783 ulDataChunkSize_p);
784 } else {
785 // wrap-around write operation
786 ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
787 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize);
788 memcpy(pShbCirDataPtr, pScrDataPtr + ulSubChunkSize,
789 ulDataChunkSize_p - ulSubChunkSize);
792 // adjust chunk descriptor
793 ulWrIndex += ulDataChunkSize_p;
794 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
796 pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
797 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
799 fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
800 pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
802 // if the complete allocated buffer is filled with data then
803 // adjust header information for circular buffer with properties
804 // of the wiritten data block
805 if (fBufferCompleted) {
806 ShbIpcEnterAtomicSection(pShbInstance_p);
808 pShbCirBuff->m_ulDataApended +=
809 pShbCirChunk_p->m_uiFullBlockSize;
810 pShbCirBuff->m_ulBlocksApended++;
812 // decrement number of currently (parallel running) write operations
813 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
814 // if there is no other write process running then
815 // set new size of readable (complete written) data and
816 // adjust number of readable blocks
817 pShbCirBuff->m_ulDataReadable +=
818 pShbCirBuff->m_ulDataApended;
819 pShbCirBuff->m_ulBlocksReadable +=
820 pShbCirBuff->m_ulBlocksApended;
822 pShbCirBuff->m_ulDataApended = 0;
823 pShbCirBuff->m_ulBlocksApended = 0;
825 fSignalNewData = TRUE;
826 fSignalReset = pShbCirBuff->m_fBufferLocked;
829 ShbIpcLeaveAtomicSection(pShbInstance_p);
832 // signal new data event to a potentially reading application
833 if (fSignalNewData) {
834 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
835 if (ShbError == kShbOk) {
836 ShbError = ShbError2;
839 // signal that the last write job has been finished to allow
840 // a waiting application to reset the buffer now
841 if (fSignalReset) {
842 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
843 if (ShbError == kShbOk) {
844 ShbError = ShbError2;
848 *pfBufferCompleted_p = fBufferCompleted;
850 Exit:
852 return (ShbError);
856 //---------------------------------------------------------------------------
857 // Read data block from Circular Shared Buffer
858 //---------------------------------------------------------------------------
860 INLINE_FUNCTION tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p,
861 void *pDstDataBlock_p,
862 unsigned long ulRdBuffSize_p,
863 unsigned long *pulDataBlockSize_p)
866 tShbCirBuff *pShbCirBuff;
867 tShbCirBlockSize ShbCirBlockSize;
868 unsigned long ulDataReadable;
869 unsigned char *pShbCirDataPtr;
870 unsigned char *pDstDataPtr;
871 unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise
872 unsigned long ulChunkSize;
873 unsigned long ulRdIndex;
874 tShbError ShbError;
876 // check arguments
877 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
878 return (kShbInvalidArg);
881 if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0)) {
882 // nothing to do here
883 ShbError = kShbOk;
884 goto Exit;
887 ShbError = kShbOk;
888 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
889 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
890 ulDataSize = 0;
892 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
893 ShbError = kShbInvalidBufferType;
894 goto Exit;
897 // get total number of readable bytes for the whole circular buffer
898 ShbIpcEnterAtomicSection(pShbInstance_p);
900 ulDataReadable = pShbCirBuff->m_ulDataReadable;
902 ShbIpcLeaveAtomicSection(pShbInstance_p);
904 // if there are readable data available, then there must be at least
905 // one complete readable data block
906 if (ulDataReadable > 0) {
907 // get pointer to start of data area and current read index
908 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
909 ulRdIndex = pShbCirBuff->m_ulRdIndex;
911 // get real size of current block (incl. alignment fill bytes)
912 ShbCirBlockSize =
913 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
914 ulRdIndex += sizeof(tShbCirBlockSize);
915 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
917 // get size of user data inside the current block
918 ulDataSize =
919 ShbCirBlockSize.m_uiFullBlockSize -
920 ShbCirBlockSize.m_uiAlignFillBytes;
921 ulDataSize -= sizeof(tShbCirBlockSize);
924 // ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
925 if (ulDataSize > ulRdBuffSize_p) {
926 ulDataSize = ulRdBuffSize_p;
927 ShbError = kShbDataTruncated;
930 if (ulDataSize == 0) {
931 // nothing to do here
932 ShbError = kShbNoReadableData;
933 goto Exit;
936 // copy the data from the circular buffer
937 // (the copy process itself will be done outside of any
938 // critical/locked section)
939 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
940 // linear read operation
941 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize);
942 } else {
943 // wrap-around read operation
944 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
945 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize);
946 memcpy(pDstDataPtr + ulChunkSize, pShbCirDataPtr,
947 ulDataSize - ulChunkSize);
950 #ifndef NDEBUG
952 tShbCirBlockSize ClrShbCirBlockSize;
954 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
955 // linear buffer
956 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
957 } else {
958 // wrap-around read operation
959 ulChunkSize =
960 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
961 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
962 memset(pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
965 ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int) */ -1; // -1 = xFFFFFFF
966 ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int) */ -1; // -1 = Fxxxxxxx
967 *(tShbCirBlockSize *) (pShbCirDataPtr +
968 pShbCirBuff->m_ulRdIndex) =
969 ClrShbCirBlockSize;
971 #endif // #ifndef NDEBUG
973 // set new size of readable data, data in use, new read index
974 // and adjust number of readable blocks
975 ShbIpcEnterAtomicSection(pShbInstance_p);
977 pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
978 pShbCirBuff->m_ulDataReadable -=
979 ShbCirBlockSize.m_uiFullBlockSize;
980 pShbCirBuff->m_ulBlocksReadable--;
982 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
983 if ((pShbCirBuff->m_ulDataInUse == 0)
984 && (pShbCirBuff->m_ulDataReadable == 0)) {
985 ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
987 pShbCirBuff->m_ulWrIndex = 0;
988 pShbCirBuff->m_ulRdIndex = 0;
989 } else
990 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
992 pShbCirBuff->m_ulRdIndex +=
993 ShbCirBlockSize.m_uiFullBlockSize;
994 pShbCirBuff->m_ulRdIndex %=
995 pShbCirBuff->m_ulBufferDataSize;
998 ShbIpcLeaveAtomicSection(pShbInstance_p);
1000 Exit:
1002 *pulDataBlockSize_p = ulDataSize;
1004 return (ShbError);
1008 //---------------------------------------------------------------------------
1009 // Get data size of next readable block from Circular Shared Buffer
1010 //---------------------------------------------------------------------------
1012 INLINE_FUNCTION tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p,
1013 unsigned long
1014 *pulDataBlockSize_p)
1017 tShbCirBuff *pShbCirBuff;
1018 unsigned long ulDataReadable;
1019 unsigned char *pShbCirDataPtr;
1020 tShbCirBlockSize ShbCirBlockSize;
1021 unsigned long ulDataSize;
1022 tShbError ShbError;
1024 // check arguments
1025 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
1026 return (kShbInvalidArg);
1029 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1030 ulDataSize = 0;
1031 ShbError = kShbOk;
1033 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1034 ShbError = kShbInvalidBufferType;
1035 goto Exit;
1038 // get total number of readable bytes for the whole circular buffer
1039 ShbIpcEnterAtomicSection(pShbInstance_p);
1041 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1043 ShbIpcLeaveAtomicSection(pShbInstance_p);
1045 // if there are readable data available, then there must be at least
1046 // one complete readable data block
1047 if (ulDataReadable > 0) {
1048 pShbCirDataPtr =
1049 &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
1051 // get real size of current block (incl. alignment fill bytes)
1052 ShbCirBlockSize = *(tShbCirBlockSize *) pShbCirDataPtr;
1054 // get size of user data inside the current block
1055 ulDataSize =
1056 ShbCirBlockSize.m_uiFullBlockSize -
1057 ShbCirBlockSize.m_uiAlignFillBytes;
1058 ulDataSize -= sizeof(tShbCirBlockSize);
1061 Exit:
1063 *pulDataBlockSize_p = ulDataSize;
1065 return (ShbError);
1069 //---------------------------------------------------------------------------
1070 // Get number of readable blocks from Circular Shared Buffer
1071 //---------------------------------------------------------------------------
1073 INLINE_FUNCTION tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,
1074 unsigned long
1075 *pulDataBlockCount_p)
1078 tShbCirBuff *pShbCirBuff;
1079 unsigned long ulBlockCount;
1080 tShbError ShbError;
1082 // check arguments
1083 if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL)) {
1084 ShbError = kShbInvalidArg;
1085 goto Exit;
1088 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1089 ulBlockCount = 0;
1090 ShbError = kShbOk;
1092 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1093 ShbError = kShbInvalidBufferType;
1094 goto Exit;
1097 ShbIpcEnterAtomicSection(pShbInstance_p);
1099 ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
1101 ShbIpcLeaveAtomicSection(pShbInstance_p);
1103 *pulDataBlockCount_p = ulBlockCount;
1105 Exit:
1107 return (ShbError);
1111 //---------------------------------------------------------------------------
1112 // Set application handler to signal new data for Circular Shared Buffer
1113 // d.k.: new parameter priority as enum
1114 //---------------------------------------------------------------------------
1116 INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData(tShbInstance
1117 pShbInstance_p,
1118 tShbCirSigHndlrNewData
1119 pfnSignalHandlerNewData_p,
1120 tShbPriority
1121 ShbPriority_p)
1124 tShbCirBuff *pShbCirBuff;
1125 tShbError ShbError;
1127 // check arguments
1128 if (pShbInstance_p == NULL) {
1129 ShbError = kShbInvalidArg;
1130 goto Exit;
1133 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1134 ShbError = kShbOk;
1136 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1137 ShbError = kShbInvalidBufferType;
1138 goto Exit;
1141 if (pfnSignalHandlerNewData_p != NULL) {
1142 // set a new signal handler
1143 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1144 ShbError = kShbAlreadySignaling;
1145 goto Exit;
1148 pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
1149 ShbError =
1150 ShbIpcStartSignalingNewData(pShbInstance_p,
1151 ShbCirSignalHandlerNewData,
1152 ShbPriority_p);
1153 } else {
1154 // remove existing signal handler
1155 ShbError = ShbIpcStopSignalingNewData(pShbInstance_p);
1156 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1157 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p, 0);
1159 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
1162 Exit:
1164 return (ShbError);
1168 #endif
1170 #if !defined(INLINE_ENABLED)
1172 //---------------------------------------------------------------------------
1173 // DEBUG: Trace Circular Shared Buffer
1174 //---------------------------------------------------------------------------
1176 #ifndef NDEBUG
1177 tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p)
1180 tShbCirBuff *pShbCirBuff;
1181 char szMagigID[sizeof(SBC_MAGIC_ID) + 1];
1182 tShbCirBlockSize ShbCirBlockSize;
1183 unsigned long ulDataReadable;
1184 unsigned char *pShbCirDataPtr;
1185 unsigned long ulBlockIndex;
1186 unsigned int nBlockCount;
1187 unsigned long ulDataSize;
1188 unsigned long ulChunkSize;
1189 unsigned long ulRdIndex;
1190 tShbError ShbError;
1192 TRACE0("\n\n##### Circular Shared Buffer #####\n");
1194 // check arguments
1195 if (pShbInstance_p == NULL) {
1196 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1197 (unsigned long)pShbInstance_p);
1198 ShbError = kShbInvalidArg;
1199 goto Exit;
1202 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1203 ShbError = kShbOk;
1205 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1206 ShbError = kShbInvalidBufferType;
1207 goto Exit;
1210 *(unsigned long *)&szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
1211 szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
1213 ShbIpcEnterAtomicSection(pShbInstance_p);
1215 TRACE1("\nBuffer Address: 0x%08lX\n",
1216 (unsigned long)pShbCirBuff);
1218 TRACE0("\nHeader Info:");
1219 TRACE2("\nMagigID: '%s' (%08lX)", szMagigID,
1220 pShbCirBuff->m_ShbCirMagicID);
1221 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1222 pShbCirBuff->m_ulBufferTotalSize);
1223 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1224 pShbCirBuff->m_ulBufferDataSize);
1225 TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex);
1226 TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex);
1227 TRACE1("\nNumOfWriteJobs: %4lu",
1228 pShbCirBuff->m_ulNumOfWriteJobs);
1229 TRACE1("\nDataInUse: %4lu [Bytes]",
1230 pShbCirBuff->m_ulDataInUse);
1231 TRACE1("\nDataApended: %4lu [Bytes]",
1232 pShbCirBuff->m_ulDataApended);
1233 TRACE1("\nBlocksApended: %4lu",
1234 pShbCirBuff->m_ulBlocksApended);
1235 TRACE1("\nDataReadable: %4lu [Bytes]",
1236 pShbCirBuff->m_ulDataReadable);
1237 TRACE1("\nBlocksReadable: %4lu",
1238 pShbCirBuff->m_ulBlocksReadable);
1239 TRACE1("\nSigHndlrNewData: %08lX",
1240 (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData);
1241 TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked);
1242 TRACE1("\nSigHndlrReset: %08lX",
1243 (unsigned long)pShbCirBuff->m_pfnSigHndlrReset);
1245 ShbTraceDump(&pShbCirBuff->m_Data,
1246 pShbCirBuff->m_ulBufferDataSize, 0x00000000L,
1247 "\nData Area:");
1249 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1250 nBlockCount = 1;
1251 ulBlockIndex = pShbCirBuff->m_ulRdIndex;
1253 while (ulDataReadable > 0) {
1254 TRACE1("\n\n--- Block #%u ---", nBlockCount);
1256 // get pointer to start of data area and current read index
1257 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
1258 ulRdIndex = ulBlockIndex;
1260 // get real size of current block (incl. alignment fill bytes)
1261 ShbCirBlockSize =
1262 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
1263 ulRdIndex += sizeof(tShbCirBlockSize);
1264 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
1266 // get size of user data inside the current block
1267 ulDataSize =
1268 ShbCirBlockSize.m_uiFullBlockSize -
1269 ShbCirBlockSize.m_uiAlignFillBytes;
1270 ulDataSize -= sizeof(tShbCirBlockSize);
1272 TRACE1
1273 ("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)",
1274 ShbCirBlockSize.m_uiFullBlockSize);
1275 TRACE1("\nUser Data Size: %4lu [Bytes]",
1276 ulDataSize);
1277 TRACE1("\nAlignment Fill Bytes: %4u [Bytes]",
1278 ShbCirBlockSize.m_uiAlignFillBytes);
1280 if (ulRdIndex + ulDataSize <=
1281 pShbCirBuff->m_ulBufferDataSize) {
1282 // linear data buffer
1283 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1284 ulDataSize, 0x00000000L, NULL);
1285 } else {
1286 // wrap-around data buffer
1287 ulChunkSize =
1288 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
1289 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1290 ulChunkSize, 0x00000000L, NULL);
1291 ShbTraceDump(pShbCirDataPtr,
1292 ulDataSize - ulChunkSize,
1293 ulChunkSize, NULL);
1296 nBlockCount++;
1298 ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
1299 ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
1301 ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
1304 ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount - 1);
1306 ShbIpcLeaveAtomicSection(pShbInstance_p);
1308 Exit:
1310 return (ShbError);
1313 #endif
1315 //-------------------------------------------------------------------------//
1316 // //
1317 // L i n e a r S h a r e d B u f f e r //
1318 // //
1319 //-------------------------------------------------------------------------//
1321 //---------------------------------------------------------------------------
1322 // Allocate Linear Shared Buffer
1323 //---------------------------------------------------------------------------
1325 tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p,
1326 const char *pszBufferID_p,
1327 tShbInstance * ppShbInstance_p,
1328 unsigned int *pfShbNewCreated_p)
1331 tShbInstance pShbInstance;
1332 tShbLinBuff *pShbLinBuff;
1333 unsigned int fShbNewCreated;
1334 unsigned long ulBufferDataSize;
1335 unsigned long ulBufferTotalSize;
1336 tShbError ShbError;
1338 // check arguments
1339 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
1340 return (kShbInvalidArg);
1343 // calculate length of memory to allocate
1344 ulBufferDataSize =
1345 (ulBufferSize_p +
1346 (SBL_BLOCK_ALIGNMENT - 1)) & ~(SBL_BLOCK_ALIGNMENT - 1);
1347 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
1349 // allocate a new or open an existing shared buffer
1350 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
1351 &pShbInstance, &fShbNewCreated);
1352 if (ShbError != kShbOk) {
1353 goto Exit;
1356 if (pShbInstance == NULL) {
1357 ShbError = kShbOutOfMem;
1358 goto Exit;
1361 // get pointer to shared buffer
1362 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance);
1364 // if the shared buffer was new created, than this process has
1365 // to initialize it, otherwise the buffer is already in use
1366 // and *must not* be reseted
1367 if (fShbNewCreated) {
1368 #ifndef NDEBUG
1370 memset(pShbLinBuff, 0xCC, ulBufferTotalSize);
1372 #endif
1374 pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
1375 pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
1376 pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
1377 } else {
1378 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1379 ShbError = kShbInvalidBufferType;
1380 goto Exit;
1384 Exit:
1386 *ppShbInstance_p = pShbInstance;
1387 *pfShbNewCreated_p = fShbNewCreated;
1389 return (ShbError);
1393 //---------------------------------------------------------------------------
1394 // Release Linear Shared Buffer
1395 //---------------------------------------------------------------------------
1397 tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p)
1400 tShbError ShbError;
1402 // check arguments
1403 if (pShbInstance_p == NULL) {
1404 ShbError = kShbOk;
1405 goto Exit;
1408 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
1410 Exit:
1412 return (ShbError);
1416 #endif // !defined(INLINE_ENABLED)
1418 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
1420 //---------------------------------------------------------------------------
1421 // Write data block to Linear Shared Buffer
1422 //---------------------------------------------------------------------------
1424 INLINE_FUNCTION tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p,
1425 unsigned long ulDstBufferOffs_p,
1426 const void *pSrcDataBlock_p,
1427 unsigned long ulDataBlockSize_p)
1430 tShbLinBuff *pShbLinBuff;
1431 unsigned char *pShbLinDataPtr;
1432 unsigned char *pScrDataPtr;
1433 unsigned long ulBufferDataSize;
1434 tShbError ShbError;
1436 // check arguments
1437 if (pShbInstance_p == NULL) {
1438 ShbError = kShbInvalidArg;
1439 goto Exit;
1442 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1443 // nothing to do here
1444 ShbError = kShbOk;
1445 goto Exit;
1448 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1449 ShbError = kShbExceedDataSizeLimit;
1450 goto Exit;
1453 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1454 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
1455 ShbError = kShbOk;
1457 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1458 ShbError = kShbInvalidBufferType;
1459 goto Exit;
1462 // check if offeset and size for the write operation matches with
1463 // the size of the shared buffer
1464 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1465 if ((ulDstBufferOffs_p > ulBufferDataSize) ||
1466 (ulDataBlockSize_p > ulBufferDataSize) ||
1467 ((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1468 ShbError = kShbDataOutsideBufferArea;
1469 goto Exit;
1472 // copy the data to the linear buffer
1473 // (the copy process will be done inside of any critical/locked section)
1474 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1475 pShbLinDataPtr += ulDstBufferOffs_p;
1477 ShbIpcEnterAtomicSection(pShbInstance_p);
1479 memcpy(pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
1481 ShbIpcLeaveAtomicSection(pShbInstance_p);
1483 Exit:
1485 return (ShbError);
1489 //---------------------------------------------------------------------------
1490 // Read data block from Linear Shared Buffer
1491 //---------------------------------------------------------------------------
1493 INLINE_FUNCTION tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p,
1494 void *pDstDataBlock_p,
1495 unsigned long ulSrcBufferOffs_p,
1496 unsigned long ulDataBlockSize_p)
1499 tShbLinBuff *pShbLinBuff;
1500 unsigned char *pShbLinDataPtr;
1501 unsigned char *pDstDataPtr;
1502 unsigned long ulBufferDataSize;
1503 tShbError ShbError;
1505 // check arguments
1506 if (pShbInstance_p == NULL) {
1507 ShbError = kShbInvalidArg;
1508 goto Exit;
1511 if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1512 // nothing to do here
1513 ShbError = kShbOk;
1514 goto Exit;
1517 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1518 ShbError = kShbExceedDataSizeLimit;
1519 goto Exit;
1522 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1523 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
1524 ShbError = kShbOk;
1526 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1527 ShbError = kShbInvalidBufferType;
1528 goto Exit;
1531 // check if offeset and size for the read operation matches with
1532 // the size of the shared buffer
1533 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1534 if ((ulSrcBufferOffs_p > ulBufferDataSize) ||
1535 (ulDataBlockSize_p > ulBufferDataSize) ||
1536 ((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1537 ShbError = kShbDataOutsideBufferArea;
1538 goto Exit;
1541 // copy the data to the linear buffer
1542 // (the copy process will be done inside of any critical/locked section)
1543 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1544 pShbLinDataPtr += ulSrcBufferOffs_p;
1546 ShbIpcEnterAtomicSection(pShbInstance_p);
1548 memcpy(pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
1550 ShbIpcLeaveAtomicSection(pShbInstance_p);
1552 Exit:
1554 return (ShbError);
1558 #endif
1560 #if !defined(INLINE_ENABLED)
1562 //---------------------------------------------------------------------------
1563 // DEBUG: Trace Linear Shared Buffer
1564 //---------------------------------------------------------------------------
1566 #ifndef NDEBUG
1567 tShbError ShbLinTraceBuffer(tShbInstance pShbInstance_p)
1570 tShbLinBuff *pShbLinBuff;
1571 char szMagigID[sizeof(SBL_MAGIC_ID) + 1];
1572 tShbError ShbError;
1574 TRACE0("\n\n##### Linear Shared Buffer #####\n");
1576 // check arguments
1577 if (pShbInstance_p == NULL) {
1578 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1579 (unsigned long)pShbInstance_p);
1580 ShbError = kShbInvalidArg;
1581 goto Exit;
1584 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1585 ShbError = kShbOk;
1587 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1588 ShbError = kShbInvalidBufferType;
1589 goto Exit;
1592 *(unsigned int *)&szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
1593 szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
1595 ShbIpcEnterAtomicSection(pShbInstance_p);
1597 TRACE1("\nBuffer Address: 0x%08lX\n",
1598 (unsigned long)pShbLinBuff);
1600 TRACE0("\nHeader Info:");
1601 TRACE2("\nMagigID: '%s' (%08X)", szMagigID,
1602 pShbLinBuff->m_ShbLinMagicID);
1603 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1604 pShbLinBuff->m_ulBufferTotalSize);
1605 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1606 pShbLinBuff->m_ulBufferDataSize);
1608 ShbTraceDump(&pShbLinBuff->m_Data,
1609 pShbLinBuff->m_ulBufferDataSize, 0x00000000L,
1610 "\nData Area:");
1612 ShbIpcLeaveAtomicSection(pShbInstance_p);
1614 Exit:
1616 return (ShbError);
1619 #endif
1621 //---------------------------------------------------------------------------
1622 // Dump buffer contents
1623 //---------------------------------------------------------------------------
1625 #ifndef NDEBUG
1626 tShbError ShbTraceDump(const unsigned char *pabStartAddr_p,
1627 unsigned long ulDataSize_p,
1628 unsigned long ulAddrOffset_p, const char *pszInfoText_p)
1631 const unsigned char *pabBuffData;
1632 unsigned long ulBuffSize;
1633 unsigned char bData;
1634 int nRow;
1635 int nCol;
1637 // get pointer to buffer and length of buffer
1638 pabBuffData = pabStartAddr_p;
1639 ulBuffSize = ulDataSize_p;
1641 if (pszInfoText_p != NULL) {
1642 TRACE0(pszInfoText_p);
1644 // dump buffer contents
1645 for (nRow = 0;; nRow++) {
1646 TRACE1("\n%08lX: ",
1647 (unsigned long)(nRow * 0x10) + ulAddrOffset_p);
1649 for (nCol = 0; nCol < 16; nCol++) {
1650 if ((unsigned long)nCol < ulBuffSize) {
1651 TRACE1("%02X ",
1652 (unsigned int)*(pabBuffData + nCol));
1653 } else {
1654 TRACE0(" ");
1658 TRACE0(" ");
1660 for (nCol = 0; nCol < 16; nCol++) {
1661 bData = *pabBuffData++;
1662 if ((unsigned long)nCol < ulBuffSize) {
1663 if ((bData >= 0x20) && (bData < 0x7F)) {
1664 TRACE1("%c", bData);
1665 } else {
1666 TRACE0(".");
1668 } else {
1669 TRACE0(" ");
1673 if (ulBuffSize > 16) {
1674 ulBuffSize -= 16;
1675 } else {
1676 break;
1680 return (kShbOk);
1683 #endif // #ifndef NDEBUG
1685 //=========================================================================//
1686 // //
1687 // P R I V A T E F U N C T I O N S //
1688 // //
1689 //=========================================================================//
1691 //---------------------------------------------------------------------------
1692 // Handler to signal new data event for Circular Shared Buffer
1693 //---------------------------------------------------------------------------
1695 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p)
1698 tShbCirBuff *pShbCirBuff;
1699 unsigned long ulDataSize;
1700 unsigned long ulBlockCount;
1701 tShbError ShbError;
1703 // check arguments
1704 if (pShbInstance_p == NULL) {
1705 return FALSE;
1708 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1709 ShbError = kShbOk;
1711 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1712 return FALSE;
1715 // call application handler
1716 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1717 /* do
1719 ShbError = ShbCirGetReadDataSize(pShbInstance_p, &ulDataSize);
1720 if ((ulDataSize > 0) && (ShbError == kShbOk)) {
1721 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p,
1722 ulDataSize);
1725 ShbError =
1726 ShbCirGetReadBlockCount(pShbInstance_p, &ulBlockCount);
1727 /* }
1728 while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
1730 // Return TRUE if there are pending blocks.
1731 // In that case ShbIpc tries to call this function again immediately if there
1732 // is no other filled shared buffer with higher priority.
1733 return ((ulBlockCount > 0) && (ShbError == kShbOk));
1737 //---------------------------------------------------------------------------
1738 // Handler to reset Circular Shared Buffer
1739 //---------------------------------------------------------------------------
1741 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
1742 unsigned int fTimeOut_p)
1745 tShbCirBuff *pShbCirBuff;
1747 // check arguments
1748 if (pShbInstance_p == NULL) {
1749 return;
1752 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1753 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1754 return;
1757 // reset buffer header
1758 if (!fTimeOut_p) {
1759 ShbIpcEnterAtomicSection(pShbInstance_p);
1761 pShbCirBuff->m_ulWrIndex = 0;
1762 pShbCirBuff->m_ulRdIndex = 0;
1763 pShbCirBuff->m_ulNumOfWriteJobs = 0;
1764 pShbCirBuff->m_ulDataInUse = 0;
1765 pShbCirBuff->m_ulDataApended = 0;
1766 pShbCirBuff->m_ulBlocksApended = 0;
1767 pShbCirBuff->m_ulDataReadable = 0;
1768 pShbCirBuff->m_ulBlocksReadable = 0;
1770 ShbIpcLeaveAtomicSection(pShbInstance_p);
1772 #ifndef NDEBUG
1774 memset(&pShbCirBuff->m_Data, 0xCC,
1775 pShbCirBuff->m_ulBufferDataSize);
1777 #endif
1780 // call application handler
1781 if (pShbCirBuff->m_pfnSigHndlrReset != NULL) {
1782 pShbCirBuff->m_pfnSigHndlrReset(pShbInstance_p, fTimeOut_p);
1785 // unlock buffer
1786 ShbIpcEnterAtomicSection(pShbInstance_p);
1788 pShbCirBuff->m_fBufferLocked = FALSE;
1789 pShbCirBuff->m_pfnSigHndlrReset = NULL;
1791 ShbIpcLeaveAtomicSection(pShbInstance_p);
1793 return;
1797 #endif
1799 // EOF