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
XTCAppstructure and at least one instance of aXTCChanstructure. The latter structure must be initialized to zero by the subsystem. TheXTCAppstruct 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
XTCAppstructure must be registered usingtargetproc_xtc_register()before callingtargetproc_init().On the target, for each subsystem that uses XTC, an
XTCAppstructure must be registered usingdevmate_xtc_register()before callingdevmate_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_PROTOTYPESvoid (*tc_handler)(_xtcappptr app, _TCHeader * hdr, faraddr_t data);#elsevoid (*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 established0: Trying to establish connectivity-1: Connectivity could not be establishedLibrary
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 theXTCAppstruct, 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-zeroblenfield, 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 errorLibrary
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 returnXTC_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
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
data
len
Number of bytes of data to read
Return Value
0: Notlenamount of data available to read-1: Receive buffer not large enough to holdlenamount of data-2: Channel is not readablelen: Data was successfully removed from the receive queueLibrary
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
data
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 writablelen: Data successfully queuedLibrary
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 usextc_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 readParameters
app
Pointer to the subsystem's state structure.
chan
Return Value
!0:xtc_close()was already called or the channel does not existLibrary
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
Return Value
0: Channel is fully closed!0: Channel is not defined, or it is not fully closedLibrary
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
Return Value
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. Afterxtc_estab()returns non-zero, the channel state should be examined using the other status functions. It is possible forxtc_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 usingxtc_error().Parameters
app
Pointer to the subsystem's state structure.
chan
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 closedLibrary
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 ofxtc_flush().Parameters
app
Pointer to the subsystem's state structure.
chan
Return Value
0: Queued data was transmitted-1: Channel not writableLibrary
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(). Whenxtc_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 newxtc_listen()call afterxtc_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);
appandcare pointers to the subsystem and channel contexts (which may not need to be accessed if the handler is devoted to a single channel).txis a pointer to the transmit buffer, in which a response is to be placed.bufandlenspecify the physical address and length of the request data.A response is simple to add: the function
xbuf_append()is called withtx, 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 ofxtc_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.
NULLis passed as the third parameter toxtc_listen()), a default response of zero data is generated. The request data can still be obtained in the mainlinextc_listen()loop, afterxtc_estab()returns non-zero. If not actually read, the request data is discarded whenxtc_listen()is next called.Parameters
app
Pointer to the subsystem's state structure.
chan
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 configuredLibrary
tc_xtc.lib (Rabbit-based targets)
tc_xtc.c (nonRabbit-based targets)
xtc_open
int xtc_open(XTCApp * app, uint8 chan);Description
Parameters
app
Pointer to the subsystem's state structure
chan
Return Value
0: Success-1: Channel already open or doesn't existLibrary
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.
optnumspecifies the option number (XTC_OPT_*) andvalueis 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
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 algorithmAll 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: ErrorLibrary
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 invokesxtc_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
lenbytes.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
data
len
Return Value
³
0: Number of bytes read-1: Channel not readableLibrary
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
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 callingxtc_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
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 callingxtc_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 byxtc_write()if there are no intervening XTC calls.
xtc_write()may be called immediately afterxtc_open(), providing the amount of data is less than or equal toapp->mss.This is a macro which invokes
xtc_writep().Parameters
app
Pointer to the subsystem's state structure.
chan
data
len
Return Value
³
0: Number of bytes queued (maximum number of bytes islen)-1: Channel not writableLibrary
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);
| Z-World http://www.zworld.com Voice: (530) 757-3737 FAX: (530) 757-3792 sales@zworld.com |