OpenCores
URL https://opencores.org/ocsvn/funbase_ip_library/funbase_ip_library/trunk

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.swp.api/] [openmcapi/] [1.0/] [libmcapi/] [mcapi/] [cntrl_msg.c] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
/*
2
 * Copyright (c) 2010, Mentor Graphics Corporation
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
 * POSSIBILITY OF SUCH DAMAGE.
28
 */
29
 
30
 
31
 
32
#include <openmcapi.h>
33
 
34
extern mcapi_endpoint_t     MCAPI_CTRL_RX_Endp;
35
extern mcapi_endpoint_t     MCAPI_CTRL_TX_Endp;
36
extern MCAPI_BUF_QUEUE      MCAPI_RX_Queue[MCAPI_PRIO_COUNT];
37
 
38
static void mcapi_connect_endpoints(MCAPI_GLOBAL_DATA *, unsigned char *,
39
                                    mcapi_status_t *);
40
static void mcapi_setup_connection(MCAPI_GLOBAL_DATA *, MCAPI_ENDPOINT *,
41
                                   unsigned char *, mcapi_status_t *, mcapi_uint16_t);
42
static void send_connect_response(unsigned char *, mcapi_status_t);
43
 
44
/*************************************************************************
45
*
46
*   FUNCTION
47
*
48
*       mcapi_process_ctrl_msg
49
*
50
*   DESCRIPTION
51
*
52
*       Processes incoming control messages sent from other nodes in
53
*       the system.
54
*
55
*   INPUTS
56
*
57
*       None.
58
*
59
*   OUTPUTS
60
*
61
*       None.
62
*
63
*************************************************************************/
64
MCAPI_THREAD_ENTRY(mcapi_process_ctrl_msg)
65
{
66
    mcapi_status_t          mcapi_status;
67
    unsigned char           buffer[MCAPI_CONTROL_MSG_LEN];
68
    mcapi_request_t         *request, mcapi_request;
69
    size_t                  rx_size;
70
    MCAPI_GLOBAL_DATA       *node_data;
71
    mcapi_node_t            node_id;
72
    mcapi_port_t            port_id;
73
    MCAPI_ENDPOINT          *endp_ptr;
74
    mcapi_endpoint_t        endpoint;
75
 
76
    /* This loop is active while the node is up and running. */
77
    for (;;)
78
    {
79
        /* Wait for data on the endpoint. */
80
        mcapi_msg_recv(MCAPI_CTRL_RX_Endp, &buffer,
81
                       MCAPI_CONTROL_MSG_LEN,
82
                       &rx_size, &mcapi_status);
83
 
84
        /* If a control message was received. */
85
        if ( (mcapi_status == MCAPI_SUCCESS) && (rx_size) )
86
        {
87
            /* Get the lock. */
88
            mcapi_lock_node_data();
89
 
90
            /* Get a pointer to the global node list. */
91
            node_data = mcapi_get_node_data();
92
 
93
            /* Determine the type of message. */
94
            switch (MCAPI_GET16(buffer, MCAPI_PROT_TYPE))
95
            {
96
                case MCAPI_GETENDP_REQUEST:
97
 
98
                    /* Extract the target port from the packet. */
99
                    port_id = MCAPI_GET16(buffer, MCAPI_GETENDP_PORT);
100
 
101
                    /* Get a pointer to the endpoint. */
102
                    endp_ptr = mcapi_find_local_endpoint(node_data,
103
                                                         MCAPI_Node_ID,
104
                                                         port_id);
105
 
106
                    /* If the endpoint was found. */
107
                    if (endp_ptr)
108
                    {
109
                        /* Set the type. */
110
                        MCAPI_PUT16(buffer, MCAPI_PROT_TYPE,
111
                                    MCAPI_GETENDP_RESPONSE);
112
 
113
                        /* Set the status. */
114
                        MCAPI_PUT32(buffer, MCAPI_GETENDP_STATUS, MCAPI_SUCCESS);
115
 
116
                        /* Extract the destination endpoint. */
117
                        endpoint = MCAPI_GET32(buffer, MCAPI_GETENDP_ENDP);
118
 
119
                        /* Put the target endpoint in the buffer. */
120
                        MCAPI_PUT32(buffer, MCAPI_GETENDP_ENDP,
121
                                    mcapi_encode_endpoint(endp_ptr->mcapi_node_id,
122
                                    endp_ptr->mcapi_port_id));
123
 
124
                        /* Send the packet back to the caller. */
125
                        msg_send(MCAPI_CTRL_TX_Endp, endpoint, buffer,
126
                                 MCAPI_GET_ENDP_LEN, MCAPI_DEFAULT_PRIO,
127
                                 &mcapi_request, &mcapi_status, 0xffffffff);
128
                    }
129
 
130
                    /* The endpoint has not been created. */
131
                    else
132
                    {
133
                        /* Decode the requestor's information. */
134
                        mcapi_decode_endpoint(MCAPI_GET32(buffer, MCAPI_GETENDP_ENDP),
135
                                              &node_id, &port_id);
136
 
137
                        /* Ensure another thread on this same remote node
138
                         * is not already waiting for the endpoint to be
139
                         * created.
140
                         */
141
                        request = node_data->mcapi_foreign_req_queue.flink;
142
 
143
                        /* Check each request. */
144
                        while (request)
145
                        {
146
                            /* If this is an endpoint request for the same endpoint
147
                             * from the same node, do not add it again since all
148
                             * tasks waiting for this endpoint will be resumed by
149
                             * one call.
150
                             */
151
                            if ( (request->mcapi_type == MCAPI_REQ_CREATED) &&
152
                                 (request->mcapi_target_node_id == MCAPI_Node_ID) &&
153
                                 (request->mcapi_target_port_id ==
154
                                  MCAPI_GET16(buffer, MCAPI_GETENDP_PORT)) &&
155
                                 (request->mcapi_requesting_node_id == node_id) )
156
                            {
157
                                request->mcapi_pending_count ++;
158
                                break;
159
                            }
160
 
161
                            request = request->mcapi_next;
162
                        }
163
 
164
                        /* If the remote node is not already pending creation
165
                         * of the target endpoint.
166
                         */
167
                        if (!request)
168
                        {
169
                            /* Reserve a global request structure. */
170
                            request = mcapi_get_free_request_struct();
171
 
172
                            /* If a free structure is available. */
173
                            if (request)
174
                            {
175
                                /* Set the type. */
176
                                request->mcapi_type = MCAPI_REQ_CREATED;
177
 
178
                                /* Set up the request structure. */
179
                                request->mcapi_target_port_id =
180
                                    MCAPI_GET16(buffer, MCAPI_GETENDP_PORT);
181
                                request->mcapi_target_node_id = MCAPI_Node_ID;
182
                                request->mcapi_requesting_node_id = node_id;
183
                                request->mcapi_requesting_port_id = port_id;
184
                                request->mcapi_status = MCAPI_PENDING;
185
                                request->mcapi_pending_count = 1;
186
 
187
                                /* Add the structure to the wait list. */
188
                                mcapi_enqueue(&node_data->mcapi_foreign_req_queue, request);
189
                            }
190
 
191
                            /* Otherwise, send an error to the caller. */
192
                            else
193
                            {
194
                                /* Set an error. */
195
                                MCAPI_PUT32(buffer, MCAPI_GETENDP_STATUS,
196
                                            (mcapi_uint32_t)MCAPI_ERR_REQUEST_LIMIT);
197
 
198
                                /* Set the type. */
199
                                MCAPI_PUT16(buffer, MCAPI_PROT_TYPE,
200
                                            MCAPI_GETENDP_RESPONSE);
201
 
202
                                /* Extract the destination endpoint. */
203
                                endpoint = MCAPI_GET32(buffer, MCAPI_GETENDP_ENDP);
204
 
205
                                /* Put the target endpoint in the packet. */
206
                                MCAPI_PUT32(buffer, MCAPI_GETENDP_ENDP,
207
                                            mcapi_encode_endpoint(MCAPI_Node_ID, port_id));
208
 
209
                                /* Send the packet back to the caller. */
210
                                msg_send(MCAPI_CTRL_TX_Endp, endpoint, buffer,
211
                                         MCAPI_GET_ENDP_LEN, MCAPI_DEFAULT_PRIO,
212
                                         &mcapi_request, &mcapi_status, 0xffffffff);
213
                            }
214
                        }
215
                    }
216
 
217
                    break;
218
 
219
                case MCAPI_GETENDP_RESPONSE:
220
 
221
                    /* Extract the status from the packet. */
222
                    mcapi_status = MCAPI_GET32(buffer, MCAPI_GETENDP_STATUS);
223
 
224
                    /* Wake the task that requested this data. */
225
                    mcapi_check_resume(MCAPI_REQ_CREATED,
226
                                       MCAPI_GET32(buffer, MCAPI_GETENDP_ENDP),
227
                                       MCAPI_NULL, 0, mcapi_status);
228
 
229
                    break;
230
 
231
                case MCAPI_CANCEL_MSG:
232
 
233
                    /* Decode the requestor's information. */
234
                    mcapi_decode_endpoint(MCAPI_GET32(buffer, MCAPI_GETENDP_ENDP),
235
                                          &node_id, &port_id);
236
 
237
                    /* Find the request message in the list. */
238
                    request = node_data->mcapi_foreign_req_queue.flink;
239
 
240
                    /* Check each request. */
241
                    while (request)
242
                    {
243
                        /* If this request matches. */
244
                        if ( (request->mcapi_type == MCAPI_REQ_CREATED) &&
245
                             (request->mcapi_target_node_id == MCAPI_Node_ID) &&
246
                             (request->mcapi_target_port_id ==
247
                              MCAPI_GET16(buffer, MCAPI_GETENDP_PORT)) &&
248
                             (request->mcapi_requesting_node_id == node_id) )
249
                        {
250
                            /* Decrement the number of tasks pending completion
251
                             * of this request.
252
                             */
253
                            request->mcapi_pending_count --;
254
 
255
                            /* If this was the only task waiting for the request
256
                             * to complete.
257
                             */
258
                            if (request->mcapi_pending_count == 0)
259
                            {
260
                                /* Remove the request from the list. */
261
                                mcapi_remove(&node_data->mcapi_foreign_req_queue, request);
262
                            }
263
 
264
                            break;
265
                        }
266
 
267
                        /* Get the next request. */
268
                        request = request->mcapi_next;
269
                    }
270
 
271
                    break;
272
 
273
                case MCAPI_CONNECT_REQUEST:
274
 
275
                    /* If the node ID of the send side is the local node,
276
                     * connect the send side.  The requestor should only
277
                     * send the connection request to the send side.
278
                     */
279
                    if (MCAPI_GET16(buffer, MCAPI_CNCT_TX_NODE) == MCAPI_Node_ID)
280
                    {
281
                        /* Send a SYN request to the receive side. */
282
                        mcapi_connect_endpoints(node_data, buffer, &mcapi_status);
283
 
284
                        /* If the connection is not possible, send an error
285
                         * to the caller.
286
                         */
287
                        if (mcapi_status != MCAPI_SUCCESS)
288
                        {
289
                            /* Send the response. */
290
                            send_connect_response(buffer, mcapi_status);
291
                        }
292
                    }
293
 
294
                    break;
295
 
296
                case MCAPI_CONNECT_SYN:
297
 
298
                    /* Extract the node ID and port ID. */
299
                    node_id = MCAPI_GET16(buffer, MCAPI_CNCT_RX_NODE);
300
                    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_RX_PORT);
301
 
302
                    /* Get a pointer to the endpoint. */
303
                    endp_ptr = mcapi_find_local_endpoint(node_data, node_id,
304
                                                         port_id);
305
 
306
                    /* If the endpoint was found. */
307
                    if (endp_ptr)
308
                    {
309
                        /* Make the call to set up the connection. */
310
                        mcapi_setup_connection(node_data, endp_ptr, buffer,
311
                                               &mcapi_status, MCAPI_RX_SIDE);
312
                    }
313
 
314
                    /* The endpoint is not valid. */
315
                    else
316
                    {
317
                        mcapi_status = MCAPI_ERR_ENDP_INVALID;
318
                    }
319
 
320
                    /* Set the type to ACK. */
321
                    MCAPI_PUT16(buffer, MCAPI_PROT_TYPE, MCAPI_CONNECT_ACK);
322
 
323
                    /* Set the status. */
324
                    MCAPI_PUT32(buffer, MCAPI_CNCT_STATUS, mcapi_status);
325
 
326
                    /* Send the status response to the transmit node. */
327
                    msg_send(MCAPI_CTRL_TX_Endp,
328
                             mcapi_encode_endpoint(MCAPI_GET16(buffer, MCAPI_CNCT_TX_NODE),
329
                             MCAPI_RX_CONTROL_PORT), buffer,
330
                             MCAPI_CONNECT_MSG_LEN, MCAPI_DEFAULT_PRIO,
331
                             &mcapi_request, &mcapi_status, 0xffffffff);
332
 
333
                    /* If the request was successful. */
334
                    if (mcapi_status == MCAPI_SUCCESS)
335
                    {
336
                        /* If the open call has been made from the application,
337
                         * send the open request to the send side.
338
                         */
339
                        if ( (endp_ptr) &&
340
                             (endp_ptr->mcapi_state & MCAPI_ENDP_RX) )
341
                        {
342
                            /* Send the open call to the other side. */
343
                            mcapi_tx_open(buffer, endp_ptr,
344
                                          endp_ptr->mcapi_foreign_node_id,
345
                                          endp_ptr->mcapi_foreign_port_id,
346
                                          endp_ptr->mcapi_node_id,
347
                                          endp_ptr->mcapi_port_id, MCAPI_OPEN_RX,
348
                                          MCAPI_GET16(buffer, MCAPI_CNCT_CHAN_TYPE),
349
                                          &mcapi_status);
350
                        }
351
                    }
352
 
353
                    break;
354
 
355
                case MCAPI_CONNECT_ACK:
356
 
357
                    /* Extract the node ID and port ID. */
358
                    node_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_NODE);
359
                    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_PORT);
360
 
361
                    /* Get a pointer to the endpoint. */
362
                    endp_ptr = mcapi_find_local_endpoint(node_data, node_id,
363
                                                         port_id);
364
 
365
                    /* Get the status from the packet. */
366
                    mcapi_status = MCAPI_GET32(buffer, MCAPI_CNCT_STATUS);
367
 
368
                    /* Ensure the endpoint wasn't deleted while waiting for
369
                     * the ACK from the other side.
370
                     */
371
                    if (endp_ptr)
372
                    {
373
                        /* If the status is success, open the connection. */
374
                        if (mcapi_status == MCAPI_SUCCESS)
375
                        {
376
                            mcapi_setup_connection(node_data, endp_ptr, buffer,
377
                                                   &mcapi_status, MCAPI_TX_SIDE);
378
 
379
                            /* If the open call has been made by the application,
380
                             * send the open request to the receive side.
381
                             */
382
                            if (endp_ptr->mcapi_state & MCAPI_ENDP_TX)
383
                            {
384
                                /* Send the open call to the other side. */
385
                                mcapi_tx_open(buffer, endp_ptr,
386
                                              endp_ptr->mcapi_node_id,
387
                                              endp_ptr->mcapi_port_id,
388
                                              endp_ptr->mcapi_foreign_node_id,
389
                                              endp_ptr->mcapi_foreign_port_id,
390
                                              MCAPI_OPEN_TX,
391
                                              MCAPI_GET16(buffer, MCAPI_CNCT_CHAN_TYPE),
392
                                              &mcapi_status);
393
                            }
394
                        }
395
 
396
                        /* The other side could not open the connection. */
397
                        else
398
                        {
399
                            /* Clear the "connecting" flag since this connection
400
                             * could not be made.
401
                             */
402
                            endp_ptr->mcapi_state &= ~MCAPI_ENDP_CONNECTING;
403
                        }
404
                    }
405
 
406
                    /* Send the response to the requestor.  If the endpoint was
407
                     * deleted, it's OK to report success to the connection
408
                     * requestor since an error will be returned to the
409
                     * RX side when it tries to open.
410
                     */
411
                    send_connect_response(buffer, mcapi_status);
412
 
413
                    break;
414
 
415
                case MCAPI_OPEN_TX:
416
 
417
                    mcapi_status = MCAPI_SUCCESS;
418
 
419
                    /* Extract the node ID and port ID. */
420
                    node_id = MCAPI_GET16(buffer, MCAPI_CNCT_RX_NODE);
421
                    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_RX_PORT);
