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

Subversion Repositories rio

[/] [rio/] [trunk/] [sw/] [stack/] [riopacket.c] - Blame information for rev 49

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 49 magro732
/*******************************************************************************
2
 *
3
 * RapidIO IP Library Core
4
 *
5
 * This file is part of the RapidIO IP library project
6
 * http://www.opencores.org/cores/rio/
7
 *
8
 * Description:
9
 * This file contains an "object" that can create and parse RapidIO packets.
10
 * It is used in the SW RapidIO stack, riostack.c, but can also be used
11
 * stand-alone together with other software, for example to tunnel RapidIO
12
 * packet over an arbitrary network.
13
 * More details about the usage can be found in the module tests in
14
 * test_riopacket.c.
15
 *
16
 * To Do:
17
 * - Add packet handlers for 8-bit deviceIds.
18
 *
19
 * Author(s):
20
 * - Magnus Rosenius, magro732@opencores.org
21
 *
22
 *******************************************************************************
23
 *
24
 * Copyright (C) 2015 Authors and OPENCORES.ORG
25
 *
26
 * This source file may be used and distributed without
27
 * restriction provided that this copyright statement is not
28
 * removed from the file and that any derivative work contains
29
 * the original copyright notice and the associated disclaimer.
30
 *
31
 * This source file is free software; you can redistribute it
32
 * and/or modify it under the terms of the GNU Lesser General
33
 * Public License as published by the Free Software Foundation;
34
 * either version 2.1 of the License, or (at your option) any
35
 * later version.
36
 *
37
 * This source is distributed in the hope that it will be
38
 * useful, but WITHOUT ANY WARRANTY; without even the implied
39
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
40
 * PURPOSE. See the GNU Lesser General Public License for more
41
 * details.
42
 *
43
 * You should have received a copy of the GNU Lesser General
44
 * Public License along with this source; if not, download it
45
 * from http://www.opencores.org/lgpl.shtml
46
 *
47
 *******************************************************************************/
48
 
49
/**
50
 * \file riopacket.c
51
 */
52
 
53
/*******************************************************************************
54
 * Includes
55
 *******************************************************************************/
56
 
57
#include "riopacket.h"
58
 
59
/* Let lint report errors and warnings only. */
60
/*lint -w2 */
61
 
62
 
63
/*******************************************************************************
64
 * Local macro definitions
65
 *******************************************************************************/
66
 
67
/* Macros to get entries from a packet in a buffer. */
68
#define FTYPE_GET(p) (((p)[0] >> 16) & 0xf)
69
#define DESTID_GET(p) ((p)[0] & 0xffff)
70
#define SRCID_GET(p) (((p)[1] >> 16) & 0xffff)
71
#define TRANSACTION_GET(p) (((p)[1] >> 12) & 0xf)
72
#define MSGLEN_GET(p) TRANSACTION_GET(p)
73
#define SSIZE_GET(p) (((p)[1] >> 8) & 0xf)
74
#define LETTER_GET(p) (((p)[1] >> 6) & 0x3)
75
#define MBOX_GET(p) (((p)[1] >> 4) & 0x3)
76
#define MSGSEG_GET(p) ((p)[1] & 0xf)
77
#define XMBOX_GET(p) MSGSEG_GET(p)
78
#define RDSIZE_GET(p) SSIZE_GET(p)
79
#define WRSIZE_GET(p) SSIZE_GET(p)
80
#define STATUS_GET(p) SSIZE_GET(p)
81
#define TID_GET(p) ((p)[1] & 0xff)
82
#define HOP_GET(p) (((p)[2] >> 24) & 0xff)
83
#define CONFIG_OFFSET_GET(p) ((p)[2] & 0x00fffffcul)
84
#define INFO_GET(p) (((p)[2] >> 16) & 0xffff)
85
#define ADDRESS_GET(p) ((p)[2] & 0xfffffff8ul)
86
#define WDPTR_GET(p) (((p)[2] >> 2) & 0x1)
87
#define XAMBS_GET(p) ((p)[2] & 0x3)
88
#define DOUBLE_WORD_MSB_GET(p, i) (p)[3+(2*i+0)]
89
#define DOUBLE_WORD_LSB_GET(p, i) (p)[3+(2*i+1)]
90
 
91
 
92
 
93
/*******************************************************************************
94
 * Local function prototypes
95
 *******************************************************************************/
96
 
97
/* Functions to help get and set payload in the packets. */
98
static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset,
99
                                 const uint16_t dataOffset,
100
                                 const uint16_t dataSize, uint8_t *data);
101
static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset,
102
                                 const uint16_t dataOffset,
103
                                 const uint16_t dataSize, const uint8_t *data);
104
 
105
/* Functions to help in conversions between rdsize/wrsize and size/offset. */
106
static uint16_t rdsizeGet(const uint32_t address, const uint16_t size);
107
static uint16_t wrsizeGet(const uint32_t address, const uint16_t size);
108
static void rdsizeToOffset(uint8_t wrsize, uint8_t wdptr,
109
                           uint8_t *offset, uint16_t *size);
110
static void wrsizeToOffset(uint8_t wrsize, uint8_t wdptr,
111
                           uint8_t *offset, uint16_t *size);
112
 
113
 
114
 
115
/*******************************************************************************
116
 * Global function prototypes
117
 *******************************************************************************/
118
 
119
/**
120
 * \brief Initialize a packet to an empty packet.
121
 *
122
 * \param[in] packet The packet to operate on.
123
 *
124
 * This function sets the size of a packet to zero.
125
 *
126
 * \note Any previous content is NOT purged.
127
 */
128
void RIOPACKET_init(RioPacket_t *packet)
129
{
130
  packet->size = 0;
131
}
132
 
133
 
134
/**
135
 * \brief Return the size of a packet.
136
 *
137
 * \param[in] packet The packet to operate on.
138
 * \return The size of the packet.
139
 *
140
 * This function gets the size of a packet in words (32-bit).
141
 */
142
uint8_t RIOPACKET_size(RioPacket_t *packet)
143
{
144
  return packet->size;
145
}
146
 
147
 
148
/**
149
 * \brief Append data to a packet.
150
 *
151
 * \param[in] packet The packet to operate on.
152
 * \param[in] word The word to append.
153
 *
154
 * This function appends a specificed word (32-bit) to the end of a packet.
155
 */
156
void RIOPACKET_append(RioPacket_t *packet, uint32_t word)
157
{
158
  if(packet->size < RIOPACKET_SIZE_MAX)
159
  {
160
    packet->payload[packet->size] = word;
161
    packet->size++;
162
  }
163
}
164
 
165
 
166
/**
167
 * \brief Check if a packet is a valid RapidIO packet.
168
 *
169
 * \param[in] packet The packet to operate on.
170
 * \return The return value is zero if not ok, non-zero otherwise.
171
 *
172
 * This function checks if a packet has a correct length and a correct CRC.
173
 * Both the embedded crc and the trailing crc are checked.
174
 */
175
int RIOPACKET_valid(RioPacket_t *packet)
176
{
177
  int returnValue;
178
  uint32_t i;
179
  uint16_t crc;
180
 
181
 
182
  /* Check that the size of the packet is ok. */
183
  if((packet->size >= RIOPACKET_SIZE_MIN) &&
184
     (packet->size <= RIOPACKET_SIZE_MAX))
185
  {
186
    /* The packet has a valid length. */
187
 
188
    /* Calculate CRC on the first word and disregard the ackId. */
189
    crc = RIOPACKET_Crc32(packet->payload[0] & 0x03fffffful, 0xffffu);
190
 
191
    /* Check if the packet contains an embedded crc. */
192
    if(packet->size < 20)
193
    {
194
      /* The packet contains only one trailing crc. */
195
      for(i = 1; i < packet->size; i++)
196
      {
197
        crc = RIOPACKET_Crc32(packet->payload[i], crc);
198
      }
199
      returnValue = (crc == 0x0000u);
200
    }
201
    else
202
    {
203
      /* The packet contains both a trailing and an embedded crc. */
204
 
205
      /* Read payload to the embedded crc. Include the embedded crc in
206
         the crc calculation.*/
207
      for(i = 1; i < 20; i++)
208
      {
209
        crc = RIOPACKET_Crc32(packet->payload[i], crc);
210
      }
211
 
212
      /* Check the embedded crc. */
213
      if(crc != ((uint16_t) (packet->payload[i] >> 16)))
214
      {
215
        /* The embedded crc is not ok. */
216
        returnValue = 0;
217
      }
218
      else
219
      {
220
        /* Read the rest of the payload including the trailing crc. */
221
        for(i = 20; i < packet->size; i++)
222
        {
223
          crc = RIOPACKET_Crc32(packet->payload[i], crc);
224
        }
225
        returnValue = (crc == 0x0000u);
226
      }
227
    }
228
  }
229
  else
230
  {
231
    /* The packet does not have a valid length. */
232
    returnValue = 0;
233
  }
234
 
235
  return returnValue;
236
}
237
 
238
 
239
/**
240
 * \brief Convert (serializes) a packet into an array of bytes.
241
 *
242
 * \param[in] packet The packet to operate on.
243
 * \param[in] size The size of the buffer to write to.
244
 * \param[out] buffer The address to write the result to.
245
 * \return The number of bytes that were written. The value 0 will be returned if the
246
 * serialized buffer does not fit into the provided buffer.
247
 *
248
 * This function serializes a packet into an array of bytes that can be transfered on
249
 * a transmission channel.
250
 */
251
int RIOPACKET_serialize(RioPacket_t *packet, const uint16_t size, uint8_t *buffer)
252
{
253
  int returnValue;
254
  int i;
255
 
256
 
257
  /* Check if the packet fits into the provided buffer. */
258
  if(size >= ((4*packet->size)+1))
259
  {
260
    /* The packet fits. */
261
 
262
    /* Write the size of the packet and the packet content itself to the buffer. */
263
    buffer[0] = packet->size;
264
    for(i = 0; i < packet->size; i++)
265
    {
266
      buffer[(4*i)+1] = (packet->payload[i] >> 24) & 0xff;
267
      buffer[(4*i)+2] = (packet->payload[i] >> 16) & 0xff;
268
      buffer[(4*i)+3] = (packet->payload[i] >> 8) & 0xff;
269
      buffer[(4*i)+4] = (packet->payload[i] >> 0) & 0xff;
270
    }
271
 
272
    /* Write the number of bytes that were written. */
273
    returnValue = (4*packet->size)+1;
274
  }
275
  else
276
  {
277
    /* The packet does not fit into the provided buffer. */
278
    returnValue = 0;
279
  }
280
 
281
  return returnValue;
282
}
283
 
284
 
285
/**
286
 * \brief Convert (deserializes) an array of bytes to a packet.
287
 *
288
 * \param[in] packet The packet to operate on.
289
 * \param[in] size The size of the buffer to read from.
290
 * \param[in] buffer The address to read from.
291
 * \return The number of words contained in the resulting packet. The value 0 is
292
 * returned if the deserialization was unsuccessfull.
293
 *
294
 * This function deserializes a packet from a byte array that was previously created
295
 *  by RIOPACKET_serialize().
296
 *
297
 * \note It is recommended to use RIOPACKET_valid() to verify the integrity of the packet
298
 * once it has been deserialized.
299
 */
300
int RIOPACKET_deserialize(RioPacket_t *packet, const uint16_t size, const uint8_t *buffer)
301
{
302
  int i;
303
  uint32_t temp = 0;
304
 
305
 
306
  /* Check if the buffer contains a valid packet length. */
307
  if(((buffer[0] >= RIOPACKET_SIZE_MIN) &&
308
      (buffer[0] <= RIOPACKET_SIZE_MAX)) &&
309
     ((4*buffer[0]+1) <= size))
310
  {
311
    /* The buffer contains a valid packet length. */
312
 
313
    /* Read the size of the packet and the packet content itself from the buffer. */
314
    packet->size = buffer[0];
315
    for(i = 0; (i < 4*packet->size); i++)
316
    {
317
      temp <<= 8;
318
      temp |= buffer[i+1];
319
      if((i%4) == 3)
320
      {
321
        packet->payload[i/4] = temp;
322
      }
323
    }
324
  }
325
  else
326
  {
327
    /* The buffer does not contain a valid packet length. */
328
    packet->size = 0;
329
  }
330
 
331
  return packet->size;
332
}
333
 
334
 
335
/**
336
 * \brief Convert a packet into a printable buffer.
337
 *
338
 * \param[in] packet The packet to operate on.
339
 * \param[in] buffer The address to write the string to.
340
 *
341
 * This function converts a packet into a human readable '\0'-terminated ASCII-format and
342
 * write it to the argument buffer.
343
 *
344
 * \note The caller must guarantee that the destination buffer is large enough to contain
345
 * the resulting string.
346
 */
