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 172

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

powered by: WebSVN 2.1.0

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