PREV NEXT INDEX



Appendix B. Using XTC

Subsystems that desire a reliable data stream or datagram service will want to use XTC services: A transport layer over the target communications (TC) link layer.

XTC is based on some of the ideas of TCP, with some features deleted because of the point-point nature of the TC. Either the target or the DeviceMate can actively open a connection or listen for a connection. The actual XTC library is almost identical on both ends. Since XTC is mainly symmetric, the rest of this document applies equally to the target or the DeviceMate unit, unless otherwise noted. The word "peer" is used to denote the target processor (TP) or the DeviceMate unit (DMU) when the distinction is not important.

An established connection is referred to as a "channel," in order to distinguish it from a TCP "socket." Any subsystem (out of the 255 allowed) can make use of XTC services. The subsystem "subtypes" are used as selectors for a particular channel instance. One subtype, 0xFF, is reserved as a "broadcast" to all channels belonging to the given subsystem. 0x00 through 0x7F are reserved for direct subsystem use. This leaves a maximum of 127 channels per subsystem, with channel numbers ranging from 0x80 through 0xFE. This is a potentially large number of resources which may not be able to be supported simultaneously on the peer. Available resources will be limited to a configured number of channels. Each channel endpoint (analogous to TCP sockets) will specify channel state, buffers, RTT estimates and any other information associated with the channel. Each subsystem will have its own pool of channels so that each subsystem has a minimum guaranteed number of endpoints.

When an subsystem initializes, it will send a "broadcast" NEG (negotiate) flag to reset any resources on the peer. All NEG packets contain a reason code and other negotiated information. The initial NEG broadcast specifies a subsystem initialization code. The peer will respond with a NEG (with initialize-acknowledge code) so that the originator knows that the peer is available and synchronized.

NEG can also be sent to individual channels, in which case it embodies some of the properties of the TCP RST (reset) flag, but can also specify a reason code and other diagnostic information. Any protocol error will result in a NEG flag being sent in order to renegotiate the channel.

The application and subtype fields from the TC header are part of the logical XTC header. The data portion of each TC packet contains a 5-byte header which contains flags, receive window, sequence number and acknowledgment number. SEQ/ACK numbers are 16 bits each. Flags and window are compressed into a single byte. There are 4 bits for the possible flags (SYN, ACK, FIN, NEG) and the available receive window is encoded in the remaining 4 bits which is interpreted as floor(log2(windowsize)). If the window size is zero, then a zero code is used. The peer must always interpret a window field of zero as meaning a closed window (not a window of 1). This logarithmic coding of available window provides fine resolution when the window is nearly closed, but very coarse resolution when it is half- to fully open. To compensate for this, each peer keeps track of the right edge of the window, using the fact that no peer is allowed to contract the window edge to the left.

B.1 Library Support

XTC clients (i.e.,subsystems that use XTC) must include in their code:


#use "dm_xtc.lib" (for Rabbit-based targets)
#include "dm_xtc.h"   (for nonRabbit-based targets)

and in the companion subsystem on the DeviceMate unit there must appear the statement:


#use "targetproc_xtc.lib"

B.2 Data Structures

Each XTC client (both on the target and on the DeviceMate) must declare one instance of a XTCApp structure and at least one instance of a XTCChan structure. The latter structure must be initialized to zero by the subsystem. The XTCApp struct must have some of its fields initialized to appropriate values before the data structure is registered. Examples of doing this are in the subsystems that use XTC: dm_var.lib, targetproc_var.lib, etc.

B.2.1 Registration

On the DeviceMate unit, for each subsystem that uses XTC, an XTCApp structure must be registered using targetproc_xtc_register() before calling targetproc_init().

On the target, for each subsystem that uses XTC, an XTCApp structure must be registered using devmate_xtc_register() before calling devmate_init().

B.2.2 XTCApp Structure

This data structure is defined in tc_xtc.lib. It contains fields that must be filled in by any subsystem wishing to use XTC services.


typedef struct _XTCApp{

// Fields to set up before calling the register function


   uint8 appno;         // Application code
uint8 numchans;      // Number of channels in following array
uint16 txbufsize;    // Transmit buffer size w/out TC header
uint16 rxbufsize;    // Receive buffer size w/out TC header
XTCChan * chans;     // Channel array

// Fields initialized by the subsystem's _xxxx_init().


   uint8 numtxbufs;     // # of transmit buffers (usually 1,
                        // maybe 2 for high speed)
uint8 numrxbufs;     // Number of receive buffers
uint16 reqpacing;    // Our requested pacing (sent to peer).
uint8 aflags;        // Subsystem flags as follows:
#define XTC_AF_READY 0x01      // Subsystem is ready to establish
                               // channels with peer
#define XTC_AF_BCASTNEG 0x02   // Broadcast NEG, waiting for
                               // a response
#define XTC_AF_SERVER 0x80    // This is a DeviceMate app struct                                // (else TP)
#define XTC_AF_CONTROL 0x40  // DeviceMate unit: automatically
                             //   listen on channel 0 (control).
                             // Target processor: automatically
                             //   active open channel 0.
                             // If this flag is set in both, then
                             // the control channel will be opened
                             // whenever devmate_xtc_ready()
                             // or targetproc_xtc_ready()
                             // returns true.
#ifdef FUNCPTR_PROTOTYPES

   void (*tc_handler)(_xtcappptr app, _TCHeader * hdr, faraddr_t data);

#else

   void (*tc_handler)();     // Handler for app subtypes that
                             // are not XTC
#endif

// the rest of the fields in this structure are internal or
// initialized by devmate_xtc_init() or targetproc_xtc_init().


          .
          .
          .
} XTCApp;