422
 
423
                    /* Get a pointer to the endpoint. */
424
                    endp_ptr = mcapi_find_local_endpoint(node_data, node_id,
425
                                                         port_id);
426
 
427
                    /* If the endpoint was found. */
428
                    if (endp_ptr)
429
                    {
430
                        /* Set the state to indicate the send side has
431
                         * opened.
432
                         */
433
                        endp_ptr->mcapi_state |= MCAPI_ENDP_TX_ACKED;
434
 
435
                        /* If the receive side has also opened. */
436
                        if (endp_ptr->mcapi_state & MCAPI_ENDP_RX_ACKED)
437
                        {
438
                            /* Indicate that the connection is complete. */
439
                            endp_ptr->mcapi_state |= MCAPI_ENDP_CONNECTED;
440
 
441
                            /* Check if any tasks are waiting for the receive side
442
                             * to be opened.
443
                             */
444
                            mcapi_check_resume(MCAPI_REQ_RX_OPEN,
445
                                               endp_ptr->mcapi_endp_handle,
446
                                               MCAPI_NULL, 0, mcapi_status);
447
                        }
448
                    }
449
 
450
                    else
451
                    {
452
                        mcapi_status = MCAPI_ERR_ENDP_INVALID;
453
                    }
454
 
455
                    /* Set the type to TX_ACK. */