347
#ifdef ENABLE_TOSTRING
348
#include <stdio.h>
349
void RIOPACKET_toString(RioPacket_t *packet, char *buffer)
350
{
351
  uint8_t ftype;
352
  uint8_t transaction;
353
  uint16_t destId;
354
  uint16_t srcId;
355
  uint8_t tid;
356
 
357
 
358
  ftype = RIOPACKET_getFtype(packet);
359
  transaction = RIOPACKET_getTransaction(packet);
360
 
361
  /* Check the message type and switch on it. */
362
  switch(ftype)
363
  {
364
    case RIOPACKET_FTYPE_REQUEST:
365
      /**************************************************************************************
366
       * A REQUEST has been received.
367
       **************************************************************************************/
368
      {
369
        uint32_t address;
370
        uint16_t payloadSize;
371
 
372
 
373
        if(transaction == RIOPACKET_TRANSACTION_REQUEST_NREAD)
374
        {
375
          RIOPACKET_getNread(packet, &destId, &srcId, &tid, &address, &payloadSize);
376
          sprintf(buffer,
377
                  "NREAD: dstid=%04x srcid=%04x tid=%02x address=%08x payloadSize=%04x",
378
                  destId, srcId, tid, address, payloadSize);
379
        }
380
        else
381
        {
382
          sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
383
        }
384
      }
385
      break;
386
 
387
    case RIOPACKET_FTYPE_WRITE:
388
      /**************************************************************************************
389
       * An WRITE has been received.
390
       **************************************************************************************/
391
      {
392
        uint32_t address;
393
        uint16_t payloadSize;
394
        uint8_t payload[256];
395
        uint32_t index;
396
        uint32_t i;
397
 
398
 
399
        if(transaction == RIOPACKET_TRANSACTION_WRITE_NWRITE)
400
        {
401
          RIOPACKET_getNwrite(packet, &destId, &srcId, &address, &payloadSize, payload);
402
 
403
          index = sprintf(&buffer[0],
404
                          "NWRITE: dstid=%04x srcid=%04x address=%08x payloadSize=%04x",
405
                          destId, srcId, address, payloadSize);
406
          for(i = 0; i < payloadSize; i++)
407
          {
408
            index += sprintf(&buffer[index], "%02x", payload[i]);
409
          }
410
        }
411
        else if(transaction == RIOPACKET_TRANSACTION_WRITE_NWRITER)
412
        {
413
          RIOPACKET_getNwriteR(packet, &destId, &srcId, &tid, &address, &payloadSize, payload);
414
 
415
          index = sprintf(&buffer[0],
416
                          "NWRITER: dstid=%04x srcid=%04x tid=%02x address=%08x payloadSize=%04x",
417
                          destId, srcId, tid, address, payloadSize);
418
          for(i = 0; i < payloadSize; i++)
419
          {
420
            index += sprintf(&buffer[index], "%02x", payload[i]);
421
          }
422
        }
423
        else
424
        {
425
          sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
426
        }
427
      }
428
      break;
429
 
430
    case RIOPACKET_FTYPE_MAINTENANCE:
431
      /**************************************************************************************
432
       * A maintenance packet has been received.
433
       **************************************************************************************/
434
      {
435
        uint8_t hop;
436
        uint32_t offset;
437
        uint32_t data;
438
 
439
 
440
        /* Check the transaction to determine the type. */
441
        if(transaction == RIOPACKET_TRANSACTION_MAINT_READ_REQUEST)
442
        {
443
          /* Maintenance read request. */
444
          RIOPACKET_getMaintReadRequest(packet, &destId, &srcId, &hop, &tid, &offset);
445
          sprintf(buffer,
446
                  "MAINTREADREQUEST: dstid=%04x srcid=%04x tid=%02x hop=%02x offset=%08x",
447
                  destId, srcId, tid, hop, offset);
448
        }
449
        else if(transaction == RIOPACKET_TRANSACTION_MAINT_WRITE_REQUEST)
450
        {
451
          /* Maintenance write request. */
452
          RIOPACKET_getMaintWriteRequest(packet, &destId, &srcId, &hop, &tid, &offset, &data);
453
          sprintf(buffer,
454
                  "MAINTWRITEREQUEST: dstid=%04x srcid=%04x tid=%02x hop=%02x offset=%08x data=%08x",
455
                  destId, srcId, tid, hop, offset, data);
456
        }
457
        else if(transaction == RIOPACKET_TRANSACTION_MAINT_READ_RESPONSE)
458
        {
459
          /* Maintenance read response. */
460
          RIOPACKET_getMaintReadResponse(packet, &destId, &srcId, &tid, &data);
461
          sprintf(buffer,
462
                  "MAINTREADRESPONSE: dstid=%04x srcid=%04x tid=%02x data=%08x",
463
                  destId, srcId, tid, data);
464
        }
465
        else if(transaction == RIOPACKET_TRANSACTION_MAINT_WRITE_RESPONSE)
466
        {
467
          /* Maintenance write repsonse. */
468
          RIOPACKET_getMaintWriteResponse(packet, &destId, &srcId, &tid);
469
          sprintf(buffer,
470
                  "MAINTWRITERESPONSE: dstid=%04x srcid=%04x tid=%02x",
471
                  destId, srcId, tid);
472
        }
473
        else if(transaction == RIOPACKET_TRANSACTION_MAINT_PORT_WRITE_REQUEST)
474
        {
475
          uint32_t componentTag;
476
          uint32_t portErrorDetect;
477
          uint32_t implementationSpecific;
478
          uint8_t portId;
479
          uint32_t logicalTransportErrorDetect;
480
 
481
          /* Maintenance port write packet. */
482
          RIOPACKET_getMaintPortWrite(packet, &destId, &srcId,
483
                                      &componentTag, &portErrorDetect, &implementationSpecific,
484
                                      &portId, &logicalTransportErrorDetect);
485
          sprintf(buffer,
486
                  "MAINTPORTWRITE: dstid=%04x srcid=%04x componentTag=%08x portErrorDetect=%08x"
487
                  "implementationSpecific=%08x portId=%02x logicalTransportErrorDetect=%08x",
488
                  destId, srcId, componentTag, portErrorDetect, implementationSpecific, portId,
489
                  logicalTransportErrorDetect);
490
        }
491
        else
492
        {
493
          sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
494
        }
495
      }
496
      break;
497
 
498
    case RIOPACKET_FTYPE_DOORBELL:
499
      /**************************************************************************************
500
       * A doorbell packet has been received.
501
       **************************************************************************************/
502
      {
503
        uint16_t info;
504
 
505
 
506
        RIOPACKET_getDoorbell(packet, &destId, &srcId, &tid, &info);
507
        sprintf(buffer,
508
                "DOORBELL: dstid=%04x srcid=%04x tid=%02x info=%04x",
509
                destId, srcId, tid, info);
510
      }
511
      break;
512
 
513
    case RIOPACKET_FTYPE_MESSAGE:
514
      /**************************************************************************************
515
       * A messaget has been received.
516
       **************************************************************************************/
517
      {
518
        uint16_t payloadSize;
519
        uint8_t payload[256];
520
        uint32_t index;
521
        uint32_t i;
522
 
523
 
524
        RIOPACKET_getMessage(packet, &destId, &srcId, &tid, &payloadSize, payload);
525
 
526
        index = sprintf(&buffer[0],
527
                        "MESSAGE: dstid=%04x srcid=%04x mailbox=%02x payloadSize=%04x",
528
                        destId, srcId, tid, payloadSize);
529
        for(i = 0; i < payloadSize; i++)
530
        {
531
          index += sprintf(&buffer[index], "%02x", payload[i]);
532
        }
533
      }
534
      break;
535
 
536
    case RIOPACKET_FTYPE_RESPONSE:
537
      /**************************************************************************************
538
       * A response packet has been received.
539
       **************************************************************************************/
540
      {
541
        uint8_t status;
542
        uint16_t payloadSize;
543
        uint8_t payload[256];
544
 
545
 
546
        if(transaction == RIOPACKET_TRANSACTION_RESPONSE_NO_PAYLOAD)
547
        {
548
          RIOPACKET_getResponseNoPayload(packet, &destId, &srcId, &tid, &status);
549
          sprintf(buffer,
550
                  "RESPONSENOPAYLOAD: dstid=%04x srcid=%04x tid=%02x status=%02x",
551
                  destId, srcId, tid, status);
552
        }
553
        else if(transaction == RIOPACKET_TRANSACTION_RESPONSE_MESSAGE_RESPONSE)
554
        {
555
          RIOPACKET_getResponseMessage(packet, &destId, &srcId, &tid, &status);
556
          sprintf(buffer,
557
                  "RESPONSEMESSAGE: dstid=%04x srcid=%04x mailbox=%02x status=%02x",
558
                  destId, srcId, tid, status);
559
        }
560
        else if(transaction == RIOPACKET_TRANSACTION_RESPONSE_WITH_PAYLOAD)
561
        {
562
          uint32_t i;
563
          uint32_t index;
564
 
565
 
566
          RIOPACKET_getResponseWithPayload(packet, &destId, &srcId, &tid, 0, &payloadSize, payload);
567
 
568
          index = sprintf(&buffer[0],
569
                          "RESPONSEWITHPAYLOAD: dstid=%04x srcid=%04x tid=%02x payloadSize=%04x ",
570
                          destId, srcId, tid, payloadSize);
571
          for(i = 0; i < payloadSize; i++)
572
          {
573
            index += sprintf(&buffer[index], "%02x", payload[i]);
574
          }
575
        }
576
        else
577
        {
578
          sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
579
        }
580
      }
581
      break;
582
 
583
    default:
584
      /**************************************************************************************
585
       * Unsupported ftype.
586
       **************************************************************************************/
587
      sprintf(buffer, "UNKNOWN:ftype=%02x transaction=%02x", ftype, transaction);
588
      break;
589
  }
590
 
591
  return;
592
}
593
#endif
594
 
595
 
596
/**
597
 * \brief Return the ftype of a packet.
598
 *
599
 * \param[in] packet The packet to operate on.
600
 * \return The ftype of the packet.
601
 *
602
 * This function gets the ftype of a packet.
603
 */
604
uint8_t RIOPACKET_getFtype(RioPacket_t *packet)
605
{
606
  return FTYPE_GET(packet->payload);
607
}
608
 
609
 
610
/**
611
 * \brief Return the destination deviceId of a packet.
612
 *
613
 * \param[in] packet The packet to operate on.
614
 * \return The destination deviceId of the packet.
615
 *
616
 * This function gets the destination deviceId of a packet.
617
 */
618
uint16_t RIOPACKET_getDestination(RioPacket_t *packet)
619
{
620
  return DESTID_GET(packet->payload);
621
}
622
 
623
 
624
/**
625
 * \brief Return the source deviceId of a packet.
626
 *
627
 * \param[in] packet The packet to operate on.
628
 * \return The source deviceId of the packet.
629
 *
630
 * This function gets the source deviceId of a packet.
631
 */
632
uint16_t RIOPACKET_getSource(RioPacket_t *packet)
633
{
634
  return SRCID_GET(packet->payload);
635
}
636
 
637
 
638
/**
639
 * \brief Return the transaction of a packet.
640
 *
641
 * \param[in] packet The packet to operate on.
642
 * \return The transaction of the packet.
643
 *
644
 * This function gets the transaction field of a packet.
645
 *
646
 * \note Not all packets contain a transaction field.
647
 */
648
uint8_t RIOPACKET_getTransaction(RioPacket_t *packet)
649
{
650
  return TRANSACTION_GET(packet->payload);
651
}
652
 
653
 
654
/**
655
 * \brief Return the transaction identifier of a packet.
656
 *
657
 * \param[in] packet The packet to operate on.
658
 * \return The transaction identifier of the packet.
659
 *
660
 * This function gets the transaction identifier field of a packet.
661
 *
662
 * \note Not all packets contain a transaction identifier field.
663
 */
664
uint8_t RIOPACKET_getTid(RioPacket_t *packet)
665
{
666
  return TID_GET(packet->payload);
667
}
668
 
669
 
670
/*******************************************************************************************
671
 * Logical I/O MAINTENANCE-READ functions.
672
 *******************************************************************************************/
673
 
674
/**
675
 * \brief Set the packet to contain a maintenance read request.
676
 *
677
 * \param[in] packet The packet to operate on.
678
 * \param[in] destId The deviceId to use as destination in the packet.
679
 * \param[in] srcId The deviceId to use as source in the packet.
680
 * \param[in] hop The hop_count to set in the packet.
681
 * \param[in] tid The transaction identifier to set in the packet.
682
 * \param[in] offset The byte address in the configuration space to read.
683
 *
684
 * This function sets the content of a packet to a maintenance read request packet containing
685
 * a request to read one word in configuration space.
686
 *
687
 */
688
void RIOPACKET_setMaintReadRequest(RioPacket_t *packet,
689
                                   uint16_t destId, uint16_t srcId, uint8_t hop,
690
                                   uint8_t tid, uint32_t offset)
691
{
692
  uint32_t content;
693
  uint16_t crc = 0xffffu;
694
 
695
 
696
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
697
  /* ackId is set when the packet is transmitted but must be set to zero. */
698
  content = 0x00180000ul;
699
  content |= (uint32_t) destId;
700
  crc = RIOPACKET_Crc32(content, crc);
701
  packet->payload[0] = content;
702
 
703
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
704
  content = ((uint32_t) srcId) << 16;
705
  content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_READ_REQUEST << 12;
706
  content |= (uint32_t) 8ul << 8;
707
  content |= (uint32_t) tid;
708
  crc = RIOPACKET_Crc32(content, crc);
709
  packet->payload[1] = content;
710
 
711
  /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
712
  content = ((uint32_t) hop) << 24;
713
  content |= offset & 0x00fffffcul;
714
  crc = RIOPACKET_Crc32(content, crc);
715
  packet->payload[2] = content;
716
 
717
  /* crc(15:0)|pad(15:0) */
718
  content = ((uint32_t) crc) << 16;
719
  packet->payload[3] = content;
720
 
721
  /* Set the size of the packet. */
722
  packet->size = 4;
723
}
724
 
725
 
726
/**
727
 * \brief Get entries from a maintenance read request.
728
 *
729
 * \param[in] packet The packet to operate on.
730
 * \param[out] destId The destination deviceId in this packet.
731
 * \param[out] srcId The source deviceId in this packet.
732
 * \param[out] hop The hop_count in this packet.
733
 * \param[out] tid The transaction id to be returned in the response to this request.
734
 * \param[out] offset The byte address in the configuration space to read.
735
 *
736
 * This function returns the content of a packet as if it contained a maintenance read
737
 * request packet.
738
 *
739
 * \note Use the ftype and transaction fields to see if the packet is indeed a
740
 * maintenance read request.
741
 * \note If the packet does not contain a maintenance read request, the result
742
 * will be undefined.
743
 */
744
void RIOPACKET_getMaintReadRequest(RioPacket_t *packet,
745
                                   uint16_t *destId, uint16_t *srcId, uint8_t *hop,
746
                                   uint8_t *tid, uint32_t *offset)
747
{
748
  *destId = DESTID_GET(packet->payload);
749
  *srcId = SRCID_GET(packet->payload);
750
  *tid = TID_GET(packet->payload);
751
  *hop = HOP_GET(packet->payload);
752
  *offset = CONFIG_OFFSET_GET(packet->payload);
753
}
754
 
755
 
756
/**
757
 * \brief Set the packet to contain a maintenance read response.
758
 *
759
 * \param[in] packet The packet to operate on.
760
 * \param[in] destId The deviceId to use as destination in the packet.
761
 * \param[in] srcId The deviceId to use as source in the packet.
762
 * \param[in] tid The transaction identifier to set in the packet.
763
 * \param[in] data The data to send in the packet.
764
 *
765
 * This function sets the content of a packet to a maintanance read response packet
766
 * containing a response to a request reading one word in configuration space.
767
 */
768
void RIOPACKET_setMaintReadResponse(RioPacket_t *packet,
769
                                    uint16_t destId, uint16_t srcId,
770
                                    uint8_t tid, uint32_t data)
