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/] [mcapi_transport_hibi_fdev/] [1.0/] [src/] [trans_hibi_fdev.c] - Blame information for rev 175

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 172 lanttu
// **************************************************************************
2
// File             : trans_hibi_fdev.c
3
// Author           : matilail
4
// Date             : 10.04.2013
5
// Decription       : MCAPI transport layer implementation for NIOS II
6
//                                        With hibi_pe_dma file device
7
//                    (modified from The Multicore Association example
8
//                    shared memory implementation)
9
// **************************************************************************
10
 
11
 
12
 
13
/*
14
Copyright (c) 2008, The Multicore Association
15
All rights reserved.
16
 
17
Redistribution and use in source and binary forms, with or without
18
modification, are permitted provided that the following conditions are
19
met:
20
(1) Redistributions of source code must retain the above copyright
21
notice, this list of conditions and the following disclaimer.
22
 
23
(2) Redistributions in binary form must reproduce the above copyright
24
notice, this list of conditions and the following disclaimer in the
25
documentation and/or other materials provided with the distribution.
26
 
27
(3) Neither the name of the Multicore Association nor the names of its
28
contributors may be used to endorse or promote products derived from
29
this software without specific prior written permission.
30
 
31
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
32
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
33
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
34
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
35
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
37
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
38
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
39
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
*/
43
 
44
 
45
 
46
 
47
 
48
 
49
 
50
#include <string.h> /* for memcpy */
51
#include <assert.h> /* for assertions */
52
#include <stdio.h>
53
#include <unistd.h>
54
#include <fcntl.h>
55
#include <stdio.h>
56
#include <sys/ioctl.h>
57
#include <stddef.h>  /* for size_t */
58
#include "includes.h"
59
 
60
#include "mcapi_trans.h" /* the transport API */
61
#include "trans_hibi_fdev.h"
62
 
63
#include <hibi_pe_dma_defines.h>
64
 
65
#include "hibi_mappings.h"
66
 
67
//////////////////////////////////////////////////////////////////////////////
68
//                                                                          //
69
//                   Constants and defines                                  //
70
//                                                                          //
71
//////////////////////////////////////////////////////////////////////////////
72
#define MAGIC_NUM 0xdeadcafe
73
#define MSG_HEADER 1
74
#define MSG_PORT 0
75
 
76
 
77
 
78
 
79
//////////////////////////////////////////////////////////////////////////////
80
//                                                                          //
81
//                   Function prototypes (private)                          //
82
//                                                                          //
83
//////////////////////////////////////////////////////////////////////////////   
84
 
85
 
86
mcapi_boolean_t mcapi_trans_decode_handle_internal (uint32_t handle, uint16_t *node_index,
87
                                           uint16_t *endpoint_index);
88
 
89
uint32_t mcapi_trans_encode_handle_internal (uint16_t node_index,uint16_t endpoint_index);
90
 
91
void mcapi_trans_signal_handler ( int sig );
92
 
93
mcapi_boolean_t mcapi_trans_add_node (mcapi_uint_t node_num);
94
 
95
mcapi_boolean_t mcapi_trans_send_internal (uint16_t sn,uint16_t se, uint16_t rn, uint16_t re,
96
                                  char* buffer, size_t buffer_size,mcapi_boolean_t blocking,uint64_t scalar);
97
 
98
mcapi_boolean_t mcapi_trans_recv_internal (uint16_t rn, uint16_t re, void** buffer, size_t buffer_size,
99
                                  size_t* received_size,mcapi_boolean_t blocking,uint64_t* scalar);
100
 
101
void mcapi_trans_recv_internal_ (uint16_t rn, uint16_t re, void** buffer, size_t buffer_size,
102
                                size_t* received_size,int qindex,uint64_t* scalar);
103
 
104
mcapi_boolean_t mcapi_trans_get_endpoint_internal (mcapi_endpoint_t *e, mcapi_uint_t node_num,
105
                                                   mcapi_uint_t port_num);
106
 
107
void mcapi_trans_open_channel_internal (uint16_t n, uint16_t e);
108
 
109
void mcapi_trans_close_channel_internal (uint16_t n, uint16_t e);
110
 
111
void mcapi_trans_connect_channel_internal (mcapi_endpoint_t send_endpoint, mcapi_endpoint_t receive_endpoint,
112
                                  channel_type type);
113
void setup_request_internal (mcapi_endpoint_t* endpoint,mcapi_request_t* request,mcapi_status_t* mcapi_status,
114
                  mcapi_boolean_t completed, size_t size,void** buffer,mcapi_request_type type);
115
 
116
void check_receive_request (mcapi_request_t *request);
117
 
118
void cancel_receive_request (mcapi_request_t *request);
119
 
120
void check_get_endpt_request (mcapi_request_t *request);
121
 
122
void check_open_request (mcapi_request_t *request);
123
 
124
int get_private_data_index ();
125
 
126
mcapi_boolean_t mcapi_trans_get_node_index(mcapi_uint_t n);
127
 
128
void mcapi_trans_display_state_internal (void* handle);
129
 
130
/* queue management */
131
void print_queue (queue q);
132
 
133
int mcapi_trans_pop_queue (queue *q);
134
 
135
int mcapi_trans_push_queue (queue *q);
136
 
137
mcapi_boolean_t mcapi_trans_empty_queue (queue q);
138
 
139
mcapi_boolean_t mcapi_trans_full_queue (queue q);
140
 
141
void mcapi_trans_compact_queue (queue* q);
142
 
143
mcapi_boolean_t mcapi_trans_create_endpoint_(mcapi_endpoint_t* ep, mcapi_uint_t node_num, mcapi_uint_t port_num,
144
                                             mcapi_boolean_t anonymous);
145
 
146
void transport_sm_yield_internal();
147
 
148
 
149
 
150
void mcapi_trans_initialize_database();
151
 
152
//////////////////////////////////////////////////////////////////////////////
153
//                                                                          //
154
//                   Data                                                   //
155
//                                                                          //
156
//////////////////////////////////////////////////////////////////////////////
157
 
158
/* Database for store endpoint and channel information */
159
mcapi_database c_db_impl;
160
mcapi_database* c_db = &c_db_impl;
161
 
162
/* the debug level */
163
int mcapi_debug = 0;
164
 
165
/* global my node id number */
166
mcapi_uint_t my_node_id = 255;
167
 
168 175 lanttu
int cfg_fdev = 0;
169 172 lanttu
//int cpu0_dev;
170
 
171 175 lanttu
typedef struct {
172
  mcapi_endpoint_t recv_ep;
173
  int pkt_fdev;
174
} pkt_chan;
175
 
176
typedef struct {
177
  mcapi_endpoint_t recv_ep;
178
  int scl_fdev;
179
} scl_chan;
180
 
181
 
182
 
183
pkt_chan pkt_channels[MAX_CHANNELS];
184
scl_chan scl_channels[MAX_CHANNELS];
185
 
186
 
187
 
188
int scl_chan_idx, pkt_chan_idx  = 0;
189
 
190 172 lanttu
//////////////////////////////////////////////////////////////////////////////
191
//                                                                          //
192
//                   mcapi_trans API                                        //
193
//                                                                          //
194
//////////////////////////////////////////////////////////////////////////////
195
/***************************************************************************
196
  NAME: mcapi_trans_get_node_num
197
  DESCRIPTION: gets the node_num (not the transport's node index!)
198
  PARAMETERS: node_num: the node_num pointer to be filled in
199
  RETURN VALUE: boolean indicating success (the node num was found) or failure
200
   (couldn't find the node num).
201
***************************************************************************/
202
mcapi_boolean_t mcapi_trans_get_node_num(mcapi_uint_t* node)
203
{
204
  //int i;
205
 
206
  /* the database does not need to be locked, but it's okay if it is */
207
  /* The database is locked whenever d[i].pid is set.  Here, we're just
208
     reading it. */
209
 
210
  //i = get_private_data_index();
211
 
212
 
213
  //if (d[i].pid == 0) {
214
  // return MCAPI_FALSE;
215
  //} else {
216
  // *node = d[i].node_num;
217
  //}
218
  *node = my_node_id; //LM
219
  return MCAPI_TRUE;
220
}
221
 
222
 
223
/***************************************************************************
224
  NAME: mcapi_trans_initialize    OK
225
  DESCRIPTION: initializes the transport layer
226
  PARAMETERS: node_num: the node number
227
  RETURN VALUE: boolean: success or failure
228
***************************************************************************/
229
mcapi_boolean_t mcapi_trans_initialize(mcapi_uint_t node_num)
230
{
231 175 lanttu
 
232 172 lanttu
        mcapi_boolean_t rc = MCAPI_TRUE;
233
 
234
        mcapi_trans_initialize_database();
235
 
236
        //rc = mcapi_trans_initialize_();
237
        if (rc) {
238
                /* add the node */
239
                rc = mcapi_trans_add_node(node_num);
240
        }
241
 
242
 
243
        my_node_id = node_num;
244 175 lanttu
 
245
        // open file device for receiving channel configurations
246
        cfg_fdev = open(dev_names[my_node_id], O_RDWR, 0x700);
247
        ioctl(cfg_fdev,SET_HIBI_RX_ADDR, (void*) (hibiEndAddresses[my_node_id] ));
248
        ioctl(cfg_fdev,SET_HIBI_RX_PACKETS,(void*) 4);
249
        ioctl(cfg_fdev,SET_HIBI_RX_BLOCKING,(void*) HIBI_READ_BLOCKING_MODE);
250 172 lanttu
 
251 175 lanttu
        //create task to poll this
252
 
253
 
254
        //printf("opening devices \n");
255
        /*for(i = 0; i < FDEV_COUNT ; i++)
256 172 lanttu
        {
257
                fdevs[i] = open(dev_names[i], O_RDWR, 0x700);
258
                if (fdevs[i] == -1) rc = MCAPI_FALSE;
259
 
260
        }
261 175 lanttu
*/
262 172 lanttu
  return rc;
263
}
264
 
265
/***************************************************************************
266
  NAME: mcapi_trans_initialize_database
267
  DESCRIPTION: Initializes the global mcapi_database structure. Does not
268
               initialize buffer contents, but other variables are
269
               initialized.
270
  PARAMETERS: -
271
  RETURN VALUE: -
272
***************************************************************************/
273
/**
274
 * NOTICE: The mcapi_database can be *huge* depending on the defines in
275
 * mcapi_config.h. If the processor's data memory is too small for the
276
 * database, this function *will* overwrite heap, stack and/or other
277
 * variables. You have been warned.
278
 */
279
void mcapi_trans_initialize_database() {
280
 
281
  /* initialize the whole mcapi_database */
282
  int i = 0;
283
  c_db->num_nodes = 0;
284
  for (i = 0; i < MAX_NODES; i++) {
285
      int j = 0;
286
      node_entry* node = &(c_db->nodes[i]);
287
      node->node_num = 0;
288
      node->finalized = MCAPI_FALSE; /* TODO: is this the correct value? */
289
      node->valid = MCAPI_FALSE;
290
      node->node_d.num_endpoints = 0;
291
      for (j = 0; j < MAX_ENDPOINTS; j++) {
292
          int k = 0;
293
          endpoint_entry* end = &(node->node_d.endpoints[j]);
294
          end->port_num = 0;
295
          end->valid = MCAPI_FALSE;
296
          end->anonymous = MCAPI_FALSE;
297
          end->open = MCAPI_FALSE;
298
          end->connected = MCAPI_FALSE;
299
          end->num_attributes = 0;
300
          for (k = 0; k < MAX_ATTRIBUTES; k++) {
301
              attribute_entry* attr = &(end->attributes[k]);
302
              attr->valid = MCAPI_FALSE;
303
              attr->attribute_num = 0;
304
              attr->bytes = 0;
305
              attr->attribute_d = NULL;
306
          }
307
          queue* epQueue = &(end->recv_queue);
308
          epQueue->send_endpt = 0;
309
          epQueue->recv_endpt = 0;
310
          epQueue->channel_type = 0;
311
          epQueue->num_elements = 0;
312
          epQueue->head = 0;
313
          epQueue->tail = 0;
314
          for (k = 0; k < MAX_QUEUE_ENTRIES; k++) {
315
              buffer_descriptor* bufferDesc = &(epQueue->elements[k]);
316
              bufferDesc->request = 0;
317
              bufferDesc->b = 0;
318
              bufferDesc->invalid = MCAPI_FALSE;
319
          }
320
      }
321
  }
322
  for (i = 0; i < MAX_BUFFERS; i++) {
323
      buffer_entry* buffer = &(c_db->buffers[i]);
324
      buffer->magic_num = 0;
325
      buffer->size = 0;
326
      buffer->in_use = MCAPI_FALSE;
327
#ifndef __TCE__
328
      buffer->scalar = 0;
329
#else
330
      buffer->scalar.hi = 0;
331
      buffer->scalar.lo = 0;
332
#endif
333
  }
334
}
335
 
336
/***************************************************************************
337
  NAME:mcapi_trans_finalize TODO: file_dev
338
  DESCRIPTION: cleans up the semaphore and shared memory resources.
339
  PARAMETERS: none
340
  RETURN VALUE: boolean: success or failure
341
***************************************************************************/
342
mcapi_boolean_t mcapi_trans_finalize ()
343
{
344
        int i = 0;
345
 
346
        // close file devices
347
        for(i = 0; i < FDEV_COUNT; i++)
348
        {
349
                close(fdevs[i]);
350
        }
351
 
352
 
353
        return MCAPI_TRUE;
354
}
355
 
356
 
357
 
358
//////////////////////////////////////////////////////////////////////////////
359
//                                                                          //
360
//                   mcapi_trans API: error checking routines               //
361
//                                                                          //
362
//////////////////////////////////////////////////////////////////////////////
363
/***************************************************************************
364
  NAME: mcapi_trans_channel_type OK
365
  DESCRIPTION: Given an endpoint, returns the type of channel (if any)
366
   associated with it.
367
  PARAMETERS: endpoint: the endpoint to be checked
368
  RETURN VALUE: the type of the channel (pkt,scalar or none)
369
***************************************************************************/
370
channel_type mcapi_trans_channel_type (mcapi_endpoint_t endpoint)
371
 {
372
  uint16_t n,e;
373
  int rc;
374
  mcapi_boolean_t rv = MCAPI_FALSE;
375
 
376
  /* lock the database */
377
  //mcapi_trans_access_database_pre();
378
 
379
  rv = mcapi_trans_decode_handle_internal(endpoint,&n,&e);
380
  //assert(rv);
381
  rc = c_db->nodes[n].node_d.endpoints[e].recv_queue.channel_type;
382
 
383
  /* unlock the database */
384
  //mcapi_trans_access_database_post();
385
 
386
  return rc;
387
}
388
 
389
/***************************************************************************
390
  NAME:mcapi_trans_send_endpoint OK
391
  DESCRIPTION:checks if the given endpoint is a send endpoint
392
  PARAMETERS: endpoint: the endpoint to be checked
393
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
394
***************************************************************************/
395
mcapi_boolean_t mcapi_trans_send_endpoint (mcapi_endpoint_t endpoint)
396
{
397
  uint16_t n,e;
398
  int rc = MCAPI_TRUE;
399
  mcapi_boolean_t rv = MCAPI_FALSE;
400
 
401
  /* lock the database */
402
  // mcapi_trans_access_database_pre();
403
 
404
  rv = mcapi_trans_decode_handle_internal(endpoint,&n,&e);
405
  //assert(rv);
406
  if ((c_db->nodes[n].node_d.endpoints[e].connected) &&
407
      (c_db->nodes[n].node_d.endpoints[e].recv_queue.recv_endpt == endpoint)) {
408
   /* this endpoint has already been marked as a receive endpoint */
409
    mcapi_dprintf(2," mcapi_trans_send_endpoint ERROR: this endpoint (%x) has already been connected as a receive endpoint\n",
410
                  endpoint);
411
    rc = MCAPI_FALSE;
412
  }
413
 
414
  /* unlock the database */
415
  //mcapi_trans_access_database_post();
416
 
417
  return rc;
418
}
419
 
420
/***************************************************************************
421
  NAME: mcapi_trans_recv_endpoint OK
422
  DESCRIPTION:checks if the given endpoint can be or is already a receive endpoint
423
  PARAMETERS: endpoint: the endpoint to be checked
424
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
425
***************************************************************************/
426
mcapi_boolean_t mcapi_trans_recv_endpoint (mcapi_endpoint_t endpoint)
427
{
428
  uint16_t n,e;
429
  int rc = MCAPI_TRUE;
430
  mcapi_boolean_t rv = MCAPI_FALSE;
431
 
432
  /* lock the database */
433
  //mcapi_trans_access_database_pre();
434
 
435
  rv = mcapi_trans_decode_handle_internal(endpoint,&n,&e);
436
  //assert(rv);
437
  if ((c_db->nodes[n].node_d.endpoints[e].connected) &&
438
      (c_db->nodes[n].node_d.endpoints[e].recv_queue.send_endpt == endpoint)) {
439
   /* this endpoint has already been marked as a send endpoint */
440
    mcapi_dprintf(2," mcapi_trans_recv_endpoint ERROR: this endpoint (%x) has already been connected as a send endpoint\n",
441
                  endpoint);
442
    rc = MCAPI_FALSE;
443
  }
444
 
445
  /* unlock the database */
446
  //mcapi_trans_access_database_post();
447
 
448
  return rc;
449
}
450
 
451
/***************************************************************************
452
  NAME:mcapi_trans_valid_port OK
453
  DESCRIPTION:checks if the given port_num is a valid port_num for this system
454
  PARAMETERS: port_num: the port num to be checked
455
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
456
***************************************************************************/
457
mcapi_boolean_t mcapi_trans_valid_port(mcapi_uint_t port_num)
458
{
459
  return MCAPI_TRUE;
460
}
461
 
462
/***************************************************************************
463
  NAME:mcapi_trans_valid_node   OK
464
  DESCRIPTION: checks if the given node_num is a valid node_num for this system
465
  PARAMETERS: node_num: the node num to be checked
466
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
467
***************************************************************************/
468
mcapi_boolean_t mcapi_trans_valid_node(mcapi_uint_t node_num)
469
{
470
  return MCAPI_TRUE;
471
}
472
 
473
/***************************************************************************
474
  NAME: mcapi_trans_valid_endpoint  OK
475
  DESCRIPTION: checks if the given endpoint handle refers to a valid endpoint
476
  PARAMETERS: endpoint
477
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
478
***************************************************************************/
479
mcapi_boolean_t mcapi_trans_valid_endpoint (mcapi_endpoint_t endpoint)
480
{
481
  uint16_t n,e;
482
  int rc = MCAPI_FALSE;
483
 
484
  /* lock the database */
485
  //  mcapi_trans_access_database_pre();
486
 
487
  if (mcapi_trans_decode_handle_internal(endpoint,&n,&e)) {
488
    rc = c_db->nodes[n].node_d.endpoints[e].valid;
489
  }
490
 
491
  mcapi_dprintf(3,"mcapi_trans_valid_endpoint endpoint=0x%lx (database indices: n=%d,e=%d) rc=%d\n",endpoint,n,e,rc);
492
 
493
  /* unlock the database */
494
  //  mcapi_trans_access_database_post();
495
 
496
  return rc;
497
}
498
 