456
                    MCAPI_PUT16(buffer, MCAPI_PROT_TYPE, MCAPI_OPEN_TX_ACK);
457
 
458
                    /* Put the status in the packet. */
459
                    MCAPI_PUT32(buffer, MCAPI_CNCT_STATUS, mcapi_status);
460
 
461
                    /* Send a status back to the send side so they
462
                     * know whether the connection should proceed.
463
                     */
464
                    msg_send(MCAPI_CTRL_TX_Endp,
465
                             mcapi_encode_endpoint(MCAPI_GET16(buffer,
466
                             MCAPI_CNCT_TX_NODE), MCAPI_RX_CONTROL_PORT),
467
                             buffer, MCAPI_CONNECT_MSG_LEN,
468
                             MCAPI_DEFAULT_PRIO,
469
                             &mcapi_request, &mcapi_status, 0xffffffff);
470
 
471
                    break;
472
 
473
                case MCAPI_OPEN_RX:
474
 
475
                    mcapi_status = MCAPI_SUCCESS;
476
 
477
                    /* Extract the node ID and port ID. */
478
                    node_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_NODE);
479
                    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_PORT);
480
 
481
                    /* Get a pointer to the endpoint. */
482
                    endp_ptr = mcapi_find_local_endpoint(node_data, node_id,
483
                                                         port_id);