771
{
772
  uint32_t content;
773
  uint16_t crc = 0xffffu;
774
 
775
 
776
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
777
  /* ackId is set when the packet is transmitted. */
778
  content = 0x00180000ul;
779
  content |= (uint32_t) destId;
780
  crc = RIOPACKET_Crc32(content, crc);
781
  packet->payload[0] = content;
782
 
783
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|srcTID(7:0) */
784
  content = (uint32_t) srcId << 16;
785
  content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_READ_RESPONSE << 12;
786
  content |= (uint32_t) RIOPACKET_RESPONSE_STATUS_DONE << 8;
787
  content |= (uint32_t) tid;
788
  crc = RIOPACKET_Crc32(content, crc);
789
  packet->payload[1] = content;
790
 
791
  /* hopcount(7:0)|reserved(23:0) */
792
  /* HopCount should always be set to 0xff in responses. */
793
  content = 0xff000000ul;
794
  crc = RIOPACKET_Crc32(content, crc);
795
  packet->payload[2] = content;
796
 
797
  /* double-word 0 */
798
  /* Note that both words are filled in to avoid looking at the offset. The receiver will not
799
     look at the other part anyway. The standard does not say anything about the value of the padding. */
800
  content = data;
801
  crc = RIOPACKET_Crc32(content, crc);
802
  packet->payload[3] = content;
803
  content = data;
804
  crc = RIOPACKET_Crc32(content, crc);
805
  packet->payload[4] = content;
806
 
807
  /* crc(15:0)|pad(15:0) */
808
  content = ((uint32_t) crc) << 16;
809
  packet->payload[5] = content;
810
 
811
  /* Set the size of the packet. */
812
  packet->size = 6;
813
}
814
 
815
 
816
/**
817
 * \brief Get entries from a maintenance read response.
818
 *
819
 * \param[in] packet The packet to operate on.
820
 * \param[out] destId The destination deviceId in this packet.
821
 * \param[out] srcId The source deviceId in this packet.
822
 * \param[out] tid The transaction identifier in the response.
823
 * \param[out] data The data in the response.
824
 *
825
 * This function returns the content of a packet as if it contained a maintenance
826
 * read response packet.
827
 *
828
 * \note Use the ftype and transaction fields to see if the packet is indeed a
829
 * maintenance read response.
830
 * \note If the packet does not contain a maintenance read response, the result
831
 * will be undefined.
832
 */
833
void RIOPACKET_getMaintReadResponse(RioPacket_t *packet,
834
                                    uint16_t *destId, uint16_t *srcId,
835
                                    uint8_t *tid, uint32_t *data)
836
{
837
  *destId = DESTID_GET(packet->payload);
838
  *srcId = SRCID_GET(packet->payload);
839
  *tid = TID_GET(packet->payload);
840
  *data = DOUBLE_WORD_MSB_GET(packet->payload, 0) | DOUBLE_WORD_LSB_GET(packet->payload, 0);
841
}
842
 
843
 
844
/*******************************************************************************************
845
 * Logical I/O MAINTENANCE-WRITE functions.
846
 *******************************************************************************************/
847
 
848
/**
849
 * \brief Set the packet to contain a maintenance write request.
850
 *
851
 * \param[in] packet The packet to operate on.
852
 * \param[in] destId The deviceId to use as destination in the packet.
853
 * \param[in] srcId The deviceId to use as source in the packet.
854
 * \param[in] hop The hop_count to set in the packet.
855
 * \param[in] tid The transaction identifier to set in the packet.
856
 * \param[in] offset The byte address in the configuration space to write to.
857
 * \param[in] data The data to write in configuration space.
858
 *
859
 * This function sets the content of a packet to a maintenance write request packet
860
 * containing a request to write one word in configuration space.
861
 */
862
void RIOPACKET_setMaintWriteRequest(RioPacket_t *packet,
863
                                    uint16_t destId, uint16_t srcId, uint8_t hop,
864
                                    uint8_t tid, uint32_t offset, uint32_t data)
865
{
866
  uint32_t content;
867
  uint16_t crc = 0xffffu;
868
 
869
 
870
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
871
  /* ackId is set when the packet is transmitted. */
872
  content = 0x00180000ul;
873
  content |= (uint32_t) destId;
874
  crc = RIOPACKET_Crc32(content, crc);
875
  packet->payload[0] = content;
876
 
877
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
878
  content = ((uint32_t) srcId) << 16;
879
  content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_WRITE_REQUEST << 12;
880
  content |= (uint32_t) 8ul << 8;
881
  content |= (uint32_t) tid;
882
  crc = RIOPACKET_Crc32(content, crc);
883
  packet->payload[1] = content;
884
 
885
  /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
886
  content = ((uint32_t) hop) << 24;
887
  content |= offset & 0x00fffffcul;
888
  crc = RIOPACKET_Crc32(content, crc);
889
  packet->payload[2] = content;
890
 
891
  /* double-word 0 */
892
  /* Note that both words are filled in to avoid looking at the offset. The receiver will not
893
     look at the other part anyway. The standard does not say anything about the value of the padding. */
894
  content = data;
895
  crc = RIOPACKET_Crc32(content, crc);
896
  packet->payload[3] = content;
897
  content = data;
898
  crc = RIOPACKET_Crc32(content, crc);
899
  packet->payload[4] = content;
900
 
901
  /* crc(15:0)|pad(15:0) */
902
  content = ((uint32_t) crc) << 16;
903
  packet->payload[5] = content;
904
 
905
  /* Set the size of the packet. */
906
  packet->size = 6;
907
}
908
 
909
 
910
/**
911
 * \brief Get entries from a maintenance write request.
912
 *
913
 * \param[in] packet The packet to operate on.
914
 * \param[out] destId The destination deviceId in this packet.
915
 * \param[out] srcId The source deviceId in this packet.
916
 * \param[out] hop The hop_count in this packet.
917
 * \param[out] tid The transaction id in this packet.
918
 * \param[out] offset The byte address in the configuration space to read.
919
 * \param[out] data The data to requested to be written in configuration space.
920
 *
921
 * This function returns the content of a packet as if it contained a maintenance write
922
 * request packet.
923
 *
924
 * \note Use the ftype and transaction fields to see if the packet is indeed a
925
 * maintenance write request.
926
 * \note If the packet does not contain a maintenance write request, the result
927
 * will be undefined.
928
 */
929
void RIOPACKET_getMaintWriteRequest(RioPacket_t *packet,
930
                                    uint16_t *destId, uint16_t *srcId, uint8_t *hop,
931
                                    uint8_t *tid, uint32_t *offset, uint32_t *data)
932
{
933
  *destId = DESTID_GET(packet->payload);
934
  *srcId = SRCID_GET(packet->payload);
935
  *tid = TID_GET(packet->payload);
936
  *hop = HOP_GET(packet->payload);
937
  *offset = CONFIG_OFFSET_GET(packet->payload);
938
  *data = DOUBLE_WORD_MSB_GET(packet->payload, 0) | DOUBLE_WORD_LSB_GET(packet->payload, 0);
939
}
940
 
941
 
942
/**
943
 * \brief Set the packet to contain a maintenance write response.
944
 *
945
 * \param[in] packet The packet to operate on.
946
 * \param[in] destId The deviceId to use as destination in the packet.
947
 * \param[in] srcId The deviceId to use as source in the packet.
948
 * \param[in] tid The transaction identifier to set in the packet.
949
 *
950
 * This function sets the content of a packet to a maintanance write response packet
951
 * containing a response to a request writing one word in configuration space.
952
 */
953
void RIOPACKET_setMaintWriteResponse(RioPacket_t *packet,
954
                                     uint16_t destId, uint16_t srcId,
955
                                     uint8_t tid)
956
{
957
  uint32_t content;
958
  uint16_t crc = 0xffffu;
959
 
960
 
961
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
962
  /* ackId is set when the packet is transmitted. */
963
  content = 0x00180000ul;
964
  content |= (uint32_t) destId;
965
  crc = RIOPACKET_Crc32(content, crc);
966
  packet->payload[0] = content;
967
 
968
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|srcTID(7:0) */
969
  content = ((uint32_t) srcId) << 16;
970
  content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_WRITE_RESPONSE << 12;
971
  content |= (uint32_t) RIOPACKET_RESPONSE_STATUS_DONE << 8;
972
  content |= (uint32_t) tid;
973
  crc = RIOPACKET_Crc32(content, crc);
974
  packet->payload[1] = content;
975
 
976
  /* hopcount(7:0)|reserved(23:0) */
977
  /* HopCount should always be set to 0xff in responses. */
978
  content = 0xff000000ul;
979
  crc = RIOPACKET_Crc32(content, crc);
980
  packet->payload[2] = content;
981
 
982
  /* crc(15:0)|pad(15:0) */
983
  content = ((uint32_t) crc) << 16;
984
  packet->payload[3] = content;
985
 
986
  /* Set the size of the packet. */
987
  packet->size = 4;
988
}
989
 
990
 
991
/**
992
 * \brief Get entries from a maintenance write response.
993
 *
994
 * \param[in] packet The packet to operate on.
995
 * \param[out] destId The destination deviceId in this packet.
996
 * \param[out] srcId The source deviceId in this packet.
997
 * \param[out] tid The transaction identifier in the response.
998
 *
999
 * This function returns the content of a packet as if it contained a maintenance
1000
 * write response packet.
1001
 *
1002
 * \note Use the ftype and transaction fields to see if the packet is indeed a
1003
 * maintenance write response.
1004
 * \note If the packet does not contain a maintenance write response, the result
1005
 * will be undefined.
1006
 */
1007
void RIOPACKET_getMaintWriteResponse(RioPacket_t *packet,
1008
                                     uint16_t *destId, uint16_t *srcId,
1009
                                     uint8_t *tid)
1010
{
1011
  *destId = DESTID_GET(packet->payload);
1012
  *srcId = SRCID_GET(packet->payload);
1013
  *tid = TID_GET(packet->payload);
1014
}
1015
 
1016
 
1017
/*******************************************************************************************
1018
 * Logical I/O MAINTENANCE-PORTWRITE functions.
1019
 *******************************************************************************************/
1020
 
1021
/**
1022
 * \brief Set the packet to contain a maintenance port-write request.
1023
 *
1024
 * \param[in] packet The packet to operate on.
1025
 * \param[in] destId The deviceId to use as destination in the packet.
1026
 * \param[in] srcId The deviceId to use as source in the packet.
1027
 * \param[in] componentTag The value of the componentTag register to set in the packet.
1028
 * \param[in] portErrorDetect The value of the Port N Error Detect CSR to set in the packet.
1029
 * \param[in] implementationSpecific An implementation specific value to set in the packet.
1030
 * \param[in] portId The port ID of the port to set in the packet.
1031
 * \param[in] logicalTransportErrorDetect The value of the Logical/Transport Layer
1032
 * Error Detect CSR to set in the packet.
1033
 *
1034
 * This function sets the content of a packet to a maintenance port-write request packet.
1035
 */
1036
void RIOPACKET_setMaintPortWrite(RioPacket_t *packet,
1037
                                 uint16_t destId, uint16_t srcId,
1038
                                 uint32_t componentTag, uint32_t portErrorDetect,
1039
                                 uint32_t implementationSpecific, uint8_t portId,
1040
                                 uint32_t logicalTransportErrorDetect)
1041
{
1042
  uint32_t content;
1043
  uint16_t crc = 0xffffu;
1044
 
1045
 
1046
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1047
  /* ackId is set when the packet is transmitted. */
1048
  content = 0x00180000ul;
1049
  content |= (uint32_t) destId;
1050
  crc = RIOPACKET_Crc32(content, crc);
1051
  packet->payload[0] = content;
1052
 
1053
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
1054
  content = (uint32_t) srcId << 16;
1055
  content |= (uint32_t) RIOPACKET_TRANSACTION_MAINT_PORT_WRITE_REQUEST << 12;
1056
  crc = RIOPACKET_Crc32(content, crc);
1057
  packet->payload[1] = content;
1058
 
1059
  /* hopcount(7:0)|reserved(23:0) */
1060
  content = 0x00000000ul;
1061
  crc = RIOPACKET_Crc32(content, crc);
1062
  packet->payload[2] = content;
1063
 
1064
  /* double-word 0 */
1065
  content = componentTag;
1066
  crc = RIOPACKET_Crc32(content, crc);
1067
  packet->payload[3] = content;
1068
  content = portErrorDetect;
1069
  crc = RIOPACKET_Crc32(content, crc);
1070
  packet->payload[4] = content;
1071
 
1072
  /* double-word 1 */
1073
  content = implementationSpecific << 8;
1074
  content |= (uint32_t) portId;
1075
  crc = RIOPACKET_Crc32(content, crc);
1076
  packet->payload[5] = content;
1077
  content = logicalTransportErrorDetect;
1078
  crc = RIOPACKET_Crc32(content, crc);
1079
  packet->payload[6] = content;
1080
 
1081
  /* crc(15:0)|pad(15:0) */
1082
  content = ((uint32_t) crc) << 16;
1083
  packet->payload[7] = content;
1084
 
1085
  /* Set the size of the packet. */
1086
  packet->size = 8;
1087
}
1088
 
1089
 
1090
/**
1091
 * \brief Get entries from a maintenance port-write request.
1092
 *
1093
 * \param[in] packet The packet to operate on.
1094
 * \param[out] destId The device id of the destination end point.
1095
 * \param[out] srcId The device id of the source end point.
1096
 * \param[out] componentTag The value of the componentTag register in this packet.
1097
 * \param[out] portErrorDetect The value of the Port N Error Detect CSR in this packet.
1098
 * \param[out] implementationSpecific An implementation specific value in this packet.
1099
 * \param[out] portId The port ID of the port in this packet.
1100
 * \param[out] logicalTransportErrorDetect The value of the Logical/Transport Layer
1101
 * Error Detect CSR in this packet.
1102
 *
1103
 * This function returns the content of a packet as if it contained a maintenance port-write
1104
 * request packet.
1105
 *
1106
 * \note Use the ftype and transaction fields to see if the packet is indeed a
1107
 * maintenance port-write request.
1108
 * \note If the packet does not contain a maintenance port-write request, the result
1109
 * will be undefined.
1110
 */
1111
void RIOPACKET_getMaintPortWrite(RioPacket_t *packet,
1112
                                 uint16_t *destId, uint16_t *srcId,
1113
                                 uint32_t *componentTag, uint32_t *portErrorDetect,
1114
                                 uint32_t *implementationSpecific, uint8_t *portId,
1115
                                 uint32_t *logicalTransportErrorDetect)
1116
{
1117
  *destId = DESTID_GET(packet->payload);
1118
  *srcId = SRCID_GET(packet->payload);
1119
  *componentTag = packet->payload[3];
1120
  *portErrorDetect = packet->payload[4];
1121
  *implementationSpecific = packet->payload[5] >> 8;
1122
  *portId = (uint8_t) (packet->payload[5] & 0xff);
1123
  *logicalTransportErrorDetect = packet->payload[6];
1124
}
1125
 
1126
 
