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