484
 
485
                    /* If the endpoint was found. */
486
                    if (endp_ptr)
487
                    {
488
                        /* Set the state to indicate the other side has
489
                         * opened.
490
                         */
491
                        endp_ptr->mcapi_state |= MCAPI_ENDP_RX_ACKED;
492
 
493
                        /* If the send side has opened and been ACKed. */
494
                        if (endp_ptr->mcapi_state & MCAPI_ENDP_TX_ACKED)
495
                        {
496
                            /* Indicate that the connection is completed. */
497
                            endp_ptr->mcapi_state |= MCAPI_ENDP_CONNECTED;
498
 
499
                            /* Check if any tasks are waiting for the send side
500
                             * to be opened.
501
                             */
502
                            mcapi_check_resume(MCAPI_REQ_TX_OPEN,
503
                                               endp_ptr->mcapi_endp_handle,
504
                                               MCAPI_NULL, 0, mcapi_status);
505
                        }
506
                    }
507
 
508
                    else
509
                    {
510
                        mcapi_status = MCAPI_ERR_ENDP_INVALID;
511
                    }
512
 
513
                    /* Set the type to RX_ACK. */
514
                    MCAPI_PUT16(buffer, MCAPI_PROT_TYPE, MCAPI_OPEN_RX_ACK);
515
 
516
                    /* Put the status in the packet. */
517
                    MCAPI_PUT32(buffer, MCAPI_CNCT_STATUS, mcapi_status);
518
 
519
                    /* Send a status back to the receive side so they
520
                     * know whether the connection should proceed.
521
                     */
522
                    msg_send(MCAPI_CTRL_TX_Endp,
523
                             mcapi_encode_endpoint(MCAPI_GET16(buffer,
524
                             MCAPI_CNCT_RX_NODE), MCAPI_RX_CONTROL_PORT),
525
                             buffer, MCAPI_CONNECT_MSG_LEN,
526
                             MCAPI_DEFAULT_PRIO,
527
                             &mcapi_request, &mcapi_status, 0xffffffff);
528
 
529
                    break;
530
 
531
                case MCAPI_OPEN_RX_ACK:
532
 
533
                    /* Extract the node ID and port ID. */
534
                    node_id = MCAPI_GET16(buffer, MCAPI_CNCT_RX_NODE);
535
                    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_RX_PORT);
536
 
537
                    /* Get a pointer to the endpoint. */
538
                    endp_ptr = mcapi_find_local_endpoint(node_data, node_id,
539
                                                         port_id);
540
 
541
                    /* If the endpoint was found. */
542
                    if (endp_ptr)
