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

Subversion Repositories rio

[/] [rio/] [trunk/] [sw/] [stack/] [riostack.c] - Rev 42

Go to most recent revision | Compare with Previous | Blame | View Log

/*******************************************************************************
 * 
 * RapidIO IP Library Core
 * 
 * This file is part of the RapidIO IP library project
 * http://www.opencores.org/cores/rio/
 * 
 * Description:
 * This file contains a software implementation of a RapidIO stack according to 
 * the 2.2 version, part 6, of the standard. Only short control symbols are 
 * supported.
 *
 * Symbols are in four flavors, idle, control, data and error. They are abstract 
 * and should be serialized by any implementation to be sent on a transmission 
 * channel. Error symbols are never generated by the stack and are used if the 
 * symbol decoder encounters an error that the stack should be notified of.
 * 
 * Symbols are inserted into the stack by calling RIO_portAddSymbol() and symbols to
 * transmit are fetched from the stack using RIO_portGetSymbol(). These two
 * functions are the low-level interface towards a physical transmission channel.
 * The function RIO_portSetStatus() is used to indicate to the stack that initial
 * training of the symbol codec has been completed and that the transmission port
 * is ready to accept other symbols than idle. The procedure is to set the port
 * status to initialized once idle symbols are successfully received.
 *
 * On the high-level interface are rio_sendXXX() functions used to create and 
 * insert packets into the outbound transmission queue. The RIO_eventPoll()
 * function is used to check if any packet is available for reading in the 
 * inbound reception queue. These packets are then accessed using 
 * rio_receiveXXX() functions.
 * 
 * -----------------
 * |  OS dependent |
 * |  (your code)  |
 * -----------------
 *        |
 * -----------------
 * |   RioStack    |
 * -----------------
 *        |
 * -----------------
 * | Symbol Codec  |
 * |  (your code)  |
 * -----------------
 *        |
 * -----------------
 * |  Port driver  |
 * -----------------
 *        |
 * -----------------
 * | Physical port |
 * -----------------
 *
 * The symbol codec maps a RapidIO symbol to the physical transmission media.
 * 
 * Some typical patterns to handle this stack are:
 * Initialization:
 *   RIO_open(...);
 *   RIO_portSetTimeout(...);
 *   ...
 *   <Symbol transcoder is successfully decoding symbols from the link>
 *   RIO_portSetStatus(1);
 *
 * Bottom-half traffic handling:
 *   RIO_portSetTime(...);
 *   <get symbol from decoder>
 *   RIO_portAddSymbol(...);
 *   s = RIO_portGetSymbol(...);
 *   <send symbol to encoder>
 *
 * Receiving packets:
 *   switch(RIO_eventPoll(...))
 *   {
 *     case RIO_EVENT_DOORBELL:
 *       RIO_receiveDoorbell(...);
 *       ...
 *   }
 *   RIO_packetRemove();
 *
 * Transmitting packets:
 *   if(RIO_sendAvailable(...))
 *   {
 *     RIO_sendDoorbell(...);
 *   }
 *   ...
 *
 * More details about the usage can be found in the module tests in the end of 
 * this file.
 * 
 * To Do:
 * -
 * 
 * Author(s): 
 * - Magnus Rosenius, magro732@opencores.org 
 * 
 *******************************************************************************
 * 
 * Copyright (C) 2013 Authors and OPENCORES.ORG 
 * 
 * This source file may be used and distributed without 
 * restriction provided that this copyright statement is not 
 * removed from the file and that any derivative work contains 
 * the original copyright notice and the associated disclaimer. 
 * 
 * This source file is free software; you can redistribute it 
 * and/or modify it under the terms of the GNU Lesser General 
 * Public License as published by the Free Software Foundation; 
 * either version 2.1 of the License, or (at your option) any 
 * later version. 
 * 
 * This source is distributed in the hope that it will be 
 * useful, but WITHOUT ANY WARRANTY; without even the implied 
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 * PURPOSE. See the GNU Lesser General Public License for more 
 * details. 
 * 
 * You should have received a copy of the GNU Lesser General 
 * Public License along with this source; if not, download it 
 * from http://www.opencores.org/lgpl.shtml 
 * 
 *******************************************************************************/
 
/** 
 * \file riostack.c
 */
 
/*******************************************************************************
 * Includes
 *******************************************************************************/
 
#include "riostack.h"
 
 
/*lint -e961 Allow function like macros. */
/*lint -e621 Long identifier names allowed to increase readability. */
/*lint -w2 */
 
 
/* lint --estring(960,17.4) It is not possible to implement a rio stack without some
 * pointer arithmetic */
 
/*******************************************************************************
 * Local macro definitions
 *******************************************************************************/
 
/* Macro to update 5-bit ackId counters. */
#define ACKID_INC(ackId) (((ackId)+1)&0x1f)
 
/* Macros to get entries from a control symbol. */
#define STYPE0_GET(data) ((uint8_t) (((data) >> 21) & 0x00000007u))
#define PARAMETER0_GET(data) ((uint8_t) (((data) >> 16) & 0x00000001fu))
#define PARAMETER1_GET(data) ((uint8_t) (((data) >> 11) & 0x00000001fu))
#define STYPE1_GET(data) ((uint8_t) (((data) >> 8) & 0x00000007u))
#define CMD_GET(data) ((uint8_t) (((data) >> 5) & 0x00000007u))
#define CRC5_GET(data) ((uint8_t) (((data) >> 0) & 0x0000001fu))
 
/* Macros to get entries from a packet in a buffer. */
#define FTYPE_GET(p) (((p)[0] >> 16) & 0xf)
#define DESTID_GET(p) ((p)[0] & 0xffff)
#define SRCID_GET(p) (((p)[1] >> 16) & 0xffff)
#define TRANSACTION_GET(p) (((p)[1] >> 12) & 0xf)
#define MSGLEN_GET(p) TRANSACTION_GET(p)
#define SSIZE_GET(p) (((p)[1] >> 8) & 0xf)
#define LETTER_GET(p) (((p)[1] >> 6) & 0x3)
#define MBOX_GET(p) (((p)[1] >> 4) & 0x3)
#define MSGSEG_GET(p) ((p)[1] & 0xf)
#define XMBOX_GET(p) MSGSEG_GET(p)
#define RDSIZE_GET(p) SSIZE_GET(p)
#define WRSIZE_GET(p) SSIZE_GET(p)
#define TID_GET(p) ((p)[1] & 0xff)
#define HOP_GET(p) (((p)[2] >> 24) & 0xff)
#define CONFIG_OFFSET_GET(p) ((p)[2] & 0x00fffffcul)
#define INFO_GET(p) (((p)[2] >> 16) & 0xffff)
#define ADDRESS_GET(p) ((p)[2] & 0xfffffff8ul)
#define WDPTR_GET(p) (((p)[2] >> 2) & 0x1)
#define XAMBS_GET(p) ((p)[2] & 0x3)
#define DOUBLE_WORD_MSB_GET(p, i) (p)[3+(2*i+0)]
#define DOUBLE_WORD_LSB_GET(p, i) (p)[3+(2*i+1)]
 
/* Transmitter frame states. */
#define TX_FRAME_START                  ((uint8_t)0u)
#define TX_FRAME_BODY                   ((uint8_t)1u)
 
/* Control symbol constants. */
#define STYPE0_PACKET_ACCEPTED          ((uint8_t)0x00u)
#define STYPE0_PACKET_RETRY             ((uint8_t)0x01u)
#define STYPE0_PACKET_NOT_ACCEPTED      ((uint8_t)0x02u)
#define STYPE0_RESERVED                 ((uint8_t)0x03u)
#define STYPE0_STATUS                   ((uint8_t)0x04u)
#define STYPE0_VC_STATUS                ((uint8_t)0x05u)
#define STYPE0_LINK_RESPONSE            ((uint8_t)0x06u)
#define STYPE0_IMPLEMENTATION_DEFINED   ((uint8_t)0x07u)
#define STYPE1_START_OF_PACKET          ((uint8_t)0x00u)
#define STYPE1_STOMP                    ((uint8_t)0x01u)
#define STYPE1_END_OF_PACKET            ((uint8_t)0x02u)
#define STYPE1_RESTART_FROM_RETRY       ((uint8_t)0x03u)
#define STYPE1_LINK_REQUEST             ((uint8_t)0x04u)
#define STYPE1_MULTICAST_EVENT          ((uint8_t)0x05u)
#define STYPE1_RESERVED                 ((uint8_t)0x06u)
#define STYPE1_NOP                      ((uint8_t)0x07u)
 
/* Packet ftype constants. */
#define FTYPE_REQUEST 0x2
#define FTYPE_WRITE 0x5
#define FTYPE_MAINTENANCE 0x8
#define FTYPE_DOORBELL 0xa
#define FTYPE_MESSAGE 0xb
#define FTYPE_RESPONSE 0xd
 
/* Transaction constants. */
#define TRANSACTION_MAINT_READ_REQUEST 0
#define TRANSACTION_MAINT_WRITE_REQUEST 1
#define TRANSACTION_MAINT_READ_RESPONSE 2
#define TRANSACTION_MAINT_WRITE_RESPONSE 3
#define TRANSACTION_WRITE_NWRITE 4
#define TRANSACTION_WRITE_NWRITER 5
#define TRANSACTION_REQUEST_NREAD 4
#define TRANSACTION_RESPONSE_NO_PAYLOAD 0
#define TRANSACTION_RESPONSE_MESSAGE_RESPONSE 1
#define TRANSACTION_RESPONSE_WITH_PAYLOAD 8
 
/* Maintenance transaction lengths. */
#define MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE ((uint32_t) 4ul)
#define MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE ((uint32_t) 6ul)
#define MAINTENANCE_TRANSACTION_READ_RESPONSE_SIZE ((uint32_t) 6ul)
#define MAINTENANCE_TRANSACTION_WRITE_RESPONSE_SIZE ((uint32_t) 4ul)
 
/* Constants used to forward different errors to the link partner. */
#define PACKET_NOT_ACCEPTED_CAUSE_RESERVED 0u
#define PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID 1u
#define PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC 2u
#define PACKET_NOT_ACCEPTED_CAUSE_NON_MAINTENANCE 3u
#define PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC 4u
#define PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER 5u
#define PACKET_NOT_ACCEPTED_CAUSE_NO_RESOURCE 6u
#define PACKET_NOT_ACCEPTED_CAUSE_DESCRAMBLER 7u
#define PACKET_NOT_ACCEPTED_CAUSE_GENERAL 31u
 
/* Constants used to request link-responses. */
#define LINK_REQUEST_RESET_DEVICE 3u
#define LINK_REQUEST_INPUT_STATUS 4u
 
/* Constants used to forward a port status in a link-resonse. */
#define LINK_RESPONSE_PORT_STATUS_ERROR 2u
#define LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED 4u
#define LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED 5u
#define LINK_RESPONSE_PORT_STATUS_OK 16u
 
/*******************************************************************************
 * Local typedefs
 *******************************************************************************/
 
/*******************************************************************************
 * Global declarations
 *******************************************************************************/
 
/*******************************************************************************
 * Local declarations
 *******************************************************************************/
 
/*******************************************************************************
 * Local function prototypes
 *******************************************************************************/
 
/* Helper functions for protocol events. */
static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus);
static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus);
static void handlePacketRetry(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus);
static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause);
static void handleLinkResponse(RioStack_t *stack, const uint8_t ackId, const uint8_t portStatus);
static void handleStartOfPacket(RioStack_t *stack);
static void handleEndOfPacket(RioStack_t *stack);
static void handleLinkRequest(RioStack_t *stack, uint8_t cmd);
static void handleNewPacketStart(RioStack_t *stack);
static void handleNewPacketEnd(RioStack_t *stack);
 
/* I/O logical layer maintenance packet functions. */
static void sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                        const uint8_t hopCount, const uint32_t offset);
static void receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                           uint8_t *hopCount, uint32_t *offset);
static void sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                         const uint8_t hopCount, const uint32_t data);
static void receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                            uint8_t *hopCount, uint32_t *data);
static void sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                         const uint8_t hopCount, const uint32_t offset, const uint32_t data );
static void receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                            uint8_t *hopCount, uint32_t *offset, uint32_t *data );
static void sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                          const uint8_t hopCount);
static void receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                             uint8_t *hopCount);
 
/* I/O logical layer packet functions. */
static void sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                        const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer, 
                        const uint8_t ack);
static uint16_t receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
                               uint32_t *address, const uint16_t dataLength, uint8_t *data );
static void sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                       const uint32_t address, const uint16_t dataLength);
static void receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                          uint32_t *address, uint16_t *dataLength);
static void sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                     const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer);
static uint16_t receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,  
                                            const uint32_t address, const uint16_t dataLength, uint8_t *data );
static void sendResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                          const uint8_t status);
static void receiveResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid);
 
/* Message passing logical layer packet functions. */
static void sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                          const uint16_t info );
static void receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                             uint16_t *info);
static void sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, 
                         const uint16_t bufferSize, const uint8_t* bufferData);
static uint16_t receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox, 
                                const uint16_t dataLength, uint8_t *data );
static void sendMessageResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, 
                                 const uint8_t status);
static void receiveMessageResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox);
 
/* Functions to help transfer data bytes to and from a packet payload. */
static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset, 
                                 const uint16_t dataSize, uint8_t *data);
static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset, 
                                 const uint16_t dataSize, const uint8_t *data);
 
/* Functions to help in conversions between rdsize/wrsize and size/offset. */
static uint16_t rdsizeGet(const uint32_t address, const uint16_t size);
static uint16_t wrsizeGet(const uint32_t address, const uint16_t size);
static void rdsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size);
static void wrsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size);
 
/**
 * \brief Create a control symbol.
 *
 * \param[in] stype0 The stype0 value.
 * \param[in] parameter0 The parameter0 value.
 * \param[in] parameter1 The parameter1 value.
 * \param[in] stype1 The stype1 value.
 * \param[in] cmd The cmd value.
 * \param[out] None
 * \return The control symbol that were created from the input parameters.
 *
 * This function creates a control symbol with the specified arguments and
 * calculates a CRC-5 checksum according to the standard specification.
 */
static RioSymbol CreateControlSymbol( const uint8_t stype0,
                                      const uint8_t parameter0, const uint8_t parameter1,
                                      const uint8_t stype1, const uint8_t cmd);
 
/**
 * \brief Function to calculate ITU-CRC5, polynom=0x15.
 *
 * \param[in] data The data of a control symbol.
 * \param[in] crc The crc to initiate the result with.
 * \return A new CRC-5 value.
 */
static uint8_t Crc5( const uint32_t data, const uint8_t crc);
 
/**
 * \brief Function to calculate CITT-CRC16, polynom=0x1021.
 *
 * \param[in] data The data to calculate CRC-16 on.
 * \param[in] crc The crc to initiate the result with.
 * \param[out] None
 * \return A new CRC-16 value.
 *
 * This function calculates and returns a new CRC-16 value based on
 * new data and a previous CRC-16 value.
 */
static uint16_t Crc16( const uint16_t data, const uint16_t crc);
 
/**
 * \brief Function to calculate CITT-CRC16, polynom=0x1021.
 *
 * \param[in] data The data to calculate CRC-16 on.
 * \param[in] crc The crc to initiate the result with.
 * \param[out] None
 * \return A new CRC-16 value.
 *
 * This function calculates and returns a new CRC-16 value based on
 * new data and a previous CRC-16 value.
 */
static uint16_t Crc32( const uint32_t data, uint16_t crc);
 
/**
 * \brief Create a queue with a specified size and a buffer attached to it.
 *
 * \param[in] The number of entries in the queue.
 * \param[in] A pointer to the buffer to store the content in.
 * \return A queue with the specified size and where new data will be stored 
 * to the specified buffer.
 */
static Queue_t QueueCreate( const uint8_t size, uint32_t *buffer);
 
/**
 * \brief Get number of available elements.
 *
 * \param[in] q The queue to operate on.
 * \return The number of free packet buffers in the queue.
 */
static uint8_t QueueAvailable( const Queue_t q );
 
/**
 * \brief Get if the queue is empty or not.
 *
 * \param[in] q The queue to operate on.
 * \return Non-zero if the queue is empty.
 */
static bool_t QueueEmpty( const Queue_t q);
 
/**
 * \brief Get the length of a queue.
 *
 * \param[in] q The queue to operate on.
 * \return The number of elements in the queue.
 */
static uint8_t QueueLength( const Queue_t q);
 
/**
 * \brief Add a new element to the queue.
 *
 * \param[in] q The queue to operate on.
 * \return A queue with one added element.
 */
static Queue_t QueueEnqueue( Queue_t q);
 
/**
 * \brief Remove an element from the queue.
 *
 * \param[in] q The queue to operate on.
 * \return A queue with on removed element.
 */
static Queue_t QueueDequeue( Queue_t q);
 
/**
 * \brief Check if the readout window is empty.
 *
 * \param[in] q The queue to operate on.
 * \return If the readout window is empty.
 */
static bool_t QueueWindowEmpty( const Queue_t q);
 
/**
 * \brief Reset the window to none.
 *
 * \param[in] q The queue to operate on.
 * \return The updated Queue_t structure.
 */
static Queue_t QueueWindowReset(Queue_t q);
 
/**
 * \brief Increase the window to the next pending element.
 *
 * \param[in] q The queue to operate on.
 * \return The updated Queue_t structure.
 */
static Queue_t QueueWindowNext(Queue_t q);
 
/**
 * \brief Set actual size of the newest element.
 *
 * \param[in] q The queue to operate on.
 * \param[in] size The size to set the newest content size to.
 */
static void QueueSetSize( Queue_t q, const uint32_t size);
 
/**
 * \brief Set content at a specified index in the newest element.
 *
 * \param[in] q The queue to operate on.
 * \param[in] index posititon into the element
 * \param[in] content The content to set at the specified index in the newest queue element.
 */
static void QueueSetContent( Queue_t q, const uint32_t index, const uint32_t content);
 
/**
 * \brief Get the size of the newest element.
 *
 * \param[in] q The queue to operate on.
 * \return The size of the currently pending element.
 */
static uint32_t QueueGetBackSize( Queue_t q);
 
/**
 * \brief Get a pointer to the buffer of the newest element.
 *
 * \param[in] q The queue to operate on.
 * \return A pointer to the content.
 */
static uint32_t *QueueGetBackBuffer( Queue_t q );
 
/**
 * \brief Get the size of the oldest element.
 * \param[in] q The queue to operate on.
 * \return The size of the element.
 */
static uint32_t QueueGetFrontSize( Queue_t q );
 
/**
 * \brief Get the content of the oldest element at specified index.
 * \param[in] q The queue to operate on.
 * \param[in] index The index into the element to get the content from.
 * \return content of element at index position.
 */
static uint32_t QueueGetFrontContent( Queue_t q, const uint32_t index);
 
/**
 * \brief Get a pointer to the buffer of the oldest element.
 *
 * \param[in] q The queue to operate on.
 * \return A pointer to the content.
 */
static uint32_t *QueueGetFrontBuffer( Queue_t q );
 
 
 
/*******************************************************************************
 * Global functions
 *******************************************************************************/
 
 
void RIO_open( RioStack_t *stack, const RioStackObserver_t *observer, const void *private,
               const uint32_t rxPacketBufferSize, uint32_t *rxPacketBuffer, 
               const uint32_t txPacketBufferSize, uint32_t *txPacketBuffer, 
               const uint16_t configDeviceVendorId, const uint16_t configDeviceId, const uint32_t configDeviceRevisionId,
               const uint16_t configAssyVendorId, const uint16_t configAssyId, const uint16_t configAssyRevisionId,
               const uint16_t configBaseDeviceId )
{
  /* Port time and timeout limit. */
  stack->portTime = 0u;
  stack->portTimeout = 1000u;
 
  /* Setup the receiver. */
  stack->rxState = RX_STATE_UNINITIALIZED;
  stack->rxCounter = 0u;
  stack->rxCrc = 0xffffu;
  stack->rxStatusReceived = 0u;
  stack->rxAckId = 0u;
  stack->rxAckIdAcked = 0u;
  stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED;
  stack->rxQueue = QueueCreate((uint8_t) (rxPacketBufferSize/RIO_BUFFER_SIZE), rxPacketBuffer);
 
  /* Setup the transmitter. */
  stack->txState = TX_STATE_UNINITIALIZED;
  stack->txCounter = 0u;
  stack->txStatusCounter = 0u;
  stack->txFrameState = TX_FRAME_START;
  stack->txAckId = 0u;
  stack->txAckIdWindow = 0u;
  stack->txQueue = QueueCreate((uint8_t) (txPacketBufferSize/RIO_BUFFER_SIZE), txPacketBuffer);
 
  /* Set our own device address to use in the packets. */
  stack->deviceIdentity = configDeviceId;
  stack->deviceVendorIdentity = configDeviceVendorId;
  stack->deviceRev = configDeviceRevisionId;
  stack->assyIdentity = configAssyId;
  stack->assyVendorIdentity = configAssyVendorId;
  stack->assyRev = configAssyRevisionId;
  stack->baseDeviceId = configBaseDeviceId;
 
  /* Initialize the host base lock CSR. */
  stack->hostBaseDeviceIdLock = 0xfffffffful;
  stack->componentTag = 0ul;
 
  /* Bits that are updated by the configuration procedure. */
  stack->host = 0u;
  stack->masterEnable = 0u;
  stack->discovered = 0u;
 
  /* Setup status counters for inbound direction. */
  stack->statusInboundPacketComplete = 0ul;
  stack->statusInboundPacketRetry = 0ul;
  stack->statusInboundErrorControlCrc = 0ul;
  stack->statusInboundErrorPacketAckId = 0ul;
  stack->statusInboundErrorPacketCrc = 0ul;
  stack->statusInboundErrorIllegalCharacter = 0ul;
  stack->statusInboundErrorGeneral = 0ul;
  stack->statusInboundErrorPacketUnsupported = 0ul;
 
  /* Setup status counters for outbound direction. */
  stack->statusOutboundPacketComplete = 0ul;
  stack->statusOutboundPacketRetry = 0ul;
  stack->statusOutboundErrorTimeout = 0ul;
  stack->statusOutboundErrorPacketAccepted = 0ul;
  stack->statusOutboundErrorPacketRetry = 0ul;
 
  /* Setup status counters for potential problems on the link-partner. */
  stack->statusPartnerLinkRequest = 0ul;
  stack->statusPartnerErrorControlCrc = 0ul;
  stack->statusPartnerErrorPacketAckId = 0ul;
  stack->statusPartnerErrorPacketCrc = 0ul;
  stack->statusPartnerErrorIllegalCharacter = 0ul;
  stack->statusPartnerErrorGeneral = 0ul;
 
  /* Set callback structure. */
  stack->observer = observer;
 
  /* Set pointer to user private data. */
  stack->private = private;
}
 
 
/*******************************************************************************************
 * Stack status functions.
 * Note that status counters are access directly in the stack-structure.
 *******************************************************************************************/
 
RioStatusType RIO_getStatus( RioStack_t *stack )
{
  RioStatusType status;
 
 
  /* Check if both receiver and transmitter is up and running. */
  if((stack->rxState == RX_STATE_LINK_INITIALIZED) && 
     (stack->txState == TX_STATE_LINK_INITIALIZED))
  {
    /* Both receiver and transmitter is up. */
 
    /* Check if it is allowed to act as a master on the bus. */
    if(stack->masterEnable)
    {
      /* Allowed to act as master. */
      status = RIO_STATUS_OPERATIONAL;
    }
    else
    {
      /* Not allowed to act as master. */
      /* The enumeration process has not been completed yet. */
      status = RIO_STATUS_ENUMERATION;
    }
  }
  else
  {
    /* The link is not up yet. */
    status = RIO_STATUS_UNINITIALIZED;
  }
 
  return status;
}
 
 
uint8_t RIO_outboundQueueLength( RioStack_t *stack )
{
  return QueueLength(stack->txQueue);
}
 
 
uint8_t RIO_inboundQueueLength( RioStack_t *stack )
{
  return QueueLength(stack->rxQueue);
}
 
 
/*******************************************************************************************
 * Packet reception functions.
 *******************************************************************************************/
 
