HID: fix bus endianity in file2alias
[linux-2.6/mini2440.git] / drivers / staging / epl / ShbIpc-LinuxKernel.c
blob1d3cb3f13de1f09b2ae16b3f76cfd32f9712eb9f
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 specific part for the
9 shared buffer
10 (Implementation for Linux KernelSpace)
12 License:
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions
16 are met:
18 1. Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
25 3. Neither the name of SYSTEC electronic GmbH nor the names of its
26 contributors may be used to endorse or promote products derived
27 from this software without prior written permission. For written
28 permission, please contact info@systec-electronic.com.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 POSSIBILITY OF SUCH DAMAGE.
43 Severability Clause:
45 If a provision of this License is or becomes illegal, invalid or
46 unenforceable in any jurisdiction, that shall not affect:
47 1. the validity or enforceability in that jurisdiction of any other
48 provision of this License; or
49 2. the validity or enforceability in other jurisdictions of that or
50 any other provision of this License.
52 -------------------------------------------------------------------------
54 2006/06/28 -rs: V 1.00 (initial version)
56 ****************************************************************************/
58 #include "global.h"
59 #include "SharedBuff.h"
60 #include "ShbIpc.h"
61 #include "ShbLinuxKernel.h"
62 #include "Debug.h"
64 #include <linux/string.h>
65 #include <linux/module.h>
66 #include <asm/processor.h>
67 //#include <linux/vmalloc.h>
68 #include <linux/sched.h>
69 #include <linux/param.h>
70 #include <linux/spinlock.h>
71 #include <linux/wait.h>
72 #include <linux/completion.h>
74 /***************************************************************************/
75 /* */
76 /* */
77 /* G L O B A L D E F I N I T I O N S */
78 /* */
79 /* */
80 /***************************************************************************/
82 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
84 //---------------------------------------------------------------------------
85 // Configuration
86 //---------------------------------------------------------------------------
88 //---------------------------------------------------------------------------
89 // Constant definitions
90 //---------------------------------------------------------------------------
92 #define MAX_LEN_BUFFER_ID 256
94 #define TIMEOUT_ENTER_ATOMIC 1000 // (ms) for debgging: INFINITE
95 #define TIMEOUT_TERM_THREAD 1000
96 #define INFINITE 3600
98 #define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
99 #define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
101 #define INVALID_ID -1
103 #define TABLE_SIZE 10
105 //---------------------------------------------------------------------------
106 // Local types
107 //---------------------------------------------------------------------------
109 // This structure is the common header for the shared memory region used
110 // by all processes attached this shared memory. It includes common
111 // information to administrate/manage the shared buffer from a couple of
112 // separated processes (e.g. the refernce counter). This structure is
113 // located at the start of the shared memory region itself and exists
114 // consequently only one times per shared memory instance.
115 typedef struct {
117 unsigned long m_ulShMemSize;
118 unsigned long m_ulRefCount;
119 int m_iBufferId;
120 // int m_iUserSpaceMem; //0 for userspace mem !=0 kernelspace mem
121 spinlock_t m_SpinlockBuffAccess;
122 BOOL m_fNewData;
123 BOOL m_fJobReady;
124 wait_queue_head_t m_WaitQueueNewData;
125 wait_queue_head_t m_WaitQueueJobReady;
127 #ifndef NDEBUG
128 unsigned long m_ulOwnerProcID;
129 #endif
131 } tShbMemHeader;
133 // This structure is the "external entry point" from a separate process
134 // to get access to a shared buffer. This structure includes all platform
135 // resp. target specific information to administrate/manage the shared
136 // buffer from a separate process. Every process attached to the shared
137 // buffer has its own runtime instance of this structure with its individual
138 // runtime data (e.g. the scope of an event handle is limitted to the
139 // owner process only). The structure member <m_pShbMemHeader> points
140 // to the (process specific) start address of the shared memory region
141 // itself.
142 typedef struct {
143 unsigned long m_SbiMagicID; // magic ID ("SBI+")
144 // void* m_pSharedMem;
145 int m_tThreadNewDataId;
146 long m_lThreadNewDataNice; // nice value of the new data thread
147 int m_tThreadJobReadyId;
148 unsigned long m_ulFlagsBuffAccess; // d.k. moved from tShbMemHeader, because each
149 // process needs to store the interrupt flags separately
150 tSigHndlrNewData m_pfnSigHndlrNewData;
151 unsigned long m_ulTimeOutJobReady;
152 tSigHndlrJobReady m_pfnSigHndlrJobReady;
153 tShbMemHeader *m_pShbMemHeader;
154 int m_iThreadTermFlag;
155 struct completion m_CompletionNewData;
157 struct semaphore *m_pSemBuffAccess;
158 struct semaphore *m_pSemNewData;
159 struct semaphore *m_pSemStopSignalingNewData;
160 struct semaphore *m_pSemJobReady;
162 #ifndef NDEBUG
163 unsigned long m_ulThreadIDNewData;
164 unsigned long m_ulThreadIDJobReady;
165 #endif
166 } tShbMemInst;
168 //---------------------------------------------------------------------------
169 // Prototypes of internal functions
170 //---------------------------------------------------------------------------
172 //tShbMemInst* ShbIpcGetShbMemInst (tShbInstance pShbInstance_p);
173 //tShbMemHeader* ShbIpcGetShbMemHeader (tShbMemInst* pShbMemInst_p);
175 //---------------------------------------------------------------------------
176 // Get pointer to process local information structure
177 //---------------------------------------------------------------------------
179 static inline tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)
182 tShbMemInst *pShbMemInst;
184 pShbMemInst = (tShbMemInst *) pShbInstance_p;
186 return (pShbMemInst);
190 //---------------------------------------------------------------------------
191 // Get pointer to shared memory header
192 //---------------------------------------------------------------------------
194 static inline tShbMemHeader *ShbIpcGetShbMemHeader(tShbMemInst * pShbMemInst_p)
197 tShbMemHeader *pShbMemHeader;
199 pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
201 return (pShbMemHeader);
205 // Get pointer to process local information structure
206 //#define ShbIpcGetShbMemInst(pShbInstance_p) ((tShbMemInst*)pShbInstance_p)
208 // Get pointer to shared memory header
209 //#define ShbIpcGetShbMemHeader(pShbMemInst_p) (pShbMemInst_p->m_pShbMemHeader)
211 // not inlined internal functions
212 int ShbIpcThreadSignalNewData(void *pvThreadParam_p);
213 int ShbIpcThreadSignalJobReady(void *pvThreadParam_p);
214 #endif
216 //---------------------------------------------------------------------------
217 // modul globale vars
218 //---------------------------------------------------------------------------
220 #if !defined(SHBIPC_INLINE_ENABLED)
221 struct sShbMemTable *psMemTableElementFirst_g;
223 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p);
224 static int ShbIpcFindListElement(int iBufferId,
225 struct sShbMemTable
226 **ppsReturnMemTableElement);
227 static void ShbIpcAppendListElement(struct sShbMemTable *sNewMemTableElement);
228 static void ShbIpcDeleteListElement(int iBufferId);
229 static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256]);
230 static unsigned long ShbIpcCrc32GetCrc(const char *pcString,
231 unsigned long aulCrcTable[256]);
233 #endif
235 //=========================================================================//
236 // //
237 // P U B L I C F U N C T I O N S //
238 // //
239 //=========================================================================//
241 #if !defined(SHBIPC_INLINE_ENABLED)
242 // not inlined external functions
244 //---------------------------------------------------------------------------
245 // Initialize IPC for Shared Buffer Module
246 //---------------------------------------------------------------------------
248 tShbError ShbIpcInit(void)
250 psMemTableElementFirst_g = NULL;
251 return (kShbOk);
255 //---------------------------------------------------------------------------
256 // Deinitialize IPC for Shared Buffer Module
257 //---------------------------------------------------------------------------
259 tShbError ShbIpcExit(void)
262 return (kShbOk);
266 //---------------------------------------------------------------------------
267 // Allocate Shared Buffer
268 //---------------------------------------------------------------------------
270 tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
271 const char *pszBufferID_p,
272 tShbInstance * ppShbInstance_p,
273 unsigned int *pfShbNewCreated_p)
275 tShbError ShbError;
276 int iBufferId = 0;
277 unsigned long ulCrc32 = 0;
278 unsigned int uiFirstProcess = 0;
279 unsigned long ulShMemSize;
280 tShbMemHeader *pShbMemHeader;
281 tShbMemInst *pShbMemInst = NULL;
282 tShbInstance pShbInstance;
283 unsigned int fShMemNewCreated = FALSE;
284 void *pSharedMem = NULL;
285 unsigned long aulCrcTable[256];
286 struct sShbMemTable *psMemTableElement;
288 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n");
289 ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
291 //create Buffer ID
292 ShbIpcCrc32GenTable(aulCrcTable);
293 ulCrc32 = ShbIpcCrc32GetCrc(pszBufferID_p, aulCrcTable);
294 iBufferId = ulCrc32;
295 DEBUG_LVL_29_TRACE2
296 ("ShbIpcAllocBuffer BufferSize:%d sizeof(tShb..):%d\n",
297 ulBufferSize_p, sizeof(tShbMemHeader));
298 DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferId:%d MemSize:%d\n",
299 iBufferId, ulShMemSize);
300 //---------------------------------------------------------------
301 // (1) open an existing or create a new shared memory
302 //---------------------------------------------------------------
303 //test if buffer already exists
304 if (ShbIpcFindListElement(iBufferId, &psMemTableElement) == 0) {
305 //Buffer already exists
306 fShMemNewCreated = FALSE;
307 pSharedMem = psMemTableElement->m_pBuffer;
308 DEBUG_LVL_29_TRACE1
309 ("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n",
310 pSharedMem);
311 uiFirstProcess = 1;
312 } else {
313 //create new Buffer
314 fShMemNewCreated = TRUE;
315 uiFirstProcess = 0;
316 pSharedMem = kmalloc(ulShMemSize, GFP_KERNEL);
317 DEBUG_LVL_29_TRACE2
318 ("ShbIpcAllocBuffer Create New Buffer at:%p Id:%d\n",
319 pSharedMem, iBufferId);
320 if (pSharedMem == NULL) {
321 //unable to create mem
322 ShbError = kShbOutOfMem;
323 goto Exit;
325 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer create semas\n");
326 // append Element to Mem Table
327 psMemTableElement =
328 kmalloc(sizeof(struct sShbMemTable), GFP_KERNEL);
329 psMemTableElement->m_iBufferId = iBufferId;
330 psMemTableElement->m_pBuffer = pSharedMem;
331 psMemTableElement->m_psNextMemTableElement = NULL;
332 ShbIpcAppendListElement(psMemTableElement);
335 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer update header\n");
336 //update header
337 pShbMemHeader = (tShbMemHeader *) pSharedMem;
338 DEBUG_LVL_29_TRACE1
339 ("ShbIpcAllocBuffer 0 pShbMemHeader->m_ulShMemSize: %d\n",
340 pShbMemHeader->m_ulShMemSize);
341 // allocate a memory block from process specific mempool to save
342 // process local information to administrate/manage the shared buffer
343 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer alloc private mem\n");
344 pShbMemInst =
345 (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst));
346 if (pShbMemInst == NULL) {
347 ShbError = kShbOutOfMem;
348 goto Exit;
350 // reset complete header to default values
351 //pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID;
352 // pShbMemInst->m_pSharedMem = pSharedMem;
353 pShbMemInst->m_tThreadNewDataId = INVALID_ID;
354 pShbMemInst->m_tThreadJobReadyId = INVALID_ID;
355 pShbMemInst->m_pfnSigHndlrNewData = NULL;
356 pShbMemInst->m_ulTimeOutJobReady = 0;
357 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
358 pShbMemInst->m_pShbMemHeader = pShbMemHeader;
359 pShbMemInst->m_iThreadTermFlag = 0;
361 // initialize completion etc.
362 init_completion(&pShbMemInst->m_CompletionNewData);
364 ShbError = kShbOk;
365 if (fShMemNewCreated) {
366 // this process was the first who wanted to use the shared memory,
367 // so a new shared memory was created
368 // -> setup new header information inside the shared memory region
369 // itself
370 pShbMemHeader->m_ulShMemSize = ulShMemSize;
371 pShbMemHeader->m_ulRefCount = 1;
372 pShbMemHeader->m_iBufferId = iBufferId;
373 // initialize spinlock
374 spin_lock_init(&pShbMemHeader->m_SpinlockBuffAccess);
375 // initialize wait queues
376 init_waitqueue_head(&pShbMemHeader->m_WaitQueueNewData);
377 init_waitqueue_head(&pShbMemHeader->m_WaitQueueJobReady);
378 } else {
379 // any other process has created the shared memory and this
380 // process only has to attach to it
381 // -> check and update existing header information inside the
382 // shared memory region itself
383 if (pShbMemHeader->m_ulShMemSize != ulShMemSize) {
384 ShbError = kShbOpenMismatch;
385 goto Exit;
387 pShbMemHeader->m_ulRefCount++;
390 Exit:
391 pShbInstance = (tShbInstance *) pShbMemInst;
392 *pfShbNewCreated_p = fShMemNewCreated;
393 *ppShbInstance_p = pShbInstance;
394 return (ShbError);
398 //---------------------------------------------------------------------------
399 // Release Shared Buffer
400 //---------------------------------------------------------------------------
402 tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)
404 tShbMemInst *pShbMemInst;
405 tShbMemHeader *pShbMemHeader;
406 tShbError ShbError;
407 tShbError ShbError2;
409 DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p);
410 if (pShbInstance_p == NULL) {
411 return (kShbOk);
413 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
414 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
416 // stop threads in any case, because they are bound to that specific instance
417 ShbError2 = ShbIpcStopSignalingNewData(pShbInstance_p);
418 // d.k.: Whats up with JobReady thread?
419 // Just wake it up, but without setting the semaphore variable
420 wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
422 if (!--pShbMemHeader->m_ulRefCount) {
423 ShbError = kShbOk;
424 // delete mem table element
425 ShbIpcDeleteListElement(pShbMemHeader->m_iBufferId);
426 // delete shared mem
427 kfree(pShbMemInst->m_pShbMemHeader);
428 } else {
429 ShbError = kShbMemUsedByOtherProcs;
431 //delete privat mem
432 kfree(pShbMemInst);
433 return (ShbError);
436 #endif // !defined(SHBIPC_INLINE_ENABLED)
438 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
440 //---------------------------------------------------------------------------
441 // Enter atomic section for Shared Buffer access
442 //---------------------------------------------------------------------------
444 INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)
447 tShbMemInst *pShbMemInst;
448 tShbMemHeader *pShbMemHeader;
449 tShbError ShbError = kShbOk;
451 if (pShbInstance_p == NULL) {
452 ShbError = kShbInvalidArg;
453 goto Exit;
455 DEBUG_LVL_29_TRACE0("enter atomic\n");
456 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
457 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
459 // lock interrupts
460 spin_lock_irqsave(&pShbMemHeader->m_SpinlockBuffAccess,
461 pShbMemInst->m_ulFlagsBuffAccess);
463 Exit:
464 return ShbError;
468 //---------------------------------------------------------------------------
469 // Leave atomic section for Shared Buffer access
470 //---------------------------------------------------------------------------
472 INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)
475 tShbMemInst *pShbMemInst;
476 tShbMemHeader *pShbMemHeader;
477 tShbError ShbError = kShbOk;
479 if (pShbInstance_p == NULL) {
480 ShbError = kShbInvalidArg;
481 goto Exit;
483 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
484 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
485 // unlock interrupts
486 spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess,
487 pShbMemInst->m_ulFlagsBuffAccess);
489 Exit:
490 DEBUG_LVL_29_TRACE0("Leave Atomic \n");
491 return ShbError;
495 //---------------------------------------------------------------------------
496 // Start signaling of new data (called from reading process)
497 //---------------------------------------------------------------------------
499 INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance
500 pShbInstance_p,
501 tSigHndlrNewData
502 pfnSignalHandlerNewData_p,
503 tShbPriority
504 ShbPriority_p)
506 tShbMemInst *pShbMemInst;
507 tShbMemHeader *pShbMemHeader;
508 tShbError ShbError;
510 DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n");
511 if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) {
512 return (kShbInvalidArg);
515 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
516 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
517 ShbError = kShbOk;
519 if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID)
520 || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) {
521 ShbError = kShbAlreadySignaling;
522 goto Exit;
524 DEBUG_LVL_26_TRACE2
525 ("ShbIpcStartSignalingNewData(%p) m_pfnSigHndlrNewData = %p\n",
526 pShbInstance_p, pfnSignalHandlerNewData_p);
527 pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
528 pShbMemHeader->m_fNewData = FALSE;
529 pShbMemInst->m_iThreadTermFlag = 0;
531 switch (ShbPriority_p) {
532 case kShbPriorityLow:
533 pShbMemInst->m_lThreadNewDataNice = -2;
534 break;
536 case kShbPriorityNormal:
537 pShbMemInst->m_lThreadNewDataNice = -9;
538 break;
540 case kshbPriorityHigh:
541 pShbMemInst->m_lThreadNewDataNice = -20;
542 break;
546 //create thread for signalling new data
547 pShbMemInst->m_tThreadNewDataId =
548 kernel_thread(ShbIpcThreadSignalNewData, pShbInstance_p,
549 CLONE_KERNEL);
551 Exit:
552 return ShbError;
556 //---------------------------------------------------------------------------
557 // Stop signaling of new data (called from reading process)
558 //---------------------------------------------------------------------------
560 INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance
561 pShbInstance_p)
563 tShbMemInst *pShbMemInst;
564 tShbMemHeader *pShbMemHeader;
565 tShbError ShbError;
567 DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n");
568 if (pShbInstance_p == NULL) {
569 return (kShbInvalidArg);
571 ShbError = kShbOk;
572 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
573 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
575 DEBUG_LVL_26_TRACE2
576 ("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n",
577 pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData);
578 if (pShbMemInst->m_pfnSigHndlrNewData != NULL) { // signal handler was set before
579 int iErr;
580 //set termination flag in mem header
581 pShbMemInst->m_iThreadTermFlag = 1;
583 // check if thread is still running at all by sending the null-signal to this thread
584 /* iErr = kill_proc(pShbMemInst->m_tThreadNewDataId, 0, 1); */
585 iErr = send_sig(0, pShbMemInst->m_tThreadNewDataId, 1);
586 if (iErr == 0) {
587 // wake up thread, because it is still running
588 wake_up_interruptible(&pShbMemHeader->
589 m_WaitQueueNewData);
591 //wait for termination of thread
592 wait_for_completion(&pShbMemInst->m_CompletionNewData);
595 pShbMemInst->m_pfnSigHndlrNewData = NULL;
596 pShbMemInst->m_tThreadNewDataId = INVALID_ID;
599 return ShbError;
603 //---------------------------------------------------------------------------
604 // Signal new data (called from writing process)
605 //---------------------------------------------------------------------------
607 INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p)
609 tShbMemHeader *pShbMemHeader;
611 if (pShbInstance_p == NULL) {
612 return (kShbInvalidArg);
614 pShbMemHeader =
615 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
616 //set semaphore
617 pShbMemHeader->m_fNewData = TRUE;
618 DEBUG_LVL_29_TRACE0("ShbIpcSignalNewData set Sem -> New Data\n");
620 wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData);
621 return (kShbOk);
624 //---------------------------------------------------------------------------
625 // Start signaling for job ready (called from waiting process)
626 //---------------------------------------------------------------------------
628 INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance
629 pShbInstance_p,
630 unsigned long
631 ulTimeOut_p,
632 tSigHndlrJobReady
633 pfnSignalHandlerJobReady_p)
635 tShbMemInst *pShbMemInst;
636 tShbMemHeader *pShbMemHeader;
637 tShbError ShbError;
639 if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) {
640 return (kShbInvalidArg);
642 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
643 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
645 ShbError = kShbOk;
646 if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID)
647 || (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) {
648 ShbError = kShbAlreadySignaling;
649 goto Exit;
651 pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
652 pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
653 pShbMemHeader->m_fJobReady = FALSE;
654 //create thread for signalling new data
655 pShbMemInst->m_tThreadJobReadyId =
656 kernel_thread(ShbIpcThreadSignalJobReady, pShbInstance_p,
657 CLONE_KERNEL);
658 Exit:
659 return ShbError;
662 //---------------------------------------------------------------------------
663 // Signal job ready (called from executing process)
664 //---------------------------------------------------------------------------
666 INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p)
668 tShbMemHeader *pShbMemHeader;
670 DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n");
671 if (pShbInstance_p == NULL) {
672 return (kShbInvalidArg);
674 pShbMemHeader =
675 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
676 //set semaphore
677 pShbMemHeader->m_fJobReady = TRUE;
678 DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady set Sem -> Job Ready \n");
680 wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
681 return (kShbOk);
684 //---------------------------------------------------------------------------
685 // Get pointer to common used share memory area
686 //---------------------------------------------------------------------------
688 INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)
691 tShbMemHeader *pShbMemHeader;
692 void *pShbShMemPtr;
694 pShbMemHeader =
695 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
696 if (pShbMemHeader != NULL) {
697 pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader);
698 } else {
699 pShbShMemPtr = NULL;
702 return (pShbShMemPtr);
706 #endif
708 //=========================================================================//
709 // //
710 // P R I V A T E F U N C T I O N S //
711 // //
712 //=========================================================================//
714 #if !defined(SHBIPC_INLINE_ENABLED)
716 //---------------------------------------------------------------------------
717 // Get pointer to process local information structure
718 //---------------------------------------------------------------------------
720 /*tShbMemInst* ShbIpcGetShbMemInst (
721 tShbInstance pShbInstance_p)
724 tShbMemInst* pShbMemInst;
726 pShbMemInst = (tShbMemInst*)pShbInstance_p;
728 return (pShbMemInst);
733 //---------------------------------------------------------------------------
734 // Get pointer to shared memory header
735 //---------------------------------------------------------------------------
737 /*tShbMemHeader* ShbIpcGetShbMemHeader (
738 tShbMemInst* pShbMemInst_p)
741 tShbMemHeader* pShbMemHeader;
743 pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
745 return (pShbMemHeader);
750 //---------------------------------------------------------------------------
751 // Allocate a memory block from process specific mempool
752 //---------------------------------------------------------------------------
754 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)
756 tShbError ShbError;
757 void *pMem;
759 DEBUG_LVL_29_TRACE0("ShbIpcAllocPrivateMem \n");
760 //get private mem
761 pMem = kmalloc(ulMemSize_p, GFP_KERNEL);
762 if (pMem == NULL) {
763 //unable to create mem
764 ShbError = kShbOutOfMem;
765 goto Exit;
767 Exit:
768 return (pMem);
772 //---------------------------------------------------------------------------
773 // Thread for new data signaling
774 //---------------------------------------------------------------------------
776 int ShbIpcThreadSignalNewData(void *pvThreadParam_p)
778 tShbInstance pShbInstance;
779 tShbMemInst *pShbMemInst;
780 tShbMemHeader *pShbMemHeader;
781 int iRetVal = -1;
782 int fCallAgain;
784 daemonize("ShbND%p", pvThreadParam_p);
785 allow_signal(SIGTERM);
786 pShbInstance = (tShbMemInst *) pvThreadParam_p;
787 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
788 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
790 DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n", pvThreadParam_p);
792 set_user_nice(current, pShbMemInst->m_lThreadNewDataNice);
794 // DEBUG_LVL_29_TRACE1("ShbIpcThreadSignalNewData wait for New Data Sem %p\n",pShbMemInst->m_pSemNewData);
795 do {
796 iRetVal =
797 wait_event_interruptible(pShbMemHeader->m_WaitQueueNewData,
798 (pShbMemInst->m_iThreadTermFlag !=
800 || (pShbMemHeader->m_fNewData !=
801 FALSE));
803 if (iRetVal != 0) { // signal pending
804 break;
807 if (pShbMemHeader->m_fNewData != FALSE) {
808 pShbMemHeader->m_fNewData = FALSE;
809 do {
810 fCallAgain =
811 pShbMemInst->
812 m_pfnSigHndlrNewData(pShbInstance);
813 // call scheduler, which will execute any task with higher priority
814 schedule();
815 } while (fCallAgain != FALSE);
817 } while (pShbMemInst->m_iThreadTermFlag == 0);
818 DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalNewData terminated \n");
819 //set thread completed
820 complete_and_exit(&pShbMemInst->m_CompletionNewData, 0);
821 return 0;
824 //---------------------------------------------------------------------------
825 // Thread for new data Job Ready signaling
826 //---------------------------------------------------------------------------
828 int ShbIpcThreadSignalJobReady(void *pvThreadParam_p)
830 tShbInstance pShbInstance;
831 tShbMemInst *pShbMemInst;
832 tShbMemHeader *pShbMemHeader;
833 long lTimeOut;
834 int iRetVal = -1;
836 daemonize("ShbJR%p", pvThreadParam_p);
837 allow_signal(SIGTERM);
838 pShbInstance = (tShbMemInst *) pvThreadParam_p;
839 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
840 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
842 DEBUG_LVL_29_TRACE0
843 ("ShbIpcThreadSignalJobReady wait for job ready Sem\n");
844 if (pShbMemInst->m_ulTimeOutJobReady != 0) {
845 lTimeOut = (long)pShbMemInst->m_ulTimeOutJobReady;
846 //wait for job ready semaphore
847 iRetVal =
848 wait_event_interruptible_timeout(pShbMemHeader->
849 m_WaitQueueJobReady,
850 (pShbMemHeader->
851 m_fJobReady != FALSE),
852 lTimeOut);
853 } else {
854 //wait for job ready semaphore
855 iRetVal =
856 wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady,
857 (pShbMemHeader->m_fJobReady !=
858 FALSE));
861 if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) {
862 //call Handler
863 pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance,
864 !pShbMemHeader->m_fJobReady);
867 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
868 return 0;
871 //Build the crc table
872 static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256])
874 unsigned long ulCrc, ulPoly;
875 int iIndexI, iIndexJ;
877 ulPoly = 0xEDB88320L;
878 for (iIndexI = 0; iIndexI < 256; iIndexI++) {
879 ulCrc = iIndexI;
880 for (iIndexJ = 8; iIndexJ > 0; iIndexJ--) {
881 if (ulCrc & 1) {
882 ulCrc = (ulCrc >> 1) ^ ulPoly;
883 } else {
884 ulCrc >>= 1;
887 aulCrcTable[iIndexI] = ulCrc;
891 //Calculate the crc value
892 static unsigned long ShbIpcCrc32GetCrc(const char *pcString,
893 unsigned long aulCrcTable[256])
895 unsigned long ulCrc;
896 int iIndex;
898 ulCrc = 0xFFFFFFFF;
899 for (iIndex = 0; iIndex < strlen(pcString); iIndex++) {
900 ulCrc =
901 ((ulCrc >> 8) & 0x00FFFFFF) ^
902 aulCrcTable[(ulCrc ^ pcString[iIndex]) & 0xFF];
904 return (ulCrc ^ 0xFFFFFFFF);
908 static void ShbIpcAppendListElement(struct sShbMemTable *psNewMemTableElement)
910 struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g;
911 psNewMemTableElement->m_psNextMemTableElement = NULL;
913 if (psMemTableElementFirst_g != NULL) { /* sind Elemente vorhanden */
914 while (psMemTableElement->m_psNextMemTableElement != NULL) { /* suche das letzte Element */
915 psMemTableElement =
916 psMemTableElement->m_psNextMemTableElement;
918 psMemTableElement->m_psNextMemTableElement = psNewMemTableElement; /* Haenge das Element hinten an */
919 } else { /* wenn die liste leer ist, bin ich das erste Element */
920 psMemTableElementFirst_g = psNewMemTableElement;
924 static int ShbIpcFindListElement(int iBufferId,
925 struct sShbMemTable **ppsReturnMemTableElement)
927 struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g;
928 while (psMemTableElement != NULL) {
929 if (psMemTableElement->m_iBufferId == iBufferId) {
930 //printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",psMemTableElement->m_pBuffer,psMemTableElement->m_iBufferId);
931 *ppsReturnMemTableElement = psMemTableElement;
932 //printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",(*ppsReturnMemTableElement)->m_pBuffer,(*ppsReturnMemTableElement)->m_iBufferId);
933 return 0;
935 psMemTableElement = psMemTableElement->m_psNextMemTableElement;
937 return -1;
940 static void ShbIpcDeleteListElement(int iBufferId)
942 struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g;
943 struct sShbMemTable *psMemTableElementOld = psMemTableElementFirst_g;
944 if (psMemTableElement != NULL) {
945 while ((psMemTableElement != NULL)
946 && (psMemTableElement->m_iBufferId != iBufferId)) {
947 psMemTableElementOld = psMemTableElement;
948 psMemTableElement =
949 psMemTableElement->m_psNextMemTableElement;
951 if (psMemTableElement != NULL) {
952 if (psMemTableElement != psMemTableElementFirst_g) {
953 psMemTableElementOld->m_psNextMemTableElement =
954 psMemTableElement->m_psNextMemTableElement;
955 kfree(psMemTableElement);
956 } else {
957 kfree(psMemTableElement);
958 psMemTableElementFirst_g = NULL;
966 #endif