543
                    {
544
                        /* Extract the status from the packet. */
545
                        mcapi_status = MCAPI_GET32(buffer, MCAPI_CNCT_STATUS);
546
 
547
                        /* If the ACK is successful. */
548
                        if (mcapi_status == MCAPI_SUCCESS)
549
                        {
550
                            /* Set the flag indicating that the RX side is
551
                             * open.
552
                             */
553
                            endp_ptr->mcapi_state |= MCAPI_ENDP_RX_ACKED;
554
 
555
                            /* If both sides have issued successful open calls. */
556
                            if (endp_ptr->mcapi_state & MCAPI_ENDP_TX_ACKED)
557
                            {
558
                                /* Indicate that the connection is connected. */
559
                                endp_ptr->mcapi_state |= MCAPI_ENDP_CONNECTED;
560
 
561
                                /* Check if any tasks are waiting for the receive side
562
                                 * to be opened.
563
                                 */
564
                                mcapi_check_resume(MCAPI_REQ_RX_OPEN,
565
                                                   endp_ptr->mcapi_endp_handle,
566
                                                   MCAPI_NULL, 0, mcapi_status);
567
                            }
568
                        }
569
 
570
                        else
571
                        {
572
                            /* Clear the flag. */
573
                            endp_ptr->mcapi_state &= ~MCAPI_ENDP_RX;
574
 
575
                            /* Check if any tasks are waiting for the receive side
576
                             * to be opened.
577
                             */
578
                            mcapi_check_resume(MCAPI_REQ_RX_OPEN,
579
                                               endp_ptr->mcapi_endp_handle,
580
                                               MCAPI_NULL, 0, mcapi_status);
581
                        }
582
                    }
583
 
584
                    break;
585
 
586
                case MCAPI_OPEN_TX_ACK:
587
 
588
                    /* Extract the status from the packet. */
589
                    mcapi_status = MCAPI_GET32(buffer, MCAPI_CNCT_STATUS);
590
 
591
                    /* Extract the node ID and port ID. */
592
                    node_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_NODE);
593
                    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_PORT);
594
 
595
                    /* Get a pointer to the endpoint. */
596
                    endp_ptr =
597
                        mcapi_find_local_endpoint(node_data, node_id, port_id);
598
 
599
                    /* If the endpoint was found. */
600
                    if (endp_ptr)
601
                    {
602
                        /* If the status of the ACK is success. */
603
                        if (mcapi_status == MCAPI_SUCCESS)
604
                        {
605
                            /* Set the state to indicate that the TX side
606
                             * is open.
607
                             */
608
                            endp_ptr->mcapi_state |= MCAPI_ENDP_TX_ACKED;
609
 
610
                            /* If both sides have issued successful open calls. */
611
                            if (endp_ptr->mcapi_state & MCAPI_ENDP_RX_ACKED)
612
                            {
613
                                /* Indicate that the connection is connected. */
614
                                endp_ptr->mcapi_state |= MCAPI_ENDP_CONNECTED;
615
 
616
                                /* Check if any tasks are waiting for the send side
617
                                 * to be opened.
618
                                 */
619
                                mcapi_check_resume(MCAPI_REQ_TX_OPEN,
620
                                                   endp_ptr->mcapi_endp_handle,
621
                                                   MCAPI_NULL, 0, mcapi_status);
622
                            }
623
                        }
624
 
625
                        else
626
                        {
627
                            /* Clear the transmit and connecting flags. */
628
                            endp_ptr->mcapi_state &= ~MCAPI_ENDP_TX;
629
 
630
                            /* Check if any tasks are waiting for the send side
631
                             * to be opened.
632
                             */
633
                            mcapi_check_resume(MCAPI_REQ_TX_OPEN,
634
                                               endp_ptr->mcapi_endp_handle,
635
                                               MCAPI_NULL, 0, mcapi_status);
636
                        }
637
                    }
638
 
639
                    break;
640
 
641
                case MCAPI_CONNECT_RESPONSE:
642
 
643
                    /* Get the status. */
644
                    mcapi_status = MCAPI_GET32(buffer, MCAPI_CNCT_STATUS);
645
 
646
                    /* Get the transmit node. */
647
                    node_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_NODE);
648
 
649
                    /* Get the transmit port. */
650
                    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_PORT);
651
 
652
                    /* Check if any tasks are waiting for this connection
653
                     * to be created.
654
                     */
655
                    mcapi_check_resume(MCAPI_REQ_CONNECTED,
656
                                       mcapi_encode_endpoint(node_id, port_id),
657
                                       MCAPI_NULL, 0, mcapi_status);
658
 
659
                    break;
660
 
661
                case MCAPI_CONNECT_FIN:
662
 
663
                    /* Extract the port ID. */
664
                    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_FIN_PORT);
665
 
666
                    /* Get a pointer to the endpoint. */
667
                    endp_ptr = mcapi_find_local_endpoint(node_data, MCAPI_Node_ID,
668
                                                         port_id);
669
 
670
                    /* If the endpoint was found. */
671
                    if (endp_ptr)
672
                    {
673
                        /* Clear the "connected" flag since the other side
674
                         * has shutdown the read/write side.
675
                         */
676
                        endp_ptr->mcapi_state &= ~MCAPI_ENDP_CONNECTED;
677
                        endp_ptr->mcapi_state &= ~MCAPI_ENDP_CONNECTING;
678
 
679
                        /* Resume any threads that are suspended on this endpoint
680
                         * for any reason.
681
                         */
682
                        mcapi_check_resume(MCAPI_REQ_CLOSED,
683
                                           endp_ptr->mcapi_endp_handle, MCAPI_NULL,
684
                                           0, MGC_MCAPI_ERR_NOT_CONNECTED);
685
 
686
                    }
687
 
688
                    break;
689
 
690
                default:
691
 
692
                    break;
693
            }
694
 
695
            /* Release the lock. */
696
            mcapi_unlock_node_data();
697
        }
698
 
699
        /* The application has called mcapi_finalize().  Exit the loop. */
