diff --git a/caProvider.md b/caProvider.md
index 6a479aa..29a285e 100644
--- a/caProvider.md
+++ b/caProvider.md
@@ -1,16 +1,20 @@
# pvAccessCPP: ca provider
-2018.07.09
+2018.10.05
Editors:
* Marty Kraimer
-This is a description of channel provider **ca** that is implemented as part of **pvAccessCPP**.
+**ca** is a channel provider **ca** that is implemented as part of **pvAccessCPP**.
+
It uses the **channel access** network protocol to communicate with a server,
i. e. the network protocol that has been used to communicate with **EPICS IOCs** since 1990.
+A description of **ca** is provided in
+[caProvider](https://mrkraimer.github.io/website/caProvider/caProvider.html)
+
Provider **pva** is another way to connect to a **DBRecord**,
But this only works if the IOC has **qsrv** installed.
**qsrv**, which is provided with
@@ -19,618 +23,4 @@ has full support for communicating with a **DBRecord**.
The only advantage of **ca** is that it does require any changes to an existing IOC.
-The following are discussed.
-
-* [Introduction](#S-introduction)
-* [client API](#S-client)
-* [Mapping DBD data to pvData](#S-dbd_to_pvdata)
-* [Developing plugins for ca provider.](#S-plugin)
-
-
-
-## Introduction
-
-The primary purpose of the **ca** provider is to access **DBRecord**s in an EPICS IOC via the
-**channel access** network protocol but to use pvData objects for the client.
-
-Each **DBRecord** instance has a record name that must be unique in the local area network.
-A client can access any public field of a **DBRecord**;
-Each **DBRecord** instance has a record name that is unique with in the local area network
-A channel name is a **recordname.fieldName**.
-If the fieldname is not specified then **.VAL** is assumed
-
-### example database
-
-The following:
-
-```
-mrk> pwd
-/home/epicsv4/masterCPP/pvAccessCPP/testCa
-mrk> softIoc -d testCaProvider.db
-```
-
-Starts an EPICS IOC that is used for all examples in this document.
-
-### examples
-
-```
-mrk> caget -d DBR_TIME_FLOAT DBRdoubleout
-DBRdoubleout
- Native data type: DBF_DOUBLE
- Request type: DBR_TIME_FLOAT
- Element count: 1
- Value: 1
- Timestamp: 2018-06-21 06:23:07.939894
- Status: NO_ALARM
- Severity: NO_ALARM
-mrk> pvget -p ca -r "value,alarm,timeStamp" -i DBRdoubleout
-DBRdoubleout
-structure
- double value 1
- alarm_t alarm
- int severity 0
- int status 0
- string message
- time_t timeStamp
- long secondsPastEpoch 1529576587
- int nanoseconds 939894210
- int userTag 0
-mrk> pvget -p ca -r "value,alarm,timeStamp" DBRdoubleout
-DBRdoubleout
-structure
- double value 1
- alarm_t alarm NO_ALARM NO_STATUS
- time_t timeStamp 2018-06-21T06:23:07.940 0
-
-mrk> pvget -p ca -r value -i DBRdoubleout.SCAN
-DBRdoubleout.SCAN
-epics:nt/NTEnum:1.0
- enum_t value
- int index 0
- string[] choices [Passive,Event,I/O Intr,10 second,5 second,2 second,1 second,.5 second,.2 second,.1 second]
-```
-
-### Overview of Channel Access
-
-**channel access**, which is provided with **epics-base**, defines and implements a protocol
-for client/server network communication.
-
-**epics-base** provides both a client and a server implementation
-This document only discusses the client API.
-
-For details see:
-
-[EPICS Channel Access 4.13.1 Reference Manual](https://epics.anl.gov/base/R7-0/1-docs/CAref.html)
-
-**channel access** allows a client to get, put, and monitor monitor data from a server.
-The data is defined by various DBD types.
-
-The following, in **epics-base/include**, are the
-main include files that show the **channel access** API:
-
-```
-cadef.h
-db_access.h
-```
-
-The client requests data via one of the DBR types.
-
-For example:
-
-```
-DBR_STS_DOUBLE returns a double status structure (dbr_sts_double)
-where
-struct dbr_sts_double{
- dbr_short_t status; /* status of value */
- dbr_short_t severity; /* severity of alarm */
- dbr_long_t RISC_pad; /* RISC alignment */
- dbr_double_t value; /* current value */
-};
-```
-
-The server converts data between the native type of the field being accessed and the DBR type.
-
-
-### Overview of ca provider
-
-**ca** is a pvAccess Channel Provider that uses **channel access** to connect a client to a server.
-
-With **ca**, the client data appears as pvData objects, i. e.
-**ca** converts the data provided by **channel access** to/from pvData
-
-Thus a pvAccess client can communicate with an existing V3 EPICS IOC without making
-any changes to existing IOCs.
-
-For an overview of pvData and pvAccess see:
-
-[EPICS V4 Developer's Guide](https://mrkraimer.github.io/website/developerGuide/developerGuide.html)
-
-**ca** requests data from the server with a DBR type that matches the native type.
-See the next section for more details.
-
-All conversion to/from other types must be done by the client.
-
-## Client API
-
-**ca** implements the following pvAccess methods : **getField**, **channelGet**, **channelPut** and **monitor**.
-
-For channelPut the only field that can be accessed is **value**.
-For channelPut a client can issue puts with and without a callback from the server.
-The default is no callback. If createChannelPut has the option "record[block=true]" then a put callback used.
-
-All of the other pvAccess methods provide access to fields **alarm** and **timeStamp**.
-
-Depending on the type associated with the **value** field the following fields may also be available:
-**display**, **control** , and **valueAlarm**.
-
-Thus a client can make requests like:
-
-```
-pvget -p ca -r "value,alarm,timeStamp,display,control,valueAlarm" names ...
-```
-
-**ca** will create a structure that has the fields requested but only for fields that are supported
-by the server.
-
-* For puts only value is supported.
-* For gets and monitors every channel supports value, alarm, and timeStamp;
-* If any of display,control, or valueAlarm are requested then timeStamp is NOT available.
-
-Lets discuss the various fields.
-
-### value
-
-This can be a scalar, scalarArray, or an enumerated structure.
-
-For a scalar or scalarArray the ScalarType is one of the following:
-**pvString**, **pvByte**, **pvShort**, **pvInt**, **pvFloat**, or **pvDouble**.
-
-Note that **channel access** does not support unsigned integers or 64 bit integers.
-
-A enumerated structure is created if the native type is **DBR_ENUM**.
-
-Some examples are:
-
-```
-pvget -p ca -r value -i DBRlongout
-DBRlongout
-structure
- int value 0
-mrk> pvget -p ca -r value -i DBRdoubleout
-DBRdoubleout
-structure
- double value 0
-mrk> pvget -p ca -r value -i DBRshortArray
-DBRshortArray
-structure
- short[] value []
-mrk> pvget -p ca -r value -i DBRstringArray
-DBRstringArray
-structure
- string[] value [aa,bb,cc]
-mrk> pvget -p ca -r value -i DBRmbbin
-DBRmbbin
-epics:nt/NTEnum:1.0
- enum_t value
- int index 1
- string[] choices [zero,one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen]
-mrk>
-
-```
-
-
-### alarm,timeStamp,display,control, and valueAlarm
-
-Each of these is one of the property structures defined in pvData.
-
-#### Examples
-
-```
-mrk> pvget -p ca -r alarm -i DBRdoubleout
-DBRdoubleout
-structure
- alarm_t alarm
- int severity 2
- int status 3
- string message HIHI
-
-mrk> pvget -p ca -r timeStamp -i DBRdoubleout
-DBRdoubleout
-structure
- time_t timeStamp
- long secondsPastEpoch 1529923341
- int nanoseconds 314916189
- int userTag 0
-mrk> pvget -p ca -r display -i DBRdoubleout
-DBRdoubleout
-structure
- display_t display
- double limitLow -10
- double limitHigh 10
- string description
- string format F8.2
- string units volts
-mrk> pvget -p ca -r control -i DBRdoubleout
-DBRdoubleout
-structure
- control_t control
- double limitLow -1e+29
- double limitHigh 1e+29
- double minStep 0
-mrk> pvget -p ca -r valueAlarm -i DBRdoubleout
-DBRdoubleout
-structure
- valueAlarm_t valueAlarm
- boolean active false
- double lowAlarmLimit -8
- double lowWarningLimit -6
- double highWarningLimit 6
- double highAlarmLimit 8
- int lowAlarmSeverity 0
- int lowWarningSeverity 0
- int highWarningSeverity 0
- int highAlarmSeverity 0
-```
-
-
-
-## DBD to pvData
-
-### Type Conversion
-
-Three type systems are involved in accessing data in a **DBRecord** and converting it to/from pvData:
-
-* DBF The type system used for **DBRecord**s.
-* DBR The type system used by **channel access**.
-* pvData
-
-The following gives a summary of the conversions between the type systems:
-
-```
-rawtype DBF DBR pvData ScalarType
-
-char[MAX_STRING_SIZE] DBF_STRING DBR_STRING pvString
-epicsInt8 DBF_CHAR DBR_CHAR pvByte
-epicsUint8 DBF_UCHAR DBR_CHAR pvByte
-epicsInt16 DBF_SHORT DBR_SHORT pvShort
-epicsUInt16 DBF_USHORT DBR_LONG pvInt
-epicsInt32 DBF_LONG DBR_LONG pvInt
-epicsUInt32 DBF_ULONG DBR_DOUBLE pvDouble
-epicsInt64 DBF_INT64 no support
-epicsUInt64 DBF_UINT64 no support
-float DBF_FLOAT DBR_FLOAT pvFloat
-double DBF_DOUBLE DBR_DOUBLE pvDouble
-epicsUInt16 DBF_ENUM DBR_ENUM enum structure
-epicsUInt16 DBF_MENU DBR_ENUM enum structure
-```
-
-Notes:
-
-* Both DBF_CHAR and DBF_UCHAR go to DBR_CHAR. This is ambigous.
-* DBF_USHORT promoted to DBR_LONG
-* DBF_ULONG promoted to DBR_DOUBLE
-* qsrv provides full access to all DBF types, but the IOC must have qsrv installed.
-
-### Accessing data in a DBRecord
-
-An IOC database is a memory resident database of **DBRecord** instances.
-
-Each **DBRecord** is an instance of one of an extensible set of record types.
-Each record type has an associated dbd definition which defines a set of fields for
-each record instance.
-
-For example an aoRecord.dbd has the definition:
-
-```
-recordtype(ao) {
- include "dbCommon.dbd"
- field(VAL,DBF_DOUBLE) {
- ...
- }
- field(OVAL,DBF_DOUBLE) {
- ...
- }
- ... many more fields
-```
-
-In addition each record type has a associated set of support code defined in recSup.h
-
-```
-/* record support entry table */
-struct typed_rset {
- long number; /* number of support routines */
- long (*report)(void *precord);
- long (*init)();
- long (*init_record)(struct dbCommon *precord, int pass);
- long (*process)(struct dbCommon *precord);
- long (*special)(struct dbAddr *paddr, int after);
- long (*get_value)(void); /* DEPRECATED set to NULL */
- long (*cvt_dbaddr)(struct dbAddr *paddr);
- long (*get_array_info)(struct dbAddr *paddr, long *no_elements, long *offset);
- long (*put_array_info)(struct dbAddr *paddr, long nNew);
- long (*get_units)(struct dbAddr *paddr, char *units);
- long (*get_precision)(const struct dbAddr *paddr, long *precision);
- long (*get_enum_str)(const struct dbAddr *paddr, char *pbuffer);
- long (*get_enum_strs)(const struct dbAddr *paddr, struct dbr_enumStrs *p);
- long (*put_enum_str)(const struct dbAddr *paddr, const char *pbuffer);
- long (*get_graphic_double)(struct dbAddr *paddr, struct dbr_grDouble *p);
- long (*get_control_double)(struct dbAddr *paddr, struct dbr_ctrlDouble *p);
- long (*get_alarm_double)(struct dbAddr *paddr, struct dbr_alDouble *p);
-};
-```
-
-The methods that support accessing data from the record include:
-
-```
-cvt_dbaddr Implemented by record types that determine VAL type at record initialization
-*array_info Implemented by array record types
-get_units Implemented by numeric record types
-get_precision Implemented by float and double record types
-*_enum_* Implemented by enumerated record types
-get_graphic_double NOTE Always returns limits as double
-get_control_double NOTE Always returns limits as double
-get_alarm_double NOTE Always returns limits as double
-```
-
-Each of these methods is optional, i. e. record support for a particular record type
-only implements methods that make sense for the record type.
-
-For example the enum methods are only implemented by records that have the definition:
-
-```
-...
- field(VAL,DBF_ENUM) {
-...
-}
-...
-```
-
-
-### Channel Access Data
-
-A client can access any public field of a **DBRecord**;
-Each **DBRecord** instance has a record name that is unique within the local area network.
-
-A channel name is a **recordname.fieldName**.
-
-If the fieldname is not specified then **.VAL** is assumed and the record support methods shown
-above can also be used to get additional data from the record.
-
-Any field that is accessable by client code must have a vald DBF_ type.
-
-A client gets/puts data via a **DBR_*** request.
-
-The basic DBR types are:
-```
-rawtype DBR
-
-char[MAX_STRING_SIZE] DBR_STRING
-epicsInt8 DBR_CHAR
-epicsInt16 DBR_SHORT
-epicsInt32 DBR_LONG
-float DBF_FLOAT
-double DBF_DOUBLE
-epicsUInt16 DBR_ENUM
-```
-
-In addition to the DBR basic types the following DBR types provide additional data:
-
-```
-DBR one of the types above.
-DBR_STATUS_* adds status and severity to DBR.
-DBR_TIME_* adds epicsTimeStamp to DBR_STATUS.
-DBR_GR_* adds display limits to DBR_STATUS. NOTE: no epicsTimeStamp
-DBR_CTRL_ adds control limits to DBR_GR. NOTE: no epicsTimeStamp
-DBR_CTRL_ENUM This is a special case.
-```
-
-NOTES:
-
-* status, severity, and epicsTimeStamp are the same for each DBR type.
-* limits have the same types as the correspondng DBR type.
-* server converts limits from double to the DBR type.
-* GR and CTRL have precision only for DBR_FLOAT and DBR_DOUBLE
-
-
-Some examples:
-
-```
-DBR_STS_DOUBLE returns a double status structure (dbr_sts_double)
-where
-struct dbr_sts_double{
- dbr_short_t status; /* status of value */
- dbr_short_t severity; /* severity of alarm */
- dbr_long_t RISC_pad; /* RISC alignment */
- dbr_double_t value; /* current value */
-};
-
-DBR_TIME_DOUBLE returns a double time structure (dbr_time_double)
-where
-struct dbr_time_double{
- dbr_short_t status; /* status of value */
- dbr_short_t severity; /* severity of alarm */
- epicsTimeStamp stamp; /* time stamp */
- dbr_long_t RISC_pad; /* RISC alignment */
- dbr_double_t value; /* current value */
-};
-
-DBR_GR_SHORT returns a graphic short structure (dbr_gr_short)
-where
-struct dbr_gr_short{
- dbr_short_t status; /* status of value */
- dbr_short_t severity; /* severity of alarm */
- char units[MAX_UNITS_SIZE]; /* units of value */
- dbr_short_t upper_disp_limit; /* upper limit of graph */
- dbr_short_t lower_disp_limit; /* lower limit of graph */
- dbr_short_t upper_alarm_limit;
- dbr_short_t upper_warning_limit;
- dbr_short_t lower_warning_limit;
- dbr_short_t lower_alarm_limit;
- dbr_short_t value; /* current value */
-};
-
-DBR_GR_DOUBLE returns a graphic double structure (dbr_gr_double)
-where
-struct dbr_gr_double{
- dbr_short_t status; /* status of value */
- dbr_short_t severity; /* severity of alarm */
- dbr_short_t precision; /* number of decimal places */
- dbr_short_t RISC_pad0; /* RISC alignment */
- char units[MAX_UNITS_SIZE]; /* units of value */
- dbr_double_t upper_disp_limit; /* upper limit of graph */
- dbr_double_t lower_disp_limit; /* lower limit of graph */
- dbr_double_t upper_alarm_limit;
- dbr_double_t upper_warning_limit;
- dbr_double_t lower_warning_limit;
- dbr_double_t lower_alarm_limit;
- dbr_double_t value; /* current value */
-};
-
-DBR_CTRL_DOUBLE returns a control double structure (dbr_ctrl_double)
-where
-struct dbr_ctrl_double{
- dbr_short_t status; /* status of value */
- dbr_short_t severity; /* severity of alarm */
- dbr_short_t precision; /* number of decimal places */
- dbr_short_t RISC_pad0; /* RISC alignment */
- char units[MAX_UNITS_SIZE]; /* units of value */
- dbr_double_t upper_disp_limit; /* upper limit of graph */
- dbr_double_t lower_disp_limit; /* lower limit of graph */
- dbr_double_t upper_alarm_limit;
- dbr_double_t upper_warning_limit;
- dbr_double_t lower_warning_limit;
- dbr_double_t lower_alarm_limit;
- dbr_double_t upper_ctrl_limit; /* upper control limit */
- dbr_double_t lower_ctrl_limit; /* lower control limit */
- dbr_double_t value; /* current value */
-};
-
-
-DBR_CTRL_ENUM returns a control enum structure (dbr_ctrl_enum)
-where
-struct dbr_ctrl_enum{
- dbr_short_t status; /* status of value */
- dbr_short_t severity; /* severity of alarm */
- dbr_short_t no_str; /* number of strings */
- char strs[MAX_ENUM_STATES][MAX_ENUM_STRING_SIZE];
- /* state strings */
- dbr_enum_t value; /* current value */
-};
-```
-
-### PVData for a DBRrecord via ca provider
-
-**pvAccessCPP/src/ca** has files **dbdToPv.h** and **dbdToPv.cpp**.
-This is the code that converts between DBD data and pvData.
-
-This code must decide which of the many **DBR_*** types to use.
-
-
-There is a static method:
-
-```
-static DbdToPvPtr create(
- CAChannelPtr const & caChannel,
- epics::pvData::PVStructurePtr const & pvRequest,
- IOType ioType); // one of getIO, putIO, and monitorIO
-```
-
-
-When this is called the first thing is to determine which fields are requested by the client.
-This is from the set **value**, **alarm**, **timeStamp**. **display**, **control** , and **valueAlarm**.
-
-
-* If the ioType is putIO only **value** is valid.
-* If the channel type is **DBR_ENUM** then **display**, **control** , and **valueAlarm** are ignored.
-* If the channel is an array then **control** , and **valueAlarm** are ignored.
-* If the channel type is **DBR_STRING** then **display**, **control** , and **valueAlarm** are ignored.
-* If any of **display**, **control** , and **valueAlarm** are still allowed then **timeStamp** is ignored,
-because the DBR type selected will not return the timeStamp.
-
-If ths channel type is **DBR_ENUM** a one time **ca_array_get_callback(DBR_GR_ENUM...** request is issued
-to get the choices for the enumerated value.
-
-Depending or which fields are still valid, the DBR type is obtained via
-
-* If any of **display**, **control** ,or **valueAlarm** is valid then **dbf_type_to_DBR_CTRL(caValueType)** .
-* else If **alarm** or **timeStamp** is valid then **dbf_type_to_DBR_TIME(caValueType)** .
-* else **dbf_type_to_DBR(caValueType)**
-
-Where **caValueType** is one of DBR_STRING, DBR_SHORT, DBR_FLOAT, DBR_ENUM, DBR_CHAR, DBR_LONG, DBR_DOUBLE.
-
-If **display** is still valid then the following call is made:
-
-```
-string name(caChannel->getChannelName() + ".DESC");
-int result = ca_create_channel(name.c_str(),
-...
-```
-When the channel connects a get is issued to get the value for **display.description**.
-
-## Developing plugins for ca provider
-
-This section provides guidelines for code developers that use **ca** to connect a client to a server.
-This includes plugins for things like MEDM, EDM, caqtDM, etc.
-But also means any code that use **ca**: pvget, pvput, pvaClientCPP, exampleCPP/exampleClient, etc.
-
-The **channel access** reference manual describes channel context:
-
-[CA Client Contexts and Application Specific Auxiliary Threads](https://epics.anl.gov/base/R7-0/1-docs/CAref.html#Client2)
-
-A brief summary of channel context is:
-
-
-* Only the thread that calls CAClientFactory::start() and associated auxillary threads
-can call **ca_xxx** functions.
-
-The public access to **ca** is:
-
-```
-class epicsShareClass CAClientFactory
-{
-public:
- /** @brief start provider ca
- *
- */
- static void start();
- /** @brief get the ca_client_context
- *
- * This can be called by an application specific auxiliary thread.
- * See ca documentation. Not for casual use.
- */
- static ca_client_context * get_ca_client_context();
- /** @brief stop provider ca
- *
- * This does nothing since epicsAtExit is used to destroy the instance.
- */
- static void stop();
-};
-```
-Any code that uses **ca** must call **CAClientFactory::start()** before making any pvAccess client requests.
-
-ca_context_create is called for the thread that calls CAClientFactory::start().
-
-If the client creates auxillary threads the make pvAccess client requests then the auxillary threads will automatically become
-a **ca** auxilary thread.
-
-
-[Deadlock in ca_clear_subscription()](https://bugs.launchpad.net/epics-base/7.0/+bug/1751380)
-
-Shows a problem with monitor callbacks.
-A test was created that shows that the same problem can occur with a combination of rapid get, put and monitor events.
-
-
-In order to prevent this problem **ca** creates the following threads:
-**getEventThread**, **putEventThread**, and **monitorEventThread**.
-
-All client callbacks are made via one of these threads.
-For example a call to the requester's **monitorEvent** method is made from the monitorEventThread.
-
-**Notes**
-
-* These threads do not call **ca_attach_context**.
-* No **ca_xxx** function should be called from the requester's callback method.
-
-
-