RioEventType RIO_eventPoll( RioStack_t *stack )
{
  RioEventType event;
  uint32_t *packet;
  uint32_t ftype;
  uint32_t transaction;
 
 
  /* Check if there are any new packets in the inbound queue. */
  if(!QueueEmpty(stack->rxQueue))
  {
    /* There are new pending packets. */
 
    /* Get the packet and its ftype. */
    packet = QueueGetFrontBuffer(stack->rxQueue);
    ftype = FTYPE_GET(packet);
    transaction = TRANSACTION_GET(packet);
 
    /* Check the type of packets, i.e. read the ftype. */
    switch(ftype)
    {
      case FTYPE_REQUEST:
        /* Request class. */
 
        /* Check transaction type. */
        switch(transaction)
        {
          case TRANSACTION_REQUEST_NREAD:
            /* Supported NREAD request. */
            event = RIO_EVENT_NREAD;
            break;
 
          default:
            /* Unsupported request transaction. */
            /* REMARK: Throw these away for now. */
            stack->statusInboundErrorPacketUnsupported++;
            stack->rxQueue = QueueDequeue(stack->rxQueue);
            event = RIO_EVENT_NONE;
            break;
        }
        break;
 
      case FTYPE_WRITE:
        /* Write class. */
 
        /* Check transaction type. */
        switch(transaction)
        {
          case TRANSACTION_WRITE_NWRITE:
            /* NWRITE transaction. */
            if(QueueGetFrontSize(stack->rxQueue) >= 6ul)
            {
              /* Supported NWRITE request. */
              event = RIO_EVENT_NWRITE;
            }
            else
            {
              /* Unsupported size. */
              /* REMARK: Throw these away for now. */
              stack->statusInboundErrorPacketUnsupported++;
              stack->rxQueue = QueueDequeue(stack->rxQueue);
              event = RIO_EVENT_NONE;
            }
            break;
 
          case TRANSACTION_WRITE_NWRITER:
            /* NWRITE_R transaction. */
            if(QueueGetFrontSize(stack->rxQueue) >= 6ul)
            {
              /* Supported NWRITE_R request. */
              event = RIO_EVENT_NWRITE_R;
            }
            else
            {
              /* Unsupported size. */
              /* REMARK: Throw these away for now. */
              stack->statusInboundErrorPacketUnsupported++;
              stack->rxQueue = QueueDequeue(stack->rxQueue);
              event = RIO_EVENT_NONE;
            }
            break;
 
          default:
            /* Unsupported write transaction. */
            /* REMARK: Throw these away for now. */
            stack->statusInboundErrorPacketUnsupported++;
            stack->rxQueue = QueueDequeue(stack->rxQueue);
            event = RIO_EVENT_NONE;
            break;
        }
        break;
 
      case FTYPE_MAINTENANCE:
        /* Maintenance class. */
 
        /* Check transaction type. */
        /* Normally, only responses could be received here unless the stack is compiled as transparent. 
           Maintenance requests are answered by the portAddSymbol() function. */
        switch(transaction)
        {
          case TRANSACTION_MAINT_READ_REQUEST:
            /* Maintenance read request transaction. */
            if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE)
            {
              /* Supported maintenance read response. */
              event = RIO_EVENT_MAINT_READ_REQUEST;
            }
            else
            {
              /* Unsupported maintenance read request. */
              /* REMARK: Throw these away for now. */
              stack->statusInboundErrorPacketUnsupported++;
              stack->rxQueue = QueueDequeue(stack->rxQueue);
              event = RIO_EVENT_NONE;
            }
            break;
 
          case TRANSACTION_MAINT_WRITE_REQUEST:
            /* Maintenance write request transaction. */
            if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE)
            {
              /* Supported maintenance write request. */
              event = RIO_EVENT_MAINT_WRITE_REQUEST;
            }
            else
            {
              /* Unsupported maintenance write response. */
              /* REMARK: Throw these away for now. */
              stack->statusInboundErrorPacketUnsupported++;
              stack->rxQueue = QueueDequeue(stack->rxQueue);
              event = RIO_EVENT_NONE;
            }
            break;
 
          case TRANSACTION_MAINT_READ_RESPONSE:
            /* Maintenance read response transaction. */
            if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_RESPONSE_SIZE)
            {
              /* Supported maintenance read response. */
              event = RIO_EVENT_MAINT_READ_RESPONSE;
            }
            else
            {
              /* Unsupported maintenance read response. */
              /* REMARK: Throw these away for now. */
              stack->statusInboundErrorPacketUnsupported++;
              stack->rxQueue = QueueDequeue(stack->rxQueue);
              event = RIO_EVENT_NONE;
            }
            break;
 
          case TRANSACTION_MAINT_WRITE_RESPONSE:
            /* Maintenance write response transaction. */
            if(QueueGetFrontSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_RESPONSE_SIZE)
            {
              /* Supported maintenance write response. */
              event = RIO_EVENT_MAINT_WRITE_RESPONSE;
            }
            else
            {
              /* Unsupported maintenance write response. */
              /* REMARK: Throw these away for now. */
              stack->statusInboundErrorPacketUnsupported++;
              stack->rxQueue = QueueDequeue(stack->rxQueue);
              event = RIO_EVENT_NONE;
            }
            break;
 
          default:
            /* Unsupported maintenance transaction. */
            /* REMARK: Throw these away for now. */
            stack->statusInboundErrorPacketUnsupported++;
            stack->rxQueue = QueueDequeue(stack->rxQueue);
            event = RIO_EVENT_NONE;
            break;
        }
        break;
 
      case FTYPE_DOORBELL:
        /* Doorbell class. */
 
        /* Check size of message. */
        if(QueueGetFrontSize(stack->rxQueue) == 3ul)
        {
          /* Supported doorbell. */
          event = RIO_EVENT_DOORBELL;
        }
        else
        {
          /* Unsupported doorbell request. */
          /* REMARK: Throw these away for now. */
          stack->statusInboundErrorPacketUnsupported++;
          stack->rxQueue = QueueDequeue(stack->rxQueue);
          event = RIO_EVENT_NONE;
        }
        break;        
 
      case FTYPE_MESSAGE:
        /* Message class. */
 
        /* Check msglen to see if this packet continues. */
        if(MSGLEN_GET(packet) == 0ul)
        {
          /* Single-packet message. */
          event = RIO_EVENT_MESSAGE;
        }
        else
        {
          /* Unsupported message type. */
          /* REMARK: Throw these away for now. */
          stack->statusInboundErrorPacketUnsupported++;
          stack->rxQueue = QueueDequeue(stack->rxQueue);
          event = RIO_EVENT_NONE;
        }
        break;        
 
      case FTYPE_RESPONSE:
        /* Response class. */
 
        /* Check transaction field. */
        switch(transaction)
        {
          case TRANSACTION_RESPONSE_NO_PAYLOAD:
            /* Response transaction without payload. */
 
            /* Check status field. */
            switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul)
            {
              case 0x00000000:
                event = RIO_EVENT_RESPONSE_DONE;
                break;
              case 0x00000300:
                event = RIO_EVENT_RESPONSE_RETRY;
                break;
              case 0x00000700:
                event = RIO_EVENT_RESPONSE_ERROR;
                break;
              default:
                /* Unsupported response status. */
                /* REMARK: Throw these away for now. */
                stack->statusInboundErrorPacketUnsupported++;
                stack->rxQueue = QueueDequeue(stack->rxQueue);
                event = RIO_EVENT_NONE;
                break;
            }
            break;
 
          case TRANSACTION_RESPONSE_MESSAGE_RESPONSE:
            /* Message response transaction. */
 
            /* Check status field. */
            switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul)
            {
              case 0x00000000:
                event = RIO_EVENT_MESSAGE_RESPONSE_DONE;
                break;
              case 0x00000300:
                event = RIO_EVENT_MESSAGE_RESPONSE_RETRY;
                break;
              case 0x00000700:
                event = RIO_EVENT_MESSAGE_RESPONSE_ERROR;
                break;
              default:
                /* Unsupported message response status. */
                /* REMARK: Throw these away for now. */
                stack->statusInboundErrorPacketUnsupported++;
                stack->rxQueue = QueueDequeue(stack->rxQueue);
                event = RIO_EVENT_NONE;
                break;
            }
            break;
 
          case TRANSACTION_RESPONSE_WITH_PAYLOAD:
            /* Response with payload transaction. */
 
            /* Check status field. */
            switch(QueueGetFrontContent(stack->rxQueue, 1ul) & 0x00000f00ul)
            {
              case 0x00000000:
                event = RIO_EVENT_RESPONSE_DONE_PAYLOAD;
                break;
              case 0x00000300:
                event = RIO_EVENT_RESPONSE_RETRY;
                break;
              case 0x00000700:
                event = RIO_EVENT_RESPONSE_ERROR;
                break;
              default:
                /* Unsupported response with payload status. */
                /* REMARK: Throw these away for now. */
                stack->statusInboundErrorPacketUnsupported++;
                stack->rxQueue = QueueDequeue(stack->rxQueue);
                event = RIO_EVENT_NONE;
                break;
            }
            break;
 
          default:
            /* Unsupported response transaction. */
            /* REMARK: Throw these away for now. */
            stack->statusInboundErrorPacketUnsupported++;
            stack->rxQueue = QueueDequeue(stack->rxQueue);
            event = RIO_EVENT_NONE;
            break;
        }
        break;        
 
      default:
        /* Unsupported class. */
        /* REMARK: Throw these away for now. */
        stack->statusInboundErrorPacketUnsupported++;
        stack->rxQueue = QueueDequeue(stack->rxQueue);
        event = RIO_EVENT_NONE;
        break;
    }
  }
  else
  {
    /* No pending events available. */
    event = RIO_EVENT_NONE;
  }
 
  return event;
}
 
 
void RIO_packetRemove( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  stack->rxQueue = QueueDequeue(stack->rxQueue);
}
 
 
bool_t RIO_sendAvailable( RioStack_t *stack, const uint16_t size )
{
  /* Return if there are buffers available and if the requested size is less
     than or equal to the maximum payload that fits into one packet. */
  return (bool_t) (stack->masterEnable && (size <= 256u) && (QueueAvailable(stack->txQueue) > 0u));
}
 
 
uint32_t RIO_packetGet( RioStack_t *stack, uint32_t length, uint32_t *dest)
{
  uint32_t i;
  uint32_t size;
  uint32_t *src;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Get the size and a pointer to the raw packet. */
  size = QueueGetFrontSize(stack->rxQueue);
  src = QueueGetFrontBuffer(stack->rxQueue);
 
  ASSERT((length >= size), "Too short destination packet.");
 
  /* Copy the packet to the destination packet pointer. */
  for(i = 0; i < size; i++)
  {
    dest[i] = src[i];
  }
 
  /* Remove the packet from the queue. */
  stack->rxQueue = QueueDequeue(stack->rxQueue);
 
  /* Return the size of the copied packet. */
  return size;
}
 
 
void RIO_packetSet( RioStack_t *stack, uint32_t length, uint32_t *src)
{
  uint32_t i;
  uint32_t *dest;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0), "Writing to full transmission queue.");
  ASSERT((length < RIO_PACKET_SIZE), "Writing a too large packet.");
 
  /* Set the size of the new packet. */
  QueueSetSize(stack->txQueue, length);
 
  /* Get a pointer to the destination packet in the transmission queue. */
  dest = QueueGetBackBuffer(stack->txQueue);
 
  /* Copy the packet into the transmission queue. */
  for(i = 0; i < length; i++)
  {
    dest[i] = src[i];
  }
 
  /* Make sure the ackId field of the copied packet is reset. */
  /* Unless this is done, the ackId field of the transmitted packet may be corrupted. */
  dest[0] &= 0x03ffffff;
 
  /* Enqueue the new packet. */
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
/*******************************************************************************************
 * Configuration-space access methods.
 *******************************************************************************************/
 
uint32_t RIO_readConfig( RioStack_t *stack, const uint32_t offset )
{
  uint32_t data;
 
  /* Check the area of the access. */
  if(offset < 0x10000ul)
  {
    /* Access is in not in implementation-defined space. */
 
    /* Check offset and return. */
    switch(offset)
    {
      case DEVICE_IDENTITY_CAR:
        data = (uint32_t)stack->deviceIdentity << 16;
        data |= stack->deviceVendorIdentity;
        break;
      case DEVICE_INFORMATION_CAR:
        data = stack->deviceRev;
        break;
      case ASSEMBLY_IDENTITY_CAR:
        data = (uint32_t)stack->assyIdentity << 16;
        data |= stack->assyVendorIdentity;
        break;
      case ASSEMBLY_INFORMATION_CAR:
        data = (uint32_t)stack->assyRev << 16;
        data |= EXTENDED_FEATURES_OFFSET;
        break;
      case PROCESSING_ELEMENT_FEATURES_CAR:
        /* Indicate processor with extended features
           and 34-bit address support. */
        /* Supports common transport large systems. */
        data = 0x20000019ul;
        break;
      case SOURCE_OPERATIONS_CAR:
        /* Supporting doorbells and data messages. */
        data = 0x00000c00ul;
        break;
      case DESTINATION_OPERATIONS_CAR:
        /* Supporting doorbells and data messages. */
        data = 0x00000c00ul;
        break;
      case PROCESSING_ELEMENT_LOGICAL_LAYER_CONTROL_CSR:
        /* Supports 34-bit addresses. */
        data = 0x00000001ul;
        break;
      case BASE_DEVICE_ID_CSR:
        data = stack->baseDeviceId;
        break;
      case HOST_BASE_DEVICE_ID_LOCK_CSR:
        data = stack->hostBaseDeviceIdLock & (uint32_t)0x0000fffful;
        break;
      case COMPONENT_TAG_CSR:
        data = stack->componentTag;
        break;
      case LP_SERIAL_REGISTER_BLOCK_HEADER(EXTENDED_FEATURES_OFFSET):
        /* Indicate Generic end point device and no more extended features. */
        data = 0x00000001ul;
        break;
      case PORT_LINK_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
        /* REMARK: Implement this... */
        data = 0x00000000ul;
        break;
      case PORT_RESPONSE_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
        /* REMARK: Implement this... */
        data = 0x00000000ul;
        break;
      case PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
        /* Return the host, master enable bit and the discovered bit. */
        data = ((uint32_t) stack->host) << 31;
        data |= ((uint32_t) stack->masterEnable) << 30;
        data |= ((uint32_t) stack->discovered) << 29;
        break;
      case PORT_N_LOCAL_ACKID_CSR(EXTENDED_FEATURES_OFFSET, 0u):
        data = ((uint32_t) stack->rxAckId) << 24;
        data |= ((uint32_t) stack->txAckId) << 8;
        data |= ((uint32_t) stack->txAckIdWindow);
        break;
      case PORT_N_ERROR_AND_STATUS_CSR(EXTENDED_FEATURES_OFFSET, 0u):
        /* Indicate the port status here. */
        if((stack->txState == TX_STATE_LINK_INITIALIZED) &&
           (stack->rxState == RX_STATE_LINK_INITIALIZED))
        {
          /* Port ok. */
          data = 0x00000002ul;
        }
        else
        {
          /* Port not ok. */
          data = 0x00000001ul;
        }
        break;
      default:
        data = 0x00000000ul;
        break;
    }
  }
  else
  {
    /* Access is in implementation-defined space. */
 
    /* Check if there are any registered callback. */
    if((stack->observer != NULL) &&
       (stack->observer->configRead != NULL))
    {
      /* Call the observer callback to handle the access. */
      data = stack->observer->configRead(stack, offset - 0x00010000ul);
    }
    else
    {
      data = 0x00000000ul;
    }
  }
 
  return data;
}
 
 
void RIO_writeConfig( RioStack_t *stack, const uint32_t offset, const uint32_t data)
{
  /* Check the area of the access. */
  if(offset < 0x00010000ul)
  {
    /* Access is not in implementation-defined space. */
 
    /* Check offset and execute request. */
    switch(offset)
    {
      case BASE_DEVICE_ID_CSR:
        stack->baseDeviceId = (uint16_t) data;
        break;
      case HOST_BASE_DEVICE_ID_LOCK_CSR:
        if (stack->hostBaseDeviceIdLock == 0xfffffffful)
        {
          stack->hostBaseDeviceIdLock = (uint16_t)data;
        }
        else
        {
          if ((stack->hostBaseDeviceIdLock & (uint32_t)0x0000fffful) ==
              (data & (uint32_t)0x0000fffful))
          {
            stack->hostBaseDeviceIdLock = 0xfffffffful;
          }
          else
          {
            /* Ignore the write. */
          }
        }
        break;
      case COMPONENT_TAG_CSR:
        stack->componentTag = data;
        break;
      case PORT_LINK_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
        /* REMARK: Implement this... */
        break;
      case PORT_RESPONSE_TIMEOUT_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
        /* REMARK: Implement this... */
        break;
      case PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET):
        /* Return host, master enable bit and discovered bit. */
        stack->host = (uint8_t)(data >> 31) & 1u;
        stack->masterEnable = (uint8_t)(data >> 30) & 1u;
        stack->discovered = (uint8_t)(data >> 29) & 1u;
        break;
      case PORT_N_LOCAL_ACKID_CSR(EXTENDED_FEATURES_OFFSET, 0u):
        if(data & 0x80000000)
        {
          while(!QueueEmpty(stack->txQueue))
          {
            stack->txQueue = QueueDequeue(stack->txQueue);
          }
        }
        stack->rxAckId = (uint8_t) ((data >> 24) & 0x1f);
        stack->txAckId = (uint8_t) ((data >> 8) & 0x1f);
        stack->txAckIdWindow = (uint8_t) (data & 0x1f);
        break;
      default:
        break;
    }
  }
  else
  {
    /* Access is in implementation-defined space. */
 
    /* Check if there are any registered callback. */
    if((stack->observer != NULL) &&
       (stack->observer->configWrite != NULL))
    {
      /* Call the observer callback to handle the access. */
      stack->observer->configWrite(stack, offset - 0x00010000ul, data);
    }
    else
    {
      /* Dont do anything. */
    }
  }
} 
 
 
/*******************************************************************************************
 * Logical I/O MAINTENANCE-READ functions.
 *******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                     const uint8_t hopCount, const uint32_t offset)
{
  sendMaintenanceReadRequest(stack, destid, srcid, tid, hopCount, offset);
}
#else
void RIO_sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint8_t tid, 
                                     const uint8_t hopCount, const uint32_t offset)
{
  sendMaintenanceReadRequest(stack, destid, stack->baseDeviceId, tid, hopCount, offset);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                        uint8_t *hopCount, uint32_t *offset)
{
  receiveMaintenanceReadRequest( stack, destid, srcid, tid, hopCount, offset);
}
#else
void RIO_receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, 
                                        uint8_t *hopCount, uint32_t *offset)
{
  receiveMaintenanceReadRequest( stack, srcid, srcid, tid, hopCount, offset);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                      const uint8_t hopCount, const uint32_t data)
{
  sendMaintenanceReadResponse(stack, destid, srcid, tid, hopCount, data);
}
#else
void RIO_sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid, 
                                      const uint8_t hopCount, const uint32_t data)
{
  sendMaintenanceReadResponse(stack, destid, stack->baseDeviceId, tid, hopCount, data);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                         uint8_t *hopCount, uint32_t *data)
{
  receiveMaintenanceReadResponse(stack, destid, srcid, tid, hopCount, data);
}  
#else
void RIO_receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, 
                                         uint8_t *hopCount, uint32_t *data)
{
  receiveMaintenanceReadResponse(stack, srcid, srcid, tid, hopCount, data);
}
#endif
 
/*******************************************************************************************
 * Logical I/O MAINTENANCE-WRITE functions.
 *******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                      const uint8_t hopCount, const uint32_t offset, const uint32_t data )
{
  sendMaintenanceWriteRequest(stack, destid, srcid, tid, hopCount, offset, data);
}
#else
void RIO_sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint8_t tid, 
                                      const uint8_t hopCount, const uint32_t offset, const uint32_t data )
{
  sendMaintenanceWriteRequest(stack, destid, stack->baseDeviceId, tid, hopCount, offset, data);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                         uint8_t *hopCount, uint32_t *offset, uint32_t *data )
{
  receiveMaintenanceWriteRequest(stack, destid, srcid, tid, hopCount, offset, data);
}
#else
void RIO_receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, 
                                         uint8_t *hopCount, uint32_t *offset, uint32_t *data )
{
  receiveMaintenanceWriteRequest(stack, srcid, srcid, tid, hopCount, offset, data);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                       const uint8_t hopCount)
{
  sendMaintenanceWriteResponse(stack, destid, srcid, tid, hopCount);
}
#else
void RIO_sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint8_t tid, 
                                       const uint8_t hopCount)
{
  sendMaintenanceWriteResponse(stack, destid, stack->baseDeviceId, tid, hopCount);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                      uint8_t *hopCount)
{
  receiveMaintenanceWriteResponse(stack, destid, srcid, tid, hopCount);
}
#else
void RIO_receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, 
                                      uint8_t *hopCount)
{
  receiveMaintenanceWriteResponse(stack, srcid, srcid, tid, hopCount);
}
#endif
 
/*******************************************************************************************
 * Logical I/O NWRITE/NWRITER functions.
 *******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, 
                     const uint32_t address, const uint16_t size, const uint8_t *data)
{
  sendNwrite(stack, destid, srcid, 0, address, size, data, 0u);
}
#else
void RIO_sendNwrite( RioStack_t *stack, const uint16_t destid, 
                     const uint32_t address, const uint16_t size, const uint8_t *data)
{
  sendNwrite(stack, destid, stack->baseDeviceId, 0, address, size, data, 0u);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                      const uint32_t address, const uint16_t size, const uint8_t *data)
{
  sendNwrite(stack, destid, srcid, tid, address, size, data, 1u);
}
#else
void RIO_sendNwriteR( RioStack_t *stack, const uint16_t destid, const uint8_t tid, 
                      const uint32_t address, const uint16_t size, const uint8_t *data)
{
  sendNwrite(stack, destid, stack->baseDeviceId, tid, address, size, data, 1u);
}
#endif
 
#ifdef RIO_TRANSPARENT
uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
                        uint32_t *address, const uint16_t dataLength, uint8_t *data )
{
  return receiveNwrite(stack, destid, srcid, tid, address, dataLength, data);
}
#else
uint16_t RIO_receiveNwrite( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,
                        uint32_t *address, const uint16_t dataLength, uint8_t *data )
{
  return receiveNwrite(stack, srcid, srcid, tid, address, dataLength, data);
}
#endif
 
/*******************************************************************************************
 * Logical I/O NREAD functions.
 *******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                    const uint32_t address, const uint16_t dataLength)
{
  sendNread(stack, destid, srcid, tid, address, dataLength);
}
#else
void RIO_sendNread( RioStack_t *stack, const uint16_t destid, const uint8_t tid, 
                    const uint32_t address, const uint16_t dataLength)
{
  sendNread(stack, destid, stack->baseDeviceId, tid, address, dataLength);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                       uint32_t *address, uint16_t *dataLength)
{
  receiveNread( stack, destid, srcid, tid, address, dataLength);
}
#else
void RIO_receiveNread( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, 
                       uint32_t *address, uint16_t *dataLength)
{
  receiveNread( stack, srcid, srcid, tid, address, dataLength);
}
#endif
 
/*******************************************************************************************
 * Logical I/O RESPONSE-DONE-PAYLOAD, RESPONSE-DONE, RESPONSE-RETRY and RESPONSE-ERROR 
 * functions.
 *******************************************************************************************/
 
 
#ifdef RIO_TRANSPARENT
void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                  const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer)
{
  sendResponseDonePayload(stack, destid, srcid, tid, address, bufferSize, buffer);
}
#else
void RIO_sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint8_t tid, 
                                  const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer)
{
  sendResponseDonePayload(stack, destid, stack->baseDeviceId, tid, address, bufferSize, buffer);
}
#endif
 