1127
/*******************************************************************************************
1128
 * Logical I/O NWRITE/NWRITER functions.
1129
 *******************************************************************************************/
1130
 
1131
/**
1132
 * \brief Set a packet to contain an NWRITE.
1133
 *
1134
 * \param[in] packet The packet to operate on.
1135
 * \param[in] destId The deviceId to use as destination in the packet.
1136
 * \param[in] srcId The deviceId to use as source in the packet.
1137
 * \param[in] address The byte address in IO-space to write to.
1138
 * \param[in] payloadSize The number of bytes to write. The largest allowed size is 256 bytes.
1139
 * \param[in] payload A pointer to the array of bytes to write.
1140
 *
1141
 * This function sets the content of a packet to an NWRITE containing a request
1142
 * to write the number of bytes specified by payloadSize to the address specified by the
1143
 * address argument.
1144
 *
1145
 * \note The address is a byte address.
1146
 *
1147
 * \note Not all combinations of addresses and sizes are allowed. The packet will be empty
1148
 * if an unallowed address/payloadSize combination is used. Use RIOPACKET_getWritePacketSize()
1149
 * to get the maximum size to use based on the address and payloadSize.
1150
 */
1151
void RIOPACKET_setNwrite(RioPacket_t *packet, uint16_t destId, uint16_t srcId,
1152
                         uint32_t address, uint16_t payloadSize, uint8_t *payload)
1153
{
1154
  uint32_t content;
1155
  uint16_t wrsize;
1156
 
1157
 
1158
  /* Convert the address and size to the wrsize field and check if the combination is valid. */
1159
  wrsize = wrsizeGet(address, payloadSize);
1160
  if(wrsize != 0xffff)
1161
  {
1162
    /* The address and size field combination is valid. */
1163
 
1164
    /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1165
    /* ackId is set when the packet is transmitted. */
1166
    content = 0x00150000ul;
1167
    content |= (uint32_t) destId;
1168
    packet->payload[0] = content;
1169
 
1170
    /* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */
1171
    content = ((uint32_t) srcId) << 16;
1172
    content |= (uint32_t) RIOPACKET_TRANSACTION_WRITE_NWRITE << 12;
1173
    content |= (uint32_t) (wrsize & 0x0f00);
1174
    packet->payload[1] = content;
1175
 
1176
    /* address(28:0)|wdptr|xamsbs(1:0) */
1177
    /* wrsize also contains wdptr in the lower nibble. */
1178
    /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the
1179
       34-bit address should be used, another mechanism to set it should be used. */
1180
    content = (address & 0xfffffff8ul);
1181
    content |= ((uint32_t) (wrsize & 0x000f)) << 2;
1182
    packet->payload[2] = content;
1183
 
1184
    /* Place the payload buffer into the payload of the packet. */
1185
    /* This function also calculates the CRC. */
1186
    packet->size = setPacketPayload(&(packet->payload[0]), 12, address & 0x7, payloadSize, payload);
1187
  }
1188
  else
1189
  {
1190
    /* The address and size field combination is not valid. */
1191
    /* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */
1192
    packet->size = 0;
1193
  }
1194
}
1195
 
1196
 
1197
/**
1198
 * \brief Get entries from a NWRITE.
1199
 *
1200
 * \param[in] packet The packet to operate on.
1201
 * \param[out] destId The destination deviceId in this packet.
1202
 * \param[out] srcId The source deviceId in this packet.
1203
 * \param[out] address The byte address into IO-space requested to be written.
1204
 * \param[out] payloadSize The number of bytes requested to be written.
1205
 * \param[out] payload The data requested to be written.
1206
 *
1207
 * This function returns the content of a packet as if it contained an NWRITE.
1208
 *
1209
 * \note The address is a byte address.
1210
 *
1211
 * \note Any padding contained in double-word0 will be removed and the content
1212
 * will be placed where the payload pointer is pointing.
1213
 */
1214
void RIOPACKET_getNwrite(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId,
1215
                         uint32_t *address, uint16_t *payloadSize, uint8_t *payload)
1216
{
1217
  uint8_t wrsize;
1218
  uint8_t wdptr;
1219
  uint8_t offset = 0;
1220
  uint16_t size = 0;
1221
 
1222
 
1223
  wrsize = WRSIZE_GET(packet->payload);
1224
  wdptr = WDPTR_GET(packet->payload);
1225
  wrsizeToOffset(wrsize, wdptr, &offset, &size);
1226
 
1227
  *destId = DESTID_GET(packet->payload);
1228
  *srcId = SRCID_GET(packet->payload);
1229
  *address = ADDRESS_GET(packet->payload) | offset;
1230
 
1231
  if(size > 16)
1232
  {
1233
    size = 4*(packet->size-4);
1234
  }
1235
  else
1236
  {
1237
    /* The size already contains the correct value. */
1238
  }
1239
 
1240
 
1241
  *payloadSize = getPacketPayload(&(packet->payload[0]), 12, offset, size, payload);
1242
}
1243
 
1244
 
1245
 
1246
/**
1247
 * \brief Set a packet to contain an NWRITER.
1248
 *
1249
 * \param[in] packet The packet to operate on.
1250
 * \param[in] destId The deviceId to use as destination in the packet.
1251
 * \param[in] srcId The deviceId to use as source in the packet.
1252
 * \param[in] tid The transaction identifier to set in the packet.
1253
 * \param[in] address The byte address in IO-space to write to.
1254
 * \param[in] payloadSize The number of bytes to write. The largest allowed size is 256 bytes.
1255
 * \param[in] payload A pointer to the array of bytes to write.
1256
 *
1257
 * This function sets the content of a packet to an NWRITER containing a request
1258
 * to write the number of bytes specified by payloadSize to the address specified by the
1259
 * address argument. This packet requires a RESPONSE containing the transaction identifier
1260
 * specified in this packet.
1261
 *
1262
 * \note The address is a byte address.
1263
 *
1264
 * \note Not all combinations of addresses and sizes are allowed. The packet will be empty
1265
 * if an unallowed address/payloadSize combination is used. Use RIOPACKET_getWritePacketSize()
1266
 * to get the maximum size to use based on the address and payloadSize.
1267
 */
1268
void RIOPACKET_setNwriteR(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid,
1269
                          uint32_t address, uint16_t payloadSize, uint8_t *payload)
1270
{
1271
  uint32_t content;
1272
  uint16_t wrsize;
1273
 
1274
 
1275
  /* Convert the address and size to the wrsize field and check if the combination is valid. */
1276
  wrsize = wrsizeGet(address, payloadSize);
1277
  if(wrsize != 0xffff)
1278
  {
1279
    /* The address and size field combination is valid. */
1280
 
1281
    /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1282
    /* ackId is set when the packet is transmitted. */
1283
    content = 0x00150000ul;
1284
    content |= (uint32_t) destId;
1285
    packet->payload[0] = content;
1286
 
1287
    /* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */
1288
    content = ((uint32_t) srcId) << 16;
1289
    content |= (uint32_t) RIOPACKET_TRANSACTION_WRITE_NWRITER << 12;
1290
    content |= (uint32_t) (wrsize & 0x0f00);
1291
    content |= (uint32_t) tid;
1292
    packet->payload[1] = content;
1293
 
1294
    /* address(28:0)|wdptr|xamsbs(1:0) */
1295
    /* wrsize also contains wdptr in the lower nibble. */
1296
    /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the
1297
       34-bit address should be used, another mechanism to set it should be used. */
1298
    content = (address & 0xfffffff8ul);
1299
    content |= ((uint32_t) (wrsize & 0x000f)) << 2;
1300
    packet->payload[2] = content;
1301
 
1302
    /* Place the payload buffer into the payload of the packet. */
1303
    /* This function also calculates the CRC. */
1304
    packet->size = setPacketPayload(&(packet->payload[0]), 12, address & 0x7, payloadSize, payload);
1305
  }
1306
  else
1307
  {
1308
    /* The address and size field combination is not valid. */
1309
    /* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */
1310
    packet->size = 0;
1311
  }
1312
}
1313
 
1314
 
1315
/**
1316
 * \brief Get entries from a NWRITER.
1317
 *
1318
 * \param[in] packet The packet to operate on.
1319
 * \param[out] destId The destination deviceId in this packet.
1320
 * \param[out] srcId The source deviceId in this packet.
1321
 * \param[out] tid The transaction id in this packet.
1322
 * \param[out] address The byte address into IO-space requested to be written.
1323
 * \param[out] payloadSize The number of bytes requested to be written.
1324
 * \param[out] payload The data requested to be written.
1325
 *
1326
 * This function returns the content of a packet as if it contained an NWRITER.
1327
 *
1328
 * \note The address is a byte address.
1329
 *
1330
 * \note Any padding contained in double-word0 will be removed and the content
1331
 * will be placed where the payload pointer is pointing.
1332
 */
1333
void RIOPACKET_getNwriteR(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid,
1334
                          uint32_t *address, uint16_t *payloadSize, uint8_t *payload)
1335
{
1336
  uint8_t wrsize;
1337
  uint8_t wdptr;
1338
  uint8_t offset = 0;
1339
  uint16_t size = 0;
1340
 
1341
 
1342
  wrsize = WRSIZE_GET(packet->payload);
1343
  wdptr = WDPTR_GET(packet->payload);
1344
  wrsizeToOffset(wrsize, wdptr, &offset, &size);
1345
 
1346
  *destId = DESTID_GET(packet->payload);
1347
  *srcId = SRCID_GET(packet->payload);
1348
  *tid = TID_GET(packet->payload);
1349
  *address = ADDRESS_GET(packet->payload) | offset;
1350
 
1351
  if(size > 16)
1352
  {
1353
    size = 4*(packet->size-4);
1354
  }
1355
  else
1356
  {
1357
    /* The size already contains the correct value. */
1358
  }
1359
 
1360
  *payloadSize = getPacketPayload(&(packet->payload[0]), 12, offset, size, payload);
1361
}
1362
 
1363
 
1364
/*******************************************************************************************
1365
 * Logical I/O NREAD functions.
1366
 *******************************************************************************************/
1367
 
1368
/**
1369
 * \brief Set a packet to contain an NREAD.
1370
 *
1371
 * \param[in] packet The packet to operate on.
1372
 * \param[in] destId The deviceId to use as destination in the packet.
1373
 * \param[in] srcId The deviceId to use as source in the packet.
1374
 * \param[in] tid The transaction id to set in the response.
1375
 * \param[in] address The byte address to read from.
1376
 * \param[in] payloadSize The number of bytes to read. The largest allowed size is 256 bytes.
1377
 *
1378
 * This function sets the content of a packet to an NREAD containing a request
1379
 * to read the number of bytes specified by payloadSize from the address specified by the
1380
 * address argument.
1381
 *
1382
 * \note The address is a byte address.
1383
 *
1384
 * \note Not all combinations of address and length are allowed. The packet will be empty
1385
 * if an unallowed address/payloadSize combination is used. Use RIOPACKET_getReadPacketSize()
1386
 * to get the maximum size to use based on the address and payloadSize.
1387
 */
1388
void RIOPACKET_setNread(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid,
1389
                        uint32_t address, uint16_t payloadSize)
1390
{
1391
  uint32_t content;
1392
  uint16_t crc = 0xffffu;
1393
  uint16_t rdsize;
1394
 
1395
 
1396
  /* Convert the address and size to the rdsize field and check if the combination is valid. */
1397
  rdsize = rdsizeGet(address, payloadSize);
1398
  if(rdsize != 0xffff)
1399
  {
1400
    /* The address and size field combination is valid. */
1401
 
1402
    /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1403
    /* ackId is set when the packet is transmitted. */
1404
    content = 0x00120000ul;
1405
    content |= (uint32_t) destId;
1406
    crc = RIOPACKET_Crc32(content, crc);
1407
    packet->payload[0] = content;
1408
 
1409
    /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
1410
    content = ((uint32_t) srcId) << 16;
1411
    content |= ((uint32_t) RIOPACKET_TRANSACTION_REQUEST_NREAD) << 12;
1412
    content |= (uint32_t) (rdsize & 0x0f00);
1413
    content |= (uint32_t) tid;
1414
    crc = RIOPACKET_Crc32(content, crc);
1415
    packet->payload[1] = content;
1416
 
1417
    /* address(28:0)|wdptr|xamsbs(1:0) */
1418
    /* rdsize also contains wdptr in the lower nibble. */
1419
    /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the
1420
       34-bit address should be used, another mechanism to set it should be used. */
1421
    content = address & 0xfffffff8ul;
1422
    content |= ((uint32_t) (rdsize & 0x000f)) << 2;
1423
    crc = RIOPACKET_Crc32(content, crc);
1424
    packet->payload[2] = content;
1425
 
1426
    /* crc(15:0)|pad(15:0) */
1427
    content = ((uint32_t) crc) << 16;
1428
    packet->payload[3] = content;
1429
 
1430
    /* Set the size of the packet. */
1431
    packet->size = 4;
1432
  }
1433
  else
1434
  {
1435
    /* The address and size field combination is not valid. */
1436
    /* Cannot create a packet from these arguments, indicate this by setting the packet size to zero. */
1437
    packet->size = 0;
1438
  }
1439
}
1440
 
1441
 
1442
/**
1443
 * \brief Get entries from an NREAD.
1444
 *
1445
 * \param[in] packet The packet to operate on.
1446
 * \param[out] destId The destination deviceId in this packet.
1447
 * \param[out] srcId The source deviceId in this packet.
1448
 * \param[out] tid The transaction id in this packet.
1449
 * \param[out] address The byte address into IO-space requested to be written.
1450
 * \param[out] payloadSize The number of bytes requested to be read.
1451
 *
1452
 * This function returns the content of a packet as if it contained an NREAD.
1453
 *
1454
 * \note The address is a byte address.
1455
 */
1456
void RIOPACKET_getNread(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid,
1457
                        uint32_t *address, uint16_t *payloadSize)
1458
{
1459
  uint8_t rdsize;
1460
  uint8_t wdptr;
1461
  uint8_t offset = 0;
1462
  uint16_t size = 0;
1463
 
1464
 
1465
  rdsize = WRSIZE_GET(packet->payload);
1466
  wdptr = WDPTR_GET(packet->payload);
1467
  rdsizeToOffset(rdsize, wdptr, &offset, &size);
1468
 
1469
  *destId = DESTID_GET(packet->payload);
1470
  *srcId = SRCID_GET(packet->payload);
1471
  *tid = TID_GET(packet->payload);
1472
  *address = ADDRESS_GET(packet->payload) | offset;
1473
  *payloadSize = size;
1474
}
1475
 
1476
 
1477
 
