.po 1i .he 'ACC'Preliminary'\*(td' .fo ''%'' .ba 1i .nr ii 1.25i .nr si 0.3i .ps +4 .sp 3 .ce \fB5250 Programmers Interface\fR .ps .sp 2 .sh 1 "Introduction" .lp This document describes the preliminary design for the ACC X.25 Programmers Interface for the 5250 and 6250 boards. .lp The Programmers Interface (PI) is an extension to the standard [5/6]250 Unix Driver. It allows user processes to access the front end (FE) at the same level as the driver. This can be used to implement new protocols over X.25. .lp Using the Programmer's Interface allows full access to the ACC X.25 Front End. All commands are available to the programmer. The PI and FE handle packet numbering and packet flow control thus greatly simplifying X.25 programming. .sh 1 "PI Devices" .lp Communication with the FE is done through a character device driver. Character special devices are opened by user programs. Packets to/from the FE are transmitted via \fIioctl(2)\fR calls to the open device. .lp Each open device is referred to as a \fIchannel\fR. The channel uses ioctl calls to reserve logical circuits. Each logical circuit can be used to establish a virtual circuit and transfer data with a remote host. The user is responsible for clearing any established call and freeing any logical circuits before closing the channel. Outstanding data queued within the driver will be aborted automatically. .lp Each channel has two queues associated with it: an input queue and one or more output queues. The input queue holds data that has come in from all logical circuits that have been associated with the channel as well as supervisory (logical circuit 0) data. The input queue will hold at most 1 message at a time from any given logical circuit. This does not apply to the supervisory circuit. Thus the length of this queue should be equal to the sum of 1) the maximum number of logical circuits a channel will have open simultaneously and 2) the maximum number of supervisory messages that will be presented to the channel at one time. .lp Channels may be shared between processes using standard UNIX open file inheritance or by multiple opens of the same minor device. Currently the driver does not support the non-blocking and block if in use flags to the open call. .lp There are 256 minor devices for each major device. The PI interface consists of a single major device regarless of the number of ACP boards in the system. Thus, the minor device numbers are split among the available boards. The constant PILINES in if_pi.c defines the number of minor devices per board. In general this number should simply be 256 divided by number of boards present. .lp The character device design allows the PI interface to be ported to many Unix drivers. This includes those that do not support a socket interface. This design also allows more different process structures for managing data traffic (See section 5). Access to the FE is controlled using the permission bits of the character device entries in the file system. .sh 1 "Programming" .lp The PI allows the user program to send any command supported by the FE. It is recommended that only those commands that affect a single logical channel be used. Global commands may adversely affect the IP and X.29 interfaces if they are being used simultaneously. .lp Each command or data packet is sent in a single \fIioctl\fR(2) call. All available ioctl calls are listed below. If an invalid command is sent to the PI ioctl handler then the ioctl call will return -1 and errno will be set to ENOTTY. .sp .ip "\fBXIOGETLCN\fR" This call will reserve a logical circuit and associate it with the channel that the ioctl is issued on. The byte of data used by the ioctl will contain the lcn of the channel reserved. A value of 0 indicates that no circuits are available. .ip "\fBXIOWRITE\fR" The write ioctl uses the following structure to describe the user buffer. .(l struct pi_dblock { caddr_t dataptr; /* pointer to user data to be written */ u_int length; /* length of data pointed to by dataptr */ u_short lcn; /* logical channel to send data out on */ u_char func; /* read status , write function value */ u_char subfunc; /* read substatus, write subfunction value */ u_short flags; /* special flags */ }; .)l The write ioctl is used to send data or supervisory messages to the FE. The data is pointed to by \fIdataptr\fR. The amount of data is given by \fIlength\fR. The \fIlcn\fR field gives the logical circuit that the data is to go out on. If this value is 0 then the data should be a supervisory message. A channel is permitted to write only on circuit 0 and those logical circuits that it has reserved for its use. (for more details see the XIOGETLCN description). .ip The \fIfunc\fR field is currently not used. It is reserved for future enhancements. It should always be set to 0. The \fIsubfunc\fR field is used to set the q-bit for packets. The value of the \fIsubfunc\fR field is or-ed into the subfunction byte in the FE's data request mailbox (See ACP [5/6]250 Hardware Installation Manual for more information). To set the q-bit for the packet the value of \fIsubfunc\fR should be 0x80 (hexadecimal 80) otherwise this field should always be 0. .ip The data is copied from the user buffer to an mbuf and then queued for output. If the data is less than or equal to (MLEN-1) (111) bytes then a small mbuf is used. If the data is 112 to 1K bytes then a page cluster is allocated to create a large mbuf. The maximum size for a packet is CLBYTES (1024 on most systems) bytes. .ip The mbuf allocated is queued for output. If the queue is full then the process will sleep waiting for it to empty. If the DB_NONBLOCK bit is set in \fIflags\fR then the write is non-blocking. The ioctl call will return -1 and errno will be set to EWOULDBLOCK. The length of the per logical circuit output queue is defined by DDA_OQMAX in if_ddavar.h. This limit applies to all interfaces: IP, x29, and PI. .ip The following table gives values returned in errno by the XIOWRITE ioctl and all possible reasons for the error. .TS box,tab(:); l l. EINVAL:lcn is <= 0 or greater than max lcns configured. EINVAL:lcn specified is not associated with this channel. EINVAL:length specified is <= 0 or greater than CLBYTES. ENOBUFS:An mbuf or cluster could not be allocated. EFAULT:dataptr address violation. EWOULDBLOCK: operation would block. .TE .ip "\fBXIOREAD\fR" The read ioctl uses the same pi_dblock structure as the XIOWRITE ioctl. The program must fill in the dataptr and length fields. The flags field can have the value of \fIDB_NONBLOCK\fR to specify a non-blocking read. .ip Upon return the length field will contain the number of bytes actually read. The lcn field will contain the logical circuit number that the data came in on. If the lcn field is 0 then the data should be interpreted as a supervisory message. Each read will return 1 complete packet. The buffer provided must be able to accept the largest possible packet. If supervisory or data packets come in when no user read has been issued then the packet will be queued on the channel input queue. Additional packets will be dropped and an error message printed on the console. This message indicates that the length of the input queue should probably be increased. The length of the input queue is set by PIQLEN in if_pi.c. .ip It should always be set to 0. The \fIsubfunc\fR field is used to set the q-bit for packets. The value of the \fIsubfunc\fR field is or-ed into the subfunction byte in the FE's data request mailbox (See ACP [5/6]250 Hardware Installation Manual for more information). To set the q-bit for the packet the value of \fIsubfunc\fR should be 0x80 (hexadecimal 80) otherwise this field should always be 0. .ip The \fIsubfunc\fR field will contain the C_SBSTAT (completion sub-status) data contained in the Host Completion Mailbox. This field indicates whether the q-bit was set for the packet. A value of 0x80 (hexadecimal 80) indicates the q-bit was set otherwise the value of \fIsubfunc\fR will be 0. .ip The \fIfunc\fR field will containing the C_STATUS (completion status) data from the Host Completion Mailbox. Since the driver always returns a complete, valid packet this value is uninteresting. .ip The following table gives values returned in errno by the XIOREAD ioctl and all possible reasons for the error. .TS box,tab(:); l l. EINVAL:the length specified is too small to hold the entire packet. EFAULT:dataptr address violation. EWOULDBLOCK:operation would block. .TE .ip "\fBXIORPEND\fR" This ioctl will return the number of messages queued on the channel's input queue. .ip "\fBXIORSIG\fR" This ioctl specifies a signal to be sent to the process when data is available to be read on this channel. The program passes an integer specifying the signal number as defined in the <sys/signal.h> include file. .ip "\fBXIOACCRING\fR" The lower and upper fields specify a range of protocol byte values that this channel will accept. The proto_range structure is used. .(l typedef proto_range { u_char lower; u_char upper; } proto_range; .)l The protocol byte of an incoming call is the first byte of the protocol field in the ring packet. Thus an incoming call with a protocol byte within the requested range may be routed to this PI device. If more than one PI device has requested rings of the same protocol type then the driver will arbitrarily (not necessarily fairly) give the ring to one of the devices. .ip "\fBXIONORING\fR" Inform the driver that the device will no longer accept incoming calls. This command will not purge any rings that have already been put in the data queue for the device. .ip "\fBXIOANYPROTO\fR" Issuing this ioctl will tell the driver that any calls that have protocol types not handled by any other channel may be routed to this channel. .ip "\fBXIOCLRCHAN\fR" This call will flush any input data queued in the driver for the channel that the ioctl is issued on. .ip "\fBXIOFREELCN\fR" This call is the complement of XIOGETLCN. It is used when the process is finished with a logical circuit. The process is responsible for clearing the call before freeing the circuit. This call will abort any outstanding writes. .ip The following table gives values returned in errno by the XIOFREELCN ioctl and all possible reasons for the error. .TS box,tab(:); l l. EINVAL:lcn is <= 0 or greater than max lcns configured. EINVAL:lcn specified is not associated with this channel. .TE .ip "\fBXIOABORT\fR" This call will abort any outstanding writes for the logical ciruit specified. This should be done before sending a CLEAR LOGICAL CIRCUIT supervisory message to ensure that no data is sent on the circuit after it has been cleared. .ip The following table gives values returned in errno by the XIOABORT ioctl and all possible reasons for the error. .TS box,tab(:); l l. EINVAL:lcn is <= 0 or greater than max lcns configured. EINVAL:lcn specified is not associated with this channel. .TE .sh 1 "Interaction with IP and X.29" .lp The PI interface can operate simultaneously with IP and X.29 interfaces. The \fIacpconfig\fR program supplied by ACC is used to configure the FE and bring up the link. .lp The main point of contention between the interfaces is allocation of virtual circuits. All interfaces share the same virtual circuit table. This means that there is a limit of 126 circuits among all types of traffic. A virtual circuit is reserved each time X.29 device is opened as well as each time a PI channel make an XIOGETLCN call. IP traffic must use whatever is left over. Virtual circuits between host pairs are never shared between traffic types. .lp It is possible for the PI interface to handle IP or X.29 traffic. The PI has precedence over the DDA and X.29 interfaces. .sh 1 "Usage Examples" .lp The following are several ways in which processes could be structured to process incoming supervisory and data traffic using the PI devices. .sh 2 "Single Process" .lp One process opens many PI devices. The process knows to open a new channel when all its channels are in use. Alternatively the process could open one PI device and make multiple XIOLCNREQ calls to have multiple circuits associated with it. .sh 2 "Multiple Process" .lp Each process opens a channel and manages the communication on that channel. Each process could open more than one channel if desired. .sh 2 "Master Process with Children" .lp A single master process sits on a channel with rings enabled. When a call comes in the process forks. The child process handles the channel. The parent process opens a new channel. Either the parent or child process can answer the call. The master process can also make outgoing calls and fork children to process the data. After the child process has been created the parent may close the channel to free the file descriptor. .sh 2 "Master Process with Peers" .lp A master process sets up connections and informs other (already running) processes of the name of the PI device to open to process the data. The peer processes handle the data. Communication between peers can be done using some combination of shared memory, sockets, pipes, files and signals. .sh 2 "Server Process" .lp One process acts as a server. It is responsible for all manipulation of PI devices. It can have one or many channels open at a time. Other processes use sockets to establish connections to the server and to send requests and receive replies. Fig. 3 shows this process structure. It is not required that there be the same number of client processes as there are open PI devices. The server can allocate data any way it wishes. .(b F .sp 2 .PS P: [ down A: circle "process" "1" B: circle "process" "2" C: circle "process" "3" ] move;move S: box "server" move right 0.75i D: box "PI driver" invis line <-> from 1/4 <S.ne, S.se> to D.l dashed "PI dev" above line <-> from 1/2 <S.ne, S.se> to D.l dashed line <-> from 3/4 <S.ne, S.se> to D.l dashed line <-> from P.A to S.nw chop circlerad chop 0 line <-> from P.B to S.l "socket" above chop circlerad chop 0 line <-> from P.C to S.sw chop circlerad chop 0 .PE \fBFigure 3. Process structure for a PI server. Dashed lines are PI devices. Solid lines are sockets.\fR .sp .)b .bp .sh 1 "Supervisory Command Formats" .lp This section describes the commands to be used in the \fBSupr\fR command types and their formats. .sh 2 "Call Command Header" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: Command code (00) 1: LCN * 2 2: NA 3: Count 4-r: Common body .sp .5v .TE .sh 2 "Ring Command Header" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: Command code (01) 1: NA 2: VCN 3: Count 4-r: Common body .sp .5v .TE .sh 2 "Clear Virtual Circuit Command Header" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: Command code (02) 1: VCN 2: Cause code 3: Count 4: Diagnostic code 5-r: Common body .sp .5v .TE .sh 2 "Answer Command Header" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: Command code (03) 1: LCN * 2 2: VCN 3: Count 4-r: Common body .sp .5v .TE .bp .sh 2 "Clear Logical Channel Command Header" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: Command Code (04) 1: LCN * 2 2: Cause Code 3: Count 4: Diagnostic code 5-r: Common body .sp .5v .TE .sh 2 "Call, Ring, Answer, Clear Virtual Circuit, and Clear Logical Channel Commands Common Body" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH m: length of called address (0 to 14 decimal) m+1: called address in ASCII n: length of calling address (0 to 14 decimal) n+1: calling address in ASCII o: length of protocol (0 to 4) o+1: protocol p: length of facilities (0 to 63 decimal) p+1: facilities q: length of user data (0 to 124 decimal) q+1: user data .sp .5v .TE .ce NOTE Offset m begins at 4 for Answer, Call, and Ring. It begins at 5 for Clear Virtual Circuit and Clear Logical Channel. All length fields are binary values giving the number of bytes for the field to follow. .sh 2 "Reset Command" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: command code (040) 1: LCN * 2 2: cause code 3: count (0 or 1) 4: diagnostic code (optional) .sp .25v .TE .sh 2 "Reset Acknowledge" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: command code (041) 1: LCN * 2 2: NA 3: count (0) .sp .25v .TE .sh 2 "Interrupt Command" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: command code (042) 1: LCN * 2 2: reason code 3: count (0) .sp .5v .TE .sh 2 "Ready Command" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: command code (043) 1: LCN * 2 2: type code (zero=RNR, nonzero=RR) 3: count (0) .sp .5v .TE .sh 2 "Interrupt Acknowledge" .TS H box center; c c r|l. .sp .5v Byte Offset .sp .5v _ .TH 0: command code (044) 1: LCN * 2 2: NA 3: count (0) .sp .5v .TE .bp .sh 1 "Ioctl Header File and Structures" .nf /* * Ioctl's have the command encoded in the lower word, * and the size of any in or out parameters in the upper * word. The high 2 bits of the upper word are used * to encode the in/out status of the parameter; for now * we restrict parameters to at most 128 bytes. */ /* this structure is used when writing or reading data data */ struct pi_dblock { caddr_t dataptr; /* pointer to user data to be written */ u_int length; /* length of data pointed to by dataptr */ u_short lcn; /* logical channel to send data out on */ u_char func; /* read status , write function value */ u_char subfunc; /* read substatus, write subfunction value */ u_short flags; /* special flags */ }; /* pi_dblock.flags: The follwing values can be used to set bits */ #define DB_NONBLOCK 0x01 /* non-blocking read or write */ typedef struct proto_range { u_char lower; /* lower bound on protocol range (inclusive) */ u_char upper; /* upper bound on protocol range (inclusive) */ } proto_range; /* data write */ #define XIOWRITE _IOWR(t, 1, struct pi_dblock) /* data read */ #define XIOREAD _IOWR(t, 2, struct pi_dblock) /* see if data is ready to be read on a particular channel. * The field will return the number of pending data bytes. */ #define XIORPEND _IOR(t, 3, int) /* allow rings on this minor device. The proto_range structure specifies * the lower and upper bounds on the protocol byte of incomming calls */ #define XIOACCRING _IOW(t, 4, proto_range) /* specify that a protocol not requested by anyone else will be accepted on * this channel. */ #define XIOANYPROTO _IO(t, 5) /* reserve an lcn for use by this channel (minor device). The number of the * lcn is returned the the character passed */ #define XIOGETLCN _IOR(t, 6, u_char) /* free an lcn specified by the u_char parameter. This should be called for all * lcn's obtained with XIOGETLCN before the channel is closed. */ #define XIOFREELCN _IOW(t, 11, u_char) /* clear any data associated with a channel. The lcn is passed. Note that * this does not clear the circut. It only flushes queued data stored in the * driver */ #define XIOCLRCHAN _IO(t, 7) /* disallow incomming calls on this channel */ #define XIONORING _IO(t, 9) /* specify a signal to be sent to the process when there is data ready to * be read on a particular channel. The u_int specifies the signal to be * sent. */ #define XIORSIG _IOW(t, 10, u_int) /* abort all output for the given lcn. */ #define XIOABORT _IOW(t, 12, u_char) .fi