499
/***************************************************************************
500
  NAME: mcapi_trans_endpoint_exists OK
501
  DESCRIPTION: checks if an endpoint has been created for this port id
502
  PARAMETERS: port id
503
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
504
***************************************************************************/
505
mcapi_boolean_t mcapi_trans_endpoint_exists (uint32_t port_num)
506
{
507
  uint32_t n,i,node_num;
508
  int rc = MCAPI_FALSE;
509
  mcapi_boolean_t rv = MCAPI_FALSE;
510
 
511
  if (port_num == MCAPI_PORT_ANY) {
512
    return rc;
513
  }
514
 
515
  /* lock the database */
516
  //mcapi_trans_access_database_pre();
517
 
518
  rv = mcapi_trans_get_node_num(&node_num);
519
  //assert(rv);
520
  n = mcapi_trans_get_node_index(node_num);
521
 
522
  /* Note: we can't just iterate for i < num_endpoints because endpoints can
523
     be deleted which would fragment the endpoints array. */
524
  for (i = 0; i < MAX_ENDPOINTS; i++) {
525
    if (c_db->nodes[n].node_d.endpoints[i].valid &&
526
        c_db->nodes[n].node_d.endpoints[i].port_num == port_num) {
527
      rc = MCAPI_TRUE;
528
      break;
529
    }
530
  }
531
 
532
  /* unlock the database */
533
  //mcapi_trans_access_database_post();
534
 
535
  return rc;
536
}
537
 
538
/***************************************************************************
539
  NAME: mcapi_trans_valid_endpoints OK
540
  DESCRIPTION: checks if the given endpoint handles refer to valid endpoints
541
  PARAMETERS: endpoint1, endpoint2
542
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
543
***************************************************************************/
544
mcapi_boolean_t mcapi_trans_valid_endpoints (mcapi_endpoint_t endpoint1,
545
                                             mcapi_endpoint_t endpoint2)
546
{
547
  uint16_t n1,e1;
548
  uint16_t n2,e2;
549
  mcapi_boolean_t rc = MCAPI_FALSE;
550
 
551
  /* lock the database */
552
  //mcapi_trans_access_database_pre();
553
 
554
  // decode_internal already tests for validity.
555
  if (mcapi_trans_decode_handle_internal(endpoint1,&n1,&e1) &&
556
      mcapi_trans_decode_handle_internal(endpoint2,&n2,&e2)) {
557
    rc = MCAPI_TRUE;
558
  }
559
 
560
  /* unlock the database */
561
  //  mcapi_trans_access_database_post();
562
 
563
  return rc;
564
}
565
 
566
/***************************************************************************
567
  NAME:mcapi_trans_pktchan_recv_isopen  OK
568
  DESCRIPTION:checks if the channel is open for a given handle
569
  PARAMETERS: receive_handle
570
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
571
***************************************************************************/
572
mcapi_boolean_t mcapi_trans_pktchan_recv_isopen (mcapi_pktchan_recv_hndl_t receive_handle)
573
 {
574
  uint16_t n,e;
575
  int rc = MCAPI_FALSE;
576
  mcapi_boolean_t rv = MCAPI_FALSE;
577
 
578
  /* lock the database */
579
  //  mcapi_trans_access_database_pre();
580
 
581
  rv = mcapi_trans_decode_handle_internal(receive_handle,&n,&e);
582
  //assert(rv);
583
  rc = (c_db->nodes[n].node_d.endpoints[e].open);
584
 
585
    /* unlock the database */
586
  // mcapi_trans_access_database_post();
587
 
588
  return rc;
589
}
590
 
591
 
592
/***************************************************************************
593
  NAME:mcapi_trans_pktchan_send_isopen OK
594
  DESCRIPTION:checks if the channel is open for a given handle
595
  PARAMETERS: send_handle
596
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
597
***************************************************************************/
598
mcapi_boolean_t mcapi_trans_pktchan_send_isopen (mcapi_pktchan_send_hndl_t send_handle)
599
 {
600
  uint16_t n,e;
601
  int rc = MCAPI_FALSE;
602
  mcapi_boolean_t rv = MCAPI_FALSE;
603
 
604
  /* lock the database */
605
  //mcapi_trans_access_database_pre();
606
 
607
  rv = mcapi_trans_decode_handle_internal(send_handle,&n,&e);
608
  //assert(rv);
609
  rc =  (c_db->nodes[n].node_d.endpoints[e].open);
610
 
611
  /* unlock the database */
612
  //mcapi_trans_access_database_post();
613
 
614
  return rc;
615
}
616
 
617
/***************************************************************************
618
  NAME:mcapi_trans_sclchan_recv_isopen OK
619
  DESCRIPTION:checks if the channel is open for a given handle
620
  PARAMETERS: receive_handle
621
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
622
***************************************************************************/
623
mcapi_boolean_t mcapi_trans_sclchan_recv_isopen (mcapi_sclchan_recv_hndl_t receive_handle)
624
 {
625
  uint16_t n,e;
626
  int rc = MCAPI_FALSE;
627
  mcapi_boolean_t rv = MCAPI_FALSE;
628
 
629
  /* lock the database */
630
  //mcapi_trans_access_database_pre();
631
 
632
  rv = mcapi_trans_decode_handle_internal(receive_handle,&n,&e);
633
  //assert(rv);
634
  rc = (c_db->nodes[n].node_d.endpoints[e].open);
635
 
636
  /* unlock the database */
637
  //mcapi_trans_access_database_post();
638
 
639
  return rc;
640
}
641
 
642
/***************************************************************************
643
  NAME:mcapi_trans_sclchan_send_isopen OK
644
  DESCRIPTION:checks if the channel is open for a given handle
645
  PARAMETERS: send_handle
646
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
647
***************************************************************************/
648
mcapi_boolean_t mcapi_trans_sclchan_send_isopen (mcapi_sclchan_send_hndl_t send_handle)
649
 {
650
  uint16_t n,e;
651
  int rc = MCAPI_FALSE;
652
  mcapi_boolean_t rv = MCAPI_FALSE;
653
 
654
  /* lock the database */
655
  // mcapi_trans_access_database_pre();
656
 
657
  rv = mcapi_trans_decode_handle_internal(send_handle,&n,&e);
658
  //assert(rv);
659
  rc = (c_db->nodes[n].node_d.endpoints[e].open);
660
 
661
    /* unlock the database */
662
  // mcapi_trans_access_database_post();
663
 
664
  return rc;
665
}
666
 
667
/***************************************************************************
668
  NAME:mcapi_trans_endpoint_channel_isopen  OK
669
  DESCRIPTION:checks if a channel is open for a given endpoint
670
  PARAMETERS: endpoint
671
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
672
***************************************************************************/
673
mcapi_boolean_t mcapi_trans_endpoint_channel_isopen (mcapi_endpoint_t endpoint)
674
{
675
  uint16_t n,e;
676
  int rc = MCAPI_FALSE;
677
  mcapi_boolean_t rv = MCAPI_FALSE;
678
 
679
  /* lock the database */
680
  // mcapi_trans_access_database_pre();
681
 
682
  rv = mcapi_trans_decode_handle_internal(endpoint,&n,&e);
683
  //assert(rv);
684
  rc =  (c_db->nodes[n].node_d.endpoints[e].open);
685
 
686
  /* unlock the database */
687
  // mcapi_trans_access_database_post();
688
 
689
  return rc;
690
}
691
 
692
/***************************************************************************
693
  NAME:mcapi_trans_endpoint_isowner  OK
694
  DESCRIPTION:checks if the given endpoint is owned by the calling node
695
  PARAMETERS: endpoint
696
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
697
***************************************************************************/
698
mcapi_boolean_t mcapi_trans_endpoint_isowner (mcapi_endpoint_t endpoint)
699
{
700
  uint16_t n,e;
701
  mcapi_uint_t node_num;
702
  int rc = MCAPI_FALSE;
703
  mcapi_boolean_t rv = MCAPI_FALSE;
704
 
705
  rv = mcapi_trans_get_node_num(&node_num);
706
  //assert(rv);
707
 
708
  /* lock the database */
709
  // mcapi_trans_access_database_pre();
710
 
711
  rv = mcapi_trans_decode_handle_internal(endpoint,&n,&e);
712
  //assert(rv);
713
  rc = ((c_db->nodes[n].node_d.endpoints[e].valid) &&
714
          (c_db->nodes[n].node_num == node_num));
715
 
716
  /* unlock the database */
717
  // mcapi_trans_access_database_post();
718
  return rc;
719
}
720
 
721
/***************************************************************************
722
  NAME:mcapi_trans_channel_connected   OK
723
  DESCRIPTION:checks if the given endpoint channel is connected
724
  PARAMETERS: endpoint
725
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
726
***************************************************************************/
727
mcapi_boolean_t mcapi_trans_channel_connected (mcapi_endpoint_t endpoint)
728
{
729
   uint16_t n,e;
730
   int rc = MCAPI_FALSE;
731
   mcapi_boolean_t rv = MCAPI_FALSE;
732
 
733
  /* lock the database */
734
  // mcapi_trans_access_database_pre();
735
 
736
   rv = mcapi_trans_decode_handle_internal(endpoint,&n,&e);
737
  //assert(rv);
738
  rc = ((c_db->nodes[n].node_d.endpoints[e].valid) &&
739
        (c_db->nodes[n].node_d.endpoints[e].connected));
740
 
741
  /* unlock the database */
742
  // mcapi_trans_access_database_post();
743
  return rc;
744
}
745
 
746
/***************************************************************************
747
  NAME:mcapi_trans_compatible_endpoint_attributes OK
748
  DESCRIPTION:checks if the given endpoints have compatible attributes
749
  PARAMETERS: send_endpoint,recv_endpoint
750
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
751
***************************************************************************/
752
mcapi_boolean_t mcapi_trans_compatible_endpoint_attributes (mcapi_endpoint_t send_endpoint,
753
                                                             mcapi_endpoint_t recv_endpoint)
754
{
755
  /* FIXME: (errata A3) currently un-implemented */
756
  return MCAPI_TRUE;
757
}
758
 
759
/***************************************************************************
760
  NAME:mcapi_trans_valid_pktchan_send_handle Ok
761
  DESCRIPTION:checks if the given pkt channel send handle is valid
762
  PARAMETERS: handle
763
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
764
***************************************************************************/
765
mcapi_boolean_t mcapi_trans_valid_pktchan_send_handle( mcapi_pktchan_send_hndl_t handle)
766
 {
767
  uint16_t n,e;
768
  channel_type type;
769
 
770
  int rc = MCAPI_FALSE;
771
 
772
  /* lock the database */
773
  // mcapi_trans_access_database_pre();
774
 
775
  type =MCAPI_PKT_CHAN;
776
  if (mcapi_trans_decode_handle_internal(handle,&n,&e)) {
777
    if (c_db->nodes[n].node_d.endpoints[e].recv_queue.channel_type == type) {
778
      rc = MCAPI_TRUE;
779
    } else {
780
      mcapi_dprintf(2," mcapi_trans_valid_pktchan_send_handle node=%d,port=%d returning false channel_type != MCAPI_PKT_CHAN\n",
781
                    c_db->nodes[n].node_num,c_db->nodes[n].node_d.endpoints[e].port_num);
782
    }
783
  }
784
  rc = MCAPI_TRUE;
785
  /* unlock the database */
786
  // mcapi_trans_access_database_post();
787
  return rc;
788
}
789
 
790
/***************************************************************************
791
  NAME:mcapi_trans_valid_pktchan_recv_handle OK
792
  DESCRIPTION:checks if the given pkt channel recv handle is valid
793
  PARAMETERS: handle
794
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
795
***************************************************************************/
796
mcapi_boolean_t mcapi_trans_valid_pktchan_recv_handle( mcapi_pktchan_recv_hndl_t handle)
797
{
798
  uint16_t n,e;
799
  channel_type type;
800
  int rc = MCAPI_FALSE;
801
 
802
  /* lock the database */
803
  // mcapi_trans_access_database_pre();
804
 
805
  type = MCAPI_PKT_CHAN;
806
  if (mcapi_trans_decode_handle_internal(handle,&n,&e)) {
807
    if (c_db->nodes[n].node_d.endpoints[e].recv_queue.channel_type == type) {
808
      rc = MCAPI_TRUE;
809
    } else {
810
      mcapi_dprintf(2," mcapi_trans_valid_pktchan_recv_handle node=%d,port=%d returning false channel_type != MCAPI_PKT_CHAN\n",
811
                    c_db->nodes[n].node_num,c_db->nodes[n].node_d.endpoints[e].port_num);
812
    }
813
  }
814
  rc = MCAPI_TRUE;
815
  /* unlock the database */
816
  // mcapi_trans_access_database_post();
817
  return rc;
818
}
819
 
820
/***************************************************************************
821
  NAME:mcapi_trans_valid_sclchan_send_handle OK
822
  DESCRIPTION: checks if the given scalar channel send handle is valid
823
  PARAMETERS: handle
824
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
825
***************************************************************************/
826
mcapi_boolean_t mcapi_trans_valid_sclchan_send_handle( mcapi_sclchan_send_hndl_t handle)
827
{
828
  uint16_t n,e;
829
  channel_type type;
830
  int rc = MCAPI_FALSE;
831
 
832
  /* lock the database */
833
  // mcapi_trans_access_database_pre();
834
 
835
  type = MCAPI_SCL_CHAN;
836
  if (mcapi_trans_decode_handle_internal(handle,&n,&e)) {
837
    if (c_db->nodes[n].node_d.endpoints[e].recv_queue.channel_type == type) {
838
      rc = MCAPI_TRUE;
839
    } else {
840
      mcapi_dprintf(2," mcapi_trans_valid_sclchan_send_handle node=%d,port=%d returning false channel_type != MCAPI_SCL_CHAN\n",
841
                    c_db->nodes[n].node_num,c_db->nodes[n].node_d.endpoints[e].port_num);
842
    }
843
  }
844
 
845
  /* unlock the database */
846
  // mcapi_trans_access_database_post();
847
 
848
  return rc;
849
}
850
 
851
/***************************************************************************
852
  NAME:mcapi_trans_valid_sclchan_recv_handle OK
853
  DESCRIPTION:checks if the given scalar channel recv handle is valid
854
  PARAMETERS:
855
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
856
***************************************************************************/
857
mcapi_boolean_t mcapi_trans_valid_sclchan_recv_handle( mcapi_sclchan_recv_hndl_t handle)
858
{
859
  uint16_t n,e;
860
  channel_type type;
861
 
862
  int rc = MCAPI_FALSE;
863
 
864
  /* lock the database */
865
  // mcapi_trans_access_database_pre();
866
 
867
  type= MCAPI_SCL_CHAN;
868
  if (mcapi_trans_decode_handle_internal(handle,&n,&e)) {
869
    if (c_db->nodes[n].node_d.endpoints[e].recv_queue.channel_type == type) {
870
      rc = MCAPI_TRUE;
871
    } else {
872
      mcapi_dprintf(2," mcapi_trans_valid_sclchan_recv_handle node=%d,port=%d returning false channel_type != MCAPI_SCL_CHAN\n",
873
                    c_db->nodes[n].node_num,c_db->nodes[n].node_d.endpoints[e].port_num);
874
    }
875
  }
876
 
877
  /* unlock the database */
878
  // mcapi_trans_access_database_post();
879
  return rc;
880
}
881
 
882
/***************************************************************************
883
  NAME: mcapi_trans_initialized OK
884
  DESCRIPTION: checks if the given node_id has called initialize
885
  PARAMETERS: node_id
886
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
887
***************************************************************************/
888
mcapi_boolean_t mcapi_trans_initialized (mcapi_node_t node_id)
889
{
890
  //int i;
891
  mcapi_boolean_t rc = MCAPI_FALSE;
892
 
893
  /* if (mcapi_trans_initialize()) { */
894
/*     /\* lock the database *\/ */
895
/*     // mcapi_trans_access_database_pre_nocheck(); */
896
 
897
/*     for (i = 0; i < MAX_NODES; i++) { */
898
/*       if ((c_db->nodes[i].valid) && (c_db->nodes[i].node_num == node_id)) */
899
/*         rc = MCAPI_TRUE; */
900
/*         break; */
901
/*     } */
902
 
903
/*     /\* unlock the database *\/ */
904
/*     // mcapi_trans_access_database_post_nocheck(); */
905
/*   } */
906
 
907
  return rc;
908
}
909
 
910
/***************************************************************************
911
  NAME: mcapi_trans_num_endpoints OK
912
  DESCRIPTION: returns the current number of endpoints for the calling node
913
  PARAMETERS:  none
914
  RETURN VALUE: num_endpoints
915
***************************************************************************/
916
mcapi_uint32_t mcapi_trans_num_endpoints()
917
{
918
  int rc = 0;
919
  uint32_t node_num,node_index;
920
  mcapi_boolean_t rv = MCAPI_FALSE;
921
 
922
  /* lock the database */
923
  // mcapi_trans_access_database_pre();
924
 
925
  rv = mcapi_trans_get_node_num(&node_num);
926
  //assert(rv);
927
 
928
  node_index = mcapi_trans_get_node_index(node_num);
929
 
930
  rc = c_db->nodes[node_index].node_d.num_endpoints;
931
  /* unlock the database */
932
  // mcapi_trans_access_database_post();
933
 
934
  return rc;
935
}
936
 
937
/***************************************************************************
938
  NAME:mcapi_trans_valid_priority OK
939
  DESCRIPTION:checks if the given priority level is valid
940
  PARAMETERS: priority
941
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
942
***************************************************************************/
943
mcapi_boolean_t mcapi_trans_valid_priority(mcapi_priority_t priority)
944
{
945
  return ((priority >=0) && (priority <= MCAPI_MAX_PRIORITY));
946
}
947
 
948
/***************************************************************************
949
  NAME:mcapi_trans_connected OK
950
  DESCRIPTION: checks if the given endpoint is connected
951
  PARAMETERS: endpoint
952
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
953
***************************************************************************/
954
mcapi_boolean_t mcapi_trans_connected(mcapi_endpoint_t endpoint)
955
{
956
  mcapi_boolean_t rc = MCAPI_FALSE;
957
  uint16_t n,e;
958
  mcapi_boolean_t rv = MCAPI_FALSE;
959
 
960
  /* lock the database */
961
  // mcapi_trans_access_database_pre();
962
  rv = mcapi_trans_decode_handle_internal(endpoint,&n,&e);
963
  //assert(rv);
964
  rc = (c_db->nodes[n].node_d.endpoints[e].recv_queue.channel_type != MCAPI_NO_CHAN);
965
  /* unlock the database */
966
  // mcapi_trans_access_database_post();
967
  return rc;
968
}
969
 
970
/***************************************************************************
971
  NAME:valid_status_param
972
  DESCRIPTION: checks if the given status is a valid status parameter
973
  PARAMETERS: status
974
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
975
***************************************************************************/
976
mcapi_boolean_t valid_status_param (mcapi_status_t* mcapi_status)
977
{
978
  return (mcapi_status != NULL);
979
}
980
 
981
/***************************************************************************
982
  NAME:valid_version_param OK
983
  DESCRIPTION: checks if the given version is a valid version parameter
984
  PARAMETERS: version
985
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
986
***************************************************************************/
987
mcapi_boolean_t valid_version_param (mcapi_version_t* mcapi_version)
988
{
989
  return (mcapi_version != NULL);
990
}
991
 
992
 
993
/***************************************************************************
994
  NAME:valid_buffer_param OK
995
  DESCRIPTION:checks if the given buffer is a valid buffer parameter
996
  PARAMETERS: buffer
997
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
998
***************************************************************************/
999
mcapi_boolean_t valid_buffer_param (void* buffer)
1000
{
1001
  return (buffer != NULL);
1002
}
1003
 
1004
 
1005
/***************************************************************************
1006
  NAME: valid_request_param OK
1007
  DESCRIPTION:checks if the given request is a valid request parameter
1008
  PARAMETERS: request
1009
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
1010
***************************************************************************/
1011
mcapi_boolean_t valid_request_param (mcapi_request_t* request)
1012
{
1013
  return (request != NULL);
1014
}
1015
 