#ifdef RIO_TRANSPARENT
uint16_t RIO_receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,  
                                         const uint32_t address, const uint16_t dataLength, uint8_t *data )
{
  return receiveResponseDonePayload(stack, destid, srcid, tid, address, dataLength, data);
}
#else
uint16_t RIO_receiveResponseDonePayload( RioStack_t *stack, uint16_t *srcid, uint8_t *tid,  
                                         const uint32_t address, const uint16_t dataLength, uint8_t *data )
{
  return receiveResponseDonePayload(stack, srcid, srcid, tid, address, dataLength, data);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid)
{
  sendResponse(stack, destid, srcid, tid, 0x0u);
}
#else
void RIO_sendResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t tid)
{
  sendResponse(stack, destid, stack->baseDeviceId, tid, 0x0u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
{
  receiveResponse(stack, destid, srcid, tid);
}
#else
void RIO_receiveResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
{
  receiveResponse(stack, srcid, srcid, tid);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid )
{
  sendResponse(stack, destid, srcid, tid, 0x3u);
}
#else
void RIO_sendResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t tid )
{
  sendResponse(stack, destid, stack->baseDeviceId, tid, 0x3u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
{
  receiveResponse(stack, destid, srcid, tid);
}
#else
void RIO_receiveResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
{
  receiveResponse(stack, srcid, srcid, tid);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid)
{
  sendResponse(stack, destid, srcid, tid, 0x7u);
}
#else
void RIO_sendResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t tid)
{
  sendResponse(stack, destid, stack->baseDeviceId, tid, 0x7u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
{
  receiveResponse(stack, destid, srcid, tid);
}
#else
void RIO_receiveResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *tid)
{
  receiveResponse(stack, srcid, srcid, tid);
}
#endif
 
 
 
/*******************************************************************************************
 * Logical message passing DOORBELL and MESSAGE functions.
 *******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                       const uint16_t info )
{
  sendDoorbell(stack, destid, srcid, tid, info);
}
#else
void RIO_sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint8_t tid, 
                       const uint16_t info )
{
  sendDoorbell(stack, destid, stack->baseDeviceId, tid, info);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                          uint16_t *info)
{
  receiveDoorbell(stack, destid, srcid, tid, info);
}
#else
void RIO_receiveDoorbell( RioStack_t *stack, uint16_t *srcid, uint8_t *tid, 
                          uint16_t *info)
{
  receiveDoorbell(stack, srcid, srcid, tid, info);
}
#endif
 
#ifdef RIO_TRANSPARENT
void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, 
                      const uint16_t bufferSize, const uint8_t* bufferData)
{
  sendMessage(stack, destid, srcid, mailbox, bufferSize, bufferData);
}
#else
void RIO_sendMessage( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox, 
                      const uint16_t bufferSize, const uint8_t* bufferData)
{
  sendMessage(stack, destid, stack->baseDeviceId, mailbox, bufferSize, bufferData);
}
#endif
 
#ifdef RIO_TRANSPARENT
uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox, 
                             const uint16_t dataLength, uint8_t *data )
{
  return receiveMessage(stack, destid, srcid, mailbox, dataLength, data);
}
#else
uint16_t RIO_receiveMessage( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox, 
                             const uint16_t dataLength, uint8_t *data )
{
  return receiveMessage(stack, srcid, srcid, mailbox, dataLength, data);
}
#endif
 
/*******************************************************************************************
 * Logical message passing MESSAGE-RESPONSE functions.
 *******************************************************************************************/
 
#ifdef RIO_TRANSPARENT
void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox)
{
  sendMessageResponse(stack, destid, srcid, mailbox, 0x0u);
}
#else
void RIO_sendMessageResponseDone( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox)
{
  sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x0u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
{
  receiveMessageResponse(stack, destid, srcid, mailbox);
}
#else
void RIO_receiveMessageResponseDone( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
{
  receiveMessageResponse(stack, srcid, srcid, mailbox);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox)
{
  sendMessageResponse(stack, destid, srcid, mailbox, 0x3u);
}
#else
void RIO_sendMessageResponseRetry( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox)
{
  sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x3u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
{
  receiveMessageResponse(stack, destid, srcid, mailbox);
}
#else
void RIO_receiveMessageResponseRetry( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
{
  receiveMessageResponse(stack, srcid, srcid, mailbox);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox)
{
  sendMessageResponse(stack, destid, srcid, mailbox, 0x7u);
}
#else
void RIO_sendMessageResponseError( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox)
{
  sendMessageResponse(stack, destid, stack->baseDeviceId, mailbox, 0x7u);
}
#endif
 
 
#ifdef RIO_TRANSPARENT
void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
{
  receiveMessageResponse(stack, destid, srcid, mailbox);
}
#else
void RIO_receiveMessageResponseError( RioStack_t *stack, uint16_t *srcid, uint8_t *mailbox)
{
  receiveMessageResponse(stack, srcid, srcid, mailbox);
}
#endif
 
 
void RIO_portSetStatus( RioStack_t *stack, const uint8_t initialized)
{
  /* REMARK: Clean the queues here as well??? */
  if (initialized)
  {
    stack->rxState = RX_STATE_PORT_INITIALIZED;
    stack->rxCounter = 0u;
    stack->rxCrc = 0xffffu;
    stack->rxStatusReceived = 0;
    stack->rxAckId = 0u;
    stack->rxAckIdAcked = 0u;
    stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_RESERVED;
 
    stack->txState = TX_STATE_PORT_INITIALIZED;
    stack->txCounter = 0u;
    stack->txStatusCounter = 0u;
    stack->txFrameState = TX_FRAME_START;
    stack->txAckId = 0u;
    stack->txAckIdWindow = 0u;
  }
  else
  {
    stack->rxState = RX_STATE_UNINITIALIZED;
    stack->txState = TX_STATE_UNINITIALIZED;
  }
}
 
 
void RIO_portSetTime( RioStack_t *stack, const uint32_t time)
{
  stack->portTime = time;
}
 
 
void RIO_portSetTimeout( RioStack_t *stack, const uint32_t time)
{
  stack->portTimeout = time;
}
 
 
void RIO_portAddSymbol( RioStack_t *stack, const RioSymbol s)
{
  uint8_t stype0;
  uint8_t parameter0;
  uint8_t parameter1;
  uint8_t stype1;
 
 
  switch(stack->rxState)
  {
    case RX_STATE_PORT_INITIALIZED:
      /******************************************************************************
       * PORT_INITIALIZED
       * This state is entered to initialize the link. Only status-control-symbols 
       * are accepted in this state. When 7 error-free, i.e. with CRC5 correct, status 
       * control symbols has been received, change state to linkInitialized.
       ******************************************************************************/
 
      /* Check the type of symbol. */
      if(s.type == RIO_SYMBOL_TYPE_CONTROL)
      {
        /* This is a control symbol. */
 
        /* Check that the control symbol contains no errors. */
        if(Crc5(s.data, 0x1fu) == (s.data & 0x1ful))
        {
          /* Error-free control symbol. */
 
          /* Check if the symbol is a status symbol. */
          stype0 = STYPE0_GET(s.data);
          if(stype0 == STYPE0_STATUS) 
          {
            /* Status symbol received. */
 
            /* Indicate an error-free status has been received. */
            stack->rxStatusReceived = 1;
 
            /* Check if enough status control symbols has been received. */
            if(stack->rxCounter == 7u)
            {
              /* Enough correct status control symbols has been received without 
                 errors in between. */
 
              /* Setup the transmitter with the content of the symbol. */
              stack->txAckId = PARAMETER0_GET(s.data);
              stack->txAckIdWindow = stack->txAckId;
              stack->txBufferStatus = PARAMETER1_GET(s.data);
 
              /* Set the transmitter in its normal operational mode. */
              stack->rxState = RX_STATE_LINK_INITIALIZED;
              stack->rxCounter = 0u;
              DEBUG_STATE("rx:normal");
            }
            else
            {
              /* Count the number of consequitive error-free status control symbols 
                 that has been received. */
              stack->rxCounter++;
            }
          }
          else
          {
            /* The received symbol is not a status symbol. */
            /* Discard it. */
          }
        }
        else
        {
          /* CRC error in control symbol. */
          /* Restart counting error-free status-control-symbols. */
          stack->rxCounter = 0u;
        }
      }
      else
      {
        /* Not a control symbol. */
        /* Discard the symbol. */
      }
 
      break;
 
    case RX_STATE_LINK_INITIALIZED:
      /******************************************************************************
       * LINK_INITIALIZED
       * The normal state. Accept packets and forward them.
       ******************************************************************************/
 
      /* Check the type of symbol. */
      switch(s.type)
      {
        case RIO_SYMBOL_TYPE_CONTROL:
          /**************************************************************************
           * This is a control symbol.
           **************************************************************************/
 
          /* Check if the CRC is correct. */
          if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
          {
            /* The CRC is correct. */
 
            /* Get the content of the control symbol. */
            stype0 = STYPE0_GET(s.data);
            parameter0 = PARAMETER0_GET(s.data);
            parameter1 = PARAMETER1_GET(s.data);
            stype1 = STYPE1_GET(s.data);            
 
            /**********************************************************************************
             * Check the stype0 part of the symbol. 
             * Note that errors in this should trigger OUTPUT_ERROR_STOPPED.
             **********************************************************************************/
            switch(stype0)
            {
              case STYPE0_STATUS:
                /* A status containing the current ackId and the buffer status has been 
                   received. */
                handleStatus(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_ACCEPTED:
                /* A packet has been accepted by the link partner. */
                handlePacketAccepted(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_RETRY:
                /* The link partner wants us to initiate a restart of the received ackId. */
                handlePacketRetry(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_NOT_ACCEPTED:
                /* The link partner indicates that a packet has been rejected. */
                handlePacketNotAccepted(stack, parameter0, parameter1);
                break;
 
              case STYPE0_LINK_RESPONSE:
                /* The link partner has sent a response to a link-request. */
                handleLinkResponse(stack, parameter0, parameter1);
                break;
 
              case STYPE0_VC_STATUS:
              case STYPE0_RESERVED:
              case STYPE0_IMPLEMENTATION_DEFINED:
              default:
                /* Unsupported symbol received. */
                /* Discard them. */
                break;
            }
 
            /**********************************************************************************
             * Check the stype1 part of the symbol.
             * Note that errors in this should trigger INPUT_ERROR_STOPPED.
             **********************************************************************************/
            switch(stype1)
            {
              case STYPE1_START_OF_PACKET:
                /* Start of a new packet. */
                handleStartOfPacket(stack);
                break;
 
              case STYPE1_END_OF_PACKET:
                /* Ending a packet. */
                handleEndOfPacket(stack);
                break;
 
              case STYPE1_STOMP:
                /* Cancel the currently received frame. */
                stack->rxCounter = 0;
                break;
 
              case STYPE1_RESTART_FROM_RETRY:
                /* Cancel the currently received frame when in this state. */
                stack->rxCounter = 0;
                break;
 
              case STYPE1_LINK_REQUEST:
                /* A link-request has been received. */
                handleLinkRequest(stack, CMD_GET(s.data));
                break;
 
              case STYPE1_NOP:
                /* No operation symbol. */
                /* Discard these. */
                break;
 
              case STYPE1_MULTICAST_EVENT:
              case STYPE1_RESERVED:
              default:
                /* Unsupported symbol received. */
                /* Discard them. */
                break;
            }
          }
          else
          {
            /* The control symbol CRC is incorrect. */
            /* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */
            stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
            stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
            stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC;
            stack->statusInboundErrorControlCrc++;
            DEBUG_STATE("rx:error-stopped");
          }
          break;
 
        case RIO_SYMBOL_TYPE_DATA:
          /**************************************************************************
           * This is a data symbol.
           **************************************************************************/
 
          /* Check if a packet has been started and that it is not too long. */
          if ((stack->rxCounter >= 1u) && (stack->rxCounter <= RIO_PACKET_SIZE))
          {
            /* A packet has been started. */
 
            /* Check if the ackId is correct on the first part of the packet. */
            if ((stack->rxCounter > 1u) ||
                ((stack->rxCounter == 1u) && (((uint8_t)(s.data >> 27)) == stack->rxAckId)))
            {
              /* The ackId is the expected one. */
 
              /* Check if this is the first symbol of a packet. */
              if (stack->rxCounter == 1u)
              {
                /* This is the first symbol of the packet. */
                /* Start to calculate the CRC of the packet. */
                /* Note that the ackId should not be included in the CRC calculation. */
                stack->rxCrc = Crc32(s.data & (uint32_t)0x03fffffful, 0xffffu);
              }
              else
              {
                /* This is not the first symbol. */
                /* Continue to calculate the CRC of the packet. */
                stack->rxCrc = Crc32(s.data, stack->rxCrc);
              }
 
              /* Save the new data in the packet queue and update the reception counter. */
              QueueSetContent(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul, s.data);
              stack->rxCounter++;
            }
            else
            {
              DEBUG_FRAMING_RX("error=%u %u", stack->rxAckId, s.data>>27);
 
              /* The ackId is not correct. */
              /* Packet error. Enter input-error-stopped state. */
              stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
              stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
              stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID;
              stack->statusInboundErrorPacketAckId++;
              DEBUG_STATE("rx:error-stopped");
            }
          }
          else
          {
            /* No packet has been started or the packet is too long. */
            /* Packet error. Enter input-error-stopped state. */
            stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
            stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
            stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
            stack->statusInboundErrorGeneral++;
            DEBUG_STATE("rx:error-stopped");
          }
          break;
 
        case RIO_SYMBOL_TYPE_ERROR:
          /**************************************************************************
           * The decoder has received a erronous symbol.
           **************************************************************************/
 
          /* Idle symbol error. Place the receiver in input-error-stopped state. */
          stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
          stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
          stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER;
          stack->statusInboundErrorIllegalCharacter++;
          DEBUG_STATE("rx:error-stopped");
          break;
 
        case RIO_SYMBOL_TYPE_IDLE:
        default:
          /**************************************************************************
           * Idle symbol or unsupported symbol.
           **************************************************************************/
 
          /* Discard these for now. */
          break;
      }
      break;
 
    case RX_STATE_INPUT_RETRY_STOPPED:
      /******************************************************************************
       * INPUT_RETRY_STOPPED
       * This state is entered when no more buffers was available and a packet was 
       * received. When in this state, all packets should be discarded until a 
       * RESTART-FROM-RETRY symbol is received. See section 5.9.1.4 of the standard. 
       * Note that it is only the input side of the port that are affected, not the 
       * output side. Packets may still be transmitted and acknowledges should be 
       * accepted.
       ******************************************************************************/
 
      /* Check the type of symbol. */
      switch(s.type)
      {
        case RIO_SYMBOL_TYPE_CONTROL:
          /* This is a control symbol. */
 
          /* Check if the CRC is correct. */
          if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
          {
            /* The CRC is correct. */
 
            /* Get the content of the control symbol. */
            stype0 = STYPE0_GET(s.data);
            parameter0 = PARAMETER0_GET(s.data);
            parameter1 = PARAMETER1_GET(s.data);
            stype1 = STYPE1_GET(s.data);
 
            /* Check the stype0 part of the symbol. */
            switch(stype0)
            {
              case STYPE0_STATUS:
                /* A status containing the current ackId and the buffer status has been 
                   received. */
                handleStatus(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_ACCEPTED:
                /* A packet has been accepted by the link partner. */
                handlePacketAccepted(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_RETRY:
                /* The link partner wants us to initiate a restart of the received ackId. */
                handlePacketRetry(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_NOT_ACCEPTED:
                /* The link partner indicates that a packet has been rejected. */
                handlePacketNotAccepted(stack, parameter0, parameter1);
                break;
 
              case STYPE0_LINK_RESPONSE:
                /* The link partner has sent a response to a link-request. */
                handleLinkResponse(stack, parameter0, parameter1);
                break;
 
              case STYPE0_VC_STATUS:
              case STYPE0_RESERVED:
              case STYPE0_IMPLEMENTATION_DEFINED:
              default:
                /* Unsupported symbol received. */
                /* Discard them. */
                break;
            }
 
            /* Check the stype1 part of the symbol. */
            switch(stype1)
            {
              case STYPE1_START_OF_PACKET:
                /* Starting new frames are ignored in this state. */
                break;
 
              case STYPE1_END_OF_PACKET:
                /* Ending new frames are ignored in this state. */
                break;
 
              case STYPE1_STOMP:
                /* Restarting frames are ignored in this state. */
                break;
 
              case STYPE1_RESTART_FROM_RETRY:
                /* The link partner has confirmed our packet-retry-symbol. */
                /* Go back to the normal state and reset the frame reception. */
                stack->rxState = RX_STATE_LINK_INITIALIZED;
                stack->rxCounter = 0u;
                DEBUG_STATE("rx:normal(restart)");
                break;
 
              case STYPE1_LINK_REQUEST:
                /* A link-request has been received. */
                handleLinkRequest(stack, CMD_GET(s.data));
                stack->rxState = RX_STATE_LINK_INITIALIZED;
                DEBUG_STATE("rx:normal(link-req)");
                break;
 
              case STYPE1_NOP:
                /* No operation symbol. */
                /* Discard these. */
                break;
 
              case STYPE1_MULTICAST_EVENT:
              case STYPE1_RESERVED:
              default:
                /* Unsupported symbol received. */
                /* Discard them. */
                break;
            }
          }
          else
          {
            /* The control symbol CRC is incorrect. */
            /* Corrupted control symbol. Discard the symbol and enter the input-error-stopped state. */
            stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
            stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
            stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC;
            stack->statusInboundErrorControlCrc++;
            DEBUG_STATE("rx:error-stopped");
          }
          break;
 
        case RIO_SYMBOL_TYPE_ERROR:
          /* Idle symbol error. Place the receiver in input-error-stopped state. */
          stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
          stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
          stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER;
          stack->statusInboundErrorIllegalCharacter++;
          DEBUG_STATE("rx:error-stopped");
          break;
 
        case RIO_SYMBOL_TYPE_DATA:
        case RIO_SYMBOL_TYPE_IDLE:
        default:
          /* Data or idle symbol. */
          /* Discard these in this state. */
          break;
      }
      break;
 
    case RX_STATE_INPUT_ERROR_STOPPED:
      /******************************************************************************
       * INPUT_ERROR_STOPPED
       * This state is entered when an error situation has occurred. When in this 
       * state, all symbols should be discarded until a link-request-symbols has 
       * been received. See section 5.13.2.6 in part 6 of the standard.
       * Note that it is only the input side of the port that are affected, not the 
       * output side. Packets may still be transmitted and acknowledges should be 
       * accepted.
       ******************************************************************************/
 
      /* Check the type of symbol. */
      switch(s.type)
      {
        case RIO_SYMBOL_TYPE_CONTROL:
          /* This is a control symbol. */
 
          /* Check if the CRC is correct. */
          if(Crc5(s.data, 0x1fu) == (s.data & (uint8_t)0x1ful))
          {
            /* The CRC is correct. */
 
            /* Get the content of the control symbol. */
            stype0 = STYPE0_GET(s.data);
            parameter0 = PARAMETER0_GET(s.data);
            parameter1 = PARAMETER1_GET(s.data);
            stype1 = STYPE1_GET(s.data);
 
            /* Check the stype0 part of the symbol. */
            switch(stype0)
            {
              case STYPE0_STATUS:
                /* A status containing the current ackId and the buffer status has been 
                   received. */
                handleStatus(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_ACCEPTED:
                /* A packet has been accepted by the link partner. */
                handlePacketAccepted(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_RETRY:
                /* The link partner wants us to initiate a restart of the received ackId. */
                handlePacketRetry(stack, parameter0, parameter1);
                break;
 
              case STYPE0_PACKET_NOT_ACCEPTED:
                /* The link partner indicates that a packet has been rejected. */
                handlePacketNotAccepted(stack, parameter0, parameter1);
                break;
 
              case STYPE0_LINK_RESPONSE:
                /* The link partner has sent a response to a link-request. */
                handleLinkResponse(stack, parameter0, parameter1);
                break;
 
              case STYPE0_VC_STATUS:
              case STYPE0_RESERVED:
              case STYPE0_IMPLEMENTATION_DEFINED:
              default:
                /* Unsupported symbol received. */
                /* Discard them. */
                break;
            }
 
            /* Check the stype1 part of the symbol. */
            switch(stype1)
            {
              case STYPE1_START_OF_PACKET:
                /* Starting new frames are ignored in this state. */
                break;
 
              case STYPE1_END_OF_PACKET:
                /* Ending new frames are ignored in this state. */
                break;
 
              case STYPE1_STOMP:
                /* Restarting frames are ignored in this state. */
                break;
 
              case STYPE1_RESTART_FROM_RETRY:
                /* Restart-from-retry are ignored in this state.  */
                break;
 
              case STYPE1_LINK_REQUEST:
                /* This is the symbol we have been waiting for. */
                /* Force the transmitter to send a link-response and go back into the normal 
                   operational state. */
                /* The transmitter will always send a status as the first symbol after this. */
                handleLinkRequest(stack, CMD_GET(s.data));
                stack->rxState = RX_STATE_LINK_INITIALIZED;
                DEBUG_STATE("rx:normal(link-req)");
                break;
 
              case STYPE1_NOP:
                /* No operation symbol. */
                /* Discard these. */
                break;
 
              case STYPE1_MULTICAST_EVENT:
              case STYPE1_RESERVED:
              default:
                /* Unsupported symbol received. */
                /* Discard them. */
                break;
            }
          }
          else
          {
            /* The CRC is incorrect. */
            /* Discard these in this state. */
          }
          break;
 
        case RIO_SYMBOL_TYPE_DATA:
        case RIO_SYMBOL_TYPE_IDLE:
        case RIO_SYMBOL_TYPE_ERROR:
        default:
          /* Data, idle or error symbol. */
          /* Discard these in this state. */
          break;
      }
      break;
 
    case RX_STATE_UNINITIALIZED:
    default:
      /******************************************************************************
       * Wait for the port to be initialized.
       ******************************************************************************/
 
      /* Discard all incoming symbols. */
      break;
  }
}
 
 
 
RioSymbol RIO_portGetSymbol( RioStack_t *stack )
{
  RioSymbol s;
 
 
  switch(stack->txState)
  {
    case TX_STATE_PORT_INITIALIZED:
      /******************************************************************************
       * PORT_INITIALIZED
       * This state is entered to initialize the link. Send status-control-symbols 
       * once in a while until the receiver has received enough error-free status-
       * control-symbols and we have transmitted enough status-control-symbols. Once 
       * an error-free status-control-symbol has been received, the statuses are
       * transmitted more frequently to decrease the time for the link to be 
       * initialized.
       ******************************************************************************/
 
      /* Check if an idle symbol or a status control symbol should be sent. */
      if(((stack->rxStatusReceived == 0) && (stack->txCounter == 255u)) ||
         ((stack->rxStatusReceived == 1) && (stack->txCounter >= 15u)))
      {
        /* A control symbol should be sent. */
 
        /* Create a new status symbol and reset the transmission counter. */
        stack->txCounter = 0u;
        s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                STYPE1_NOP, 0u);
 
        /* Check if the receiver has received any error-free status and that we 
           have sent at least 15 status control symbols. */
        if((stack->rxStatusReceived == 1) && (stack->txStatusCounter < 15u))
        {
          /* Has not sent enough status control symbols. */
          stack->txStatusCounter++;
        }
        else
        {
          /* Has sent enough status control symbols. */
          /* Dont do anything. */
        }
      }
      else
      {
        /* Idle symbol should be sent. */
        s.type = RIO_SYMBOL_TYPE_IDLE;
        stack->txCounter++;
      }
 
      /* Check if we are ready to set the transmitter in a link initialized state. */
      if ((stack->rxState == RX_STATE_LINK_INITIALIZED) && (stack->txStatusCounter == 15u))
      {
        /* Ready to go to link initialized. */
        stack->txState = TX_STATE_LINK_INITIALIZED;
        stack->txFrameState = TX_FRAME_START;
        stack->txStatusCounter = 0u;
        DEBUG_STATE("tx:normal");
      }
      else
      {
        /* Not ready to go to link initialized. */
        /* Dont do anything. */
      }
 
      break;
 
    case TX_STATE_LINK_INITIALIZED:
      /******************************************************************************
       * LINK_INITIALIZED
       * The normal state. Accept packets and forward them. Send acknowledges when 
       * the receiver has received complete packets.
       ******************************************************************************/
 
      /* Check if the receiver wants to acknowledge a packet. */
      if(stack->rxAckId == stack->rxAckIdAcked)
      {
        /* The receiver does not want to acknowledge a packet. */
 
        /* Check if there are any outstanding packets and if it has timed out. */
        if((stack->txAckId == stack->txAckIdWindow) ||
           ((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout))
        {
          /* There are no outstanding packets or there has been no timeout. */
 
          /* Check if a packet is ongoing. */
          if(stack->txFrameState == TX_FRAME_BODY)
          {
            /* A packet transmission is ongoing. */
 
            /* Check if the packet has been completly sent. */
            if(stack->txCounter != QueueGetFrontSize(stack->txQueue))
            {
              /* The packet has not been completly sent. */
 
              /* Create a new data symbol to transmit. */
              s.type = RIO_SYMBOL_TYPE_DATA;
              s.data = QueueGetFrontContent(stack->txQueue, (uint32_t)stack->txCounter);
 
              /* Check if this is the first symbol in a packet. */
              if (stack->txCounter == 0u)
              {
                /* Place the correct ackId in the right place. */
                s.data |= (uint32_t)stack->txAckIdWindow << 27;
              }
              else
              {
                /* Dont do anything. */
              }
 
              /* Update the transmission counter. */
              stack->txCounter++;
 
              /* A status control symbol was not sent. Update the status counter. */
              stack->txStatusCounter++;
            }
            else 
            {
              /* The packet has been sent. */
 
              /* Save the timeout time and update to the next ackId. */
              stack->txFrameTimeout[stack->txAckIdWindow] = stack->portTime;
              stack->txAckIdWindow = ACKID_INC(stack->txAckIdWindow);
              stack->txQueue = QueueWindowNext(stack->txQueue);
 
              /* Check if there are more packets pending to be sent. */
              /* Also check that there are buffer available at the receiver and that not too many 
                 packets are outstanding. */
              if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) &&
                 (((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31))
              {
                /* More pending packets. */
                DEBUG_FRAMING_TX("cont=%i", stack->txAckIdWindow);
                /* Create a control symbol to signal that the new packet has started. */
                s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                        STYPE1_START_OF_PACKET, 0u);
 
                /* Restart transmission counter. */
                stack->txCounter = 0;
              }
              else
              {
                /* No more pending packets. */
                DEBUG_FRAMING_TX("end=%i", stack->txAckIdWindow);
                /* Create a control symbol to signal that the packet has ended. */
                s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                        STYPE1_END_OF_PACKET, 0u);
 
                /* Go back to wait for a new frame. */
                stack->txFrameState = TX_FRAME_START;
              }
 
              /* A status control symbol has been sent. Reset the status counter. */
              stack->txStatusCounter = 0u;
            }
          }
          else
          {
            /* No packet is being sent. */
 
            /* Check if there are any pending packets to start sending. */
            /* Also check that there are buffer available at the receiver and that not too many 
               packets are outstanding. */
            if(!QueueWindowEmpty(stack->txQueue) && (stack->txBufferStatus > 0) &&
               (((stack->txAckIdWindow - stack->txAckId) & 0x1f) != 31))
            {
              /* There is a pending packet to send. */
              DEBUG_FRAMING_TX("start=%i", stack->txAckIdWindow);
              /* Send a start-of-packet control symbol to start to send the packet. */
              s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                      STYPE1_START_OF_PACKET, 0u);
              stack->txFrameState = TX_FRAME_BODY;
              stack->txCounter = 0u;
 
              /* A status control symbol has been sent. Reset the status counter. */
              stack->txStatusCounter = 0u;
            }
            else
            {
              /* There are no pending packets to send. */
 
              /* Check if a status control symbol must be transmitted. */
              if(stack->txStatusCounter < 255u)
              {
                /* Not required to send a status control symbol. */
 
                /* Send an idle-symbol. */
                s.type = RIO_SYMBOL_TYPE_IDLE;
                stack->txStatusCounter++;
              }
              else
              {
                /* Must send a status control symbol. */
 
                /* Create a status control symbol. */
                s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                        STYPE1_NOP, 0u);
 
                /* A status control symbol has been sent. Reset the status counter. */
                stack->txStatusCounter = 0u;
              }
            }
          }
        }
        else
        {
          /* There has been a timeout. */
          /* A packet has been sent but no packet-accepted has been received. */
          DEBUG_FRAMING_TX("timeout=%i", stack->txAckId);
          /* Send link-request-symbol (input-status). */
          s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                  STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
 
          /* Save the time when this was transmitted. */
          stack->txFrameTimeout[stack->txAckId] = stack->portTime;
 
          /* Remember that this symbol has been transmitted. */
          stack->txCounter = 1;
 
          /* Go into the output error stopped state. */
          stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
          stack->statusOutboundErrorTimeout++;
          DEBUG_STATE("tx:error-stopped");
        }
      }
      else
      {
        /* The receiver wants us to send an acknowledgement. */
        s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue), 
                                STYPE1_NOP, 0u);
        stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked);
 
        /* A status control symbol was not sent. Update the status counter. */
        stack->txStatusCounter++;
      }
      break;
 
    case TX_STATE_SEND_PACKET_RETRY:
      /******************************************************************************
       * SEND_PACKET_RETRY
       * This state is set by the receiver to force a packet-retry-symbol to be 
       * transmitted.
       ******************************************************************************/
 
      /* Check if the receiver wants to acknowledge a packet. */
      /* This must be done first or we will get an error for a missmatching 
         ackId in the link-partner. */
      if(stack->rxAckId == stack->rxAckIdAcked)
      {
        /* No pending acknowledge. */
 
        /* Send a packet-retry symbol to tell the link partner to retry the last frame. */
        s = CreateControlSymbol(STYPE0_PACKET_RETRY, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                STYPE1_NOP, 0u);
 
        /* Proceed with normal transmission. */
        stack->txState = TX_STATE_LINK_INITIALIZED;
 
        /* A status control symbol was not sent. Update the status counter. */
        stack->txStatusCounter++;
      }
      else
      {
 
        /* The receiver wants us to send an acknowledgement. */
        s = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, stack->rxAckIdAcked, QueueAvailable(stack->rxQueue), 
                                STYPE1_NOP, 0u);
        stack->rxAckIdAcked = ACKID_INC(stack->rxAckIdAcked);
 
        /* A status control symbol was not sent. Update the status counter. */
        stack->txStatusCounter++;
      }
      break;
 
    case TX_STATE_SEND_PACKET_NOT_ACCEPTED:
      /******************************************************************************
       * SEND_PACKET_NOT_ACCEPTED
       * This state is set by the receiver to force a packet-not-accepted-symbol to be 
       * transmitted.
       ******************************************************************************/
 
      /* Send a packet-not-accepted symbol to indicate an error on the link. */
      s = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, stack->rxErrorCause, 
                              STYPE1_NOP, 0u);
 
      /* Proceed with normal transmission. */
      stack->txState = TX_STATE_LINK_INITIALIZED;
 
      /* A status control symbol was not sent. Update the status counter. */
      stack->txStatusCounter++;
      break;
 
    case TX_STATE_SEND_LINK_RESPONSE:
      /******************************************************************************
       * SEND_LINK_RESPONSE
       * This state is set by the receiver to force a link-response-symbol to be 
       * transmitted.
       ******************************************************************************/
 
      DEBUG_FRAMING_RX("link-res:%u", stack->rxAckId);
 
      /* Check the state of the receiver. */
      /* REMARK: If a link-request gives this response and a link-request also makes the receiver 
         enter the normal operational state, none of these states except the normal state will ever 
         be used... */
      if((stack->rxState == RX_STATE_LINK_INITIALIZED) || (stack->rxState == RX_STATE_PORT_INITIALIZED))
      {
        /* Normal state. */
        s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_OK, 
                                STYPE1_NOP, 0u);
      }
      else if(stack->rxState == RX_STATE_INPUT_RETRY_STOPPED)
      {
        /* Input-retry-stopped state. */
        s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_RETRY_STOPPED, 
                                STYPE1_NOP, 0u);
      }
      else if(stack->rxState == RX_STATE_INPUT_ERROR_STOPPED)
      {
        /* Input-error-stopped state. */
        s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR_STOPPED, 
                                STYPE1_NOP, 0u);
      }
      else
      {
        /* Not in the defined states. */
        s = CreateControlSymbol(STYPE0_LINK_RESPONSE, stack->rxAckId, LINK_RESPONSE_PORT_STATUS_ERROR, 
                                STYPE1_NOP, 0u);
      }
 
      /* Proceed with normal transmission. */
      stack->txState = TX_STATE_LINK_INITIALIZED;
 
      /* Force a status to be transmitted the next time to comply to the input-error-stopped 
         state rules. */
      stack->txStatusCounter = 255;
      break;
 
    case TX_STATE_OUTPUT_RETRY_STOPPED:
      /******************************************************************************
       * OUTPUT_RETRY_STOPPED
       * This state is entered when the link-partner has transmitted a 
       * packet-retry-symbol. The packet-retry-symbol is acknowledged by sending a 
       * restart-from-retry-symbol.
       * This state follows 5.9.1.5 in part 6. 
       ******************************************************************************/
 
      /* Send a restart-from-retry symbol to acknowledge. */
      s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                              STYPE1_RESTART_FROM_RETRY, 0u);
 
      /* Restart the current frame and proceed with normal operation. */
      stack->txFrameState = TX_FRAME_START;
      stack->txState = TX_STATE_LINK_INITIALIZED;
      stack->txCounter = 0;
      DEBUG_STATE("tx:normal");
 
      /* Discard all packets that has not received a matching packet-accepted. */
      stack->txAckIdWindow = stack->txAckId;
      stack->txQueue = QueueWindowReset(stack->txQueue);
 
      /* A status control symbol was sent. Reset the status counter. */
      stack->txStatusCounter = 0;
      break;
 
    case TX_STATE_OUTPUT_ERROR_STOPPED:
      /******************************************************************************
       * OUTPUT_ERROR_STOPPED
       * This state is entered when the link partner has encountered any problem 
       * which is indicated by sending a packet-not-accepted symbol or if a packet 
       * timeout has expired. The error condition is acknowledged by sending a 
       * link-request-symbol and then wait for a link-response reply.
       * This state follows 5.13.2.7 in part 6. 
       ******************************************************************************/
 
      /* Check if a link-request-symbol has been transmitted. */
      if(stack->txCounter == 0)
      {
        /* A link-request-symbol has not been transmitted. */
 
        /* Send link-request-symbol (input-status). */
        s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
 
        /* Save the time when this was transmitted. */
        stack->txFrameTimeout[stack->txAckId] = stack->portTime;
 
        /* Remember that this symbol has been transmitted. */
        stack->txCounter = 1;
      }
      else
      {
        /* A link-request-symbol has been transmitted. */
 
        /* Check if the link partner reply has timed out. */
        if((stack->portTime - stack->txFrameTimeout[stack->txAckId]) < stack->portTimeout)
        {
          /* No timeout. */
 
          /* A link-request-symbol has been transmitted. */
          /* Send only idle-symbols until the link-response is received. */
          s.type = RIO_SYMBOL_TYPE_IDLE;
        }
        else
        {
          /* Link response timeout. */
 
          /* Check if the link-partner has not responded for too many times. */
          if(stack->txCounter < 5)
          {
            /* Not too many timeouts. */
            /* Retry and send a new link-request. */
 
            /* Send link-request-symbol (input-status). */
            s = CreateControlSymbol(STYPE0_STATUS, stack->rxAckId, QueueAvailable(stack->rxQueue), 
                                    STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
 
            /* Save the time when this was transmitted. */
            stack->txFrameTimeout[stack->txAckId] = stack->portTime;
 
            /* Increment the number of times we have retransmitted the link-request. */
            stack->txCounter++;
          }
          else
          {
            /* The link partner has not answered for too many times. */
            /* Give up and set the state to uninitialized. */
            stack->txState = TX_STATE_UNINITIALIZED;
            s.type = RIO_SYMBOL_TYPE_IDLE;
            ASSERT0("No link-response received, giving up.");
          }
        }
      }
      break;
 
    case TX_STATE_UNINITIALIZED:
    default:
      /******************************************************************************
       * Wait for the port to be initialized.
       ******************************************************************************/
 
      /* Send only idle symbols. */
      s.type = RIO_SYMBOL_TYPE_IDLE;
      break;
  }
 
  /* Return the created symbol. */
  return s;
}
 
/*******************************************************************************
 * Deprecated functions
 *******************************************************************************/
 
uint8_t RIO_packetTid( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue) , "Reading from empty reception queue.");
 
  return (uint8_t) (QueueGetFrontContent(stack->rxQueue, 1ul) & 0xfful);
}
 
 
uint16_t RIO_packetDestination( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 0ul));
}
 
 
uint16_t RIO_packetSource( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 1ul) >> 16);
}
 
 
uint8_t RIO_readMaintenanceReadRequestHop( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
}
 
