\input manualMacros.tex
\manBegin
\manPageInfo{RCI Reference Manual}{}{}
\manTitle{IOdevice}{7}
\manSection{NAME}
{\it \manName{IOdevice}} -- RCI I/O device and driver interface.
\manSection{INTERFACE}
The driver interface to an RCI I/O device is summarized below:

\cverbatim
#include <IOdevice.h>

read(dev, buffer, size)
   IO_DEVICE *dev;
   char *buffer;
   int size;

testRead(dev)
   IO_DEVICE *dev;

write(dev, buffer, size)
   IO_DEVICE *dev;
   char *buffer;
   int size;

testWrite(dev)
   IO_DEVICE *dev;

probe(dev)
   IO_DEVICE *dev;

attach(dev)
   IO_DEVICE *dev;

detach(dev)
   IO_DEVICE *dev;

signal(dev, signo)
   IO_DEVICE *dev;
   int signo;   

ioctl(dev, com, data)
   IO_DEVICE *dev;
   int com;
   void *data; @endcverbatim
\manSection{ARGUMENTS}
\manItem{{\tt dev} --}
Pointer to {\it device} structure.
\manItem{{\tt buffer} --}
Buffer for sending or receiving information.
\manItem{{\tt size} --}
Amount of information to send, or maximum amount of information
that can be received.
\manItem{{\tt signo} --}
Signal number.
\manSection{DESCRIPTION}
An RCI I/O device consists of, physically, some computer interface device
like a parallel port or serial line connect that is used to communicate
with an outside peripheral (like a robot).

In terms of software, an I/O device consists of an instantiated 
{\tt IO_DEVICE} structure (described below), and a collection of driver
routines that conform to the interface specified above. Pointers to the driver
routines are contained in the {\tt IO_DEVICE} structure.

{\tt read()} receives a data packet from the device, and should return
the number of bytes received.

{\tt testRead()} returns true when the device is ready to be
read from, and false
otherwise. This function can be used as a task wakeup function.
In particular, it is typically used to implement the robot ready function
(see {\tt ROBOT_READY()}).

{\tt write()} sends a packet of data to the device, and should return the
number of bytes sent.

{\tt testWrite()} returns true when the device is ready to be
written to, and false
otherwise. 

\manInset{NOTE: {\tt testWrite()} is on its way out. It is not used presently
by any RCI software at the time of this writing. Moreover, it is not
implemented by the {\tt sim} driver which is used whenever RCI is run in
simulator mode.} 

{\tt signal()} sends a notification signal to the device. 
In particular, the routine is used by the existing robot interface functions
to send wakeup and release signals to the robot controller (see
{\tt ROBOT_WAKEUP()}).

{\tt probe()} checks for the existence of the device, and is responsible
for setting the {\tt size} and {\tt location} fields of the {\it device}
structure. The {\tt probe()} routine should return -1 if the
device does not exist or appears to be malfunctioning.

{\tt attach()} initiates a control session with a device; it should
return -1 if it cannot do this.

{\tt detach()} disconnects the device and puts it into 
a ``known state''.

{\tt ioctl()} is used to set various options and modes associated
with the device. A few I/O control codes are predefined in {\tt <IOdevice.h>}:

\manItem{{\tt IOC_SIGINTER_ENABLE} --}
Enables interrupts on the device.

\manItem{{\tt IOC_SIGINTER_DISABLE} --}
Disables device interrupts.

\manItem{{\tt IOC_TIMEOUT} --}
Sets the {\tt timeout} field in the {\it device} structure to the
integer value pointed to by {\tt data}. This number is used 
internally by the driver routines to control their timeout tolerance.

\manItem{{\tt IOC_SET_BLOCKTIME} --}
Sets the maximum blocking time associated with read or write operations,
in milliseconds, to the integer value pointed to by {\tt data}. 
The number is also written into the 
{\tt blocktime} field in the {\it device} structure.

\manItem{{\tt IOC_GET_BLOCKTIME} --}
Returns the maximum blocking time permitted for a read or write operation,
in milliseconds, into an
integer pointed to by {\tt data}.

All of the above routines should return -1 in the event of an error
(see DIAGNOSTICS, below).

The {\it device} structure contains pointers to all of the driver functions,
as well as several data fields for use by the functions. These fields are:

\cverbatim
 char *name;             /* name of the device               */
 int unit;               /* unit number of the driver        */
 int address;            /* bus address of interface         */
 char *addrStr;          /* supplemental address information */
 int args[MAX_DEVARGS];  /* program supplied arguments       */
 unsigned char *location;/* memory address of interface      */
 int size;               /* size of the interface (in bytes) */
 unsigned long timeout;  /* a spin-loop timeout parameter    */
 int blocktime;          /* max. time read or write can block */
 int byteCount;          /* byte count for I/O operations    */@endcverbatim