1016
 
1017
/***************************************************************************
1018
  NAME:valid_size_param OK
1019
  DESCRIPTION: checks if the given size is a valid size parameter
1020
  PARAMETERS: size
1021
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE
1022
***************************************************************************/
1023
mcapi_boolean_t valid_size_param (size_t* size)
1024
{
1025
  return (size != NULL);
1026
}
1027
 
1028
//////////////////////////////////////////////////////////////////////////////
1029
//                                                                          //
1030
//                   mcapi_trans API: endpoints                             //
1031
//                                                                          //
1032
//////////////////////////////////////////////////////////////////////////////
1033
/***************************************************************************
1034
  NAME:mcapi_trans_create_endpoint  OK
1035
  DESCRIPTION: This function just looks up the node_num and calls
1036
       mcapi_trans_create_endpoint_.  NOTE: the reason I separated create_endpoint
1037
       into these two functions is because it's useful for the testharness to be
1038
       able to explicitly create multiple nodes and multiple endpoints on those
1039
       nodes within the same process/thread.  This is very useful for testing and
1040
       this decoupling allows that.  See ./tests/valid_endpoint.c.
1041
  PARAMETERS:
1042
       ep - the endpoint to be filled in
1043
       port_num - the port id (only valid if !anonymous)
1044
       anonymous - whether or not this should be an anonymous endpoint
1045
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE indicating success or failure
1046
***************************************************************************/
1047
mcapi_boolean_t mcapi_trans_create_endpoint(mcapi_endpoint_t* ep, mcapi_uint_t port_num,
1048
                                            mcapi_boolean_t anonymous)
1049
{
1050
  mcapi_uint_t node_num;
1051
  mcapi_boolean_t rv = MCAPI_FALSE;
1052
 
1053
  rv = mcapi_trans_get_node_num(&node_num);
1054
  //assert (rv);
1055
  return mcapi_trans_create_endpoint_(ep,node_num,port_num,anonymous);
1056
}
1057
 
1058
/***************************************************************************
1059
  NAME:mcapi_trans_create_endpoint_  OK
1060
  DESCRIPTION:create endpoint <node_num,port_num> and return it's handle
1061
  PARAMETERS:
1062
       ep - the endpoint to be filled in
1063
       port_num - the port id (only valid if !anonymous)
1064
       anonymous - whether or not this should be an anonymous endpoint
1065
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE indicating success or failure
1066
***************************************************************************/
1067
mcapi_boolean_t mcapi_trans_create_endpoint_(mcapi_endpoint_t* ep, mcapi_uint_t node_num, mcapi_uint_t port_num,
1068
                                              mcapi_boolean_t anonymous)
1069
{
1070
  int i, node_index, endpoint_index;
1071
  mcapi_boolean_t rc = MCAPI_FALSE;
1072
 
1073
  node_num = my_node_id;
1074
 
1075
  /* lock the database */
1076
  // mcapi_trans_access_database_pre();
1077
 
1078
  node_index = mcapi_trans_get_node_index (node_num);
1079
 
1080
  /* make sure there's room - mcapi should have already checked this */
1081
  //assert (c_db->nodes[node_index].node_d.num_endpoints < MAX_ENDPOINTS);
1082
 
1083
 
1084
  /* create the endpoint */
1085
  /* find the first available endpoint index */
1086
  endpoint_index = MAX_ENDPOINTS;
1087
  for (i = 0; i < MAX_ENDPOINTS; i++) {
1088
    if (! c_db->nodes[node_index].node_d.endpoints[i].valid) {
1089
      endpoint_index = i;
1090
      break;
1091
    }
1092
  }
1093
 
1094
  //assert(node_index < MAX_NODES);
1095
  //assert(endpoint_index < MAX_ENDPOINTS);
1096
  //assert (c_db->nodes[node_index].node_d.endpoints[endpoint_index].valid == MCAPI_FALSE);
1097
  /* initialize the endpoint entry */
1098
  c_db->nodes[node_index].node_d.endpoints[endpoint_index].valid = MCAPI_TRUE;
1099
  c_db->nodes[node_index].node_d.endpoints[endpoint_index].port_num = port_num;
1100
  c_db->nodes[node_index].node_d.endpoints[endpoint_index].open = MCAPI_FALSE;
1101
  c_db->nodes[node_index].node_d.endpoints[endpoint_index].anonymous = anonymous;
1102
  c_db->nodes[node_index].node_d.endpoints[endpoint_index].num_attributes = 0;
1103
 
1104
  c_db->nodes[node_index].node_d.num_endpoints++;
1105
 
1106
  /* set the handle */
1107
  //*ep = mcapi_trans_encode_handle_internal (node_index,endpoint_index);
1108
 
1109
  *ep = node_num;
1110
  *ep = node_num << 16;
1111
  *ep = *ep | port_num;
1112
  //printf("my_ep=%x\n",*ep);
1113
  //dprintf(" mcapi_trans_create_endpoint (node_num=%x port_num=%d) ep=%x, node_index=%d, endpoint_index=%d\n",
1114
  //            node_num,port_num,*ep,node_index,endpoint_index);
1115
  rc = MCAPI_TRUE;
1116
 
1117
 
1118
  /* unlock the database */
1119
  // mcapi_trans_access_database_post();
1120 175 lanttu
 
1121
  //Open device for local endpoint to receive messages
1122
   //int fdev = 0;
1123
   fdevs[node_num] = open(dev_names[node_num], O_RDWR, 0x700);
1124 172 lanttu
 
1125
  ioctl(fdevs[node_num],SET_HIBI_RX_ADDR,(void*) (hibiBaseAddresses[node_num] | port_num)  );
1126
  ioctl(fdevs[node_num],SET_HIBI_RX_PACKETS,(void*) DEFAULT_MSG_SIZE);
1127
  ioctl(fdevs[node_num],SET_HIBI_RX_BLOCKING,(void*) HIBI_READ_BLOCKING_MODE);
1128
 
1129
  return rc;
1130
}
1131
 
1132
 
1133
/***************************************************************************
1134
  NAME:mcapi_trans_get_endpoint_i
1135
  DESCRIPTION:non-blocking get endpoint for the given <node_num,port_num>
1136
  PARAMETERS:
1137
     endpoint - the endpoint handle to be filled in
1138
     node_num - the node id
1139
     port_num - the port id
1140
     request - the request handle to be filled in when the task is complete
1141
  RETURN VALUE: none
1142
***************************************************************************/
1143
void mcapi_trans_get_endpoint_i( mcapi_endpoint_t* endpoint,mcapi_uint_t node_num,
1144
                                 mcapi_uint_t port_num, mcapi_request_t* request,
1145
                                 mcapi_status_t* mcapi_status)
1146
{
1147
 
1148
  mcapi_boolean_t valid =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_TRUE : MCAPI_FALSE;
1149
  mcapi_boolean_t completed = MCAPI_FALSE;
1150
 
1151
  /* lock the database */
1152
  // mcapi_trans_access_database_pre();
1153
 
1154
  if (valid) {
1155
    /* try to get the endpoint */
1156
    if (mcapi_trans_get_endpoint_internal (endpoint,node_num,port_num)) {
1157
      completed = MCAPI_TRUE;
1158
    } else {
1159
      request->node_num = node_num;
1160
      request->port_num = port_num;
1161
    }
1162
  }
1163
 
1164
  setup_request_internal(endpoint,request,mcapi_status,completed,0,NULL,GET_ENDPT);
1165
 
1166
  /* unlock the database */
1167
   // mcapi_trans_access_database_post();
1168
}
1169
/***************************************************************************
1170
  NAME:mcapi_trans_get_endpoint_internal
1171
  DESCRIPTION:get endpoint for the given <node_num,port_num>
1172
  PARAMETERS:
1173
     endpoint - the endpoint handle to be filled in
1174
     node_num - the node id
1175
     port_num - the port id
1176
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE indicating success or failure
1177
***************************************************************************/
1178
mcapi_boolean_t mcapi_trans_get_endpoint_internal (mcapi_endpoint_t *e, mcapi_uint_t node_num,
1179
                                                   mcapi_uint_t port_num)
1180
{
1181
   int i,j;
1182
   int rc = MCAPI_FALSE;
1183
 
1184
   /* the database should already be locked */
1185
 
1186
   mcapi_dprintf(2," mcapi_trans_get_endpoint_internal node_num=%d, port_num=%d\n",
1187
                 node_num,port_num);
1188
 
1189
   for (i = 0; i < c_db->num_nodes; i++) {
1190
     if (c_db->nodes[i].node_num == node_num) {
1191
       for (j = 0; j < c_db->nodes[i].node_d.num_endpoints; j++) {
1192
         if ((c_db->nodes[i].node_d.endpoints[j].valid) &&
1193
             (c_db->nodes[i].node_d.endpoints[j].port_num == port_num)) {
1194
           /* return the handle */
1195
           *e = mcapi_trans_encode_handle_internal (i,j);
1196
           rc = MCAPI_TRUE;
1197
         }
1198
       }
1199
     }
1200
   }
1201
   return rc;
1202
}
1203
 
1204
/***************************************************************************
1205
  NAME:mcapi_trans_get_endpoint
1206
  DESCRIPTION:blocking get endpoint for the given <node_num,port_num>
1207
  PARAMETERS:
1208
     endpoint - the endpoint handle to be filled in
1209
     node_num - the node id
1210
     port_num - the port id
1211
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE indicating success or failure
1212
***************************************************************************/
1213
void mcapi_trans_get_endpoint(mcapi_endpoint_t *e, mcapi_uint_t node_num,
1214
                                         mcapi_uint_t port_num)
1215
{
1216
  *e = node_num;
1217
  *e = node_num << 16;
1218
  *e = *e | port_num;
1219
 
1220
 
1221
  /* lock the database */
1222
  // mcapi_trans_access_database_pre();
1223
 
1224
  //while(!mcapi_trans_get_endpoint_internal (e,node_num,port_num)) {
1225
    /* yield */
1226
    //mcapi_dprintf(5," mcapi_trans_get_endpoint - attempting to yield\n");
1227
    //transport_sm_yield_internal();
1228
  //}
1229
 
1230
   /* lock the database */
1231
  // mcapi_trans_access_database_post(); 
1232
}
1233
 
1234
 
1235
/***************************************************************************
1236
  NAME: mcapi_trans_delete_endpoint
1237
  DESCRIPTION:delete the given endpoint
1238
  PARAMETERS: endpoint
1239
  RETURN VALUE: none
1240
***************************************************************************/
1241
 void mcapi_trans_delete_endpoint( mcapi_endpoint_t endpoint)
1242
{
1243
  uint16_t n,e;
1244
  mcapi_boolean_t rv = MCAPI_FALSE;
1245
 
1246
    /* lock the database */
1247
  // mcapi_trans_access_database_pre();
1248
 
1249
  rv = mcapi_trans_decode_handle_internal(endpoint,&n,&e);
1250
  //assert(rv);
1251
 
1252
  mcapi_dprintf(2," mcapi_trans_delete_endpoint_internal node_num=%d, port_num=%d\n",
1253
                c_db->nodes[n].node_num,c_db->nodes[n].node_d.endpoints[e].port_num);
1254
 
1255
  /* remove the endpoint */
1256
  c_db->nodes[n].node_d.num_endpoints--;
1257
  /* zero out the old endpoint entry in the shared memory database */
1258
  memset (&c_db->nodes[n].node_d.endpoints[e],0,sizeof(endpoint_entry));
1259
 
1260
  /* unlock the database */
1261
  // mcapi_trans_access_database_post();
1262
}
1263
 
1264
//////////////////////////////////////////////////////////////////////////////
1265
//                                                                          //
1266
//                   mcapi_trans API: messages                              //
1267
//                                                                          //
1268
//////////////////////////////////////////////////////////////////////////////
1269
/***************************************************************************
1270
  NAME: mcapi_trans_msg_send OK
1271
  DESCRIPTION: sends a connectionless message from one endpoint to another (blocking)
1272
  PARAMETERS:
1273
     send_endpoint - the sending endpoint's handle
1274
     receive_endpoint - the receiving endpoint's handle
1275
     buffer - the user supplied buffer
1276
     buffer_size - the size in bytes of the buffer
1277
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE indicating success or failure
1278
***************************************************************************/
1279
mcapi_boolean_t mcapi_trans_msg_send( mcapi_endpoint_t  send_endpoint,
1280
                                      mcapi_endpoint_t  receive_endpoint, char* buffer,
1281
                                      size_t buffer_size)
1282
{
1283
  mcapi_request_t request;
1284
  mcapi_status_t status = MCAPI_SUCCESS;
1285
  size_t size;
1286
 
1287
 
1288
  /* use non-blocking followed by wait */
1289
  mcapi_trans_msg_send_i (send_endpoint,receive_endpoint,buffer,buffer_size,&request,&status);
1290
  mcapi_trans_wait (&request,&size,&status,MCAPI_INFINITE);
1291
 
1292
  if (status == MCAPI_SUCCESS) {
1293
    return MCAPI_TRUE;
1294
  }
1295
  return MCAPI_FALSE;
1296
}
1297
 
1298
/***************************************************************************
1299
  NAME: mcapi_trans_msg_send_i
1300
  DESCRIPTION: sends a connectionless message from one endpoint to another (non-blocking)
1301
  PARAMETERS:
1302
     send_endpoint - the sending endpoint's handle
1303
     receive_endpoint - the receiving endpoint's handle
1304
     buffer - the user supplied buffer
1305
     buffer_size - the size in bytes of the buffer
1306
     request - the request handle to be filled in when the task is complete
1307
  RETURN VALUE:none
1308
***************************************************************************/
1309
 void mcapi_trans_msg_send_i( mcapi_endpoint_t  send_endpoint, mcapi_endpoint_t  receive_endpoint,
1310
                            char* buffer, size_t buffer_size, mcapi_request_t* request,
1311
                             mcapi_status_t* mcapi_status)
1312
{
1313 175 lanttu
  int port_id,node_id ,fdev = 0;
1314 172 lanttu
  uint16_t sn,se;
1315
  uint16_t rn,re;
1316
  /* if errors were found at the mcapi layer, then the request is considered complete */
1317
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1318
  mcapi_boolean_t rv = MCAPI_FALSE;
1319
 
1320
  mcapi_dprintf(2,"  mcapi_trans_msg_send_i se=%x re=%x\n",send_endpoint,receive_endpoint);
1321
 
1322
  /* lock the database */
1323
  // mcapi_trans_access_database_pre();
1324
 
1325
 
1326
 
1327
  if (!completed) {
1328
    completed = MCAPI_TRUE; /* sends complete immediately */
1329
    /* these function calls were in asserts */
1330
    rv = mcapi_trans_decode_handle_internal(send_endpoint,&sn,&se);
1331
    //assert(rv);
1332
    rv = mcapi_trans_decode_handle_internal(receive_endpoint,&rn,&re);
1333
    //assert(rv);
1334
 
1335
    /* FIXME: (errata B1) is it really an error to send/recv a message with a _connected_ endpoint? */
1336
    //assert (c_db->nodes[sn].node_d.endpoints[se].recv_queue.channel_type == MCAPI_NO_CHAN);
1337
    //assert (c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type == MCAPI_NO_CHAN);
1338
 
1339
 
1340
 
1341 175 lanttu
    //printf("TRANS: Sending message...\n");
1342 172 lanttu
    // TODO: FILE_DEVICE send_data
1343
    port_id = receive_endpoint & 0x0000FFFF;
1344
    node_id = receive_endpoint >> 16;
1345 175 lanttu
 
1346
        fdev = open(dev_names[node_id], O_RDWR, 0x700);
1347 172 lanttu
 
1348 175 lanttu
 
1349 172 lanttu
    if(port_id != 0)
1350
    {
1351
        lseek(fdevs[node_id], port_id, SEEK_SET);
1352
    }
1353
    write(fdevs[node_id], buffer , buffer_size);
1354
 
1355 175 lanttu
        close(fdevs[node_id]);
1356
 
1357 172 lanttu
    //if (!mcapi_trans_send_internal (sn,se,rn,re,buffer,buffer_size,MCAPI_FALSE,0)) {
1358
      /* assume couldn't get a buffer */
1359
    // *mcapi_status = MCAPI_ENO_BUFFER;
1360
    //}
1361
 
1362
  }
1363
 
1364
  //setup_request_internal(&receive_endpoint,request,mcapi_status,completed,buffer_size,NULL,SEND);
1365
 
1366
  /* unlock the database */
1367
    // mcapi_trans_access_database_post();
1368
 }
1369
 
1370
/***************************************************************************
1371
  NAME:mcapi_trans_msg_recv
1372
  DESCRIPTION:receives a message from this endpoints receive queue (blocking)
1373
  PARAMETERS:
1374
     receive_endpoint - the receiving endpoint
1375
     buffer - the user supplied buffer to copy the message into
1376
     buffer_size - the size of the user supplied buffer
1377
     received_size - the actual size of the message received
1378
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE indicating success or failure
1379
***************************************************************************/
1380
mcapi_boolean_t mcapi_trans_msg_recv( mcapi_endpoint_t  receive_endpoint,  char* buffer,
1381
                          size_t buffer_size, size_t* received_size)
1382
{
1383
 
1384
 
1385
  mcapi_request_t request;
1386
  mcapi_status_t status = MCAPI_SUCCESS;
1387
 
1388
  mcapi_dprintf(2,"  mcapi_trans_msg_recv re=%x\n",receive_endpoint);
1389
 
1390
  /* use non-blocking followed by wait */
1391
  mcapi_trans_msg_recv_i (receive_endpoint,buffer,buffer_size,&request,&status);
1392
  // TODO: this wait never finishes on TTA. WHY???
1393
//  mcapi_trans_wait (&request,received_size,&status,MCAPI_INFINITE);
1394
 
1395
  if (status == MCAPI_SUCCESS) {
1396
    return MCAPI_TRUE;
1397
  }
1398
  return MCAPI_FALSE;
1399
 
1400
}
1401
 
1402
/***************************************************************************
1403
  NAME:mcapi_trans_msg_recv_i
1404
  DESCRIPTION:receives a message from this endpoints receive queue (non-blocking)
1405
  PARAMETERS:
1406
     receive_endpoint - the receiving endpoint
1407
     buffer - the user supplied buffer to copy the message into
1408
     buffer_size - the size of the user supplied buffer
1409
     received_size - the actual size of the message received
1410
     request - the request to be filled in when the task is completed.
1411
  RETURN VALUE:MCAPI_TRUE/MCAPI_FALSE indicating success or failure
1412
***************************************************************************/
1413
void mcapi_trans_msg_recv_i( mcapi_endpoint_t  receive_endpoint,  char* buffer,
1414
                             size_t buffer_size, mcapi_request_t* request,
1415
                             mcapi_status_t* mcapi_status)
