Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Content Zone
locationtop
typelist
Requirements

Concepts

The low-level interface to an RCE's protocol plugins uses abstractions called ports, frames, channels, local ports and drivers.

A port is the RCE end of a communications link similar in concept to a BSD socket. Ports are globally visible although but not MT-safe; at any given time only one thread may be waiting for incoming data on a given port. Some I/O capability of an RCE system provided by its protocol plugins is made available to application code using abstractions called ports. Some of those ports are predefined, i.e., are set up by the RCE core code before created by before any application code is started.

  • Data container zero in the configuration flash contains tables providing all the information needed to make ready the predefined ports. This includes pointers to device driver code but not the code itself; other containers will hold driver code. In addition the tables provide some extra information not actually needed for setup but required to print a summary, meaningful to human beings, of the characteristics of the predefined ports.
  • The RCE core code uses the information in the tables to define the ports they describe, except for loading and running device drivers (see below).
  • called.

    Ports deliver data as frames. The exact content of a frame depends on the transmission protocol being used but at the port recognizes a division into header and payload. One frame corresponds to one message on the I/O medium and is delivered in a single buffer. In other words all ports implement datagram rather than byte-stream protocols. It's up to higher-level software such as a TCP stack to provide any operations that cross frame boundaries. Each port contains a queue of frames which have arrived and not yet been consumed by the application.

    A channel is a hardware I/O engine capable of DMA to and from system RAM, i.e., a protocol plugin. Most channels will make use of one or more of the Multi-Gigabit Tranceiver modules available in firmware, though some may simply offer access to on-board resources such as DSPs. Each channel has its own "local port" space where each local port is identified by a 16-bit unsigned integer. Each local port represents a different source of incoming data such as a UDP port or a Petacache flash lane. Some local ports will be predefined in the sense of being made ready for use early during system initialization, others may be created later if the driver allows it. Predefined local ports may not be destroyed but any others may be.

    With one exception there is a one-to-one correspondence between (channel, local port) and ports. Therefore for each predefined local port there will be a predefined port object. One data container in configuration flash will contain a table of the predefined ports available on the RCE plus related information enabling the RCE core software to find the required drivers, etc.

    The exception to the rule of correspondence between port and local port is the predefined "default" port, which receives data that doesn't "belong" to any other port.

    Any attempt to close or destroy a predefined port will be ignored.

    A channel is not obliged to predefine any local ports, in which case the channel's presence won't be detected by looking in the table of predefined ports; the table of channels will have to be searched.

    Each channel

    Each channel (PPI)

    has exactly one device driver whose object code fits into a single container in the configuration flash.

    The tables described above contain references to these containers.

    A device driver is just a module as defined by the RCE dynamic linker; its rce_appmain() function initializes the driver.

    The

    Early in the system init. process the RCE core code loads the device driver modules into system RAM

    along with the application module(s)

    and links them all together

    in

    with the default instance of the linker. It then calls the rce_appmain() of each driver (no order guaranteed)

    before calling that of the application

    . Technically this allows a driver to depend on other drivers

    or even on the application code

    but DON'T DO IT. A driver should depend only on the RCE core.

    Later on the same instance of the linker used for the drivers is used to link the main application module, making it possible for the application code to use the drivers as simple libraries if they export any functions or classes for other modules. A driver might export nothing directly but instead register a new device in the RTEMS in-memory filesystem.

    Port and channel information in configuration flash

    Data container zero in the configuration flash contains tables providing all the information needed to make ready the all channels and predefined ports. This includes references to device driver code but not the code itself; other containers will hold driver code. In addition the tables provide some extra information not actually needed for setup but required to print a summary of what the protocol plugins provide.

  • The core provides an API by which the application code can discover which ports are defined and their characteristics. When the application starts the API can return information about any predefined port.
  • Table format in configuration flash

    The tables are called Ports, Channels, Channel Classes, Bandwidths, Drivers and Strings. Except for Strings each table is an array of plain-old-data structs with the first field being a key or ID field normally equal to the array index. An ID equal to 0xffffffff signifies the end of the table in which case none of the other fields in the struct have any guaranteed values and should never be read. Thus you'll generate end-of-table sentinels automatically when you erase a flash block before writing tables into it, provided you leave at least one 32-bit word of unused unwritten space at the end of each table. If you write all the tables in one go then you must provide the end-of-table markers explicitly.

    The Strings table is like an ELF string table; NUL-terminated ASCII strings laid end to end. Certain standard strings such as the short-names of channels are at the front of the table with only one instance of each string present. The other tables refer to a string by giving the offset of its first character in the Strings table.

    General layout of the container contents

    The first words of the container are the 32-bit offsets in the container to the starts of the tables in the following order:

    Offset of Ports

    .

    Offset of Channels

    .

    Offset of Channel Classes

    .

    Offset of Bandwidths

    .

    Offset of Drivers

    .

    Offset of Strings

    .

    Each of the offsets should be divisible by four.

    After that come the tables themselves. No particular order is required, though since all the tables except Strings can be allocated a fixed chunk of flash String table entries have variable length it's most convenient to have Strings come last.place it last.

    To make alignment easier we use 32-bit fields wherever possible, even for 16-bit quantities such as local port numbers.

    Code Block
    none
    none
    
    typedef uint32_t StringOff; // Offset within the Strings table.
    

    The Ports table

    Code Block
    none
    none
    struct Port {
        uint32_t  id;             // Unique port number.
        uint32_t  channelId;      // Ref. to Channels table.
        uint32_t  channelPortNumlocalPort;      // Port's number within the channel.
        StringOff description;    // A short description of the port.
    };
    

    The Channels table

    Code Block
    none
    none
    struct Channel {
        uint32_t id;              // Unique channel number.
        unit32_t idWithinClass;   // Class-unique 0, 1, ... .
        unit32_t classId;         // Ref. to Channel Classes table.
        StringOff description;
    };
    

    The Channel Classes table

    Code Block
    none
    none
    struct ChannelClass {
        uint32_t  id;
        uint32_t  driverId;
        unit32_t  bandwidthId;
        StringOff shortName;
        StringOff description;
    };
    

    The Drivers table

    Code Block
    none
    none
    Struct Driver {
        uint32_t  id;
        uint32_t  containerName;
        StringOff description;
    };
    

    The Bandwidths table

    Code Block
    none
    none
    struct Bandwidth {
        uint32_t  id;
        StringOff description;
    };
    

    On Virtex-4 RCEs the bandwidth ID is just the number of Multi-Gigabit Tranceivers used by the plugin. The ID zero is reserved for non-network plugins.

    Example configuration tables

    Here's what the tables would look like for an Virtex-4 RCE that defines nothing but the standard facilities that all RCEs have regardless of application:

    The Ports table:

    ID

    Channel ID

    Local ID

    Description

    0

    0

    0

    "Local area network"

    1

    1

    0

    "Configuration flash"

    The Channels table:

    ID

    Id in class

    Class ID

    Description

    0

    0

    0

    "Local area network"

    1

    0

    1

    "Configuration flash"

    The Channel Classes table:

    ID

    Driver ID

    Bandwidth ID

    Short name

    Description

    0

    0

    4

    "eth"

    "ethernet"

    1

    1

    0

    "config"

    "Configuration flash"

    The Drivers table:

    ID

    Container name

    Description

    0

    <name1>

    "Virtex-4 10 Gb/s ethernet"

    1

    <name2>

    "Virtex-4 configuration flash"

    The Bandwidths table:

    ID

    Description

    0

    "non-network"

    1

    "2.5 Gb/s"

    2

    "5.0 Gb/s"

    3

    "7.5 Gb/s"

    4

    "10.0 Gb/s"