qlge: bugfix: Pad outbound frames smaller than 60 bytes.
[safe/jmp/linux-2.6] / drivers / staging / epl / EplSdoAsndu.c
1 /****************************************************************************
2
3   (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4       www.systec-electronic.com
5
6   Project:      openPOWERLINK
7
8   Description:  source file for SDO/Asnd-Protocolabstractionlayer module
9
10   License:
11
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions
14     are met:
15
16     1. Redistributions of source code must retain the above copyright
17        notice, this list of conditions and the following disclaimer.
18
19     2. Redistributions in binary form must reproduce the above copyright
20        notice, this list of conditions and the following disclaimer in the
21        documentation and/or other materials provided with the distribution.
22
23     3. Neither the name of SYSTEC electronic GmbH nor the names of its
24        contributors may be used to endorse or promote products derived
25        from this software without prior written permission. For written
26        permission, please contact info@systec-electronic.com.
27
28     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32     COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39     POSSIBILITY OF SUCH DAMAGE.
40
41     Severability Clause:
42
43         If a provision of this License is or becomes illegal, invalid or
44         unenforceable in any jurisdiction, that shall not affect:
45         1. the validity or enforceability in that jurisdiction of any other
46            provision of this License; or
47         2. the validity or enforceability in other jurisdictions of that or
48            any other provision of this License.
49
50   -------------------------------------------------------------------------
51
52                 $RCSfile: EplSdoAsndu.c,v $
53
54                 $Author: D.Krueger $
55
56                 $Revision: 1.7 $  $Date: 2008/10/17 15:32:32 $
57
58                 $State: Exp $
59
60                 Build Environment:
61                     GCC V3.4
62
63   -------------------------------------------------------------------------
64
65   Revision History:
66
67   2006/07/07 k.t.:   start of the implementation
68
69 ****************************************************************************/
70
71 #include "user/EplSdoAsndu.h"
72 #include "user/EplDlluCal.h"
73
74 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
75
76 /***************************************************************************/
77 /*                                                                         */
78 /*                                                                         */
79 /*          G L O B A L   D E F I N I T I O N S                            */
80 /*                                                                         */
81 /*                                                                         */
82 /***************************************************************************/
83
84 //---------------------------------------------------------------------------
85 // const defines
86 //---------------------------------------------------------------------------
87
88 #ifndef EPL_SDO_MAX_CONNECTION_ASND
89 #define EPL_SDO_MAX_CONNECTION_ASND 5
90 #endif
91
92 //---------------------------------------------------------------------------
93 // local types
94 //---------------------------------------------------------------------------
95
96 // instance table
97 typedef struct {
98         unsigned int m_auiSdoAsndConnection[EPL_SDO_MAX_CONNECTION_ASND];
99         tEplSequLayerReceiveCb m_fpSdoAsySeqCb;
100
101 } tEplSdoAsndInstance;
102
103 //---------------------------------------------------------------------------
104 // modul globale vars
105 //---------------------------------------------------------------------------
106
107 static tEplSdoAsndInstance SdoAsndInstance_g;
108
109 //---------------------------------------------------------------------------
110 // local function prototypes
111 //---------------------------------------------------------------------------
112
113 tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p);
114
115 /***************************************************************************/
116 /*                                                                         */
117 /*                                                                         */
118 /*          C L A S S  <EPL SDO-Asnd Protocolabstraction layer>            */
119 /*                                                                         */
120 /*                                                                         */
121 /***************************************************************************/
122 //
123 // Description: EPL SDO-Asnd Protocolabstraction layer
124 //
125 //
126 /***************************************************************************/
127
128 //=========================================================================//
129 //                                                                         //
130 //          P U B L I C   F U N C T I O N S                                //
131 //                                                                         //
132 //=========================================================================//
133
134 //---------------------------------------------------------------------------
135 //
136 // Function:    EplSdoAsnduInit
137 //
138 // Description: init first instance of the module
139 //
140 //
141 //
142 // Parameters:  pReceiveCb_p    =   functionpointer to Sdo-Sequence layer
143 //                                  callback-function
144 //
145 //
146 // Returns:     tEplKernel  = Errorcode
147 //
148 //
149 // State:
150 //
151 //---------------------------------------------------------------------------
152 tEplKernel PUBLIC EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p)
153 {
154         tEplKernel Ret;
155
156         Ret = EplSdoAsnduAddInstance(fpReceiveCb_p);
157
158         return Ret;
159 }
160
161 //---------------------------------------------------------------------------
162 //
163 // Function:    EplSdoAsnduAddInstance
164 //
165 // Description: init additional instance of the module
166 //
167 //
168 //
169 // Parameters:  pReceiveCb_p    =   functionpointer to Sdo-Sequence layer
170 //                                  callback-function
171 //
172 //
173 // Returns:     tEplKernel  = Errorcode
174 //
175 //
176 // State:
177 //
178 //---------------------------------------------------------------------------
179 tEplKernel PUBLIC EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p)
180 {
181         tEplKernel Ret;
182
183         Ret = kEplSuccessful;
184
185         // init control structure
186         EPL_MEMSET(&SdoAsndInstance_g, 0x00, sizeof(SdoAsndInstance_g));
187
188         // save pointer to callback-function
189         if (fpReceiveCb_p != NULL) {
190                 SdoAsndInstance_g.m_fpSdoAsySeqCb = fpReceiveCb_p;
191         } else {
192                 Ret = kEplSdoUdpMissCb;
193         }
194
195 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
196         Ret = EplDlluCalRegAsndService(kEplDllAsndSdo,
197                                        EplSdoAsnduCb, kEplDllAsndFilterLocal);
198 #endif
199
200         return Ret;
201 }
202
203 //---------------------------------------------------------------------------
204 //
205 // Function:    EplSdoAsnduDelInstance
206 //
207 // Description: del instance of the module
208 //              del socket and del Listen-Thread
209 //
210 //
211 //
212 // Parameters:
213 //
214 //
215 // Returns:     tEplKernel  = Errorcode
216 //
217 //
218 // State:
219 //
220 //---------------------------------------------------------------------------
221 tEplKernel PUBLIC EplSdoAsnduDelInstance()
222 {
223         tEplKernel Ret;
224
225         Ret = kEplSuccessful;
226
227 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
228         // deregister callback function from DLL
229         Ret = EplDlluCalRegAsndService(kEplDllAsndSdo,
230                                        NULL, kEplDllAsndFilterNone);
231 #endif
232
233         return Ret;
234 }
235
236 //---------------------------------------------------------------------------
237 //
238 // Function:    EplSdoAsnduInitCon
239 //
240 // Description: init a new connect
241 //
242 //
243 //
244 // Parameters:  pSdoConHandle_p = pointer for the new connection handle
245 //              uiTargetNodeId_p = NodeId of the target node
246 //
247 //
248 // Returns:     tEplKernel  = Errorcode
249 //
250 //
251 // State:
252 //
253 //---------------------------------------------------------------------------
254 tEplKernel PUBLIC EplSdoAsnduInitCon(tEplSdoConHdl * pSdoConHandle_p,
255                                      unsigned int uiTargetNodeId_p)
256 {
257         tEplKernel Ret;
258         unsigned int uiCount;
259         unsigned int uiFreeCon;
260         unsigned int *puiConnection;
261
262         Ret = kEplSuccessful;
263
264         if ((uiTargetNodeId_p == EPL_C_ADR_INVALID)
265             || (uiTargetNodeId_p >= EPL_C_ADR_BROADCAST)) {
266                 Ret = kEplSdoAsndInvalidNodeId;
267                 goto Exit;
268         }
269         // get free entry in control structure
270         uiCount = 0;
271         uiFreeCon = EPL_SDO_MAX_CONNECTION_ASND;
272         puiConnection = &SdoAsndInstance_g.m_auiSdoAsndConnection[0];
273         while (uiCount < EPL_SDO_MAX_CONNECTION_ASND) {
274                 if (*puiConnection == uiTargetNodeId_p) {       // existing connection to target node found
275                         // save handle for higher layer
276                         *pSdoConHandle_p = (uiCount | EPL_SDO_ASND_HANDLE);
277
278                         goto Exit;
279                 } else if (*puiConnection == 0) {       // free entry-> save target nodeId
280                         uiFreeCon = uiCount;
281                 }
282                 uiCount++;
283                 puiConnection++;
284         }
285
286         if (uiFreeCon == EPL_SDO_MAX_CONNECTION_ASND) {
287                 // no free connection
288                 Ret = kEplSdoAsndNoFreeHandle;
289         } else {
290                 puiConnection =
291                     &SdoAsndInstance_g.m_auiSdoAsndConnection[uiFreeCon];
292                 *puiConnection = uiTargetNodeId_p;
293                 // save handle for higher layer
294                 *pSdoConHandle_p = (uiFreeCon | EPL_SDO_ASND_HANDLE);
295
296                 goto Exit;
297         }
298
299       Exit:
300         return Ret;
301 }
302
303 //---------------------------------------------------------------------------
304 //
305 // Function:    EplSdoAsnduSendData
306 //
307 // Description: send data using exisiting connection
308 //
309 //
310 //
311 // Parameters:  SdoConHandle_p  = connection handle
312 //              pSrcData_p      = pointer to data
313 //              dwDataSize_p    = number of databyte
314 //                                  -> without asnd-header!!!
315 //
316 // Returns:     tEplKernel  = Errorcode
317 //
318 //
319 // State:
320 //
321 //---------------------------------------------------------------------------
322 tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p,
323                                       tEplFrame * pSrcData_p,
324                                       DWORD dwDataSize_p)
325 {
326         tEplKernel Ret;
327         unsigned int uiArray;
328         tEplFrameInfo FrameInfo;
329
330         Ret = kEplSuccessful;
331
332         uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
333
334         if (uiArray > EPL_SDO_MAX_CONNECTION_ASND) {
335                 Ret = kEplSdoAsndInvalidHandle;
336                 goto Exit;
337         }
338         // fillout Asnd header
339         // own node id not needed -> filled by DLL
340
341         // set message type
342         AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, (BYTE) kEplMsgTypeAsnd); // ASnd == 0x06
343         // target node id
344         AmiSetByteToLe(&pSrcData_p->m_le_bDstNodeId,
345                        (BYTE) SdoAsndInstance_g.
346                        m_auiSdoAsndConnection[uiArray]);
347         // set source-nodeid (filled by DLL 0)
348         AmiSetByteToLe(&pSrcData_p->m_le_bSrcNodeId, 0x00);
349
350         // calc size
351         dwDataSize_p += EPL_ASND_HEADER_SIZE;
352
353         // send function of DLL
354         FrameInfo.m_uiFrameSize = dwDataSize_p;
355         FrameInfo.m_pFrame = pSrcData_p;
356         EPL_MEMSET(&FrameInfo.m_NetTime, 0x00, sizeof(tEplNetTime));
357 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
358         Ret = EplDlluCalAsyncSend(&FrameInfo, kEplDllAsyncReqPrioGeneric);
359 #endif
360
361       Exit:
362         return Ret;
363
364 }
365
366 //---------------------------------------------------------------------------
367 //
368 // Function:    EplSdoAsnduDelCon
369 //
370 // Description: delete connection from intern structure
371 //
372 //
373 //
374 // Parameters:  SdoConHandle_p  = connection handle
375 //
376 // Returns:     tEplKernel  = Errorcode
377 //
378 //
379 // State:
380 //
381 //---------------------------------------------------------------------------
382 tEplKernel PUBLIC EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p)
383 {
384         tEplKernel Ret;
385         unsigned int uiArray;
386
387         Ret = kEplSuccessful;
388
389         uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
390         // check parameter
391         if (uiArray > EPL_SDO_MAX_CONNECTION_ASND) {
392                 Ret = kEplSdoAsndInvalidHandle;
393                 goto Exit;
394         }
395         // set target nodeId to 0
396         SdoAsndInstance_g.m_auiSdoAsndConnection[uiArray] = 0;
397
398       Exit:
399         return Ret;
400 }
401
402 //=========================================================================//
403 //                                                                         //
404 //          P R I V A T E   F U N C T I O N S                              //
405 //                                                                         //
406 //=========================================================================//
407
408 //---------------------------------------------------------------------------
409 //
410 // Function:    EplSdoAsnduCb
411 //
412 // Description: callback function for SDO ASnd frames
413 //
414 //
415 //
416 // Parameters:      pFrameInfo_p = Frame with SDO payload
417 //
418 //
419 // Returns:         tEplKernel = errorcode
420 //
421 //
422 // State:
423 //
424 //---------------------------------------------------------------------------
425 tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p)
426 {
427         tEplKernel Ret = kEplSuccessful;
428         unsigned int uiCount;
429         unsigned int *puiConnection;
430         unsigned int uiNodeId;
431         unsigned int uiFreeEntry = 0xFFFF;
432         tEplSdoConHdl SdoConHdl;
433         tEplFrame *pFrame;
434
435         pFrame = pFrameInfo_p->m_pFrame;
436
437         uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
438
439         // search corresponding entry in control structure
440         uiCount = 0;
441         puiConnection = &SdoAsndInstance_g.m_auiSdoAsndConnection[0];
442         while (uiCount < EPL_SDO_MAX_CONNECTION_ASND) {
443                 if (uiNodeId == *puiConnection) {
444                         break;
445                 } else if ((*puiConnection == 0)
446                            && (uiFreeEntry == 0xFFFF)) {        // free entry
447                         uiFreeEntry = uiCount;
448                 }
449                 uiCount++;
450                 puiConnection++;
451         }
452
453         if (uiCount == EPL_SDO_MAX_CONNECTION_ASND) {
454                 if (uiFreeEntry != 0xFFFF) {
455                         puiConnection =
456                             &SdoAsndInstance_g.
457                             m_auiSdoAsndConnection[uiFreeEntry];
458                         *puiConnection = uiNodeId;
459                         uiCount = uiFreeEntry;
460                 } else {
461                         EPL_DBGLVL_SDO_TRACE0
462                             ("EplSdoAsnduCb(): no free handle\n");
463                         goto Exit;
464                 }
465         }
466 //    if (uiNodeId == *puiConnection)
467         {                       // entry found or created
468                 SdoConHdl = (uiCount | EPL_SDO_ASND_HANDLE);
469
470                 SdoAsndInstance_g.m_fpSdoAsySeqCb(SdoConHdl,
471                                                   &pFrame->m_Data.m_Asnd.
472                                                   m_Payload.m_SdoSequenceFrame,
473                                                   (pFrameInfo_p->m_uiFrameSize -
474                                                    18));
475         }
476
477       Exit:
478         return Ret;
479
480 }
481
482 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
483 // EOF