1416
{
1417
 
1418
 
1419
  uint16_t rn,re,rp;
1420
  //size_t received_size = 0;
1421
  /* if errors were found at the mcapi layer, then the request is considered complete */
1422
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1423
  mcapi_boolean_t rv = MCAPI_FALSE;
1424
 
1425
  /* lock the database */
1426
  // mcapi_trans_access_database_pre();
1427
 
1428
  mcapi_dprintf(2,"  mcapi_trans_msg_recv_i re=%x\n",receive_endpoint);
1429
 
1430
  if (!completed) {
1431
    rv = mcapi_trans_decode_handle_internal(receive_endpoint,&rn,&re);
1432
    //assert(rv);
1433
    /* FIXME: (errata B1) is it really an error recv a message with a _connected_ endpoint? */
1434
    //assert (c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type == MCAPI_NO_CHAN);
1435
 
1436
 
1437
    //if (mcapi_trans_recv_internal(rn,re,(void*)&buffer,buffer_size,&received_size,MCAPI_FALSE,NULL)) {
1438
    // completed = MCAPI_TRUE;
1439
    // buffer_size = received_size;
1440
    //}   
1441
  }
1442
 
1443
  rn = receive_endpoint & 0x0000FFFF;
1444
  rp = receive_endpoint  >> 16;
1445
 
1446
  ioctl(fdevs[rn],SET_HIBI_RX_ADDR,(void*) (hibiBaseAddresses[rn] | rp));
1447
  ioctl(fdevs[rn],SET_HIBI_RX_PACKETS,(void*) DEFAULT_MSG_SIZE);
1448
  ioctl(fdevs[rn],SET_HIBI_RX_BLOCKING,(void*) HIBI_READ_BLOCKING_MODE);
1449
 
1450
 
1451
  // TODO: FILE_DEV get received data from hibi_pe_dma
1452 175 lanttu
  read(fdevs[rp], (char*) &buffer, buffer_size);
1453 172 lanttu
 
1454
  // initialize msg channel
1455
  //initCh(hibi_address_table[my_node_id] + receive_endpoint & 0x0000FFFF, receive_endpoint & 0x0000FFFF, (int)(rx_data), buffer_size);
1456
 
1457
  setup_request_internal(&receive_endpoint,request,mcapi_status,completed,buffer_size,(void**)((void*)&buffer),RECV);
1458
 
1459
 
1460
  /* unlock the database */
1461
  // mcapi_trans_access_database_post();
1462
}
1463
 
1464
/***************************************************************************
1465
  NAME: mcapi_trans_msg_available
1466
  DESCRIPTION: counts the number of messages in the endpoints receive queue
1467
  PARAMETERS:  endpoint
1468
  RETURN VALUE: the number of messages in the queue
1469
***************************************************************************/
1470
mcapi_uint_t mcapi_trans_msg_available( mcapi_endpoint_t receive_endpoint)
1471
{
1472
  uint16_t rn,re;
1473
  int rc = MCAPI_FALSE;
1474
  mcapi_boolean_t rv = MCAPI_FALSE;
1475
 
1476
  /* lock the database */
1477
  // mcapi_trans_access_database_pre();
1478
 
1479
  rv = mcapi_trans_decode_handle_internal(receive_endpoint,&rn,&re);
1480
  //assert(rv);   
1481
 
1482
 
1483
 
1484
  //rc = c_db->nodes[rn].node_d.endpoints[re].recv_queue.num_elements;
1485
 
1486
  /* unlock the database */
1487
  // mcapi_trans_access_database_post();
1488
 
1489
  return rc;
1490
}
1491
 
1492
//////////////////////////////////////////////////////////////////////////////
1493
//                                                                          //
1494
//                   mcapi_trans API: packet channels                       //
1495
//                                                                          //
1496
//////////////////////////////////////////////////////////////////////////////
1497
/***************************************************************************
1498
  NAME:mcapi_trans_connect_pktchan_i
1499
  DESCRIPTION: connects a packet channel
1500
  PARAMETERS:
1501
    send_endpoint - the sending endpoint handle
1502
    receive_endpoint - the receiving endpoint handle
1503
    request - the request to be filled in when the task is complete
1504
    mcapi_status -
1505
  RETURN VALUE:none
1506
***************************************************************************/
1507
void mcapi_trans_connect_pktchan_i( mcapi_endpoint_t  send_endpoint,
1508
                                   mcapi_endpoint_t  receive_endpoint,
1509
                                    mcapi_request_t* request,mcapi_status_t* mcapi_status)
1510
{
1511
 
1512 175 lanttu
  int port_id, node_id =0;
1513
  char buffer;
1514
 
1515 172 lanttu
  /* if errors were found at the mcapi layer, then the request is considered complete */
1516
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1517
 
1518
  /* lock the database */
1519
  // mcapi_trans_access_database_pre();
1520
 
1521
  if (!completed) {
1522
    mcapi_trans_connect_channel_internal (send_endpoint,receive_endpoint,MCAPI_PKT_CHAN);
1523
    completed = MCAPI_TRUE;
1524
  }
1525
  setup_request_internal(&receive_endpoint,request,mcapi_status,completed,0,NULL,0);
1526
 
1527 175 lanttu
 
1528
  port_id = receive_endpoint & 0x0000FFFF;
1529
  node_id = receive_endpoint >> 16;
1530
 
1531
 
1532
  // Open file device for packet channel and store receive endpoint
1533
  pkt_channels[pkt_chan_idx].pkt_fdev = open((void*) fdevs[node_id], O_RDWR, 0x700);
1534
  pkt_channels[pkt_chan_idx].recv_ep = receive_endpoint;
1535
  pkt_chan_idx++;
1536
 
1537
  //Send connect message to receive nodes config channel TODO:set correct size
1538
  write(fdevs[node_id],(void*) 11 ,  4);
1539
 
1540
  // Receive acknoledge
1541
  read(cfg_fdev, (char*) &buffer, 1);
1542
 
1543 172 lanttu
    /* unlock the database */
1544
  // mcapi_trans_access_database_post();
1545
}
1546
 
1547
/***************************************************************************
1548
  NAME: mcapi_trans_open_pktchan_recv_i
1549
  DESCRIPTION: opens the receive endpoint on a packet channel
1550
  PARAMETERS:
1551
    recv_handle - the receive channel handle to be filled in
1552
    receive_endpoint - the receiving endpoint handle
1553
    request - the request to be filled in when the task is complete
1554
    mcapi_status
1555
  RETURN VALUE: none
1556
***************************************************************************/
1557
 void mcapi_trans_open_pktchan_recv_i( mcapi_pktchan_recv_hndl_t* recv_handle,
1558
                                       mcapi_endpoint_t receive_endpoint,
1559
                                       mcapi_request_t* request,mcapi_status_t* mcapi_status)
1560
{
1561
  uint16_t rn,re;
1562
   /* if errors were found at the mcapi layer, then the request is considered complete */
1563
   mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1564
   mcapi_boolean_t rv = MCAPI_FALSE;
1565
 
1566
   completed = MCAPI_TRUE;
1567
   /* lock the database */
1568
   // mcapi_trans_access_database_pre();
1569
 
1570
   if (!completed) {
1571
       rv = mcapi_trans_decode_handle_internal(receive_endpoint,&rn,&re);
1572
     //assert(rv);
1573
 
1574
     mcapi_trans_open_channel_internal (rn,re);
1575
 
1576
     /* fill in the channel handle */
1577
     *recv_handle = mcapi_trans_encode_handle_internal(rn,re);
1578
 
1579 175 lanttu
         // TODO: read(configure)
1580
 
1581 172 lanttu
 
1582
     /* has the channel been connected yet? */
1583
     if ( c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type == MCAPI_PKT_CHAN) {
1584
       completed = MCAPI_TRUE;
1585
     }
1586
 
1587
     mcapi_dprintf(2," mcapi_trans_open_pktchan_recv_i (node_num=%d,port_num=%d) handle=%x\n",
1588
                   c_db->nodes[rn].node_num,c_db->nodes[rn].node_d.endpoints[re].port_num,*recv_handle);
1589
   }
1590
 
1591
   //setup_request_internal(&receive_endpoint,request,mcapi_status,completed,0,NULL,OPEN_PKTCHAN);
1592
 
1593
   /* unlock the database */
1594
   // mcapi_trans_access_database_post();
1595
   *mcapi_status = MCAPI_SUCCESS;
1596
}
1597
 
1598
 
1599
/***************************************************************************
1600
  NAME: mcapi_trans_open_pktchan_send_i
1601
  DESCRIPTION: opens the send endpoint on a packet channel
1602
  PARAMETERS:
1603
    send_handle - the send channel handle to be filled in
1604
    receive_endpoint - the receiving endpoint handle
1605
    request - the request to be filled in when the task is complete
1606
    mcapi_status
1607
  RETURN VALUE: none
1608
***************************************************************************/
1609
void mcapi_trans_open_pktchan_send_i( mcapi_pktchan_send_hndl_t* send_handle,
1610
                                      mcapi_endpoint_t send_endpoint,mcapi_request_t* request,
1611
                                      mcapi_status_t* mcapi_status)
1612
{
1613
  uint16_t sn,se;
1614
  /* if errors were found at the mcapi layer, then the request is considered complete */
1615
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1616
  mcapi_boolean_t rv = MCAPI_FALSE;
1617
 
1618
  /* lock the database */
1619
  // mcapi_trans_access_database_pre();
1620
 
1621
  if (!completed) {
1622
    rv = mcapi_trans_decode_handle_internal(send_endpoint,&sn,&se);
1623
    //assert(rv);
1624
 
1625
    /* mark the endpoint as open */
1626
    c_db->nodes[sn].node_d.endpoints[se].open = MCAPI_TRUE;
1627
 
1628
    /* fill in the channel handle */
1629
    *send_handle = mcapi_trans_encode_handle_internal(sn,se);
1630
 
1631
    /* has the channel been connected yet? */
1632
    if ( c_db->nodes[sn].node_d.endpoints[se].recv_queue.channel_type == MCAPI_PKT_CHAN) {
1633
      completed = MCAPI_TRUE;
1634
    }
1635
 
1636
    mcapi_dprintf(2," mcapi_trans_open_pktchan_send_i (node_num=%d,port_num=%d) handle=%x\n",
1637
                  c_db->nodes[sn].node_num,c_db->nodes[sn].node_d.endpoints[se].port_num,*send_handle);
1638
  }
1639
 
1640
  setup_request_internal(&send_endpoint,request,mcapi_status,completed,0,NULL,OPEN_PKTCHAN);
1641
 
1642
  /* unlock the database */
1643
  // mcapi_trans_access_database_post();
1644
}
1645
 
1646
/***************************************************************************
1647
  NAME:mcapi_trans_pktchan_send_i
1648
  DESCRIPTION: sends a packet on a packet channel (non-blocking)
1649
  PARAMETERS:
1650
    send_handle - the send channel handle
1651
    buffer - the buffer
1652
    size - the size in bytes of the buffer
1653
    request - the request handle to be filled in when the task is complete
1654
    mcapi_status -
1655
  RETURN VALUE: none
1656
***************************************************************************/
1657
void mcapi_trans_pktchan_send_i( mcapi_pktchan_send_hndl_t send_handle,
1658
                                void* buffer, size_t size, mcapi_request_t* request,
1659
                                 mcapi_status_t* mcapi_status)
1660
{
1661 175 lanttu
  int i;
1662 172 lanttu
  uint16_t sn,se,rn,re;
1663
   /* if errors were found at the mcapi layer, then the request is considered complete */
1664
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1665
  mcapi_boolean_t rv = MCAPI_FALSE;
1666
 
1667
  mcapi_dprintf(2,"  mcapi_trans_pktchan_send_i send_handle=%x\n",send_handle);
1668
 
1669
  /* lock the database */
1670
  // mcapi_trans_access_database_pre();
1671
  completed = MCAPI_FALSE;
1672
 
1673
  if (!completed) {
1674
    rv = mcapi_trans_decode_handle_internal(send_handle,&sn,&se);
1675
    //assert(rv);   
1676
    rv = mcapi_trans_decode_handle_internal(c_db->nodes[sn].node_d.endpoints[se].recv_queue.recv_endpt,&rn,&re);
1677
    //assert(rv);
1678
 
1679
    /*   if (!mcapi_trans_send_internal (sn,se,rn,re,(char*)buffer,size,MCAPI_FALSE,0)) { */
1680
    /*       *mcapi_status = MCAPI_ENO_BUFFER; */
1681
    /*     } */
1682
 
1683
 
1684 175 lanttu
  for(i=0; i < pkt_chan_idx;) {
1685
        if (pkt_channels[i].recv_ep == re) break;
1686
        i++;
1687
  }
1688
 
1689
  write(pkt_channels[i].pkt_fdev, buffer , size);
1690 172 lanttu
 
1691
 
1692
    completed = MCAPI_TRUE;
1693
  }
1694
 
1695
  setup_request_internal(&send_handle,request,mcapi_status,completed,size,NULL,SEND);
1696
 
1697
  /* unlock the database */
1698
  // mcapi_trans_access_database_post();
1699
}
1700
 
1701
/***************************************************************************
1702
  NAME:mcapi_trans_pktchan_send
1703
  DESCRIPTION: sends a packet on a packet channel (blocking)
1704
  PARAMETERS:
1705
    send_handle - the send channel handle
1706
    buffer - the buffer
1707
    size - the size in bytes of the buffer
1708
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
1709
***************************************************************************/
1710
mcapi_boolean_t mcapi_trans_pktchan_send( mcapi_pktchan_send_hndl_t send_handle,
1711
                                         void* buffer, size_t size)
1712
{
1713
  mcapi_request_t request;
1714
  mcapi_status_t status = MCAPI_SUCCESS;
1715
 
1716
  mcapi_dprintf(2,"  mcapi_trans_pktchan_send re=%x\n",send_handle);
1717
 
1718
  /* use non-blocking followed by wait */
1719
  mcapi_trans_pktchan_send_i (send_handle,buffer,size,&request,&status);
1720
  mcapi_trans_wait (&request,&size,&status,MCAPI_INFINITE);
1721
  status = MCAPI_SUCCESS;
1722
  if (status == MCAPI_SUCCESS) {
1723
    return MCAPI_TRUE;
1724
  }
1725
  return MCAPI_FALSE;
1726
}
1727
 
1728
 
1729
/***************************************************************************
1730
  NAME:mcapi_trans_pktchan_recv_i
1731
  DESCRIPTION: receives a packet on a packet channel (non-blocking)
1732
  PARAMETERS:
1733
    receive_handle - the send channel handle
1734
    buffer - a pointer to a pointer to a buffer
1735
    request - the request handle to be filled in when the task is complete
1736
    mcapi_status -
1737
  RETURN VALUE: none
1738
***************************************************************************/
1739
void mcapi_trans_pktchan_recv_i( mcapi_pktchan_recv_hndl_t receive_handle,
1740
                                 void** buffer, mcapi_request_t* request,
1741
                                 mcapi_status_t* mcapi_status)
1742
{
1743
  uint16_t rn,re,rp;
1744
  /* if errors were found at the mcapi layer, then the request is considered complete */
1745
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1746
  mcapi_boolean_t rv = MCAPI_FALSE;
1747
 
1748
  size_t size = MAX_PKT_SIZE;
1749
 
1750
  /* lock the database */
1751
  // mcapi_trans_access_database_pre();
1752
 
1753
  completed = MCAPI_FALSE;
1754
 
1755
  if (!completed) {
1756
    rv = mcapi_trans_decode_handle_internal(receive_handle,&rn,&re);
1757
    //assert(rv);
1758
 
1759
    /* *buffer will be filled in the with a ptr to an mcapi buffer */
1760
    //*buffer = NULL;
1761
    //*buffer = rx_data;
1762
 
1763
    //decode handle
1764
 
1765
    ioctl(fdevs[rn],SET_HIBI_RX_ADDR,(void*) (hibiBaseAddresses[rn] | rp)  );
1766
    ioctl(fdevs[rn],SET_HIBI_RX_PACKETS,(void*) DEFAULT_MSG_SIZE);
1767
    ioctl(fdevs[rn],SET_HIBI_RX_BLOCKING,(void*) HIBI_READ_BLOCKING_MODE);
1768
 
1769
 
1770
    // TODO: FILE_DEV
1771
    read(fdevs[0], (char*) &buffer, 1);
1772
 
1773
 
1774
    //if (mcapi_trans_recv_internal (rn,re,buffer,MAX_PKT_SIZE,&size,MCAPI_FALSE,NULL)) {
1775
    completed = MCAPI_TRUE;
1776
    //}
1777
  }
1778
 
1779
  setup_request_internal(&receive_handle,request,mcapi_status,completed,size,buffer,RECV);
1780
 
1781
  /* unlock the database */
1782
  // mcapi_trans_access_database_post();
1783
}
1784
 
1785
/***************************************************************************
1786
  NAME:mcapi_trans_pktchan_recv
1787
  DESCRIPTION: receives a packet on a packet channel (blocking)
1788
  PARAMETERS:
1789
    send_handle - the send channel handle
1790
    buffer - the buffer
1791
    received_size - the size in bytes of the buffer
1792
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE (only returns MCAPI_FALSE if it couldn't get a buffer)
1793
***************************************************************************/
1794
mcapi_boolean_t mcapi_trans_pktchan_recv( mcapi_pktchan_recv_hndl_t receive_handle,
1795
                              void** buffer, size_t* received_size)
1796
{
1797
 
1798
  mcapi_request_t request;
1799
  mcapi_status_t status = MCAPI_SUCCESS;
1800
 
1801
  mcapi_dprintf(2,"  mcapi_trans_pktchan_recv re=%x\n",receive_handle);
1802
 
1803
  /* use non-blocking followed by wait */
1804
  mcapi_trans_pktchan_recv_i (receive_handle,buffer,&request,&status);
1805
  mcapi_trans_wait (&request,received_size,&status,MCAPI_INFINITE);
1806
  status = MCAPI_SUCCESS;
1807
  if (status == MCAPI_SUCCESS) {
1808
    return MCAPI_TRUE;
1809
  }
1810
  return MCAPI_FALSE;
1811
}
1812
 
1813
/***************************************************************************
1814
  NAME: mcapi_trans_pktchan_available
1815
  DESCRIPTION: counts the number of elements in the endpoint receive queue
1816
    identified by the receive handle.
1817
  PARAMETERS: receive_handle - the receive channel handle
1818
  RETURN VALUE: the number of elements in the receive queue
1819
***************************************************************************/
1820
mcapi_uint_t mcapi_trans_pktchan_available( mcapi_pktchan_recv_hndl_t receive_handle)
1821
{
1822
  uint16_t rn,re;
1823
  int rc = MCAPI_FALSE;
1824
  mcapi_boolean_t rv = MCAPI_FALSE;
1825
 
1826
  /* lock the database */
1827
  // mcapi_trans_access_database_pre();
1828
 
1829
  rv = mcapi_trans_decode_handle_internal(receive_handle,&rn,&re);
1830
  //assert(rv); 
1831
  rc = c_db->nodes[rn].node_d.endpoints[re].recv_queue.num_elements;
1832
 
1833
  /* unlock the database */
1834
  // mcapi_trans_access_database_post();
1835
 
1836
  return rc;
1837
}
1838
 
1839
/***************************************************************************
1840
  NAME:mcapi_trans_pktchan_free
1841
  DESCRIPTION: frees the given buffer
1842
  PARAMETERS: buffer pointer
1843
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE indicating success or failure (buffer not found)
1844
***************************************************************************/
1845
mcapi_boolean_t mcapi_trans_pktchan_free( void* buffer)
1846
{
1847
 
1848
   int rc = MCAPI_TRUE;
1849
   buffer_entry* b_e;
1850
 
1851
   /* lock the database */
1852
  // mcapi_trans_access_database_pre();
1853
 
1854
  /* optimization - just do pointer arithmetic on the buffer pointer to get
1855
     the base address of the buffer_entry structure. */
1856
  b_e = buffer-9;
1857
  if (b_e->magic_num == MAGIC_NUM) {
1858
    memset(b_e,0,sizeof(buffer_entry));
1859
  } else {
1860
    /* didn't find the buffer */
1861
    rc = MCAPI_FALSE;
1862
  }
1863
 
1864
  /* unlock the database */
1865
  // mcapi_trans_access_database_post();
1866
 
1867
  return rc;
1868
}
1869
 
1870
 