1478
/*******************************************************************************************
1479
 * Logical message passing DOORBELL and MESSAGE functions.
1480
 *******************************************************************************************/
1481
 
1482
/**
1483
 * \brief Set a packet to contain a DOORBELL.
1484
 *
1485
 * \param[in] packet The packet to operate on.
1486
 * \param[in] destId The deviceId to use as destination in the packet.
1487
 * \param[in] srcId The deviceId to use as source in the packet.
1488
 * \param[in] tid The transaction identifier to set in the packet.
1489
 * \param[in] info The information to send with the doorbell.
1490
 *
1491
 * This function sets the content of a packet to a DOORBELL.
1492
 */
1493
void RIOPACKET_setDoorbell(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t tid,
1494
                           uint16_t info)
1495
{
1496
  uint32_t content;
1497
  uint16_t crc = 0xffffu;
1498
 
1499
 
1500
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1501
  /* ackId is set when the packet is transmitted. */
1502
  content = 0x001a0000ul;
1503
  content |= (uint32_t) destId;
1504
  crc = RIOPACKET_Crc32(content, crc);
1505
  packet->payload[0] = content;
1506
 
1507
  /* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */
1508
  content = ((uint32_t) srcId) << 16;
1509
  content |= (uint32_t) tid;
1510
  crc = RIOPACKET_Crc32(content, crc);
1511
  packet->payload[1] = content;
1512
 
1513
  /* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
1514
  content = ((uint32_t) info) << 16;
1515
  crc = RIOPACKET_Crc16(info, crc);
1516
  content |= crc;
1517
  packet->payload[2] = content;
1518
 
1519
  /* Set the size of the packet. */
1520
  packet->size = 3;
1521
}
1522
 
1523
 
1524
/**
1525
 * \brief Get entries from a DOORBELL.
1526
 *
1527
 * \param[in] packet The packet to operate on.
1528
 * \param[out] destId The destination deviceId in this packet.
1529
 * \param[out] srcId The source deviceId in this packet.
1530
 * \param[out] tid The transaction identifier in this packet.
1531
 * \param[out] info The information field in this packet.
1532
 *
1533
 * This function returns the content of a packet as if it contained a DOORBELL.
1534
 */
1535
void RIOPACKET_getDoorbell(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *tid,
1536
                           uint16_t *info)
1537
{
1538
  *destId = DESTID_GET(packet->payload);
1539
  *srcId = SRCID_GET(packet->payload);
1540
  *tid = TID_GET(packet->payload);
1541
  *info = INFO_GET(packet->payload);
1542
}
1543
 
1544
 
1545
/**
1546
 * \brief Set a packet to contain a MESSAGE.
1547
 *
1548
 * \param[in] packet The packet to operate on.
1549
 * \param[in] destId The deviceId to use as destination in the packet.
1550
 * \param[in] srcId The deviceId to use as source in the packet.
1551
 * \param[in] mailbox The mailbox to send the message to.
1552
 * \param[in] payloadSize The number of bytes to place into the message.
1553
 * \param[in] payload A pointer to the array of bytes to place into the message.
1554
 *
1555
 * This function sets the content of a packet to contain a MESSAGE.
1556
 *
1557
 * \note The mailbox argument maps to the packet fields as:
1558
 * {xmbox(3:0), letter(1:0), mbox(1:0)} which means that mailbox 0-15 can support
1559
 * multipacket messages and 16-255 can handle only single packet messages.
1560
 *
1561
 * \note The payload size has to be larger than zero and less than 256.
1562
 *
1563
 * \note Only payloads of even double-words are supported by the protocol itself. Payload
1564
 * that is shorter will be padded.
1565
 */
1566
void RIOPACKET_setMessage(RioPacket_t *packet, uint16_t destId, uint16_t srcId, uint8_t mailbox,
1567
                          uint16_t payloadSize, uint8_t *payload)
1568
{
1569
  uint32_t content;
1570
 
1571
 
1572
  /* Make sure that the message payload size is larger than zero. */
1573
  if((payloadSize > 0) && (payloadSize <= 256))
1574
  {
1575
    /* The payload size is larger than zero. */
1576
 
1577
    /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1578
    /* ackId is set when the packet is transmitted. */
1579
    content = 0x001b0000ul;
1580
    content |= (uint32_t) destId;
1581
    packet->payload[0] = content;
1582
 
1583
    /* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0)|mbox(1:0)|msgseg(3:0)/xmbox(3:0) */
1584
    content = ((uint32_t) srcId) << 16;
1585
    if(payloadSize <= 8u)
1586
    {
1587
      content |= 0x00000900ul;
1588
    }
1589
    else if(payloadSize <= 16u)
1590
    {
1591
      content |= 0x00000a00ul;
1592
    }
1593
    else if(payloadSize <= 32u)
1594
    {
1595
      content |= 0x00000b00ul;
1596
    }
1597
    else if(payloadSize <= 64u)
1598
    {
1599
      content |= 0x00000c00ul;
1600
    }
1601
    else if(payloadSize <= 128u)
1602
    {
1603
      content |= 0x00000d00ul;
1604
    }
1605
    else
1606
    {
1607
      content |= 0x00000e00ul;
1608
    }
1609
    content |= (((uint32_t) mailbox) & 0xful) << 4;
1610
    content |= ((uint32_t) mailbox) >> 4;
1611
    packet->payload[1] = content;
1612
 
1613
    /* Place data buffer into the payload of the packet and set the size. */
1614
    packet->size = setPacketPayload(&(packet->payload[0]), 8, 0, payloadSize, payload);
1615
  }
1616
  else
1617
  {
1618
    /* The payload size is not allowed. */
1619
    /* Unable to create the new packet. */
1620
    packet->size = 0;
1621
  }
1622
}
1623
 
1624
 
1625
/**
1626
 * \brief Get entries from a MESSAGE.
1627
 *
1628
 * \param[in] packet The packet to operate on.
1629
 * \param[out] destId The destination deviceId in this packet.
1630
 * \param[out] srcId The source deviceId in this packet.
1631
 * \param[out] mailbox The mailbox the message is received on.
1632
 * \param[out] payloadSize The number of bytes in the payload.
1633
 * \param[out] payload The payload of the packet.
1634
 *
1635
 * This function returns the content of a packet as if it contained a MESSAGE.
1636
 *
1637
 * \note The mailbox argument maps to the packet fields as:
1638
 * {xmbox(3:0), letter(1:0), mbox(1:0)} which means that mailbox 0-15 can support
1639
 * multipacket messages and 16-255 can handle only single packet messages.
1640
 *
1641
 * \note Only payloads of even double-words are supported by the protocol itself so the
1642
 * returned payloadSize is always an even multiple of eight.
1643
 */
1644
void RIOPACKET_getMessage(RioPacket_t *packet, uint16_t *destId, uint16_t *srcId, uint8_t *mailbox,
1645
                          uint16_t *payloadSize, uint8_t *payload)
1646
{
1647
  *destId = DESTID_GET(packet->payload);
1648
  *srcId = SRCID_GET(packet->payload);
1649
  *mailbox = XMBOX_GET(packet->payload);
1650
  *mailbox <<= 2;
1651
  *mailbox |= LETTER_GET(packet->payload);
1652
  *mailbox <<= 2;
1653
  *mailbox |= MBOX_GET(packet->payload);
1654
  *payloadSize = getPacketPayload(&(packet->payload[0]), 8, 0, (packet->size-3)*4, payload);
1655
}
1656
 
1657
 
1658
 
1659
 
1660
/*******************************************************************************************
1661
 * Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR
1662
 * functions.
1663
 *******************************************************************************************/
1664
 
1665
/**
1666
 * \brief Set a packet to contain a RESPONSE without payload.
1667
 *
1668
 * \param[in] packet The packet to operate on.
1669
 * \param[in] destId The deviceId to use as destination in the packet.
1670
 * \param[in] srcId The deviceId to use as source in the packet.
1671
 * \param[in] tid The transaction id to send the response for.
1672
 * \param[in] status The status to send in the packet.
1673
 *
1674
 * This function sets the content of a packet to contain a RESPONSE without payload.
1675
 *
1676
 * \note The tid field must be the same value as the packet contained that this is the
1677
 * response for.
1678
 *
1679
 * \note The status field should be either of the values RIOPACKET_RESPONSE_STATUS_XXXX.
1680
 */
1681
void RIOPACKET_setResponseNoPayload(RioPacket_t *packet,
1682
                                    uint16_t destId, uint16_t srcId,
1683
                                    uint8_t tid, uint8_t status)
1684
{
1685
  uint32_t content;
1686
  uint16_t crc = 0xffffu;
1687
 
1688
 
1689
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1690
  /* ackId is set when the packet is transmitted. */
1691
  content = 0x001d0000ul;
1692
  content |= (uint32_t) destId;
1693
  crc = RIOPACKET_Crc32(content, crc);
1694
  packet->payload[0] = content;
1695
 
1696
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
1697
  content = ((uint32_t) srcId) << 16;
1698
  content |= ((uint32_t) RIOPACKET_TRANSACTION_RESPONSE_NO_PAYLOAD) << 12;
1699
  content |= ((uint32_t) (status & 0xf)) << 8;
1700
  content |= (uint32_t) tid;
1701
  crc = RIOPACKET_Crc32(content, crc);
1702
  packet->payload[1] = content;
1703
 
1704
  /* crc(15:0)|pad(15:0) */
1705
  content = ((uint32_t) crc) << 16;
1706
  packet->payload[2] = content;
1707
 
1708
  /* Set the size of the packet. */
1709
  packet->size = 3;
1710
}
1711
 
1712
 
1713
/**
1714
 * \brief Get entries from a RESPONSE without payload.
1715
 *
1716
 * \param[in] packet The packet to operate on.
1717
 * \param[out] destId The destination deviceId in this packet.
1718
 * \param[out] srcId The source deviceId in this packet.
1719
 * \param[out] tid The transaction identifier in this packet.
1720
 * \param[out] status The status in this packet.
1721
 *
1722
 * This function returns the content of a packet as if it contained a RESPONSE.
1723
 */
1724
void RIOPACKET_getResponseNoPayload(RioPacket_t *packet,
1725
                                    uint16_t *destId, uint16_t *srcId,
1726
                                    uint8_t *tid, uint8_t *status)
1727
{
1728
  *destId = DESTID_GET(packet->payload);
1729
  *srcId = SRCID_GET(packet->payload);
1730
  *tid = TID_GET(packet->payload);
1731
  *status = STATUS_GET(packet->payload);
1732
}
1733
 
1734
 
1735
 
1736
/**
1737
 * \brief Set a packet to contain a RESPONSE also containing payload.
1738
 *
1739
 * \param[in] packet The packet to operate on.
1740
 * \param[in] destId The deviceId to use as destination in the packet.
1741
 * \param[in] srcId The deviceId to use as source in the packet.
1742
 * \param[in] tid The transaction id to send the response for.
1743
 * \param[in] offset The offset into the payload to start to write the input payload to.
1744
 * \param[in] payloadSize The size of the payload to return in the reply.
1745
 * \param[in] payload The payload to return in the reply.
1746
 *
1747
 * This function sets the content of a packet to contain a RESPOSE with payload.
1748
 *
1749
 * \note The tid field must be the same value as the packet contained that this is the
1750
 * response for.
1751
 *
1752
 * \note The offset field can be used to offset the payload in a response to, for
1753
 * example, an NREAD.
1754
 *
1755
 * \note The payloadSize must match the size of the packet that this is the
1756
 * response for.
1757
 */
1758
void RIOPACKET_setResponseWithPayload(RioPacket_t *packet,
1759
                                      uint16_t destId, uint16_t srcId,
1760
                                      uint8_t tid, uint8_t offset,
1761
                                      uint16_t payloadSize, uint8_t *payload)
1762
{
1763
  uint32_t content;
1764
 
1765
 
1766
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1767
  /* ackId is set when the packet is transmitted. */
1768
  content = 0x001d0000ul;
1769
  content |= (uint32_t) destId;
1770
  packet->payload[0] = content;
1771
 
1772
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
1773
  /* status=DONE is 0. */
1774
  content = ((uint32_t) srcId) << 16;
1775
  content |= ((uint32_t) RIOPACKET_TRANSACTION_RESPONSE_WITH_PAYLOAD) << 12;
1776
  content |= (uint32_t) tid;
1777
  packet->payload[1] = content;
1778
 
1779
  packet->size = setPacketPayload(&(packet->payload[0]), 8, offset & 0x7, payloadSize, payload);
1780
}
1781
 
1782
/**
1783
 * \brief Get entries from a RESPONSE containing payload.
1784
 *
1785
 * \param[in] packet The packet to operate on.
1786
 * \param[out] destId The destination deviceId in this packet.
1787
 * \param[out] srcId The source deviceId in this packet.
1788
 * \param[out] tid The transaction identifier in this packet.
1789
 * \param[in] offset The offset into the payload to start reading from.
1790
 * \param[out] payloadSize The number of bytes in the payload.
1791
 * \param[out] payload The payload of the packet.
1792
 *
1793
 * This function returns the content of a packet as if it contained a RESPONSE with payload.
1794
 *
1795
 * \note The offset field can be used to read the payload in a response to, for
1796
 * example, an NREAD.
1797
 */
1798
void RIOPACKET_getResponseWithPayload(RioPacket_t *packet,
1799
                                      uint16_t *destId, uint16_t *srcId,
1800
                                      uint8_t *tid, uint8_t offset,
1801
                                      uint16_t *payloadSize, uint8_t *payload)
1802
{
1803
  *destId = DESTID_GET(packet->payload);
1804
  *srcId = SRCID_GET(packet->payload);
1805
  *tid = TID_GET(packet->payload);
1806
  *payloadSize = getPacketPayload(&(packet->payload[0]), 8, offset & 0x7, (packet->size-3)*4, payload);
1807
}
1808
 
1809
 
1810
 
1811
/**
1812
 * \brief Set a packet to contains a RESPONSE to a message.
1813
 *
1814
 * \param[in] packet The packet to operate on.
1815
 * \param[in] destId The deviceId to use as destination in the packet.
1816
 * \param[in] srcId The deviceId to use as source in the packet.
1817
 * \param[in] mailbox The mailbox to send the message to.
1818
 * \param[in] status The status to send in the packet.
1819
 *
1820
 * This function is used to send a response indicating a successfull
1821
 * completion in reply to a previously received packet.
1822
 *
1823
 * \note The mailbox field should contain the same value as the packet that this is the
1824
 * response to.
1825
 *
1826
 * \note The status field should be either of the values RIOPACKET_RESPONSE_STATUS_XXXX.
1827
 */
