iocCore permits link fields to be changed at runtime, including INP and OUT
fields of records that are currently connected to a real piece of hardware.
However most device support layers probably only look at the link address at
initialization time, and so completely ignore any changes.
Changing the DTYP field of a record will not change its linked DSET address,
so you can't change the device support layer that a record links to at all.
Characteristics of a Solution
Must be backwards compatible
Old device support must work without change (other than maybe
recompilation)
Record support must work without change
It would be dangerous to add new routines to the Device Support Entry Table:
Different record types have different numbers of DSET routines
Every device support layer defines its own DSET struct
Some device support layers add their own routines too (GPIB, BitBus)
Should allow new-style device support to deny an address change change
operation in either direction
My Solution: Extended Device Support
In the device support initialization routine, an extended support layer
calls
devExtend(&myDSXT);
myDSXT is a struct dsxt which is, defined in devSup.h as:
typedef struct dsxt { /* device support extension table */
long (*add_record)(struct dbCommon *precord);
long (*del_record)(struct dbCommon *precord);
/* Recordtypes are *not* allowed to extend this table */
} dsxt;
The add_record() routine is called before the record type's init_record(),
and to offer a new record to use this device support.
The del_record() routine will be called to request a record to switch to a
different device support.
It is not told what the new device or address will be.
Rules for Extended Device Support
A device's hardware address can only be changed if the device support has
registered as being extended.
If it hasn't, changes to the INP/OUT field using
ca_put_callback() will return an error,
ca_put() will generate an exception callback.
This is incompatible with old behaviour.
Either the old or the new device support layer may refuse a change by
returning non-zero from the add_record()/del_record() routine.
If SCAN=I/O Intr and the new layer does not support this, SCAN will be
changed to Passive.
Change DTYP before INP/OUT if switching to a different device support
layer.
long add_record(dbCommon *precord)
When converting existing device support, this routine will be very similar
to the old init_record() routine.
May need to do more work in some cases, depending on record type.
If there are any errors, say in the link address, return a non-zero status
value to reject the record link.
Never leave precord->pact set.
Output record readback value processing by the record is not supported
If there are no errors, add_record() must return 0
returning 2 would mean it's reporting an error.
mbbi/mbbo record types must convert NOBT into MASK, and set and apply SHFT as
necessary for the link address
SHFT may be different on different device support
long del_record(dbCommon *precord)
This routine is responsible for closing down the connection to the hardware,
freeing any memory reserved for DPVT etc.
It may refuse to allow an address change if it's currently busy (or just
feeling petulant!) by returning a non-zero value.
This will flow back through CA causing an error/exception.
On device support that must run in vxWorks IOCs for long periods, be careful
not to fragment memory by calling malloc()/free()
Use a freelist for DPVT memory allocation, or
Save the DPVT storage with the registered hardware address and
retrieve it if/when the address is reused later.
long init_record(struct ..Record *prec)
To maintain full compatibility of records, there are some fields that must be
set in an init_record() routine
The record's init_record() routine runs after add_record() and
overwrites these fields.
Your init_record() routine must set:
Initial RVAL readback with conversion (if supported)
MASK for mbbi/mbbo records
ESLO/EOFF of analog records
Other fields that the record's init_record() routine touches.
Current Status
Originally developed in my advanced work for R3.15 (to V4)
Tested by modifying an Acromag 9440 digital I/O driver on vxWorks.
The patch to install this functionality is less that 20KBytes.
I applied it to R3.14.6 on Wednesday this week, without problems
Not tested on this release yet, no problems expected
It is feasible that it could even be applied to earlier versions if you
really want to try that
Don't expect much support from me if you do that though...
May be included in R3.14.8 if there is sufficient interest.