1871
/***************************************************************************
1872
  NAME:mcapi_trans_pktchan_recv_close_i
1873
  DESCRIPTION: non-blocking close of the receiving end of the packet channel
1874
  PARAMETERS: receive_handle
1875
  RETURN VALUE:none
1876
***************************************************************************/
1877
void mcapi_trans_pktchan_recv_close_i( mcapi_pktchan_recv_hndl_t  receive_handle,
1878
                                       mcapi_request_t* request, mcapi_status_t* mcapi_status)
1879
{
1880
  uint16_t rn,re;
1881
  /* if errors were found at the mcapi layer, then the request is considered complete */
1882
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1883
  mcapi_boolean_t rv = MCAPI_FALSE;
1884
 
1885
  /* lock the database */
1886
  // mcapi_trans_access_database_pre();
1887
 
1888
  if (!completed) {
1889
    rv = mcapi_trans_decode_handle_internal(receive_handle,&rn,&re);
1890
    //assert(rv);
1891
    mcapi_trans_close_channel_internal (rn,re);
1892
    completed = MCAPI_TRUE;
1893
  }
1894
  setup_request_internal(&receive_handle,request,mcapi_status,completed,0,NULL,0);
1895
 
1896
  /* unlock the database */
1897
  // mcapi_trans_access_database_post();
1898
}
1899
 
1900
 
1901
/***************************************************************************
1902
  NAME:mcapi_trans_pktchan_send_close_i
1903
  DESCRIPTION: non-blocking close of the sending end of the packet channel
1904
  PARAMETERS: receive_handle
1905
  RETURN VALUE:none
1906
***************************************************************************/
1907
void mcapi_trans_pktchan_send_close_i( mcapi_pktchan_send_hndl_t  send_handle,
1908
                                       mcapi_request_t* request,mcapi_status_t* mcapi_status)
1909
{
1910
  uint16_t sn,se;
1911
  /* if errors were found at the mcapi layer, then the request is considered complete */
1912
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1913
  mcapi_boolean_t rv = MCAPI_FALSE;
1914
  /* lock the database */
1915
  // mcapi_trans_access_database_pre();
1916
 
1917
  if (!completed) {
1918
     rv = mcapi_trans_decode_handle_internal(send_handle,&sn,&se);
1919
     //assert(rv);
1920
     mcapi_trans_close_channel_internal (sn,se);
1921
     completed = MCAPI_TRUE;
1922
   }
1923
 
1924
  setup_request_internal(&send_handle,request,mcapi_status,completed,0,NULL,0);
1925
 
1926
  /* unlock the database */
1927
  // mcapi_trans_access_database_post();
1928
}
1929
 
1930
//////////////////////////////////////////////////////////////////////////////
1931
//                                                                          //
1932
//                   mcapi_trans API: scalar channels                       //
1933
//                                                                          //
1934
//////////////////////////////////////////////////////////////////////////////
1935
 
1936
/***************************************************************************
1937
  NAME:mcapi_trans_connect_sclchan_i
1938
  DESCRIPTION: connects a scalar channel between the given two endpoints
1939
  PARAMETERS:
1940
      send_endpoint - the sending endpoint
1941
      receive_endpoint - the receiving endpoint
1942
      request - the request
1943
      mcapi_status - the status
1944
  RETURN VALUE: none
1945
***************************************************************************/
1946
void mcapi_trans_connect_sclchan_i( mcapi_endpoint_t  send_endpoint,
1947
                                    mcapi_endpoint_t  receive_endpoint,
1948
                                    mcapi_request_t* request,mcapi_status_t* mcapi_status)
1949
{
1950 175 lanttu
  int node_id, port_id = 0;
1951
  char buffer;
1952
 
1953 172 lanttu
  /* if errors were found at the mcapi layer, then the request is considered complete */
1954
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
1955
 
1956
  /* lock the database */
1957
  // mcapi_trans_access_database_pre();
1958
 
1959
  if (!completed) {
1960
    mcapi_trans_connect_channel_internal (send_endpoint,receive_endpoint,MCAPI_SCL_CHAN);
1961
    completed = MCAPI_TRUE;
1962
  }
1963
  setup_request_internal(&receive_endpoint,request,mcapi_status,completed,0,NULL,0);
1964
 
1965 175 lanttu
 
1966
  port_id = receive_endpoint & 0x0000FFFF;
1967
  node_id = receive_endpoint >> 16;
1968
 
1969
  // Open file device for packet channel and store receive endpoint
1970
  scl_channels[scl_chan_idx].scl_fdev = open((void*)fdevs[node_id], O_RDWR, 0x700);
1971
  scl_channels[scl_chan_idx].recv_ep = receive_endpoint;
1972
  scl_chan_idx++;
1973
 
1974
  //Send connect message to receive nodes config channel TODO: Set correct size
1975
  write(fdevs[node_id],(void*) 11 , 4);
1976
 
1977
  // Receive acknoledge
1978
  read(cfg_fdev, (char*) &buffer, 1);
1979
 
1980 172 lanttu
  /* unlock the database */
1981
  // mcapi_trans_access_database_post();
1982
}
1983
 
1984
/***************************************************************************
1985
  NAME: mcapi_trans_open_sclchan_recv_i
1986
  DESCRIPTION: opens the receive endpoint on a packet channel
1987
  PARAMETERS:
1988
    recv_handle - the receive channel handle to be filled in
1989
    receive_endpoint - the receiving endpoint handle
1990
    request - the request to be filled in when the task is complete
1991
    mcapi_status
1992
  RETURN VALUE: none
1993
***************************************************************************/
1994
void mcapi_trans_open_sclchan_recv_i( mcapi_sclchan_recv_hndl_t* recv_handle,
1995
                                      mcapi_endpoint_t receive_endpoint,
1996
                                      mcapi_request_t* request,mcapi_status_t* mcapi_status)
1997
{
1998
  uint16_t rn,re;
1999
  /* if errors were found at the mcapi layer, then the request is considered complete */
2000
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
2001
  mcapi_boolean_t rv = MCAPI_FALSE;
2002
 
2003
  /* lock the database */
2004
  // mcapi_trans_access_database_pre();
2005
 
2006
  if (!completed) {
2007
    rv = mcapi_trans_decode_handle_internal(receive_endpoint,&rn,&re);
2008
    //assert(rv);
2009
 
2010
    mcapi_trans_open_channel_internal (rn,re);
2011
 
2012
    /* fill in the channel handle */
2013
    *recv_handle = mcapi_trans_encode_handle_internal(rn,re);
2014
 
2015
    /* has the channel been connected yet? */
2016
    if ( c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type == MCAPI_SCL_CHAN){
2017
      completed = MCAPI_TRUE;
2018
    }
2019
 
2020
    mcapi_dprintf(2," mcapi_trans_open_sclchan_recv_i (node_num=%d,port_num=%d) handle=%x\n",
2021
                  c_db->nodes[rn].node_num,c_db->nodes[rn].node_d.endpoints[re].port_num,*recv_handle);
2022
  }
2023
 
2024
  setup_request_internal(&receive_endpoint,request,mcapi_status,completed,0,NULL,OPEN_SCLCHAN);
2025
 
2026
  /* unlock the database */
2027
  // mcapi_trans_access_database_post();
2028
}
2029
 
2030
 
2031
/***************************************************************************
2032
  NAME: mcapi_trans_open_sclchan_send_i
2033
  DESCRIPTION: opens the receive endpoint on a packet channel
2034
  PARAMETERS:
2035
    send_handle - the receive channel handle to be filled in
2036
    receive_endpoint - the receiving endpoint handle
2037
    request - the request to be filled in when the task is complete
2038
    mcapi_status
2039
  RETURN VALUE: none
2040
***************************************************************************/
2041
void mcapi_trans_open_sclchan_send_i( mcapi_sclchan_send_hndl_t* send_handle,
2042
                                      mcapi_endpoint_t  send_endpoint,
2043
                                      mcapi_request_t* request,mcapi_status_t* mcapi_status)
2044
{
2045
  uint16_t sn,se;
2046
  /* if errors were found at the mcapi layer, then the request is considered complete */
2047
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
2048
  mcapi_boolean_t rv = MCAPI_FALSE;
2049
 
2050
  /* lock the database */
2051
  // mcapi_trans_access_database_pre();
2052
  if (!completed) {
2053
    rv = mcapi_trans_decode_handle_internal(send_endpoint,&sn,&se);
2054
    //assert(rv);
2055
 
2056
    /* mark the endpoint as open */
2057
    c_db->nodes[sn].node_d.endpoints[se].open = MCAPI_TRUE;
2058
 
2059
    /* fill in the channel handle */
2060
    *send_handle = mcapi_trans_encode_handle_internal(sn,se);
2061
 
2062
    /* has the channel been connected yet? */
2063
    if ( c_db->nodes[sn].node_d.endpoints[se].recv_queue.channel_type == MCAPI_SCL_CHAN){
2064
      completed = MCAPI_TRUE;
2065
    }
2066
 
2067
    mcapi_dprintf(2," mcapi_trans_open_sclchan_send_i (node_num=%d,port_num=%d) handle=%x\n",
2068
                  c_db->nodes[sn].node_num,c_db->nodes[sn].node_d.endpoints[se].port_num,*send_handle);
2069
  }
2070
 
2071
  setup_request_internal(&send_endpoint,request,mcapi_status,completed,0,NULL,OPEN_SCLCHAN);
2072
 
2073
  /* unlock the database */
2074
  // mcapi_trans_access_database_post();
2075
}
2076
 
2077
/***************************************************************************
2078
  NAME:mcapi_trans_sclchan_send
2079
  DESCRIPTION: sends a packet on a packet channel (blocking)
2080
  PARAMETERS:
2081
    send_handle - the send channel handle
2082
    buffer - the buffer
2083
    size - the size in bytes of the buffer
2084
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE
2085
***************************************************************************/
2086
mcapi_boolean_t mcapi_trans_sclchan_send(
2087
    mcapi_sclchan_send_hndl_t send_handle, uint64_t dataword, uint32_t size)
2088
{
2089 175 lanttu
  int i = 0;
2090 172 lanttu
  uint16_t sn,se,rn,re;
2091
  int rc = MCAPI_FALSE;
2092
  mcapi_boolean_t rv = MCAPI_FALSE;
2093
 
2094
  mcapi_dprintf(2,"  mcapi_trans_sclchan_send send_handle=%x\n",send_handle);
2095
 
2096
  /* lock the database */
2097
  // mcapi_trans_access_database_pre();
2098
 
2099
  rv = mcapi_trans_decode_handle_internal(send_handle,&sn,&se);
2100
  //assert(rv);
2101
  rv = mcapi_trans_decode_handle_internal(c_db->nodes[sn].node_d.endpoints[se].recv_queue.recv_endpt,&rn,&re);
2102
  //assert(rv);
2103
 
2104
  rc = mcapi_trans_send_internal (sn,se,rn,re,NULL,size,MCAPI_TRUE,dataword);
2105
 
2106 175 lanttu
 for(i=0; i < scl_chan_idx;) {
2107
        if (pkt_channels[i].recv_ep == re) break;
2108
        i++;
2109
  }
2110
 
2111
  write(scl_channels[i].scl_fdev, &dataword , size);
2112 172 lanttu
 
2113
  /* unlock the database */
2114
  // mcapi_trans_access_database_post();
2115
 
2116
  return rc;
2117
}
2118
 
2119
 
2120
/***************************************************************************
2121
  NAME:mcapi_trans_sclchan_recv
2122
  DESCRIPTION: receives a packet on a packet channel (blocking)
2123
  PARAMETERS:
2124
    send_handle - the send channel handle
2125
    buffer - the buffer
2126
    received_size - the size in bytes of the buffer
2127
  RETURN VALUE: MCAPI_TRUE/MCAPI_FALSE (only returns MCAPI_FALSE if it couldn't get a buffer)
2128
***************************************************************************/
2129
mcapi_boolean_t mcapi_trans_sclchan_recv(
2130
    mcapi_sclchan_recv_hndl_t receive_handle, uint64_t *data,uint32_t size)
2131
{
2132
  uint16_t rn,re;
2133
  size_t received_size;
2134
  int rc = MCAPI_FALSE;
2135
  mcapi_boolean_t rv = MCAPI_FALSE;
2136
 
2137
  /* lock the database */
2138
  // mcapi_trans_access_database_pre();
2139
 
2140
  rv = mcapi_trans_decode_handle_internal(receive_handle,&rn,&re);
2141
  //assert(rv);
2142
 
2143
 
2144
  if (mcapi_trans_recv_internal (rn,re,NULL,size,&received_size,MCAPI_TRUE,data) &&
2145
      received_size == size) {
2146
    rc = MCAPI_TRUE;
2147
  }
2148
 
2149
 
2150
  /* FIXME: (errata A2) if size != received_size then we shouldn't remove the item from the
2151
     endpoints receive queue */
2152
 
2153
  /* unlock the database */
2154
  // mcapi_trans_access_database_post();
2155
 
2156
  return rc;
2157
}
2158
 
2159
/***************************************************************************
2160
  NAME: mcapi_trans_sclchan_available
2161
  DESCRIPTION: counts the number of elements in the endpoint receive queue
2162
    identified by the receive handle.
2163
  PARAMETERS: receive_handle - the receive channel handle
2164
  RETURN VALUE: the number of elements in the receive queue
2165
***************************************************************************/
2166
mcapi_uint_t mcapi_trans_sclchan_available_i( mcapi_sclchan_recv_hndl_t receive_handle)
2167
{
2168
  uint16_t rn,re;
2169
  int rc = MCAPI_FALSE;
2170
  mcapi_boolean_t rv = MCAPI_FALSE;
2171
 
2172
  /* lock the database */
2173
  // mcapi_trans_access_database_pre();
2174
 
2175
  rv = mcapi_trans_decode_handle_internal(receive_handle,&rn,&re);
2176
  //assert(rv); 
2177
  rc = c_db->nodes[rn].node_d.endpoints[re].recv_queue.num_elements;
2178
 
2179
 
2180
    /* unlock the database */
2181
  // mcapi_trans_access_database_post();
2182
 
2183
  return rc;
2184
}
2185
 
2186
/***************************************************************************
2187
  NAME:mcapi_trans_sclchan_recv_close_i
2188
  DESCRIPTION: non-blocking close of the receiving end of the scalar channel
2189
  PARAMETERS:
2190
    receive_handle -
2191
    request -
2192
    mcapi_status -
2193
  RETURN VALUE:none
2194
***************************************************************************/
2195
void mcapi_trans_sclchan_recv_close_i( mcapi_sclchan_recv_hndl_t  recv_handle,
2196
                                       mcapi_request_t* request,mcapi_status_t* mcapi_status)
2197
{
2198
  uint16_t rn,re;
2199
   /* if errors were found at the mcapi layer, then the request is considered complete */
2200
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
2201
  mcapi_boolean_t rv = MCAPI_FALSE;
2202
 
2203
  /* lock the database */
2204
  // mcapi_trans_access_database_pre();
2205
  if (!completed) {
2206
    rv = mcapi_trans_decode_handle_internal(recv_handle,&rn,&re);
2207
    //assert(rv);
2208
    mcapi_trans_close_channel_internal (rn,re);
2209
    completed = MCAPI_TRUE;
2210
  }
2211
  setup_request_internal(&recv_handle,request,mcapi_status,completed,0,NULL,0);
2212
  /* unlock the database */
2213
  // mcapi_trans_access_database_post();
2214
}
2215
 
2216
 
2217
/***************************************************************************
2218
  NAME:mcapi_trans_sclchan_send_close_i
2219
  DESCRIPTION: non-blocking close of the sending end of the scalar channel
2220
  PARAMETERS:
2221
    send_handle -
2222
    request -
2223
    mcapi_status -
2224
  RETURN VALUE:none
2225
***************************************************************************/
2226
void mcapi_trans_sclchan_send_close_i( mcapi_sclchan_send_hndl_t send_handle,
2227
                                       mcapi_request_t* request,mcapi_status_t* mcapi_status)
2228
{
2229
  uint16_t sn,se;
2230
  /* if errors were found at the mcapi layer, then the request is considered complete */
2231
  mcapi_boolean_t completed =  (*mcapi_status == MCAPI_SUCCESS) ? MCAPI_FALSE : MCAPI_TRUE;
2232
  mcapi_boolean_t rv = MCAPI_FALSE;
2233
 
2234
  /* lock the database */
2235
  // mcapi_trans_access_database_pre();
2236
  if (!completed) {
2237
    rv = mcapi_trans_decode_handle_internal(send_handle,&sn,&se);
2238
    //assert(rv);
2239
    mcapi_trans_close_channel_internal (sn,se);
2240
    completed = MCAPI_TRUE;
2241
  }
2242
  setup_request_internal(&send_handle,request,mcapi_status,completed,0,NULL,0);
2243
  /* unlock the database */
2244
  // mcapi_trans_access_database_post();
2245
}
2246
 
2247
 
2248
 
2249
//////////////////////////////////////////////////////////////////////////////
2250
//                                                                          //
2251
//                   test and wait functions                                //
2252
//                                                                          //
2253
//////////////////////////////////////////////////////////////////////////////
2254
 
2255
/***************************************************************************
2256
  NAME:mcapi_trans_test_i
2257
  DESCRIPTION: Tests if the request has completed yet (non-blocking).
2258
  PARAMETERS:
2259
    request -
2260
    size -
2261
    mcapi_status -
2262
  RETURN VALUE: TRUE/FALSE indicating if the request has completed.
2263
***************************************************************************/
2264
mcapi_boolean_t mcapi_trans_test_i( mcapi_request_t* request, size_t* size,
2265
                                    mcapi_status_t* mcapi_status)
2266
{
2267
 
2268
  /* FIXME: (errata B6) need to be able to set EREQ_CANCELED just like wait does */
2269
  mcapi_boolean_t rc;
2270
 
2271
  rc = MCAPI_FALSE;
2272
 
2273
  mcapi_dprintf(3,"mcapi_trans_test_i request:0x%lx\n",(long unsigned int) request);
2274
  if (request->valid == MCAPI_FALSE) {
2275
    *mcapi_status = MCAPI_ENOTREQ_HANDLE;
2276
    rc = MCAPI_FALSE;
2277
  } else if (request->cancelled) {
2278
    *mcapi_status = MCAPI_EREQ_CANCELED;
2279
    rc = MCAPI_FALSE;
2280
  } else if (!(request->completed)) {
2281
    /* try to complete the request */
2282
    /*  receives to an empty channel or get_endpt for an endpt that
2283
        doesn't yet exist are the only two types of non-blocking functions
2284
        that don't complete immediately for this implementation */
2285
    switch (request->type) {
2286
    case (RECV) :
2287
      check_receive_request (request); break;
2288
    case (GET_ENDPT) :
2289
      check_get_endpt_request (request);break;
2290
    default:
2291
      //assert(0);
2292
      break;
2293
    };
2294
  }
2295
 
2296
  if (request->completed) {
2297
    *size = request->size;
2298
    *mcapi_status = request->status;
2299
    rc = MCAPI_TRUE;
2300
  }
2301
 
2302
  return rc;
2303
}
2304
 
2305
/***************************************************************************
2306
  NAME:mcapi_trans_wait
2307
  DESCRIPTION:Tests if the request has completed yet (non-blocking).
2308
  PARAMETERS:
2309
    send_handle -
2310
    request -
2311
    mcapi_status -
2312
  RETURN VALUE:  TRUE indicating the request has completed or FALSE
2313
    indicating the request has been cancelled.
2314
***************************************************************************/
2315
mcapi_boolean_t mcapi_trans_wait( mcapi_request_t* request, size_t* size,
2316
                                  mcapi_status_t* mcapi_status,
2317
                                  mcapi_timeout_t timeout)
