IOCCOREV4

Feb 20, 1997

Scope of This Document

iocCore includes:

Goals

The following are goals forEPICS base release 4.xx

Simple Overview

The rest of this document describes details concerning three basic extensions to the existing iocCore:

  1. Allow a field to be a structure or a pointer to a structure.
  2. A link field contains 2 things:
    1. A menu of choices.
    2. Given a choice, a pointer to a structure containing additional information.
  3. RSETs, DSETS, Driver Entry Tables extended to provide user defined interfaces.

Database Definition Changes

The name recordtype will be replaced by struct.

COMMENT: maybe we should use the names struct, recordtype, and recordlink.These are the three types of things discussed below.

The following field types in epics base release 3.13 will be changed:

  • DBF_DEVICE - This will disappear
  • DBF_XXXLINK - New semantics and implementation.
  • The following new or changed field types are provided:

  • DBF_PSTRING - A char * field.
  • DBF_VSTRING - A variable length field type.
  • DBF_INLINK - Same functionality as existing soft input links
  • DBF_OUTLINK - Same functionality as existing soft output links
  • DBF_FWDLINK - Same functionality as existing soft forward links
  • DBF_INSTRUCTLINK - Extension to capabilities of existing INP fields
  • DBF_OUTSTRUCTLINK - Extension to capabilities of existing OUT fields>
  • Should we consider these? I will not discuss any further in this document.

  • DBF_STRUCT - A substructure appears in generated include file.
  • DBF_PSTRUCT - Address of a structure. The record support module must allocate storage.
  • where

    DBF_PSTRING
    A char * field. Database puts free old storage and allocate new storage. This type is fine for fields like NAME, DESC, UNITS, Binary state names, etc. These fields infrequently change. Note that for typical databases we would use less storage because many string fields are never assigned values. The restriction of lengths of strings goes away.
    DBF_VSTRING
    A variable length string. Implementation could be modeled after some C++ implementation of string class. We can have a religous war about how this should be done. Thus would be an ideal type for any string field which can frequently change. The VAL fields of stringin and stringout fields come to mind.
    DBF_XXXLINKs
    DBF_INLINKs and DBF_OUTLINKs have an associated set of menus and for each menu choice a struct definition. The menu choices correspond to NULL, DB_LINKs, and CA_LINKs.
    DBF_XXXSTRUCTLINKs have an associated set of linkdefinitions, which are a replacement for the old device definitions. A definition has the form:
    link(<struct_name>.<field>,<link_struct_name>,<iid_name>,"<choice_string">)
    

    where:

    <struct_name>.<field>
    Identifies that struct and field within the structure that this definition references. Specifying ".<field>" eliminates the need for DTYP and also allows multiple hardware links per record.
    <link_struct_name>
    Provides the name of a structure that defines additional information for this link.
    <iid_name>
    Name of interface that will process link at run time. See below.
    <choice_string>
    A menu choice for selecting this link definition

    It is mandatory that menu choices be defined forNULL, DB_LINKs, and CA_LINKs. These choices must provide the same functionality as DBF_INLINK or DBF_OUTLINK.

    From the point of view of static database access, a link field consists of two components:

    1. a menu of choices.
    2. Having made a choice a structure of additional information.

    The <iid_name> identifies an interface that can be called at run time to process the link. More about interfaces below. The DBF_INLINK, DBF_OUTLINK, and DBF_FWDLINK are similar to DBF_XXXSTRUCTLINKs except that the menu choices, additional structure, and <iid_names>are automatically handled by the static and run time database access libraries.

    Changes to field definitions.

    The following changes are proposed:

    Deleted attribute:
    interest(<level>)
    The only thing that uses this attribute is dbpr. I say just do the same as level 4 does now. Almost every time I see someone execute this command they ask for highest level anyway.
    Changed Attribute
    promptgroup(<guigroup>)
    This is left over from a tool that was to be developed by SSC. Nothing else ever used it except for (o,nonzero) meaning DCT tools (did not, did) prompt for a value for a field. The existing groups defined for record have many errors. Thus this attriubute could be replaced by:
    dct(<No or Yes>)

    Three examples follow: The first shows how soft links are handled, the second an existing vme link, and the third a vme link with additional configuration information.

    Example Soft Input Link - DBF_INLINK

    A soft input link has the definitions :

        menu(menuSoftInLink) {
            choice(menuSoftInLinkNULL,"NULL Link")
            choice(menuSoftInLinkDB,"Database Link")
            choice(menuSoftInLinkCA,"Channel Access Link")
        }
        menu(menuCALinkProcess) {
            choice(menuCALinkProcessNo,"No Process")
            choice(menuCALinkProcessPassive,"Process if Passive")
            choice(menuCALinkProcessAlways,"Process Always")
        }
        struct(dbSoftInLinkDB) {
            field(pvname,DBF_VSTRING) {
                prompt("Process Variable Name")
                promptgroup(GUI_INPUT)
            }
            field(process_passive,DBF_MENU) {
                prompt("Process Passive")
                promptgroup(GUI_INPUT)
                menu(menuYesNo)
            }
            field(max_sevr,DBF_MENU) {
                prompt("Maximize Severity")
                promptgroup(GUI_INPUT)
                menu(menuYesNo)
            }
        }
        struct(dbSoftInLinkCA) {
            field(pvname,DBF_VSTRING) {
                prompt("Process Variable Name")
                promptgroup(GUI_INPUT)
            }
            field(process_passive,DBF_MENU) {
                prompt("Process on Monitor")
                promptgroup(GUI_INPUT)
                menu(menuCALinkProcess)
            }
            field(max_sevr,DBF_MENU) {
                prompt("Maximize Severity")
                promptgroup(GUI_INPUT)
                menu(menuYesNo)
            }
        }
        # The following are psuedo definitions.
        link(<all DBF_INLINKs>,NULL,<system>,"NULL Link")
        link(<all DBF_INLINKs>,dbSoftInLinkDB,<system>,"Database Link")
        link(<all DBF_INLINKs>,dbSoftInLinkCA,<system>,"Channel Access Link")
    

    A record instance file could define a DBF_INLINK as follows:

        ...
        field(INPA,"Channel Access Link"){
            field(pvname,"<record name>.<field_name>")
            field(process_passive,"Yes")
            field(max_sevr,"Yes")
        }
        ...

    Comments:

    Example - Existing vme support.

    Lets take an ai record connected to a VME_IO input. This example shows how existing 3.13 link functionality is reimplemented. The old recordtype(ai) definition is now:

    struct(ai) {
        include "dbCommon"
        ...
        field(INP,DBF_INSTRUCTLINK) {
            ...
        }
        ...
    }
    

    The following defines the vmeio structure .

    struct(vmeLink) {
        field(card,DBF_USHORT) {
            prompt("card")
            promptgroup(GUI_INPUTS)
        }
        field(signal,DBF_USHORT) {
            prompt("signal")
            promptgroup(GUI_INPUTS)
        }
        field(parm,DBF_PSTRING) {
            prompt("parm")
            promptgroup(GUI_INPUTS)
        }
    }
    

    The above definition results in an include file that duplicates the "struct vmeio" currently defined in link.h. The other existing bus types defined in link.h are defined in a similar manner. User defined bus types can be be created as desired.

    Assume the old device definitions were:

    device(ai,CONSTANT,devAiSoft,"Soft Channel")
    device(ai,CONSTANT,devAiSoftRaw,"Raw Soft Channel")
    device(ai,VME_IO,devAiXy566Se,"XYCOM-566 SE Scanned")
    
    

    The new definition would be:

    link(ai.INP,NULL,NULL,"NULL Link")
    link(ai.INP,dbSoftInLinkDB,devAiSoft,"Database Link")
    link(ai.INP,dbSoftInLinkCA,devAiSoft,"Channel Access Link")
    link(ai.INP,dbSoftInLinkDB,devAiSoftRaw,"Raw Database Link")
    link(ai.INP,dbSoftInLinkCA,devAiSoftRaw,"Raw Channel Access Link")
    link(ai.INP,VME_IO,devAiXy566Se,"XYCOM-566 SE Scanned")
    

    NOTE: In order to get all the soft definitions out of base.dbd and baseLIBOBJS, the soft definitions and support modules should be bundled with record support.

    A record instance is defined as follows:

    record(ai,xxx) {
        ...
        field(INP,"vmeLink") {
            field(card,"1")
            field(signal,"2")
        }
        ...
    }
    

    Comments:

    Example: A vme link with additional information.

    Now lets give an example that provides more functionality. We want to be able to configure the vme addresses for a module. In addition each channel can have individual gain. Lets define two additional structure: the first describes a module. The other describes a link.

    #Each physical module will have a record instance of type xxxAdc
    struct(xxxAdc) {
        field(NAME,DBF_STRING) {
            prompt("Record Name")
            special(SPC_NOMOD)
            size(29)
        }
        field(card,DBF_ULONG) {
            prompt("VME Slot")
            promptgroup(GUI_INPUT)
        }
        field(a24o,DBF_ULONG) {
            prompt("A24 Offset")
            promptgroup(GUI_INPUT)
        }
        field(a24l,DBF_ULONG) {
            prompt("A24 Length")
            promptgroup(GUI_INPUT)
        }
        ...
    }
    #Each INP Link referencing a physical module will use this link type
    struct(xxxAdcLink) {
        field(xxxAdcName,DBF_STRING) {
            prompt("xxxAdc Record Name")
            promptgroup(GUI_INPUT)
        }
        field(signal,DBF_USHORT) {
            prompt("Signal")
            promptgroup(GUI_INPUT)
        }
        field(gain,DBF_MENU) {
            prompt("Gain")
            promptgroup(GUI_INPUT)
            menu(menuXxxAdcGain)
        }
        ...
    }
    

    A record is defined as

    #mycard is an actual physical module
    record(mycard,xxxAdc) {
        field(NAME,"xxxAdcCard1")
        field(card,"1")
        field(a24o,"0x00a000")
        field(a24l,"0x1000")
    }
    #This is the ai record that uses a signal of mycard
    record(xxx,ai) {
        ...
        field(INP,"xxxAdcLink") {
            field(xxxAdcName,"xxxAdcCard1")
            field(signal,"2")
            field(gain,"10x")
        }
        ...
    }
    

    Comments:

    Accessing the new field types.

    Now lets discuss how the three different viewpoints of epics databases, i.e. DCT tools, Runtime database Access, and record/device access. NOTE: These are "half baked" thoughts

    DCT Tools:
    The old DCT_MENUFORM type will disappear. In addition the old routines for manipulating Link and Menuform fields will disappear.
    The normal menu routines can be used on DCT_XXXLINK fields. In addition the following routine is provided:
           long dbGetStruct(DBENTRY *pfrom,DBENTRY *pstruct)
    The first argument to dbGetStruct must reference a DCT_XXXLINK field. On successful completion, the second argument references a structure. The fields of the structure can be accessed just like fields of a record.
    My guess is that the static database access library will shrink in size and that DCTs will be easier to implement.
    Runtime Database Access:
    DBR_STRUCT is a new request type that can be applied to DBF_XXXLINK fields. It's value for a get request is the structure name returned as a string.
    A structure field can also be accessed via a DBR_STRING request with the value in the form:
         {field1,field2,...fieldn}
    where fieldi is the it'h field in the structure.
    A new DBR request, DBR_STRUCT_FIELDNAMES, will return the complete set of field names for a structure. The caller can then make separate requests for each field.
    What about a DBR_STRUCT_FIELDTYPES request?
    The native type for a link field will be reported as DBR_LINK. The caller can pass requesets DBR_LINK_MENU, and the calls specified for a DBR_STRUCT field shown above.
    Jeff and Jim, after gdd etc, may have much better ideas.
    Record/device support
    This is a combination of static database access, runtime database access, and interfaces.

    dbCommon fields

    Instead of having a single dbCommon that defines a large number of fields, a set of definitions will be provided. Each definition adds additional fields to the previous definition.

    No Special Fields
    NAME Field - include "name.dbd"
    Accessable via Run Time database access and Channel Access - include "dbAccess.dbd"
    Can be Processed - include "dbCommon.dbd"

    COMMENT: Groups of fields used by subsystems (access security, database access, channel access) are replaced by a "void *" field for each subsystem. In fact I think all DBF_NOACCESS fields should be "void *" fields. Also the fields that record support modules use privately should all be declared in a separate structure and referenced via a "void * recPvt" field.

    Miscellaneous db related topics,

    The dbToRecordTypeH utility will be renamed to dbToStructH, i.e. a c structure can be generated for any structure. All code that intimately uses the information in a structure should use the generated structures. Note that except for a few special structure types iocCore will NOT include the generated structure definitions.

    Interfaces

    EPICS 3.13 supports the following interfaces: RSET, DSET, DRVET. Other than the first field (number) of each interface they are similar to the COM definition of an interface. What is being proposed is to use a few of the basic ideas of COM interfaces.

    Brief description of COM interface:

    Brief Description of iocCore Interfaces:

    Interface supported by each record , link , and driver support module.

    The header file ifInit.h is defined as:

        typedef long ifInit_init(void);
        typedef struct ifInit {
            ifInit_init *init;
        } ifInit;

    A record support module would implement this interface something like the following:

        include "ifInit.h"
        ...
        LOCAL ifInit_init init;
        /* aiRecord_ifInit must be global variable. IT CAN BE THE ONLY ONE*/
        ifInit aiRecord_ifInit = {init};
        ...
        ifXXX_yyy yyy;
        ifXXX_zzz zzz;
        static ifXXX aiRecord_ifXXX = {yyy,zzz};
        long init(void)
        {
            ifRegister("aiRecord_ifXXX",aiRecord_ifXXX);
            ...
        }

    Replacements for old RSETs.

    The old RSET will be replaced by the following interfaces:

    Comments about init_record:

    Link Support Interfaces - Replacement for DSET

    The old DSET will be replaced by the following interfaces:

    The arguments for init_link are:

        init_link(DBLINK *plink,int phase, int passInPhase,
             int *nextPhase,int *delaySeconds)

    This routine will be called by record support from it's init_record method.

    COMMENT: Note that each record type can define a recordtype specific interface for communicating with it's link support modules. I also think it should define a structure or use parameters for communicating with its link support. Link support modules should NOT include the record structure declaration. This should get rid of a whole bunch of funny business in communication between record and device support.

    Driver Support Interfaces

    More of the same.

    Locating Interfaces

    Two routines are provided:

        long ifRegister(char *name, void *location);
        void *ifLocate(char *name)

    ifRegister is called by the ifInit init methods to register interfaces. Any code can call ifLocate to locate an interface. Every record type has an associated ifInit interface named <record type>Record_ifInit. Every link support interface is named in a link definition.Every driver support interface is named in a driver definition. Since the ifInit init interfaces call ifRegister for all other interfaces EVERY interface used in an ioc can be easily determined. One idea is to generate a source module from the xxxApp.dbd file. This source file maps the interface names to the external names of each ifInit interface. Jim Kowalkowski also has another method for location the names. In any case the gioal is to locate all interfaces without calling symFindByName. This makes the port to ,other operating system and toronado easier.

    On-line Add and Delete

    For complete on-line add delete each physical interface must have a record instance. The fields can be modified via database or channel access. Should have a field "CMD" that accepts commands like:

    DBF_INLINK, DBF_FWDLINK, and DBF_OUTLINK fields can be modified by iocCore without aid from record support. This is just like in 3.13.

    DBF_INSTRUCTLINK and DBF_OUTSTRUCTLINK need support from the an interface attached to the link definitions. Again it should accept commands like:

    If record instances are to be deleted there must be help from an interface.

    iocInit needs work. It 's functionality should be made into a library that can be called by iocInit as well as by something that adds things after iocInit. Something like dbAddDatabase is needed followed by iocReinit. This is a way to add new record/device/driver support and new record instances.

    Needs lots of thought.