It is not necessary to create a driver support module in order to interface EPICS to hardware. For simple hardware device support is sufficient. At the present time most hardware support has both. The reason for this is historical. Before EPICS there was GTACS. During the change from GTACS to EPICS, record support was changed drastically. In order to preserve all existing hardware support the GTACS drivers were used without change. The device support layer was created just to shield the existing drivers form the record support changes.
Since EPICS now has both device and driver support the question arises: When do I need driver support and when don't I? Lets give a few reasons why drivers should be created.
The only thing needed to interface a driver to EPICS is to provide a driver support module, which can be layered on top of an existing driver, and provide a database definition for the driver. The driver support module is described in the next section. The database definition is described in chapter ``Database Definition".
Device drivers are modules that interface directly with the hardware. They are provided to isolate device support routines from details of how to interface to the hardware. Device drivers have no knowledge of the internals of database records. Thus there is no necessary correspondence between record types and device drivers. For example the Allen Bradley driver provides support for many different types of signals including analog inputs, analog outputs, binary inputs, and binary outputs.
In general only device support routines know how to call device drivers. Since device support varies widely from device
to device, the set of routines provided by a device driver is almost completely driver dependent. The only requirement is
that routines report
and init
must be provided. Device support routines must, of course, know what routines are
provided by a driver.
File drvSup.h
describes the format of a driver support entry table. The driver support module must supply a driver entry
table. An example definition is:
LOCAL long report(); LOCAL long init(); struct { long number; DRVSUPFUN report; DRVSUPFUN init; } drvAb={ 2, report, init }; epicsExportAddress(drvet,drvGpib);
The above example is for the Allen Bradley driver. It has an associated ascii definition of:
driver(drvGpib)
Thus it is seen that the driver support module should supply two EPICS callable routines: int
and report
.
This routine, which has no arguments, is called by iocInit
. The driver is expected to look for and initialize the
hardware it supports. As an example the init routine for Allen Bradley is:
LOCAL long init() { return(ab_driver_init()); }
The report routine is called by the dbior
IOC test routine. It is responsible for producing a report describing the
hardware it found at init time. It is passed one argument, level, which is a hint about how much information to display. An
example, taken from Allen Bradley, is:
LOCAL long report(int level) { return(ab_io_report(level)); }
Guidelines for level are as follows:
Hardware configuration includes the following:
The information contained in hardware links supplies some but not all configuration information. In particular it does not define the VME/VXI addresses and interrupt vectors. This additional information is what is meant by hardware configuration in this chapter.
The problem of defining hardware configuration information is an unsolved problem for EPICS. At one time
configuration information was defined in module_types.h
Many existing device/driver support modules still uses this
method. It should NOT be used for any new support for the following reasons:
The fact that it is now easy to include ASCII definitions for only the device/driver support used in each IOC makes the
configuration problem much more manageable than previously. Previously if you wanted to support a new VME modules
it was necessary to pick addresses that nothing in module_types.h
was using. Now you only have to check modules
you are actually using.
Since there are no EPICS defined rules for hardware configuration, the following minimal guidelines should be used:
#define
to specify things like VME addresses. Instead use variables and assign default values. Allow
the default values to be changed before iocInit is executed. The best way is to supply a global routine that can be
invoked from the IOC startup file. Note that all arguments to such routines should be one of the following:
int
char *
double