2318
{
2319
  mcapi_timeout_t time = 0;
2320
  mcapi_boolean_t rc;
2321
  while(1) {
2322
    time++;
2323
    rc = mcapi_trans_test_i(request,size,mcapi_status);
2324
    if (request->completed) {
2325
      return rc;
2326
    }
2327
    /* yield */
2328
    mcapi_dprintf(5," mcapi_trans_wait - attempting to yield\n");
2329
    /* we don't have the lock, it's safe to just yield */
2330
    //sched_yield();
2331
    if ((timeout !=  MCAPI_INFINITE) && (time >= timeout)) {
2332
      *mcapi_status = MCAPI_EREQ_TIMEOUT;
2333
      return MCAPI_FALSE;
2334
    }
2335
  }
2336
}
2337
 
2338
/***************************************************************************
2339
  NAME:mcapi_trans_wait_any
2340
  DESCRIPTION:Tests if any of the requests have completed yet (blocking).
2341
      Note: the request is now cleared if it has been completed or cancelled.
2342
  PARAMETERS:
2343
    send_handle -
2344
    request -
2345
    mcapi_status -
2346
  RETURN VALUE: TRUE indicating one of the requests has completed or FALSE
2347
    indicating one of the requests has been cancelled.
2348
***************************************************************************/
2349
mcapi_boolean_t mcapi_trans_wait_any(size_t number, mcapi_request_t** requests, size_t* size,
2350
                                  mcapi_status_t* mcapi_status,
2351
                                  mcapi_timeout_t timeout)
2352
{
2353
  mcapi_timeout_t time = 0;
2354
  mcapi_boolean_t rc;
2355
  unsigned int i;
2356
  while(1) {
2357
    time++;
2358
    for (i = 0; i < number; i++) {
2359
      rc = mcapi_trans_test_i(requests[i],size,mcapi_status);
2360
      if (requests[i]->completed) {
2361
        return rc;
2362
      }
2363
      /* yield */
2364
      mcapi_dprintf(5," mcapi_trans_wait_any - attempting to yield\n");
2365
      /* we don't have the lock, it's safe to just yield */
2366
      //sched_yield();
2367
      if ((timeout !=  MCAPI_INFINITE) && (time >= timeout)) {
2368
        *mcapi_status = MCAPI_EREQ_TIMEOUT;
2369
        return MCAPI_FALSE;
2370
      }
2371
    }
2372
  }
2373
}
2374
 
2375
/***************************************************************************
2376
  NAME:mcapi_trans_cancel
2377
  DESCRIPTION: Cancels the given request
2378
  PARAMETERS:
2379
    request -
2380
    mcapi_status -
2381
  RETURN VALUE:none
2382
***************************************************************************/
2383
void mcapi_trans_cancel(mcapi_request_t* request,mcapi_status_t* mcapi_status)
2384
{
2385
  if (request->valid == MCAPI_FALSE) {
2386
    *mcapi_status = MCAPI_ENOTREQ_HANDLE;
2387
    return;
2388
  } else if (request->cancelled) {
2389
    /* this reqeust has already been cancelled */
2390
    mcapi_dprintf(1," mcapi_trans_cancel - request was already cancelled\n");
2391
    *mcapi_status = MCAPI_EREQ_CANCELED;
2392
    return;
2393
  } else if (!(request->completed)) {
2394
    /* cancel the request */
2395
    request->cancelled = MCAPI_TRUE;
2396
    switch (request->type) {
2397
    case (RECV) :
2398
      cancel_receive_request (request); break;
2399
    case (GET_ENDPT) :
2400
      break;
2401
    default:
2402
      //assert(0);
2403
      break;
2404
    };
2405
  } else {
2406
    /* it's too late, the request has already completed */
2407
    mcapi_dprintf(1," mcapi_trans_cancel - request has already completed\n");
2408
  }
2409
}
2410
 
2411
 
2412
//////////////////////////////////////////////////////////////////////////////
2413
//                                                                          //
2414
//                   misc helper functions                                  //
2415
//                                                                          //
2416
//////////////////////////////////////////////////////////////////////////////
2417
 
2418
/***************************************************************************
2419
  NAME:mcapi_trans_signal_handler
2420
  DESCRIPTION: The purpose of this function is to catch signals so that we
2421
   can clean up our shared memory and sempaphore resources cleanly.
2422
  PARAMETERS: the signal
2423
  RETURN VALUE: none
2424
***************************************************************************/
2425
void mcapi_trans_signal_handler ( int sig )
2426
{
2427
 /*  /\* Since this handler is established for more than one kind of signal,  */
2428
/*      it might still get invoked recursively by delivery of some other kind */
2429
/*      of signal.  Use a static variable to keep track of tha *\/ */
2430
 
2431
/*   if (fatal_error_in_progress) */
2432
/*     raise (sig); */
2433
/*   fatal_error_in_progress = 1; */
2434
 
2435
/*   /\* clean up ipc resources *\/ */
2436
/*   fprintf(stderr,"FAIL: received signal, freeing semaphore and shared memory\n"); */
2437
/*   mcapi_trans_finalize(); */
2438
 
2439
/*   /\* Now reraise the signal.  We reactivate the signal's */
2440
/*      default handling, which is to terminate the process. */
2441
/*      We could just call exit or abort, */
2442
/*      but reraising the signal sets the return status */
2443
/*      from the process correctly. *\/ */
2444
/*   signal (sig, SIG_DFL); */
2445
/*   raise (sig); */
2446
}
2447
 
2448
/***************************************************************************
2449
  NAME: print_tid
2450
  DESCRIPTION: Displays the thread id.
2451
  PARAMETERS: t - opaque pthread_t handle
2452
  RETURN VALUE: string representing the TID value
2453
***************************************************************************/
2454
//const char *print_tid(pthread_t t) {
2455
//  static char buffer[100];
2456
//  char *p = buffer;
2457
//  
2458
//#ifdef __linux
2459
//  /* We know that pthread_t is an unsigned long */
2460
//  sprintf(p, "%lu", t);
2461
//#else
2462
//  /* Just print out the contents of the pthread_t */ {
2463
//    char *const tend = (char *) ((&t)+1);
2464
//    char *tp = (char *) &t;
2465
//    while (tp < tend) {
2466
//      p += sprintf (p, "%02x", *tp);
2467
//      tp++;
2468
//      if (tp < tend)
2469
//        *p++ = ':';
2470
//    }
2471
//  }
2472
//#endif
2473
//  return buffer;
2474
//}
2475
 
2476
/***************************************************************************
2477
  NAME: mcapi_trans_set_debug_level
2478
  DESCRIPTION: Sets the debug level which controls verbosity.
2479
  PARAMETERS: d - the desired level
2480
  RETURN VALUE: none
2481
***************************************************************************/
2482
void mcapi_trans_set_debug_level (int d)
2483
{
2484
  //if (!WITH_DEBUG) {
2485
    //printf("ERROR mcapi_trans_set_debug_level : This library was built without debug support.\n");
2486
  //printf("If you want to enable debugging, re-build with the --enable-debug option.\n");
2487
  //} else {
2488
  mcapi_debug = d;
2489
  //}
2490
  }
2491
 
2492
/***************************************************************************
2493
  NAME: get_private_data_index
2494
  DESCRIPTION: Retuns the index for this <pid,tid> into the private globals array.
2495
  PARAMETERS: none
2496
  RETURN VALUE: The index.
2497
***************************************************************************/
2498
int get_private_data_index () {
2499
/* { */
2500
/*   /\* note: an optimization to searching this structure would be for */
2501
/*      mcapi_initialize to return a handle that we could just use to  */
2502
/*      index.  *\/ */
2503
/*   int i; */
2504
/*   int pid; */
2505
 
2506
/*   pthread_t tid; */
2507
/*   pid = getpid(); */
2508
/*   tid = pthread_self(); */
2509
/*   //assert(pid); */
2510
/*   for (i = 0; i < MAX_ENDPOINTS; i++) { */
2511
/*     if ((d[i].pid == pid) && (pthread_equal(d[i].tid,tid))) { */
2512
/*       return i; */
2513
/*     } */
2514
/*     if (d[i].pid == 0) { */
2515
/*       break; */
2516
/*     } */
2517
/*   } */
2518
/*   fprintf(stderr,"FAIL: PID:%u TID:%s (has initialize been called yet?)\n",pid,print_tid(tid));   */
2519
  return 0;
2520
}
2521
 
2522
/***************************************************************************
2523
  NAME: setup_request_internal
2524
  DESCRIPTION: Sets up the request for a non-blocking function.
2525
  PARAMETERS:
2526
     handle -
2527
     request -
2528
     mcapi_status -
2529
     completed - whether the request has already been completed or not (usually
2530
       it has - receives to an empty queue or get_endpoint for endpoints that
2531
       don't yet exist are the two main cases where completed will be false)
2532
     size -
2533
     buffer - the buffer
2534
     type - the type of the request
2535
  RETURN VALUE:
2536
***************************************************************************/
2537
void setup_request_internal (mcapi_endpoint_t* handle,mcapi_request_t* request,
2538
                             mcapi_status_t* mcapi_status, mcapi_boolean_t completed,
2539
                             size_t size,void** buffer,mcapi_request_type type)
2540
{
2541
 
2542
  int i,qindex;
2543
  uint16_t n,e;
2544
  mcapi_boolean_t rv = MCAPI_FALSE;
2545
 
2546
  if (!valid_request_param (request)) {
2547
    return;
2548
  }
2549
 
2550
  /* the database should already be locked */
2551
  request->valid = MCAPI_TRUE;
2552
  request->status = *mcapi_status;
2553
  request->size = size;
2554
  request->cancelled = MCAPI_FALSE;
2555
  request->completed = completed;
2556
 
2557
  /* this is hacky, there's probably a better way to do this */
2558
  if ((buffer != NULL) && (!completed)) {
2559
    rv = mcapi_trans_decode_handle_internal(*handle,&n,&e);
2560
    //assert(rv);
2561
    if ( c_db->nodes[n].node_d.endpoints[e].recv_queue.channel_type == MCAPI_PKT_CHAN) {
2562
      /* packet buffer means system buffer, so save the users pointer to the buffer */
2563
      request->buffer_ptr = buffer;
2564
    } else {
2565
      /* message buffer means user buffer, so save the users buffer */
2566
      request->buffer = *buffer;
2567
    }
2568
  }
2569
  request->type = type;
2570
  request->handle = *handle;
2571
 
2572
  /* save the pointer so that we can fill it in (the endpoint may not have been created yet)
2573
     an alternative is to make buffer a void* and use it for everything (messages, endpoints, etc.) */
2574
  if (request->type == GET_ENDPT) {
2575
    request->endpoint = handle;
2576
  }
2577
 
2578
  /* if this was a non-blocking receive to an empty queue, then reserve the next buffer */
2579
  if ((type == RECV) && (!completed)) {
2580
    rv = mcapi_trans_decode_handle_internal(*handle,&n,&e);
2581
    //assert(rv);
2582
    /*find the queue entry that doesn't already have a request associated with it */
2583
    for (i = 0; i < MAX_QUEUE_ENTRIES; i++) {
2584
      /* walk from head to tail */
2585
      qindex = (c_db->nodes[n].node_d.endpoints[e].recv_queue.head + i) % (MAX_QUEUE_ENTRIES);
2586
      if ((!c_db->nodes[n].node_d.endpoints[e].recv_queue.elements[qindex].request) &&
2587
          (!c_db->nodes[n].node_d.endpoints[e].recv_queue.elements[qindex].invalid)) {
2588
        mcapi_dprintf(4," receive request reserving qindex=%i\n",qindex);
2589
        c_db->nodes[n].node_d.endpoints[e].recv_queue.elements[qindex].request = request;
2590
        break;
2591
      }
2592
    }
2593
    if (i == MAX_QUEUE_ENTRIES) {
2594
      /* all of this endpoint's buffers already have reqeusts associated with them */
2595
      *mcapi_status = MCAPI_ENO_REQUEST;
2596
      request->completed = MCAPI_TRUE;
2597
    }
2598
  }
2599
}
2600
 
2601
/***************************************************************************
2602
  NAME:mcapi_trans_display_state
2603
  DESCRIPTION: This function is useful for debugging.  If the handle is null,
2604
   we'll print out the state of the entire database.  Otherwise, we'll print out
2605
   only the state of the endpoint that the handle refers to.
2606
  PARAMETERS:
2607
     handle
2608
  RETURN VALUE: none
2609
***************************************************************************/
2610
void mcapi_trans_display_state (void* handle)
2611
{
2612
  /* lock the database */
2613
  // mcapi_trans_access_database_pre_nocheck();  
2614
  mcapi_trans_display_state_internal(handle);
2615
  /* unlock the database */
2616
  // mcapi_trans_access_database_post_nocheck();
2617
}
2618
 
2619
/***************************************************************************
2620
  NAME:mcapi_trans_display_state_internal
2621
  DESCRIPTION: This function is useful for debugging.  If the handle is null,
2622
   we'll print out the state of the entire database.  Otherwise, we'll print out
2623
   only the state of the endpoint that the handle refers to.  Expects the database
2624
   to be locked.
2625
  PARAMETERS:
2626
     handle
2627
  RETURN VALUE: none
2628
***************************************************************************/
2629
void mcapi_trans_display_state_internal (void* handle)
2630
{
2631
#ifdef __TCE__
2632
    return;
2633
#else
2634
  uint16_t n,e,a;
2635
  mcapi_endpoint_t* endpoint = (mcapi_endpoint_t*)handle;
2636
  mcapi_boolean_t rv = MCAPI_FALSE;
2637
 
2638
  printf("DISPLAY STATE:\n");
2639
 
2640
 
2641
  if (handle != NULL) {
2642
   /* print the data for the given endpoint */
2643
   rv = mcapi_trans_decode_handle_internal(*endpoint,&n,&e);
2644
   //assert(rv); 
2645
   printf("node: %u, port: %u, receive queue (num_elements=%i):\n",
2646
          (unsigned)c_db->nodes[n].node_num,(unsigned)c_db->nodes[n].node_d.endpoints[e].port_num,
2647
          (unsigned)c_db->nodes[n].node_d.endpoints[e].recv_queue.num_elements);
2648
 
2649
   printf("    endpoint: %d\n",e);
2650
   printf("      valid:%d\n",c_db->nodes[n].node_d.endpoints[e].valid);
2651
   printf("      anonymous:%d\n",c_db->nodes[n].node_d.endpoints[e].anonymous);
2652
   printf("      open:%d\n",c_db->nodes[n].node_d.endpoints[e].open);
2653
   printf("      connected:%d\n",c_db->nodes[n].node_d.endpoints[e].connected);
2654
   printf("      num_attributes:%d\n",(unsigned)c_db->nodes[n].node_d.endpoints[e].num_attributes);
2655
   for (a = 0; a < c_db->nodes[n].node_d.endpoints[e].num_attributes; a++) {
2656
     printf("        attribute:%d\n",a);
2657
     printf("          valid:%d\n",c_db->nodes[n].node_d.endpoints[e].attributes[a].valid);
2658
     printf("          attribute_num:%d\n",c_db->nodes[n].node_d.endpoints[e].attributes[a].attribute_num);
2659
     printf("          bytes:%i\n",(unsigned)c_db->nodes[n].node_d.endpoints[e].attributes[a].bytes);
2660
   }
2661
   print_queue(c_db->nodes[n].node_d.endpoints[e].recv_queue);
2662
  } else {
2663
    /* print the whole database */
2664
    for (n = 0; n < c_db->num_nodes; n++) {
2665
      printf("n=%d\n",n);
2666
      printf("node: %u\n",(unsigned)c_db->nodes[n].node_num);
2667
      printf("  valid:%d\n",c_db->nodes[n].valid);
2668
      printf("  finalized:%d\n",c_db->nodes[n].finalized);
2669
      printf("  num_endpoints:%d\n",c_db->nodes[n].node_d.num_endpoints);
2670
      for (e = 0; e < c_db->nodes[n].node_d.num_endpoints; e++) {
2671
        printf("    e=%d\n",e);
2672
        printf("    endpoint: %u\n",(unsigned)c_db->nodes[n].node_d.endpoints[e].port_num);
2673
        printf("      valid:%d\n",c_db->nodes[n].node_d.endpoints[e].valid);
2674
        printf("      anonymous:%d\n",c_db->nodes[n].node_d.endpoints[e].anonymous);
2675
        printf("      open:%d\n",c_db->nodes[n].node_d.endpoints[e].open);
2676
        printf("      connected:%d\n",c_db->nodes[n].node_d.endpoints[e].connected);
2677
        printf("      num_attributes:%u\n",(unsigned)c_db->nodes[n].node_d.endpoints[e].num_attributes);
2678
        for (a = 0; a < c_db->nodes[n].node_d.endpoints[e].num_attributes; a++) {
2679
          printf("        a=%d\n",a);
2680
          printf("        attribute:%d\n",a);
2681
          printf("          valid:%d\n",c_db->nodes[n].node_d.endpoints[e].attributes[a].valid);
2682
          printf("          attribute_num:%d\n",c_db->nodes[n].node_d.endpoints[e].attributes[a].attribute_num);
2683
          printf("          bytes:%u\n",(unsigned)c_db->nodes[n].node_d.endpoints[e].attributes[a].bytes);
2684
        }
2685
        print_queue(c_db->nodes[n].node_d.endpoints[e].recv_queue);
2686
      }
2687
    }
2688
  }
2689
  printf("\n\n");
2690
#endif
2691
}
2692
 
2693
 
2694
/***************************************************************************
2695
  NAME:check_get_endpt_request
2696
  DESCRIPTION: Checks if the request to get an endpoint has been completed or not.
2697
  PARAMETERS: the request pointer (to be filled in)
2698
  RETURN VALUE: none
2699
***************************************************************************/
2700
void check_get_endpt_request (mcapi_request_t *request)
2701
{
2702
 
2703
  /* lock the database */
2704
  // mcapi_trans_access_database_pre();
2705
 
2706
  if (mcapi_trans_get_endpoint_internal (request->endpoint, request->node_num,
2707
                                         request->port_num)) {
2708
    request->completed = MCAPI_TRUE;
2709
    request->status = MCAPI_SUCCESS;
2710
  }
2711
 
2712
  /* unlock the database */
2713
  // mcapi_trans_access_database_post();
2714
}
2715
 