uint32_t RIO_readMaintenanceReadRequestOffset( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (QueueGetFrontContent(stack->rxQueue, 2ul) & 0x00fffffcul);
}
 
uint8_t RIO_readMaintenanceReadResponseHop( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
}
 
uint32_t RIO_readMaintenanceReadResponse( RioStack_t *stack )
{
  uint32_t readData;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* There is no way of knowing where the data is positioned. */
  /* Bit-or the two words together since one of the words are zero. */
  readData = QueueGetFrontContent(stack->rxQueue, 3ul);
  readData |= QueueGetFrontContent(stack->rxQueue, 4ul);
  return readData;
}
 
uint8_t RIO_readMaintenanceWriteRequestHop( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
}
 
uint32_t RIO_readMaintenanceWriteRequestOffset( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (QueueGetFrontContent(stack->rxQueue, 2ul) & 0x00fffffcul);
}
 
uint32_t RIO_readMaintenanceWriteRequestData( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (QueueGetFrontContent(stack->rxQueue, 3ul) | QueueGetFrontContent(stack->rxQueue, 4ul));
}
 
uint8_t RIO_readMaintenanceWriteResponseHop( RioStack_t *stack )
{
  return (uint8_t) (QueueGetFrontContent(stack->rxQueue, 2ul) >> 24);
}
 
 
 
void RIO_sendNwrite8( RioStack_t *stack, const uint16_t destid, const uint32_t address, 
                      const uint8_t data)
{
  sendNwrite(stack, destid, stack->baseDeviceId, 0, address, 1, &data, 0u);
}
 
 
void RIO_sendNwriteR8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, 
                       const uint8_t data)
{
  sendNwrite(stack, destid, stack->baseDeviceId, tid, address, 1, &data, 1u);
}
 
 
uint32_t RIO_readNwriteAddress8( RioStack_t *stack )
{
  uint32_t address;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Assemble the address from the wrsize field and the address itself to get a byte address. */
  address = (QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0x00000003ul;
  address |= QueueGetFrontContent(stack->rxQueue, 2ul) & (uint32_t)0xfffffffcul;
 
  return address;
}
 
 
uint8_t RIO_readNwriteSize8( RioStack_t *stack )
{
  uint8_t wrsize;
  uint8_t n;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Get the wrsize field from the packet and check its value. */
  wrsize = (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0xful);
  switch(wrsize)
  {
    case 0:
      /* Reading one byte. */
      n = 1u;
      break;
    case 1:
      /* Reading one byte. */
      n = 1u;
      break;
    case 2:
      /* Reading one byte. */
      n = 1u;
      break;
    case 3:
      /* Reading one byte. */
      n = 1u;
      break;
    default:
      /* Unsupported. */
      n = 0u;
      break;
  }
 
  return n;
}
 
 
uint8_t RIO_readNwritePayload8( RioStack_t *stack )
{
  uint8_t returnValue;
  uint32_t readData;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Since there is no way of knowing where the byte will be placed, 
     OR all bytes in the payload and return it. */
  readData = QueueGetFrontContent(stack->rxQueue, 3ul);
  returnValue = (uint8_t) (readData >> 24);
  returnValue |= (uint8_t) (readData >> 16);
  returnValue |= (uint8_t) (readData >> 8);
  returnValue |= (uint8_t) (readData);
  readData = QueueGetFrontContent(stack->rxQueue, 4ul);
  returnValue |= (uint8_t) (readData >> 24);
  returnValue |= (uint8_t) (readData >> 16);
  returnValue |= (uint8_t) (readData >> 8);
  returnValue |= (uint8_t) (readData);
 
  return returnValue;
}
 
void RIO_sendNread8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = ((uint32_t) 0x0012ul) << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
  content = ((uint32_t) stack->baseDeviceId) << 16;
  content |= ((uint32_t) 0x4ul) << 12;
  content |= (address & (uint32_t)0x00000003ul) << 8;
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* address(28:0)|wdptr|xamsbs(1:0) */
  /* xamsbs cannot be used if the address is a word. */
  content = address & (uint32_t)0xfffffffcul;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* crc(15:0)|pad(15:0) */
  content = ((uint32_t) crc) << 16;
  QueueSetContent(stack->txQueue, 3ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 4ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
 
uint32_t RIO_readNreadAddress8( RioStack_t *stack )
{
  uint32_t address;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Assemble the address from the rdsize field and the address itself to get a byte address. */
  address = (QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0x00000003ul;
  address |= QueueGetFrontContent(stack->rxQueue, 2ul) & (uint32_t)0xfffffffcul;
 
  return address;
}
 
 
uint8_t RIO_readNreadSize8( RioStack_t *stack )
{
  uint8_t rdsize;
  uint8_t n;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Get the rdsize field from the packet and check its value. */
  rdsize = (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 8) & (uint32_t)0xful);
  switch(rdsize)
  {
    case 0:
      /* Reading one byte. */
      n = 1u;
      break;
    case 1:
      /* Reading one byte. */
      n = 1u;
      break;
    case 2:
      /* Reading one byte. */
      n = 1u;
      break;
    case 3:
      /* Reading one byte. */
      n = 1u;
      break;
    default:
      /* Unsupported. */
      n = 0u;
      break;
  }
 
  return n;
}
 
 
void RIO_sendMessage8( RioStack_t *stack, const uint16_t destid, const uint8_t mailbox, const uint16_t size, const uint8_t* data)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
  uint32_t packetIndex;
  uint32_t dataIndex;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
  ASSERT((size <= 256), "Packet sizes over 256 are currently unsupported.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = ((uint32_t) 0x001bul) << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0|mbox(1:0)|xmbox(3:0) */
  content = ((uint32_t) stack->baseDeviceId) << 16;
  if(size <= 8u)
  {
    content |= ((uint32_t) 0x09ul) << 8;
  }
  else if(size <= 16u)
  {
    content |= ((uint32_t) 0x0aul) << 8;
  }
  else if(size <= 32u)
  {
    content |= ((uint32_t) 0x0bul) << 8;
  }
  else if(size <= 64u)
  {
    content |= ((uint32_t) 0x0cul) << 8;
  }
  else if(size <= 128u)
  {
    content |= ((uint32_t) 0x0dul) << 8;
  }
  else
  {
    content |= ((uint32_t) 0x0eul) << 8;
  }
  content |= ((uint32_t)mailbox & (uint32_t)0xfu) << 4;
  content |= ((uint32_t)mailbox) >> 4;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* double-word0...double-wordN */
  dataIndex = 0;
  packetIndex = 8;
  while(dataIndex < size)
  {
    content <<= 8;
    if(packetIndex == 80)
    {
      content |= crc >> 8;
    }
    else if(packetIndex == 81)
    {
      content |= crc & 0xff;
    }
    else
    {
      content |= data[dataIndex++];
    }
 
    if((packetIndex & 0x3) == 3)
    {
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, packetIndex>>2, content);
    }
 
    packetIndex++;
  }
 
  /* Pad the data to an even double word. */
  while((dataIndex & 0x7) != 0)
  {
    content <<= 8;
    dataIndex++;
 
    if((packetIndex & 0x3) == 3)
    {
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, packetIndex>>2, content);
    }
 
    packetIndex++;
  }
 
  /* Check where the CRC should be placed. */
  if((packetIndex & 0x3) == 0)
  {
    /* crc(15:0)|pad(15:0) */
    content = ((uint32_t) crc) << 16;
  }
  else
  {
    /* double-wordN-LSB|crc(15:0) */
    content &= 0x0000ffff;
    crc = Crc16(content, crc);
    content <<= 16;
    content |= crc;
  }
 
  /* Set the crc. */
  QueueSetContent(stack->txQueue, packetIndex>>2, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 1+(packetIndex>>2));
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
 
uint8_t RIO_readMessageMbox( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue." );
 
  return (uint8_t) ((QueueGetFrontContent(stack->rxQueue, 1ul) >> 4) & (uint32_t)0xful);
}
 
 
uint16_t RIO_readMessageSize8( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (uint16_t) (4ul*(QueueGetFrontSize(stack->rxQueue) - 3ul));
}
 
 
/*lint -save -e613 */
void RIO_readMessagePayload8( RioStack_t *stack, uint8_t* buffer )
{
  uint32_t size;
  uint32_t dataIndex;
  uint32_t packetIndex;
  uint32_t content = 0;;
 
 
  ASSERT((buffer != NULL), "Buffer is not allocated.");
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Move bytes from inbound packet queue into the user buffer. */
  /* Long messages contain a CRC in byte 80-81, this is removed when the buffer 
     is copied. */
  size = QueueGetFrontSize(stack->rxQueue);
  dataIndex = 0;
  packetIndex = 8;
  while((packetIndex>>2) < size)
  {
    /* Check if a new word should be read from the inbound queue. */
    if((packetIndex & 0x3) == 0)
    {
      /* Get a new word. */
      content = QueueGetFrontContent(stack->rxQueue, packetIndex>>2);
    }
    else
    {
      /* Update the current word. Remove the MSB, it has already be moved 
         to the user buffer. */
      content <<= 8;
    }
 
    /* Check if the current byte is CRC. */
    if((packetIndex != 80) && (packetIndex != 81))
    {
      /* Not CRC. */
      /* Move the byte to the user buffer. */
      buffer[dataIndex++] = (content >> 24);
    }
 
    /* Increment to the next position in the packet. */
    packetIndex++;
  }
}
/*lint -restore */
 
uint16_t RIO_readDoorbellInfo( RioStack_t *stack )
{
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  return (uint16_t) (QueueGetFrontContent(stack->rxQueue, 2ul) >> 16);
}
 
 
void RIO_sendResponseDone8( RioStack_t *stack, const uint16_t destid, const uint8_t tid, const uint32_t address, const uint8_t data)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = 0x001dul << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
  content = ((uint32_t) stack->baseDeviceId) << 16;
  content |= (uint32_t)0x80ul << 8;
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* double-word 0 */
  switch(address & 0x7ul)
  {
    case 0:
      /* MSB byte. */
      content = ((uint32_t) data) << 24;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 2ul, content);
      content = 0x00000000ul;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 3ul, content);
      break;
    case 1:
      content = ((uint32_t) data) << 16;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 2ul, content);
      content = 0x00000000ul;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 3ul, content);
      break;
    case 2:
      content = ((uint32_t) data) << 8;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 2ul, content);
      content = 0x00000000ul;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 3ul, content);
      break;
    case 3:
      content = ((uint32_t) data);
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 2ul, content);
      content = 0x00000000ul;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 3ul, content);
      break;
    case 4:
      content = 0x00000000ul;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 2ul, content);
      content = ((uint32_t) data) << 24;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 3ul, content);
      break;
    case 5:
      content = 0x00000000ul;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 2ul, content);
      content = ((uint32_t) data) << 16;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 3ul, content);
      break;
    case 6:
      content = 0x00000000ul;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 2ul, content);
      content = ((uint32_t) data) << 8;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 3ul, content);
      break;
    default:
      /* LSB byte. */
      content = 0x00000000ul;
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 2ul, content);
      content = ((uint32_t) data);
      crc = Crc32(content, crc);
      QueueSetContent(stack->txQueue, 3ul, content);
      break;
  }
 
  /* crc(15:0)|pad(15:0) */
  content = ((uint32_t) crc) << 16;
  QueueSetContent(stack->txQueue, 4ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 5ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
 
uint8_t RIO_readResponseDone8( RioStack_t *stack )
{
  uint8_t returnValue;
  uint32_t readData;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Since there is no way of knowing where the byte will be placed, 
     OR all bytes in the reply and return it. */
  readData = QueueGetFrontContent(stack->rxQueue, 2ul);
  returnValue = (uint8_t) (readData >> 24);
  returnValue |= (uint8_t) (readData >> 16);
  returnValue |= (uint8_t) (readData >> 8);
  returnValue |= (uint8_t) (readData);
  readData = QueueGetFrontContent(stack->rxQueue, 3ul);
  returnValue |= (uint8_t) (readData >> 24);
  returnValue |= (uint8_t) (readData >> 16);
  returnValue |= (uint8_t) (readData >> 8);
  returnValue |= (uint8_t) (readData);
 
  return returnValue;
}
 
 
 
/*******************************************************************************
 * Local functions
 *******************************************************************************/
 
 
static void handleStatus(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
{
  /* Update the buffer status of the link partner. */
  (void) ackId;
  stack->txBufferStatus = bufferStatus;
}
 
 
static void handlePacketAccepted(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
{
  /* Check if an acknowledge is expected and that it is for a transmitted packet. */
  if((stack->txAckId != stack->txAckIdWindow) && (ackId == stack->txAckId))
  {
    DEBUG_FRAMING_TX("ack=%i", ackId);
    /* Acknowledge for a recently transmitted packet received. */
    /* Remove the packet from the outbound queue and restart the transmission for
       a new packet. */
    stack->txQueue = QueueDequeue(stack->txQueue);
    stack->txAckId = ACKID_INC(stack->txAckId);
    stack->statusOutboundPacketComplete++;
  }
  else
  {
    DEBUG_FRAMING_TX("*ack=%i", ackId);
    /* Acknowledge for an unexpected ackId or not waiting for an acknowledge. */
    /* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */
    stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
    stack->txCounter = 0u;
    stack->statusOutboundErrorPacketAccepted++;
    DEBUG_STATE("tx:error-stopped");
  }
 
  /* Update the buffer status of the link partner. */
  stack->txBufferStatus = bufferStatus;
}
 
 
static void handlePacketRetry(RioStack_t *stack, const uint8_t ackId, const uint8_t bufferStatus)
{
  /* Check if the retried packet ackId is acceptable. */
  if(ackId == stack->txAckId)
  {
    DEBUG_FRAMING_TX("retry=%u", ackId);
    /* The request for retry is for the current packet. */
    /* Force the transmitter to send a RESTART-FROM-RETRY symbol. */
    stack->txState = TX_STATE_OUTPUT_RETRY_STOPPED;
    stack->statusOutboundPacketRetry++;
    DEBUG_STATE("tx:retry-stopped");
  }
  else
  {
    DEBUG_FRAMING_TX("*retry=%u %u", ackId, stack->txAckId);
    /* Link protocol violation. Discard the symbol and enter the output-error-stopped state. */
    stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
    stack->txCounter = 0u;
    stack->statusOutboundErrorPacketRetry++;
    DEBUG_STATE("tx:error-stopped");
  }
 
  /* Update the buffer status of the link partner. */
  stack->txBufferStatus = bufferStatus;
}
 
 
static void handlePacketNotAccepted(RioStack_t *stack, const uint8_t arbitrary, const uint8_t cause)
{
  (void) arbitrary;
 
  /* Force the transmitter to enter output-error-stopped state. */
  stack->txState = TX_STATE_OUTPUT_ERROR_STOPPED;
  stack->txCounter = 0u;
 
  /* Record the type of error that caused the packet to not being accepted. */
  switch(cause)
  {
    case PACKET_NOT_ACCEPTED_CAUSE_UNEXPECTED_ACKID:
      stack->statusPartnerErrorPacketAckId++;
      break;
    case PACKET_NOT_ACCEPTED_CAUSE_CONTROL_CRC:
      stack->statusPartnerErrorControlCrc++;
      break;
    case PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC:
      stack->statusPartnerErrorPacketCrc++;
      break;
    case PACKET_NOT_ACCEPTED_CAUSE_ILLEGAL_CHARACTER:
      stack->statusPartnerErrorIllegalCharacter++;
      break;
    default:
      stack->statusPartnerErrorGeneral++;
      break;
  }
 
  DEBUG_STATE("tx:error-stopped");
}
 
 
static void handleLinkResponse(RioStack_t *stack, const uint8_t ackId, const uint8_t portStatus)
{
  uint8_t window;
  uint8_t windowReceived;
 
 
  (void) portStatus;
 
  /* Check if this symbols is expected. */
  if(stack->txState == TX_STATE_OUTPUT_ERROR_STOPPED)
  {
    DEBUG_FRAMING_TX("link-res:%u %u %u", stack->txAckIdWindow, stack->txAckId, ackId);
 
    /* Calculate the number of packets that has not received an acknowledge on our side and 
       on the link-partner side. */
    window = (stack->txAckIdWindow - stack->txAckId) & 0x1f;
    windowReceived = (ackId - stack->txAckId) & 0x1f;
 
    /* Check if the link-partners response is acceptable. */
    if(windowReceived <= window)
    {
      /* A link-response is expected. */
      DEBUG_STATE("tx:recover");
 
      /* Remove entries in the queue that the link-partner has sent acknowledges for that has been lost. */
      while(stack->txAckId != ackId)
      {
        stack->txQueue = QueueDequeue(stack->txQueue);
        stack->txAckId = ACKID_INC(stack->txAckId);
        stack->statusOutboundPacketComplete++;
      }
 
      /* Set the transmission window to the resend packets that has not been received. */
      stack->txQueue = QueueWindowReset(stack->txQueue);
      stack->txAckIdWindow = ackId;
      stack->txFrameState = TX_FRAME_START;
 
      /* Set the transmitter back into normal operation. */
      stack->txState = TX_STATE_LINK_INITIALIZED;
    }
    else
    {
      /* The link-partner response is unacceptable. */
      /* Recovery is not possible. */
      stack->txState = TX_STATE_UNINITIALIZED;
      ASSERT0("Unrecoverable protocol error.");
    }
  }
  else
  {
    /* Not expecting a link-response. */
    /* Just discard this symbol. */
    /* REMARK: Add status counter here??? */
  }
}
 
 
static void handleStartOfPacket(RioStack_t *stack)
{
  /* Check if a packet is already started. */
  if(stack->rxCounter != 0u)
  {
    /* Packet has already started. */
    /* This indicates an implicit end-of-packet symbol and signals the previous packet as ready. */
    DEBUG_FRAMING_RX("cont=%u", stack->rxAckId);
 
    /* Check the packet crc. */
    if(stack->rxCrc == 0x0000u)
    {
      /* The packet has a correct CRC. */
 
      /* Check if the packet is long enough to contain a complete packet. */
      if(stack->rxCounter > 3u)
      {
        /* Packet long enough to process. */
 
        /* Process the newly received packet and start a new one. */
        handleNewPacketEnd(stack);
        handleNewPacketStart(stack);
      }
      else
      {
        /* The packet has a valid CRC but is too short. */
        /* Packet error. Enter input-error-stopped state. */
        stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
        stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
        stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
        stack->statusInboundErrorGeneral++;
        DEBUG_STATE("rx:error-stopped");
      }
    }
    else
    {
      /* The packet has an invalid CRC. */
      /* Packet error. Enter input-error-stopped state. */
      stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
      stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
      stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC;
      stack->statusInboundErrorPacketCrc++;
      DEBUG_STATE("rx:error-stopped");
    }
  }
  else
  {
    /* Packet has not already started. */
    DEBUG_FRAMING_RX("start=%u", stack->rxAckId);
    handleNewPacketStart(stack);
  }
}
 
 
static void handleEndOfPacket(RioStack_t *stack)
{
  DEBUG_FRAMING_RX("end=%u", stack->rxAckId);
 
  /* Check if the CRC is correct. */
  if(stack->rxCrc == 0x0000u)
  {
    /* The packet has a correct CRC. */
 
    /* Check if the packet is long enough to contain a complete packet. */
    if(stack->rxCounter > 3u)
    {
      /* Packet long enough to process. */
 
      /* Process the newly received packet. */
      handleNewPacketEnd(stack);
    }
    else
    {
      /* The packet has a valid CRC but is too short. */
      /* Packet error. Enter input-error-stopped state. */
      stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
      stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
      stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_GENERAL;
      stack->statusInboundErrorGeneral++;
      DEBUG_STATE("rx:error-stopped");
    }
  }
  else
  {
    /* The packet has an invalid CRC. */
    /* Packet error. Enter input-error-stopped state. */
    stack->txState = TX_STATE_SEND_PACKET_NOT_ACCEPTED;
    stack->rxState = RX_STATE_INPUT_ERROR_STOPPED;
    stack->rxErrorCause = PACKET_NOT_ACCEPTED_CAUSE_PACKET_CRC;
    stack->statusInboundErrorPacketCrc++;
    DEBUG_STATE("rx:error-stopped");
  }
}
 
 
static void handleNewPacketStart(RioStack_t *stack)
{
  /* Check if there are buffers available to store the new frame. */
  if (QueueAvailable(stack->rxQueue) > 0u)
  {
    /* There are buffers available to accept the new packet. */
 
    /* Update the reception counter to indicate the frame has started. */
    stack->rxCounter = 1;
  }
  else
  {
    /* There are no buffers available. */
    /* Go to input retry stopped state. */
    DEBUG_FRAMING_RX("retry=%u", stack->rxAckId);
    stack->statusInboundPacketRetry++;
    stack->txState = TX_STATE_SEND_PACKET_RETRY;
    stack->rxState = RX_STATE_INPUT_RETRY_STOPPED;
    DEBUG_STATE("rx:retry-stopped");
  }
}
 
 
static void handleNewPacketEnd(RioStack_t *stack)
{
  uint32_t *packet;
  uint32_t ftype;
  uint32_t transaction;
 
 
  /* Save the size of the packet. */
  QueueSetSize(stack->rxQueue, (uint32_t)stack->rxCounter - (uint32_t)1ul);
 
  /* Get the packet and information about its type. */
  packet = QueueGetBackBuffer(stack->rxQueue);
  ftype = FTYPE_GET(packet);
  transaction = TRANSACTION_GET(packet);
 
#ifdef RIO_TRANSPARENT
  /* Always forward the packet to the top of the stack. */
  stack->rxQueue = QueueEnqueue(stack->rxQueue);
#else
  /* Check if the packet should be forwarded to the top of the stack. */
  if ((QueueGetBackSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_READ_REQUEST_SIZE) &&
      (ftype == FTYPE_MAINTENANCE) && (transaction == TRANSACTION_MAINT_READ_REQUEST))
  {
    /* Received maintenance read request. */
    /* Send a maintenance read response. This packet is aimed at the stack, it should 
       not be forwarded. */
    /* Note that only single word accesses are supported. */
    RIO_sendMaintenanceReadResponse(stack, SRCID_GET(packet),TID_GET(packet), 0xff,
                                    RIO_readConfig(stack, CONFIG_OFFSET_GET(packet)));
  }
  else if ((QueueGetBackSize(stack->rxQueue) == MAINTENANCE_TRANSACTION_WRITE_REQUEST_SIZE) &&
           (ftype == FTYPE_MAINTENANCE) && (transaction == TRANSACTION_MAINT_WRITE_REQUEST))
  {
    /* Received maintenance write request. */
    /* Send a maintenance write response. This packet is aimed at the stack, it should 
       not be forwarded. */
    /* Note that only single word accesses are supported. */
    RIO_writeConfig(stack, CONFIG_OFFSET_GET(packet),
                    DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0));
    RIO_sendMaintenanceWriteResponse(stack, SRCID_GET(packet), TID_GET(packet), 0xff);
  }
  else
  {
    /* Forward this packet to the top of the stack. */
    stack->rxQueue = QueueEnqueue(stack->rxQueue);
  }
#endif
  /* Reset the reception counter. */
  stack->rxCounter = 0u;
 
  /* Update the ackId for the receiver. */
  stack->rxAckId = ACKID_INC(stack->rxAckId);
 
  /* Update status counter. */
  stack->statusInboundPacketComplete++;
}
 
 
static void handleLinkRequest(RioStack_t *stack, uint8_t cmd)
{
  /* Check the command of the link-request. */
  if(cmd == LINK_REQUEST_INPUT_STATUS)
  {
    /* Input-status requested. */
    /* Return input port status. */
 
    /* Force the transmitter to send a link-response-symbol. */
    stack->txState = TX_STATE_SEND_LINK_RESPONSE;
  }
  else if(cmd == LINK_REQUEST_RESET_DEVICE)
  {
    /* Reset-device requested. */
    /* REMARK: Support this??? */
  }
  else
  {
    /* Unrecognized command. */
    /* Dont do anything. */
  }
 
  /* Always cancel an ongoing frame when a link-request has been received. */
  stack->rxCounter = 0;
 
  /* Receiving this indicates the link partner having encountered a potential problem. */
  /* Count the number of times this happens. */
  stack->statusPartnerLinkRequest++;
}
 
 
static void sendMaintenanceReadRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                        const uint8_t hopCount, const uint32_t offset)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = 0x0018ul << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
  content = ((uint32_t) srcid) << 16;
  content |= (uint32_t) 0x08ul << 8;
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
  content = ((uint32_t) hopCount) << 24;
  content |= offset & (uint32_t) 0x00fffffcul;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* crc(15:0)|pad(15:0) */
  content = ((uint32_t) crc) << 16;
  QueueSetContent(stack->txQueue, 3ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 4ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
static void receiveMaintenanceReadRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                    uint8_t *hopCount, uint32_t *offset)
{
  uint32_t *packet;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
  *hopCount = HOP_GET(packet);
  *offset = CONFIG_OFFSET_GET(packet);
}
 
static void sendMaintenanceReadResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                         const uint8_t hopCount, const uint32_t data)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
 
 
  /* REMARK: What should we do if there are no buffers available to send the packet... */
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = (uint32_t)0x0018ul << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
  content = (uint32_t) srcid << 16;
  content |= (uint32_t) 0x28ul << 8;
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* hopcount(7:0)|reserved(23:0) */
  content = (uint32_t) (hopCount << 24);
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* double-word 0 */
  /* Send the data in both words since this function cannot know the offset the request was sent to. */
  content = data;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 3ul, content);
  content = data;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 4ul, content);
 
  /* crc(15:0)|pad(15:0) */
  content = (uint32_t)crc << 16;
  QueueSetContent(stack->txQueue, 5ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 6ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
static void receiveMaintenanceReadResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                            uint8_t *hopCount, uint32_t *data)
{
  uint32_t *packet;
 
 
  ASSERT((data != NULL), "Buffer is not allocated.");
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
  *hopCount = HOP_GET(packet);
  *data = DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0);
}
 
