debugfs: Modified default dir of debugfs for debugging UHCI.
[linux/fpc-iii.git] / drivers / staging / epl / SharedBuff.c
blob2b10c375f3e61a0fd79998a394f7d8c3319c2e92
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 #include <linux/string.h>
89 #include <linux/kernel.h>
91 /***************************************************************************/
92 /* */
93 /* */
94 /* G L O B A L D E F I N I T I O N S */
95 /* */
96 /* */
97 /***************************************************************************/
99 //---------------------------------------------------------------------------
100 // Configuration
101 //---------------------------------------------------------------------------
103 //---------------------------------------------------------------------------
104 // Constant definitions
105 //---------------------------------------------------------------------------
107 #define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#")
108 #define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#")
110 //---------------------------------------------------------------------------
111 // Local types
112 //---------------------------------------------------------------------------
114 // structure to administrate circular shared buffer head
115 typedef struct {
116 unsigned long m_ShbCirMagicID; // magic ID ("SBC#")
117 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
118 unsigned long m_ulBufferDataSize; // size of complete data area
119 unsigned long m_ulWrIndex; // current write index (set bevore write)
120 unsigned long m_ulRdIndex; // current read index (set after read)
121 unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations
122 unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations)
123 unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1)
124 unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1)
125 unsigned long m_ulDataReadable; // buffer size with readable (complete written) data
126 unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks
127 tShbCirSigHndlrNewData m_pfnSigHndlrNewData; // application handler to signal new data
128 unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request)
129 tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done
130 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
132 } tShbCirBuff;
134 // structure to administrate linear shared buffer head
135 typedef struct {
136 unsigned int m_ShbLinMagicID; // magic ID ("SBL#")
137 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
138 unsigned long m_ulBufferDataSize; // size of complete data area
139 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
141 } tShbLinBuff;
143 // type to save size of a single data block inside the circular shared buffer
144 typedef struct {
145 unsigned int m_uiFullBlockSize:28; // a single block must not exceed a length of 256MByte :-)
146 unsigned int m_uiAlignFillBytes:4;
148 } tShbCirBlockSize;
150 #define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)!
151 #define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
153 #define SBL_BLOCK_ALIGNMENT 4
154 #define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
156 //---------------------------------------------------------------------------
157 // Global variables
158 //---------------------------------------------------------------------------
160 //---------------------------------------------------------------------------
161 // Local variables
162 //---------------------------------------------------------------------------
164 //---------------------------------------------------------------------------
165 // Prototypes of internal functions
166 //---------------------------------------------------------------------------
168 //---------------------------------------------------------------------------
169 // Get pointer to Circular Shared Buffer
170 //---------------------------------------------------------------------------
172 tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p)
175 tShbCirBuff *pShbCirBuff;
177 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
178 ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
180 return (pShbCirBuff);
184 //---------------------------------------------------------------------------
185 // Get pointer to Linear Shared Buffer
186 //---------------------------------------------------------------------------
188 tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p)
191 tShbLinBuff *pShbLinBuff;
193 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
194 ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
196 return (pShbLinBuff);
200 // not inlined internal functions
201 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p);
202 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
203 unsigned int fTimeOut_p);
206 //=========================================================================//
207 // //
208 // P U B L I C F U N C T I O N S //
209 // //
210 //=========================================================================//
212 // not inlined external functions
214 //---------------------------------------------------------------------------
215 // Initialize Shared Buffer Module
216 //---------------------------------------------------------------------------
218 tShbError ShbInit(void)
221 tShbError ShbError;
223 ShbError = ShbIpcInit();
225 return (ShbError);
229 //---------------------------------------------------------------------------
230 // Deinitialize Shared Buffer Module
231 //---------------------------------------------------------------------------
233 tShbError ShbExit(void)
236 tShbError ShbError;
238 ShbError = ShbIpcExit();
240 return (ShbError);
244 //-------------------------------------------------------------------------//
245 // //
246 // C i r c u l a r S h a r e d B u f f e r //
247 // //
248 //-------------------------------------------------------------------------//
250 //---------------------------------------------------------------------------
251 // Allocate Circular Shared Buffer
252 //---------------------------------------------------------------------------
254 tShbError ShbCirAllocBuffer(unsigned long ulBufferSize_p,
255 const char *pszBufferID_p,
256 tShbInstance * ppShbInstance_p,
257 unsigned int *pfShbNewCreated_p)
260 tShbInstance pShbInstance;
261 tShbCirBuff *pShbCirBuff;
262 unsigned int fShbNewCreated;
263 unsigned long ulBufferDataSize;
264 unsigned long ulBufferTotalSize;
265 tShbError ShbError;
267 // check arguments
268 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
269 return (kShbInvalidArg);
272 // calculate length of memory to allocate
273 ulBufferDataSize =
274 (ulBufferSize_p +
275 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
276 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
278 // allocate a new or open an existing shared buffer
279 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
280 &pShbInstance, &fShbNewCreated);
281 if (ShbError != kShbOk) {
282 goto Exit;
285 if (pShbInstance == NULL) {
286 ShbError = kShbOutOfMem;
287 goto Exit;
290 // get pointer to shared buffer
291 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance);
293 // if the shared buffer was new created, than this process has
294 // to initialize it, otherwise the buffer is already in use
295 // and *must not* be reseted
296 if (fShbNewCreated) {
297 #ifndef NDEBUG
299 memset(pShbCirBuff, 0xCC, ulBufferTotalSize);
301 #endif
303 pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID;
304 pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize;
305 pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize;
306 pShbCirBuff->m_ulWrIndex = 0;
307 pShbCirBuff->m_ulRdIndex = 0;
308 pShbCirBuff->m_ulNumOfWriteJobs = 0;
309 pShbCirBuff->m_ulDataInUse = 0;
310 pShbCirBuff->m_ulDataApended = 0;
311 pShbCirBuff->m_ulBlocksApended = 0;
312 pShbCirBuff->m_ulDataReadable = 0;
313 pShbCirBuff->m_ulBlocksReadable = 0;
314 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
315 pShbCirBuff->m_fBufferLocked = FALSE;
316 pShbCirBuff->m_pfnSigHndlrReset = NULL;
317 } else {
318 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
319 ShbError = kShbInvalidBufferType;
320 goto Exit;
324 Exit:
326 *ppShbInstance_p = pShbInstance;
327 *pfShbNewCreated_p = fShbNewCreated;
329 return (ShbError);
333 //---------------------------------------------------------------------------
334 // Release Circular Shared Buffer
335 //---------------------------------------------------------------------------
337 tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p)
340 tShbError ShbError;
342 // check arguments
343 if (pShbInstance_p == NULL) {
344 ShbError = kShbOk;
345 goto Exit;
348 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
350 Exit:
352 return (ShbError);
356 //---------------------------------------------------------------------------
357 // Reset Circular Shared Buffer
358 //---------------------------------------------------------------------------
360 tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p,
361 unsigned long ulTimeOut_p,
362 tShbCirSigHndlrReset pfnSignalHandlerReset_p)
365 tShbCirBuff *pShbCirBuff;
366 unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise
367 tShbError ShbError;
369 // check arguments
370 if (pShbInstance_p == NULL) {
371 ShbError = kShbInvalidArg;
372 goto Exit;
375 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
376 ShbError = kShbOk;
378 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
379 ShbError = kShbInvalidBufferType;
380 goto Exit;
383 // start reset job by setting request request in buffer header
384 ShbIpcEnterAtomicSection(pShbInstance_p);
386 if (!pShbCirBuff->m_fBufferLocked) {
387 ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
389 pShbCirBuff->m_fBufferLocked = TRUE;
390 pShbCirBuff->m_pfnSigHndlrReset =
391 pfnSignalHandlerReset_p;
392 } else {
393 ShbError = kShbAlreadyReseting;
396 ShbIpcLeaveAtomicSection(pShbInstance_p);
398 if (ShbError != kShbOk) {
399 goto Exit;
402 // if there is currently no running write operation then reset buffer
403 // immediately, otherwise wait until the last write job is ready by
404 // starting a signal process
405 if (ulNumOfWriteJobs == 0) {
406 // there is currently no running write operation
407 // -> reset buffer immediately
408 ShbCirSignalHandlerReset(pShbInstance_p, FALSE);
409 ShbError = kShbOk;
410 } else {
411 // there is currently at least one running write operation
412 // -> starting signal process to wait until the last write job is ready
413 ShbError =
414 ShbIpcStartSignalingJobReady(pShbInstance_p, ulTimeOut_p,
415 ShbCirSignalHandlerReset);
418 Exit:
420 return (ShbError);
424 //---------------------------------------------------------------------------
425 // Write data block to Circular Shared Buffer
426 //---------------------------------------------------------------------------
428 tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p,
429 const void *pSrcDataBlock_p,
430 unsigned long ulDataBlockSize_p)
433 tShbCirBuff *pShbCirBuff;
434 tShbCirBlockSize ShbCirBlockSize;
435 unsigned int uiFullBlockSize;
436 unsigned int uiAlignFillBytes;
437 unsigned char *pShbCirDataPtr;
438 unsigned char *pScrDataPtr;
439 unsigned long ulDataSize;
440 unsigned long ulChunkSize;
441 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
442 unsigned int fSignalNewData;
443 unsigned int fSignalReset;
444 tShbError ShbError;
445 tShbError ShbError2;
446 int fRes;
448 // check arguments
449 if (pShbInstance_p == NULL) {
450 ShbError = kShbInvalidArg;
451 goto Exit;
454 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
455 // nothing to do here
456 ShbError = kShbOk;
457 goto Exit;
460 if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE) {
461 ShbError = kShbExceedDataSizeLimit;
462 goto Exit;
465 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
466 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
467 fSignalNewData = FALSE;
468 fSignalReset = FALSE;
469 ShbError = kShbOk;
471 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
472 ShbError = kShbInvalidBufferType;
473 goto Exit;
476 // calculate data block size in circular buffer
477 ulDataSize =
478 (ulDataBlockSize_p +
479 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
480 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
481 uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
483 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
484 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
486 // reserve the needed memory for the write operation to do now
487 // and make necessary adjustments in the circular buffer header
488 ShbIpcEnterAtomicSection(pShbInstance_p);
490 // check if there is sufficient memory available to store
491 // the new data
492 fRes =
493 uiFullBlockSize <=
494 (pShbCirBuff->m_ulBufferDataSize -
495 pShbCirBuff->m_ulDataInUse);
496 if (fRes) {
497 // set write pointer for the write operation to do now
498 // to the current write pointer of the circular buffer
499 ulWrIndex = pShbCirBuff->m_ulWrIndex;
501 // reserve the needed memory for the write operation to do now
502 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
504 // set new write pointer behind the reserved memory
505 // for the write operation to do now
506 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
507 pShbCirBuff->m_ulWrIndex %=
508 pShbCirBuff->m_ulBufferDataSize;
510 // increment number of currently (parallel running)
511 // write operations
512 pShbCirBuff->m_ulNumOfWriteJobs++;
515 ShbIpcLeaveAtomicSection(pShbInstance_p);
517 if (!fRes) {
518 ShbError = kShbBufferFull;
519 goto Exit;
522 // copy the data to the circular buffer
523 // (the copy process itself will be done outside of any
524 // critical/locked section)
525 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
527 // write real size of current block (incl. alignment fill bytes)
528 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
529 ulWrIndex += sizeof(tShbCirBlockSize);
530 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
532 if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize) {
533 // linear write operation
534 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
535 ulDataBlockSize_p);
536 } else {
537 // wrap-around write operation
538 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
539 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize);
540 memcpy(pShbCirDataPtr, pScrDataPtr + ulChunkSize,
541 ulDataBlockSize_p - ulChunkSize);
544 // adjust header information for circular buffer with properties
545 // of the wiritten data block
546 ShbIpcEnterAtomicSection(pShbInstance_p);
548 pShbCirBuff->m_ulDataApended += uiFullBlockSize;
549 pShbCirBuff->m_ulBlocksApended++;
551 // decrement number of currently (parallel running) write operations
552 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
553 // if there is no other write process running then
554 // set new size of readable (complete written) data and
555 // adjust number of readable blocks
556 pShbCirBuff->m_ulDataReadable +=
557 pShbCirBuff->m_ulDataApended;
558 pShbCirBuff->m_ulBlocksReadable +=
559 pShbCirBuff->m_ulBlocksApended;
561 pShbCirBuff->m_ulDataApended = 0;
562 pShbCirBuff->m_ulBlocksApended = 0;
564 fSignalNewData = TRUE;
565 fSignalReset = pShbCirBuff->m_fBufferLocked;
568 ShbIpcLeaveAtomicSection(pShbInstance_p);
570 // signal new data event to a potentially reading application
571 if (fSignalNewData) {
572 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
573 if (ShbError == kShbOk) {
574 ShbError = ShbError2;
577 // signal that the last write job has been finished to allow
578 // a waiting application to reset the buffer now
579 if (fSignalReset) {
580 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
581 if (ShbError == kShbOk) {
582 ShbError = ShbError2;
586 Exit:
588 return (ShbError);
592 //---------------------------------------------------------------------------
593 // Allocate block within the Circular Shared Buffer for chunk writing
594 //---------------------------------------------------------------------------
596 tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p,
597 tShbCirChunk * pShbCirChunk_p,
598 unsigned long ulDataBufferSize_p)
601 tShbCirBuff *pShbCirBuff;
602 tShbCirBlockSize ShbCirBlockSize;
603 unsigned int uiFullBlockSize;
604 unsigned int uiAlignFillBytes;
605 unsigned char *pShbCirDataPtr;
606 unsigned long ulDataSize;
607 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
608 tShbError ShbError;
609 int fRes;
611 // check arguments
612 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)) {
613 ShbError = kShbInvalidArg;
614 goto Exit;
617 if (ulDataBufferSize_p == 0) {
618 ShbError = kShbInvalidArg;
619 goto Exit;
622 if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE) {
623 ShbError = kShbExceedDataSizeLimit;
624 goto Exit;
627 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
628 ShbError = kShbOk;
630 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
631 ShbError = kShbInvalidBufferType;
632 goto Exit;
635 // calculate data block size in circular buffer
636 ulDataSize =
637 (ulDataBufferSize_p +
638 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
639 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
640 uiAlignFillBytes = ulDataSize - ulDataBufferSize_p;
642 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
643 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
645 // reserve the needed memory for the write operation to do now
646 // and make necessary adjustments in the circular buffer header
647 ShbIpcEnterAtomicSection(pShbInstance_p);
649 // check if there is sufficient memory available to store
650 // the new data
651 fRes =
652 (uiFullBlockSize <=
653 (pShbCirBuff->m_ulBufferDataSize -
654 pShbCirBuff->m_ulDataInUse));
655 if (fRes) {
656 // set write pointer for the write operation to do now
657 // to the current write pointer of the circular buffer
658 ulWrIndex = pShbCirBuff->m_ulWrIndex;
660 // reserve the needed memory for the write operation to do now
661 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
663 // set new write pointer behind the reserved memory
664 // for the write operation to do now
665 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
666 pShbCirBuff->m_ulWrIndex %=
667 pShbCirBuff->m_ulBufferDataSize;
669 // increment number of currently (parallel running)
670 // write operations
671 pShbCirBuff->m_ulNumOfWriteJobs++;
674 ShbIpcLeaveAtomicSection(pShbInstance_p);
676 if (!fRes) {
677 ShbError = kShbBufferFull;
678 goto Exit;
681 // setup header information for allocated buffer
682 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
684 // write real size of current block (incl. alignment fill bytes)
685 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
686 ulWrIndex += sizeof(tShbCirBlockSize);
687 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
689 // setup chunk descriptor
690 pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize;
691 pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p;
692 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
693 pShbCirChunk_p->m_fBufferCompleted = FALSE;
695 Exit:
697 return (ShbError);
701 //---------------------------------------------------------------------------
702 // Write data chunk into an allocated buffer of the Circular Shared Buffer
703 //---------------------------------------------------------------------------
705 tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p,
706 tShbCirChunk *pShbCirChunk_p,
707 const void *pSrcDataChunk_p,
708 unsigned long ulDataChunkSize_p,
709 unsigned int *pfBufferCompleted_p)
712 tShbCirBuff *pShbCirBuff;
713 unsigned char *pShbCirDataPtr;
714 unsigned char *pScrDataPtr;
715 unsigned long ulSubChunkSize;
716 unsigned long ulWrIndex;
717 unsigned int fBufferCompleted;
718 unsigned int fSignalNewData;
719 unsigned int fSignalReset;
720 tShbError ShbError;
721 tShbError ShbError2;
723 // check arguments
724 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)
725 || (pfBufferCompleted_p == NULL)) {
726 ShbError = kShbInvalidArg;
727 goto Exit;
730 if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0)) {
731 // nothing to do here
732 ShbError = kShbOk;
733 goto Exit;
736 if (pShbCirChunk_p->m_fBufferCompleted) {
737 ShbError = kShbBufferAlreadyCompleted;
738 goto Exit;
741 if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize) {
742 ShbError = kShbExceedDataSizeLimit;
743 goto Exit;
746 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
747 pScrDataPtr = (unsigned char *)pSrcDataChunk_p;
748 fSignalNewData = FALSE;
749 fSignalReset = FALSE;
750 ShbError = kShbOk;
752 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
753 ShbError = kShbInvalidBufferType;
754 goto Exit;
757 ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
759 // copy the data to the circular buffer
760 // (the copy process itself will be done outside of any
761 // critical/locked section)
762 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
764 if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize) {
765 // linear write operation
766 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
767 ulDataChunkSize_p);
768 } else {
769 // wrap-around write operation
770 ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
771 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize);
772 memcpy(pShbCirDataPtr, pScrDataPtr + ulSubChunkSize,
773 ulDataChunkSize_p - ulSubChunkSize);
776 // adjust chunk descriptor
777 ulWrIndex += ulDataChunkSize_p;
778 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
780 pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
781 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
783 fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
784 pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
786 // if the complete allocated buffer is filled with data then
787 // adjust header information for circular buffer with properties
788 // of the wiritten data block
789 if (fBufferCompleted) {
790 ShbIpcEnterAtomicSection(pShbInstance_p);
792 pShbCirBuff->m_ulDataApended +=
793 pShbCirChunk_p->m_uiFullBlockSize;
794 pShbCirBuff->m_ulBlocksApended++;
796 // decrement number of currently (parallel running) write operations
797 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
798 // if there is no other write process running then
799 // set new size of readable (complete written) data and
800 // adjust number of readable blocks
801 pShbCirBuff->m_ulDataReadable +=
802 pShbCirBuff->m_ulDataApended;
803 pShbCirBuff->m_ulBlocksReadable +=
804 pShbCirBuff->m_ulBlocksApended;
806 pShbCirBuff->m_ulDataApended = 0;
807 pShbCirBuff->m_ulBlocksApended = 0;
809 fSignalNewData = TRUE;
810 fSignalReset = pShbCirBuff->m_fBufferLocked;
813 ShbIpcLeaveAtomicSection(pShbInstance_p);
816 // signal new data event to a potentially reading application
817 if (fSignalNewData) {
818 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
819 if (ShbError == kShbOk) {
820 ShbError = ShbError2;
823 // signal that the last write job has been finished to allow
824 // a waiting application to reset the buffer now
825 if (fSignalReset) {
826 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
827 if (ShbError == kShbOk) {
828 ShbError = ShbError2;
832 *pfBufferCompleted_p = fBufferCompleted;
834 Exit:
836 return (ShbError);
840 //---------------------------------------------------------------------------
841 // Read data block from Circular Shared Buffer
842 //---------------------------------------------------------------------------
844 tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p,
845 void *pDstDataBlock_p,
846 unsigned long ulRdBuffSize_p,
847 unsigned long *pulDataBlockSize_p)
850 tShbCirBuff *pShbCirBuff;
851 tShbCirBlockSize ShbCirBlockSize;
852 unsigned long ulDataReadable;
853 unsigned char *pShbCirDataPtr;
854 unsigned char *pDstDataPtr;
855 unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise
856 unsigned long ulChunkSize;
857 unsigned long ulRdIndex;
858 tShbError ShbError;
860 // check arguments
861 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
862 return (kShbInvalidArg);
865 if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0)) {
866 // nothing to do here
867 ShbError = kShbOk;
868 goto Exit;
871 ShbError = kShbOk;
872 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
873 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
874 ulDataSize = 0;
876 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
877 ShbError = kShbInvalidBufferType;
878 goto Exit;
881 // get total number of readable bytes for the whole circular buffer
882 ShbIpcEnterAtomicSection(pShbInstance_p);
884 ulDataReadable = pShbCirBuff->m_ulDataReadable;
886 ShbIpcLeaveAtomicSection(pShbInstance_p);
888 // if there are readable data available, then there must be at least
889 // one complete readable data block
890 if (ulDataReadable > 0) {
891 // get pointer to start of data area and current read index
892 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
893 ulRdIndex = pShbCirBuff->m_ulRdIndex;
895 // get real size of current block (incl. alignment fill bytes)
896 ShbCirBlockSize =
897 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
898 ulRdIndex += sizeof(tShbCirBlockSize);
899 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
901 // get size of user data inside the current block
902 ulDataSize =
903 ShbCirBlockSize.m_uiFullBlockSize -
904 ShbCirBlockSize.m_uiAlignFillBytes;
905 ulDataSize -= sizeof(tShbCirBlockSize);
908 // ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
909 if (ulDataSize > ulRdBuffSize_p) {
910 ulDataSize = ulRdBuffSize_p;
911 ShbError = kShbDataTruncated;
914 if (ulDataSize == 0) {
915 // nothing to do here
916 ShbError = kShbNoReadableData;
917 goto Exit;
920 // copy the data from the circular buffer
921 // (the copy process itself will be done outside of any
922 // critical/locked section)
923 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
924 // linear read operation
925 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize);
926 } else {
927 // wrap-around read operation
928 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
929 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize);
930 memcpy(pDstDataPtr + ulChunkSize, pShbCirDataPtr,
931 ulDataSize - ulChunkSize);
934 #ifndef NDEBUG
936 tShbCirBlockSize ClrShbCirBlockSize;
938 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
939 // linear buffer
940 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
941 } else {
942 // wrap-around read operation
943 ulChunkSize =
944 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
945 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
946 memset(pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
949 ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int) */ -1; // -1 = xFFFFFFF
950 ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int) */ -1; // -1 = Fxxxxxxx
951 *(tShbCirBlockSize *) (pShbCirDataPtr +
952 pShbCirBuff->m_ulRdIndex) =
953 ClrShbCirBlockSize;
955 #endif // #ifndef NDEBUG
957 // set new size of readable data, data in use, new read index
958 // and adjust number of readable blocks
959 ShbIpcEnterAtomicSection(pShbInstance_p);
961 pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
962 pShbCirBuff->m_ulDataReadable -=
963 ShbCirBlockSize.m_uiFullBlockSize;
964 pShbCirBuff->m_ulBlocksReadable--;
966 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
967 if ((pShbCirBuff->m_ulDataInUse == 0)
968 && (pShbCirBuff->m_ulDataReadable == 0)) {
969 ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
971 pShbCirBuff->m_ulWrIndex = 0;
972 pShbCirBuff->m_ulRdIndex = 0;
973 } else
974 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
976 pShbCirBuff->m_ulRdIndex +=
977 ShbCirBlockSize.m_uiFullBlockSize;
978 pShbCirBuff->m_ulRdIndex %=
979 pShbCirBuff->m_ulBufferDataSize;
982 ShbIpcLeaveAtomicSection(pShbInstance_p);
984 Exit:
986 *pulDataBlockSize_p = ulDataSize;
988 return (ShbError);
992 //---------------------------------------------------------------------------
993 // Get data size of next readable block from Circular Shared Buffer
994 //---------------------------------------------------------------------------
996 tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p,
997 unsigned long *pulDataBlockSize_p)
1000 tShbCirBuff *pShbCirBuff;
1001 unsigned long ulDataReadable;
1002 unsigned char *pShbCirDataPtr;
1003 tShbCirBlockSize ShbCirBlockSize;
1004 unsigned long ulDataSize;
1005 tShbError ShbError;
1007 // check arguments
1008 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
1009 return (kShbInvalidArg);
1012 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1013 ulDataSize = 0;
1014 ShbError = kShbOk;
1016 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1017 ShbError = kShbInvalidBufferType;
1018 goto Exit;
1021 // get total number of readable bytes for the whole circular buffer
1022 ShbIpcEnterAtomicSection(pShbInstance_p);
1024 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1026 ShbIpcLeaveAtomicSection(pShbInstance_p);
1028 // if there are readable data available, then there must be at least
1029 // one complete readable data block
1030 if (ulDataReadable > 0) {
1031 pShbCirDataPtr =
1032 &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
1034 // get real size of current block (incl. alignment fill bytes)
1035 ShbCirBlockSize = *(tShbCirBlockSize *) pShbCirDataPtr;
1037 // get size of user data inside the current block
1038 ulDataSize =
1039 ShbCirBlockSize.m_uiFullBlockSize -
1040 ShbCirBlockSize.m_uiAlignFillBytes;
1041 ulDataSize -= sizeof(tShbCirBlockSize);
1044 Exit:
1046 *pulDataBlockSize_p = ulDataSize;
1048 return (ShbError);
1052 //---------------------------------------------------------------------------
1053 // Get number of readable blocks from Circular Shared Buffer
1054 //---------------------------------------------------------------------------
1056 tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,
1057 unsigned long *pulDataBlockCount_p)
1060 tShbCirBuff *pShbCirBuff;
1061 unsigned long ulBlockCount;
1062 tShbError ShbError;
1064 // check arguments
1065 if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL)) {
1066 ShbError = kShbInvalidArg;
1067 goto Exit;
1070 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1071 ulBlockCount = 0;
1072 ShbError = kShbOk;
1074 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1075 ShbError = kShbInvalidBufferType;
1076 goto Exit;
1079 ShbIpcEnterAtomicSection(pShbInstance_p);
1081 ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
1083 ShbIpcLeaveAtomicSection(pShbInstance_p);
1085 *pulDataBlockCount_p = ulBlockCount;
1087 Exit:
1089 return (ShbError);
1093 //---------------------------------------------------------------------------
1094 // Set application handler to signal new data for Circular Shared Buffer
1095 // d.k.: new parameter priority as enum
1096 //---------------------------------------------------------------------------
1098 tShbError ShbCirSetSignalHandlerNewData(tShbInstance pShbInstance_p,
1099 tShbCirSigHndlrNewData pfnSignalHandlerNewData_p,
1100 tShbPriority ShbPriority_p)
1103 tShbCirBuff *pShbCirBuff;
1104 tShbError ShbError;
1106 // check arguments
1107 if (pShbInstance_p == NULL) {
1108 ShbError = kShbInvalidArg;
1109 goto Exit;
1112 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1113 ShbError = kShbOk;
1115 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1116 ShbError = kShbInvalidBufferType;
1117 goto Exit;
1120 if (pfnSignalHandlerNewData_p != NULL) {
1121 // set a new signal handler
1122 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1123 ShbError = kShbAlreadySignaling;
1124 goto Exit;
1127 pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
1128 ShbError =
1129 ShbIpcStartSignalingNewData(pShbInstance_p,
1130 ShbCirSignalHandlerNewData,
1131 ShbPriority_p);
1132 } else {
1133 // remove existing signal handler
1134 ShbError = ShbIpcStopSignalingNewData(pShbInstance_p);
1135 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1136 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p, 0);
1138 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
1141 Exit:
1143 return (ShbError);
1147 //---------------------------------------------------------------------------
1148 // DEBUG: Trace Circular Shared Buffer
1149 //---------------------------------------------------------------------------
1151 #ifndef NDEBUG
1152 tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p)
1155 tShbCirBuff *pShbCirBuff;
1156 char szMagigID[sizeof(SBC_MAGIC_ID) + 1];
1157 tShbCirBlockSize ShbCirBlockSize;
1158 unsigned long ulDataReadable;
1159 unsigned char *pShbCirDataPtr;
1160 unsigned long ulBlockIndex;
1161 unsigned int nBlockCount;
1162 unsigned long ulDataSize;
1163 unsigned long ulChunkSize;
1164 unsigned long ulRdIndex;
1165 tShbError ShbError;
1167 TRACE0("\n\n##### Circular Shared Buffer #####\n");
1169 // check arguments
1170 if (pShbInstance_p == NULL) {
1171 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1172 (unsigned long)pShbInstance_p);
1173 ShbError = kShbInvalidArg;
1174 goto Exit;
1177 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1178 ShbError = kShbOk;
1180 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1181 ShbError = kShbInvalidBufferType;
1182 goto Exit;
1185 *(unsigned long *)&szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
1186 szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
1188 ShbIpcEnterAtomicSection(pShbInstance_p);
1190 TRACE1("\nBuffer Address: 0x%08lX\n",
1191 (unsigned long)pShbCirBuff);
1193 TRACE0("\nHeader Info:");
1194 TRACE2("\nMagigID: '%s' (%08lX)", szMagigID,
1195 pShbCirBuff->m_ShbCirMagicID);
1196 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1197 pShbCirBuff->m_ulBufferTotalSize);
1198 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1199 pShbCirBuff->m_ulBufferDataSize);
1200 TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex);
1201 TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex);
1202 TRACE1("\nNumOfWriteJobs: %4lu",
1203 pShbCirBuff->m_ulNumOfWriteJobs);
1204 TRACE1("\nDataInUse: %4lu [Bytes]",
1205 pShbCirBuff->m_ulDataInUse);
1206 TRACE1("\nDataApended: %4lu [Bytes]",
1207 pShbCirBuff->m_ulDataApended);
1208 TRACE1("\nBlocksApended: %4lu",
1209 pShbCirBuff->m_ulBlocksApended);
1210 TRACE1("\nDataReadable: %4lu [Bytes]",
1211 pShbCirBuff->m_ulDataReadable);
1212 TRACE1("\nBlocksReadable: %4lu",
1213 pShbCirBuff->m_ulBlocksReadable);
1214 TRACE1("\nSigHndlrNewData: %08lX",
1215 (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData);
1216 TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked);
1217 TRACE1("\nSigHndlrReset: %08lX",
1218 (unsigned long)pShbCirBuff->m_pfnSigHndlrReset);
1220 ShbTraceDump(&pShbCirBuff->m_Data,
1221 pShbCirBuff->m_ulBufferDataSize, 0x00000000L,
1222 "\nData Area:");
1224 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1225 nBlockCount = 1;
1226 ulBlockIndex = pShbCirBuff->m_ulRdIndex;
1228 while (ulDataReadable > 0) {
1229 TRACE1("\n\n--- Block #%u ---", nBlockCount);
1231 // get pointer to start of data area and current read index
1232 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
1233 ulRdIndex = ulBlockIndex;
1235 // get real size of current block (incl. alignment fill bytes)
1236 ShbCirBlockSize =
1237 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
1238 ulRdIndex += sizeof(tShbCirBlockSize);
1239 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
1241 // get size of user data inside the current block
1242 ulDataSize =
1243 ShbCirBlockSize.m_uiFullBlockSize -
1244 ShbCirBlockSize.m_uiAlignFillBytes;
1245 ulDataSize -= sizeof(tShbCirBlockSize);
1247 TRACE1
1248 ("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)",
1249 ShbCirBlockSize.m_uiFullBlockSize);
1250 TRACE1("\nUser Data Size: %4lu [Bytes]",
1251 ulDataSize);
1252 TRACE1("\nAlignment Fill Bytes: %4u [Bytes]",
1253 ShbCirBlockSize.m_uiAlignFillBytes);
1255 if (ulRdIndex + ulDataSize <=
1256 pShbCirBuff->m_ulBufferDataSize) {
1257 // linear data buffer
1258 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1259 ulDataSize, 0x00000000L, NULL);
1260 } else {
1261 // wrap-around data buffer
1262 ulChunkSize =
1263 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
1264 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1265 ulChunkSize, 0x00000000L, NULL);
1266 ShbTraceDump(pShbCirDataPtr,
1267 ulDataSize - ulChunkSize,
1268 ulChunkSize, NULL);
1271 nBlockCount++;
1273 ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
1274 ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
1276 ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
1279 ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount - 1);
1281 ShbIpcLeaveAtomicSection(pShbInstance_p);
1283 Exit:
1285 return (ShbError);
1288 #endif
1290 //-------------------------------------------------------------------------//
1291 // //
1292 // L i n e a r S h a r e d B u f f e r //
1293 // //
1294 //-------------------------------------------------------------------------//
1296 //---------------------------------------------------------------------------
1297 // Allocate Linear Shared Buffer
1298 //---------------------------------------------------------------------------
1300 tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p,
1301 const char *pszBufferID_p,
1302 tShbInstance * ppShbInstance_p,
1303 unsigned int *pfShbNewCreated_p)
1306 tShbInstance pShbInstance;
1307 tShbLinBuff *pShbLinBuff;
1308 unsigned int fShbNewCreated;
1309 unsigned long ulBufferDataSize;
1310 unsigned long ulBufferTotalSize;
1311 tShbError ShbError;
1313 // check arguments
1314 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
1315 return (kShbInvalidArg);
1318 // calculate length of memory to allocate
1319 ulBufferDataSize =
1320 (ulBufferSize_p +
1321 (SBL_BLOCK_ALIGNMENT - 1)) & ~(SBL_BLOCK_ALIGNMENT - 1);
1322 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
1324 // allocate a new or open an existing shared buffer
1325 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
1326 &pShbInstance, &fShbNewCreated);
1327 if (ShbError != kShbOk) {
1328 goto Exit;
1331 if (pShbInstance == NULL) {
1332 ShbError = kShbOutOfMem;
1333 goto Exit;
1336 // get pointer to shared buffer
1337 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance);
1339 // if the shared buffer was new created, than this process has
1340 // to initialize it, otherwise the buffer is already in use
1341 // and *must not* be reseted
1342 if (fShbNewCreated) {
1343 #ifndef NDEBUG
1345 memset(pShbLinBuff, 0xCC, ulBufferTotalSize);
1347 #endif
1349 pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
1350 pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
1351 pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
1352 } else {
1353 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1354 ShbError = kShbInvalidBufferType;
1355 goto Exit;
1359 Exit:
1361 *ppShbInstance_p = pShbInstance;
1362 *pfShbNewCreated_p = fShbNewCreated;
1364 return (ShbError);
1368 //---------------------------------------------------------------------------
1369 // Release Linear Shared Buffer
1370 //---------------------------------------------------------------------------
1372 tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p)
1375 tShbError ShbError;
1377 // check arguments
1378 if (pShbInstance_p == NULL) {
1379 ShbError = kShbOk;
1380 goto Exit;
1383 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
1385 Exit:
1387 return (ShbError);
1391 //---------------------------------------------------------------------------
1392 // Write data block to Linear Shared Buffer
1393 //---------------------------------------------------------------------------
1394 tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p,
1395 unsigned long ulDstBufferOffs_p,
1396 const void *pSrcDataBlock_p,
1397 unsigned long ulDataBlockSize_p)
1400 tShbLinBuff *pShbLinBuff;
1401 unsigned char *pShbLinDataPtr;
1402 unsigned char *pScrDataPtr;
1403 unsigned long ulBufferDataSize;
1404 tShbError ShbError;
1406 // check arguments
1407 if (pShbInstance_p == NULL) {
1408 ShbError = kShbInvalidArg;
1409 goto Exit;
1412 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1413 // nothing to do here
1414 ShbError = kShbOk;
1415 goto Exit;
1418 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1419 ShbError = kShbExceedDataSizeLimit;
1420 goto Exit;
1423 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1424 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
1425 ShbError = kShbOk;
1427 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1428 ShbError = kShbInvalidBufferType;
1429 goto Exit;
1432 // check if offeset and size for the write operation matches with
1433 // the size of the shared buffer
1434 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1435 if ((ulDstBufferOffs_p > ulBufferDataSize) ||
1436 (ulDataBlockSize_p > ulBufferDataSize) ||
1437 ((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1438 ShbError = kShbDataOutsideBufferArea;
1439 goto Exit;
1442 // copy the data to the linear buffer
1443 // (the copy process will be done inside of any critical/locked section)
1444 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1445 pShbLinDataPtr += ulDstBufferOffs_p;
1447 ShbIpcEnterAtomicSection(pShbInstance_p);
1449 memcpy(pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
1451 ShbIpcLeaveAtomicSection(pShbInstance_p);
1453 Exit:
1455 return (ShbError);
1459 //---------------------------------------------------------------------------
1460 // Read data block from Linear Shared Buffer
1461 //---------------------------------------------------------------------------
1462 tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p,
1463 void *pDstDataBlock_p,
1464 unsigned long ulSrcBufferOffs_p,
1465 unsigned long ulDataBlockSize_p)
1468 tShbLinBuff *pShbLinBuff;
1469 unsigned char *pShbLinDataPtr;
1470 unsigned char *pDstDataPtr;
1471 unsigned long ulBufferDataSize;
1472 tShbError ShbError;
1474 // check arguments
1475 if (pShbInstance_p == NULL) {
1476 ShbError = kShbInvalidArg;
1477 goto Exit;
1480 if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1481 // nothing to do here
1482 ShbError = kShbOk;
1483 goto Exit;
1486 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1487 ShbError = kShbExceedDataSizeLimit;
1488 goto Exit;
1491 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1492 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
1493 ShbError = kShbOk;
1495 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1496 ShbError = kShbInvalidBufferType;
1497 goto Exit;
1500 // check if offeset and size for the read operation matches with
1501 // the size of the shared buffer
1502 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1503 if ((ulSrcBufferOffs_p > ulBufferDataSize) ||
1504 (ulDataBlockSize_p > ulBufferDataSize) ||
1505 ((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1506 ShbError = kShbDataOutsideBufferArea;
1507 goto Exit;
1510 // copy the data to the linear buffer
1511 // (the copy process will be done inside of any critical/locked section)
1512 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1513 pShbLinDataPtr += ulSrcBufferOffs_p;
1515 ShbIpcEnterAtomicSection(pShbInstance_p);
1517 memcpy(pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
1519 ShbIpcLeaveAtomicSection(pShbInstance_p);
1521 Exit:
1523 return (ShbError);
1527 //---------------------------------------------------------------------------
1528 // DEBUG: Trace Linear Shared Buffer
1529 //---------------------------------------------------------------------------
1531 #ifndef NDEBUG
1532 tShbError ShbLinTraceBuffer(tShbInstance pShbInstance_p)
1535 tShbLinBuff *pShbLinBuff;
1536 char szMagigID[sizeof(SBL_MAGIC_ID) + 1];
1537 tShbError ShbError;
1539 TRACE0("\n\n##### Linear Shared Buffer #####\n");
1541 // check arguments
1542 if (pShbInstance_p == NULL) {
1543 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1544 (unsigned long)pShbInstance_p);
1545 ShbError = kShbInvalidArg;
1546 goto Exit;
1549 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1550 ShbError = kShbOk;
1552 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1553 ShbError = kShbInvalidBufferType;
1554 goto Exit;
1557 *(unsigned int *)&szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
1558 szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
1560 ShbIpcEnterAtomicSection(pShbInstance_p);
1562 TRACE1("\nBuffer Address: 0x%08lX\n",
1563 (unsigned long)pShbLinBuff);
1565 TRACE0("\nHeader Info:");
1566 TRACE2("\nMagigID: '%s' (%08X)", szMagigID,
1567 pShbLinBuff->m_ShbLinMagicID);
1568 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1569 pShbLinBuff->m_ulBufferTotalSize);
1570 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1571 pShbLinBuff->m_ulBufferDataSize);
1573 ShbTraceDump(&pShbLinBuff->m_Data,
1574 pShbLinBuff->m_ulBufferDataSize, 0x00000000L,
1575 "\nData Area:");
1577 ShbIpcLeaveAtomicSection(pShbInstance_p);
1579 Exit:
1581 return (ShbError);
1584 #endif
1586 //---------------------------------------------------------------------------
1587 // Dump buffer contents
1588 //---------------------------------------------------------------------------
1590 #ifndef NDEBUG
1591 tShbError ShbTraceDump(const unsigned char *pabStartAddr_p,
1592 unsigned long ulDataSize_p,
1593 unsigned long ulAddrOffset_p, const char *pszInfoText_p)
1596 const unsigned char *pabBuffData;
1597 unsigned long ulBuffSize;
1598 unsigned char bData;
1599 int nRow;
1600 int nCol;
1602 // get pointer to buffer and length of buffer
1603 pabBuffData = pabStartAddr_p;
1604 ulBuffSize = ulDataSize_p;
1606 if (pszInfoText_p != NULL) {
1607 TRACE1("%s", pszInfoText_p);
1609 // dump buffer contents
1610 for (nRow = 0;; nRow++) {
1611 TRACE1("\n%08lX: ",
1612 (unsigned long)(nRow * 0x10) + ulAddrOffset_p);
1614 for (nCol = 0; nCol < 16; nCol++) {
1615 if ((unsigned long)nCol < ulBuffSize) {
1616 TRACE1("%02X ",
1617 (unsigned int)*(pabBuffData + nCol));
1618 } else {
1619 TRACE0(" ");
1623 TRACE0(" ");
1625 for (nCol = 0; nCol < 16; nCol++) {
1626 bData = *pabBuffData++;
1627 if ((unsigned long)nCol < ulBuffSize) {
1628 if ((bData >= 0x20) && (bData < 0x7F)) {
1629 TRACE1("%c", bData);
1630 } else {
1631 TRACE0(".");
1633 } else {
1634 TRACE0(" ");
1638 if (ulBuffSize > 16) {
1639 ulBuffSize -= 16;
1640 } else {
1641 break;
1645 return (kShbOk);
1648 #endif // #ifndef NDEBUG
1650 //=========================================================================//
1651 // //
1652 // P R I V A T E F U N C T I O N S //
1653 // //
1654 //=========================================================================//
1656 //---------------------------------------------------------------------------
1657 // Handler to signal new data event for Circular Shared Buffer
1658 //---------------------------------------------------------------------------
1660 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p)
1663 tShbCirBuff *pShbCirBuff;
1664 unsigned long ulDataSize;
1665 unsigned long ulBlockCount;
1666 tShbError ShbError;
1668 // check arguments
1669 if (pShbInstance_p == NULL) {
1670 return FALSE;
1673 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1674 ShbError = kShbOk;
1676 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1677 return FALSE;
1680 // call application handler
1681 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1682 /* do
1684 ShbError = ShbCirGetReadDataSize(pShbInstance_p, &ulDataSize);
1685 if ((ulDataSize > 0) && (ShbError == kShbOk)) {
1686 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p,
1687 ulDataSize);
1690 ShbError =
1691 ShbCirGetReadBlockCount(pShbInstance_p, &ulBlockCount);
1692 /* }
1693 while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
1695 // Return TRUE if there are pending blocks.
1696 // In that case ShbIpc tries to call this function again immediately if there
1697 // is no other filled shared buffer with higher priority.
1698 return ((ulBlockCount > 0) && (ShbError == kShbOk));
1702 //---------------------------------------------------------------------------
1703 // Handler to reset Circular Shared Buffer
1704 //---------------------------------------------------------------------------
1706 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
1707 unsigned int fTimeOut_p)
1710 tShbCirBuff *pShbCirBuff;
1712 // check arguments
1713 if (pShbInstance_p == NULL) {
1714 return;
1717 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1718 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1719 return;
1722 // reset buffer header
1723 if (!fTimeOut_p) {
1724 ShbIpcEnterAtomicSection(pShbInstance_p);
1726 pShbCirBuff->m_ulWrIndex = 0;
1727 pShbCirBuff->m_ulRdIndex = 0;
1728 pShbCirBuff->m_ulNumOfWriteJobs = 0;
1729 pShbCirBuff->m_ulDataInUse = 0;
1730 pShbCirBuff->m_ulDataApended = 0;
1731 pShbCirBuff->m_ulBlocksApended = 0;
1732 pShbCirBuff->m_ulDataReadable = 0;
1733 pShbCirBuff->m_ulBlocksReadable = 0;
1735 ShbIpcLeaveAtomicSection(pShbInstance_p);
1737 #ifndef NDEBUG
1739 memset(&pShbCirBuff->m_Data, 0xCC,
1740 pShbCirBuff->m_ulBufferDataSize);
1742 #endif
1745 // call application handler
1746 if (pShbCirBuff->m_pfnSigHndlrReset != NULL) {
1747 pShbCirBuff->m_pfnSigHndlrReset(pShbInstance_p, fTimeOut_p);
1750 // unlock buffer
1751 ShbIpcEnterAtomicSection(pShbInstance_p);
1753 pShbCirBuff->m_fBufferLocked = FALSE;
1754 pShbCirBuff->m_pfnSigHndlrReset = NULL;
1756 ShbIpcLeaveAtomicSection(pShbInstance_p);
1758 return;
1762 // EOF