2716
/***************************************************************************
2717
  NAME: cancel_receive_request
2718
  DESCRIPTION: Cancels an outstanding receive request.  This is a little tricky
2719
     because we have to preserve FIFO which means we have to shift all other
2720
     outstanding receive requests down.
2721
  PARAMETERS:
2722
     request -
2723
  RETURN VALUE: none
2724
***************************************************************************/
2725
void cancel_receive_request (mcapi_request_t *request)
2726
{
2727
  uint16_t rn,re;
2728
  int i,last,start,curr;
2729
  mcapi_boolean_t rv = MCAPI_FALSE;
2730
 
2731
  /* lock the database */
2732
  // mcapi_trans_access_database_pre();
2733
 
2734
  rv = mcapi_trans_decode_handle_internal(request->handle,&rn,&re);
2735
  //assert(rv);
2736
  for (i = 0; i < MAX_QUEUE_ENTRIES; i++) {
2737
    if (c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[i].request == request) {
2738
      /* we found the request, now clear the reservation */
2739
      mcapi_dprintf(5,"cancel_receive_request - cancelling request at index %i\n BEFORE:",i);
2740
      print_queue(c_db->nodes[rn].node_d.endpoints[re].recv_queue);
2741
      c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[i].request = NULL;
2742
      break;
2743
    }
2744
  }
2745
 
2746
  /* we should have found the outstanding request */
2747
  //assert (i != MAX_QUEUE_ENTRIES);
2748
 
2749
  /* shift all pending reservations down*/
2750
  start = i;
2751
  last = start;
2752
  for (i = 0; i < MAX_QUEUE_ENTRIES; i++) {
2753
    curr = (i+start)%MAX_QUEUE_ENTRIES;
2754
    /* don't cross over the head or the tail */
2755
    if ((curr == c_db->nodes[rn].node_d.endpoints[re].recv_queue.tail) &&
2756
        (curr != start)) {
2757
      break;
2758
    }
2759
    if ((curr == c_db->nodes[rn].node_d.endpoints[re].recv_queue.head) &&
2760
        (curr != start)) {
2761
      break;
2762
    }
2763
    if (c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[curr].request) {
2764
     mcapi_dprintf(5,"cancel_receive_request - shifting request at index %i to index %i\n",curr,last);
2765
     c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[last].request =
2766
        c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[curr].request;
2767
      c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[curr].request = NULL;
2768
      last = curr;
2769
    }
2770
  }
2771
 
2772
  request->cancelled = MCAPI_TRUE;
2773
 
2774
  /* unlock the database */
2775
  // mcapi_trans_access_database_post();
2776
}
2777
 
2778
/***************************************************************************
2779
  NAME: check_receive_request
2780
  DESCRIPTION: Checks if the given non-blocking receive request has completed.
2781
     This is a little tricky because we can't just pop from the head of the
2782
     endpoints receive queue.  We have to locate the reservation that was
2783
     made in the queue (to preserve FIFO) at the time the request was made.
2784
  PARAMETERS: the request pointer (to be filled in
2785
  RETURN VALUE: none
2786
***************************************************************************/
2787
void check_receive_request (mcapi_request_t *request)
2788
{
2789
  uint16_t rn,re;
2790
  int i;
2791
  size_t size;
2792
  mcapi_boolean_t rv = MCAPI_FALSE;
2793
 
2794
  /* lock the database */
2795
  // mcapi_trans_access_database_pre();
2796
 
2797
  rv = mcapi_trans_decode_handle_internal(request->handle,&rn,&re);
2798
  //assert(rv);
2799
  for (i = 0; i < MAX_QUEUE_ENTRIES; i++) {
2800
    if (c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[i].request == request) {
2801
      /* we found the request, check to see if there is valid data in the receive queue entry */
2802
      if (c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[i].b) {
2803
        /* clear the request reservation */
2804
        c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[i].request = NULL;
2805
        /* the buffer better still exist */
2806
        //assert (c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[i].b->in_use);
2807
        /* update the request */
2808
        request->completed = MCAPI_TRUE;
2809
        request->status = MCAPI_SUCCESS;
2810
        /* first take the entry out of the queue  this has the potential to fragment our
2811
           receive queue since we may not be removing from the head */
2812
        if ( c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type == MCAPI_PKT_CHAN) {
2813
          /* packet buffer means system buffer, so save the users pointer to the buffer */
2814
            mcapi_trans_recv_internal_ (rn,re,request->buffer_ptr,request->size,&request->size,i,NULL);
2815
        } else {
2816
          /* message buffer means user buffer, so save the users buffer */
2817
          size = request->size;
2818
          mcapi_trans_recv_internal_ (rn,re,&request->buffer,request->size,&request->size,i,NULL);
2819
          if (request->size > size) {
2820
            request->size = size;
2821
            request->status = MCAPI_ETRUNCATED;
2822
          }
2823
        }
2824
        /* now update the receive queue state */
2825
        c_db->nodes[rn].node_d.endpoints[re].recv_queue.num_elements--;
2826
        /* mark this entry as invalid so that the "bubble" won't be re-used */
2827
        c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[i].invalid = MCAPI_TRUE;
2828
        mcapi_trans_compact_queue (&c_db->nodes[rn].node_d.endpoints[re].recv_queue);
2829
        mcapi_dprintf(4," receive request (test/wait) popped from qindex=%i, num_elements=%i, head=%i, tail=%i\n",
2830
                      i,c_db->nodes[rn].node_d.endpoints[re].recv_queue.num_elements,
2831
                      c_db->nodes[rn].node_d.endpoints[re].recv_queue.head,
2832
                      c_db->nodes[rn].node_d.endpoints[re].recv_queue.tail);
2833
      }
2834
      break;
2835
    }
2836
  }
2837
  /* we should have found the outstanding request */
2838
  //assert (i != MAX_QUEUE_ENTRIES);
2839
 
2840
  /* unlock the database */
2841
  // mcapi_trans_access_database_post();
2842
}
2843
 
2844
/***************************************************************************
2845
  NAME:mcapi_trans_connect_channel_internal
2846
  DESCRIPTION: connects a channel
2847
  PARAMETERS:
2848
     send_endpoint
2849
     receive_endpoint
2850
     type
2851
  RETURN VALUE:none
2852
***************************************************************************/
2853
void mcapi_trans_connect_channel_internal (mcapi_endpoint_t send_endpoint,
2854
                                  mcapi_endpoint_t receive_endpoint,channel_type type)
2855
{
2856
  uint16_t sn,se;
2857
  uint16_t rn,re;
2858
  mcapi_boolean_t rv = MCAPI_FALSE;
2859
 
2860
  /* the database should already be locked */
2861
 
2862
  rv = mcapi_trans_decode_handle_internal(send_endpoint,&sn,&se);
2863
  //assert(rv);
2864
  rv = mcapi_trans_decode_handle_internal(receive_endpoint,&rn,&re);
2865
  //assert(rv);
2866
 
2867
  /* update the send endpoint */
2868
  c_db->nodes[sn].node_d.endpoints[se].connected = MCAPI_TRUE;
2869
  c_db->nodes[sn].node_d.endpoints[se].recv_queue.recv_endpt = receive_endpoint;
2870
  c_db->nodes[sn].node_d.endpoints[se].recv_queue.send_endpt = send_endpoint;
2871
  c_db->nodes[sn].node_d.endpoints[se].recv_queue.channel_type = type;
2872
 
2873
  /* update the receive endpoint */
2874
  c_db->nodes[rn].node_d.endpoints[re].connected = MCAPI_TRUE;
2875
  c_db->nodes[rn].node_d.endpoints[re].recv_queue.send_endpt = send_endpoint;
2876
  c_db->nodes[rn].node_d.endpoints[re].recv_queue.recv_endpt = receive_endpoint;
2877
  c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type = type;
2878
 
2879
 
2880
  mcapi_dprintf(1," channel_type=%d connected sender (node=%d,port=%d) to receiver (node=%d,port=%d)\n",
2881
                type,c_db->nodes[sn].node_num,c_db->nodes[sn].node_d.endpoints[se].port_num,
2882
                c_db->nodes[rn].node_num,c_db->nodes[rn].node_d.endpoints[re].port_num);
2883
 
2884
}
2885
 
2886
/***************************************************************************
2887
  NAME:mcapi_trans_send_internal
2888
  DESCRIPTION: Attempts to send a message from one endpoint to another
2889
  PARAMETERS:
2890
    sn - the send node index (only used for verbose debug print)
2891
    se - the send endpoint index (only used for verbose debug print)
2892
    rn - the receive node index
2893
    re - the receive endpoint index
2894
    buffer -
2895
    buffer_size -
2896
    blocking - whether or not this is a blocking send (currently not used!)
2897
  RETURN VALUE: true/false indicating success or failure
2898
***************************************************************************/
2899
mcapi_boolean_t mcapi_trans_send_internal (
2900
    uint16_t sn,uint16_t se, uint16_t rn, uint16_t re,
2901
    char* buffer, size_t buffer_size,mcapi_boolean_t blocking,uint64_t scalar)
2902
{
2903
  int qindex,i;
2904
  buffer_entry* db_buff = NULL;
2905
 
2906
  mcapi_dprintf(3," mcapi_trans_send_internal sender (node=%d,port=%d) to receiver (node=%d,port=%d)\n",
2907
                c_db->nodes[sn].node_num,c_db->nodes[sn].node_d.endpoints[se].port_num,
2908
                c_db->nodes[rn].node_num,c_db->nodes[rn].node_d.endpoints[re].port_num);
2909
 
2910
  /* The database should already be locked! */
2911
 
2912
  /* Note: the blocking parameter is not used.
2913
     I'm not sure if I'm implementing blocking sends correctly.  They can still
2914
     return ENO_BUFFER, so it doesn't look from the spec like they are supposed to block
2915
     until a buffer is free.  A blocking receive blocks on an empty queue until there is
2916
     something available, but a blocking send does not block on a full queue.  Is that correct? */
2917
  if (mcapi_trans_full_queue(c_db->nodes[rn].node_d.endpoints[re].recv_queue)) {
2918
    /* we couldn't get space in the endpoints receive queue, try to compact the queue */
2919
    mcapi_trans_compact_queue(&c_db->nodes[rn].node_d.endpoints[re].recv_queue);
2920
    return MCAPI_FALSE;
2921
  }
2922
 
2923
  /* find a free mcapi buffer (we only have to worry about this on the sending side) */
2924
  for (i = 0; i < MAX_BUFFERS; i++) {
2925
    if (!c_db->buffers[i].in_use) {
2926
      c_db->buffers[i].in_use = MCAPI_TRUE;
2927
      c_db->buffers[i].magic_num = MAGIC_NUM;
2928
      db_buff = &c_db->buffers[i];
2929
      break;
2930
    }
2931
  }
2932
  if (i == MAX_BUFFERS) {
2933
    /* we couldn't get a free buffer */
2934
    mcapi_dprintf(2," ERROR mcapi_trans_send_internal: No more buffers available - try freeing some buffers. \n");
2935
    return MCAPI_FALSE;
2936
  }
2937
 
2938
  /* now go about updating buffer into the database... */
2939
  /* find the next index in the circular queue */
2940
  qindex = mcapi_trans_push_queue(&c_db->nodes[rn].node_d.endpoints[re].recv_queue);
2941
  mcapi_dprintf(4," send pushing %u byte buffer to qindex=%i, num_elements=%i, head=%i, tail=%i\n",
2942
                buffer_size,qindex,c_db->nodes[rn].node_d.endpoints[re].recv_queue.num_elements,
2943
                c_db->nodes[rn].node_d.endpoints[re].recv_queue.head,
2944
                c_db->nodes[rn].node_d.endpoints[re].recv_queue.tail);
2945
  /* printf(" send pushing to qindex=%i\n",qindex); */
2946
  if (c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type == MCAPI_SCL_CHAN ) {
2947
    db_buff->scalar = scalar;
2948
  } else {
2949
    /* copy the buffer parm into a mcapi buffer */
2950
    memcpy (db_buff->buff,buffer,buffer_size);
2951
  }
2952
  /* set the size */
2953
  db_buff->size = buffer_size;
2954
  /* update the ptr in the receive_endpoints queue to point to our mcapi buffer */
2955
  c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b = db_buff;
2956
 
2957
 
2958
  return MCAPI_TRUE;
2959
}
2960
 
2961
/***************************************************************************
2962
  NAME:  mcapi_trans_recv_internal_
2963
  DESCRIPTION: Removes a message (at the given qindex) from the given
2964
    receive endpoints queue.  This function is used both by check_receive_request
2965
    and mcapi_trans_recv_internal.  We needed to separate the functionality
2966
    because in order to preserve FIFO, if recv was called to an empty queue we
2967
    had to set a reservation at the head of the queue.  Thus we can't always
2968
    just pop from the head of the queue.
2969
  PARAMETERS:
2970
    rn - the receive node index
2971
    re - the receive endpoint index
2972
    buffer -
2973
    buffer_size -
2974
    received_size - the actual size (in bytes) of the data received
2975
    qindex - index into the receive endpoints queue that we should remove from
2976
  RETURN VALUE: none
2977
***************************************************************************/
2978
void mcapi_trans_recv_internal_ (
2979
    uint16_t rn, uint16_t re, void** buffer, size_t buffer_size,
2980
    size_t* received_size,int qindex,uint64_t* scalar)
2981
{
2982
/*   size_t size; */
2983
/*   int i; */
2984
 
2985
/*   /\* the database should already be locked! *\/ */
2986
 
2987
/*   mcapi_dprintf(3," mcapi_trans_recv_internal_ for receiver (node=%d,port=%d)\n",  */
2988
/*                 c_db->nodes[rn].node_num,c_db->nodes[rn].node_d.endpoints[re].port_num); */
2989
 
2990
/*   /\* printf(" recv popping from qindex=%i\n",qindex); *\/ */
2991
/*   /\* first make sure buffer is big enough for the message *\/ */
2992
/*   if ((buffer_size) < c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b->size) { */
2993
/*     fprintf(stderr,"ERROR: mcapi_trans_recv_internal buffer not big enough - loss of data: buffer_size=%i, element_size=%i\n", */
2994
/*             (int)buffer_size, */
2995
/*             (int)c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b->size); */
2996
/*     /\* NOTE: MCAPI_ETRUNCATED will be set by the calling functions by noticing that buffer_size < received_size *\/ */
2997
/*   } */
2998
 
2999
/*   /\* set the size *\/ */
3000
/*   size = c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b->size; */
3001
 
3002
/*   /\* fill in the size *\/ */
3003
/*   *received_size = size; */
3004
/*   if (buffer_size < size) { */
3005
/*     size = buffer_size; */
3006
/*   }  */
3007
 
3008
/*   mcapi_dprintf(4," receive popping %u byte buffer from qindex=%i, num_elements=%i, head=%i, tail=%i\n", */
3009
/*                 size,qindex,c_db->nodes[rn].node_d.endpoints[re].recv_queue.num_elements, */
3010
/*                 c_db->nodes[rn].node_d.endpoints[re].recv_queue.head, */
3011
/*                 c_db->nodes[rn].node_d.endpoints[re].recv_queue.tail); */
3012
 
3013
/*   /\* copy the buffer out of the receive_endpoint's queue and into the buffer parm *\/ */
3014
/*   if (c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type == MCAPI_PKT_CHAN) { */
3015
/*     /\* mcapi supplied buffer (pkt receive), so just update the pointer *\/ */
3016
/*     *buffer = c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b->buff; */
3017
/*   } else { */
3018
/*     /\* user supplied buffer, copy it in and free the mcapi buffer *\/ */
3019
/*     if   (c_db->nodes[rn].node_d.endpoints[re].recv_queue.channel_type == MCAPI_SCL_CHAN) { */
3020
/*       /\* scalar receive *\/ */
3021
/*       *scalar = c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b->scalar; */
3022
/*     } else { */
3023
/*       /\* msg receive *\/ */
3024
/*       memcpy (*buffer,c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b->buff,size); */
3025
/*     } */
3026
/*     /\* free the mcapi message buffer *\/ */
3027
/*     for (i = 0; i < MAX_BUFFERS; i++) { */
3028
/*       if ((c_db->buffers[i].in_use) &&  */
3029
/*           (c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b->buff ==  */
3030
/*            c_db->buffers[i].buff)) { */
3031
/*         c_db->buffers[i].in_use = MCAPI_FALSE; */
3032
/*         break; */
3033
/*       } */
3034
/*       /\* we should have found it *\/ */
3035
/*       //assert (i != MAX_BUFFERS); */
3036
/*     } */
3037
/*   } */
3038
/*   /\* clear the buffer pointer in the receive queue entry *\/ */
3039
/*   c_db->nodes[rn].node_d.endpoints[re].recv_queue.elements[qindex].b = NULL; */
3040
 
3041
}
3042
 
3043
/***************************************************************************
3044
  NAME: mcapi_trans_recv_internal
3045
  DESCRIPTION: checks if a message is available, if so performs the pop (from
3046
   the head of the queue) and sends the qindex to be used to mcapi_trans_recv_internal_
3047
  PARAMETERS:
3048
    rn - the receive node index
3049
    re - the receive endpoint index
3050
    buffer -
3051
    buffer_size -
3052
    received_size - the actual size (in bytes) of the data received
3053
    blocking - whether or not this is a blocking receive
3054
  RETURN VALUE: true/false indicating success or failure
3055
***************************************************************************/
3056
mcapi_boolean_t mcapi_trans_recv_internal (
3057
    uint16_t rn, uint16_t re, void** buffer,
3058
    size_t buffer_size, size_t* received_size,
3059
    mcapi_boolean_t blocking,uint64_t* scalar)
3060
{
3061
  int qindex;
3062
 
3063
  /* The database should already be locked! */
3064
 
3065
  if ((!blocking) && (mcapi_trans_empty_queue(c_db->nodes[rn].node_d.endpoints[re].recv_queue))) {
3066
    return MCAPI_FALSE;
3067
  }
3068
 
3069
  while (mcapi_trans_empty_queue(c_db->nodes[rn].node_d.endpoints[re].recv_queue)) {
3070
    mcapi_dprintf(5,"mcapi_trans_recv_internal to empty queue - attempting to yield\n");
3071
    /* we have the lock, use this yield */
3072
    transport_sm_yield_internal();
3073
  }
3074
 
3075
  /* remove the element from the receive endpoints queue */
3076
  qindex = mcapi_trans_pop_queue(&c_db->nodes[rn].node_d.endpoints[re].recv_queue);
3077
  mcapi_trans_recv_internal_ (rn,re,buffer,buffer_size,received_size,qindex,scalar);
3078
 
3079
  return MCAPI_TRUE;
3080
}
3081
 
3082
/***************************************************************************
3083
  NAME: mcapi_trans_open_channel_internal
3084
  DESCRIPTION: marks the given endpoint as open
3085
  PARAMETERS:
3086
    n - the node index
3087
    e - the endpoint index
3088
  RETURN VALUE: none
3089
***************************************************************************/
3090
void mcapi_trans_open_channel_internal (uint16_t n, uint16_t e)
3091
{
3092
 
3093
  /* The database should already be locked! */
3094
 
3095
  /* mark the endpoint as open */
3096
  c_db->nodes[n].node_d.endpoints[e].open = MCAPI_TRUE;
3097
 
3098
}
3099
 
3100
/***************************************************************************
3101
  NAME:mcapi_trans_close_channel_internal
3102
  DESCRIPTION: marks the given endpoint as closed
3103
  PARAMETERS:
3104
    n - the node index
3105
    e - the endpoint index
3106
  RETURN VALUE:none
3107
***************************************************************************/
3108
void mcapi_trans_close_channel_internal (uint16_t n, uint16_t e)
3109
{
3110
 
3111
  /* The database should already be locked! */
3112
 
3113
  /* mark the endpoint as closed */
3114
  c_db->nodes[n].node_d.endpoints[e].open = MCAPI_FALSE;
3115
}
3116
 
3117
/***************************************************************************
3118
  NAME:transport_sm_yield_internal
3119
  DESCRIPTION: releases the lock, attempts to yield, re-acquires the lock.
3120
  PARAMETERS: none
3121
  RETURN VALUE: none
3122
***************************************************************************/
3123
void transport_sm_yield_internal ()
3124
{
3125
  /* call this version of sched_yield when you have the lock */
3126
  /* release the lock */
3127
  // mcapi_trans_access_database_post();
3128
  //sched_yield();
3129
  /* re-acquire the lock */
3130
  // mcapi_trans_access_database_pre();
3131
}
3132
 