static void sendMaintenanceWriteRequest( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                         const uint8_t hopCount, const uint32_t offset, const uint32_t data )
{
  uint32_t content;
  uint16_t crc = 0xffffu;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = 0x0018ul << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
  content = ((uint32_t) srcid) << 16;
  content |= (uint32_t)0x18ul << 8;
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* hopcount(7:0)|configOffset(20:0)|wdptr|reserved(1:0) */
  content = ((uint32_t) hopCount) << 24;
  content |= offset & (uint32_t)0x00fffffcul;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* double-word 0 */
  /* Note that both words are filled in to avoid looking at the offset. The receiver will not 
     look at the other part anyway. The standard does not say anything about the value of the padding. */
  content = data;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 3ul, content);
  content = data;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 4ul, content);
 
  /* crc(15:0)|pad(15:0) */
  content = ((uint32_t) crc) << 16;
  QueueSetContent(stack->txQueue, 5ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 6ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
static void receiveMaintenanceWriteRequest( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                            uint8_t *hopCount, uint32_t *offset, uint32_t *data )
{
  uint32_t *packet;
 
 
  ASSERT((data != NULL), "Buffer is not allocated.");
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
  *hopCount = HOP_GET(packet);
  *offset = CONFIG_OFFSET_GET(packet);
  *data = DOUBLE_WORD_MSB_GET(packet, 0) | DOUBLE_WORD_LSB_GET(packet, 0);
}
 
static void sendMaintenanceWriteResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                          const uint8_t hopCount)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
 
 
  /* REMARK: What should we do if there are no buffers available to send the packet... */
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = (uint32_t)0x0018ul << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
  content = (uint32_t) srcid << 16;
  content |= (uint32_t)0x38ul << 8;
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* hopcount(7:0)|reserved(23:0) */
  content = hopCount << 24;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* crc(15:0)|pad(15:0) */
  content = (uint32_t)crc << 16;
  QueueSetContent(stack->txQueue, 3ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 4ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
static void receiveMaintenanceWriteResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                                      uint8_t *hopCount)
{
  uint32_t *packet;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
  *hopCount = HOP_GET(packet);
}
 
/* REMARK: Use a packet pointer instead of using the QueueSetContent... */
static void sendNwrite( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                        const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer, 
                        const uint8_t ack)
{
  uint32_t content;
  uint32_t size;
  uint16_t wrsize = wrsizeGet(address, bufferSize);
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
  ASSERT((wrsize != 0xffff), "Write access unsupported by protocol.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = ((uint32_t)0x0015ul) << 16;
  content |= (uint32_t)destid;
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|wrsize(3:0)|srcTID(7:0) */
  content = ((uint32_t) srcid) << 16;
  if(ack == 0u)
  {
    /* Send NWRITE. */
    content |= (uint32_t) TRANSACTION_WRITE_NWRITE << 12;
  }
  else
  {
    /* Send NWRITE_R. */
    content |= (uint32_t) TRANSACTION_WRITE_NWRITER << 12;
  }
  content |= (uint32_t) (wrsize & 0x0f00); 
  content |= (uint32_t) tid;
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* address(28:0)|wdptr|xamsbs(1:0) */
  /* wrsize also contains wdptr in the lower nibble. */
  /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the 
     34-bit address should be used, another mechanism to set it should be used. */
  content = (address & 0xfffffff8ul);
  content |= ((uint32_t) (wrsize & 0x000f)) << 2;
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* Place data buffer into the payload of the packet. */
  size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 12, address & 0x7, bufferSize, buffer);  
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, size+1);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
static uint16_t receiveNwrite( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,
                               uint32_t *address, const uint16_t dataLength, uint8_t *data )
{
  uint32_t *packet;
  uint8_t offset;
  uint16_t size;
  uint8_t wrsize;
  uint8_t wdptr;
 
 
  ASSERT((data != NULL), "Buffer is not allocated.");
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  wrsize = WRSIZE_GET(packet);
  wdptr = WDPTR_GET(packet);
  wrsizeToOffset(wrsize, wdptr, &offset, &size);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
  *address = ADDRESS_GET(packet) | offset;
 
  if(size > 16)
  {
    /* Remove header and crc from the size count. */
    size = ((QueueGetFrontSize(stack->rxQueue)-4) * 4);
  }
 
  /* Check if there is enough room in the receiving buffer. */
  if(size <= dataLength)
  {
    return getPacketPayload(packet, 12, offset, size, data);
  }
  else
  {
    return 0;
  }
}
 
static void sendNread( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                       const uint32_t address, const uint16_t dataLength)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
  uint16_t rdsize = rdsizeGet(address, dataLength);
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
  ASSERT((rdsize != 0xffff), "Read access unsupported by protocol.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = ((uint32_t) 0x0012ul) << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|rdsize(3:0)|srcTID(7:0) */
  content = ((uint32_t) srcid) << 16;
  content |= ((uint32_t) TRANSACTION_REQUEST_NREAD) << 12;
  content |= (uint32_t) (rdsize & 0x0f00);
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* address(28:0)|wdptr|xamsbs(1:0) */
  /* rdsize also contains wdptr in the lower nibble. */
  /* REMARK: Note that xamsbs cannot be used if the address is a word. If the 2 msb bits in the 
     34-bit address should be used, another mechanism to set it should be used. */
  content = address & 0xfffffff8ul;
  content |= ((uint32_t) (rdsize & 0x000f)) << 2;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* crc(15:0)|pad(15:0) */
  content = ((uint32_t) crc) << 16;
  QueueSetContent(stack->txQueue, 3ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 4ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
static void receiveNread( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                          uint32_t *address, uint16_t *dataLength)
{
  uint32_t *packet;
  uint8_t offset;
  uint16_t size;
  uint8_t rdsize;
  uint8_t wdptr;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  rdsize = WRSIZE_GET(packet);
  wdptr = WDPTR_GET(packet);
  rdsizeToOffset(rdsize, wdptr, &offset, &size);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
  *address = ADDRESS_GET(packet) | offset;
  *dataLength = size;
}
 
static void sendResponseDonePayload( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                                     const uint32_t address, const uint16_t bufferSize, const uint8_t *buffer)
{
  uint32_t content;
  uint32_t size;
 
 
  ASSERT((buffer != NULL), "Buffer is not allocated.");
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = 0x001dul << 16;
  content |= (uint32_t) destid;
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
  content = ((uint32_t) srcid) << 16;
  content |= ((uint32_t) TRANSACTION_RESPONSE_WITH_PAYLOAD) << 12;
  content |= (uint32_t) tid;
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* Place data buffer into the payload of the packet. */
  size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 8, address & 0x7, bufferSize, buffer);  
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, size+1);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
 
static uint16_t receiveResponseDonePayload( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid,  
                                            const uint32_t address, const uint16_t dataLength, uint8_t *data )
{
  uint32_t *packet;
 
 
  ASSERT((data != NULL), "Buffer is not allocated.");
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
 
  return getPacketPayload(packet, 8, address & 0x7, dataLength, data);
}
 
 
static void sendResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                          const uint8_t status)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = (uint32_t)0x001dul << 16;
  content |= destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|targetTID(7:0) */
  content = (uint32_t)srcid << 16;
  content |= ((uint32_t)status & (uint32_t)0x0ful) << 8;
  content |= tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* crc(15:0)|pad(15:0) */
  content = (uint32_t)crc << 16;
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 3ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
 
static void receiveResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid)
{
  uint32_t *packet;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
}
 
 
static void sendDoorbell( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t tid, 
                          const uint16_t info )
{
  uint32_t content;
  uint16_t crc;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = 0x001aul << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, 0xffffu);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */
  content = ((uint32_t) srcid) << 16;
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
  content = ((uint32_t) info) << 16;
  crc = Crc16(info, crc);
  content |= crc;
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 3ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
 
static void receiveDoorbell( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *tid, 
                             uint16_t *info)
{
  uint32_t *packet;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *tid = TID_GET(packet);
  *info = INFO_GET(packet);
}
 
 
static void sendMessage( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, 
                         const uint16_t bufferSize, const uint8_t* bufferData)
{
  uint32_t content;
  uint32_t size;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
  ASSERT((bufferSize <= 256), "Packet sizes larger than 256 are currently unsupported.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = ((uint32_t) 0x001bul) << 16;
  content |= (uint32_t) destid;
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|msglen(3:0)|ssize(3:0)|letter(1:0|mbox(1:0)|xmbox(3:0) */
  content = ((uint32_t) srcid) << 16;
  if(bufferSize <= 8u)
  {
    content |= ((uint32_t) 0x09ul) << 8;
  }
  else if(bufferSize <= 16u)
  {
    content |= ((uint32_t) 0x0aul) << 8;
  }
  else if(bufferSize <= 32u)
  {
    content |= ((uint32_t) 0x0bul) << 8;
  }
  else if(bufferSize <= 64u)
  {
    content |= ((uint32_t) 0x0cul) << 8;
  }
  else if(bufferSize <= 128u)
  {
    content |= ((uint32_t) 0x0dul) << 8;
  }
  else
  {
    content |= ((uint32_t) 0x0eul) << 8;
  }
  content |= ((uint32_t)mailbox & (uint32_t)0xfu) << 4;
  content |= ((uint32_t)mailbox) >> 4;
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* Place data buffer into the payload of the packet. */
  size = setPacketPayload(QueueGetBackBuffer(stack->txQueue), 8, 0, bufferSize, bufferData);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, size+1);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
static uint16_t receiveMessage( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox, 
                                const uint16_t dataLength, uint8_t *data )
{
  uint32_t *packet;
  uint32_t size;
 
 
  ASSERT((data != NULL), "Buffer is not allocated.");
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  /* Get a pointer to the packet. */
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  /* The higher mailbox numbers are used with messages that cannot be multi-packets. */
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *mailbox = XMBOX_GET(packet);
  *mailbox <<= 2;
  *mailbox |= LETTER_GET(packet);
  *mailbox <<= 2;
  *mailbox |= MBOX_GET(packet);
 
  /* Calculate the number of bytes to transfer. */
  /* Remove the header and crc from the size count. */
  size = (QueueGetFrontSize(stack->rxQueue)-3) * 4;
 
  /* Check if there is enough room in the receiving buffer. */
  if(size <= dataLength)
  {
    return getPacketPayload(packet, 8, 0, size, data);
  }
  else
  {
    return 0;
  }
 
}
 
static void sendMessageResponse( RioStack_t *stack, const uint16_t destid, const uint16_t srcid, const uint8_t mailbox, 
                                 const uint8_t status)
{
  uint32_t content;
  uint16_t crc = 0xffffu;
 
 
  ASSERT((QueueAvailable(stack->txQueue) > 0u), "Transmission queue packet overflow.");
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = (uint32_t)0x001dul << 16;
  content |= destid;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 0ul, content);
 
  /* sourceId(15:0)|transaction(3:0)|status(3:0)|letter(1:0|mbox(1:0)|msgseg(3:0) */
  content = (uint32_t)srcid << 16;
  content |= (uint32_t)0x1ul << 12;
  content |= ((uint32_t)status & (uint32_t)0xful) << 8;
  content |= ((uint32_t)mailbox & (uint32_t)0xful) << 4;
  content |= ((uint32_t)mailbox) >> 4;
  crc = Crc32(content, crc);
  QueueSetContent(stack->txQueue, 1ul, content);
 
  /* crc(15:0)|pad(15:0) */
  content = (uint32_t)crc << 16;
  QueueSetContent(stack->txQueue, 2ul, content);
 
  /* Set the size of the packet and place it in the queue. */
  QueueSetSize(stack->txQueue, 3ul);
  stack->txQueue = QueueEnqueue(stack->txQueue);
}
 
static void receiveMessageResponse( RioStack_t *stack, uint16_t *destid, uint16_t *srcid, uint8_t *mailbox)
{
  uint32_t *packet;
 
 
  ASSERT(!QueueEmpty(stack->rxQueue), "Reading from empty reception queue.");
 
  packet = QueueGetFrontBuffer(stack->rxQueue);
 
  *destid = DESTID_GET(packet);
  *srcid = SRCID_GET(packet);
  *mailbox = XMBOX_GET(packet);
  *mailbox <<= 2;
  *mailbox |= LETTER_GET(packet);
  *mailbox <<= 2;
  *mailbox |= MBOX_GET(packet);
}
 
 
static uint16_t getPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset, 
                                 const uint16_t dataSize, uint8_t *data)
{
  uint32_t content = 0;
  uint16_t packetIndex;
  uint16_t payloadIndex;
  uint16_t dataIndex;
 
 
  /* Move bytes from inbound packet queue into the user buffer. */
  /* Long packets contain a CRC in byte 80-81, this is removed when the buffer 
     is copied. */
  packetIndex = payloadOffset;
  payloadIndex = 0;
  dataIndex = 0;
  while(dataIndex < dataSize)
  {
    /* Check if a new word should be read from the inbound queue. */
    if((packetIndex & 0x3) == 0)
    {
      /* Get a new word. */
      content = packet[packetIndex>>2];
    }
    else
    {
      /* Update the current word. Remove the MSB, it has already be moved 
         to the user buffer. */
      content <<= 8;
    }
 
    /* Check if the current byte is CRC. */
    if((packetIndex != 80) && (packetIndex != 81) && (payloadIndex >= dataOffset))
    {
      /* Not CRC. */
      /* Move the byte to the user buffer. */
      data[dataIndex++] = (content >> 24);
    }
 
    /* Increment to the next position in the packet. */
    packetIndex++;
    payloadIndex++;
  }
 
  return dataIndex;
}
 
 
static uint16_t setPacketPayload(uint32_t *packet, const uint16_t payloadOffset, const uint16_t dataOffset, 
                                 const uint16_t dataSize, const uint8_t *data)
{
  uint16_t crc = 0xffffu;
  uint32_t content = 0;
  uint16_t packetIndex;
  uint16_t payloadIndex;
  uint16_t dataIndex;
 
 
  /***************************************************
   * Calculate the CRC for the packet header.
   ***************************************************/
  for(packetIndex = 0; packetIndex < payloadOffset; packetIndex+=4)
  {
    crc = Crc32(packet[packetIndex>>2], crc);
  }
 
  /***************************************************
   * Pad the data before the actual data is written.
   ***************************************************/
  payloadIndex = 0;
  while(payloadIndex < dataOffset)
  {
    content <<= 8;
 
    if((packetIndex & 0x3) == 3)
    {
      crc = Crc32(content, crc);
      packet[packetIndex>>2] = content;
    }
 
    payloadIndex++;
    packetIndex++;
  }
 
  /***************************************************
   * Write content and any embedded CRC.
   ***************************************************/
  dataIndex = 0;
  while(dataIndex < dataSize)
  {
    content <<= 8;
 
    /* Check if CRC or content should be entered into the packet. */
    if(packetIndex == 80)
    {
      /* CRC MSB. */
      content |= crc >> 8;
    }
    else if(packetIndex == 81)
    {
      /* CRC LSB. */
      content |= crc & 0xff;
    }
    else
    {
      /* Data content. */
      content |= data[dataIndex++];
      payloadIndex++;
    }
 
    if((packetIndex & 0x3) == 3)
    {
      crc = Crc32(content, crc);
      packet[packetIndex>>2] = content;
    }
 
    packetIndex++;
  }
 
  /***************************************************
   * Pad the data to an even double word.
   ***************************************************/
  while((payloadIndex & 0x7) != 0)
  {
    content <<= 8;
 
    if((packetIndex & 0x3) == 3)
    {
      crc = Crc32(content, crc);
      packet[packetIndex>>2] = content;
    }
 
    packetIndex++;
    payloadIndex++;
  }
 
  /***************************************************
   * Write the CRC into the packet.
   ***************************************************/
  if((packetIndex & 0x3) == 0)
  {
    /* crc(15:0)|pad(15:0) */
    content = ((uint32_t) crc) << 16;
  }
  else
  {
    /* double-wordN-LSB|crc(15:0) */
    content &= 0x0000ffff;
    crc = Crc16(content, crc);
    content <<= 16;
    content |= crc;
  }
  packet[packetIndex>>2] = content;
 
  return (packetIndex>>2);
}
 
 
/* \note See the RapidIO standard part1 table 4-4 for details about 
 * {address, size}->{wdptr, wrsize} mapping.
 */