1828
void RIOPACKET_setResponseMessage(RioPacket_t *packet,
1829
                                  uint16_t destId, uint16_t srcId,
1830
                                  uint8_t mailbox, uint8_t status)
1831
{
1832
  uint32_t content;
1833
  uint16_t crc = 0xffffu;
1834
 
1835
 
1836
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
1837
  /* ackId is set when the packet is transmitted. */
1838
  content = 0x001d0000ul;
1839
  content |= (uint32_t) destId;
1840
  crc = RIOPACKET_Crc32(content, crc);
1841
  packet->payload[0] = content;
1842
 
1843
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|letter(1:0|mbox(1:0)|msgseg(3:0) */
1844
  content = ((uint32_t) srcId) << 16;
1845
  content |= ((uint32_t) RIOPACKET_TRANSACTION_RESPONSE_MESSAGE_RESPONSE) << 12;
1846
  content |= ((uint32_t) (status & 0xf)) << 8;
1847
  content |= ((uint32_t) (mailbox & 0xf)) << 4;
1848
  content |= ((uint32_t) mailbox) >> 4;
1849
  crc = RIOPACKET_Crc32(content, crc);
1850
  packet->payload[1] = content;
1851
 
1852
  /* crc(15:0)|pad(15:0) */
1853
  content = ((uint32_t) crc) << 16;
1854
  packet->payload[2] = content;
1855
 
1856
  /* Set the size of the packet. */
1857
  packet->size = 3;
1858
}
1859
 
1860
/**
1861
 * \brief Get entries from a RESPONSE to a message.
1862
 *
1863
 * \param[in] packet The packet to operate on.
1864
 * \param[out] destId The destination deviceId in this packet.
1865
 * \param[out] srcId The source deviceId in this packet.
1866
 * \param[out] mailbox The mailbox the response should be sent to.
1867
 * \param[out] status The status in the packet.
1868
 *
1869
 * This function returns the content of a packet as if it contained a RESPONSE to a message.
1870
 */
1871
void RIOPACKET_getResponseMessage(RioPacket_t *packet,
1872
                                  uint16_t *destId, uint16_t *srcId,
1873
                                  uint8_t *mailbox, uint8_t *status)
1874
{
1875
  *destId = DESTID_GET(packet->payload);
1876
  *srcId = SRCID_GET(packet->payload);
1877
  *mailbox = XMBOX_GET(packet->payload);
1878
  *mailbox <<= 2;
1879
  *mailbox |= LETTER_GET(packet->payload);
1880
  *mailbox <<= 2;
1881
  *mailbox |= MBOX_GET(packet->payload);
1882
  *status = STATUS_GET(packet->payload);
1883
}
1884
 
1885
 
1886
/**
1887
 * \brief Calculate a new CRC16 value.
1888
 *
1889
 * \param[in] data The new data (16-bit) to update the current crc value with.
1890
 * \param[in] crc The old crc value that should be updated.
1891
 * \returns The new crc value based on the input arguments.
1892
 *
1893
 * This function calculates a new crc value using the generator polynom
1894
 * P(X)=x16+x12+x5+1. It is defined in RapidIO 3.0 part6 chapter 2.4.2.
1895
 */
1896
uint16_t RIOPACKET_Crc16(const uint16_t data, const uint16_t crc)
1897
{
1898
  static const uint16_t crcTable[] = {
1899
    0x0000u, 0x1021u, 0x2042u, 0x3063u, 0x4084u, 0x50a5u, 0x60c6u, 0x70e7u,
1900
    0x8108u, 0x9129u, 0xa14au, 0xb16bu, 0xc18cu, 0xd1adu, 0xe1ceu, 0xf1efu,
1901
    0x1231u, 0x0210u, 0x3273u, 0x2252u, 0x52b5u, 0x4294u, 0x72f7u, 0x62d6u,
1902
    0x9339u, 0x8318u, 0xb37bu, 0xa35au, 0xd3bdu, 0xc39cu, 0xf3ffu, 0xe3deu,
1903
    0x2462u, 0x3443u, 0x0420u, 0x1401u, 0x64e6u, 0x74c7u, 0x44a4u, 0x5485u,
1904
    0xa56au, 0xb54bu, 0x8528u, 0x9509u, 0xe5eeu, 0xf5cfu, 0xc5acu, 0xd58du,
1905
    0x3653u, 0x2672u, 0x1611u, 0x0630u, 0x76d7u, 0x66f6u, 0x5695u, 0x46b4u,
1906
    0xb75bu, 0xa77au, 0x9719u, 0x8738u, 0xf7dfu, 0xe7feu, 0xd79du, 0xc7bcu,
1907
    0x48c4u, 0x58e5u, 0x6886u, 0x78a7u, 0x0840u, 0x1861u, 0x2802u, 0x3823u,
1908
    0xc9ccu, 0xd9edu, 0xe98eu, 0xf9afu, 0x8948u, 0x9969u, 0xa90au, 0xb92bu,
1909
    0x5af5u, 0x4ad4u, 0x7ab7u, 0x6a96u, 0x1a71u, 0x0a50u, 0x3a33u, 0x2a12u,
1910
    0xdbfdu, 0xcbdcu, 0xfbbfu, 0xeb9eu, 0x9b79u, 0x8b58u, 0xbb3bu, 0xab1au,
1911
    0x6ca6u, 0x7c87u, 0x4ce4u, 0x5cc5u, 0x2c22u, 0x3c03u, 0x0c60u, 0x1c41u,
1912
    0xedaeu, 0xfd8fu, 0xcdecu, 0xddcdu, 0xad2au, 0xbd0bu, 0x8d68u, 0x9d49u,
1913
    0x7e97u, 0x6eb6u, 0x5ed5u, 0x4ef4u, 0x3e13u, 0x2e32u, 0x1e51u, 0x0e70u,
1914
    0xff9fu, 0xefbeu, 0xdfddu, 0xcffcu, 0xbf1bu, 0xaf3au, 0x9f59u, 0x8f78u,
1915
    0x9188u, 0x81a9u, 0xb1cau, 0xa1ebu, 0xd10cu, 0xc12du, 0xf14eu, 0xe16fu,
1916
    0x1080u, 0x00a1u, 0x30c2u, 0x20e3u, 0x5004u, 0x4025u, 0x7046u, 0x6067u,
1917
    0x83b9u, 0x9398u, 0xa3fbu, 0xb3dau, 0xc33du, 0xd31cu, 0xe37fu, 0xf35eu,
1918
    0x02b1u, 0x1290u, 0x22f3u, 0x32d2u, 0x4235u, 0x5214u, 0x6277u, 0x7256u,
1919
    0xb5eau, 0xa5cbu, 0x95a8u, 0x8589u, 0xf56eu, 0xe54fu, 0xd52cu, 0xc50du,
1920
    0x34e2u, 0x24c3u, 0x14a0u, 0x0481u, 0x7466u, 0x6447u, 0x5424u, 0x4405u,
1921
    0xa7dbu, 0xb7fau, 0x8799u, 0x97b8u, 0xe75fu, 0xf77eu, 0xc71du, 0xd73cu,
1922
    0x26d3u, 0x36f2u, 0x0691u, 0x16b0u, 0x6657u, 0x7676u, 0x4615u, 0x5634u,
1923
    0xd94cu, 0xc96du, 0xf90eu, 0xe92fu, 0x99c8u, 0x89e9u, 0xb98au, 0xa9abu,
1924
    0x5844u, 0x4865u, 0x7806u, 0x6827u, 0x18c0u, 0x08e1u, 0x3882u, 0x28a3u,
1925
    0xcb7du, 0xdb5cu, 0xeb3fu, 0xfb1eu, 0x8bf9u, 0x9bd8u, 0xabbbu, 0xbb9au,
1926
    0x4a75u, 0x5a54u, 0x6a37u, 0x7a16u, 0x0af1u, 0x1ad0u, 0x2ab3u, 0x3a92u,
1927
    0xfd2eu, 0xed0fu, 0xdd6cu, 0xcd4du, 0xbdaau, 0xad8bu, 0x9de8u, 0x8dc9u,
1928
    0x7c26u, 0x6c07u, 0x5c64u, 0x4c45u, 0x3ca2u, 0x2c83u, 0x1ce0u, 0x0cc1u,
1929
    0xef1fu, 0xff3eu, 0xcf5du, 0xdf7cu, 0xaf9bu, 0xbfbau, 0x8fd9u, 0x9ff8u,
1930
    0x6e17u, 0x7e36u, 0x4e55u, 0x5e74u, 0x2e93u, 0x3eb2u, 0x0ed1u, 0x1ef0u
1931
  };
1932
 
1933
  uint16_t result;
1934
  uint8_t index;
1935
 
1936
  result = crc;
1937
  index = (uint8_t) ((data >> 8) ^ (result >> 8));
1938
  result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8));
1939
  index = (uint8_t) ((data) ^ (result >> 8));
1940
  result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8));
1941
 
1942
  return result;
1943
}
1944
 
1945
 
1946
/**
1947
 * \brief Calculate a new CRC16 value.
1948
 *
1949
 * \param[in] data The new data (32-bit) to update the current crc value with.
1950
 * \param[in] crc The old crc value that should be updated.
1951
 * \returns The new crc value based on the input arguments.
1952
 *
1953
 * This function calculates a new crc value using the generator polynom
1954
 * P(X)=x16+x12+x5+1. It is defined in RapidIO 3.0 part6 chapter 2.4.2.
1955
 */
1956
uint16_t RIOPACKET_Crc32(const uint32_t data, uint16_t crc)
1957
{
1958
  crc = RIOPACKET_Crc16((uint16_t) (data >> 16), crc);
1959
  crc = RIOPACKET_Crc16((uint16_t) (data), crc);
1960
  return crc;
1961
}
1962
 
1963
 
1964
/**
1965
 * \brief Get the maximum size of an NWRITE payload.
1966
 *
1967
 * \param[in] address The starting address to write to in the NWRITE.
1968
 * \param[in] size The total size of the access to NWRITE.
1969
 * \returns The maximum number of bytes that are allowed to send in a single
1970
 * NWRITE packet that conforms to the RapidIO standard.
1971
 *
1972
 * This function calculates the maximum sized NWRITE packet payload that are
1973
 * possible to send without breaking the limitations in the RapidIO specification.
1974
 * It is intended to be called repeatedly.
1975
 *
1976
 * Example: An area with address=0x00007 and size=258 needs to be written.
1977
 *          Call RIOPACKET_getWritePacketSize(0x00007, 258)->1.
1978
 *          Send an NWRITE to address=0x00007 and size=1.
1979
 *          Update the address and size with the returned value->
1980
 *          address+=1->address=0x00008 size-=1->size=257.
1981
 *          Call RIOPACKET_getWritePacketSize(0x00008, 257)->256.
1982
 *          Send an NWRITE to address=0x00008 and size=256.
1983
 *          Update the address and size with the returned value->
1984
 *          address+=256->address=0x00108 size-=256->size=1.
1985
 *          Call RIOPACKET_getWritePacketSize(0x00108, 1)->1.
1986
 *          Send an NWRITE to address=0x00108 and size=1.
1987
 *          Update the address and size with the returned value->
1988
 *          address+=1->address=0x00109 size-=1->size=0.
1989
 *          All the data has been written.
1990
 *
1991
 */
1992
uint32_t RIOPACKET_getWritePacketSize(uint32_t address, uint32_t size)
1993
{
1994
  uint32_t returnValue;
1995
 
1996
 
1997
  switch(address%8)
1998
  {
1999
    case 0:
2000
      if(size >= 256)
2001
      {
2002
        returnValue = 256;
2003
      }
2004
      else if(size >= 8)
2005
      {
2006
        returnValue = size - (size % 8);
2007
      }
2008
      else
2009
      {
2010
        returnValue = size;
2011
      }
2012
      break;
2013
    case 1:
2014
      if(size >= 7)
2015
      {
2016
        returnValue = 7;
2017
      }
2018
      else
2019
      {
2020
        returnValue = 1;
2021
      }
2022
      break;
2023
    case 2:
2024
      if(size >= 6)
2025
      {
2026
        returnValue = 6;
2027
      }
2028
      else if(size >= 2)
2029
      {
2030
        returnValue = 2;
2031
      }
2032
      else
2033
      {
2034
        returnValue = 1;
2035
      }
2036
      break;
2037
    case 3:
2038
      if(size >= 5)
2039
      {
2040
        returnValue = 5;
2041
      }
2042
      else
2043
      {
2044
        returnValue = 1;
2045
      }
2046
      break;
2047
    case 4:
2048
      if(size >= 4)
2049
      {
2050
        returnValue = 4;
2051
      }
2052
      else if(size >= 2)
2053
      {
2054
        returnValue = 2;
2055
      }
2056
      else
2057
      {
2058
        returnValue = 1;
2059
      }
2060
      break;
2061
    case 5:
2062
      if(size >= 3)
2063
      {
2064
        returnValue = 3;
2065
      }
2066
      else
2067
      {
2068
        returnValue = 1;
2069
      }
2070
      break;
2071
    case 6:
2072
      if(size >= 2)
2073
      {
2074
        returnValue = 2;
2075
      }
2076
      else
2077
      {
2078
        returnValue = 1;
2079
      }
2080
      break;
2081
    default:
2082
      returnValue = 1;
2083
      break;
2084
  }
2085
 
2086
  return returnValue;
2087
}
2088
 
2089
 
2090
/**
2091
 * \brief Get the maximum size of an NREAD payload.
2092
 *
2093
 * \param[in] address The starting address to read from in the NREAD.
2094
 * \param[in] size The total size of the access to NREAD.
2095
 * \returns The maximum number of bytes that are allowed to send in a single
2096
 * NREAD packet that conforms to the RapidIO standard.
2097
 *
2098
 * This function calculates the maximum sized NREAD packet payload that are
2099
 * possible to send without breaking the limitations in the RapidIO specification.
2100
 * It is intended to be called repeatedly.
2101
 *
2102
 * Example: An area with address=0x00007 and size=258 needs to be read.
2103
 *          Call RIOPACKET_getReadPacketSize(0x00007, 258)->1.
2104
 *          Send an NREAD to address=0x00007 and size=1.
2105
 *          Update the address and size with the returned value->
2106
 *          address+=1->address=0x00008 size-=1->size=257.
2107
 *          Call RIOPACKET_getReadPacketSize(0x00008, 257)->256.
2108
 *          Send an NREAD to address=0x00008 and size=256.
2109
 *          Update the address and size with the returned value->
2110
 *          address+=256->address=0x00108 size-=256->size=1.
2111
 *          Call RIOPACKET_getReadPacketSize(0x00108, 1)->1.
2112
 *          Send an NREAD to address=0x00108 and size=1.
2113
 *          Update the address and size with the returned value->
2114
 *          address+=1->address=0x00109 size-=1->size=0.
2115
 *          All the data has been read.
2116
 *
2117
 */