700
        else
701
        {
702
            break;
703
        }
704
    }
705
 
706
    /* Terminate this task. */
707
    MCAPI_Cleanup_Task();
708
 
709
    return NULL;
710
}
711
 
712
/*************************************************************************
713
*
714
*   FUNCTION
715
*
716
*       mcapi_connect_endpoints
717
*
718
*   DESCRIPTION
719
*
720
*       Issues a request to an endpoint to connect the endpoint.
721
*
722
*   INPUTS
723
*
724
*       *node_data              A pointer to the global node data.
725
*       *buffer                 A pointer to the buffer containing
726
*                               the request.  This buffer will be
727
*                               reused to send the SYN to the receive
728
*                               endpoint.
729
*       *status                 A pointer that will be filled in with
730
*                               the status of the request.
731
*
732
*   OUTPUTS
733
*
734
*       None.
735
*
736
*************************************************************************/
737
static void mcapi_connect_endpoints(MCAPI_GLOBAL_DATA *node_data,
738
                                    unsigned char *buffer,
739
                                    mcapi_status_t *mcapi_status)
740
{
741
    MCAPI_ENDPOINT      *endp_ptr;
742
    mcapi_node_t        local_node_id, foreign_node_id;
743
    mcapi_port_t        local_port_id;
744
    mcapi_request_t     request;
745
 
746
    /* Get the local node. */
747
    local_node_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_NODE);
748
 
749
    /* Get the local port. */
750
    local_port_id = MCAPI_GET16(buffer, MCAPI_CNCT_TX_PORT);
751
 
752
    /* Get the foreign node. */
753
    foreign_node_id = MCAPI_GET16(buffer, MCAPI_CNCT_RX_NODE);
754
 
755
    /* Get a pointer to the endpoint. */
756
    endp_ptr = mcapi_find_local_endpoint(node_data, local_node_id,
757
                                         local_port_id);
758
 
759
    /* If the endpoint was found. */
760
    if (endp_ptr)
761
    {
762
        /* If the endpoint is not already connected. */
763
        if (!(endp_ptr->mcapi_state & MCAPI_ENDP_CONNECTING))
764
        {
765
            /* Set the type to connected so another node doesn't
766
             * try to issue a connection while this connection
767
             * is in progress.
768
             */
769
            endp_ptr->mcapi_state |= MCAPI_ENDP_CONNECTING;
770
 
771
            /* Clear the disconnected status in case it is set. */
772
            endp_ptr->mcapi_state &= ~MCAPI_ENDP_DISCONNECTED;
773
 
774
            /* Set the packet type. */
775
            MCAPI_PUT16(buffer, MCAPI_PROT_TYPE, MCAPI_CONNECT_SYN);
776
 
777
            /* Send a message to the foreign node to see if
778
             * the connection can be made.
779
             */
780
            msg_send(MCAPI_CTRL_TX_Endp,
781
                     mcapi_encode_endpoint(foreign_node_id,
782
                     MCAPI_RX_CONTROL_PORT), buffer,
783
                     MCAPI_CONNECT_MSG_LEN, MCAPI_DEFAULT_PRIO,
784
                     &request, mcapi_status, 0xffffffff);
785
        }
786
 
787
        /* This endpoint is already connected. */
788
        else
789
        {
790
            *mcapi_status = MCAPI_ERR_CHAN_CONNECTED;
791
        }
792
    }
793
 
794
    /* This endpoint is not a valid endpoint. */
795
    else
796
    {
797
        *mcapi_status = MCAPI_ERR_ENDP_INVALID;
798
    }
799
 
800
}
801
 
802
/*************************************************************************
803
*
804
*   FUNCTION
805
*
806
*       mcapi_setup_connection
807
*
808
*   DESCRIPTION
809
*
810
*       Sets up a connection over an endpoint.
811
*
812
*   INPUTS
813
*
814
*       *node_data              A pointer to the global node data.
815
*       *buffer                 A pointer to the buffer containing the
816
*                               connection SYN.
817
*       *mcapi_status           A pointer that will be filled in with
818
*                               the status of the operation.
819
*       connect_side            The local node's side of the connection:
820
*                               MCAPI_TX_SIDE or MCAPI_RX_SIDE.
821
*
822
*   OUTPUTS
823
*
824
*       None.
825
*
826
*************************************************************************/
827
static void mcapi_setup_connection(MCAPI_GLOBAL_DATA *node_data,
828
                                   MCAPI_ENDPOINT *endp_ptr, unsigned char *buffer,
829
                                   mcapi_status_t *mcapi_status,
830
                                   mcapi_uint16_t connect_side)