B.2.3 XTC Configuration Macro

TC_MAX_XTC_APPS

Defaults to 4, which allows for the currently defined set of subsystems that use XTC services, namely TCP/IP, file system, web page variables and e-mail. This macro may be defined before the inclusion of dm_xtc.lib.

B.3 XTC API


_devmate_xtc_init



void _devmate_xtc_init(void);

Description

Initialize (or re-initialize) use of XTC layer.

Library

dm_xtc.lib (Rabbit-based targets)
dm_xtc.c (nonRabbit-based targets)


devmate_xtc_ready



int devmate_xtc_ready(XTCApp * app);

Description

Initiate a connection at the subsystem level, and test the connectivity state of the XTC subsystem. Returns positive when ready, 0 when trying to establish connectivity, or -1 if connectivity cannot be established.

This function initiates the process of establishing connectivity, by sending a broadcast NEG packet to the peer. If the peer responds with a broadcast NEG then the subsystem is considered to be connectable and the function returns positive. If the peer responds with an "app not registered" system message, then it is assumed that the subsystem is not defined on the peer, and -1 is returned. (This may be because the DeviceMate unit has not registered the same subsystem number.) Otherwise zero is returned and the subsystem should keep trying.

This function does not call devmate_tick(), so the subsystem should spin on this function using e.g.,


while (!devmate_xtc_ready(&MyApp)) devmate_tick();

Parameters

app

This is a pointer to the subsystem's state structure.

Return Value

³1: Connection is established
 0: Trying to establish connectivity
-1: Connectivity could not be established

Library

dm_xtc.lib (Rabbit-based targets)
dm_xtc.c (nonRabbit-based targets)


devmate_xtc_register



int devmate_xtc_register(XTCApp * app, uint16 rxlen, uint16 txlen);

Description

This function must be called before devmate_init(), once only for each subsystem that uses XTC. The caller should initialize the necessary fields in the XTCApp struct, including the channel array as follows: either memset the entire channel struct to zero (in which case the parameters will be used to allocate suitable buffers etc.) or memset the channel to zero except for the rx and/or tx xbuf. If either rx or tx xbuf has a non-zero blen field, then it is assumed to be already initialized. rxlen/txlen must be at least 2 greater than the MSS.

Parameters

app

This is a pointer to the subsystem's state structure.

rxlen

Default buffer size for receive buffer

txlen

Default buffer size for transmit buffer

Return Value

 0: Success
-1: Error, too many subsystems
-2/-3: Buffer size error

Library

dm_xtc.lib (Rabbit-based targets)
dm_xtc.c (nonRabbit-based targets)


xtc_abort



int xtc_abort(XTCApp * app, uint8 chan);

Description

Force a channel to close, informing the peer if there is an active session. This generally causes a NEG packet to be sent, and forces the channel to the closed state. Both sides of the session will receive a "reset" reason code if they test the channel using xtc_error().

If a session is established, but is immediately aborted with no transfer of data, then xtc_estab() will return -1, xtc_error() will return XTC_NEGCODE_RESET, and there will be no readable data.

Parameters

app

This is a pointer to the subsystem's state structure.

chan

The particular connection that will be forcibly closed

Return Value

0

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_aread



int xtc_aread(XTCApp * app, uint8 chan, char * data, uint16 len);

Description

Read queued data, but only if the specified length of data is immediately available in the receive buffer.

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

data

Location of data to read

len

Number of bytes of data to read

Return Value

 0: Not len amount of data available to read
-1: Receive buffer not large enough to hold len amount of data
-2: Channel is not readable
len: Data was successfully removed from the receive queue

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_areadp



int xtc_areadp(XTCApp * app, uint8 chan, faraddr_t data, uint16 len);

Same as xtc_aread(), except uses xmem address for data.


xtc_awrite



int xtc_awrite(XTCApp * app, uint8 chan, char * data, uint16 len);

Description