2118
uint32_t RIOPACKET_getReadPacketSize(uint32_t address, uint32_t size)
2119
{
2120
  uint32_t returnValue;
2121
 
2122
 
2123
  switch(address%8)
2124
  {
2125
    case 0:
2126
      if(size >= 256)
2127
      {
2128
        returnValue = 256;
2129
      }
2130
      else if(size >= 224)
2131
      {
2132
        returnValue = 224;
2133
      }
2134
      else if(size >= 192)
2135
      {
2136
        returnValue = 192;
2137
      }
2138
      else if(size >= 160)
2139
      {
2140
        returnValue = 160;
2141
      }
2142
      else if(size >= 128)
2143
      {
2144
        returnValue = 128;
2145
      }
2146
      else if(size >= 96)
2147
      {
2148
        returnValue = 96;
2149
      }
2150
      else if(size >= 64)
2151
      {
2152
        returnValue = 64;
2153
      }
2154
      else if(size >= 32)
2155
      {
2156
        returnValue = 32;
2157
      }
2158
      else if(size >= 16)
2159
      {
2160
        returnValue = 16;
2161
      }
2162
      else if(size >= 8)
2163
      {
2164
        returnValue = 8;
2165
      }
2166
      else
2167
      {
2168
        returnValue = size;
2169
      }
2170
      break;
2171
    case 1:
2172
      if(size >= 7)
2173
      {
2174
        returnValue = 7;
2175
      }
2176
      else
2177
      {
2178
        returnValue = 1;
2179
      }
2180
      break;
2181
    case 2:
2182
      if(size >= 6)
2183
      {
2184
        returnValue = 6;
2185
      }
2186
      else if(size >= 2)
2187
      {
2188
        returnValue = 2;
2189
      }
2190
      else
2191
      {
2192
        returnValue = 1;
2193
      }
2194
      break;
2195
    case 3:
2196
      if(size >= 5)
2197
      {
2198
        returnValue = 5;
2199
      }
2200
      else
2201
      {
2202
        returnValue = 1;
2203
      }
2204
      break;
2205
    case 4:
2206
      if(size >= 4)
2207
      {
2208
        returnValue = 4;
2209
      }
2210
      else if(size >= 2)
2211
      {
2212
        returnValue = 2;
2213
      }
2214
      else
2215
      {
2216
        returnValue = 1;
2217
      }
2218
      break;
2219
    case 5:
2220
      if(size >= 3)
2221
      {
2222
        returnValue = 3;
2223
      }
2224
      else
2225
      {
2226
        returnValue = 1;
2227
      }
2228
      break;
2229
    case 6:
2230
      if(size >= 2)
2231
      {
2232
        returnValue = 2;
2233
      }
2234
      else
2235
      {
2236
        returnValue = 1;
2237
      }
2238
      break;
2239
    default:
2240
      returnValue = 1;
2241
      break;
2242
  }
2243
 
2244
  return returnValue;
2245
}
2246
 
2247
 
2248
 
2249
/*******************************************************************************
2250
 * Locally used helper functions.
2251
 *******************************************************************************/
2252
 
2253
static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset,
2254
                                 const uint16_t dataSize, uint8_t *data)
2255
{
2256
  uint32_t content = 0;
2257
  uint16_t packetIndex;
2258
  uint16_t payloadIndex;
2259
  uint16_t dataIndex;
2260
 
2261
 
2262
  /* Move payload bytes from RapidIO packet into a user buffer. */
2263
  /* Long packets contain a CRC in byte 80-81, this is removed when the buffer
2264
     is copied. */
2265
  packetIndex = payloadOffset;
2266
  payloadIndex = 0;
2267
  dataIndex = 0;
2268
  while(dataIndex < dataSize)
2269
  {
2270
    /* Check if a new word should be read from the inbound queue. */
2271
    if((packetIndex & 0x3) == 0)
2272
    {
2273
      /* Get a new word. */
2274
      content = packet[packetIndex>>2];
2275
    }
2276
    else
2277
    {
2278
      /* Update the current word. Remove the MSB, it has already be moved
2279
         to the user buffer. */
2280
      content <<= 8;
2281
    }
2282
 
2283
    /* Check if the current byte is CRC. */
2284
    if((packetIndex != 80) && (packetIndex != 81) && (payloadIndex >= dataOffset))
2285
    {
2286
      /* Not CRC. */
2287
      /* Move the byte to the user buffer. */
2288
      data[dataIndex++] = (content >> 24);
2289
    }
2290
 
2291
    /* Increment to the next position in the packet. */
2292
    packetIndex++;
2293
    payloadIndex++;
2294
  }
2295
 
2296
  return dataIndex;
2297
}
2298
 
2299
 
2300
static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset,
2301
                                 const uint16_t dataSize, const uint8_t *data)
2302
{
2303
  uint16_t crc = 0xffffu;
2304
  uint32_t content = 0;
2305
  uint16_t packetIndex;
2306
  uint16_t payloadIndex;
2307
  uint16_t dataIndex;
2308
 
2309
 
2310
  /***************************************************
2311
   * Calculate the CRC for the packet header.
2312
   ***************************************************/
2313
  for(packetIndex = 0; packetIndex < payloadOffset; packetIndex+=4)
2314
  {
2315
    crc = RIOPACKET_Crc32(packet[packetIndex>>2], crc);
2316
  }
2317
 
2318
  /***************************************************
2319
   * Pad the data before the actual data is written.
2320
   ***************************************************/
2321
  payloadIndex = 0;
2322
  while(payloadIndex < dataOffset)
2323
  {
2324
    content <<= 8;
2325
 
2326
    if((packetIndex & 0x3) == 3)
2327
    {
2328
      crc = RIOPACKET_Crc32(content, crc);
2329
      packet[packetIndex>>2] = content;
2330
    }
2331
 
2332
    payloadIndex++;
2333
    packetIndex++;
2334
  }
2335
 
2336
  /***************************************************
2337
   * Write content and any embedded CRC.
2338
   ***************************************************/
2339
  dataIndex = 0;
2340
  while(dataIndex < dataSize)
2341
  {
2342
    content <<= 8;
2343
 
2344
    /* Check if CRC or content should be entered into the packet. */
2345
    if(packetIndex == 80)
2346
    {
2347
      /* CRC MSB. */
2348
      content |= crc >> 8;
2349
    }
2350
    else if(packetIndex == 81)
2351
    {
2352
      /* CRC LSB. */
2353
      content |= crc & 0xff;
2354
    }
2355
    else
2356
    {
2357
      /* Data content. */
2358
      content |= data[dataIndex++];
2359
      payloadIndex++;
2360
    }
2361
 
2362
    if((packetIndex & 0x3) == 3)
2363
    {
2364
      crc = RIOPACKET_Crc32(content, crc);
2365
      packet[packetIndex>>2] = content;
2366
    }
2367
 
2368
    packetIndex++;
2369
  }
2370
 
2371
  /***************************************************
2372
   * Pad the data to an even double word.
2373
   ***************************************************/
2374
  while((payloadIndex & 0x7) != 0)
2375
  {
2376
    content <<= 8;
2377
 
2378
    if((packetIndex & 0x3) == 3)
2379
    {
2380
      crc = RIOPACKET_Crc32(content, crc);
2381
      packet[packetIndex>>2] = content;
2382
    }
2383
 
2384
    packetIndex++;
2385
    payloadIndex++;
2386
  }
2387
 
2388
  /***************************************************
2389
   * Write the CRC into the packet.
2390
   ***************************************************/
2391
  if((packetIndex & 0x3) == 0)
2392
  {
2393
    /* crc(15:0)|pad(15:0) */
2394
    content = ((uint32_t) crc) << 16;
2395
  }
2396
  else
2397
  {
2398
    /* double-wordN-LSB|crc(15:0) */
2399
    content &= 0x0000ffff;
2400
    crc = RIOPACKET_Crc16(content, crc);
2401
    content <<= 16;
2402
    content |= crc;
2403
  }
2404
  packet[packetIndex>>2] = content;
2405
 
2406
  return (packetIndex>>2)+1;
2407
}
2408
 
2409
 
2410
 
2411
/* \note See the RapidIO standard part1 table 4-4 for details about
2412
 * {address, size}->{wdptr, wrsize} mapping.
2413
 */
2414
static uint16_t rdsizeGet(const uint32_t address, const uint16_t size)
2415
{
2416
  uint8_t wdptr;
2417
  uint8_t rdsize;
2418
 
2419
 
2420
  switch(size/8)
2421
  {
2422
    case 0:
2423
      /**************************************************************
2424
       * Sub double-word access.
2425
       **************************************************************/
2426
      switch(size%8)
2427
      {
2428
        case 0:
2429
          /* Not supported by protocol. */
2430
          wdptr = 0xff;
2431
          rdsize = 0xff;
2432
          break;
2433
        case 1:
2434
          /* Reading one byte. */
2435
          /* Any address is allowed. */
2436
          wdptr = (address >> 2) & 0x1;
2437
          rdsize = address & 0x3;
2438
          break;
2439
        case 2:
2440
          /* Reading two bytes. */
2441
          /* Address 0, 2, 4, 6 are valid. */
2442
          if((address & 0x1) == 0)
2443
          {
2444
            wdptr = (address >> 2) & 0x1;
2445
            rdsize = (address & 0x7) | 0x4;
2446
          }
2447
          else
2448
          {
2449
            /* Not supported by protocol. */
2450
            wdptr = 0xff;
2451
            rdsize = 0xff;
2452
          }
2453
          break;
2454
        case 3:
2455
          /* Reading 3 bytes. */
2456
          /* Address 0 and 5 are valid. */
2457
          if(((address & 0x7) == 0) ||
2458
             ((address & 0x7) == 5))
2459
          {
2460
            wdptr = (address >> 2) & 0x1;
2461
            rdsize = 0x5ul;
2462
          }
2463
          else
2464
          {
2465
            /* Not supported by protocol. */
2466
            wdptr = 0xff;
2467
            rdsize = 0xff;
2468
          }
2469
          break;
2470
        case 4:
2471
          /* Reading 4 bytes. */
2472
          /* Address 0 and 4 are valid. */
2473
          if(((address & 0x7) == 0) ||
2474
             ((address & 0x7) == 4))
2475
          {
2476
            wdptr = (address >> 2) & 0x1;
2477
            rdsize = 0x8ul;
2478
          }
2479
          else
2480
          {
2481
            /* Not supported by protocol. */
2482
            wdptr = 0xff;
2483
            rdsize = 0xff;
2484
          }
2485
          break;
2486
        case 5:
2487
          /* Reading 5 bytes. */
2488
          /* Address 0 and 3 are valid. */
2489
          if(((address & 0x7) == 0) ||
2490
             ((address & 0x7) == 3))
2491
          {
2492
            wdptr = (address >> 1) & 0x1;
2493
            rdsize = 0x7ul;
2494
          }
2495
          else
2496
          {
2497
            /* Not supported by protocol. */
2498
            wdptr = 0xff;
2499
            rdsize = 0xff;
2500
          }
2501
          break;
2502
        case 6:
2503
          /* Reading 6 bytes. */
2504
          /* Addresses 0 and 2 are valid. */
2505
          if(((address & 0x7) == 0) ||
2506
             ((address & 0x7) == 2))
2507
          {
2508
            wdptr = (address >> 1) & 0x1;
2509
            rdsize = 0x9ul;
2510
          }
2511
          else
2512
          {
2513
            /* Not supported by protocol. */
2514
            wdptr = 0xff;
2515
            rdsize = 0xff;
2516
          }
2517
          break;
2518
        default:
2519
          /* Reading 7 bytes. */
2520
          /* Addresses 0 and 1 are valid. */
2521
          if(((address & 0x7) == 0) ||
2522
             ((address & 0x7) == 1))
2523
          {
2524
            wdptr = address & 0x1;
2525
            rdsize = 0xaul;
2526
          }
2527
          else
2528
          {
2529
            /* Not supported by protocol. */
2530
            wdptr = 0xff;
2531
            rdsize = 0xff;
2532
          }
2533
          break;
2534
      }
2535
      break;
2536
    case 1:
2537
      /* Reading 8 bytes. */
2538
      /* Only even double-word address are valid. */
2539
      if((address % 8) == 0)
2540
      {
2541
        wdptr = 0;
2542
        rdsize = 0xbul;
2543
      }
2544
      else
2545
      {
2546
        /* Not supported by protocol. */
2547
        wdptr = 0xff;
2548
        rdsize = 0xff;
2549
      }
2550
      break;
2551
    case 2:
2552
      /* Reading 16 bytes max. */
2553
      /* Only even double-word address are valid. */
2554
      if((address % 8) == 0)
2555
      {
2556
        wdptr = 1;
2557
        rdsize = 0xbul;
2558
      }
2559
      else
2560
      {
2561
        /* Not supported by protocol. */
2562
        wdptr = 0xff;
2563
        rdsize = 0xff;
2564
      }
2565
      break;
2566
    case 3:
2567
      /* Not supported by protocol. */
2568
      wdptr = 0xff;
2569
      rdsize = 0xff;
2570
      break;
2571
    case 4:
2572
      /* Reading 32 bytes max. */
2573
      /* Only even double-word address are valid. */
2574
      if((address & 0x7) == 0)
2575
      {
2576
        wdptr = 0;
2577
        rdsize = 0xcul;
2578
      }
2579
      else
2580
      {
2581
        /* Not supported by protocol. */
2582
        wdptr = 0xff;
2583
        rdsize = 0xff;
2584
      }
2585
      break;
2586
    case 5:
2587
    case 6:
2588
    case 7:
2589
      /* Not supported by protocol. */
2590
      wdptr = 0xff;
2591
      rdsize = 0xff;
2592
      break;
2593
    case 8:
2594
      /* Reading 64 bytes max. */
2595
      /* Only even double-word address are valid. */
2596
      if((address & 0x7) == 0)
2597
      {
2598
        wdptr = 1;
2599
        rdsize = 0xcul;
2600
      }
2601
      else
2602
      {
2603
        /* Not supported by protocol. */
2604
        wdptr = 0xff;
2605
        rdsize = 0xff;
2606
      }
2607
      break;
2608
    case 9:
2609
    case 10:
2610
    case 11:
2611
      /* Not supported by protocol. */
2612
      wdptr = 0xff;
2613
      rdsize = 0xff;
2614
      break;
2615
    case 12:
2616
      /* Reading 96 bytes. */
2617
      /* Only even double-word address are valid. */
2618
      if((address & 0x7) == 0)
2619
      {
2620
        wdptr = 0;
2621
        rdsize = 0xdul;
2622
      }
2623
      else
2624
      {
2625
        /* Not supported by protocol. */
2626
        wdptr = 0xff;
2627
        rdsize = 0xff;
2628
      }
2629
      break;
2630
    case 13:
2631
    case 14:
2632
    case 15:
2633
      /* Not supported by protocol. */
2634
      wdptr = 0xff;
2635
      rdsize = 0xff;
2636
      break;
2637
    case 16:
2638
      /* Reading 128 bytes max. */
2639
      /* Only even double-word address are valid. */
2640
      if((address & 0x7) == 0)
2641
      {
2642
        wdptr = 1;
2643
        rdsize = 0xdul;
2644
      }
2645
      else
2646
      {
2647
        /* Not supported by protocol. */
2648
        wdptr = 0xff;
2649
        rdsize = 0xff;
2650
      }
2651
      break;
2652
    case 17:
2653
    case 18:
2654
    case 19:
2655
      /* Not supported by protocol. */
2656
      wdptr = 0xff;
2657
      rdsize = 0xff;
2658
      break;
2659
    case 20:
2660
      /* Reading 160 bytes. */
2661
      /* Only even double-word address are valid. */
2662
      if((address & 0x7) == 0)
2663
      {
2664
        wdptr = 0;
2665
        rdsize = 0xeul;
2666
      }
2667
      else
2668
      {
2669
        /* Not supported by protocol. */
2670
        wdptr = 0xff;
2671
        rdsize = 0xff;
2672
      }
2673
      break;
2674
    case 21:
2675
    case 22:
2676
    case 23:
2677
      /* Not supported by protocol. */
2678
      wdptr = 0xff;
2679
      rdsize = 0xff;
2680
      break;
2681
    case 24:
2682
      /* Reading 192 bytes. */
2683
      /* Only even double-word address are valid. */
2684
      if((address & 0x7) == 0)
2685
      {
2686
        wdptr = 1;
2687
        rdsize = 0xeul;
2688
      }
2689
      else
2690
      {
2691
        /* Not supported by protocol. */
2692
        wdptr = 0xff;
2693
        rdsize = 0xff;
2694
      }
2695
      break;
2696
    case 25:
2697
    case 26:
2698
    case 27:
2699
      /* Not supported by protocol. */
2700
      wdptr = 0xff;
2701
      rdsize = 0xff;
2702
      break;
2703
    case 28:
2704
      /* Reading 224 bytes. */
2705
      /* Only even double-word address are valid. */
2706
      if((address & 0x7) == 0)
2707
      {
2708
        wdptr = 0;
2709
        rdsize = 0xful;
2710
      }
2711
      else
2712
      {
2713
        /* Not supported by protocol. */
2714
        wdptr = 0xff;
2715
        rdsize = 0xff;
2716
      }
2717
      break;
2718
    case 29:
2719
    case 30:
2720
    case 31:
2721
      /* Not supported by protocol. */
2722
      wdptr = 0xff;
2723
      rdsize = 0xff;
2724
      break;
2725
    case 32:
2726
      /* Reading 256 bytes max. */
2727
      /* Only even double-word address are valid. */
2728
      if((address & 0x7) == 0)
2729
      {
2730
        wdptr = 1;
2731
        rdsize = 0xful;
2732
      }
2733
      else
2734
      {
2735
        /* Not supported by protocol. */
2736
        wdptr = 0xff;
2737
        rdsize = 0xff;
2738
      }
2739
      break;
2740
    default:
2741
      /* Not supported by protocol. */
2742
      wdptr = 0xff;
2743
      rdsize = 0xff;
2744
      break;
2745
  }
2746
 
2747
  return ((((uint16_t) rdsize) << 8) | ((uint16_t) wdptr));
2748
}
2749
 