static uint16_t rdsizeGet(const uint32_t address, const uint16_t size)
{
  uint8_t wdptr;
  uint8_t rdsize;
 
 
  switch(size/8)
  {
    case 0:
      /**************************************************************
       * Sub double-word access.
       **************************************************************/
      /* REMARK: The same code as in wrsizeGet for sub 
         double-word... use it instead??? */
      switch(size%8)
      {
        case 0:
          /* Not supported by protocol. */
          wdptr = 0xff;
          rdsize = 0xff;
          break;
        case 1:
          /* Reading one byte. */
          /* Any address is allowed. */
          wdptr = (address >> 2) & 0x1;
          rdsize = address & 0x3;
          break;
        case 2:
          /* Reading two bytes. */
          /* Address 0, 2, 4, 6 are valid. */
          if((address & 0x1) == 0)
          {
            wdptr = (address >> 2) & 0x1;
            rdsize = (address & 0x7) | 0x4;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            rdsize = 0xff;
          }
          break;
        case 3:
          /* Reading 3 bytes. */
          /* Address 0 and 5 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 5))
          {
            wdptr = (address >> 2) & 0x1;
            rdsize = 0x5ul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            rdsize = 0xff;
          }
          break;
        case 4:
          /* Reading 4 bytes. */
          /* Address 0 and 4 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 4))
          {
            wdptr = (address >> 2) & 0x1;
            rdsize = 0x8ul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            rdsize = 0xff;
          }
          break;
        case 5:
          /* Reading 5 bytes. */
          /* Address 0 and 3 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 3))
          {
            wdptr = (address >> 1) & 0x1;
            rdsize = 0x7ul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            rdsize = 0xff;
          }
          break;
        case 6:
          /* Reading 6 bytes. */
          /* Addresses 0 and 2 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 2))
          {
            wdptr = (address >> 1) & 0x1;
            rdsize = 0x9ul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            rdsize = 0xff;
          }
          break;
        default:
          /* Reading 7 bytes. */
          /* Addresses 0 and 1 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 1))
          {
            wdptr = address & 0x1;
            rdsize = 0xaul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            rdsize = 0xff;
          }
          break;
      }
      break;
    case 1:
      /* Reading 8 bytes. */
      /* Only even double-word address are valid. */
      if((address % 8) == 0)
      {
        wdptr = 0;
        rdsize = 0xbul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 2:
      /* Reading 16 bytes max. */
      /* Only even double-word address are valid. */
      if((address % 8) == 0)
      {
        wdptr = 1;
        rdsize = 0xbul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 3:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
    case 4:
      /* Reading 32 bytes max. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 0;
        rdsize = 0xcul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 5:
    case 6:
    case 7:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
    case 8:
      /* Reading 64 bytes max. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 1;
        rdsize = 0xcul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 9:
    case 10:
    case 11:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
    case 12:
      /* Reading 96 bytes. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 0;
        rdsize = 0xdul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 13:
    case 14:
    case 15:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
    case 16:
      /* Reading 128 bytes max. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 1;
        rdsize = 0xdul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 17:
    case 18:
    case 19:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
    case 20:
      /* Reading 160 bytes. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 0;
        rdsize = 0xeul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 21:
    case 22:
    case 23:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
    case 24:
      /* Reading 192 bytes. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 1;
        rdsize = 0xeul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 25:
    case 26:
    case 27:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
    case 28:
      /* Reading 224 bytes. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 0;
        rdsize = 0xful;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    case 29:
    case 30:
    case 31:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
    case 32:
      /* Reading 256 bytes max. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 1;
        rdsize = 0xful;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        rdsize = 0xff;
      }
      break;
    default:
      /* Not supported by protocol. */
      wdptr = 0xff;
      rdsize = 0xff;
      break;
  }
 
  return ((((uint16_t) rdsize) << 8) | ((uint16_t) wdptr));
}
 
 
void rdsizeToOffset(uint8_t rdsize, uint8_t wdptr, uint8_t *offset, uint16_t *size)
{
  switch(rdsize)
  {
    case 0:
    case 1:
    case 2:
    case 3:
      *offset = wdptr << 2;
      *offset |= rdsize;
      *size = 1;
      break;
    case 4:
    case 6:
      *offset = wdptr << 2;
      *offset |= rdsize & 0x02;
      *size = 2;
      break;
    case 5:
      *offset = wdptr * 5;
      *size = 3;
      break;
    case 8:
      *offset = wdptr * 4;
      *size = 4;
      break;
    case 7:
      *offset = wdptr * 3;
      *size = 5;
      break;
    case 9:
      *offset = wdptr * 2;
      *size = 6;
      break;
    case 10:
      *offset = wdptr * 1;
      *size = 7;
      break;
    case 11:
      *offset = 0;
      *size = 8 + 8*wdptr;
      break;
    case 12:
      *offset = 0;
      *size = 32 + 32*wdptr;
      break;
    case 13:
      *offset = 0;
      *size = 96 + 32*wdptr;
      break; 
    case 14:
      *offset = 0;
      *size = 160 + 32*wdptr;
      break;
    case 15:
      *offset = 0;
      *size = 224 + 32*wdptr;
      break;
  }
}
 
 
static uint16_t wrsizeGet(const uint32_t address, const uint16_t size)
{
  uint8_t wdptr;
  uint8_t wrsize;
 
 
  switch(size/8)
  {
    case 0:
      /**************************************************************
       * Sub double-word access.
       **************************************************************/
      switch(size%8)
      {
        case 0:
          /* Not supported by protocol. */
          wdptr = 0xff;
          wrsize = 0xff;
          break;
        case 1:
          /* Writing one byte. */
          /* Any address is allowed. */
          wdptr = (address >> 2) & 0x1;
          wrsize = address & 0x3;
          break;
        case 2:
          /* Writing two bytes. */
          /* Address 0, 2, 4, 6 are valid. */
          if((address & 0x1) == 0)
          {
            wdptr = (address >> 2) & 0x1;
            wrsize = (address & 0x7) | 0x4;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            wrsize = 0xff;
          }
          break;
        case 3:
          /* Writing 3 bytes. */
          /* Address 0 and 5 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 5))
          {
            wdptr = (address >> 2) & 0x1;
            wrsize = 0x5ul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            wrsize = 0xff;
          }
          break;
        case 4:
          /* Writing 4 bytes. */
          /* Address 0 and 4 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 4))
          {
            wdptr = (address >> 2) & 0x1;
            wrsize = 0x8ul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            wrsize = 0xff;
          }
          break;
        case 5:
          /* Writing 5 bytes. */
          /* Address 0 and 3 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 3))
          {
            wdptr = (address >> 1) & 0x1;
            wrsize = 0x7ul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            wrsize = 0xff;
          }
          break;
        case 6:
          /* Writing 6 bytes. */
          /* Addresses 0 and 2 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 2))
          {
            wdptr = (address >> 1) & 0x1;
            wrsize = 0x9ul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            wrsize = 0xff;
          }
          break;
        default:
          /* Writing 7 bytes. */
          /* Addresses 0 and 1 are valid. */
          if(((address & 0x7) == 0) ||
             ((address & 0x7) == 1))
          {
            wdptr = address & 0x1;
            wrsize = 0xaul;
          }
          else
          {
            /* Not supported by protocol. */
            wdptr = 0xff;
            wrsize = 0xff;
          }
          break;
      }
      break;
    case 1:
      /* Writing 8 bytes. */
      /* Only even double-word address are valid. */
      if((address % 8) == 0)
      {
        wdptr = 0;
        wrsize = 0xbul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        wrsize = 0xff;
      }
      break;
    case 2:
      /* Writing 16 bytes max. */
      /* Only even double-word address are valid. */
      if((address % 8) == 0)
      {
        wdptr = 1;
        wrsize = 0xbul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        wrsize = 0xff;
      }
      break;
    case 3:
    case 4:
      /* Writing 32 bytes max. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 0;
        wrsize = 0xcul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        wrsize = 0xff;
      }
      break;
    case 5:
    case 6:
    case 7:
    case 8:
      /* Writing 64 bytes max. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 1;
        wrsize = 0xcul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        wrsize = 0xff;
      }
      break;
    case 9:
    case 10:
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
    case 16:
      /* Writing 128 bytes max. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 1;
        wrsize = 0xdul;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        wrsize = 0xff;
      }
      break;
    case 17:
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
    case 24:
    case 25:
    case 26:
    case 27:
    case 28:
    case 29:
    case 30:
    case 31:
    case 32:
      /* Writing 256 bytes max. */
      /* Only even double-word address are valid. */
      if((address & 0x7) == 0)
      {
        wdptr = 1;
        wrsize = 0xful;
      }
      else
      {
        /* Not supported by protocol. */
        wdptr = 0xff;
        wrsize = 0xff;
      }
      break;
    default:
      /* Not supported by protocol. */
      wdptr = 0xff;
      wrsize = 0xff;
      break;
  }
 
  return ((((uint16_t) wrsize) << 8) | ((uint16_t) wdptr));
}
 
 
void wrsizeToOffset(uint8_t wrsize, uint8_t wdptr, uint8_t *offset, uint16_t *size)
{
  switch(wrsize)
  {
    case 0:
    case 1:
    case 2:
    case 3:
      *offset = wdptr << 2;
      *offset |= wrsize;
      *size = 1;
      break;
    case 4:
    case 6:
      *offset = wdptr << 2;
      *offset |= wrsize & 0x02;
      *size = 2;
      break;
    case 5:
      *offset = wdptr * 5;
      *size = 3;
      break;
    case 8:
      *offset = wdptr * 4;
      *size = 4;
      break;
    case 7:
      *offset = wdptr * 3;
      *size = 5;
      break;
    case 9:
      *offset = wdptr * 2;
      *size = 6;
      break;
    case 10:
      *offset = wdptr * 1;
      *size = 7;
      break;
    case 11:
      *offset = 0;
      *size = 8 + 8*wdptr;
      break;
    case 12:
      *offset = 0;
      *size = 32 + 32*wdptr;
      break;
    case 13:
      *offset = 0;
      *size = 128*wdptr;
      break;
    case 14:
      *offset = 0;
      *size = 0;
      break;
    case 15:
      *offset = 0;
      *size = 256*wdptr;
      break;
  }
}
 
 
static RioSymbol CreateControlSymbol( const uint8_t stype0,
				      const uint8_t parameter0, const uint8_t parameter1,
                                      const uint8_t stype1, const uint8_t cmd)
{
  RioSymbol s;
 
  s.type = RIO_SYMBOL_TYPE_CONTROL;
 
  s.data = ((uint32_t)stype0 & (uint32_t)0x07ul) << 21;
  s.data |= ((uint32_t)parameter0 & (uint32_t)0x1ful) << 16;
  s.data |= ((uint32_t)parameter1 & (uint32_t)0x1ful) << 11;
  s.data |= ((uint32_t)stype1 & (uint32_t)0x07ul) << 8;
  s.data |= ((uint32_t)cmd & (uint32_t)0x7ul) << 5;
  s.data |= Crc5(s.data, 0x1fu);
 
  return s;
}
 
 
static uint8_t Crc5( const uint32_t data, const uint8_t crc)
{
  static const uint8_t crcTable[] = {
    0x00u, 0x15u, 0x1fu, 0x0au, 0x0bu, 0x1eu, 0x14u, 0x01u,
    0x16u, 0x03u, 0x09u, 0x1cu, 0x1du, 0x08u, 0x02u, 0x17u,
    0x19u, 0x0cu, 0x06u, 0x13u, 0x12u, 0x07u, 0x0du, 0x18u,
    0x0fu, 0x1au, 0x10u, 0x05u, 0x04u, 0x11u, 0x1bu, 0x0eu
  };
 
  uint8_t result;
  uint8_t index;
 
  result = crc;
  index  = (uint8_t)((data >> 19) & (uint32_t)0x1ful) ^ result;
  result = crcTable[index];
  index  = (uint8_t)((data >> 14) & (uint32_t)0x1ful) ^ result;
  result = crcTable[index];
  index  = (uint8_t)((data >> 9) & (uint32_t)0x1ful) ^ result;
  result = crcTable[index];
  index  = (uint8_t)((data >> 4) & (uint32_t)0x1eul) ^ result;
  result = crcTable[index];
 
  return result;
}
 
 
static uint16_t Crc16( const uint16_t data, const uint16_t crc)
{
  static const uint16_t crcTable[] = {
    0x0000u, 0x1021u, 0x2042u, 0x3063u, 0x4084u, 0x50a5u, 0x60c6u, 0x70e7u,
    0x8108u, 0x9129u, 0xa14au, 0xb16bu, 0xc18cu, 0xd1adu, 0xe1ceu, 0xf1efu,
    0x1231u, 0x0210u, 0x3273u, 0x2252u, 0x52b5u, 0x4294u, 0x72f7u, 0x62d6u,
    0x9339u, 0x8318u, 0xb37bu, 0xa35au, 0xd3bdu, 0xc39cu, 0xf3ffu, 0xe3deu,
    0x2462u, 0x3443u, 0x0420u, 0x1401u, 0x64e6u, 0x74c7u, 0x44a4u, 0x5485u,
    0xa56au, 0xb54bu, 0x8528u, 0x9509u, 0xe5eeu, 0xf5cfu, 0xc5acu, 0xd58du,
    0x3653u, 0x2672u, 0x1611u, 0x0630u, 0x76d7u, 0x66f6u, 0x5695u, 0x46b4u,
    0xb75bu, 0xa77au, 0x9719u, 0x8738u, 0xf7dfu, 0xe7feu, 0xd79du, 0xc7bcu,
    0x48c4u, 0x58e5u, 0x6886u, 0x78a7u, 0x0840u, 0x1861u, 0x2802u, 0x3823u,
    0xc9ccu, 0xd9edu, 0xe98eu, 0xf9afu, 0x8948u, 0x9969u, 0xa90au, 0xb92bu,
    0x5af5u, 0x4ad4u, 0x7ab7u, 0x6a96u, 0x1a71u, 0x0a50u, 0x3a33u, 0x2a12u,
    0xdbfdu, 0xcbdcu, 0xfbbfu, 0xeb9eu, 0x9b79u, 0x8b58u, 0xbb3bu, 0xab1au,
    0x6ca6u, 0x7c87u, 0x4ce4u, 0x5cc5u, 0x2c22u, 0x3c03u, 0x0c60u, 0x1c41u,
    0xedaeu, 0xfd8fu, 0xcdecu, 0xddcdu, 0xad2au, 0xbd0bu, 0x8d68u, 0x9d49u,
    0x7e97u, 0x6eb6u, 0x5ed5u, 0x4ef4u, 0x3e13u, 0x2e32u, 0x1e51u, 0x0e70u,
    0xff9fu, 0xefbeu, 0xdfddu, 0xcffcu, 0xbf1bu, 0xaf3au, 0x9f59u, 0x8f78u,
    0x9188u, 0x81a9u, 0xb1cau, 0xa1ebu, 0xd10cu, 0xc12du, 0xf14eu, 0xe16fu,
    0x1080u, 0x00a1u, 0x30c2u, 0x20e3u, 0x5004u, 0x4025u, 0x7046u, 0x6067u,
    0x83b9u, 0x9398u, 0xa3fbu, 0xb3dau, 0xc33du, 0xd31cu, 0xe37fu, 0xf35eu,
    0x02b1u, 0x1290u, 0x22f3u, 0x32d2u, 0x4235u, 0x5214u, 0x6277u, 0x7256u,
    0xb5eau, 0xa5cbu, 0x95a8u, 0x8589u, 0xf56eu, 0xe54fu, 0xd52cu, 0xc50du,
    0x34e2u, 0x24c3u, 0x14a0u, 0x0481u, 0x7466u, 0x6447u, 0x5424u, 0x4405u,
    0xa7dbu, 0xb7fau, 0x8799u, 0x97b8u, 0xe75fu, 0xf77eu, 0xc71du, 0xd73cu,
    0x26d3u, 0x36f2u, 0x0691u, 0x16b0u, 0x6657u, 0x7676u, 0x4615u, 0x5634u,
    0xd94cu, 0xc96du, 0xf90eu, 0xe92fu, 0x99c8u, 0x89e9u, 0xb98au, 0xa9abu,
    0x5844u, 0x4865u, 0x7806u, 0x6827u, 0x18c0u, 0x08e1u, 0x3882u, 0x28a3u,
    0xcb7du, 0xdb5cu, 0xeb3fu, 0xfb1eu, 0x8bf9u, 0x9bd8u, 0xabbbu, 0xbb9au,
    0x4a75u, 0x5a54u, 0x6a37u, 0x7a16u, 0x0af1u, 0x1ad0u, 0x2ab3u, 0x3a92u,
    0xfd2eu, 0xed0fu, 0xdd6cu, 0xcd4du, 0xbdaau, 0xad8bu, 0x9de8u, 0x8dc9u,
    0x7c26u, 0x6c07u, 0x5c64u, 0x4c45u, 0x3ca2u, 0x2c83u, 0x1ce0u, 0x0cc1u,
    0xef1fu, 0xff3eu, 0xcf5du, 0xdf7cu, 0xaf9bu, 0xbfbau, 0x8fd9u, 0x9ff8u,
    0x6e17u, 0x7e36u, 0x4e55u, 0x5e74u, 0x2e93u, 0x3eb2u, 0x0ed1u, 0x1ef0u
  };
 
  uint16_t result;
  uint8_t index;
 
  result = crc;
  index = (uint8_t) ((data >> 8)  ^ (result >> 8));
  result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8));
  index = (uint8_t) ((data)  ^ (result >> 8));
  result = (uint16_t) (crcTable[index] ^ (uint16_t)(result << 8));
 
  return result;
}
 
 
static uint16_t Crc32( const uint32_t data, uint16_t crc)
{
  crc = Crc16((uint16_t) (data >> 16), crc);
  crc = Crc16((uint16_t) (data), crc);
  return crc;
}
 
 
 
 
 
static Queue_t QueueCreate( const uint8_t size, uint32_t *buffer)
{
  Queue_t q;
 
  q.size = size;
  q.available = size;
  q.windowSize = 0u;
  q.windowIndex = 0u;
  q.frontIndex = 0u;
  q.backIndex = 0u;
  q.buffer_p = buffer;
 
  return q;
}
 
 
static uint8_t QueueAvailable( const Queue_t q)
{
  return q.available;
}
 
 
static bool_t QueueEmpty( const Queue_t q)
{
  return (bool_t) (q.available == q.size);
}
 
 
static uint8_t QueueLength( const Queue_t q)
{
  return q.size - q.available;
}
 
 
static Queue_t QueueEnqueue( Queue_t q)
{
  q.backIndex++;
  if(q.backIndex == q.size)
  {
    q.backIndex = 0;
  }
  q.available--;
  return q;
}
 
 
static Queue_t QueueDequeue( Queue_t q)
{
  q.frontIndex++;
  if(q.frontIndex == q.size)
  {
    q.frontIndex = 0;
  }
  q.available++;
  if(q.windowSize == 0)
  {
    q.windowIndex = q.frontIndex;
  }
  else
  {
    q.windowSize--;
  }
  return q;
}
 
 
static bool_t QueueWindowEmpty( const Queue_t q)
{
  return (bool_t) ((q.available + q.windowSize) == q.size);
}
 
 
static Queue_t QueueWindowReset(Queue_t q)
{
  q.windowIndex = q.frontIndex;
  q.windowSize = 0;
  return q;
}
 
 
static Queue_t QueueWindowNext(Queue_t q)
{
  q.windowIndex++;
  if(q.windowIndex == q.size)
  {
    q.windowIndex = 0;
  }
  q.windowSize++;
  return q;
}
 
 
static void QueueSetSize( Queue_t q, const uint32_t size)
{
  (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0] = size;
}
 
 
static void QueueSetContent( Queue_t q, const uint32_t index, const uint32_t content)
{
  (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[index+1ul] = content;
}
 
 
static uint32_t QueueGetFrontSize( Queue_t q)
{
  return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[0];
}
 
 
static uint32_t QueueGetFrontContent( const Queue_t q, const uint32_t index)
{
  return (q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[index+1ul];
}
 
 
static uint32_t *QueueGetFrontBuffer( const Queue_t q )
{
  return &((q.buffer_p+(RIO_BUFFER_SIZE*q.windowIndex))[1]);
}
 
 
static uint32_t QueueGetBackSize( const Queue_t q)
{
  return (q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[0];
}
 
 
static uint32_t *QueueGetBackBuffer( const Queue_t q )
{
  return &((q.buffer_p+(RIO_BUFFER_SIZE*q.backIndex))[1]);
}
 
 
#ifdef MODULE_TEST
#include <stdio.h>
#define PrintS(s)                                \
  {                                               \
    FILE *fd;                                     \
    fd=fopen("testspec.txt", "a");                \
    fputs(s "\n", fd);                                 \
    fclose(fd);                                   \
  }
 
#define TESTSTART(s) printf(s)
#define TESTEND printf(" passed.\n");
 
#define TESTCOND(got)                           \
  if (!(got))                                   \
  {                                             \
    printf("ERROR at line %u:%s=%u (0x%08x)\n", \
           __LINE__, #got, (got), (got));       \
    exit(1);                                    \
  }
 
#define TESTEXPR(got, expected)                                         \
  if ((got)!=(expected))                                                \
  {                                                                     \
    printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n",    \
           __LINE__, #got, (got), (got), (expected), (expected));       \
    exit(1);                                                            \
  }
 
#define TESTSYMBOL(got, expected) testSymbol(__LINE__, #got, (got), (expected))
 
void testSymbol(uint32_t line, char *expression, RioSymbol got, RioSymbol expected)
{
  if ((got).type==(expected).type)                                      
  {                                                                     
    switch ((got).type)                                                 
    {                                                                   
      case RIO_SYMBOL_TYPE_ERROR:
      case RIO_SYMBOL_TYPE_IDLE:                                        
        break;                                                          
      case RIO_SYMBOL_TYPE_CONTROL:                                     
        if((got).data != (expected).data)                               
        {                                                               
          if(STYPE0_GET((got).data) != STYPE0_GET((expected).data))     
          {                                                             
            printf("ERROR at line %u:STYPE0=0x%02x expected=0x%02x\n",  
                   line, STYPE0_GET((got).data), STYPE0_GET((expected).data)); 
          }                                                             
          if(PARAMETER0_GET((got).data) != PARAMETER0_GET((expected).data)) 
          {                                                             
            printf("ERROR at line %u:PARAMETER0=0x%02x expected=0x%02x\n", 
                   line, PARAMETER0_GET((got).data), PARAMETER0_GET((expected).data)); 
          }                                                             
          if(PARAMETER1_GET((got).data) != PARAMETER1_GET((expected).data)) 
          {                                                             
            printf("ERROR at line %u:PARAMETER1=0x%02x expected=0x%02x\n", 
                   line, PARAMETER1_GET((got).data), PARAMETER1_GET((expected).data)); 
          }                                                             
          if(STYPE1_GET((got).data) != STYPE1_GET((expected).data))     
          {                                                             
            printf("ERROR at line %u:STYPE1=0x%02x expected=0x%02x\n",  
                   line, STYPE1_GET((got).data), STYPE1_GET((expected).data)); 
          }                                                             
          if(CMD_GET((got).data) != CMD_GET((expected).data))           
          {                                                             
            printf("ERROR at line %u:CMD=0x%02x expected=0x%02x\n",     
                   line, CMD_GET((got).data), CMD_GET((expected).data)); 
          }                                                             
          if(CRC5_GET((got).data) != CRC5_GET((expected).data))         
          {                                                             
            printf("ERROR at line %u:CRC5=0x%02x expected=0x%02x\n",    
                   line, CRC5_GET((got).data), CRC5_GET((expected).data)); 
          }                                                             
          exit(1);
        }                                                               
        break;                                                          
      case RIO_SYMBOL_TYPE_DATA:                                        
        if((got).data != (expected).data)                               
        {                                                               
          printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", 
                 line, expression, (got).data, (got).data, (expected).data, (expected).data); 
          exit(1);
        }                                                               
        break;                                                          
    }    
  }
  else
  {
    printf("ERROR at line %u:%s=%u (0x%08x) expected=%u (0x%08x)\n", 
           line, expression, (got).type, (got).type, (expected).type, (expected).type); 
    exit(1);
  }
}
 
 
 
uint32_t testConfigWriteData;
 
uint8_t createDoorbell(uint32_t *doorbell, uint8_t ackId, uint16_t destid, uint16_t srcId, uint8_t tid, uint16_t info)
{
  uint16_t crc;
  uint32_t content;
 
  /* ackId(4:0)|0|vc|crf|prio(1:0)|tt(1:0)|ftype(3:0)|destinationId(15:0) */
  /* ackId is set when the packet is transmitted. */
  content = 0x001aul << 16;
  content |= (uint32_t) destid;
  crc = Crc32(content, 0xffffu);
  doorbell[0] = (((uint32_t) ackId) << 27) | content;
 
  /* sourceId(15:0)|rsrv(7:0)|srcTID(7:0) */
  content = ((uint32_t) srcId) << 16;
  content |= (uint32_t) tid;
  crc = Crc32(content, crc);
  doorbell[1] = content;
 
  /* infoMSB(7:0)|infoLSB(7:0)|crc(15:0) */
  content = ((uint32_t) info) << 16;
  crc = Crc16(info, crc);
  content |= ((uint32_t) crc);
  doorbell[2] = content;
 
  return 3;
 
}
 
uint32_t testConfigRead(RioStack_t *stack, uint32_t offset)
{
  switch(offset)
  {
    case 0:
      return 0x80000006;
    case 4:
      return 0x00a100a2;
    case 8:
      return testConfigWriteData;
    default:
      return 0x00000000;
  }
}
 
void testConfigWrite(RioStack_t *stack, uint32_t offset, uint32_t data)
{
  switch(offset)
  {
    case 8:
      testConfigWriteData = data;
      break;
    default:
      /* Dont do anything. */
      break;
  }
}
 
/*******************************************************************************
 * Module test for this file.
 *******************************************************************************/
int32_t main(void)
{
  RioStack_t stack;
  RioStackObserver_t observer;
  uint32_t rxPacketBuffer[RIO_BUFFER_SIZE*8], txPacketBuffer[RIO_BUFFER_SIZE*8];
  RioSymbol s, c, d;
  int i, j, k;
  uint16_t length;
  uint16_t srcid;
  uint8_t tid;
  uint8_t hop;
  uint8_t mailbox;
  uint16_t info;
  uint32_t address;
  uint32_t data;
  uint8_t payload8[256];
  uint8_t payload8Expected[256];
  uint32_t packet[69];
  uint32_t packetLength;
 
 
  /*************************************************************************
   * Test prelude.
   * Setup the RIO stack for operation.
   *************************************************************************/
 
  /* Setup callback handlers for config-space accesses in the implementation- 
     defined address range. */
  observer.configRead = testConfigRead;
  observer.configWrite = testConfigWrite;
 
  /* Open the stack and set the port status to initialized. */
  RIO_open(&stack, &observer, NULL,
           RIO_BUFFER_SIZE*8, &rxPacketBuffer[0],
           RIO_BUFFER_SIZE*8, &txPacketBuffer[0],
           0xb03b, 0x0000, 0x00000000, 0x0000, 0x0000, 0x0000, 0xffff);
 
  /* Set the port timeout. */
  RIO_portSetTimeout(&stack, 1);
 
  /* Set the current port time. */
  RIO_portSetTime(&stack, 0);
 
  /* Set master enable. */
  RIO_writeConfig(&stack, 
                  PORT_GENERAL_CONTROL_CSR(EXTENDED_FEATURES_OFFSET), 0x40000000);
 
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack");
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC1");
  PrintS("Description: Test link initialization and normal packet exchange.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send packets when port is uninitialized.");
  PrintS("Result: All packets should be ignored during initialization.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step1");
  /******************************************************************************/
 
  /* Place a packet in the outbound queue to check that it is received once 
     the transmitter is placed in the correct state. */
  RIO_sendDoorbell(&stack, 1, 0, 0xdeaf);
 
  /* Check that only idle symbols are transmitted when the port has not been
     initialied even if statuses are received. */
  for(i = 0; i < 1024; i++)
  {
    RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
    s = RIO_portGetSymbol(&stack);
    TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
  }
 
  /******************************************************************************/
  TESTEND;
  /*****************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Set port initialized and get symbols from the stack.");
  PrintS("Result: Status-control-symbols should be generated each 256 symbol.");
  PrintS("----------------------------------------------------------------------");
  /*****************************************************************************/
  TESTSTART("TG_riostack-TC1-Step2");
  /*****************************************************************************/
 
  /* Set the port status to intialized. */
  RIO_portSetStatus(&stack, 1);
 
  /* Set port time. */
  RIO_portSetTime(&stack, 1);
 
  /* Check that status-control-symbols are transmitted once every 256 symbol. */
  for(j = 0; j < 15; j++)
  {
    for(i = 0; i < 255; i++)
    {
      s = RIO_portGetSymbol(&stack);
      TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
    }
    s = RIO_portGetSymbol(&stack);
    c = CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_NOP, 0);
    TESTEXPR(s.type, c.type);
    TESTEXPR(s.data, c.data);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 3:");
  PrintS("Action: Add a status-control-symbol to the receiver.");
  PrintS("Result: Status-control-symbols should be generated each 15 symbol.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step3");
  /*****************************************************************************/
 
  /* Insert a status-control-symbol in the receive. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
 
  /* Check that status-control-symbols are transmitted once every 16 symbol. */
  for(i = 0; i < 15; i++)
  {
    s = RIO_portGetSymbol(&stack);
    TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
  }
  s = RIO_portGetSymbol(&stack);
  c = CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_NOP, 0);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 4:");
  PrintS("Action: Add a packet to the receiver.");
  PrintS("Result: Packet should be ignored until the link is initialized.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step4");
  /*****************************************************************************/
 
  /* Send a packet. Note that the start and end of the packet contains a status. */
  packetLength = createDoorbell(packet, 0, 0, 0, 0, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
  /* Check that packet was not received. */
  TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_NONE);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 5:");
  PrintS("Action: Add four more status-control-symbols followed by one with error in ");
  PrintS("        CRC5. Then send a packet.");
  PrintS("Result: The receiver should remain in port initialized and packet should ");
  PrintS("        still be ignored.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step5");
  /*****************************************************************************/
 
  /* Send 4 more status-control-symbols followed by one erronous. */
  for(i = 0; i < 4; i++)
  {
    RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
  }
  c = CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0);
  c.data ^= 1;
  RIO_portAddSymbol(&stack, c);
 
  /* Send a packet. Note that the start and end of the packet contains status. */
  packetLength = createDoorbell(packet, 0, 0, 0, 0, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
  /* Check that the packet was ignored. */
  TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_NONE);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 6:");
  PrintS("Action: Add six more status-control-symbols. Then send a packet.");
  PrintS("Result: The receiver should enter link initialized and the packet should ");
  PrintS("        be received.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step6");
  /*****************************************************************************/
 
  /* Send 6 more status-control-symbols. */
  for(i = 0; i < 6; i++)
  {
    RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 1, STYPE1_NOP, 0));
  }
 
  /* Send a packet and check that it is accepted. */
  /* The ackId on receiver in testobject is updated when this has been transmitted. */
  packetLength = createDoorbell(packet, 0, 0, 0, 0, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 0, 8, STYPE1_END_OF_PACKET, 0));
 
  /* Check that the packet is received. */
  TESTEXPR(RIO_eventPoll(&stack), RIO_EVENT_DOORBELL);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 7:");
  PrintS("Action: Get symbols from transmitter.");
  PrintS("Result: Status-control-symbols should still be generated each 15 symbol ");
  PrintS("until a total of 15 status-control-symbols has been transmitted. Once these ");
  PrintS("has been transmitted, the transmitter will be link initialized.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step7");
  /*****************************************************************************/
 
  /* Note that the available buffers in the receiver should have decremented once 
     since the previously received packet has not been read from the application 
     side of the stack yet. */
  for(j = 0; j < 14; j++)
  {
    for(i = 0; i < 15; i++)
    {
      s = RIO_portGetSymbol(&stack);
      TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
    }
    s = RIO_portGetSymbol(&stack);
    c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_NOP, 0);
    TESTEXPR(s.type, c.type);
    TESTEXPR(s.data, c.data);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 8:");
  PrintS("Action: Get the first symbol from the transmitter once the link-intialized ");
  PrintS("        state has been entered.");
  PrintS("Result: A packet-accepted-symbol should be received for the newly received ");
  PrintS("        packet.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step8");
  /*****************************************************************************/
 
  c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 0, 7, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 9:");
  PrintS("Action: Get the next symbols from the transmitter.");
  PrintS("Result: The packet placed in the outbound queue at startup should be ");
  PrintS("        received. Dont acknowledge the packet yet.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step9");
  /*****************************************************************************/
 
  /* Create a packet. */
  packetLength = createDoorbell(packet, 0, 1, 0xffff, 0, 0xdeaf);
 
  /* Receive the start of the frame. */
  c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Receive the data of the frame. */
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
 
  /* Receive the end of the frame. */
  c = CreateControlSymbol(STYPE0_STATUS, 1, 7, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTSYMBOL(s, c);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 10:");
  PrintS("Action: Remove the packet from the inbound queue. Dont acknowledge the");
  PrintS("        transmitted packet yet.");
  PrintS("Result: Check that status-control-symbols are sent each 256 symbol and that ");
  PrintS("        the buffer count is updated when the inbound packet has been read.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step10");
  /*****************************************************************************/
 
  /* Simulate the application reading the received packet to free one reception 
     buffer. */
  RIO_packetRemove(&stack);
 
  /* Check that the status-control-symbols are generated each 256 symbol. */
  for(i = 0; i < 255; i++)
  {
    s = RIO_portGetSymbol(&stack);
    TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
  }
 
  /* Check that the buffer status has been updated. */
  s = RIO_portGetSymbol(&stack);
  c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 11:");
  PrintS("Action: Send a packet when an acknowledge has not been received.");
  PrintS("Result: Only idle and status control symbols should be transmitted until ");
  PrintS("        the packet-accepted symbol has been received.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step11");
  /*****************************************************************************/
 
  /* Place a packet in the outbound queue. */
  RIO_sendDoorbell(&stack, 2, 1, 0xc0de);
 
  packetLength = createDoorbell(packet, 1, 2, 0xffff, 1, 0xc0de);
 
  /* Receive the start of the frame. */
  c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Receive the data of the frame. */
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
 
  /* Receive the end of the frame. */
  c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTSYMBOL(s, c);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 12:");
  PrintS("Action: Send a packet-accepted symbol.");
  PrintS("Result: Check that the new packet is transmitted.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step12");
  /*****************************************************************************/
 
  /* Send acknowledge for the first frame. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 0, 1, STYPE1_NOP, 0));
 
  /* Check that status-control-symbols are transmitted once every 256 symbol with 
     updated ackId. */
  for(i = 0; i < 255; i++)
  {
    s = RIO_portGetSymbol(&stack);
    TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
  }
  s = RIO_portGetSymbol(&stack);
  c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 13:");
  PrintS("Action: Send a packet-accepted symbol.");
  PrintS("Result: Check that only idle and status-control-symbols are transmitted ");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC1-Step13");
  /*****************************************************************************/
 
  /* Acknowledge the second frame. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 1, 1, STYPE1_NOP, 0));
 
  /* Check that status-control-symbols are transmitted once every 256 symbol with 
     updated ackId. */
  for(i = 0; i < 255; i++)
  {
    s = RIO_portGetSymbol(&stack);
    TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
  }
  s = RIO_portGetSymbol(&stack);
  c = CreateControlSymbol(STYPE0_STATUS, 1, 8, STYPE1_NOP, 0);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC2");
  PrintS("Description: Test flow control.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send packets to receiver but don't acknowledge them.");
  PrintS("Result: The reception queue of the stack is full.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step1");
  /******************************************************************************/
 
  /* Fill input queue in receiver. */
  for(j = 0; j < 8; j++)
  {
    packetLength = createDoorbell(packet, 1+j, 0, 0, 1+j, 0);
 
    RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
    for(i = 0; i < packetLength; i++)
    {
      d.type = RIO_SYMBOL_TYPE_DATA;
      d.data = packet[i];
      RIO_portAddSymbol(&stack, d);
    }
    RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
 
    c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 1+j, 7-j, STYPE1_NOP, 0);
    s = RIO_portGetSymbol(&stack);
    TESTEXPR(s.type, c.type);
    TESTEXPR(s.data, c.data);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Send a packet when the inbound queue of the stack is full.");
  PrintS("Result: The stack sends a packet-retry symbol. The receiver will end up in ");
  PrintS("input-retry-stopped state.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step2");
  /******************************************************************************/
 
  /* Send another packet. */
  packetLength = createDoorbell(packet, 9, 0, 0, 9, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
 
  /* Receive indication from stack that the packet must be retried. */
  c = CreateControlSymbol(STYPE0_PACKET_RETRY, 9, 0, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 3:");
  PrintS("Action: Send a packet when the receiver is in input-retry-stopped.");
  PrintS("Result: The receiver should ignore the new packet.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step3");
  /******************************************************************************/
 
  /* Resend the packet. */
  packetLength = createDoorbell(packet, 9, 0, 0, 9, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
  s = RIO_portGetSymbol(&stack);
 
  /* Check that nothing is transmitted. */
  TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
 
  /* REMARK: Send other symbols here to check that they are handled as expected... */
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 4:");
  PrintS("Action: Send restart-from-retry and resend the previous packet.");
  PrintS("Result: The receiver should leave the input-retry-stopped state and receive ");
  PrintS("        the new frame.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step4");
  /******************************************************************************/
 
  /* Send restart-from-retry. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_RESTART_FROM_RETRY, 0));
 
  /* Check that the transaction id is correct and remove a packet from the inbound 
     queue. One entry in the inbound queue will be empty. */
  RIO_receiveDoorbell(&stack, &srcid, &tid, &info);
  TESTEXPR(tid, 1);
  RIO_packetRemove(&stack);
 
  /* Check that the buffer status has changed to show that a buffer is available. */
  s = RIO_portGetSymbol(&stack);  
  while(s.type == RIO_SYMBOL_TYPE_IDLE)
  {
    s = RIO_portGetSymbol(&stack);  
  }
  c = CreateControlSymbol(STYPE0_STATUS, 9, 1, STYPE1_NOP, 0);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Resend the packet and check that it is received. */
  packetLength = createDoorbell(packet, 9, 0, 0, 9, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
  c = CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 9, 0, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 5:");
  PrintS("Action: Place receiver in input-retry-stopped state.");
  PrintS("Result: Check that packets may be transmitted normally.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step5");
  /******************************************************************************/
 
  /* Send another packet and check that the receiver indicates that it should be retried. */
  packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 2, 1, STYPE1_END_OF_PACKET, 0));
  c = CreateControlSymbol(STYPE0_PACKET_RETRY, 10, 0, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send two packets to see that the first acknowledge has been processed. */
  RIO_sendDoorbell(&stack, 0, 2, 0xfeed);
  RIO_sendDoorbell(&stack, 0, 3, 0xdeed);
 
  /* Get the first packet. */
  packetLength = createDoorbell(packet, 2, 0, 0xffff, 2, 0xfeed);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
 
  /* Get the second packet. */
  packetLength = createDoorbell(packet, 3, 0, 0xffff, 3, 0xdeed);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTSYMBOL(s, c);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Indicate the packets must be retransmitted. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 2, 1, STYPE1_NOP, 0));
 
  /* Receive confirmation that the packet will be retransmitted. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_RESTART_FROM_RETRY, 0);
  s = RIO_portGetSymbol(&stack);
  TESTSYMBOL(s, c);
 
  /* Get the retransmission of the first packet. */
  packetLength = createDoorbell(packet, 2, 0, 0xffff, 2, 0xfeed);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
 
  /* Get the retransmission of the second packet. */
  packetLength = createDoorbell(packet, 3, 0, 0xffff, 3, 0xdeed);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTSYMBOL(s, c);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Confirm the reception of the packets. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 2, 1, STYPE1_NOP, 0));
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 3, 1, STYPE1_NOP, 0));
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 6:");
  PrintS("Action: Send status-control-symbol to show that no packets can be ");
  PrintS("        transmitted.");
  PrintS("Result: No packets should be transmitted.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step6");
  /******************************************************************************/
 
  /* Send status with bufferStatus set to zero. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 4, 0, STYPE1_NOP, 0));
 
  /* Send a packet. */
  RIO_sendDoorbell(&stack, 0, 4, 0xf00d);
 
  /* Check that nothing is transmitted but status-control-symbols. */  
  for(i = 0; i < 255; i++)
  {
    s = RIO_portGetSymbol(&stack);
    TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
  }
  s = RIO_portGetSymbol(&stack);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_NOP, 0);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 7:");
  PrintS("Action: Indicate free buffers and receive a frame, then request it to be ");
  PrintS("retried.");
  PrintS("Result: The packet should be retransmitted.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step7");
  /******************************************************************************/
 
  /* Send status with bufferStatus set to available. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 4, 1, STYPE1_NOP, 0));
 
  /* Get the packet but request it to be retried. */
  packetLength = createDoorbell(packet, 4, 0, 0xffff, 4, 0xf00d);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 4, 1, STYPE1_NOP, 0));
 
  /* Check the acknowledge of the retransmission. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_RESTART_FROM_RETRY, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Get the packet and acknowledge it. */
  packetLength = createDoorbell(packet, 4, 0, 0xffff, 4, 0xf00d);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 0, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 4, 1, STYPE1_NOP, 0));
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 8:");
  PrintS("Action: Read all inbound packets from the reception queue.");
  PrintS("Result: The buffer status should be updated.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step8");
  /******************************************************************************/
 
  for(j = 0; j < 8; j++)
  {
    RIO_receiveDoorbell(&stack, &srcid, &tid, &info);
    TESTEXPR(tid, j+2);
    RIO_packetRemove(&stack);
 
    for(i = 0; i < 255; i++)
    {
      s = RIO_portGetSymbol(&stack);
      TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
    }
    s = RIO_portGetSymbol(&stack);
    c = CreateControlSymbol(STYPE0_STATUS, 10, j+1, STYPE1_NOP, 0);
    TESTEXPR(s.type, c.type);
    TESTEXPR(s.data, c.data);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 9:");
  PrintS("Action: Send a restart-from-retry to make the receiver leave the ");
  PrintS("        input-retry-stopped state.");
  PrintS("Result: New packets should be received again.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC2-Step9");
  /******************************************************************************/
 
  /* Send restart-from-retry. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_RESTART_FROM_RETRY, 0));
 
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC3");
  PrintS("Description: Test receiver error handling.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send invalid ack id in packet.");
  PrintS("Result: Input-error-stopped state should be entered and link-response ");
  PrintS("        should indicate an ackId error.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC3-Step1");
  /******************************************************************************/
 
  /* Send packet with invalid ackId, same as sent previously. */
  packetLength = createDoorbell(packet, 9, 0, 0, 10, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0));
 
  /* Check that the packet is not accepted with cause error in ackId. */  
  c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 1, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send a link-request. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, 
                                            STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
 
  /* Check that a link-response is returned. */
  /* Note that the status of the input-port will be reported as ok since a 
     link-request has been received. */
  c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Check that a status is transmitted directly after the link-response. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Send packet with invalid CRC.");
  PrintS("Result: Input-error-stopped state should be entered and link-response ");
  PrintS("        should indicate a CRC error.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC3-Step2");
  /******************************************************************************/
 
  /* Send packet with invalid crc. */
  packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
  packet[0] ^= 0x00000001;
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < packetLength; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0));
 
  /* Check that the packet is not accepted with cause error in ackId. */  
  c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 4, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send a link-request. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, 
                                    STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
 
  /* Check that a link-response is returned. */
  /* Note that the status of the input-port will be reported as ok since a 
     link-request has been received. */
  c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Check that a status is transmitted directly after the link-response. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 3:");
  PrintS("Action: Send a packet that is too short.");
  PrintS("Result: Input-error-stopped state should be entered and link-response ");
  PrintS("        should indicate a packet error.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC3-Step3");
  /******************************************************************************/
 
  /* Send packet with valid ackid and crc but too short. */
  packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
  d.type = RIO_SYMBOL_TYPE_DATA;
  d.data = packet[0];
  RIO_portAddSymbol(&stack, d);
  d.type = RIO_SYMBOL_TYPE_DATA;
  d.data = ((uint32_t) Crc32(packet[0] & 0x07ffffff, 0xffff)) << 16;
  RIO_portAddSymbol(&stack, d);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0));
 
  /* Check that the packet is not accepted with cause error in ackId. */  
  c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send a link-request. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, 
                                    STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
 
  /* Check that a link-response is returned. */
  /* Note that the status of the input-port will be reported as ok since a 
     link-request has been received. */
  c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Check that a status is transmitted directly after the link-response. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 4:");
  PrintS("Action: Send a packet that is too long.");
  PrintS("Result: Input-error-stopped state should be entered and link-response ");
  PrintS("        should indicate a packet error.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC3-Step4");
  /******************************************************************************/
 
  /* Send packet with too many data symbols and without a end-of-packet. */
  packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_START_OF_PACKET, 0));
  for(i = 0; i < 70; i++)
  {
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    RIO_portAddSymbol(&stack, d);
  }
 
  /* Check that the packet is not accepted with cause error in ackId. */  
  c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send a link-request. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, 
                                            STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
 
  /* Check that a link-response is returned. */
  /* Note that the status of the input-port will be reported as ok since a 
     link-request has been received. */
  c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Check that a status is transmitted directly after the link-response. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 5:");
  PrintS("Action: Send a data symbol without starting a packet.");
  PrintS("Result: Input-error-stopped state should be entered and link-response ");
  PrintS("        should indicate a packet error.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC3-Step5");
  /******************************************************************************/
 
  /* Send a data symbol. */
  packetLength = createDoorbell(packet, 10, 0, 0, 10, 0);
  d.type = RIO_SYMBOL_TYPE_DATA;
  d.data = packet[0];
  RIO_portAddSymbol(&stack, d);
 
  /* Check that the packet is not accepted with cause error in ackId. */  
  c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send a link-request. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, 
                                            STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
 
  /* Check that a link-response is returned. */
  /* Note that the status of the input-port will be reported as ok since a 
     link-request has been received. */
  c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Check that a status is transmitted directly after the link-response. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 6:");
  PrintS("Action: Send end-of-packet without matching start.");
  PrintS("Result: Input-error-stopped state should be entered and link-response ");
  PrintS("        should indicate a packet error.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC3-Step6");
  /******************************************************************************/
 
  /* Send end-of-packet. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_END_OF_PACKET, 0));
 
  /* Check that the packet is not accepted with cause error in ackId. */
  c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 31, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send a link-request. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, 
                                            STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
 
  /* Check that a link-response is returned. */
  /* Note that the status of the input-port will be reported as ok since a 
     link-request has been received. */
  c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Check that a status is transmitted directly after the link-response. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 7:");
  PrintS("Action: Send a symbol indicating a codec error.");
  PrintS("Result: Input-error-stopped state should be entered and link-response ");
  PrintS("        should indicate a symbol error.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC3-Step7");
  /******************************************************************************/
 
  /* Send error-symbol. */
  s.type = RIO_SYMBOL_TYPE_ERROR;
  RIO_portAddSymbol(&stack, s);
 
  /* Check that the packet is not accepted with cause error in ackId. */  
  c = CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 5, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send a link-request. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, 
                                            STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS));
 
  /* Check that a link-response is returned. */
  /* Note that the status of the input-port will be reported as ok since a 
     link-request has been received. */
  c = CreateControlSymbol(STYPE0_LINK_RESPONSE, 10, 16, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Check that a status is transmitted directly after the link-response. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_NOP, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC4");
  PrintS("Description: Test transmitter error handling.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send acknowledge for a frame that has not been transmitted and ");
  PrintS("        without any frame being expected.");
  PrintS("Result: The transmitter should enter output-error-stopped and send ");
  PrintS("        link-request.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC4-Step1");
  /******************************************************************************/
 
  /* Packet acknowledge for unsent frame. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0));
 
  /* Check that a link-request is received as the transmitter enters 
     output-error-stopped state. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, 
                          STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send link-response with expected ackId. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 5, 16, STYPE1_NOP, 0));
 
  /* Send a status directly afterwards. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 5, 1, STYPE1_NOP, 0));
 
  /* Check that packets are relayed after this. */
  RIO_sendDoorbell(&stack, 0, 5, 2);
  packetLength = createDoorbell(packet, 5, 0, 0xffff, 5, 2);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0));
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Send a packet and send acknowledge for a previous frame. Then send ");
  PrintS("        a link-response indicating that the packet was received (accepted ");
  PrintS("        but reply corrupted).");
  PrintS("Result: The transmitter should enter output-error-stopped state and send ");
  PrintS("        link-request and proceed with the next packet.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC4-Step2");
  /******************************************************************************/
 
  /* Send a packet. */
  RIO_sendDoorbell(&stack, 0, 6, 2);
  packetLength = createDoorbell(packet, 6, 0, 0xffff, 6, 2);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send acknowledge for another packet. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 5, 1, STYPE1_NOP, 0));
 
  /* Check that a link-request is received as the transmitter enters 
     output-error-stopped state. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, 
                          STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send link-response with expected ackId. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0));
 
  /* Send a status directly afterwards. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 7, 1, STYPE1_NOP, 0));
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 3:");
  PrintS("Action: Send a packet and let the packet-accepted time out. Then send a ");
  PrintS("        link-response indicating that the packet was not received.");
  PrintS("Result: The transmitter should enter output-error-stopped state, send a");
  PrintS("        link-request and then resend the packet.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC4-Step3");
  /******************************************************************************/
 
  /* Set the time at frame transmission. */
  RIO_portSetTime(&stack, 2);
 
  /* Send an output packet. */
  RIO_sendDoorbell(&stack, 0, 7, 2);
 
  /* Receive the transmitted packet. */
  packetLength = createDoorbell(packet, 7, 0, 0xffff, 7, 2);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Indicate that time has passed to trigger a timeout. */
  RIO_portSetTime(&stack, 3);
 
  /* Check that a link-request is received as the transmitter enters 
     output-error-stopped state. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, 
                          STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send link-response with expected ackId. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 7, 16, STYPE1_NOP, 0));
 
  /* Send a status directly afterwards. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 7, 1, STYPE1_NOP, 0));
 
  /* Receive retransmitted packet. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send acknowledge for the retransmitted packet. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 7, 1, STYPE1_NOP, 0));
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 4:");
  PrintS("Action: Send a packet and then indicate that the packet was not accepted. ");
  PrintS("        Then send a link-response indicating that the packet was not received.");
  PrintS("Result: The transmitter should enter output-error-stopped state, send a");
  PrintS("        link-request and then resend the packet.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC4-Step4");
  /******************************************************************************/
 
  /* Send an output packet. */
  RIO_sendDoorbell(&stack, 0, 8, 3);
 
  /* Receive the transmitted packet. */
  packetLength = createDoorbell(packet, 8, 0, 0xffff, 8, 3);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send packet-not-accepted indicating CRC error. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_NOT_ACCEPTED, 0, 4, STYPE1_NOP, 0));
 
  /* Check that a link-request is received as the transmitter enters 
     output-error-stopped state. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, 
                          STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send link-response with expected ackId. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 8, 16, STYPE1_NOP, 0));
 
  /* Send a status directly afterwards. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 8, 1, STYPE1_NOP, 0));
 
  /* Receive retransmitted packet. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send acknowledge for the retransmitted packet. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 8, 1, STYPE1_NOP, 0));
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 5:");
  PrintS("Action: Send a packet-retry for an unexpected packet. Then send a");
  PrintS("        link-response indicating the expected ackId and a normal packet.");
  PrintS("Result: The transmitter should enter output-error-stopped state, send a");
  PrintS("        link-request and then the normal packet.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC4-Step5");
  /******************************************************************************/
 
  /* Send packet-retry indicating that a packet should be retransmitted. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 8, 1, STYPE1_NOP, 0));
 
  /* Check that a link-request is received as the transmitter enters 
     output-error-stopped state. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, 
                          STYPE1_LINK_REQUEST, LINK_REQUEST_INPUT_STATUS);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send link-response with expected ackId. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_LINK_RESPONSE, 9, 16, STYPE1_NOP, 0));
 
  /* Send a status directly afterwards. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_STATUS, 9, 1, STYPE1_NOP, 0));
 
  /* Send an output packet. */
  RIO_sendDoorbell(&stack, 0, 9, 4);
 
  /* Receive retransmitted packet. */
  packetLength = createDoorbell(packet, 9, 0, 0xffff, 9, 4);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Send acknowledge for the retransmitted packet. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 9, 1, STYPE1_NOP, 0));
 
  /******************************************************************************/
  TESTEND; 
 /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 6:");
  PrintS("Action: Fill outbound queue with packets, then check retransmission when ");
  PrintS("        packet-retry is encountered. ");
  PrintS("Result: Packets should be retried until packet-accepted is received.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC4-Step6");
  /******************************************************************************/
 
  TESTCOND(RIO_sendAvailable(&stack, 0));
  RIO_sendDoorbell(&stack, 0, 20, 0xbabe);
 
  TESTCOND(RIO_sendAvailable(&stack, 0));
  RIO_sendDoorbell(&stack, 0, 21, 0xbabe);
 
  TESTCOND(RIO_sendAvailable(&stack, 0));
  RIO_sendDoorbell(&stack, 0, 22, 0xbabe);
 
  TESTCOND(RIO_sendAvailable(&stack, 0));
  RIO_sendDoorbell(&stack, 0, 23, 0xbabe);
 
  TESTCOND(RIO_sendAvailable(&stack, 0));
  RIO_sendDoorbell(&stack, 0, 24, 0xbabe);
 
  TESTCOND(RIO_sendAvailable(&stack, 0));
  RIO_sendDoorbell(&stack, 0, 25, 0xbabe);
 
  TESTCOND(RIO_sendAvailable(&stack, 0));
  RIO_sendDoorbell(&stack, 0, 26, 0xbabe);
 
  TESTCOND(RIO_sendAvailable(&stack, 0));
  RIO_sendDoorbell(&stack, 0, 27, 0xbabe);
 
  TESTCOND(!RIO_sendAvailable(&stack, 0));
 
  /* Receive transmitted packet. */
  packetLength = createDoorbell(packet, 10, 0, 0xffff, 20, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 11, 0, 0xffff, 21, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 12, 0, 0xffff, 22, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 13, 0, 0xffff, 23, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 14, 0, 0xffff, 24, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 15, 0, 0xffff, 25, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 16, 0, 0xffff, 26, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 17, 0, 0xffff, 27, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  for(i = 0; i < 10; i++)
  {
    s = RIO_portGetSymbol(&stack);
    TESTEXPR(s.type, RIO_SYMBOL_TYPE_IDLE);
  }
 
  /* Request retransmission. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_RETRY, 10, 1, STYPE1_NOP, 0));
 
  /* Acknowledge retransmission. */
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_RESTART_FROM_RETRY, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  /* Check retransmitted packets. */
  packetLength = createDoorbell(packet, 10, 0, 0xffff, 20, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 11, 0, 0xffff, 21, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 12, 0, 0xffff, 22, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
 
  /* Acknowledge. */
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 10, 1, STYPE1_NOP, 0));
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 11, 1, STYPE1_NOP, 0));
 
  packetLength = createDoorbell(packet, 13, 0, 0xffff, 23, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 14, 0, 0xffff, 24, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
 
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 12, 1, STYPE1_NOP, 0));
 
  packetLength = createDoorbell(packet, 15, 0, 0xffff, 25, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
 
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 13, 1, STYPE1_NOP, 0));
 
  packetLength = createDoorbell(packet, 16, 0, 0xffff, 26, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 14, 1, STYPE1_NOP, 0));
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  packetLength = createDoorbell(packet, 17, 0, 0xffff, 27, 0xbabe);
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_START_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
  for(i = 0; i < packetLength; i++)
  {
    s = RIO_portGetSymbol(&stack);
    d.type = RIO_SYMBOL_TYPE_DATA;
    d.data = packet[i];
    TESTEXPR(s.type, d.type);
    TESTEXPR(s.data, d.data);
  }
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 15, 1, STYPE1_NOP, 0));
  c = CreateControlSymbol(STYPE0_STATUS, 10, 8, STYPE1_END_OF_PACKET, 0);
  s = RIO_portGetSymbol(&stack);
  TESTEXPR(s.type, c.type);
  TESTEXPR(s.data, c.data);
 
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 16, 1, STYPE1_NOP, 0));
  RIO_portAddSymbol(&stack, CreateControlSymbol(STYPE0_PACKET_ACCEPTED, 17, 1, STYPE1_NOP, 0));
 
 
  /*************************************************************************
   * Reset ackIds to be able to use the stack in loopback for the testcases 
   * below.
   *************************************************************************/
 
  stack.rxAckId = 0;
  stack.rxAckIdAcked = 0;
  stack.txAckId = 0;
  stack.txAckIdWindow = 0;
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC5");
  PrintS("Description: Test MAINTENANCE-READ-REQUEST, MAINTENANCE-READ-RESPONSE,");
  PrintS("             MAINTENANCE-WRITE-REQUEST and MAINTENANCE-WRITE-RESPONSE packets.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send two read requests to read identity and address of stack.");
  PrintS("Result: The identity and address defined at RIO_open should be returned.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC5-Step1");
  /******************************************************************************/
 
  /* Send two read requests. */
  RIO_sendMaintenanceReadRequest(&stack, 0xffff, 10, 0, 0x00000000);
  RIO_sendMaintenanceReadRequest(&stack, 0xffff, 11, 0, 0x00000060);
 
  TESTEXPR(RIO_outboundQueueLength(&stack), 2);
 
  while(RIO_inboundQueueLength(&stack) != 2)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
  TESTEXPR(srcid, 0xffff);
  TESTEXPR(tid, 10);
  TESTEXPR(hop, 0xff);
  TESTEXPR(data, 0x0000b03b);
  RIO_packetRemove(&stack);
 
  RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
  TESTEXPR(srcid, 0xffff);
  TESTEXPR(tid, 11);
  TESTEXPR(hop, 0xff);
  TESTEXPR(data, 0x0000ffff);
  RIO_packetRemove(&stack);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Send a write requests to write base device id of the stack.");
  PrintS("Result: The identity and address defined at RIO_open should be returned.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC5-Step2");
  /******************************************************************************/
 
  /* Write base device id. */
  RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 12, 0, 0x00000060, 0xdead);
  while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 12);
  TESTEXPR(hop, 0xff);
  RIO_packetRemove(&stack);
 
  /* Read back the written base device id. */
  RIO_sendMaintenanceReadRequest(&stack, 0xffff, 14, 0, 0x00000060);
  while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_READ_RESPONSE)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 14);
  TESTEXPR(hop, 0xff);
  TESTEXPR(data, 0x0000dead);
  RIO_packetRemove(&stack);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 3:");
  PrintS("Action: Send a write requests to write to the implementation defined ");
  PrintS("        configuration space of the stack.");
  PrintS("Result: The same data should be returned.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC5-Step3");
  /******************************************************************************/
 
  /* Write to implementation defined space. */
  RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 14, 0, 0x00010004, 0x01020304);
  RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 15, 0, 0x00010008, 0xc0debabe);
  RIO_sendMaintenanceWriteRequest(&stack, 0xffff, 16, 0, 0x0001000c, 0x05060708);
 
  while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 14);
  TESTEXPR(hop, 0xff);
  RIO_packetRemove(&stack);
 
  while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 15);
  TESTEXPR(hop, 0xff);
  RIO_packetRemove(&stack);
 
  while(RIO_eventPoll(&stack) != RIO_EVENT_MAINT_WRITE_RESPONSE)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveMaintenanceWriteResponse(&stack, &srcid, &tid, &hop);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 16);
  TESTEXPR(hop, 0xff);
  RIO_packetRemove(&stack);
 
  /* Read from implementation defined space. */
  RIO_sendMaintenanceReadRequest(&stack, 0xffff, 14, 0, 0x00010000);
  RIO_sendMaintenanceReadRequest(&stack, 0xffff, 15, 0, 0x00010004);
  RIO_sendMaintenanceReadRequest(&stack, 0xffff, 16, 0, 0x00010008);
  RIO_sendMaintenanceReadRequest(&stack, 0xffff, 17, 0, 0x0001000c);
 
  while(RIO_inboundQueueLength(&stack) != 4)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 14);
  TESTEXPR(hop, 0xff);
  TESTEXPR(data, 0x80000006);
  RIO_packetRemove(&stack);
 
  RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 15);
  TESTEXPR(hop, 0xff);
  TESTEXPR(data, 0x00a100a2);
  RIO_packetRemove(&stack);
 
  RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 16);
  TESTEXPR(hop, 0xff);
  TESTEXPR(data, 0xc0debabe);
  RIO_packetRemove(&stack);
 
  RIO_receiveMaintenanceReadResponse(&stack, &srcid, &tid, &hop, &data);
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 17);
  TESTEXPR(hop, 0xff);
  TESTEXPR(data, 0x00000000);
  RIO_packetRemove(&stack);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC6");
  PrintS("Description: Test NREAD packets.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send one byte using NREAD and receive it at the other side.");
  PrintS("Result: The same NREAD should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC6-Step1");
  /******************************************************************************/
 
  for(j = 0; j < 8; j++)
  {
    RIO_sendNread(&stack, 0x0060, j, 0xaaaaaaaa+j, 1);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
 
    TESTEXPR(tid, j);
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(address, 0xaaaaaaaa+j);
    TESTEXPR(length, 1);
 
    RIO_packetRemove(&stack);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Send two bytes using NREAD and receive it at the other side.");
  PrintS("Result: The same NREAD should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC6-Step2");
  /******************************************************************************/
 
  for(j = 0; j < 4; j++)
  {
    RIO_sendNread(&stack, 0x0060, j, 0x00000008+2*j, 2);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
 
    TESTEXPR(tid, j);
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(address, 0x00000008+2*j);
    TESTEXPR(length, 2);
 
    RIO_packetRemove(&stack);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 3:");
  PrintS("Action: Send three to seven bytes using NREAD and receive it at the other ");
  PrintS("        side.");
  PrintS("Result: The same NREAD should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC6-Step3");
  /******************************************************************************/
 
  for(k = 3; k < 8; k++)
  {
    for(j = 0; j < 2; j++)
    {
      RIO_sendNread(&stack, 0x0060, j, 0x00000008+(8-k)*j, k);
 
      while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
      {
        s = RIO_portGetSymbol(&stack);
        RIO_portAddSymbol(&stack, s);
      }
 
      RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
 
      TESTEXPR(tid, j);
      TESTEXPR(srcid, 0xdead);
      TESTEXPR(address, 0x00000008+(8-k)*j);
      TESTEXPR(length, k);
 
      RIO_packetRemove(&stack);
    }
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 4:");
  PrintS("Action: Send one and two double words using NREAD and receive it at the ");
  PrintS("        other side.");
  PrintS("Result: The same NREAD should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC6-Step4");
  /******************************************************************************/
 
  for(j = 0; j < 2; j++)
  {
    RIO_sendNread(&stack, 0x0060, j, 0x00000008+8*j, 8*j+8);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
 
    TESTEXPR(tid, j);
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(address, 0x00000008+8*j);
    TESTEXPR(length, 8*j+8);
 
    RIO_packetRemove(&stack);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 5:");
  PrintS("Action: Send multiple of four full double words using NREAD and receive it");
  PrintS("at the other side.");
  PrintS("Result: The same NREAD should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC6-Step5");
  /******************************************************************************/
 
  for(j = 0; j < 8; j++)
  {
    RIO_sendNread(&stack, 0x0060, j, 0x00000008+8*j, 32*j+32);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_NREAD)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    RIO_receiveNread(&stack, &srcid, &tid, &address, &length);
 
    TESTEXPR(tid, j);
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(address, 0x00000008+8*j);
    TESTEXPR(length, 32*j+32);
 
    RIO_packetRemove(&stack);
  }
 
  /* REMARK: Add negative testcase where all unallowed address, size combinations 
     are sent...*/
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC7");
  PrintS("Description: Test NWRITER packets.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send one byte using NWRITER and receive it at the other side.");
  PrintS("Result: The same NWRITER should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC7-Step1");
  /******************************************************************************/
 
  for(j = 0; j < 8; j++)
  {
    for(i = 0; i < 1; i++)
    {
      payload8[i] = i+j+1;
      payload8Expected[i] = 0;
    }
 
    RIO_sendNwrite(&stack, 0x0060, 0xaaaaaaaa+j, 1, payload8);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected);
 
    TESTEXPR(length, 1);
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(address, 0xaaaaaaaa+j);
 
    for(i = 0; i < 1; i++)
    {
      TESTEXPR(payload8Expected[i], i+j+1);
    }
 
    RIO_packetRemove(&stack);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Send two bytes using NWRITE and receive it at the other side.");
  PrintS("Result: The same NWRITE should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC7-Step2");
  /******************************************************************************/
 
  for(j = 0; j < 4; j++)
  {
    for(i = 0; i < 2; i++)
    {
      payload8[i] = i+j;
      payload8Expected[i] = 0;
    }
 
    RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+2*j, 2, payload8);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected);
 
    TESTEXPR(tid, j);
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(address, 0x00000008+2*j);
    TESTEXPR(length, 2);
 
    for(i = 0; i < 2; i++)
    {
      TESTEXPR(payload8Expected[i], i+j);
    }
 
    RIO_packetRemove(&stack);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 3:");
  PrintS("Action: Send three to seven bytes using NWRITE and receive it at the other ");
  PrintS("        side.");
  PrintS("Result: The same NWRITE should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC7-Step3");
  /******************************************************************************/
 
  for(k = 3; k < 8; k++)
  {
    for(j = 0; j < 2; j++)
    {
      for(i = 0; i < k; i++)
      {
        payload8[i] = i+j+1;
        payload8Expected[i] = 0;
      }
 
      RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+(8-k)*j, k, payload8);
 
      while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R)
      {
        s = RIO_portGetSymbol(&stack);
        RIO_portAddSymbol(&stack, s);
      }
 
      length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected);
 
      TESTEXPR(tid, j);
      TESTEXPR(srcid, 0xdead);
      TESTEXPR(address, 0x00000008+(8-k)*j);
      TESTEXPR(length, k);
 
      for(i = 0; i < k; i++)
      {
        TESTEXPR(payload8Expected[i], i+j+1);
      }
 
      RIO_packetRemove(&stack);
    }
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 4:");
  PrintS("Action: Send full double words using NWRITE and receive it at the other side.");
  PrintS("Result: The same NWRITE should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC7-Step4");
  /******************************************************************************/
 
  for(j = 1; j < 32; j++)
  {
    for(i = 0; i < 8*j; i++)
    {
      payload8[i] = i+j+1;
      payload8Expected[i] = 0;
    }
 
    RIO_sendNwriteR(&stack, 0x0060, j, 0x00000008+8*j, 8*j, payload8);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_NWRITE_R)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    length = RIO_receiveNwrite(&stack, &srcid, &tid, &address, sizeof(payload8Expected), payload8Expected);
 
    TESTEXPR(tid, j);
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(address, 0x00000008+8*j);
    TESTEXPR(length, 8*j);
 
    for(i = 0; i < 8*j; i++)
    {
      TESTEXPR(payload8Expected[i], (uint8_t) (i+j+1));
    }
 
    RIO_packetRemove(&stack);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC8");
  PrintS("Description: Test RESPONSE packets.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send one byte using RESPONSE_WITH_PAYLOAD and receive it at the ");
  PrintS("        other side.");
  PrintS("Result: The same RESPONSE_WITH_PAYLOAD should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC8-Step1");
  /******************************************************************************/
 
  for(j = 0; j < 8; j++)
  {
    for(i = 0; i < 1; i++)
    {
      payload8[i] = i+j+1;
      payload8Expected[i] = 0;
    }
 
    RIO_sendResponseDonePayload(&stack, 0x0060, j, 0x00000008+j, 1, payload8);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_RESPONSE_DONE_PAYLOAD)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    length = RIO_receiveResponseDonePayload(&stack, &srcid, &tid, 0x00000008+j, 1, payload8Expected);
 
    TESTEXPR(tid, j);
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(length, 1);
 
    for(i = 0; i < 1; i++)
    {
      TESTEXPR(payload8Expected[i], i+j+1);
    }
 
    RIO_packetRemove(&stack);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC9");
  PrintS("Description: Test DOORBELL packet and its response.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send a doorbell.");
  PrintS("Result: The received doorbell should have the same properties as the sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC9-Step1");
  /******************************************************************************/
 
  RIO_sendDoorbell(&stack, 0x0060, 16, 0xbabe);
 
  while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveDoorbell(&stack, &srcid, &tid, &info);
 
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 16);
  TESTEXPR(info, 0xbabe);
  RIO_packetRemove(&stack);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Send a response that is used for doorbells.");
  PrintS("Result: The same data should be returned.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC9-Step2");
  /******************************************************************************/
 
  RIO_sendResponseDone(&stack, 0x0060, 16);
 
  while(RIO_eventPoll(&stack) != RIO_EVENT_RESPONSE_DONE)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveResponseDone(&stack, &srcid, &tid);
 
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 16);
  RIO_packetRemove(&stack);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC10");
  PrintS("Description: Test MESSAGE packets.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send increasing number of byte using MESSAGE on all mailboxes");
  PrintS("        and receive it at the other side.");
  PrintS("Result: The same MESSAGE on the correct mailbox should be received as has");
  PrintS("        been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC10-Step1");
  /******************************************************************************/
 
  for(k = 0; k < 256; k++)
  {
    for(j = 1; j < 256; j++)
    {
      for(i = 0; i < j; i++)
      {
        payload8[i] = i+j+1;
        payload8Expected[i] = 0;
      }
 
      RIO_sendMessage(&stack, 0x0060, k, j, payload8);
 
      while(RIO_eventPoll(&stack) != RIO_EVENT_MESSAGE)
      {
        s = RIO_portGetSymbol(&stack);
        RIO_portAddSymbol(&stack, s);
      }
 
      length = RIO_receiveMessage(&stack, &srcid, &mailbox, sizeof(payload8Expected), payload8Expected);
 
      TESTEXPR(srcid, 0xdead);
      TESTEXPR(mailbox, k);
      TESTEXPR(length, (((j-1)/8)+1)*8);
 
      for(i = 0; i < j; i++)
      {
        TESTEXPR(payload8Expected[i], (uint8_t) (i+j+1));
      }
 
      RIO_packetRemove(&stack);
    }
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 2:");
  PrintS("Action: Send a MESSAGE-RESPONSE from all mailboxes.");
  PrintS("Result: The same MESSAGE-RESPONSE should be received as has been sent.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC10-Step2");
  /******************************************************************************/
 
  for(i = 0; i < 256; i++)
  {
    RIO_sendMessageResponseDone(&stack, 0x0060, i);
 
    while(RIO_eventPoll(&stack) != RIO_EVENT_MESSAGE_RESPONSE_DONE)
    {
      s = RIO_portGetSymbol(&stack);
      RIO_portAddSymbol(&stack, s);
    }
 
    RIO_receiveMessageResponseDone(&stack, &srcid, &mailbox);
 
    TESTEXPR(srcid, 0xdead);
    TESTEXPR(mailbox, i);
    RIO_packetRemove(&stack);
  }
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
  PrintS("----------------------------------------------------------------------");
  PrintS("TG_riostack-TC11");
  PrintS("Description: Test reading and writing raw packets.");
  PrintS("Requirement: XXXXX");
  PrintS("----------------------------------------------------------------------");
  PrintS("Step 1:");
  PrintS("Action: Send a packet using normal functions then copy it using the ");
  PrintS("        packetGet() and packetSet() functions. ");
  PrintS("Result: The same packet should be received when copied.");
  PrintS("----------------------------------------------------------------------");
  /******************************************************************************/
  TESTSTART("TG_riostack-TC11-Step1");
  /******************************************************************************/
 
  RIO_sendDoorbell(&stack, 0x0060, 1, 0xca1e);
 
  while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  RIO_receiveDoorbell(&stack, &srcid, &tid, &info);
 
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 1);
  TESTEXPR(info, 0xca1e);
 
  packetLength = RIO_packetGet(&stack, sizeof(packet)/4, packet);
  RIO_packetSet(&stack, packetLength, packet);
 
  while(RIO_eventPoll(&stack) != RIO_EVENT_DOORBELL)
  {
    s = RIO_portGetSymbol(&stack);
    RIO_portAddSymbol(&stack, s);
  }
 
  TESTEXPR(srcid, 0xdead);
  TESTEXPR(tid, 1);
  TESTEXPR(info, 0xca1e);
  RIO_packetRemove(&stack);
 
  /******************************************************************************/
  TESTEND;
  /******************************************************************************/
 
  return 0;
}
#endif
 
/*************************** end of file **************************************/
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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