3133
/***************************************************************************
3134
  NAME:  mcapi_trans_access_database_pre_nocheck
3135
  DESCRIPTION: The first node that calls initialize can't do the balanced
3136
    lock/unlock checking because it hasn't registered itself yet.  Thus
3137
    the need for a nocheck version of this function.  This function
3138
    acquires the semaphore.
3139
  PARAMETERS: none
3140
  RETURN VALUE: none
3141
***************************************************************************/
3142
void mcapi_trans_access_database_pre_nocheck ()
3143
{
3144
  /* acquire the semaphore, this is a blocking function */
3145
  //transport_sm_lock_semaphore(sem_id);
3146
}
3147
 
3148
/***************************************************************************
3149
  NAME: mcapi_trans_access_database_pre
3150
  DESCRIPTION: This function acquires the semaphore.
3151
  PARAMETERS: none
3152
  RETURN VALUE:none
3153
***************************************************************************/
3154
void mcapi_trans_access_database_pre ()
3155
{
3156
/*   int i = 0; */
3157
/*   int pid = 0; */
3158
/*   pthread_t tid = 0; */
3159
 
3160
/*   /\* first acquire the semaphore, this is a blocking function *\/ */
3161
/*   transport_sm_lock_semaphore(sem_id); */
3162
 
3163
/*   if (mcapi_debug > 5) { */
3164
/*     /\* turn on balanced semaphore lock/unlock checking *\/ */
3165
/*     i = get_private_data_index(); */
3166
/*     assert (d[i].have_lock == MCAPI_FALSE); */
3167
/*     pid = d[i].pid; */
3168
/*     tid = d[i].tid; */
3169
/*     d[i].have_lock = MCAPI_TRUE; */
3170
/*     mcapi_dprintf(7," PID:%d TID%u got lock\n",pid,(unsigned long)tid); */
3171
/*   } */
3172
 
3173
}
3174
 
3175
/***************************************************************************
3176
  NAME:mcapi_trans_access_database_post_nocheck
3177
  DESCRIPTION:The first node that calls initialize can't do the balanced
3178
    lock/unlock checking because it hasn't registered itself yet.  Thus
3179
    the need for a nocheck version of this function.  This function
3180
    releases the semaphore.
3181
  PARAMETERS: none
3182
  RETURN VALUE: none
3183
***************************************************************************/
3184
void mcapi_trans_access_database_post_nocheck ()
3185
{
3186
  /* release the semaphore, this should always work */
3187
  //assert (transport_sm_unlock_semaphore(sem_id));
3188
}
3189
 
3190
/***************************************************************************
3191
  NAME:mcapi_trans_access_database_post
3192
  DESCRIPTION: This function releases the semaphore.
3193
  PARAMETERS: none
3194
  RETURN VALUE: none
3195
***************************************************************************/
3196
void mcapi_trans_access_database_post ()
3197
{
3198
  /* int i = 0; */
3199
/*   int pid = 0;; */
3200
/*   pthread_t tid = 0; */
3201
 
3202
/*   if (mcapi_debug > 5) { */
3203
/*     /\* turn on balanced semaphore lock/unlock checking *\/ */
3204
/*     i = get_private_data_index(); */
3205
/*     assert (d[i].have_lock == MCAPI_TRUE); */
3206
/*     pid = d[i].pid; */
3207
/*     tid = d[i].tid;    */
3208
/*     d[i].have_lock = MCAPI_FALSE; */
3209
/*     mcapi_dprintf(7," PID:%d TID%u released lock\n",pid,(unsigned long)tid); */
3210
/*   } */
3211
 
3212
/*   /\* finally, release the semaphore, this should always work *\/ */
3213
/*   assert (transport_sm_unlock_semaphore(sem_id)); */
3214
 
3215
}
3216
 
3217
/***************************************************************************
3218
  NAME:mcapi_trans_add_node
3219
  DESCRIPTION: Adds a node to the database (called by intialize)
3220
  PARAMETERS: node_num
3221
  RETURN VALUE: true/false indicating success or failure
3222
***************************************************************************/
3223
mcapi_boolean_t mcapi_trans_add_node (mcapi_uint_t node_num)
3224
{
3225
  mcapi_boolean_t rc = MCAPI_TRUE;
3226
 
3227
  /* lock the database */
3228
  //mcapi_trans_access_database_pre_nocheck();
3229
 
3230
  /* mcapi should have checked that the node doesn't already exist */
3231
 
3232
  if (c_db->num_nodes == MAX_NODES) {
3233
    rc = MCAPI_FALSE;
3234
  }
3235
 
3236
  if (rc) {
3237
  /* setup our local (private data) */
3238
  /* we do this while we have the lock because we don't want an inconsistency/
3239
     race condition where the node exists in the database but not yet in
3240
     the transport layer's cached state */
3241
    mcapi_trans_set_node_num(node_num);
3242
 
3243
    /* add the node */
3244
    c_db->nodes[c_db->num_nodes].finalized = MCAPI_FALSE;
3245
    c_db->nodes[c_db->num_nodes].valid = MCAPI_TRUE;
3246
    c_db->nodes[c_db->num_nodes].node_num = node_num;
3247
    c_db -> num_nodes++;
3248
  }
3249
 
3250
  /* unlock the database */
3251
  // mcapi_trans_access_database_post_nocheck();
3252
 
3253
  return rc;
3254
}
3255
 
3256
/***************************************************************************
3257
  NAME:mcapi_trans_encode_handle_internal
3258
  DESCRIPTION:
3259
   Our handles are very simple - a 32 bit integer is encoded with
3260
   an index (16 bits gives us a range of 0:64K indices).
3261
   Currently, we only have 2 indices for each of: node array and
3262
   endpoint array.
3263
  PARAMETERS:
3264
   node_index -
3265
   endpoint_index -
3266
  RETURN VALUE: the handle
3267
***************************************************************************/
3268
uint32_t mcapi_trans_encode_handle_internal (uint16_t node_index,uint16_t endpoint_index)
3269
{
3270
  /* The database should already be locked */
3271
  uint32_t handle = 0;
3272
  uint8_t shift = 16;
3273
 
3274
  //assert ((node_index < MAX_NODES) && (endpoint_index < MAX_ENDPOINTS));
3275
 
3276
  handle = node_index;
3277
  handle <<= shift;
3278
  handle |= endpoint_index;
3279
 
3280
  return handle;
3281
}
3282
 
3283
/***************************************************************************
3284
  NAME:mcapi_trans_decode_handle_internal
3285
  DESCRIPTION: Decodes the given handle into it's database indices
3286
  PARAMETERS:
3287
   handle -
3288
   node_index -
3289
   endpoint_index -
3290
  RETURN VALUE: true/false indicating success or failure
3291
***************************************************************************/
3292
mcapi_boolean_t mcapi_trans_decode_handle_internal (uint32_t handle, uint16_t *node_index,
3293
                                                    uint16_t *endpoint_index)
3294
{
3295
  //int rc = MCAPI_FALSE;
3296
  uint8_t shift = 16;
3297
 
3298
  /* The database should already be locked */
3299
  *node_index              = (handle & 0xffff0000) >> shift;
3300
  *endpoint_index          = (handle & 0x0000ffff);
3301
 
3302
  if (*node_index >= MAX_NODES || *endpoint_index >= MAX_ENDPOINTS) {
3303
      return MCAPI_FALSE;
3304
  }
3305
 
3306
  if (*node_index == my_node_id &&
3307
      !(c_db->nodes[*node_index].node_d.endpoints[*endpoint_index].valid)) {
3308
      return MCAPI_FALSE;
3309
  }
3310
  return MCAPI_TRUE;
3311
}
3312
 
3313
/***************************************************************************
3314
  NAME: mcapi_trans_set_node_num
3315
  DESCRIPTION: sets the node_num
3316
  PARAMETERS: n: the node_num
3317
  RETURN VALUE: boolean indicating success (there was room in our data array) or failure
3318
   (couldn't find a free entry to set the node_num)
3319
***************************************************************************/
3320
mcapi_boolean_t mcapi_trans_set_node_num(mcapi_uint_t n)
3321
{
3322
 /*  /\* note: an optimization to searching this structure would be for */
3323
/*      mcapi_initialize to return a handle that we could just use to  */
3324
/*      index.  *\/ */
3325
/*   int i; */
3326
 
3327
/*   for (i = 0; i < MAX_ENDPOINTS; i++) { */
3328
/*     /\* assume pid=0 means this entry is not being used *\/ */
3329
/*     if (!d[i].pid) { */
3330
/*       d[i].pid = getpid(); */
3331
/*       d[i].tid = pthread_self(); */
3332
/*       d[i].node_num = n; */
3333
 
3334
/*       mcapi_dprintf(1," Adding node: NODE:%u PID:%u TID:%u\n",n,(int)d[i].pid, */
3335
/*                     (unsigned long)d[i].tid); */
3336
 
3337
/*       return MCAPI_TRUE; */
3338
/*     } */
3339
/*   } */
3340
/*   assert(!"we should never get here"); */
3341
  return MCAPI_FALSE;
3342
}
3343
 
3344
/***************************************************************************
3345
  NAME: mcapi_trans_get_node_index
3346
  DESCRIPTION: Returns the index into our database corresponding to the node_num
3347
  PARAMETERS: n: the node_num
3348
  RETURN VALUE:
3349
***************************************************************************/
3350
mcapi_boolean_t mcapi_trans_get_node_index(mcapi_uint_t node_num)
3351
{
3352
 /*  /\* look up the node *\/ */
3353
/*   int i; */
3354
/*   uint32_t node_index = MAX_NODES; */
3355
/*   for (i = 0; i < c_db->num_nodes; i++) { */
3356
/*     if (c_db->nodes[i].node_num == node_num) { */
3357
/*       node_index = i; */
3358
/*       break; */
3359
/*     } */
3360
/*   } */
3361
/*   assert (node_index != MAX_NODES); */
3362
   return node_num;
3363
}
3364
 
3365
 
3366
 
3367
 
3368
 
3369
 
3370
 
3371
 
3372
 
3373
 
3374
 
3375
 
3376
 
3377
 
3378
 
3379
 
3380
 
3381
 
3382
 
3383
 
3384
 
3385
 
3386
 
3387
 
3388
 
3389
 
3390
 
3391
 
3392
 
3393
 
3394
 
3395
//////////////////////////////////////////////////////////////////////////////
3396
//                                                                          //
3397
//                   queue management                                       //
3398
//                                                                          //
3399
//////////////////////////////////////////////////////////////////////////////
3400
/***************************************************************************
3401
  NAME: print_queue
3402
  DESCRIPTION: Prints an endpoints receive queue (useful for debugging)
3403
  PARAMETERS: q - the queue
3404
  RETURN VALUE: none
3405
***************************************************************************/
3406
void print_queue (queue q)
3407
{
3408
#ifdef __TCE__
3409
  return;
3410
#else
3411
  int i,qindex;
3412
  /*print the recv queue from head to tail*/
3413
  printf("      recv_queue:\n");
3414
  for (i = 0; i < MAX_QUEUE_ENTRIES; i++) {
3415
    /* walk the queue from the head to the tail */
3416
    qindex = (q.head + i) % (MAX_QUEUE_ENTRIES);
3417
    printf("          ----------------QINDEX: %i",qindex);
3418
    if (q.head == qindex) { printf("           *** HEAD ***"); }
3419
    if (q.tail == qindex) { printf("           *** TAIL ***"); }
3420
    printf("\n          request:0x%lx\n",(long unsigned int)q.elements[qindex].request);
3421
    if (q.elements[qindex].request) {
3422
      printf("             valid:%u\n",q.elements[qindex].request->valid);
3423
      printf("             size:%u\n",(int)q.elements[qindex].request->size);
3424
      switch (q.elements[qindex].request->type) {
3425
      case (OTHER_REQUEST): printf("             type:OTHER\n"); break;
3426
      case (SEND): printf("             type:SEND\n"); break;
3427
      case (RECV): printf("             type:RECV\n"); break;
3428
      case (GET_ENDPT): printf("             type:GET_ENDPT\n"); break;
3429
      default:  printf("             type:UNKNOWN!!!\n"); break;
3430
      };
3431
      printf("             buffer:[%s]\n",(char*)q.elements[qindex].request->buffer);
3432
      printf("             buffer_ptr:0x%lx\n",(long unsigned int)q.elements[qindex].request->buffer_ptr);
3433
      printf("             completed:%u\n",q.elements[qindex].request->completed);
3434
      printf("             cancelled:%u\n",q.elements[qindex].request->cancelled);
3435
      printf("             handle:0x%i\n",(int)q.elements[qindex].request->handle);
3436
      /*   printf("             status:%s\n",mcapi_display_status(q.elements[qindex].request->status)); */
3437
      printf("             status:%i\n",(int)q.elements[qindex].request->status);
3438
      printf("             endpoint:0x%lx\n",(long unsigned int)q.elements[qindex].request->endpoint);
3439
    }
3440
    printf("          invalid:%u\n",q.elements[qindex].invalid);
3441
 
3442
    printf("          b:0x%lx\n",(long unsigned int)q.elements[qindex].b);
3443
    if (q.elements[qindex].b) {
3444
      printf("             size:%u\n",(unsigned)q.elements[qindex].b->size);
3445
      printf("             in_use:%u\n",q.elements[qindex].b->in_use);
3446
      printf("             buff:[%s]\n\n",(char*)q.elements[qindex].b->buff);
3447
    }
3448
  }
3449
#endif
3450
}
3451
 
3452
/***************************************************************************
3453
  NAME: push_queue
3454
  DESCRIPTION: Returns the qindex that should be used for adding an element.
3455
     Also updates the num_elements, and tail pointer.
3456
  PARAMETERS: q - the queue pointer
3457
  RETURN VALUE: the qindex to be used
3458
***************************************************************************/
3459
int mcapi_trans_push_queue(queue* q)
3460
{
3461
  int i;
3462
 
3463
  if ( (q->tail + 1) % MAX_QUEUE_ENTRIES == q->head) {
3464
    /* assert (q->num_elements ==  MAX_QUEUE_ENTRIES);*/
3465
    //assert(!"push_queue called on full queue\n");
3466
  }
3467
  q->num_elements++;
3468
  i = q->tail;
3469
  q->tail = ++q->tail % MAX_QUEUE_ENTRIES;
3470
  //assert (q->head != q->tail);
3471
  return i;
3472
}
3473
 
3474
/***************************************************************************
3475
  NAME: pop_queue
3476
  DESCRIPTION: Returns the qindex that should be used for removing an element.
3477
     Also updates the num_elements, and head pointer.
3478
  PARAMETERS: q - the queue pointer
3479
  RETURN VALUE: the qindex to be used
3480
***************************************************************************/
3481
int mcapi_trans_pop_queue (queue* q)
3482
{
3483
  int i,qindex;
3484
  int x = 0;
3485
 
3486
  if (q->head == q->tail) {
3487
    /*assert (q->num_elements ==  0);*/
3488
    //assert (!"pop_queue called on empty queue\n");
3489
  }
3490
 
3491
  /* we can't just pop the first element off the head of the queue, because it
3492
     may be reserved for an earlier recv call, we need to take the first element
3493
     that doesn't already have a request associated with it.  This can fragment
3494
     our queue. */
3495
  for (i = 0; i < MAX_QUEUE_ENTRIES; i++) {
3496
    /* walk the queue from the head to the tail */
3497
    qindex = (q->head + i) % (MAX_QUEUE_ENTRIES);
3498
    if ((!q->elements[qindex].request) &&
3499
        (q->elements[qindex].b)){
3500
      x = qindex;
3501
      break;
3502
    }
3503
  }
3504
  if (i == MAX_QUEUE_ENTRIES) {
3505
    /* all of this endpoint's buffers already have requests associated with them */
3506
    //assert(0); /* mcapi_trans_empty_queue should have already checked for this case */
3507
  }
3508
 
3509
  q->num_elements--;
3510
 
3511
  /* if we are removing from the front of the queue, then move head */
3512
  if (x == q->head) {
3513
    q->head = ++q->head % MAX_QUEUE_ENTRIES;
3514
  } else {
3515
    /* we are fragmenting the queue, mark this entry as invalid */
3516
    q->elements[qindex].invalid = MCAPI_TRUE;
3517
  }
3518
 
3519
  if (q->num_elements > 0) {
3520
    //assert (q->head != q->tail);
3521
  }
3522
 
3523
  mcapi_trans_compact_queue (q);
3524
 
3525
  return x;
3526
}
3527
 
3528
/***************************************************************************
3529
  NAME: compact_queue
3530
  DESCRIPTION: Attempts to compact the queue.  It can become fragmented based
3531
     on the order that blocking/non-blocking sends/receives/tests come in
3532
  PARAMETERS: q - the queue pointer
3533
  RETURN VALUE: none
3534
***************************************************************************/
3535
void mcapi_trans_compact_queue (queue* q)
3536
{
3537
  int i;
3538
  int qindex;
3539
 
3540
  mcapi_dprintf(7,"before mcapi_trans_compact_queue head=%i,tail=%i,num_elements=%i\n",q->head,q->tail,q->num_elements);
3541
  for (i = 0; i < MAX_QUEUE_ENTRIES; i++) {
3542
    qindex = (q->head + i) % (MAX_QUEUE_ENTRIES);
3543
    if ((qindex == q->tail) ||
3544
        (q->elements[qindex].request) ||
3545
        (q->elements[qindex].b)){
3546
      break;
3547
    } else {
3548
      /* advance the head pointer */
3549
      q->elements[qindex].invalid = MCAPI_FALSE;
3550
      q->head = ++q->head % MAX_QUEUE_ENTRIES;
3551
      i--;
3552
    }
3553
  }
3554
  mcapi_dprintf(7,"after mcapi_trans_compact_queue head=%i,tail=%i,num_elements=%i\n",q->head,q->tail,q->num_elements);
3555
  if (q->num_elements > 0) {
3556
    //assert (q->head != q->tail);
3557
  }
3558
 
3559
}
3560
 
3561
 
3562
/***************************************************************************
3563
  NAME: mcapi_trans_empty_queue
3564
  DESCRIPTION: Checks if the queue is empty or not
3565
  PARAMETERS: q - the queue
3566
  RETURN VALUE: true/false
3567
***************************************************************************/
3568
mcapi_boolean_t mcapi_trans_empty_queue (queue q)
3569
{
3570
  int i,qindex;
3571
  if  (q.head == q.tail) {
3572
    /* assert (q.num_elements ==  0); */
3573
    return MCAPI_TRUE;
3574
  }
3575
 
3576
  /* if we have any buffers in our queue that don't have
3577
     reservations, then our queue is non-empty */
3578
  for (i = 0; i < MAX_QUEUE_ENTRIES; i++) {
3579
    qindex = (q.head + i) % (MAX_QUEUE_ENTRIES);
3580
    if ((!q.elements[qindex].request) &&
3581
        (q.elements[qindex].b)){
3582
      break;
3583
    }
3584
  }
3585
  if (i == MAX_QUEUE_ENTRIES) {
3586
    return MCAPI_TRUE;
3587
  }
3588
 
3589
  return MCAPI_FALSE;
3590
}
3591
 
3592
/***************************************************************************
3593
  NAME: mcapi_trans_full_queue
3594
  DESCRIPTION: Checks if the queue is full or not
3595
  PARAMETERS: q - the queue
3596
  RETURN VALUE: true/false
3597
***************************************************************************/
3598
mcapi_boolean_t mcapi_trans_full_queue (queue q)
3599
{
3600
  if ( (q.tail + 1) % MAX_QUEUE_ENTRIES == q.head) {
3601
    /*  assert (q.num_elements ==  (MAX_QUEUE_ENTRIES -1)); */
3602
    return MCAPI_TRUE;
3603
  }
3604
  return MCAPI_FALSE;
3605
}
3606
 
3607
 
3608
 
3609
 
3610
 
3611
 
3612
 
3613
 
3614
 

powered by: WebSVN 2.1.0

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