2750
 
2751
void rdsizeToOffset(uint8_t rdsize, uint8_t wdptr, uint8_t *offset, uint16_t *size)
2752
{
2753
  switch(rdsize)
2754
  {
2755
    case 0:
2756
    case 1:
2757
    case 2:
2758
    case 3:
2759
      *offset = wdptr << 2;
2760
      *offset |= rdsize;
2761
      *size = 1;
2762
      break;
2763
    case 4:
2764
    case 6:
2765
      *offset = wdptr << 2;
2766
      *offset |= rdsize & 0x02;
2767
      *size = 2;
2768
      break;
2769
    case 5:
2770
      *offset = wdptr * 5;
2771
      *size = 3;
2772
      break;
2773
    case 8:
2774
      *offset = wdptr * 4;
2775
      *size = 4;
2776
      break;
2777
    case 7:
2778
      *offset = wdptr * 3;
2779
      *size = 5;
2780
      break;
2781
    case 9:
2782
      *offset = wdptr * 2;
2783
      *size = 6;
2784
      break;
2785
    case 10:
2786
      *offset = wdptr * 1;
2787
      *size = 7;
2788
      break;
2789
    case 11:
2790
      *offset = 0;
2791
      *size = 8 + 8*wdptr;
2792
      break;
2793
    case 12:
2794
      *offset = 0;
2795
      *size = 32 + 32*wdptr;
2796
      break;
2797
    case 13:
2798
      *offset = 0;
2799
      *size = 96 + 32*wdptr;
2800
      break;
2801
    case 14:
2802
      *offset = 0;
2803
      *size = 160 + 32*wdptr;
2804
      break;
2805
    case 15:
2806
      *offset = 0;
2807
      *size = 224 + 32*wdptr;
2808
      break;
2809
  }
2810
}
2811
 
2812
 
2813
static uint16_t wrsizeGet(const uint32_t address, const uint16_t size)
2814
{
2815
  uint8_t wdptr;
2816
  uint8_t wrsize;
2817
 
2818
 
2819
  switch(size/8)
2820
  {
2821
    case 0:
2822
      /**************************************************************
2823
       * Sub double-word access.
2824
       **************************************************************/
2825
      switch(size%8)
2826
      {
2827
        case 0:
2828
          /* Not supported by protocol. */
2829
          wdptr = 0xff;
2830
          wrsize = 0xff;
2831
          break;
2832
        case 1:
2833
          /* Writing one byte. */
2834
          /* Any address is allowed. */
2835
          wdptr = (address >> 2) & 0x1;
2836
          wrsize = address & 0x3;
2837
          break;
2838
        case 2:
2839
          /* Writing two bytes. */
2840
          /* Address 0, 2, 4, 6 are valid. */
2841
          if((address & 0x1) == 0)
2842
          {
2843
            wdptr = (address >> 2) & 0x1;
2844
            wrsize = (address & 0x7) | 0x4;
2845
          }
2846
          else
2847
          {
2848
            /* Not supported by protocol. */
2849
            wdptr = 0xff;
2850
            wrsize = 0xff;
2851
          }
2852
          break;
2853
        case 3:
2854
          /* Writing 3 bytes. */
2855
          /* Address 0 and 5 are valid. */
2856
          if(((address & 0x7) == 0) ||
2857
             ((address & 0x7) == 5))
2858
          {
2859
            wdptr = (address >> 2) & 0x1;
2860
            wrsize = 0x5ul;
2861
          }
2862
          else
2863
          {
2864
            /* Not supported by protocol. */
2865
            wdptr = 0xff;
2866
            wrsize = 0xff;
2867
          }
2868
          break;
2869
        case 4:
2870
          /* Writing 4 bytes. */
2871
          /* Address 0 and 4 are valid. */
2872
          if(((address & 0x7) == 0) ||
2873
             ((address & 0x7) == 4))
2874
          {
2875
            wdptr = (address >> 2) & 0x1;
2876
            wrsize = 0x8ul;
2877
          }
2878
          else
2879
          {
2880
            /* Not supported by protocol. */
2881
            wdptr = 0xff;
2882
            wrsize = 0xff;
2883
          }
2884
          break;
2885
        case 5:
2886
          /* Writing 5 bytes. */
2887
          /* Address 0 and 3 are valid. */
2888
          if(((address & 0x7) == 0) ||
2889
             ((address & 0x7) == 3))
2890
          {
2891
            wdptr = (address >> 1) & 0x1;
2892
            wrsize = 0x7ul;
2893
          }
2894
          else
2895
          {
2896
            /* Not supported by protocol. */
2897
            wdptr = 0xff;
2898
            wrsize = 0xff;
2899
          }
2900
          break;
2901
        case 6:
2902
          /* Writing 6 bytes. */
2903
          /* Addresses 0 and 2 are valid. */
2904
          if(((address & 0x7) == 0) ||
2905
             ((address & 0x7) == 2))
2906
          {
2907
            wdptr = (address >> 1) & 0x1;
2908
            wrsize = 0x9ul;
2909
          }
2910
          else
2911
          {
2912
            /* Not supported by protocol. */
2913
            wdptr = 0xff;
2914
            wrsize = 0xff;
2915
          }
2916
          break;
2917
        default:
2918
          /* Writing 7 bytes. */
2919
          /* Addresses 0 and 1 are valid. */
2920
          if(((address & 0x7) == 0) ||
2921
             ((address & 0x7) == 1))
2922
          {
2923
            wdptr = address & 0x1;
2924
            wrsize = 0xaul;
2925
          }
2926
          else
2927
          {
2928
            /* Not supported by protocol. */
2929
            wdptr = 0xff;
2930
            wrsize = 0xff;
2931
          }
2932
          break;
2933
      }
2934
      break;
2935
    case 1:
2936
      /* Writing 8 bytes. */
2937
      /* Only even double-word address are valid. */
2938
      if((address % 8) == 0)
2939
      {
2940
        wdptr = 0;
2941
        wrsize = 0xbul;
2942
      }
2943
      else
2944
      {
2945
        /* Not supported by protocol. */
2946
        wdptr = 0xff;
2947
        wrsize = 0xff;
2948
      }
2949
      break;
2950
    case 2:
2951
      /* Writing 16 bytes max. */
2952
      /* Only even double-word address are valid. */
2953
      if((address % 8) == 0)
2954
      {
2955
        wdptr = 1;
2956
        wrsize = 0xbul;
2957
      }
2958
      else
2959
      {
2960
        /* Not supported by protocol. */
2961
        wdptr = 0xff;
2962
        wrsize = 0xff;
2963
      }
2964
      break;
2965
    case 3:
2966
    case 4:
2967
      /* Writing 32 bytes max. */
2968
      /* Only even double-word address are valid. */
2969
      if((address & 0x7) == 0)
2970
      {
2971
        wdptr = 0;
2972
        wrsize = 0xcul;
2973
      }
2974
      else
2975
      {
2976
        /* Not supported by protocol. */
2977
        wdptr = 0xff;
2978
        wrsize = 0xff;
2979
      }
2980
      break;
2981
    case 5:
2982
    case 6:
2983
    case 7:
2984
    case 8:
2985
      /* Writing 64 bytes max. */
2986
      /* Only even double-word address are valid. */
2987
      if((address & 0x7) == 0)
2988
      {
2989
        wdptr = 1;
2990
        wrsize = 0xcul;
2991
      }
2992
      else
2993
      {
2994
        /* Not supported by protocol. */
2995
        wdptr = 0xff;
2996
        wrsize = 0xff;
2997
      }
2998
      break;
2999
    case 9:
3000
    case 10:
3001
    case 11:
3002
    case 12:
3003
    case 13:
3004
    case 14:
3005
    case 15:
3006
    case 16:
3007
      /* Writing 128 bytes max. */
3008
      /* Only even double-word address are valid. */
3009
      if((address & 0x7) == 0)
3010
      {
3011
        wdptr = 1;
3012
        wrsize = 0xdul;
3013
      }
3014
      else
3015
      {
3016
        /* Not supported by protocol. */
3017
        wdptr = 0xff;
3018
        wrsize = 0xff;
3019
      }
3020
      break;
3021
    case 17:
3022
    case 18:
3023
    case 19:
3024
    case 20:
3025
    case 21:
3026
    case 22:
3027
    case 23:
3028
    case 24:
3029
    case 25:
3030
    case 26:
3031
    case 27:
3032
    case 28:
3033
    case 29:
3034
    case 30:
3035
    case 31:
3036
    case 32:
3037
      /* Writing 256 bytes max. */
3038
      /* Only even double-word address are valid. */
3039
      if((address & 0x7) == 0)
3040
      {
3041
        wdptr = 1;
3042
        wrsize = 0xful;
3043
      }
3044
      else
3045
      {
3046
        /* Not supported by protocol. */
3047
        wdptr = 0xff;
3048
        wrsize = 0xff;
3049
      }
3050
      break;
3051
    default:
3052
      /* Not supported by protocol. */
3053
      wdptr = 0xff;
3054
      wrsize = 0xff;
3055
      break;
3056
  }
3057
 
3058
  return ((((uint16_t) wrsize) << 8) | ((uint16_t) wdptr));
3059
}
3060
 
3061
 
3062
void wrsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size)
3063
{
3064
  switch(wrsize)
3065
  {
3066
    case 0:
3067
    case 1:
3068
    case 2:
3069
    case 3:
3070
      *offset = wdptr << 2;
3071
      *offset |= wrsize;
3072
      *size = 1;
3073
      break;
3074
    case 4:
3075
    case 6:
3076
      *offset = wdptr << 2;
3077
      *offset |= wrsize & 0x02;
3078
      *size = 2;
3079
      break;
3080
    case 5:
3081
      *offset = wdptr * 5;
3082
      *size = 3;
3083
      break;
3084
    case 8:
3085
      *offset = wdptr * 4;
3086
      *size = 4;
3087
      break;
3088
    case 7:
3089
      *offset = wdptr * 3;
3090
      *size = 5;
3091
      break;
3092
    case 9:
3093
      *offset = wdptr * 2;
3094
      *size = 6;
3095
      break;
3096
    case 10:
3097
      *offset = wdptr * 1;
3098
      *size = 7;
3099
      break;
3100
    case 11:
3101
      *offset = 0;
3102
      *size = 8 + 8*wdptr;
3103
      break;
3104
    case 12:
3105
      *offset = 0;
3106
      *size = 32 + 32*wdptr;
3107
      break;
3108
    case 13:
3109
      *offset = 0;
3110
      *size = 128*wdptr;
3111
      break;
3112
    case 14:
3113
      *offset = 0;
3114
      *size = 0;
3115
      break;
3116
    case 15:
3117
      *offset = 0;
3118
      *size = 256*wdptr;
3119
      break;
3120
  }
3121
}
3122
 
3123
/*************************** end of file **************************************/

powered by: WebSVN 2.1.0

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