Merge branch 'topic/hda' into for-linus
[linux-2.6] / drivers / staging / epl / ShbIpc-LinuxKernel.c
1 /****************************************************************************
2
3   (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4       www.systec-electronic.com
5
6   Project:      Project independend shared buffer (linear + circular)
7
8   Description:  Implementation of platform specific part for the
9                 shared buffer
10                 (Implementation for Linux KernelSpace)
11
12   License:
13
14     Redistribution and use in source and binary forms, with or without
15     modification, are permitted provided that the following conditions
16     are met:
17
18     1. Redistributions of source code must retain the above copyright
19        notice, this list of conditions and the following disclaimer.
20
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.
24
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.
29
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.
42
43     Severability Clause:
44
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.
51
52   -------------------------------------------------------------------------
53
54   2006/06/28 -rs:   V 1.00 (initial version)
55
56 ****************************************************************************/
57
58 #include "global.h"
59 #include "SharedBuff.h"
60 #include "ShbIpc.h"
61 #include "ShbLinuxKernel.h"
62 #include "Debug.h"
63
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>
73
74 /***************************************************************************/
75 /*                                                                         */
76 /*                                                                         */
77 /*          G L O B A L   D E F I N I T I O N S                            */
78 /*                                                                         */
79 /*                                                                         */
80 /***************************************************************************/
81
82 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
83
84 //---------------------------------------------------------------------------
85 //  Configuration
86 //---------------------------------------------------------------------------
87
88 //---------------------------------------------------------------------------
89 //  Constant definitions
90 //---------------------------------------------------------------------------
91
92 #define MAX_LEN_BUFFER_ID       256
93
94 #define TIMEOUT_ENTER_ATOMIC    1000    // (ms) for debgging: INFINITE
95 #define TIMEOUT_TERM_THREAD     1000
96 #define INFINITE                3600
97
98 #define SBI_MAGIC_ID            0x5342492B      // magic ID ("SBI+")
99 #define SBH_MAGIC_ID            0x5342482A      // magic ID ("SBH*")
100
101 #define INVALID_ID              -1
102
103 #define TABLE_SIZE              10
104
105 //---------------------------------------------------------------------------
106 //  Local types
107 //---------------------------------------------------------------------------
108
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 {
116
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;
126
127 #ifndef NDEBUG
128         unsigned long m_ulOwnerProcID;
129 #endif
130
131 } tShbMemHeader;
132
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;
156 /*
157     struct semaphore    *m_pSemBuffAccess;
158     struct semaphore    *m_pSemNewData;
159     struct semaphore    *m_pSemStopSignalingNewData;
160     struct semaphore    *m_pSemJobReady;
161 */
162 #ifndef NDEBUG
163         unsigned long m_ulThreadIDNewData;
164         unsigned long m_ulThreadIDJobReady;
165 #endif
166 } tShbMemInst;
167
168 //---------------------------------------------------------------------------
169 //  Prototypes of internal functions
170 //---------------------------------------------------------------------------
171
172 //tShbMemInst*            ShbIpcGetShbMemInst         (tShbInstance pShbInstance_p);
173 //tShbMemHeader*          ShbIpcGetShbMemHeader       (tShbMemInst* pShbMemInst_p);
174
175 //---------------------------------------------------------------------------
176 //  Get pointer to process local information structure
177 //---------------------------------------------------------------------------
178
179 static inline tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)
180 {
181
182         tShbMemInst *pShbMemInst;
183
184         pShbMemInst = (tShbMemInst *) pShbInstance_p;
185
186         return (pShbMemInst);
187
188 }
189
190 //---------------------------------------------------------------------------
191 //  Get pointer to shared memory header
192 //---------------------------------------------------------------------------
193
194 static inline tShbMemHeader *ShbIpcGetShbMemHeader(tShbMemInst * pShbMemInst_p)
195 {
196
197         tShbMemHeader *pShbMemHeader;
198
199         pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
200
201         return (pShbMemHeader);
202
203 }
204
205 //  Get pointer to process local information structure
206 //#define ShbIpcGetShbMemInst(pShbInstance_p) ((tShbMemInst*)pShbInstance_p)
207
208 //  Get pointer to shared memory header
209 //#define ShbIpcGetShbMemHeader(pShbMemInst_p) (pShbMemInst_p->m_pShbMemHeader)
210
211 // not inlined internal functions
212 int ShbIpcThreadSignalNewData(void *pvThreadParam_p);
213 int ShbIpcThreadSignalJobReady(void *pvThreadParam_p);
214 #endif
215
216 //---------------------------------------------------------------------------
217 // modul globale vars
218 //---------------------------------------------------------------------------
219
220 #if !defined(SHBIPC_INLINE_ENABLED)
221 struct sShbMemTable *psMemTableElementFirst_g;
222
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]);
232
233 #endif
234
235 //=========================================================================//
236 //                                                                         //
237 //          P U B L I C   F U N C T I O N S                                //
238 //                                                                         //
239 //=========================================================================//
240
241 #if !defined(SHBIPC_INLINE_ENABLED)
242 // not inlined external functions
243
244 //---------------------------------------------------------------------------
245 //  Initialize IPC for Shared Buffer Module
246 //---------------------------------------------------------------------------
247
248 tShbError ShbIpcInit(void)
249 {
250         psMemTableElementFirst_g = NULL;
251         return (kShbOk);
252
253 }
254
255 //---------------------------------------------------------------------------
256 //  Deinitialize IPC for Shared Buffer Module
257 //---------------------------------------------------------------------------
258
259 tShbError ShbIpcExit(void)
260 {
261
262         return (kShbOk);
263
264 }
265
266 //---------------------------------------------------------------------------
267 //  Allocate Shared Buffer
268 //---------------------------------------------------------------------------
269
270 tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
271                             const char *pszBufferID_p,
272                             tShbInstance * ppShbInstance_p,
273                             unsigned int *pfShbNewCreated_p)
274 {
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;
287
288         DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n");
289         ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
290
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;
324                 }
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);
333         }
334
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;
349         }
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;
360
361         // initialize completion etc.
362         init_completion(&pShbMemInst->m_CompletionNewData);
363
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;
386                 }
387                 pShbMemHeader->m_ulRefCount++;
388         }
389
390       Exit:
391         pShbInstance = (tShbInstance *) pShbMemInst;
392         *pfShbNewCreated_p = fShMemNewCreated;
393         *ppShbInstance_p = pShbInstance;
394         return (ShbError);
395
396 }
397
398 //---------------------------------------------------------------------------
399 //  Release Shared Buffer
400 //---------------------------------------------------------------------------
401
402 tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)
403 {
404         tShbMemInst *pShbMemInst;
405         tShbMemHeader *pShbMemHeader;
406         tShbError ShbError;
407         tShbError ShbError2;
408
409         DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p);
410         if (pShbInstance_p == NULL) {
411                 return (kShbOk);
412         }
413         pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
414         pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
415
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);
421
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;
430         }
431         //delete privat mem
432         kfree(pShbMemInst);
433         return (ShbError);
434 }
435
436 #endif // !defined(SHBIPC_INLINE_ENABLED)
437
438 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
439
440 //---------------------------------------------------------------------------
441 //  Enter atomic section for Shared Buffer access
442 //---------------------------------------------------------------------------
443
444 INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)
445 {
446
447         tShbMemInst *pShbMemInst;
448         tShbMemHeader *pShbMemHeader;
449         tShbError ShbError = kShbOk;
450
451         if (pShbInstance_p == NULL) {
452                 ShbError = kShbInvalidArg;
453                 goto Exit;
454         }
455         DEBUG_LVL_29_TRACE0("enter atomic\n");
456         pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
457         pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
458
459         // lock interrupts
460         spin_lock_irqsave(&pShbMemHeader->m_SpinlockBuffAccess,
461                           pShbMemInst->m_ulFlagsBuffAccess);
462
463       Exit:
464         return ShbError;
465
466 }
467
468 //---------------------------------------------------------------------------
469 //  Leave atomic section for Shared Buffer access
470 //---------------------------------------------------------------------------
471
472 INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)
473 {
474
475         tShbMemInst *pShbMemInst;
476         tShbMemHeader *pShbMemHeader;
477         tShbError ShbError = kShbOk;
478
479         if (pShbInstance_p == NULL) {
480                 ShbError = kShbInvalidArg;
481                 goto Exit;
482         }
483         pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
484         pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
485         // unlock interrupts
486         spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess,
487                                pShbMemInst->m_ulFlagsBuffAccess);
488
489       Exit:
490         DEBUG_LVL_29_TRACE0("Leave Atomic \n");
491         return ShbError;
492
493 }
494
495 //---------------------------------------------------------------------------
496 //  Start signaling of new data (called from reading process)
497 //---------------------------------------------------------------------------
498
499 INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance
500                                                       pShbInstance_p,
501                                                       tSigHndlrNewData
502                                                       pfnSignalHandlerNewData_p,
503                                                       tShbPriority
504                                                       ShbPriority_p)
505 {
506         tShbMemInst *pShbMemInst;
507         tShbMemHeader *pShbMemHeader;
508         tShbError ShbError;
509
510         DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n");
511         if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) {
512                 return (kShbInvalidArg);
513         }
514
515         pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
516         pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
517         ShbError = kShbOk;
518
519         if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID)
520             || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) {
521                 ShbError = kShbAlreadySignaling;
522                 goto Exit;
523         }
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;
530
531         switch (ShbPriority_p) {
532         case kShbPriorityLow:
533                 pShbMemInst->m_lThreadNewDataNice = -2;
534                 break;
535
536         case kShbPriorityNormal:
537                 pShbMemInst->m_lThreadNewDataNice = -9;
538                 break;
539
540         case kshbPriorityHigh:
541                 pShbMemInst->m_lThreadNewDataNice = -20;
542                 break;
543
544         }
545
546         //create thread for signalling new data
547         pShbMemInst->m_tThreadNewDataId =
548             kernel_thread(ShbIpcThreadSignalNewData, pShbInstance_p,
549                           CLONE_KERNEL);
550
551       Exit:
552         return ShbError;
553
554 }
555
556 //---------------------------------------------------------------------------
557 //  Stop signaling of new data (called from reading process)
558 //---------------------------------------------------------------------------
559
560 INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance
561                                                      pShbInstance_p)
562 {
563         tShbMemInst *pShbMemInst;
564         tShbMemHeader *pShbMemHeader;
565         tShbError ShbError;
566
567         DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n");
568         if (pShbInstance_p == NULL) {
569                 return (kShbInvalidArg);
570         }
571         ShbError = kShbOk;
572         pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
573         pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
574
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;
582
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);
590
591                         //wait for termination of thread
592                         wait_for_completion(&pShbMemInst->m_CompletionNewData);
593                 }
594
595                 pShbMemInst->m_pfnSigHndlrNewData = NULL;
596                 pShbMemInst->m_tThreadNewDataId = INVALID_ID;
597         }
598
599         return ShbError;
600
601 }
602
603 //---------------------------------------------------------------------------
604 //  Signal new data (called from writing process)
605 //---------------------------------------------------------------------------
606
607 INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p)
608 {
609         tShbMemHeader *pShbMemHeader;
610
611         if (pShbInstance_p == NULL) {
612                 return (kShbInvalidArg);
613         }
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");
619
620         wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData);
621         return (kShbOk);
622 }
623
624 //---------------------------------------------------------------------------
625 //  Start signaling for job ready (called from waiting process)
626 //---------------------------------------------------------------------------
627
628 INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance
629                                                        pShbInstance_p,
630                                                        unsigned long
631                                                        ulTimeOut_p,
632                                                        tSigHndlrJobReady
633                                                        pfnSignalHandlerJobReady_p)
634 {
635         tShbMemInst *pShbMemInst;
636         tShbMemHeader *pShbMemHeader;
637         tShbError ShbError;
638
639         if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) {
640                 return (kShbInvalidArg);
641         }
642         pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
643         pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
644
645         ShbError = kShbOk;
646         if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID)
647             || (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) {
648                 ShbError = kShbAlreadySignaling;
649                 goto Exit;
650         }
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;
660 }
661
662 //---------------------------------------------------------------------------
663 //  Signal job ready (called from executing process)
664 //---------------------------------------------------------------------------
665
666 INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p)
667 {
668         tShbMemHeader *pShbMemHeader;
669
670         DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n");
671         if (pShbInstance_p == NULL) {
672                 return (kShbInvalidArg);
673         }
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");
679
680         wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
681         return (kShbOk);
682 }
683
684 //---------------------------------------------------------------------------
685 //  Get pointer to common used share memory area
686 //---------------------------------------------------------------------------
687
688 INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)
689 {
690
691         tShbMemHeader *pShbMemHeader;
692         void *pShbShMemPtr;
693
694         pShbMemHeader =
695             ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
696         if (pShbMemHeader != NULL) {
697                 pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader);
698         } else {
699                 pShbShMemPtr = NULL;
700         }
701
702         return (pShbShMemPtr);
703
704 }
705
706 #endif
707
708 //=========================================================================//
709 //                                                                         //
710 //          P R I V A T E   F U N C T I O N S                              //
711 //                                                                         //
712 //=========================================================================//
713
714 #if !defined(SHBIPC_INLINE_ENABLED)
715
716 //---------------------------------------------------------------------------
717 //  Get pointer to process local information structure
718 //---------------------------------------------------------------------------
719
720 /*tShbMemInst*  ShbIpcGetShbMemInst (
721     tShbInstance pShbInstance_p)
722 {
723
724 tShbMemInst*  pShbMemInst;
725
726     pShbMemInst = (tShbMemInst*)pShbInstance_p;
727
728     return (pShbMemInst);
729
730 }
731 */
732
733 //---------------------------------------------------------------------------
734 //  Get pointer to shared memory header
735 //---------------------------------------------------------------------------
736
737 /*tShbMemHeader*  ShbIpcGetShbMemHeader (
738     tShbMemInst* pShbMemInst_p)
739 {
740
741 tShbMemHeader*  pShbMemHeader;
742
743     pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
744
745     return (pShbMemHeader);
746
747 }
748 */
749
750 //---------------------------------------------------------------------------
751 //  Allocate a memory block from process specific mempool
752 //---------------------------------------------------------------------------
753
754 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)
755 {
756         tShbError ShbError;
757         void *pMem;
758
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;
766         }
767       Exit:
768         return (pMem);
769
770 }
771
772 //---------------------------------------------------------------------------
773 //  Thread for new data signaling
774 //---------------------------------------------------------------------------
775
776 int ShbIpcThreadSignalNewData(void *pvThreadParam_p)
777 {
778         tShbInstance pShbInstance;
779         tShbMemInst *pShbMemInst;
780         tShbMemHeader *pShbMemHeader;
781         int iRetVal = -1;
782         int fCallAgain;
783
784         daemonize("ShbND%p", pvThreadParam_p);
785         allow_signal(SIGTERM);
786         pShbInstance = (tShbMemInst *) pvThreadParam_p;
787         pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
788         pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
789
790         DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n", pvThreadParam_p);
791
792         set_user_nice(current, pShbMemInst->m_lThreadNewDataNice);
793
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 !=
799                                               0)
800                                              || (pShbMemHeader->m_fNewData !=
801                                                  FALSE));
802
803                 if (iRetVal != 0) {     // signal pending
804                         break;
805                 }
806
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);
816                 }
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;
822 }
823
824 //---------------------------------------------------------------------------
825 //  Thread for new data Job Ready signaling
826 //---------------------------------------------------------------------------
827
828 int ShbIpcThreadSignalJobReady(void *pvThreadParam_p)
829 {
830         tShbInstance pShbInstance;
831         tShbMemInst *pShbMemInst;
832         tShbMemHeader *pShbMemHeader;
833         long lTimeOut;
834         int iRetVal = -1;
835
836         daemonize("ShbJR%p", pvThreadParam_p);
837         allow_signal(SIGTERM);
838         pShbInstance = (tShbMemInst *) pvThreadParam_p;
839         pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
840         pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
841
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));
859         }
860
861         if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) {
862                 //call Handler
863                 pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance,
864                                                    !pShbMemHeader->m_fJobReady);
865         }
866
867         pShbMemInst->m_pfnSigHndlrJobReady = NULL;
868         return 0;
869 }
870
871 //Build the crc table
872 static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256])
873 {
874         unsigned long ulCrc, ulPoly;
875         int iIndexI, iIndexJ;
876
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;
885                         }
886                 }
887                 aulCrcTable[iIndexI] = ulCrc;
888         }
889 }
890
891 //Calculate the crc value
892 static unsigned long ShbIpcCrc32GetCrc(const char *pcString,
893                                        unsigned long aulCrcTable[256])
894 {
895         unsigned long ulCrc;
896         int iIndex;
897
898         ulCrc = 0xFFFFFFFF;
899         for (iIndex = 0; iIndex < strlen(pcString); iIndex++) {
900                 ulCrc =
901                     ((ulCrc >> 8) & 0x00FFFFFF) ^
902                     aulCrcTable[(ulCrc ^ pcString[iIndex]) & 0xFF];
903         }
904         return (ulCrc ^ 0xFFFFFFFF);
905
906 }
907
908 static void ShbIpcAppendListElement(struct sShbMemTable *psNewMemTableElement)
909 {
910         struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g;
911         psNewMemTableElement->m_psNextMemTableElement = NULL;
912
913         if (psMemTableElementFirst_g != NULL) { /* sind Elemente vorhanden */
914                 while (psMemTableElement->m_psNextMemTableElement != NULL) {    /* suche das letzte Element */
915                         psMemTableElement =
916                             psMemTableElement->m_psNextMemTableElement;
917                 }
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;
921         }
922 }
923
924 static int ShbIpcFindListElement(int iBufferId,
925                                  struct sShbMemTable **ppsReturnMemTableElement)
926 {
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;
934                 }
935                 psMemTableElement = psMemTableElement->m_psNextMemTableElement;
936         }
937         return -1;
938 }
939
940 static void ShbIpcDeleteListElement(int iBufferId)
941 {
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;
950                 }
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;
959                         }
960
961                 }
962         }
963
964 }
965
966 #endif