\manItem{{\tt name} --}
Assigned by RCI. A copy of the string name of the device.
\manItem{{\tt unit} --}
Assigned by RCI. A unique unit number (small integer)
is assigned by RCI to each device of a given type 
used by a program; this can be used by the driver as an index into an
array of per-device data structures. The unit number depends only on the
order that devices are defined in the program, not on the actual location
of the device itself.
\manItem{{\tt address} --}
Assigned when the device is created (either from config file
information or a call to {\tt rciAllocDevice()}).
This identifies the physical location of the device; typically this
is its bus address.
\manItem{{\tt addrStr} --}
Addtional address information, in string form, that can be assigned when the
device is created with {\tt rciAllocDevice()}.

\manInset{{\bf WARNING:} This field is valid for applications which are
running on the arbiter CPU only. It is actually just a kludge around to
provide a way to pass TCP addressing information to the simulation device {\tt
sim}.}

\manItem{{\tt args} --}
Optional arguments supplied when the device is allocated (either from
config file information or a call to {\tt rciAllocDevice()}). These arguments
may supply any extra per-device information needed by the driver,
including extra addressing information.
\manItem{{\tt location} --}
Set by the {\tt probe()} routine. This is a pointer to the memory location
where the device can be found; assumably, this will lie somewhere in
the I/O space memory map that RCI provides to the tasks. The {\tt location} is
computed directly from the {\tt address} information.
\manItem{{\tt size} --}
Set by the {\tt probe()} routine. This is the size of the device, in bytes
(the amount of space the device takes up in the I/O space memory map).
\manItem{{\tt timeout} --}
Generally set by either the {\tt probe()} routine 
or the predefined I/O control {\tt IOC_TIMEOUT}.
This is a parameter from which the I/O routines decide how long to
wait before issuing a timeout error.
\manItem{{\tt blocktime} --}
Generally set by either the {\tt probe()} routine 
or the predefined I/O control {\tt IOC_SET_BLOCKTIME}.
This is a parameter which determines how long I/O routines which are
supposed to block should block before issuing a timeout error. It is 
different from the timeout parameter in that blocking may be acceptable,
and may also be a large number. The timeout parameter, on the other hand,
generally controls interactions that are assumed to be immediate.
\manItem{{\tt byteCount} --}
Set by the read function (and possibly the write function) 
to indicate to the calling routine
the number of bytes transferred during I/O.
\manSection{INSTALLATION}
The easiest way to write an I/O driver is to clone an
existing one. At the time of this writing, there exists an
I/O driver in the file {\tt priDriver.c}; this controls
a DEC DRV11 Q-bus parallel port. 
Driver specific definitions
and function declarations should be placed in a separate {\tt .h}
file. 

Once the driver is written, it may be installed in the RCI libraries
by editing the table {\tt IOdrivers} in the file
{\tt IOdriverTable.c}. The entry should consist of (1) a string
by which the driver will be referenced, and (2) the function pointers
for the driver itself, in the order that they are described above.
It will be necessary to declare the functions before the table; this can
be done by including the driver's {\tt .h} file.

After the file has been prepared, in must be compiled and installed into
the RCI system. Driver modules are normally kept in the directory
{\tt drivers}. New modules must be incorporated into this directory's
{\tt Imakefile}. If this is done properly, then the command {\tt make libs}
should compile the file and load it into the RCI libraries.

\manSection{DIAGNOSTICS}
All driver functions should return -1 in the event of error.
Error codes can be returned on the error stack (q.v.).
The following error codes,
defined in {\tt <errorCode.h>}, are used by the existing device
drivers:

\manItem{{\tt EDevTimeout} --}
No response from the device.
\manItem{{\tt ETransmit} --}
Data corruption was detected during transmission.
\manItem{{\tt ECount} --}
A bad data count (too large or negative) was either received or
specified for transmission.
\manItem{{\tt ENoDev} --}
Device does not exist (can be returned by {\tt probe()}, for instance).
\manItem{{\tt ESync} --}
Data transfer protocol error.
\manItem{{\tt EConnect} --}
Device is not ready; can't connect to it.
\manItem{{\tt EBadIoctl} --}
Invalid or unsupported {\it ioctl} command.

The file {\filefont drivers/driErrorMsgs.c} contains
string messages associated with these error codes.

\manSection{SEE ALSO}
\rightskip=0ptplus1fil
{\tt rciAllocDevice(3)}, {\tt rciScheduling(3)}, {\tt ROBOT_WAKEUP(3)},
{\tt ROBOT_READY(3)}, {\tt errorStack(3)}.
\manEnd
\end
