The database attributes defined in this chapter are fixed, i.e. they are common to all IOC databases. They are defined via C include files. Any changes to these include files can affect many IOC software components, which will have to be modified and recompiled. A serious reader of this chapter should obtain a listing of all the files in epics/share/epicsH.
In the IOC a single global variable (pdbBase) contains the address of the dbBase structures that defines the run time database. The various structures mentioned in dbBase are described in this chapter. Any IOC source module using the macros and other routines mentioned in this chapter must include a definition:
extern dbBase *pdbBase;Then a particular routine accessing a database structure can either reference it via pdbBase or create a local copy which must be initialized via pdbBase.
GET_PRECNAME (prectype, rec_type)Typical Usage:
char *pstr; if(!(pstr=GET_PRECNAME(precType,type)) {/*action if not found*/}This macro returns a pointer to the record name.
GET_PRECLOC (precheader, rec_type)Typical Usage:
struct recLoc *precLoc; if(!(precLoc=GET_PRECLOC(precHeader,type)) {/*action if not found*/}This macro returns a pointer to the record location structure.
GET_PFLDDES (prectypdes, ind_fld)Typical Usage:
struct fldDes *pfldDes; if(!(pfldDes=GET_PFLDDES(precTypDes,ind)) {/*action if not found*/}This macro returns a pointer to the field description structure for a particular field of the record type defined by precTypDes.
GET_PRECTYPDES (precdes, ind_rec)Typical Usage:
struct recTypDes *precTypDes; if(!(precTypDes=GET_PRECTYPDES(precDes,ind)) {/*action if not found*/}This macro returns a pointer to the record type description structure.
GET_CHOICE (pchoice_set, ind_choice)Typical Usage:
char *pchoice; if(!(pchoice=GET_CHOICE(pchoiceSet,ind)) {/*action if not found*/}This macro returns a pointer to the string defining a particular choice.
GET_PCHOICE_SET(parr_choice_set, ind_arr)Typical Usage:
struct choiceSet *pchoiceSet; if(!(pchoiceSet=GET_PCHOICE_SET(parrChoiceSet,ind)) {/*action if not found*/}This macro returns a pointer to the structure defining a particular choice set.
GET_PARR_CHOICE_SET (pchoice_rec, ind_arr)Typical Usage:
struct arrChoiceSet *parrChoiceSet; if(!(parrChoiceSet=GET_PARR_CHOICE_SET(pChoiceRec,ind)) {/*action*/}This macro returns a pointer to the structure defining an array of choice sets.
GET_DEV_CHOICE (pdev_choice_set, ind_choice)Typical Usage:
struct devChoice *pdevChoice; if(!(pdevChoice=GET_DEV_CHOICE(pdevChoice,ind)) {/*action*/}This macro returns a pointer to the structure defining a device choice.
GET_PDEV_CHOICE_SET (pchoice_dev, ind_rec)Typical Usage:
struct devChoiceSet *pdevChoiceSet; if(!(pdevChoiceSet=GET_PDEV_CHOICE_SET(pchoiceDev,ind)) {/*action*/}This macro returns a pointer to the structure defining the device choices for a particular record.
GET_PRSET (precsup, rec_type)Typical Usage:
struct rset *prset; if(!(prset=GET_PRSET(precSup,type)) {/*action if not found*/}This macro returns a pointer to a record support entry table.
GET_PDSET (pdevsup,dtype)Typical Usage:
struct dset *pdset; if(!(pdset=GET_PDSET(pdevSup,type)) {/*action if not found*/}This macro returns a pointer to a device support entry table.
GET_PDEVSUP (precdevsup, rec_type)Typical Usage:
struct devSup *pdevSup; if(!(pdevSup=GET_PDEVSET(precDevSup,rectype)) {/*action if not found*/}This macro returns a pointer to a structure defining the ndevice support entry tables for a particular record type.
GET_PDRVET (pdrvsup,type)Typical Usage:
struct drvet *pdrvet; if(!(pdrvet=GET_PDRVET(pdrvSup,type)) {/*action if not found*/}This macro returns a pointer to a driver entry table.
GET_PDRVNAME (pdrvsup,type)Typical Usage:
char *pdrvName; if(!(pdrvName=GET_PDRVNAME(pdrvSup,type)) {/*action if not found*/}This macro returns a pointer to the driver name.
struct recType { long number; /* number of types */ char **papName; /* ptr to arr of ptr to name */ };Figure 12-1 shows the memory layout of the record type structures.
This is among the simpler of the IOC structures thus let's discuss a few details. The external variable dbRecType points to structure recType. This structure contains two elements: number and papName. number specifies the number of record types. papName is a pointer to an array of pointers to record names. Notice in the figure the unnamed array of pointers. It is permissible for any pointer in the array to be NULL.This type of structure will be seen many times in the following subsections. Thus whenever a variable starts with "pap" it means "pointer to array of pointers".
typedef struct{ ELLNODE next; void *precord; } RECNODE; struct recLoc{ /* record location */ long rec_size; /* record size in bytes */ long record_type; /* record type */ ELLLIST *preclist /* LIST head of sorted RECNODEs */ }; struct recHeader{ /*record header*/ long number; /*number of record types*/ struct recLoc **papRecLoc; /*ptr to arr of ptr to recLoc*/ };Figure 12-2 shows the memory layout of the database records.
/* conversion types*/ #define CT_DECIMAL 0 #define CT_HEX 1 /* lowfl, highfl */ #define CON 0 #define VAR 1 #define PROMPT_SZ 24 union fld_types{ char char_value; unsigned char uchar_value; short short_value; unsigned short ushort_value; long long_value; unsigned long ulong_value; float float_value; double double_value; unsigned short enum_value; }; struct range { long fldnum; unionfld_types value; }; struct fldDes{ /* field description */ char prompt[PROMPT_SZ]; /*Prompt string for DCT */ char fldname[FLDNAME_SZ];/*field name */ short offset; /* Offset in bytes from beginning of record */ short size; /* length in bytes of a field element */ short special; /* Special processing requirements */ short field_type; /* Field type as defined in dbFldTypes.h */ short process_passive; /*should dbPutField process passive records*/ short choice_set; /* index of choiceSet GBLCHOICE & RECCHOICE*/ short cvt_type; /* Conversion type for DCT */ short promptflag; /* Does DCT display this field */ short lowfl; /* Is range1 CON or VAR */ short highfl; /* Is range2 CON or VAR */ short interest; /* interest level for reporting */ union fld_types initial; /* initial value */ struct range range1; /* Low value for field (Used by DCT) */ struct range range2; /* High value for field (Used by DCT) */ }; struct recTypDes{ /* record type description */ short rec_size; /* size of the record */ short no_fields; /* number of fields defined */ short no_prompt; /* number of fields to configure */ short no_links; /* number of links */ short *link_ind; /* addr of array of ind in apFldDes */ unsigned long *sortFldName; /* addr of array of sorted fldname */ short *sortFldInd; /* addr of array of ind in apFldDes */ struct fldDes **papFldDes; /* ptr to array of ptr to fldDes */ }; struct recDes{ /* record description */ long number; /*number of recTypDes*/ struct recTypDes **papRecTypDes;/*ptr to arr of ptr to recTypDes*/ }; extern struct recDes *dbRecDes;Figure 12-3 shows the memory layout of the record descriptions. Lets first discuss structure recTypDes and then fldDes.
Figure 12-3: Record Descriptions
Structure recTypDes describes the information specific to each record type. It contains the following information:
struct choiceSet { /* This defines one set of choices*/ long number; /*number of choices */ char **papChoice; /*ptr to arr of ptr to choice string */ }; struct arrChoiceSet{ /*An array of choice sets for particular record type*/ long number; /*number of choice sets */ struct choiceSet **papChoiceSet; /*ptr to arr of ptr to choiceSet*/ }; struct choiceRec{ /*define choices for each record type*/ long number; /*number of arrChoiceSet */ struct arrChoiceSet **papArrChoiceSet; /*ptr to arr of ptr to arrChoiceSet*/ }; /* device choices */ struct devChoice{ long link_type; /*link type for this device*/ char *pchoice; /*ptr to choice string */ }; struct devChoiceSet { /* This defines one set of device choices*/ long number; /*number of choices */ struct devChoice **papDevChoice; /*ptr to arr of ptr to devChoice */ char **papChoice; /*ptr to arr of ptr to choice string */ }; struct devChoiceRec{ /*define device choices for each record type*/ long number; /*number of devChoiceSet */ struct devChoiceSet **papDevChoiceSet; /*ptr to arr of ptr to devChoiceSet*/ };Figure 12-4 shows the memory layout of the choice definitions. In the database a choice field is stored as an unsigned short value. The meaning is determined via the associated choice structures. Four types of structures are referenced via the following pointers (stored in struct dbBase):
Figure 12-4: Choice Definitions
struct brkInt{ /* breakpoint interval */ long raw; /*raw value for beginning of interval */ float slope; /*slope for interval */ float eng; /*converted value for beginning of interval*/ }; struct brkTable { /* breakpoint table */ char *name; /*breakpoint table name */ long number; /*number of brkInt in this table */ long rawLow; /*lowest raw data value allowed */ long rawHigh; /*highest raw data value allowed */ struct brkInt **papBrkInt; /* ptr to array of ptr to brkInt */ }; struct arrBrkTable { /* array of brkTable */ long number; /*number of break tables */ struct brkTable **papBrkTable; /* ptr to array of ptr to brkTable */ };
Figure 12-5: Conversion Tables
typedef long (*RECSUPFUN) (); /* ptr to record support function */ struct rset { /* record support entry table */ long number; /*number of support routines */ RECSUPFUN report; /*print report */ RECSUPFUN init; /*init support */ RECSUPFUN init_record; /*init record */ RECSUPFUN process; /*process record */ RECSUPFUN special; /*special processing */ RECSUPFUN get_value; /*get value field */ RECSUPFUN cvt_dbaddr; /*cvt dbAddr */ RECSUPFUN get_array_info; RECSUPFUN put_array_info; RECSUPFUN get_units; RECSUPFUN get_precision; RECSUPFUN get_enum_str; /*get string from enum item */ RECSUPFUN get_enum_strs; /*get all enum strings */ RECSUPFUN put_enum_str; /*put string to enum item */ RECSUPFUN get_graphic_double; RECSUPFUN get_control_double; RECSUPFUN get_alarm_double; }; struct recSup { long number; /*number of record types */ struct rset **papRset; /*ptr to arr of ptr to rset */ }; #define RSETNUMBER ( (sizeof(struct rset) - sizeof(long))/sizeof(RECSUPFUN) )Figure 12-6 shows the memory layout of the record support definitions. Each record type must have an associated set of record support routines. Note that only the record and device support routines use the record structure declarations while accessing a record. The record support routines are intended to isolate the rest of the IOC software from details of record access and processing.
typedef long (*DEVSUPFUN) (); /* ptr to device support function*/ struct dset { /* device support entry table */ long number; /*number of support routines*/ DEVSUPFUN report; /*print report*/ DEVSUPFUN init; /*init support*/ DEVSUPFUN init_record; /*init support for particular record*/ DEVSUPFUN get_ioint_info; /*get I/O interrupt information*/ /*other functions are record dependent*/ }; struct devSup { long number; /*number of dset */ char **papDsetName; /*ptr of arr of ptr to name */ struct dset **papDset; /*ptr to arr of ptr to dset */ }; struct recDevSup { long number; /*number of record types */ struct devSup **papDevSup; /*ptr to arr of ptr to devSup */ }; extern struct recDevSup *devSup;Figure 12-7 shows the memory layout of the device support definitions. The device support routines are intended to isolate the record processing routines from device specific details.
typedef int (*DRVSUPFUN) (); /* ptr to driver support function*/ struct drvet { /* driver entry table */ long number; /*number of support routines*/ DRVSUPFUN report; /*print report*/ DRVSUPFUN init; /*init support*/ DERSUPFUN reboot; /*reboot entry*/ /* other functions are device dependent*/ }; struct drvSup { long number; /*number of dset */ char **papDrvName; /*ptr to arr of ptr to drvetName*/ struct drvet **papDrvet; /*ptr to arr ptr to drvet */ }; #define DRVETNUMBER ( (sizeof(struct drvet) -sizeof(long))/sizeof(DRVSUPFUN) )Figure 12-8 shows the memory layout of the driver support definitions.