831
{
832
    int                 node_idx;
833
    MCAPI_NODE          *node_ptr;
834
 
835
    /* If the endpoint is not already connected.  Note that the
836
     * transmit side is set to connected when the initial connect
837
     * request is made.
838
     */
839
    if ( (connect_side == MCAPI_TX_SIDE) ||
840
         (!(endp_ptr->mcapi_state & MCAPI_ENDP_CONNECTING)) )
841
    {
842
        /* Get the index of the local node. */
843
        node_idx = mcapi_find_node(endp_ptr->mcapi_node_id, node_data);
844
 
845
        if (node_idx != -1)
846
        {
847
            /* Get a pointer to the node structure. */
848
            node_ptr = &node_data->mcapi_node_list[node_idx];
849
 
850
            /* Set up routes between the two endpoints. */
851
            endp_ptr->mcapi_route =
852
                mcapi_find_route(endp_ptr->mcapi_node_id, node_ptr);
853
 
854
            /* Ensure the receive side is reachable from this node. */
855
            if (endp_ptr->mcapi_route)
856
            {
857
                /* Ensure the attributes of both endpoints match. */
858
 
859
                /* Set the state of the send endpoint. */
860
                endp_ptr->mcapi_state |= MCAPI_ENDP_CONNECTING;
861
 
862
                /* Clear the disconnected status in case it is set. */
863
                endp_ptr->mcapi_state &= ~MCAPI_ENDP_DISCONNECTED;
864
 
865
                /* Get the index of the local node. */
866
                if (connect_side == MCAPI_TX_SIDE)
867
                {
868
                    /* Get the receive node. */
869
                    endp_ptr->mcapi_foreign_node_id =
870
                        MCAPI_GET16(buffer, MCAPI_CNCT_RX_NODE);
871
 
872
                    /* Get the receive port. */
873
                    endp_ptr->mcapi_foreign_port_id =
874
                        MCAPI_GET16(buffer, MCAPI_CNCT_RX_PORT);
875
 
876
                    /* Set the state indicating that this side is connecting
877
                     * as a sender.
878
                     */
879
                    endp_ptr->mcapi_state |= MCAPI_ENDP_CONNECTING_TX;
880
                }
881
 
882
                else
883
                {
884
                    /* Get the receive node. */
885
                    endp_ptr->mcapi_foreign_node_id =
886
                        MCAPI_GET16(buffer, MCAPI_CNCT_TX_NODE);
887
 
888
                    /* Get the receive port. */
889
                    endp_ptr->mcapi_foreign_port_id =
890
                        MCAPI_GET16(buffer, MCAPI_CNCT_TX_PORT);
891
 
892
                    /* Set the state indicating that this side is connecting
893
                     * as a receiver.
894
                     */
895
                    endp_ptr->mcapi_state |= MCAPI_ENDP_CONNECTING_RX;
896
                }
897
 
898
                /* Set the channel type. */
899
                endp_ptr->mcapi_chan_type =
900
                    MCAPI_GET16(buffer, MCAPI_CNCT_CHAN_TYPE);
901
 
902
                /* Extract the requestor's node ID and port ID. */
903
                endp_ptr->mcapi_req_node_id =
904
                    MCAPI_GET16(buffer, MCAPI_CNCT_REQ_NODE);
905
 
906
                endp_ptr->mcapi_req_port_id =
907
                    MCAPI_GET16(buffer, MCAPI_CNCT_REQ_PORT);
908
            }
909
 
910
            /* The node is not reachable from this node. */
911
            else
912
            {
913
                *mcapi_status = MCAPI_ERR_ENDP_INVALID;
914
            }
915
        }
916
 
917
        /* The node is not reachable from this node. */
918
        else
919
        {
920
            *mcapi_status = MCAPI_ERR_ENDP_INVALID;
921
        }
922
    }
923
 
924
    else
925
    {
926
        *mcapi_status = MCAPI_ERR_CHAN_CONNECTED;
927
    }
928
 
929
}
930
 
931
/*************************************************************************
932
*
933
*   FUNCTION
934
*
935
*       send_connect_response
936
*
937
*   DESCRIPTION
938
*
939
*       Sends a response to a connection request.
940
*
941
*   INPUTS
942
*
943
*       *buffer                 A pointer to the buffer containing the
944
*                               outgoing response.
945
*       status                  The status to insert in the response.
946
*
947
*   OUTPUTS
948
*
949
*       None.
950
*
951
*************************************************************************/
952
static void send_connect_response(unsigned char *buffer, mcapi_status_t status)
953
{
954
    mcapi_node_t    node_id;
955
    mcapi_port_t    port_id;
956
    mcapi_status_t  mcapi_status;
957
    mcapi_request_t request;
958
 
959
    /* Get the requestor node. */
960
    node_id = MCAPI_GET16(buffer, MCAPI_CNCT_REQ_NODE);
961
 
962
    /* Get the requestor port. */
963
    port_id = MCAPI_GET16(buffer, MCAPI_CNCT_REQ_PORT);
964
 
965
    /* Set the error message in the packet. */
966
    MCAPI_PUT32(buffer, MCAPI_CNCT_STATUS, status);
967
 
968
    /* Set the type to response. */
969
    MCAPI_PUT16(buffer, MCAPI_PROT_TYPE, MCAPI_CONNECT_RESPONSE);
970
 
971
    /* Send the error response to the requestor. */
972
    msg_send(MCAPI_CTRL_TX_Endp,
973
             mcapi_encode_endpoint(node_id, port_id),
974
             buffer, MCAPI_CONNECT_MSG_LEN,
975
             MCAPI_DEFAULT_PRIO,
976
             &request, &mcapi_status, 0xffffffff);
977
 
978
}
979
 