Queue data for transmission, but only if there is sufficient space in the transmit buffer. The `a' stands for "atomic."

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

data

Location of data to write

len

Number of bytes of data to write

Return Value

 0: Data cannot be queued
-1: Transmit buffer not large enough
-2: Channel is not writable
len: Data successfully queued

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_awritep



int xtc_awritep(XTCApp * app, uint8 chan, faraddr_t data, uint16 len);
Same as xtc_awrite(), except uses xmem address for data.

xtc_close



int xtc_close(XTCApp * app, uint8 chan);

Description

Indicate that the channel is closed for writing. The channel will generally still be readable until the peer also issues xtc_close(). If the other side never closes its side of the channel, then it will be necessary to use xtc_abort() to force the channel closed. If the channel is passively opened, with no session established, then it will be quietly closed.

The return code may be safely ignored: it returns non-zero only if xtc_close() has already been called for this channel, or the channel does not exist.

Note that the channel may be closed yet readable, i.e. the subsystem did not finish reading data. xtc_readable() is a better test for a closed channel when it is important that all data be read

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

Return Value

!0: xtc_close() was already called or the channel does not exist

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_closed



int xtc_closed(XTCApp * app, uint8 chan);

Description

Returns non-zero only if the channel is not defined, or fully closed. After calling xtc_close(), the subsystem can spin on this function to wait for complete termination of the session.

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

Return Value

 0: Channel is fully closed
!0: Channel is not defined, or it is not fully closed

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_error



int xtc_error(XTCApp * app, uint8 chan);

Description

Returns the most recent error code from the channel. The code will be zero if the channel has successfully closed after a previous session, or is currently open. Otherwise, a non-zero error code may be returned in the case that the channel was reset (NEG) by the peer. The actual error code will be one of a documented set of "official" error codes, or, if not one of these, will be a diagnostic code to assist developers.

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

Return Value

See "Description"

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_estab



int xtc_estab(XTCApp * app, uint8 chan);

Description

This function checks the status of the connection. After an active or passive open, the subsystem should spin on xtc_estab() waiting for a non-zero return value. After xtc_estab() returns non-zero, the channel state should be examined using the other status functions. It is possible for xtc_estab()to return non-zero for a closed channel. This means that the channel became active, but was immediately reset by the peer. In this case, the return code will be negative, or this can be subsequently be tested using xtc_error().

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

Return Value

 0: Channel has been opened (active or passive) but not yet ready to transfer data

-1: Channel closed and an error occurred in the previous session (xtc_error() will return a non-zero error code in this case)

>0: Channel is readable, or successfully closed

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_flush



int xtc_flush(XTCApp * app, uint8 chan);

Description

Forces XTC to send the queued transmit data as soon as possible. Normally, there is no need to call this function, as xtc_write() will send data at the optimum point in time considering link efficiency. However, sometimes the subsystem needs the timeliest response, in which case this function can be used. Note that XTC uses the Nagle algorithm by default, however this can be overridden by a channel flag or by use of xtc_flush().

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

Return Value

 0: Queued data was transmitted
-1: Channel not writable

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_listen



int xtc_listen(XTCApp * app, uint8 chan, int (*handler)());

Description

Passively open the specified channel. After passively opening a channel, the subsystem must spin on xtc_estab(). When xtc_estab() returns non-zero, a session is either currently open, or a transaction was received, or the channel was reset by the peer. At this point, any results should be garnered (or the channel may be used in streaming mode) then the channel may be closed and re-used with a new xtc_listen() call after xtc_closed() returns true.

The handler function that may be passed as the third parameter has the following prototype:


int handler(XTCApp * app, XTCChan * c, xbuf * tx, long buf, uint16 len);

app and c are pointers to the subsystem and channel contexts (which may not need to be accessed if the handler is devoted to a single channel). tx is a pointer to the transmit buffer, in which a response is to be placed. buf and len specify the physical address and length of the request data.

A response is simple to add: the function xbuf_append() is called with tx, and the response data:


int xbuf_append(xbuf * cb, long data, uint16 dlen);

The handler function should return the result from xbuf_append(), i.e. the number of bytes successfully queued, or -1 if an error occurred. If -1 is returned, the session is aborted so that the peer can tell (by examining the result of xtc_error()) that the transaction failed.

The response should not be longer than app->mss. If it is longer, then the response will not be sent in a single segment. This should be transparent to the receiving peer apart from the longer time necessary, however, the intention of transaction mode is to allow quick request/response processing.

If no handler function is specified (i.e. NULL is passed as the third parameter to xtc_listen()), a default response of zero data is generated. The request data can still be obtained in the mainline xtc_listen() loop, after xtc_estab() returns non-zero. If not actually read, the request data is discarded when xtc_listen() is next called.

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

handler

Pointer to function that will handle transaction mode requests. If this pointer is NULL, requests will still be accepted, but responses will contain no data.

Return Value

 0: Channel was opened passively
-1: Error, e.g., channel was already open or the channel number was not configured

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_open



int xtc_open(XTCApp * app, uint8 chan);

Description

Open a new channel.

Parameters

app

Pointer to the subsystem's state structure

chan

The XTC connection

Return Value

 0: Success
-1: Channel already open or doesn't exist

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_opts



int xtc_opts(XTCApp * app, uint8 chan, uint8 optnum, uint16 value)

Description

Specify channel or subsystem options. optnum specifies the option number (XTC_OPT_*) and value is a value appropriate for the specified option. Most options apply for the life of the subsystem, but some may only apply to the next or current session. Some options may apply to the subsystem as a whole, others to the specific channel number.

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

optnum

The option number. Actual options are:

XTC_OPT_SERVER: subsystem to act as the DeviceMate

XTC_OPT_CONTROL: subsystem automatically listens on control channel 0, if server; otherwise it actively opens the control channel

XTC_OPT_NONAG : channel to bypass Nagle algorithm

All options currently take a boolean parameter value: 0 = turn setting off, else turn it on.

value

An appropriate value for the specified option

Return Value

 0: Option set successfully
-1: Error

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_preread



int xtc_preread(XTCApp * app, uint8 chan, char * data, uint16 len);

Same as xtc_read(), except that the data is not removed from the queue. This is a macro which invokes xtc_prereadp().


xtc_prereadp



int xtc_prereadp(XTCApp * app, uint8 chan, faraddr_t data, uint16 len);

Same as xtc_readp(), except that the data is not removed from the queue.


xtc_read



int xtc_read(XTCApp * app, uint8 chan, char * data, uint16 len);

Description

Read queued data, to a maximum of len bytes.

Returns from 0 to len, or -1 if channel not in a readable state. A channel may be readable when closed, and indeed should not be re-opened until all queued data have been read, however if opened before that then the queued data will be discarded.

If data is NULL, then the data is merely removed from the queue.

This is a macro which invokes xtc_readp().

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

data

Pointer to data to read

len

Number of bytes

Return Value

³0: Number of bytes read
-1: Channel not readable

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_readable



int xtc_readable(XTCApp * app, uint8 chan);

Description

This function returns positive if the channel is currently readable. This means that there is either unread data in the receive buffer, or that the channel is still open and able to receive more data from the peer. A channel can be readable even after it is closed. Any unread data in the receive buffer is only discarded when the channel is re-opened.

The return value also indicates the amount of data in the receive buffer. The number of bytes that may be read immediately (by calling xtc_read()) is obtained by subtracting 1 from the return value of this function.

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

Return Value

 0: Channel is not in a readable state.

>0: Channel is currently readable, subtracting 1 from this return value is the number of bytes that may be read immediately (by calling xtc_read()).

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_readp



int xtc_readp(XTCApp * app, uint8 chan, faraddr_t data, uint16 len);

Same as xtc_read(), except uses xmem address for data.


xtc_writable



int xtc_writable(XTCApp * app, uint8 chan);

Description

This function returns positive if the channel is currently writable. This means that the channel is open (but not necessarily established), and xtc_close() has not yet been called.

The return value also indicates the number of bytes that may be immediately written to the transmit buffer (by calling xtc_write()). The amount of free space in the buffer is calculated by subtracting 1 from the return value.

Note that it is possible to write to a channel that is not established. There is a limit to the amount of data which may be buffered, however the buffered data will be sent immediately when a connection is established.

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

Return Value

 0: Channel is not in a writable state.

>0: Channel is currently writable, this return value is the number of bytes that may be immediately written to the transmit buffer (by calling xtc_write()).

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_write



int xtc_write(XTCApp * app, uint8 chan, char * data, uint16 len)

Description

Queue data for transmission. The length parameter is defined as unsigned, however in practice the specified length should be less than or equal to INT_MAX (32767) since the return value, which reflects the amount actually written, is signed.

If xtc_writable()-1 is positive, then that amount of data is guaranteed to be accepted by xtc_write() if there are no intervening XTC calls.

xtc_write() may be called immediately after xtc_open(), providing the amount of data is less than or equal to app->mss.

This is a macro which invokes xtc_writep().

Parameters

app

Pointer to the subsystem's state structure.

chan

The XTC connection

data

Pointer to data to read

len

Number of bytes to queue

Return Value

³0: Number of bytes queued (maximum number of bytes is len)
-1: Channel not writable

Library

tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)


xtc_writep



int xtc_writep(XTCApp * app, uint8 chan, faraddr_t data, uint16 len);

Same as xtc_write(), except uses xmem address for data.


Z-World
http://www.zworld.com
Voice: (530) 757-3737
FAX: (530) 757-3792
sales@zworld.com
PREV NEXT INDEX