Staging: add epl stack
[platform/kernel/linux-starfive.git] / 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
59 #include "global.h"
60 #include "SharedBuff.h"
61 #include "ShbIpc.h"
62 #include "ShbLinuxKernel.h"
63 #include "Debug.h"
64
65 #include <linux/string.h>
66 #include <linux/module.h>
67 #include <asm/processor.h>
68 //#include <linux/vmalloc.h>
69 #include <linux/sched.h>
70 #include <linux/param.h>
71 #include <linux/spinlock.h>
72 #include <linux/wait.h>
73 #include <linux/completion.h>
74
75
76
77 /***************************************************************************/
78 /*                                                                         */
79 /*                                                                         */
80 /*          G L O B A L   D E F I N I T I O N S                            */
81 /*                                                                         */
82 /*                                                                         */
83 /***************************************************************************/
84
85 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
86
87 //---------------------------------------------------------------------------
88 //  Configuration
89 //---------------------------------------------------------------------------
90
91
92
93 //---------------------------------------------------------------------------
94 //  Constant definitions
95 //---------------------------------------------------------------------------
96
97 #define MAX_LEN_BUFFER_ID       256
98
99 #define TIMEOUT_ENTER_ATOMIC    1000        // (ms) for debgging: INFINITE
100 #define TIMEOUT_TERM_THREAD     1000
101 #define INFINITE                3600
102
103 #define SBI_MAGIC_ID            0x5342492B  // magic ID ("SBI+")
104 #define SBH_MAGIC_ID            0x5342482A  // magic ID ("SBH*")
105
106 #define INVALID_ID              -1
107
108 #define TABLE_SIZE              10
109
110
111 //---------------------------------------------------------------------------
112 //  Local types
113 //---------------------------------------------------------------------------
114
115 // This structure is the common header for the shared memory region used
116 // by all processes attached this shared memory. It includes common
117 // information to administrate/manage the shared buffer from a couple of
118 // separated processes (e.g. the refernce counter). This structure is
119 // located at the start of the shared memory region itself and exists
120 // consequently only one times per shared memory instance.
121 typedef struct
122 {
123
124     unsigned long       m_ulShMemSize;
125     unsigned long       m_ulRefCount;
126     int                 m_iBufferId;
127 //    int                 m_iUserSpaceMem;           //0 for userspace mem   !=0 kernelspace mem
128     spinlock_t          m_SpinlockBuffAccess;
129     BOOL                m_fNewData;
130     BOOL                m_fJobReady;
131     wait_queue_head_t   m_WaitQueueNewData;
132     wait_queue_head_t   m_WaitQueueJobReady;
133
134     #ifndef NDEBUG
135         unsigned long   m_ulOwnerProcID;
136     #endif
137
138 } tShbMemHeader;
139
140
141
142 // This structure is the "external entry point" from a separate process
143 // to get access to a shared buffer. This structure includes all platform
144 // resp. target specific information to administrate/manage the shared
145 // buffer from a separate process. Every process attached to the shared
146 // buffer has its own runtime instance of this structure with its individual
147 // runtime data (e.g. the scope of an event handle is limitted to the
148 // owner process only). The structure member <m_pShbMemHeader> points
149 // to the (process specific) start address of the shared memory region
150 // itself.
151 typedef struct
152 {
153     unsigned long       m_SbiMagicID;           // magic ID ("SBI+")
154 //    void*               m_pSharedMem;
155     int                 m_tThreadNewDataId;
156     long                m_lThreadNewDataNice;   // nice value of the new data thread
157     int                 m_tThreadJobReadyId;
158     unsigned long       m_ulFlagsBuffAccess;    // d.k. moved from tShbMemHeader, because each
159                                                 // process needs to store the interrupt flags separately
160     tSigHndlrNewData    m_pfnSigHndlrNewData;
161     unsigned long       m_ulTimeOutJobReady;
162     tSigHndlrJobReady   m_pfnSigHndlrJobReady;
163     tShbMemHeader*      m_pShbMemHeader;
164     int                 m_iThreadTermFlag;
165     struct completion   m_CompletionNewData;
166 /*
167     struct semaphore    *m_pSemBuffAccess;
168     struct semaphore    *m_pSemNewData;
169     struct semaphore    *m_pSemStopSignalingNewData;
170     struct semaphore    *m_pSemJobReady;
171 */
172     #ifndef NDEBUG
173         unsigned long   m_ulThreadIDNewData;
174         unsigned long   m_ulThreadIDJobReady;
175     #endif
176 } tShbMemInst;
177
178
179 //---------------------------------------------------------------------------
180 //  Prototypes of internal functions
181 //---------------------------------------------------------------------------
182
183 //tShbMemInst*            ShbIpcGetShbMemInst         (tShbInstance pShbInstance_p);
184 //tShbMemHeader*          ShbIpcGetShbMemHeader       (tShbMemInst* pShbMemInst_p);
185
186 //---------------------------------------------------------------------------
187 //  Get pointer to process local information structure
188 //---------------------------------------------------------------------------
189
190 static inline tShbMemInst*  ShbIpcGetShbMemInst (
191     tShbInstance pShbInstance_p)
192 {
193
194 tShbMemInst*  pShbMemInst;
195
196
197     pShbMemInst = (tShbMemInst*)pShbInstance_p;
198
199
200     return (pShbMemInst);
201
202 }
203
204
205
206 //---------------------------------------------------------------------------
207 //  Get pointer to shared memory header
208 //---------------------------------------------------------------------------
209
210 static inline tShbMemHeader*  ShbIpcGetShbMemHeader (
211     tShbMemInst* pShbMemInst_p)
212 {
213
214 tShbMemHeader*  pShbMemHeader;
215
216
217     pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
218
219     return (pShbMemHeader);
220
221 }
222
223 //  Get pointer to process local information structure
224 //#define ShbIpcGetShbMemInst(pShbInstance_p) ((tShbMemInst*)pShbInstance_p)
225
226 //  Get pointer to shared memory header
227 //#define ShbIpcGetShbMemHeader(pShbMemInst_p) (pShbMemInst_p->m_pShbMemHeader)
228
229 // not inlined internal functions
230 int                     ShbIpcThreadSignalNewData   (void* pvThreadParam_p);
231 int                     ShbIpcThreadSignalJobReady  (void* pvThreadParam_p);
232 #endif
233
234 //---------------------------------------------------------------------------
235 // modul globale vars
236 //---------------------------------------------------------------------------
237
238 #if !defined(SHBIPC_INLINE_ENABLED)
239 struct sShbMemTable *psMemTableElementFirst_g;
240
241 static void*            ShbIpcAllocPrivateMem       (unsigned long ulMemSize_p);
242 static int              ShbIpcFindListElement       (int iBufferId, struct sShbMemTable **ppsReturnMemTableElement);
243 static void             ShbIpcAppendListElement     (struct sShbMemTable *sNewMemTableElement);
244 static void             ShbIpcDeleteListElement     (int iBufferId);
245 static void             ShbIpcCrc32GenTable         (unsigned long aulCrcTable[256]);
246 static unsigned long    ShbIpcCrc32GetCrc           (const char *pcString, unsigned long aulCrcTable[256]);
247
248 #endif
249
250
251 //=========================================================================//
252 //                                                                         //
253 //          P U B L I C   F U N C T I O N S                                //
254 //                                                                         //
255 //=========================================================================//
256
257 #if !defined(SHBIPC_INLINE_ENABLED)
258 // not inlined external functions
259
260 //---------------------------------------------------------------------------
261 //  Initialize IPC for Shared Buffer Module
262 //---------------------------------------------------------------------------
263
264 tShbError  ShbIpcInit (void)
265 {
266     psMemTableElementFirst_g = NULL;
267     return (kShbOk);
268
269 }
270
271
272
273 //---------------------------------------------------------------------------
274 //  Deinitialize IPC for Shared Buffer Module
275 //---------------------------------------------------------------------------
276
277 tShbError  ShbIpcExit (void)
278 {
279
280     return (kShbOk);
281
282 }
283
284
285
286 //---------------------------------------------------------------------------
287 //  Allocate Shared Buffer
288 //---------------------------------------------------------------------------
289
290 tShbError  ShbIpcAllocBuffer (
291     unsigned long ulBufferSize_p,
292     const char* pszBufferID_p,
293     tShbInstance* ppShbInstance_p,
294     unsigned int* pfShbNewCreated_p)
295 {
296 tShbError               ShbError;
297 int                     iBufferId=0;
298 unsigned long           ulCrc32=0;
299 unsigned int            uiFirstProcess=0;
300 unsigned long           ulShMemSize;
301 tShbMemHeader*          pShbMemHeader;
302 tShbMemInst*            pShbMemInst=NULL;
303 tShbInstance            pShbInstance;
304 unsigned int            fShMemNewCreated=FALSE;
305 void                    *pSharedMem=NULL;
306 unsigned long           aulCrcTable[256];
307 struct sShbMemTable     *psMemTableElement;
308
309
310     DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n");
311     ulShMemSize      = ulBufferSize_p + sizeof(tShbMemHeader);
312
313     //create Buffer ID
314     ShbIpcCrc32GenTable(aulCrcTable);
315     ulCrc32=ShbIpcCrc32GetCrc(pszBufferID_p,aulCrcTable);
316     iBufferId=ulCrc32;
317     DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferSize:%d sizeof(tShb..):%d\n",ulBufferSize_p,sizeof(tShbMemHeader));
318     DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferId:%d MemSize:%d\n",iBufferId,ulShMemSize);
319     //---------------------------------------------------------------
320     // (1) open an existing or create a new shared memory
321     //---------------------------------------------------------------
322     //test if buffer already exists
323     if (ShbIpcFindListElement(iBufferId, &psMemTableElement) == 0)
324     {
325         //Buffer already exists
326         fShMemNewCreated=FALSE;
327         pSharedMem = psMemTableElement->m_pBuffer;
328         DEBUG_LVL_29_TRACE1("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n",pSharedMem);
329         uiFirstProcess=1;
330     }
331     else
332     {
333         //create new Buffer
334         fShMemNewCreated = TRUE;
335         uiFirstProcess=0;
336         pSharedMem = kmalloc(ulShMemSize,GFP_KERNEL);
337         DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer Create New Buffer at:%p Id:%d\n",pSharedMem,iBufferId);
338         if (pSharedMem == NULL)
339         {
340             //unable to create mem
341             ShbError = kShbOutOfMem;
342             goto Exit;
343         }
344         DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer create semas\n");
345         // append Element to Mem Table
346         psMemTableElement = kmalloc(sizeof(struct sShbMemTable),GFP_KERNEL);
347         psMemTableElement->m_iBufferId = iBufferId;
348         psMemTableElement->m_pBuffer = pSharedMem;
349         psMemTableElement->m_psNextMemTableElement = NULL;
350         ShbIpcAppendListElement (psMemTableElement);
351     }
352
353     DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer update header\n");
354     //update header
355     pShbMemHeader = (tShbMemHeader*)pSharedMem;
356     DEBUG_LVL_29_TRACE1("ShbIpcAllocBuffer 0 pShbMemHeader->m_ulShMemSize: %d\n",pShbMemHeader->m_ulShMemSize);
357     // allocate a memory block from process specific mempool to save
358     // process local information to administrate/manage the shared buffer
359     DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer alloc private mem\n");
360     pShbMemInst = (tShbMemInst*) ShbIpcAllocPrivateMem (sizeof(tShbMemInst));
361     if (pShbMemInst == NULL)
362     {
363         ShbError = kShbOutOfMem;
364         goto Exit;
365     }
366
367     // reset complete header to default values
368     //pShbMemInst->m_SbiMagicID                             = SBI_MAGIC_ID;
369 //    pShbMemInst->m_pSharedMem                               = pSharedMem;
370     pShbMemInst->m_tThreadNewDataId                         = INVALID_ID;
371     pShbMemInst->m_tThreadJobReadyId                        = INVALID_ID;
372     pShbMemInst->m_pfnSigHndlrNewData                       = NULL;
373     pShbMemInst->m_ulTimeOutJobReady                        = 0;
374     pShbMemInst->m_pfnSigHndlrJobReady                      = NULL;
375     pShbMemInst->m_pShbMemHeader                            = pShbMemHeader;
376     pShbMemInst->m_iThreadTermFlag                          = 0;
377
378     // initialize completion etc.
379     init_completion(&pShbMemInst->m_CompletionNewData);
380
381     ShbError         = kShbOk;
382     if ( fShMemNewCreated )
383     {
384         // this process was the first who wanted to use the shared memory,
385         // so a new shared memory was created
386         // -> setup new header information inside the shared memory region
387         //    itself
388         pShbMemHeader->m_ulShMemSize = ulShMemSize;
389         pShbMemHeader->m_ulRefCount  = 1;
390         pShbMemHeader->m_iBufferId=iBufferId;
391         // initialize spinlock
392         spin_lock_init(&pShbMemHeader->m_SpinlockBuffAccess);
393         // initialize wait queues
394         init_waitqueue_head(&pShbMemHeader->m_WaitQueueNewData);
395         init_waitqueue_head(&pShbMemHeader->m_WaitQueueJobReady);
396     }
397     else
398     {
399         // any other process has created the shared memory and this
400         // process only has to attach to it
401         // -> check and update existing header information inside the
402         //    shared memory region itself
403         if (pShbMemHeader->m_ulShMemSize != ulShMemSize)
404         {
405             ShbError = kShbOpenMismatch;
406             goto Exit;
407         }
408         pShbMemHeader->m_ulRefCount++;
409     }
410
411     Exit:
412     pShbInstance = (tShbInstance*)pShbMemInst;
413     *pfShbNewCreated_p = fShMemNewCreated;
414     *ppShbInstance_p   = pShbInstance;
415     return (ShbError);
416
417 }
418
419
420
421 //---------------------------------------------------------------------------
422 //  Release Shared Buffer
423 //---------------------------------------------------------------------------
424
425 tShbError  ShbIpcReleaseBuffer (tShbInstance pShbInstance_p)
426 {
427 tShbMemInst*    pShbMemInst;
428 tShbMemHeader*  pShbMemHeader;
429 tShbError       ShbError;
430 tShbError       ShbError2;
431
432     DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p);
433     if (pShbInstance_p == NULL)
434     {
435         return (kShbOk);
436     }
437     pShbMemInst   = ShbIpcGetShbMemInst   (pShbInstance_p);
438     pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
439
440     // stop threads in any case, because they are bound to that specific instance
441     ShbError2 = ShbIpcStopSignalingNewData (pShbInstance_p);
442     // d.k.: Whats up with JobReady thread?
443     //       Just wake it up, but without setting the semaphore variable
444     wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
445
446     if ( !--pShbMemHeader->m_ulRefCount )
447     {
448         ShbError = kShbOk;
449         // delete mem table element
450         ShbIpcDeleteListElement(pShbMemHeader->m_iBufferId);
451         // delete shared mem
452         kfree(pShbMemInst->m_pShbMemHeader);
453     }
454     else
455     {
456         ShbError = kShbMemUsedByOtherProcs;
457     }
458     //delete privat mem
459     kfree(pShbMemInst);
460     return (ShbError);
461 }
462
463
464 #endif  // !defined(SHBIPC_INLINE_ENABLED)
465
466 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
467
468
469 //---------------------------------------------------------------------------
470 //  Enter atomic section for Shared Buffer access
471 //---------------------------------------------------------------------------
472
473 INLINE_FUNCTION tShbError  ShbIpcEnterAtomicSection (
474     tShbInstance pShbInstance_p)
475 {
476
477 tShbMemInst*    pShbMemInst;
478 tShbMemHeader*  pShbMemHeader;
479 tShbError       ShbError = kShbOk;
480
481     if (pShbInstance_p == NULL)
482     {
483         ShbError = kShbInvalidArg;
484         goto Exit;
485     }
486     DEBUG_LVL_29_TRACE0("enter atomic\n");
487     pShbMemInst   = ShbIpcGetShbMemInst   (pShbInstance_p);
488     pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
489
490     // lock interrupts
491     spin_lock_irqsave(&pShbMemHeader->m_SpinlockBuffAccess, pShbMemInst->m_ulFlagsBuffAccess);
492
493 Exit:
494     return ShbError;
495
496 }
497
498
499
500 //---------------------------------------------------------------------------
501 //  Leave atomic section for Shared Buffer access
502 //---------------------------------------------------------------------------
503
504 INLINE_FUNCTION tShbError  ShbIpcLeaveAtomicSection (
505     tShbInstance pShbInstance_p)
506 {
507
508 tShbMemInst*    pShbMemInst;
509 tShbMemHeader*  pShbMemHeader;
510 tShbError       ShbError = kShbOk;
511
512     if (pShbInstance_p == NULL)
513     {
514         ShbError = kShbInvalidArg;
515         goto Exit;
516     }
517     pShbMemInst   = ShbIpcGetShbMemInst   (pShbInstance_p);
518     pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
519     // unlock interrupts
520     spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess, pShbMemInst->m_ulFlagsBuffAccess);
521
522 Exit:
523     DEBUG_LVL_29_TRACE0("Leave Atomic \n");
524     return ShbError;
525
526 }
527
528
529
530 //---------------------------------------------------------------------------
531 //  Start signaling of new data (called from reading process)
532 //---------------------------------------------------------------------------
533
534 INLINE_FUNCTION tShbError  ShbIpcStartSignalingNewData (
535     tShbInstance pShbInstance_p,
536     tSigHndlrNewData pfnSignalHandlerNewData_p,
537     tShbPriority ShbPriority_p)
538 {
539 tShbMemInst*    pShbMemInst;
540 tShbMemHeader*  pShbMemHeader;
541 tShbError       ShbError;
542
543     DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n");
544     if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL))
545     {
546         return (kShbInvalidArg);
547     }
548
549     pShbMemInst   = ShbIpcGetShbMemInst   (pShbInstance_p);
550     pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
551     ShbError = kShbOk;
552
553     if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID)
554         || (pShbMemInst->m_pfnSigHndlrNewData != NULL))
555     {
556         ShbError = kShbAlreadySignaling;
557         goto Exit;
558     }
559     DEBUG_LVL_26_TRACE2("ShbIpcStartSignalingNewData(%p) m_pfnSigHndlrNewData = %p\n", pShbInstance_p, pfnSignalHandlerNewData_p);
560     pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
561     pShbMemHeader->m_fNewData = FALSE;
562     pShbMemInst->m_iThreadTermFlag = 0;
563
564     switch (ShbPriority_p)
565     {
566         case kShbPriorityLow:
567             pShbMemInst->m_lThreadNewDataNice = -2;
568             break;
569
570         case kShbPriorityNormal:
571             pShbMemInst->m_lThreadNewDataNice = -9;
572             break;
573
574         case kshbPriorityHigh:
575             pShbMemInst->m_lThreadNewDataNice = -20;
576             break;
577
578     }
579
580     //create thread for signalling new data
581     pShbMemInst->m_tThreadNewDataId = kernel_thread(ShbIpcThreadSignalNewData,pShbInstance_p,CLONE_KERNEL);
582
583 Exit:
584     return ShbError;
585
586 }
587
588
589
590 //---------------------------------------------------------------------------
591 //  Stop signaling of new data (called from reading process)
592 //---------------------------------------------------------------------------
593
594 INLINE_FUNCTION tShbError  ShbIpcStopSignalingNewData (
595     tShbInstance pShbInstance_p)
596 {
597 tShbMemInst*    pShbMemInst;
598 tShbMemHeader*  pShbMemHeader;
599 tShbError       ShbError;
600
601     DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n");
602     if (pShbInstance_p == NULL)
603     {
604         return (kShbInvalidArg);
605     }
606     ShbError = kShbOk;
607     pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
608     pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
609
610     DEBUG_LVL_26_TRACE2("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n", pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData);
611     if (pShbMemInst->m_pfnSigHndlrNewData != NULL)
612     {   // signal handler was set before
613         int iErr;
614         //set termination flag in mem header
615         pShbMemInst->m_iThreadTermFlag = 1;
616
617         // check if thread is still running at all by sending the null-signal to this thread
618         /* iErr = kill_proc(pShbMemInst->m_tThreadNewDataId, 0, 1); */
619         iErr = send_sig(0, pShbMemInst->m_tThreadNewDataId, 1);
620         if (iErr == 0)
621         {
622             // wake up thread, because it is still running
623             wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData);
624
625             //wait for termination of thread
626             wait_for_completion(&pShbMemInst->m_CompletionNewData);
627         }
628
629         pShbMemInst->m_pfnSigHndlrNewData = NULL;
630         pShbMemInst->m_tThreadNewDataId = INVALID_ID;
631     }
632
633     return ShbError;
634
635 }
636
637
638
639 //---------------------------------------------------------------------------
640 //  Signal new data (called from writing process)
641 //---------------------------------------------------------------------------
642
643 INLINE_FUNCTION tShbError  ShbIpcSignalNewData (
644     tShbInstance pShbInstance_p)
645 {
646 tShbMemHeader*  pShbMemHeader;
647
648     if (pShbInstance_p == NULL)
649     {
650         return (kShbInvalidArg);
651     }
652     pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p));
653     //set semaphore
654     pShbMemHeader->m_fNewData = TRUE;
655     DEBUG_LVL_29_TRACE0("ShbIpcSignalNewData set Sem -> New Data\n");
656
657     wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData);
658     return (kShbOk);
659 }
660
661
662
663 //---------------------------------------------------------------------------
664 //  Start signaling for job ready (called from waiting process)
665 //---------------------------------------------------------------------------
666
667 INLINE_FUNCTION tShbError  ShbIpcStartSignalingJobReady (
668     tShbInstance pShbInstance_p,
669     unsigned long ulTimeOut_p,
670     tSigHndlrJobReady pfnSignalHandlerJobReady_p)
671 {
672 tShbMemInst*    pShbMemInst;
673 tShbMemHeader*  pShbMemHeader;
674 tShbError       ShbError;
675
676     if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL))
677     {
678         return (kShbInvalidArg);
679     }
680     pShbMemInst   = ShbIpcGetShbMemInst   (pShbInstance_p);
681     pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
682
683     ShbError = kShbOk;
684     if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID)||(pShbMemInst->m_pfnSigHndlrJobReady!= NULL))
685     {
686         ShbError = kShbAlreadySignaling;
687         goto Exit;
688     }
689     pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
690     pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
691     pShbMemHeader->m_fJobReady = FALSE;
692     //create thread for signalling new data
693     pShbMemInst->m_tThreadJobReadyId=kernel_thread(ShbIpcThreadSignalJobReady,pShbInstance_p,CLONE_KERNEL);
694     Exit:
695     return ShbError;
696 }
697
698
699
700 //---------------------------------------------------------------------------
701 //  Signal job ready (called from executing process)
702 //---------------------------------------------------------------------------
703
704 INLINE_FUNCTION tShbError  ShbIpcSignalJobReady (
705     tShbInstance pShbInstance_p)
706 {
707 tShbMemHeader*  pShbMemHeader;
708
709
710     DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n");
711     if (pShbInstance_p == NULL)
712     {
713         return (kShbInvalidArg);
714     }
715     pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p));
716     //set semaphore
717     pShbMemHeader->m_fJobReady = TRUE;
718     DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady set Sem -> Job Ready \n");
719
720     wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
721     return (kShbOk);
722 }
723
724
725
726 //---------------------------------------------------------------------------
727 //  Get pointer to common used share memory area
728 //---------------------------------------------------------------------------
729
730 INLINE_FUNCTION void*  ShbIpcGetShMemPtr (tShbInstance pShbInstance_p)
731 {
732
733 tShbMemHeader*  pShbMemHeader;
734 void*  pShbShMemPtr;
735
736
737     pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p));
738     if (pShbMemHeader != NULL)
739     {
740         pShbShMemPtr = (BYTE*)pShbMemHeader + sizeof(tShbMemHeader);
741     }
742     else
743     {
744         pShbShMemPtr = NULL;
745     }
746
747     return (pShbShMemPtr);
748
749 }
750
751 #endif
752
753
754
755 //=========================================================================//
756 //                                                                         //
757 //          P R I V A T E   F U N C T I O N S                              //
758 //                                                                         //
759 //=========================================================================//
760
761 #if !defined(SHBIPC_INLINE_ENABLED)
762
763 //---------------------------------------------------------------------------
764 //  Get pointer to process local information structure
765 //---------------------------------------------------------------------------
766
767 /*tShbMemInst*  ShbIpcGetShbMemInst (
768     tShbInstance pShbInstance_p)
769 {
770
771 tShbMemInst*  pShbMemInst;
772
773
774     pShbMemInst = (tShbMemInst*)pShbInstance_p;
775
776
777     return (pShbMemInst);
778
779 }
780 */
781
782
783 //---------------------------------------------------------------------------
784 //  Get pointer to shared memory header
785 //---------------------------------------------------------------------------
786
787 /*tShbMemHeader*  ShbIpcGetShbMemHeader (
788     tShbMemInst* pShbMemInst_p)
789 {
790
791 tShbMemHeader*  pShbMemHeader;
792
793
794     pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
795
796     return (pShbMemHeader);
797
798 }
799 */
800
801
802 //---------------------------------------------------------------------------
803 //  Allocate a memory block from process specific mempool
804 //---------------------------------------------------------------------------
805
806 static void*  ShbIpcAllocPrivateMem (unsigned long ulMemSize_p)
807 {
808 tShbError       ShbError;
809 void*           pMem;
810
811     DEBUG_LVL_29_TRACE0("ShbIpcAllocPrivateMem \n");
812     //get private mem
813     pMem = kmalloc(ulMemSize_p, GFP_KERNEL);
814     if (pMem == NULL)
815     {
816         //unable to create mem
817         ShbError = kShbOutOfMem;
818         goto Exit;
819     }
820 Exit:
821     return (pMem);
822
823 }
824
825
826 //---------------------------------------------------------------------------
827 //  Thread for new data signaling
828 //---------------------------------------------------------------------------
829
830 int ShbIpcThreadSignalNewData (void *pvThreadParam_p)
831 {
832 tShbInstance    pShbInstance;
833 tShbMemInst*    pShbMemInst;
834 tShbMemHeader*  pShbMemHeader;
835 int             iRetVal=-1;
836 int             fCallAgain;
837
838     daemonize("ShbND%p", pvThreadParam_p);
839     allow_signal(SIGTERM);
840     pShbInstance = (tShbMemInst*)pvThreadParam_p;
841     pShbMemInst  = ShbIpcGetShbMemInst (pShbInstance);
842     pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
843
844     DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n",pvThreadParam_p);
845
846     set_user_nice(current, pShbMemInst->m_lThreadNewDataNice);
847
848 //            DEBUG_LVL_29_TRACE1("ShbIpcThreadSignalNewData wait for New Data Sem %p\n",pShbMemInst->m_pSemNewData);
849     do
850     {
851         iRetVal = wait_event_interruptible(pShbMemHeader->m_WaitQueueNewData,
852             (pShbMemInst->m_iThreadTermFlag != 0) || (pShbMemHeader->m_fNewData != FALSE));
853
854         if (iRetVal != 0)
855         {   // signal pending
856             break;
857         }
858
859         if (pShbMemHeader->m_fNewData != FALSE)
860         {
861             pShbMemHeader->m_fNewData = FALSE;
862             do
863             {
864                 fCallAgain = pShbMemInst->m_pfnSigHndlrNewData(pShbInstance);
865                 // call scheduler, which will execute any task with higher priority
866                 schedule();
867             } while (fCallAgain != FALSE);
868         }
869     } while (pShbMemInst->m_iThreadTermFlag==0);
870     DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalNewData terminated \n");
871     //set thread completed
872     complete_and_exit(&pShbMemInst->m_CompletionNewData, 0);
873     return 0;
874 }
875
876
877
878 //---------------------------------------------------------------------------
879 //  Thread for new data Job Ready signaling
880 //---------------------------------------------------------------------------
881
882 int ShbIpcThreadSignalJobReady (void *pvThreadParam_p)
883 {
884 tShbInstance    pShbInstance;
885 tShbMemInst*    pShbMemInst;
886 tShbMemHeader*  pShbMemHeader;
887 long            lTimeOut;
888 int             iRetVal=-1;
889
890     daemonize("ShbJR%p", pvThreadParam_p);
891     allow_signal(SIGTERM);
892     pShbInstance = (tShbMemInst*)pvThreadParam_p;
893     pShbMemInst  = ShbIpcGetShbMemInst (pShbInstance);
894     pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
895
896     DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalJobReady wait for job ready Sem\n");
897     if (pShbMemInst->m_ulTimeOutJobReady != 0)
898     {
899         lTimeOut = (long) pShbMemInst->m_ulTimeOutJobReady;
900         //wait for job ready semaphore
901         iRetVal = wait_event_interruptible_timeout(pShbMemHeader->m_WaitQueueJobReady,
902             (pShbMemHeader->m_fJobReady != FALSE), lTimeOut);
903     }
904     else
905     {
906         //wait for job ready semaphore
907         iRetVal = wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady,
908             (pShbMemHeader->m_fJobReady != FALSE));
909     }
910
911     if (pShbMemInst->m_pfnSigHndlrJobReady != NULL)
912     {
913         //call Handler
914         pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, !pShbMemHeader->m_fJobReady);
915     }
916
917     pShbMemInst->m_pfnSigHndlrJobReady=NULL;
918     return 0;
919 }
920
921
922
923 //Build the crc table
924 static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256])
925 {
926     unsigned long       ulCrc,ulPoly;
927     int                 iIndexI,iIndexJ;
928
929     ulPoly = 0xEDB88320L;
930     for (iIndexI = 0; iIndexI < 256; iIndexI++)
931     {
932         ulCrc = iIndexI;
933         for (iIndexJ = 8; iIndexJ > 0; iIndexJ--)
934         {
935             if (ulCrc & 1)
936             {
937                 ulCrc = (ulCrc >> 1) ^ ulPoly;
938             }
939             else
940             {
941                 ulCrc >>= 1;
942             }
943         }
944         aulCrcTable[iIndexI] = ulCrc;
945     }
946 }
947
948 //Calculate the crc value
949 static unsigned long ShbIpcCrc32GetCrc(const char *pcString,unsigned long aulCrcTable[256])
950 {
951     unsigned long   ulCrc;
952     int             iIndex;
953
954     ulCrc = 0xFFFFFFFF;
955     for (iIndex=0;iIndex<strlen(pcString);iIndex++)
956     {
957         ulCrc = ((ulCrc>>8) & 0x00FFFFFF) ^ aulCrcTable[ (ulCrc^pcString[iIndex]) & 0xFF ];
958     }
959     return( ulCrc^0xFFFFFFFF );
960
961 }
962
963 static void ShbIpcAppendListElement (struct sShbMemTable *psNewMemTableElement)
964 {
965     struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g;
966     psNewMemTableElement->m_psNextMemTableElement=NULL;
967
968     if (psMemTableElementFirst_g!= NULL )
969     {      /* sind Elemente vorhanden */
970        while (psMemTableElement->m_psNextMemTableElement != NULL )
971        {    /* suche das letzte Element */
972            psMemTableElement=psMemTableElement->m_psNextMemTableElement;
973        }
974        psMemTableElement->m_psNextMemTableElement=psNewMemTableElement;              /*  Haenge das Element hinten an */
975     }
976     else
977     {                           /* wenn die liste leer ist, bin ich das erste Element */
978         psMemTableElementFirst_g=psNewMemTableElement;
979     }
980 }
981
982
983
984
985 static int ShbIpcFindListElement (int iBufferId, struct sShbMemTable **ppsReturnMemTableElement)
986 {
987     struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g;
988     while (psMemTableElement!=NULL)
989     {
990         if(psMemTableElement->m_iBufferId==iBufferId)
991         {
992 //printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",psMemTableElement->m_pBuffer,psMemTableElement->m_iBufferId);
993              *ppsReturnMemTableElement=psMemTableElement;
994 //printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",(*ppsReturnMemTableElement)->m_pBuffer,(*ppsReturnMemTableElement)->m_iBufferId);
995              return 0;
996         }
997         psMemTableElement=psMemTableElement->m_psNextMemTableElement;
998     }
999     return -1;
1000 }
1001
1002 static void ShbIpcDeleteListElement(int iBufferId)
1003 {
1004    struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g;
1005    struct sShbMemTable *psMemTableElementOld=psMemTableElementFirst_g;
1006    if (psMemTableElement!=NULL)
1007    {
1008         while((psMemTableElement!=NULL)&&(psMemTableElement->m_iBufferId!=iBufferId))
1009         {
1010             psMemTableElementOld=psMemTableElement;
1011             psMemTableElement=psMemTableElement->m_psNextMemTableElement;
1012         }
1013         if (psMemTableElement!=NULL)
1014         {
1015             if (psMemTableElement!=psMemTableElementFirst_g)
1016             {
1017                 psMemTableElementOld->m_psNextMemTableElement=psMemTableElement->m_psNextMemTableElement;
1018                 kfree(psMemTableElement);
1019             }
1020             else
1021             {
1022                 kfree(psMemTableElement);
1023                 psMemTableElementFirst_g=NULL;
1024             }
1025
1026         }
1027    }
1028
1029 }
1030
1031 #endif