980
/*************************************************************************
981
*
982
*   FUNCTION
983
*
984
*       mcapi_tx_response
985
*
986
*   DESCRIPTION
987
*
988
*       Transmits a response to a foreign node for a pending request.
989
*
990
*   INPUTS
991
*
992
*       *node_data              A pointer to the global MCAPI node data
993
*                               structure.
994
*       *request                The request structure associated with the
995
*                               foreign node to resume.
996
*
997
*   OUTPUTS
998
*
999
*       None.
1000
*
1001
*************************************************************************/
1002
void mcapi_tx_response(MCAPI_GLOBAL_DATA *node_data, mcapi_request_t *request)
1003
{
1004
    mcapi_status_t      tx_status;
1005
    mcapi_endpoint_t    remote_endp;
1006
    mcapi_request_t     tx_request;
1007
    unsigned char       buffer[MCAPI_GET_ENDP_LEN];
1008
 
1009
    /* If the get request was successful, send the response. */
1010
    if (request->mcapi_status != MCAPI_ERR_REQUEST_CANCELLED)
1011
    {
1012
        MCAPI_PUT16(buffer, MCAPI_PROT_TYPE,  MCAPI_GETENDP_RESPONSE);
1013
 
1014
        /* Set the status. */
1015
        MCAPI_PUT32(buffer, MCAPI_GETENDP_STATUS, request->mcapi_status);
1016
    }
1017
 
1018
    /* If the get request is being canceled, send a cancel message. */
1019
    else
1020
    {
1021
        MCAPI_PUT16(buffer, MCAPI_PROT_TYPE,  MCAPI_CANCEL_MSG);
1022
    }
1023
 
1024
    /* Put the target port in the buffer. */
1025
    MCAPI_PUT16(buffer, MCAPI_GETENDP_PORT, request->mcapi_target_port_id);
1026
 
1027
    remote_endp = mcapi_encode_endpoint(request->mcapi_requesting_node_id,
1028
                                        request->mcapi_requesting_port_id);
1029
 
1030
    /* Put the target endpoint in the packet. */
1031
    MCAPI_PUT32(buffer, MCAPI_GETENDP_ENDP,
1032
                mcapi_encode_endpoint(MCAPI_Node_ID,
1033
                request->mcapi_target_port_id));
1034
 
1035
    /* Send the packet back to the caller. */
1036
    msg_send(MCAPI_CTRL_TX_Endp, remote_endp, buffer, MCAPI_GET_ENDP_LEN,
1037
             MCAPI_DEFAULT_PRIO, &tx_request, &tx_status,
1038
             0xffffffff);
1039
 
1040
}
1041
 
1042
/*************************************************************************
1043
*
1044
*   FUNCTION
1045
*
1046
*       mcapi_rx_data
1047
*
1048
*   DESCRIPTION
1049
*
1050
*       Process incoming data from driver level interfaces.
1051
*
1052
*   INPUTS
1053
*
1054
*       None.
1055
*
1056
*   OUTPUTS
1057
*
1058
*       None.
1059
*
1060
*************************************************************************/
1061
void mcapi_rx_data(void)
1062
{
1063
    MCAPI_ENDPOINT      *endp_ptr;
1064
    MCAPI_BUFFER        *mcapi_buf_ptr;
1065
    MCAPI_GLOBAL_DATA   *node_data;
1066
    mcapi_int_t         cookie;
1067
    mcapi_node_t        dest_node;
1068
    mcapi_port_t        dest_port;
1069
    int                 i;
1070
 
1071
    mcapi_lock_node_data();
1072
 
1073
    /* Get a pointer to the global node list. */
1074
    node_data = mcapi_get_node_data();
1075
 
1076
    for (i = 0; i < MCAPI_PRIO_COUNT; i++)
1077
    {
1078
        /* Process all data on the incoming receive queue. */
1079
        while (MCAPI_RX_Queue[i].head)
1080
        {
1081
            /* Disable interrupts - the HISR could add to this queue
1082
             * while we remove from it.
1083
             */
1084
            cookie = MCAPI_Lock_RX_Queue();
1085
 
1086
            /* Pull the buffer off the queue. */
1087
            mcapi_buf_ptr = mcapi_dequeue(&MCAPI_RX_Queue[i]);
1088
 
1089
            /* Restore interrupts to the previous level. */
1090
            MCAPI_Unlock_RX_Queue(cookie);
1091
 
1092
            /* Extract the destination node. */
1093
            dest_node =
1094
                MCAPI_GET16(mcapi_buf_ptr->buf_ptr, MCAPI_DEST_NODE_OFFSET);
1095
 
1096
            /* Extract the destination port. */
1097
            dest_port =
1098
                MCAPI_GET16(mcapi_buf_ptr->buf_ptr, MCAPI_DEST_PORT_OFFSET);
1099
 
1100
            /* Decode message header and obtain RX endpoint */
1101
            endp_ptr =
1102
                mcapi_find_local_endpoint(node_data, dest_node, dest_port);
1103
 
1104
            /* If the packet is for this node. */
1105
            if (endp_ptr)
1106
            {
1107
                /* Enqueue the new buffer onto the receive queue for
1108
                 * the endpoint.
1109
                 */
1110
                mcapi_enqueue(&endp_ptr->mcapi_rx_queue, mcapi_buf_ptr);
1111
 
1112
                /* Check if any tasks are waiting to receive data on this
1113
                 * endpoint.
1114
                 */
1115
                mcapi_check_resume(MCAPI_REQ_RX_FIN,
1116
                                   endp_ptr->mcapi_endp_handle, endp_ptr,
1117
                                   mcapi_buf_ptr->buf_size - MCAPI_HEADER_LEN,
1118
                                   MCAPI_SUCCESS);
1119
            }
1120
 
1121
            else
1122
#if (MCAPI_ENABLE_FORWARDING == 1)
1123
            {
1124
                /* Attempt to forward the packet. */
1125
                mcapi_forward(node_data, mcapi_buf_ptr, dest_node);
1126
            }
1127
#else
1128
            {
1129
                /* The packet is not destined for this node, and forwarding
1130
                 * capabilities are disabled.
1131
                 */
1132
                ((MCAPI_INTERFACE*)(mcapi_buf_ptr->mcapi_dev_ptr))->
1133
                    mcapi_recover_buffer(mcapi_buf_ptr);
1134
            }
1135
#endif
1136
        }
1137
    }
1138
 
1139
    /* Release the lock. */
1140
    mcapi_unlock_node_data();
1141
 
1142
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.